Hi Colton, On Thu, May 23, 2024 at 10:41 AM Colton Lewis <coltonlewis@xxxxxxxxxx> wrote: > > 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@xxxxxxxxxx> > --- > v6: > * Rebase to v6.9.1 > * Move decision to enable WFx traps back to vcpu load time > * Move policy enum to arm.c and mark variable as __read_mostly > * Add explicit disclaimer traps are not guaranteed even when setting enabled > * Remove explicit "default" case from early param handling as it is not needed > > v5: > https://lore.kernel.org/kvmarm/20240430181444.670773-1-coltonlewis@xxxxxxxxxx/ > > v4: > https://lore.kernel.org/kvmarm/20240422181716.237284-1-coltonlewis@xxxxxxxxxx/ > > v3: > https://lore.kernel.org/kvmarm/20240410175437.793508-1-coltonlewis@xxxxxxxxxx/ > > v2: > https://lore.kernel.org/kvmarm/20240319164341.1674863-1-coltonlewis@xxxxxxxxxx/ > > v1: > https://lore.kernel.org/kvmarm/20240129213918.3124494-1-coltonlewis@xxxxxxxxxx/ > > .../admin-guide/kernel-parameters.txt | 18 +++++ > arch/arm64/include/asm/kvm_emulate.h | 16 ----- > arch/arm64/kvm/arm.c | 68 ++++++++++++++++++- > 3 files changed, 83 insertions(+), 19 deletions(-) > > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt > index 396137ee018d..f334265a9cfa 100644 > --- a/Documentation/admin-guide/kernel-parameters.txt > +++ b/Documentation/admin-guide/kernel-parameters.txt > @@ -2693,6 +2693,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 > diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h > index 975af30af31f..68c4a170b871 100644 > --- a/arch/arm64/include/asm/kvm_emulate.h > +++ b/arch/arm64/include/asm/kvm_emulate.h > @@ -109,22 +109,6 @@ static inline unsigned long *vcpu_hcr(struct kvm_vcpu *vcpu) > return (unsigned long *)&vcpu->arch.hcr_el2; > } > > -static inline void vcpu_clear_wfx_traps(struct kvm_vcpu *vcpu) > -{ > - vcpu->arch.hcr_el2 &= ~HCR_TWE; > - if (atomic_read(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vlpi_count) || > - vcpu->kvm->arch.vgic.nassgireq) > - vcpu->arch.hcr_el2 &= ~HCR_TWI; > - else > - vcpu->arch.hcr_el2 |= HCR_TWI; > -} > - > -static inline void vcpu_set_wfx_traps(struct kvm_vcpu *vcpu) > -{ > - vcpu->arch.hcr_el2 |= HCR_TWE; > - vcpu->arch.hcr_el2 |= HCR_TWI; > -} > - > static inline void vcpu_ptrauth_enable(struct kvm_vcpu *vcpu) > { > vcpu->arch.hcr_el2 |= (HCR_API | HCR_APK); > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c > index c4a0a35e02c7..1cd58ca5d410 100644 > --- a/arch/arm64/kvm/arm.c > +++ b/arch/arm64/kvm/arm.c > @@ -47,6 +47,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); > @@ -428,6 +437,24 @@ void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) > > } > > +static bool kvm_vcpu_should_clear_twi(struct kvm_vcpu *vcpu) > +{ > + if (likely(kvm_wfi_trap_policy == KVM_WFX_NOTRAP_SINGLE_TASK)) > + return single_task_running() && > + (atomic_read(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vlpi_count) || > + vcpu->kvm->arch.vgic.nassgireq); > + > + return kvm_wfi_trap_policy == KVM_WFX_NOTRAP; > +} > + > +static bool kvm_vcpu_should_clear_twe(struct kvm_vcpu *vcpu) > +{ > + if (likely(kvm_wfe_trap_policy == KVM_WFX_NOTRAP_SINGLE_TASK)) > + return single_task_running(); > + > + return kvm_wfe_trap_policy == KVM_WFX_NOTRAP; > +} > + > void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) > { > struct kvm_s2_mmu *mmu; > @@ -461,10 +488,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->arch.hcr_el2 |= HCR_TWE; > + > + if (kvm_vcpu_should_clear_twi(vcpu)) > + vcpu->arch.hcr_el2 &= ~HCR_TWI; > else > - vcpu_set_wfx_traps(vcpu); > + vcpu->arch.hcr_el2 |= HCR_TWI; > > if (vcpu_has_ptrauth(vcpu)) > vcpu_ptrauth_disable(vcpu); > @@ -2663,6 +2695,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; > -- > 2.45.1.288.g0e0cd299f1-goog > Reviewed-by: Jing Zhang <jingzhangos@xxxxxxxxxx> Jing