mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 05:44:45 +01:00
KVM: arm64: Add early_param to control WFx trapping
Add an early_params to control WFI and WFE trapping. This is to control the degree guests can wait for interrupts on their own without being trapped by KVM. Options for each param are trap and notrap. trap enables the trap. notrap disables the trap. Note that when enabled, traps are allowed but not guaranteed by the CPU architecture. Absent an explicitly set policy, default to current behavior: disabling the trap if only a single task is running and enabling otherwise. Signed-off-by: Colton Lewis <coltonlewis@google.com> Reviewed-by: Jing Zhang <jingzhangos@google.com> Link: https://lore.kernel.org/r/20240523174056.1565133-1-coltonlewis@google.com [ oliver: rework kvm_vcpu_should_clear_tw*() for readability ] Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
This commit is contained in:
parent
83a7eefedc
commit
0b5afe0537
2 changed files with 83 additions and 3 deletions
|
|
@ -2745,6 +2745,24 @@
|
|||
[KVM,ARM,EARLY] Allow use of GICv4 for direct
|
||||
injection of LPIs.
|
||||
|
||||
kvm-arm.wfe_trap_policy=
|
||||
[KVM,ARM] Control when to set WFE instruction trap for
|
||||
KVM VMs. Traps are allowed but not guaranteed by the
|
||||
CPU architecture.
|
||||
|
||||
trap: set WFE instruction trap
|
||||
|
||||
notrap: clear WFE instruction trap
|
||||
|
||||
kvm-arm.wfi_trap_policy=
|
||||
[KVM,ARM] Control when to set WFI instruction trap for
|
||||
KVM VMs. Traps are allowed but not guaranteed by the
|
||||
CPU architecture.
|
||||
|
||||
trap: set WFI instruction trap
|
||||
|
||||
notrap: clear WFI instruction trap
|
||||
|
||||
kvm_cma_resv_ratio=n [PPC,EARLY]
|
||||
Reserves given percentage from system memory area for
|
||||
contiguous memory allocation for KVM hash pagetable
|
||||
|
|
|
|||
|
|
@ -48,6 +48,15 @@
|
|||
|
||||
static enum kvm_mode kvm_mode = KVM_MODE_DEFAULT;
|
||||
|
||||
enum kvm_wfx_trap_policy {
|
||||
KVM_WFX_NOTRAP_SINGLE_TASK, /* Default option */
|
||||
KVM_WFX_NOTRAP,
|
||||
KVM_WFX_TRAP,
|
||||
};
|
||||
|
||||
static enum kvm_wfx_trap_policy kvm_wfi_trap_policy __read_mostly = KVM_WFX_NOTRAP_SINGLE_TASK;
|
||||
static enum kvm_wfx_trap_policy kvm_wfe_trap_policy __read_mostly = KVM_WFX_NOTRAP_SINGLE_TASK;
|
||||
|
||||
DECLARE_KVM_HYP_PER_CPU(unsigned long, kvm_hyp_vector);
|
||||
|
||||
DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
|
||||
|
|
@ -546,6 +555,24 @@ static void vcpu_set_pauth_traps(struct kvm_vcpu *vcpu)
|
|||
}
|
||||
}
|
||||
|
||||
static bool kvm_vcpu_should_clear_twi(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (unlikely(kvm_wfi_trap_policy != KVM_WFX_NOTRAP_SINGLE_TASK))
|
||||
return kvm_wfi_trap_policy == KVM_WFX_NOTRAP;
|
||||
|
||||
return single_task_running() &&
|
||||
(atomic_read(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vlpi_count) ||
|
||||
vcpu->kvm->arch.vgic.nassgireq);
|
||||
}
|
||||
|
||||
static bool kvm_vcpu_should_clear_twe(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (unlikely(kvm_wfe_trap_policy != KVM_WFX_NOTRAP_SINGLE_TASK))
|
||||
return kvm_wfe_trap_policy == KVM_WFX_NOTRAP;
|
||||
|
||||
return single_task_running();
|
||||
}
|
||||
|
||||
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||
{
|
||||
struct kvm_s2_mmu *mmu;
|
||||
|
|
@ -579,10 +606,15 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
|||
if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
|
||||
kvm_make_request(KVM_REQ_RECORD_STEAL, vcpu);
|
||||
|
||||
if (single_task_running())
|
||||
vcpu_clear_wfx_traps(vcpu);
|
||||
if (kvm_vcpu_should_clear_twe(vcpu))
|
||||
vcpu->arch.hcr_el2 &= ~HCR_TWE;
|
||||
else
|
||||
vcpu_set_wfx_traps(vcpu);
|
||||
vcpu->arch.hcr_el2 |= HCR_TWE;
|
||||
|
||||
if (kvm_vcpu_should_clear_twi(vcpu))
|
||||
vcpu->arch.hcr_el2 &= ~HCR_TWI;
|
||||
else
|
||||
vcpu->arch.hcr_el2 |= HCR_TWI;
|
||||
|
||||
vcpu_set_pauth_traps(vcpu);
|
||||
|
||||
|
|
@ -2858,6 +2890,36 @@ static int __init early_kvm_mode_cfg(char *arg)
|
|||
}
|
||||
early_param("kvm-arm.mode", early_kvm_mode_cfg);
|
||||
|
||||
static int __init early_kvm_wfx_trap_policy_cfg(char *arg, enum kvm_wfx_trap_policy *p)
|
||||
{
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
|
||||
if (strcmp(arg, "trap") == 0) {
|
||||
*p = KVM_WFX_TRAP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(arg, "notrap") == 0) {
|
||||
*p = KVM_WFX_NOTRAP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int __init early_kvm_wfi_trap_policy_cfg(char *arg)
|
||||
{
|
||||
return early_kvm_wfx_trap_policy_cfg(arg, &kvm_wfi_trap_policy);
|
||||
}
|
||||
early_param("kvm-arm.wfi_trap_policy", early_kvm_wfi_trap_policy_cfg);
|
||||
|
||||
static int __init early_kvm_wfe_trap_policy_cfg(char *arg)
|
||||
{
|
||||
return early_kvm_wfx_trap_policy_cfg(arg, &kvm_wfe_trap_policy);
|
||||
}
|
||||
early_param("kvm-arm.wfe_trap_policy", early_kvm_wfe_trap_policy_cfg);
|
||||
|
||||
enum kvm_mode kvm_get_mode(void)
|
||||
{
|
||||
return kvm_mode;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue