Commit 04e4caa8 authored by Andrew Scull's avatar Andrew Scull Committed by Marc Zyngier

KVM: arm64: nVHE: Migrate hyp-init to SMCCC

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: default avatarAndrew Scull <ascull@google.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20200915104643.2543892-19-ascull@google.com
parent 05469831
...@@ -480,11 +480,6 @@ int kvm_test_age_hva(struct kvm *kvm, unsigned long hva); ...@@ -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_halt_guest(struct kvm *kvm);
void kvm_arm_resume_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, ...) \ #define kvm_call_hyp_nvhe(f, ...) \
({ \ ({ \
struct arm_smccc_res res; \ struct arm_smccc_res res; \
......
...@@ -13,7 +13,7 @@ obj-$(CONFIG_KVM) += hyp/ ...@@ -13,7 +13,7 @@ obj-$(CONFIG_KVM) += hyp/
kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \ kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \
$(KVM)/vfio.o $(KVM)/irqchip.o \ $(KVM)/vfio.o $(KVM)/irqchip.o \
arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.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 \ guest.o debug.o reset.o sys_regs.o \
vgic-sys-reg-v3.o fpsimd.o pmu.o \ vgic-sys-reg-v3.o fpsimd.o pmu.o \
aarch32.o arch_timer.o \ aarch32.o arch_timer.o \
......
...@@ -1264,6 +1264,7 @@ static void cpu_init_hyp_mode(void) ...@@ -1264,6 +1264,7 @@ static void cpu_init_hyp_mode(void)
unsigned long hyp_stack_ptr; unsigned long hyp_stack_ptr;
unsigned long vector_ptr; unsigned long vector_ptr;
unsigned long tpidr_el2; unsigned long tpidr_el2;
struct arm_smccc_res res;
/* Switch from the HYP stub to our own HYP init vector */ /* Switch from the HYP stub to our own HYP init vector */
__hyp_set_vectors(kvm_get_idmap_vector()); __hyp_set_vectors(kvm_get_idmap_vector());
...@@ -1288,7 +1289,9 @@ static void cpu_init_hyp_mode(void) ...@@ -1288,7 +1289,9 @@ static void cpu_init_hyp_mode(void)
* cpus_have_const_cap() wrapper. * cpus_have_const_cap() wrapper.
*/ */
BUG_ON(!system_capabilities_finalized()); 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 * Disabling SSBD on a non-VHE system requires us to enable SSBS
......
/* 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)
...@@ -4,11 +4,13 @@ ...@@ -4,11 +4,13 @@
* Author: Marc Zyngier <marc.zyngier@arm.com> * Author: Marc Zyngier <marc.zyngier@arm.com>
*/ */
#include <linux/arm-smccc.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/alternative.h> #include <asm/alternative.h>
#include <asm/assembler.h> #include <asm/assembler.h>
#include <asm/kvm_arm.h> #include <asm/kvm_arm.h>
#include <asm/kvm_asm.h>
#include <asm/kvm_mmu.h> #include <asm/kvm_mmu.h>
#include <asm/pgtable-hwdef.h> #include <asm/pgtable-hwdef.h>
#include <asm/sysreg.h> #include <asm/sysreg.h>
...@@ -44,27 +46,37 @@ __invalid: ...@@ -44,27 +46,37 @@ __invalid:
b . b .
/* /*
* x0: HYP pgd * x0: SMCCC function ID
* x1: HYP stack * x1: HYP pgd
* x2: HYP vectors * x2: per-CPU offset
* x3: per-CPU offset * x3: HYP stack
* x4: HYP vectors
*/ */
__do_hyp_init: __do_hyp_init:
/* Check for a stub HVC call */ /* Check for a stub HVC call */
cmp x0, #HVC_STUB_HCALL_NR cmp x0, #HVC_STUB_HCALL_NR
b.lo __kvm_handle_stub_hvc 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 alternative_if ARM64_HAS_CNP
orr x4, x4, #TTBR_CNP_BIT orr x0, x0, #TTBR_CNP_BIT
alternative_else_nop_endif alternative_else_nop_endif
msr ttbr0_el2, x4 msr ttbr0_el2, x0
mrs x4, tcr_el1 mrs x0, tcr_el1
mov_q x5, TCR_EL2_MASK mov_q x1, TCR_EL2_MASK
and x4, x4, x5 and x0, x0, x1
mov x5, #TCR_EL2_RES1 mov x1, #TCR_EL2_RES1
orr x4, x4, x5 orr x0, x0, x1
/* /*
* The ID map may be configured to use an extended virtual address * The ID map may be configured to use an extended virtual address
...@@ -80,18 +92,18 @@ alternative_else_nop_endif ...@@ -80,18 +92,18 @@ alternative_else_nop_endif
* *
* So use the same T0SZ value we use for the ID map. * So use the same T0SZ value we use for the ID map.
*/ */
ldr_l x5, idmap_t0sz ldr_l x1, idmap_t0sz
bfi x4, x5, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH bfi x0, x1, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH
/* /*
* Set the PS bits in TCR_EL2. * 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 mrs x0, mair_el1
msr mair_el2, x4 msr mair_el2, x0
isb isb
/* Invalidate the stale TLBs from Bootloader */ /* Invalidate the stale TLBs from Bootloader */
...@@ -103,24 +115,22 @@ alternative_else_nop_endif ...@@ -103,24 +115,22 @@ alternative_else_nop_endif
* as well as the EE bit on BE. Drop the A flag since the compiler * as well as the EE bit on BE. Drop the A flag since the compiler
* is allowed to generate unaligned accesses. * is allowed to generate unaligned accesses.
*/ */
mov_q x4, (SCTLR_EL2_RES1 | (SCTLR_ELx_FLAGS & ~SCTLR_ELx_A)) mov_q x0, (SCTLR_EL2_RES1 | (SCTLR_ELx_FLAGS & ~SCTLR_ELx_A))
CPU_BE( orr x4, x4, #SCTLR_ELx_EE) CPU_BE( orr x0, x0, #SCTLR_ELx_EE)
alternative_if ARM64_HAS_ADDRESS_AUTH 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) SCTLR_ELx_ENDA | SCTLR_ELx_ENDB)
orr x4, x4, x5 orr x0, x0, x1
alternative_else_nop_endif alternative_else_nop_endif
msr sctlr_el2, x4 msr sctlr_el2, x0
isb isb
/* Set the stack and new vectors */ /* Set the stack and new vectors */
mov sp, x1 mov sp, x3
msr vbar_el2, x2 msr vbar_el2, x4
/* Set tpidr_el2 for use by HYP */
msr tpidr_el2, x3
/* Hello, World! */ /* Hello, World! */
mov x0, #SMCCC_RET_SUCCESS
eret eret
SYM_CODE_END(__kvm_hyp_init) SYM_CODE_END(__kvm_hyp_init)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment