[PATCH v20 07/22] KVM: arm64: Refactor the vcpu_load to allow for VM specific callbacks

From: Suzuki K Poulose

Date: Thu Sep 24 2026 - 12:15:21 EST


To keep the VCPU load/put handling cleaner with the different kinds of VM
types, we are about to introduce VM specific callbacks to do just the right
thing. In preparation for that, make some refactoring to add the change
easier by mainly feature specific configurations to individual wrappers,
so that different callbacks could reuse the helpers.

Adds vcpu_prepare_mmu()/vcpu_put_mmu() wrappers to load/put MMU related
configurations for !pKVM guests. Additionally makes it explicit that
kvm_arm_vmid_clear_active() is not required for pKVM host.

Add vcpu_load_pvtime(), vcpu_set_wfx_traps() wrappers for handling the
corresponding configurations.

While at it, also make it clear that the timer loading constraints only
apply for the VHE.

No functional changes intended. Based on a work by Marc Zyngier.

Reviewed-by: Gavin Shan <gshan@xxxxxxxxxx>
Tested-by: Gavin Shan <gshan@xxxxxxxxxx>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@xxxxxxx>
---
Changes since v19:
- Add vcpu_put_mmu() to pair with the vcpu_prepare_mmu() and make the
call conditional on !is_protected_kvm_enabled(). Preparing the path
for per-flavor callbacks
- Update the timer load constraints comment to reflect that it only applies
for VHE
- Wrap kvm_arm_vmid_clear_active() to vcpu_put_mmu() to compliement
with the vcpu_prepare_mmu(). Also only clear the VMID for non-pKVM
guests
---
arch/arm64/kvm/arm.c | 59 ++++++++++++++++++++++++++++++--------------
1 file changed, 40 insertions(+), 19 deletions(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 849f5fcc26c15..6393b2c1a65de 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -684,14 +684,11 @@ static bool kvm_vcpu_should_clear_twe(struct kvm_vcpu *vcpu)
return single_task_running();
}

-void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+static void vcpu_prepare_mmu(struct kvm_vcpu *vcpu)
{
struct kvm_s2_mmu *mmu;
int *last_ran;

- if (is_protected_kvm_enabled())
- goto nommu;
-
if (vcpu_has_nv(vcpu))
kvm_vcpu_load_hw_mmu(vcpu);

@@ -721,34 +718,56 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
kvm_call_hyp(__kvm_flush_cpu_context, mmu);
*last_ran = vcpu->vcpu_idx;
}
+}

-nommu:
+static void vcpu_put_mmu(struct kvm_vcpu *vcpu)
+{
+ kvm_arm_vmid_clear_active();
+}
+
+static void vcpu_set_wfx_traps(struct kvm_vcpu *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->arch.hcr_el2 |= HCR_TWI;
+}
+
+static void vcpu_load_pvtime(struct kvm_vcpu *vcpu)
+{
+ if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
+ kvm_make_request(KVM_REQ_RECORD_STEAL, vcpu);
+}
+
+void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
vcpu->cpu = cpu;

+ if (!is_protected_kvm_enabled())
+ vcpu_prepare_mmu(vcpu);
/*
- * The timer must be loaded before the vgic to correctly set up physical
- * interrupt deactivation in nested state (e.g. timer interrupt).
+ * For VHE, the timer must be loaded before the vgic to correctly
+ * set up physical interrupt deactivation in nested state (e.g. timer
+ * interrupt).
*/
kvm_timer_vcpu_load(vcpu);
kvm_vgic_load(vcpu);
kvm_vcpu_load_debug(vcpu);
kvm_vcpu_load_fgt(vcpu);
+
if (has_vhe())
kvm_vcpu_load_vhe(vcpu);
+
kvm_arch_vcpu_load_fp(vcpu);
kvm_vcpu_pmu_restore_guest(vcpu);
- if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
- kvm_make_request(KVM_REQ_RECORD_STEAL, 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->arch.hcr_el2 |= HCR_TWI;
+ vcpu_load_pvtime(vcpu);
+ vcpu_set_wfx_traps(vcpu);

if (!is_protected_kvm_enabled())
vcpu_set_pauth_traps(vcpu);
@@ -787,7 +806,9 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
kvm_vcpu_pmu_restore_host(vcpu);
if (vcpu_has_nv(vcpu))
kvm_vcpu_put_hw_mmu(vcpu);
- kvm_arm_vmid_clear_active();
+
+ if (!is_protected_kvm_enabled())
+ vcpu_put_mmu(vcpu);

vcpu_clear_on_unsupported_cpu(vcpu);
vcpu->cpu = -1;
--
2.43.0