Using a vfp_hard_struct per vcpu for the host is a bit overkill (odds are we have more vcpus than physical CPUs). It then makes sense to have a global set of vfp_hard_structs for the host. Define a per-cpu variable holding the host CPU states, and let each vcpu point to the right state as they're about to run. Cc: Antonios Motakis <a.motakis@xxxxxxxxxxxxxxxxxxxxxx> Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx> --- arch/arm/include/asm/kvm_host.h | 2 +- arch/arm/kvm/arm.c | 19 ++++++++++++++++++ arch/arm/kvm/interrupts.S | 42 ++++++++++++++++++++------------------- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 1e4366e..678aa33 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -116,7 +116,7 @@ struct kvm_vcpu_arch { /* Floating point registers (VFP and Advanced SIMD/NEON) */ struct vfp_hard_struct vfp_guest; - struct vfp_hard_struct vfp_host; + struct vfp_hard_struct *vfp_host; /* * Anything that is not used directly from assembly code goes diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 803b97c..49d916c 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -55,6 +55,9 @@ __asm__(".arch_extension virt"); static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page); +/* Per-CPU variable containing the host VFP state */ +static DEFINE_PER_CPU(struct vfp_hard_struct, kvm_host_vfp_state); + /* The VMID used in the VTTBR */ static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); static u8 kvm_next_vmid; @@ -283,6 +286,7 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { vcpu->cpu = cpu; + vcpu->arch.vfp_host = this_cpu_ptr(&kvm_host_vfp_state); /* * Check whether this vcpu requires the cache to be flushed on @@ -771,6 +775,21 @@ static int init_hyp_mode(void) } } + /* + * Map the host VFP structures + */ + for_each_possible_cpu(cpu) { + struct vfp_hard_struct *vfp; + + vfp = &per_cpu(kvm_host_vfp_state, cpu); + err = create_hyp_mappings(vfp, vfp + 1); + + if (err) { + kvm_err("Cannot map host VFP state\n"); + goto out_free_mappings; + } + } + return 0; out_free_mappings: free_hyp_pmds(); diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S index 450144a..4d6cc71 100644 --- a/arch/arm/kvm/interrupts.S +++ b/arch/arm/kvm/interrupts.S @@ -90,15 +90,13 @@ ENTRY(__kvm_flush_vm_context) bx lr ENDPROC(__kvm_flush_vm_context) -/* Clobbers {r2-r7} */ -.macro store_vfp_state vfp_off, vcpup - add r6, \vcpup, \vfp_off - +/* Clobbers {r2-r6} */ +.macro store_vfp_state vfp_base @ The VFPFMRX and VFPFMXR macros are the VMRS and VMSR instructions VFPFMRX r2, FPEXC @ Make sure VFP is enabled so we can touch the registers. - orr r7, r2, #FPEXC_EN - VFPFMXR FPEXC, r7 + orr r6, r2, #FPEXC_EN + VFPFMXR FPEXC, r6 VFPFMRX r3, FPSCR tst r2, #FPEXC_EX @ Check for VFP Subarchitecture @@ -108,19 +106,17 @@ ENDPROC(__kvm_flush_vm_context) VFPFMRX r4, FPINST tst r2, #FPEXC_FP2V VFPFMRX r5, FPINST2, ne @ vmrsne - bic r7, r2, #FPEXC_EX @ FPEXC_EX disable - VFPFMXR FPEXC, r7 + bic r6, r2, #FPEXC_EX @ FPEXC_EX disable + VFPFMXR FPEXC, r6 1: - VFPFSTMIA r6, r7 @ Save VFP registers - stm r6, {r2-r5} @ Save FPEXC, FPSCR, FPINST, FPINST2 + VFPFSTMIA \vfp_base, r6 @ Save VFP registers + stm \vfp_base, {r2-r5} @ Save FPEXC, FPSCR, FPINST, FPINST2 .endm -/* Assume FPEXC_EN is on and FPEXC_EX is off, clobbers {r2-r7} */ -.macro restore_vfp_state vfp_off, vcpup - add r6, \vcpup, \vfp_off - - VFPFLDMIA r6, r7 @ Load VFP registers - ldm r6, {r2-r5} @ Load FPEXC, FPSCR, FPINST, FPINST2 +/* Assume FPEXC_EN is on and FPEXC_EX is off, clobbers {r2-r6} */ +.macro restore_vfp_state vfp_base + VFPFLDMIA \vfp_base, r6 @ Load VFP registers + ldm \vfp_base, {r2-r5} @ Load FPEXC, FPSCR, FPINST, FPINST2 VFPFMXR FPSCR, r3 tst r2, #FPEXC_EX @ Check for VFP Subarchitecture @@ -456,8 +452,11 @@ __kvm_vcpu_return: bne after_vfp_restore @ Switch VFP/NEON hardware state to the host's - store_vfp_state #VCPU_VFP_GUEST, r1 - restore_vfp_state #VCPU_VFP_HOST, r1 + add r7, r1, #VCPU_VFP_GUEST + store_vfp_state r7 + add r7, r1, #VCPU_VFP_HOST + ldr r7, [r7] + restore_vfp_state r7 after_vfp_restore: @ Restore FPEXC_EN which we clobbered on entry @@ -728,8 +727,11 @@ switch_to_guest_vfp: set_hcptr 0, (HCPTR_TCP(10) | HCPTR_TCP(11)) @ Switch VFP/NEON hardware state to the guest's - store_vfp_state #VCPU_VFP_HOST, r0 - restore_vfp_state #VCPU_VFP_GUEST, r0 + add r7, r0, #VCPU_VFP_HOST + ldr r7, [r7] + store_vfp_state r7 + add r7, r0, #VCPU_VFP_GUEST + restore_vfp_state r7 pop {r3-r7} pop {r0-r2} -- 1.7.10.3 _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm