Skip to content

Commit 0b5afe0

Browse files
coltonlewisoupton
authored andcommitted
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 <[email protected]> Reviewed-by: Jing Zhang <[email protected]> Link: https://lore.kernel.org/r/[email protected] [ oliver: rework kvm_vcpu_should_clear_tw*() for readability ] Signed-off-by: Oliver Upton <[email protected]>
1 parent 83a7eef commit 0b5afe0

File tree

2 files changed

+83
-3
lines changed

2 files changed

+83
-3
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2745,6 +2745,24 @@
27452745
[KVM,ARM,EARLY] Allow use of GICv4 for direct
27462746
injection of LPIs.
27472747

2748+
kvm-arm.wfe_trap_policy=
2749+
[KVM,ARM] Control when to set WFE instruction trap for
2750+
KVM VMs. Traps are allowed but not guaranteed by the
2751+
CPU architecture.
2752+
2753+
trap: set WFE instruction trap
2754+
2755+
notrap: clear WFE instruction trap
2756+
2757+
kvm-arm.wfi_trap_policy=
2758+
[KVM,ARM] Control when to set WFI instruction trap for
2759+
KVM VMs. Traps are allowed but not guaranteed by the
2760+
CPU architecture.
2761+
2762+
trap: set WFI instruction trap
2763+
2764+
notrap: clear WFI instruction trap
2765+
27482766
kvm_cma_resv_ratio=n [PPC,EARLY]
27492767
Reserves given percentage from system memory area for
27502768
contiguous memory allocation for KVM hash pagetable

arch/arm64/kvm/arm.c

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@
4848

4949
static enum kvm_mode kvm_mode = KVM_MODE_DEFAULT;
5050

51+
enum kvm_wfx_trap_policy {
52+
KVM_WFX_NOTRAP_SINGLE_TASK, /* Default option */
53+
KVM_WFX_NOTRAP,
54+
KVM_WFX_TRAP,
55+
};
56+
57+
static enum kvm_wfx_trap_policy kvm_wfi_trap_policy __read_mostly = KVM_WFX_NOTRAP_SINGLE_TASK;
58+
static enum kvm_wfx_trap_policy kvm_wfe_trap_policy __read_mostly = KVM_WFX_NOTRAP_SINGLE_TASK;
59+
5160
DECLARE_KVM_HYP_PER_CPU(unsigned long, kvm_hyp_vector);
5261

5362
DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
@@ -546,6 +555,24 @@ static void vcpu_set_pauth_traps(struct kvm_vcpu *vcpu)
546555
}
547556
}
548557

558+
static bool kvm_vcpu_should_clear_twi(struct kvm_vcpu *vcpu)
559+
{
560+
if (unlikely(kvm_wfi_trap_policy != KVM_WFX_NOTRAP_SINGLE_TASK))
561+
return kvm_wfi_trap_policy == KVM_WFX_NOTRAP;
562+
563+
return single_task_running() &&
564+
(atomic_read(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vlpi_count) ||
565+
vcpu->kvm->arch.vgic.nassgireq);
566+
}
567+
568+
static bool kvm_vcpu_should_clear_twe(struct kvm_vcpu *vcpu)
569+
{
570+
if (unlikely(kvm_wfe_trap_policy != KVM_WFX_NOTRAP_SINGLE_TASK))
571+
return kvm_wfe_trap_policy == KVM_WFX_NOTRAP;
572+
573+
return single_task_running();
574+
}
575+
549576
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
550577
{
551578
struct kvm_s2_mmu *mmu;
@@ -579,10 +606,15 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
579606
if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
580607
kvm_make_request(KVM_REQ_RECORD_STEAL, vcpu);
581608

582-
if (single_task_running())
583-
vcpu_clear_wfx_traps(vcpu);
609+
if (kvm_vcpu_should_clear_twe(vcpu))
610+
vcpu->arch.hcr_el2 &= ~HCR_TWE;
611+
else
612+
vcpu->arch.hcr_el2 |= HCR_TWE;
613+
614+
if (kvm_vcpu_should_clear_twi(vcpu))
615+
vcpu->arch.hcr_el2 &= ~HCR_TWI;
584616
else
585-
vcpu_set_wfx_traps(vcpu);
617+
vcpu->arch.hcr_el2 |= HCR_TWI;
586618

587619
vcpu_set_pauth_traps(vcpu);
588620

@@ -2858,6 +2890,36 @@ static int __init early_kvm_mode_cfg(char *arg)
28582890
}
28592891
early_param("kvm-arm.mode", early_kvm_mode_cfg);
28602892

2893+
static int __init early_kvm_wfx_trap_policy_cfg(char *arg, enum kvm_wfx_trap_policy *p)
2894+
{
2895+
if (!arg)
2896+
return -EINVAL;
2897+
2898+
if (strcmp(arg, "trap") == 0) {
2899+
*p = KVM_WFX_TRAP;
2900+
return 0;
2901+
}
2902+
2903+
if (strcmp(arg, "notrap") == 0) {
2904+
*p = KVM_WFX_NOTRAP;
2905+
return 0;
2906+
}
2907+
2908+
return -EINVAL;
2909+
}
2910+
2911+
static int __init early_kvm_wfi_trap_policy_cfg(char *arg)
2912+
{
2913+
return early_kvm_wfx_trap_policy_cfg(arg, &kvm_wfi_trap_policy);
2914+
}
2915+
early_param("kvm-arm.wfi_trap_policy", early_kvm_wfi_trap_policy_cfg);
2916+
2917+
static int __init early_kvm_wfe_trap_policy_cfg(char *arg)
2918+
{
2919+
return early_kvm_wfx_trap_policy_cfg(arg, &kvm_wfe_trap_policy);
2920+
}
2921+
early_param("kvm-arm.wfe_trap_policy", early_kvm_wfe_trap_policy_cfg);
2922+
28612923
enum kvm_mode kvm_get_mode(void)
28622924
{
28632925
return kvm_mode;

0 commit comments

Comments
 (0)