OSDN Git Service

KVM: arm64: nVHE: Migrate hyp-init to SMCCC
authorAndrew Scull <ascull@google.com>
Tue, 15 Sep 2020 10:46:42 +0000 (11:46 +0100)
committerMarc Zyngier <maz@kernel.org>
Tue, 15 Sep 2020 17:39:04 +0000 (18:39 +0100)
To complete the transition to SMCCC, the hyp initialization is given a
function ID. This looks neater than comparing the hyp stub function IDs
to the page table physical address.

Some care is taken to only clobber x0-3 before the host context is saved
as only those registers can be clobbered accoring to SMCCC. Fortunately,
only a few acrobatics are needed. The possible new tpidr_el2 is moved to
the argument in x2 so that it can be stashed in tpidr_el2 early to free
up a scratch register. The page table configuration then makes use of
x0-2.

Signed-off-by: Andrew Scull <ascull@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20200915104643.2543892-19-ascull@google.com
arch/arm64/include/asm/kvm_host.h
arch/arm64/kvm/Makefile
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp.S [deleted file]
arch/arm64/kvm/hyp/nvhe/hyp-init.S

index 82c941c..ef0325c 100644 (file)
@@ -480,11 +480,6 @@ int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 void kvm_arm_halt_guest(struct kvm *kvm);
 void kvm_arm_resume_guest(struct kvm *kvm);
 
-u64 __kvm_call_hyp_init(phys_addr_t pgd_ptr,
-                       unsigned long hyp_stack_ptr,
-                       unsigned long vector_ptr,
-                       unsigned long tpidr_el2);
-
 #define kvm_call_hyp_nvhe(f, ...)                                              \
        ({                                                              \
                struct arm_smccc_res res;                               \
index 99977c1..1504c81 100644 (file)
@@ -13,7 +13,7 @@ obj-$(CONFIG_KVM) += hyp/
 kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \
         $(KVM)/vfio.o $(KVM)/irqchip.o \
         arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.o \
-        inject_fault.o regmap.o va_layout.o hyp.o handle_exit.o \
+        inject_fault.o regmap.o va_layout.o handle_exit.o \
         guest.o debug.o reset.o sys_regs.o \
         vgic-sys-reg-v3.o fpsimd.o pmu.o \
         aarch32.o arch_timer.o \
index 49aa08b..c074d98 100644 (file)
@@ -1264,6 +1264,7 @@ static void cpu_init_hyp_mode(void)
        unsigned long hyp_stack_ptr;
        unsigned long vector_ptr;
        unsigned long tpidr_el2;
+       struct arm_smccc_res res;
 
        /* Switch from the HYP stub to our own HYP init vector */
        __hyp_set_vectors(kvm_get_idmap_vector());
@@ -1288,7 +1289,9 @@ static void cpu_init_hyp_mode(void)
         * cpus_have_const_cap() wrapper.
         */
        BUG_ON(!system_capabilities_finalized());
-       __kvm_call_hyp_init(pgd_ptr, hyp_stack_ptr, vector_ptr, tpidr_el2);
+       arm_smccc_1_1_hvc(KVM_HOST_SMCCC_FUNC(__kvm_hyp_init),
+                         pgd_ptr, tpidr_el2, hyp_stack_ptr, vector_ptr, &res);
+       WARN_ON(res.a0 != SMCCC_RET_SUCCESS);
 
        /*
         * Disabling SSBD on a non-VHE system requires us to enable SSBS
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
deleted file mode 100644 (file)
index 12aa426..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012,2013 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.com>
- */
-
-#include <linux/linkage.h>
-
-#include <asm/alternative.h>
-#include <asm/assembler.h>
-#include <asm/cpufeature.h>
-
-/*
- * u64 __kvm_call_hyp_init(phys_addr_t pgd_ptr,
- *                        unsigned long hyp_stack_ptr,
- *                        unsigned long vector_ptr,
- *                        unsigned long tpidr_el2);
- */
-SYM_FUNC_START(__kvm_call_hyp_init)
-       hvc     #0
-       ret
-SYM_FUNC_END(__kvm_call_hyp_init)
index abe885e..47224dc 100644 (file)
@@ -4,11 +4,13 @@
  * Author: Marc Zyngier <marc.zyngier@arm.com>
  */
 
+#include <linux/arm-smccc.h>
 #include <linux/linkage.h>
 
 #include <asm/alternative.h>
 #include <asm/assembler.h>
 #include <asm/kvm_arm.h>
+#include <asm/kvm_asm.h>
 #include <asm/kvm_mmu.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/sysreg.h>
@@ -44,27 +46,37 @@ __invalid:
        b       .
 
        /*
-        * x0: HYP pgd
-        * x1: HYP stack
-        * x2: HYP vectors
-        * x3: per-CPU offset
+        * x0: SMCCC function ID
+        * x1: HYP pgd
+        * x2: per-CPU offset
+        * x3: HYP stack
+        * x4: HYP vectors
         */
 __do_hyp_init:
        /* Check for a stub HVC call */
        cmp     x0, #HVC_STUB_HCALL_NR
        b.lo    __kvm_handle_stub_hvc
 
-       phys_to_ttbr x4, x0
+       /* Set tpidr_el2 for use by HYP to free a register */
+       msr     tpidr_el2, x2
+
+       mov     x2, #KVM_HOST_SMCCC_FUNC(__kvm_hyp_init)
+       cmp     x0, x2
+       b.eq    1f
+       mov     x0, #SMCCC_RET_NOT_SUPPORTED
+       eret
+
+1:     phys_to_ttbr x0, x1
 alternative_if ARM64_HAS_CNP
-       orr     x4, x4, #TTBR_CNP_BIT
+       orr     x0, x0, #TTBR_CNP_BIT
 alternative_else_nop_endif
-       msr     ttbr0_el2, x4
+       msr     ttbr0_el2, x0
 
-       mrs     x4, tcr_el1
-       mov_q   x5, TCR_EL2_MASK
-       and     x4, x4, x5
-       mov     x5, #TCR_EL2_RES1
-       orr     x4, x4, x5
+       mrs     x0, tcr_el1
+       mov_q   x1, TCR_EL2_MASK
+       and     x0, x0, x1
+       mov     x1, #TCR_EL2_RES1
+       orr     x0, x0, x1
 
        /*
         * The ID map may be configured to use an extended virtual address
@@ -80,18 +92,18 @@ alternative_else_nop_endif
         *
         * So use the same T0SZ value we use for the ID map.
         */
-       ldr_l   x5, idmap_t0sz
-       bfi     x4, x5, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH
+       ldr_l   x1, idmap_t0sz
+       bfi     x0, x1, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH
 
        /*
         * Set the PS bits in TCR_EL2.
         */
-       tcr_compute_pa_size x4, #TCR_EL2_PS_SHIFT, x5, x6
+       tcr_compute_pa_size x0, #TCR_EL2_PS_SHIFT, x1, x2
 
-       msr     tcr_el2, x4
+       msr     tcr_el2, x0
 
-       mrs     x4, mair_el1
-       msr     mair_el2, x4
+       mrs     x0, mair_el1
+       msr     mair_el2, x0
        isb
 
        /* Invalidate the stale TLBs from Bootloader */
@@ -103,24 +115,22 @@ alternative_else_nop_endif
         * as well as the EE bit on BE. Drop the A flag since the compiler
         * is allowed to generate unaligned accesses.
         */
-       mov_q   x4, (SCTLR_EL2_RES1 | (SCTLR_ELx_FLAGS & ~SCTLR_ELx_A))
-CPU_BE(        orr     x4, x4, #SCTLR_ELx_EE)
+       mov_q   x0, (SCTLR_EL2_RES1 | (SCTLR_ELx_FLAGS & ~SCTLR_ELx_A))
+CPU_BE(        orr     x0, x0, #SCTLR_ELx_EE)
 alternative_if ARM64_HAS_ADDRESS_AUTH
-       mov_q   x5, (SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | \
+       mov_q   x1, (SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | \
                     SCTLR_ELx_ENDA | SCTLR_ELx_ENDB)
-       orr     x4, x4, x5
+       orr     x0, x0, x1
 alternative_else_nop_endif
-       msr     sctlr_el2, x4
+       msr     sctlr_el2, x0
        isb
 
        /* Set the stack and new vectors */
-       mov     sp, x1
-       msr     vbar_el2, x2
-
-       /* Set tpidr_el2 for use by HYP */
-       msr     tpidr_el2, x3
+       mov     sp, x3
+       msr     vbar_el2, x4
 
        /* Hello, World! */
+       mov     x0, #SMCCC_RET_SUCCESS
        eret
 SYM_CODE_END(__kvm_hyp_init)