Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[sfrench/cifs-2.6.git] / arch / arm64 / kvm / hyp / nvhe / switch.c
index 8d3dd4f479244c3080da9a32b70fb6b3ce216ec8..a457a0306e031fbd3ecf5993f8a14173dfddff8e 100644 (file)
 #include <asm/processor.h>
 #include <asm/thread_info.h>
 
 #include <asm/processor.h>
 #include <asm/thread_info.h>
 
+/* Non-VHE specific context */
+DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data);
+DEFINE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
+DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
+
 static void __activate_traps(struct kvm_vcpu *vcpu)
 {
        u64 val;
 static void __activate_traps(struct kvm_vcpu *vcpu)
 {
        u64 val;
@@ -42,6 +47,7 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
        }
 
        write_sysreg(val, cptr_el2);
        }
 
        write_sysreg(val, cptr_el2);
+       write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
 
        if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
                struct kvm_cpu_context *ctxt = &vcpu->arch.ctxt;
 
        if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
                struct kvm_cpu_context *ctxt = &vcpu->arch.ctxt;
@@ -60,6 +66,7 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
 
 static void __deactivate_traps(struct kvm_vcpu *vcpu)
 {
 
 static void __deactivate_traps(struct kvm_vcpu *vcpu)
 {
+       extern char __kvm_hyp_host_vector[];
        u64 mdcr_el2;
 
        ___deactivate_traps(vcpu);
        u64 mdcr_el2;
 
        ___deactivate_traps(vcpu);
@@ -91,9 +98,10 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
        write_sysreg(mdcr_el2, mdcr_el2);
        write_sysreg(HCR_HOST_NVHE_FLAGS, hcr_el2);
        write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
        write_sysreg(mdcr_el2, mdcr_el2);
        write_sysreg(HCR_HOST_NVHE_FLAGS, hcr_el2);
        write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
+       write_sysreg(__kvm_hyp_host_vector, vbar_el2);
 }
 
 }
 
-static void __deactivate_vm(struct kvm_vcpu *vcpu)
+static void __load_host_stage2(void)
 {
        write_sysreg(0, vttbr_el2);
 }
 {
        write_sysreg(0, vttbr_el2);
 }
@@ -173,9 +181,7 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
                pmr_sync();
        }
 
                pmr_sync();
        }
 
-       vcpu = kern_hyp_va(vcpu);
-
-       host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt;
+       host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
        host_ctxt->__hyp_running_vcpu = vcpu;
        guest_ctxt = &vcpu->arch.ctxt;
 
        host_ctxt->__hyp_running_vcpu = vcpu;
        guest_ctxt = &vcpu->arch.ctxt;
 
@@ -194,7 +200,7 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
        __sysreg32_restore_state(vcpu);
        __sysreg_restore_state_nvhe(guest_ctxt);
 
        __sysreg32_restore_state(vcpu);
        __sysreg_restore_state_nvhe(guest_ctxt);
 
-       __activate_vm(kern_hyp_va(vcpu->arch.hw_mmu));
+       __load_guest_stage2(kern_hyp_va(vcpu->arch.hw_mmu));
        __activate_traps(vcpu);
 
        __hyp_vgic_restore_state(vcpu);
        __activate_traps(vcpu);
 
        __hyp_vgic_restore_state(vcpu);
@@ -204,7 +210,7 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
 
        do {
                /* Jump in the fire! */
 
        do {
                /* Jump in the fire! */
-               exit_code = __guest_enter(vcpu, host_ctxt);
+               exit_code = __guest_enter(vcpu);
 
                /* And we're baaack! */
        } while (fixup_guest_exit(vcpu, &exit_code));
 
                /* And we're baaack! */
        } while (fixup_guest_exit(vcpu, &exit_code));
@@ -215,7 +221,7 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
        __hyp_vgic_save_state(vcpu);
 
        __deactivate_traps(vcpu);
        __hyp_vgic_save_state(vcpu);
 
        __deactivate_traps(vcpu);
-       __deactivate_vm(vcpu);
+       __load_host_stage2();
 
        __sysreg_restore_state_nvhe(host_ctxt);
 
 
        __sysreg_restore_state_nvhe(host_ctxt);
 
@@ -235,35 +241,31 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
        if (system_uses_irq_prio_masking())
                gic_write_pmr(GIC_PRIO_IRQOFF);
 
        if (system_uses_irq_prio_masking())
                gic_write_pmr(GIC_PRIO_IRQOFF);
 
+       host_ctxt->__hyp_running_vcpu = NULL;
+
        return exit_code;
 }
 
        return exit_code;
 }
 
-void __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt)
+void __noreturn hyp_panic(void)
 {
        u64 spsr = read_sysreg_el2(SYS_SPSR);
        u64 elr = read_sysreg_el2(SYS_ELR);
        u64 par = read_sysreg(par_el1);
 {
        u64 spsr = read_sysreg_el2(SYS_SPSR);
        u64 elr = read_sysreg_el2(SYS_ELR);
        u64 par = read_sysreg(par_el1);
-       struct kvm_vcpu *vcpu = host_ctxt->__hyp_running_vcpu;
-       unsigned long str_va;
+       bool restore_host = true;
+       struct kvm_cpu_context *host_ctxt;
+       struct kvm_vcpu *vcpu;
 
 
-       if (read_sysreg(vttbr_el2)) {
+       host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
+       vcpu = host_ctxt->__hyp_running_vcpu;
+
+       if (vcpu) {
                __timer_disable_traps(vcpu);
                __deactivate_traps(vcpu);
                __timer_disable_traps(vcpu);
                __deactivate_traps(vcpu);
-               __deactivate_vm(vcpu);
+               __load_host_stage2();
                __sysreg_restore_state_nvhe(host_ctxt);
        }
 
                __sysreg_restore_state_nvhe(host_ctxt);
        }
 
-       /*
-        * Force the panic string to be loaded from the literal pool,
-        * making sure it is a kernel address and not a PC-relative
-        * reference.
-        */
-       asm volatile("ldr %0, =%1" : "=r" (str_va) : "S" (__hyp_panic_string));
-
-       __hyp_do_panic(str_va,
-                      spsr, elr,
-                      read_sysreg(esr_el2), read_sysreg_el2(SYS_FAR),
-                      read_sysreg(hpfar_el2), par, vcpu);
+       __hyp_do_panic(restore_host, spsr, elr, par);
        unreachable();
 }
 
        unreachable();
 }