[kvmarm] [RFC PATCH] ARM: KVM: Switch HVBAR setting to be HVC-based

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

 



Instead of relying on SMC calls to setup HVBAR, introduce a new
HVC-based API. This of course requires a hypervisor stub to be
installed already. At the moment, this is implemented as part of the
boot wrapper, but will be moved to the kernel itself when it actually
understands being booted in HYP mode.

The kernel now uses "hvc #0xff", with r0 containing the pointer to
the new vectors.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm/include/asm/kvm_asm.h |    5 -----
 arch/arm/kvm/arm.c             |   29 ++++++++++++-----------------
 arch/arm/kvm/init.S            |    5 +++++
 arch/arm/kvm/interrupts.S      |   12 ++++++++++++
 4 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index e01dfab..a2bf1c5 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -28,11 +28,6 @@
 #define ARM_EXCEPTION_FIQ	  6
 #define ARM_EXCEPTION_HVC	  7
 
-/*
- * SMC Hypervisor API call number
- */
-#define SMCHYP_HVBAR_W 0xfffffff0
-
 #ifndef __ASSEMBLY__
 struct kvm;
 struct kvm_vcpu;
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index cf9ca42..18c5ba3 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -780,21 +780,17 @@ long kvm_arch_vm_ioctl(struct file *filp,
 static void cpu_set_vector(void *vector)
 {
 	unsigned long vector_ptr;
-	unsigned long smc_hyp_nr;
 
 	vector_ptr = (unsigned long)vector;
-	smc_hyp_nr = SMCHYP_HVBAR_W;
 
 	/*
 	 * Set the HVBAR
 	 */
 	asm volatile (
 		"mov	r0, %[vector_ptr]\n\t"
-		"mov	r7, %[smc_hyp_nr]\n\t"
-		"smc	#0\n\t" : :
-		[vector_ptr] "r" (vector_ptr),
-		[smc_hyp_nr] "r" (smc_hyp_nr) :
-		"r0", "r7");
+		"hvc	#0xff\n\t" : :
+		[vector_ptr] "r" (vector_ptr) :
+		"r0");
 }
 
 static void cpu_init_hyp_mode(void *vector)
@@ -802,23 +798,29 @@ static void cpu_init_hyp_mode(void *vector)
 	unsigned long pgd_ptr;
 	unsigned long hyp_stack_ptr;
 	unsigned long stack_page;
+	unsigned long vector_ptr;
 
+	/* Switch from the HYP stub to our own HYP init vector */
 	cpu_set_vector(vector);
 
 	pgd_ptr = virt_to_phys(hyp_pgd);
 	stack_page = __get_cpu_var(kvm_arm_hyp_stack_page);
 	hyp_stack_ptr = stack_page + PAGE_SIZE;
+	vector_ptr = (unsigned long)__kvm_hyp_vector;
 
 	/*
-	 * Call initialization code
+	 * Call initialization code, and switch to the full blown
+	 * HYP code.
 	 */
 	asm volatile (
 		"mov	r0, %[pgd_ptr]\n\t"
 		"mov	r1, %[hyp_stack_ptr]\n\t"
+		"mov	r2, %[vector_ptr]\n\t"
 		"hvc	#0\n\t" : :
 		[pgd_ptr] "r" (pgd_ptr),
-		[hyp_stack_ptr] "r" (hyp_stack_ptr) :
-		"r0", "r1");
+		[hyp_stack_ptr] "r" (hyp_stack_ptr),
+		[vector_ptr] "r" (vector_ptr) :
+		"r0", "r1", "r2");
 }
 
 /**
@@ -899,13 +901,6 @@ static int init_hyp_mode(void)
 	if (err)
 		goto out_free_mappings;
 	
-	/*
-	 * Set the HVBAR to the virtual kernel address
-	 */
-	for_each_online_cpu(cpu)
-		smp_call_function_single(cpu, cpu_set_vector,
-					 __kvm_hyp_vector, 1);
-
 	return 0;
 out_free_mappings:
 	free_hyp_pmds();
diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S
index 10ecdf9..8a29b8f 100644
--- a/arch/arm/kvm/init.S
+++ b/arch/arm/kvm/init.S
@@ -27,6 +27,7 @@
 @    - should be called with:
 @        r0 = Hypervisor pgd pointer
 @        r1 = top of Hyp stack (kernel VA)
+@        r2 = pointer to hyp vectors 
 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 	.text
 	.arm
@@ -113,6 +114,10 @@ __do_hyp_init:
 	@ Set stack pointer and return to the kernel
 	pop	{r0, r1, r2, r12}
 	mov	sp, r1
+
+	@ Set HVBAR to point to the HYP vectors
+	mcr	p15, 4, r2, c12, c0, 0	@ HVBAR
+
 	eret
 
 	.ltorg
diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
index eb26870..c79c6a8 100644
--- a/arch/arm/kvm/interrupts.S
+++ b/arch/arm/kvm/interrupts.S
@@ -710,6 +710,18 @@ hyp_hvc:
 	cmp     r2, #0
 	bne	guest_trap		@ Guest called HVC
 
+	@ HVC came from host. Check if this is a request to
+	@ switch HVBAR to another set of vectors (kvm_exit).
+	lsl	r0, r0, #16
+	lsr	r0, r0, #16
+	cmp	r0, #0xff
+	bne	host_switch_to_hyp	@ Not HVC #0xff
+
+	pop	{r0, r1, r2}
+	mcr	p15, 4, r0, c12, c0, 0  @ HVBAR
+	eret
+
+host_switch_to_hyp:
 	@ Store lr_usr,spsr (svc cpsr) on bottom of stack
 	mov	r1, sp
 	bic	r1, r1, #0x0ff
-- 
1.7.10.3





[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