[PATCH] ARM: KVM: vfp: Use a per-CPU struct for host VFP state

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux