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@xxxxxxx> --- arch/arm/include/asm/kvm_asm.h | 5 --- arch/arm/kvm/arm.c | 54 +++++++++++++++++++++++++-------------- arch/arm/kvm/init.S | 34 +++++++++++++++--------- arch/arm/kvm/interrupts.S | 14 ++++++++++ 4 files changed, 69 insertions(+), 38 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 390e8b8..da5fc5f 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -39,6 +39,7 @@ #include <asm/tlbflush.h> #include <asm/cacheflush.h> #include <asm/cputype.h> +#include <asm/virt.h> #include <asm/kvm_arm.h> #include <asm/kvm_asm.h> #include <asm/kvm_mmu.h> @@ -701,21 +702,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) @@ -723,25 +720,34 @@ 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; - cpu_set_vector(vector); + /* Switch from the HYP stub to our own HYP init vector */ + __hyp_set_vectors((unsigned long)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. The init code corrupts r12, so set the clobber + * list accordingly. */ 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", "r12"); } +static unsigned long hyp_default_vectors; + /** * Inits Hyp-mode on all online CPUs */ @@ -752,6 +758,12 @@ static int init_hyp_mode(void) int err = 0; /* + * It is probably enough to obtain the default on one + * CPU. It's unlikely to be different on the others. + */ + hyp_default_vectors = __hyp_get_vectors(); + + /* * Allocate stack pages for Hypervisor-mode */ for_each_possible_cpu(cpu) { @@ -807,13 +819,6 @@ static int init_hyp_mode(void) } /* - * 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); - - /* * Map the host VFP structures */ for_each_possible_cpu(cpu) { @@ -844,6 +849,11 @@ int kvm_arch_init(void *opaque) { int err; + if (!is_hyp_mode_available()) { + kvm_err("HYP mode not available\n"); + return -ENODEV; + } + if (kvm_target_cpu() < 0) { kvm_err("Target CPU (%#08x) not supported!\n", read_cpuid_id()); return -ENODEV; @@ -864,9 +874,13 @@ static void cpu_exit_hyp_mode(void *vector) cpu_set_vector(vector); /* - * Disable Hyp-MMU for each cpu + * Disable Hyp-MMU for each cpu, and switch back to the + * default vectors. */ - asm volatile ("hvc #0"); + asm volatile ("mov r0, %[vector_ptr]\n\t" + "hvc #0\n\t" : : + [vector_ptr] "r" (hyp_default_vectors) : + "r0"); } static int exit_hyp_mode(void) diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S index 4db26cb..77a8e1f 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 @@ -106,8 +107,12 @@ __do_hyp_init: isb @ Set stack pointer and return to the kernel - pop {r0, r1, r2, r12} + pop {r0, r1, r2} mov sp, r1 + + @ Set HVBAR to point to the HYP vectors + mcr p15, 4, r2, c12, c0, 0 @ HVBAR + eret .ltorg @@ -123,22 +128,25 @@ __kvm_hyp_exit: .globl __kvm_hyp_exit @ Hyp-mode exception vector - nop - nop - nop - nop - nop - b __do_hyp_exit - nop - nop + W(b) . + W(b) . + W(b) . + W(b) . + W(b) . + W(b) __do_hyp_exit + W(b) . + W(b) . __do_hyp_exit: - @ Clear the MMU and TE bits in the HSCR - mrc p15, 4, sp, c1, c0, 0 @ HSCR - bic sp, sp, #((1 << 30) | (1 << 0)) + @ Set the next HVBAR (normally the default vectors) + mcr p15, 4, r0, c12, c0, 0 @ HVBAR + + @ Clear the MMU bit in the HSCR + mrc p15, 4, r0, c1, c0, 0 @ HSCR + bic r0, r0, #HSCTLR_M isb - mcr p15, 4, sp, c1, c0, 0 @ HSCR + mcr p15, 4, r0, c1, c0, 0 @ HSCR mcr p15, 4, r0, c8, c7, 0 @ Flush Hyp TLB, r0 ignored isb eret diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S index 5816376..4d6cc71 100644 --- a/arch/arm/kvm/interrupts.S +++ b/arch/arm/kvm/interrupts.S @@ -637,6 +637,20 @@ 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 + + @ We're switching away from this hypervisor, let's blow the TLBs. + pop {r0, r1, r2} + mcr p15, 4, r0, c12, c0, 0 @ HVBAR + mcr p15, 4, r0, c8, c7, 0 @ Flush Hyp TLB, r0 ignored + eret + +host_switch_to_hyp: @ Store lr_usr,spsr (svc cpsr) on bottom of stack mov r1, sp bic r1, r1, #0x0ff -- 1.7.8.6 _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm