KVM: arm64: Restore mdcr_el2 from vcpu
authorFuad Tabba <tabba@google.com>
Tue, 17 Aug 2021 08:11:25 +0000 (09:11 +0100)
committerMarc Zyngier <maz@kernel.org>
Fri, 20 Aug 2021 10:12:17 +0000 (11:12 +0100)
On deactivating traps, restore the value of mdcr_el2 from the
newly created and preserved host value vcpu context, rather than
directly reading the hardware register.

Up until and including this patch the two values are the same,
i.e., the hardware register and the vcpu one. A future patch will
be changing the value of mdcr_el2 on activating traps, and this
ensures that its value will be restored.

No functional change intended.

Signed-off-by: Fuad Tabba <tabba@google.com>
Acked-by: Will Deacon <will@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20210817081134.2918285-7-tabba@google.com
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_hyp.h
arch/arm64/kvm/hyp/include/hyp/switch.h
arch/arm64/kvm/hyp/nvhe/switch.c
arch/arm64/kvm/hyp/vhe/switch.c
arch/arm64/kvm/hyp/vhe/sysreg-sr.c

index 4d2d974c1522b8defb83f1e6dd09883842274d54..76462c6a91eee6195fb441c5dc77add054bd9de0 100644 (file)
@@ -287,10 +287,13 @@ struct kvm_vcpu_arch {
        /* Stage 2 paging state used by the hardware on next switch */
        struct kvm_s2_mmu *hw_mmu;
 
-       /* HYP configuration */
+       /* Values of trap registers for the guest. */
        u64 hcr_el2;
        u64 mdcr_el2;
 
+       /* Values of trap registers for the host before guest entry. */
+       u64 mdcr_el2_host;
+
        /* Exception Information */
        struct kvm_vcpu_fault_info fault;
 
index 9d60b3006efcf97a0a6bb2177c13430dabbd1dcf..657d0c94cf828964cf7e9a8c9b0940f2f629f76a 100644 (file)
@@ -95,7 +95,7 @@ void __sve_restore_state(void *sve_pffr, u32 *fpsr);
 
 #ifndef __KVM_NVHE_HYPERVISOR__
 void activate_traps_vhe_load(struct kvm_vcpu *vcpu);
-void deactivate_traps_vhe_put(void);
+void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu);
 #endif
 
 u64 __guest_enter(struct kvm_vcpu *vcpu);
index e4a2f295a39450e4759026a8a29233543cb862ee..a0e78a6027be0d1f5a7a1cd4f74fa1d38feeece5 100644 (file)
@@ -92,11 +92,15 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
                write_sysreg(0, pmselr_el0);
                write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0);
        }
+
+       vcpu->arch.mdcr_el2_host = read_sysreg(mdcr_el2);
        write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
 }
 
-static inline void __deactivate_traps_common(void)
+static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
 {
+       write_sysreg(vcpu->arch.mdcr_el2_host, mdcr_el2);
+
        write_sysreg(0, hstr_el2);
        if (kvm_arm_support_pmu_v3())
                write_sysreg(0, pmuserenr_el0);
index f7af9688c1f72839280dc9c391b00c919860e300..2ea764a48958ddc5816c10177e23e6bf4fa2920a 100644 (file)
@@ -69,12 +69,10 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
 static void __deactivate_traps(struct kvm_vcpu *vcpu)
 {
        extern char __kvm_hyp_host_vector[];
-       u64 mdcr_el2, cptr;
+       u64 cptr;
 
        ___deactivate_traps(vcpu);
 
-       mdcr_el2 = read_sysreg(mdcr_el2);
-
        if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
                u64 val;
 
@@ -92,13 +90,12 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
                isb();
        }
 
-       __deactivate_traps_common();
+       vcpu->arch.mdcr_el2_host &= MDCR_EL2_HPMN_MASK |
+                                   MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT |
+                                   MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT;
 
-       mdcr_el2 &= MDCR_EL2_HPMN_MASK;
-       mdcr_el2 |= MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT;
-       mdcr_el2 |= MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT;
+       __deactivate_traps_common(vcpu);
 
-       write_sysreg(mdcr_el2, mdcr_el2);
        write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
 
        cptr = CPTR_EL2_DEFAULT;
index b3229924d2431a164f32e746c4c8b4274cf219e3..ec158fa41ae604ee8139c7187aa8faebc83ce35a 100644 (file)
@@ -91,17 +91,13 @@ void activate_traps_vhe_load(struct kvm_vcpu *vcpu)
        __activate_traps_common(vcpu);
 }
 
-void deactivate_traps_vhe_put(void)
+void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu)
 {
-       u64 mdcr_el2 = read_sysreg(mdcr_el2);
+       vcpu->arch.mdcr_el2_host &= MDCR_EL2_HPMN_MASK |
+                                   MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT |
+                                   MDCR_EL2_TPMS;
 
-       mdcr_el2 &= MDCR_EL2_HPMN_MASK |
-                   MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT |
-                   MDCR_EL2_TPMS;
-
-       write_sysreg(mdcr_el2, mdcr_el2);
-
-       __deactivate_traps_common();
+       __deactivate_traps_common(vcpu);
 }
 
 /* Switch to the guest for VHE systems running in EL2 */
index 2a0b8c88d74fc53359551afa35061b0a05910faf..007a12dd4351d28abfbd81b32848ed18e5cbac4d 100644 (file)
@@ -101,7 +101,7 @@ void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu)
        struct kvm_cpu_context *host_ctxt;
 
        host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
-       deactivate_traps_vhe_put();
+       deactivate_traps_vhe_put(vcpu);
 
        __sysreg_save_el1_state(guest_ctxt);
        __sysreg_save_user_state(guest_ctxt);