1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright (C) 2012,2013 - ARM Ltd
4 * Author: Marc Zyngier <marc.zyngier@arm.com>
7 #include <linux/linkage.h>
9 #include <asm/alternative.h>
10 #include <asm/assembler.h>
11 #include <asm/kvm_arm.h>
12 #include <asm/kvm_mmu.h>
13 #include <asm/pgtable-hwdef.h>
14 #include <asm/sysreg.h>
18 .pushsection .hyp.idmap.text, "ax"
22 SYM_CODE_START(__kvm_hyp_init)
23 ventry __invalid // Synchronous EL2t
24 ventry __invalid // IRQ EL2t
25 ventry __invalid // FIQ EL2t
26 ventry __invalid // Error EL2t
28 ventry __invalid // Synchronous EL2h
29 ventry __invalid // IRQ EL2h
30 ventry __invalid // FIQ EL2h
31 ventry __invalid // Error EL2h
33 ventry __do_hyp_init // Synchronous 64-bit EL1
34 ventry __invalid // IRQ 64-bit EL1
35 ventry __invalid // FIQ 64-bit EL1
36 ventry __invalid // Error 64-bit EL1
38 ventry __invalid // Synchronous 32-bit EL1
39 ventry __invalid // IRQ 32-bit EL1
40 ventry __invalid // FIQ 32-bit EL1
41 ventry __invalid // Error 32-bit EL1
53 /* Check for a stub HVC call */
54 cmp x0, #HVC_STUB_HCALL_NR
55 b.lo __kvm_handle_stub_hvc
58 alternative_if ARM64_HAS_CNP
59 orr x4, x4, #TTBR_CNP_BIT
60 alternative_else_nop_endif
64 mov_q x5, TCR_EL2_MASK
70 * The ID map may be configured to use an extended virtual address
71 * range. This is only the case if system RAM is out of range for the
72 * currently configured page size and VA_BITS, in which case we will
73 * also need the extended virtual range for the HYP ID map, or we won't
74 * be able to enable the EL2 MMU.
76 * However, at EL2, there is only one TTBR register, and we can't switch
77 * between translation tables *and* update TCR_EL2.T0SZ at the same
78 * time. Bottom line: we need to use the extended range with *both* our
81 * So use the same T0SZ value we use for the ID map.
84 bfi x4, x5, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH
87 * Set the PS bits in TCR_EL2.
89 tcr_compute_pa_size x4, #TCR_EL2_PS_SHIFT, x5, x6
97 /* Invalidate the stale TLBs from Bootloader */
102 * Preserve all the RES1 bits while setting the default flags,
103 * as well as the EE bit on BE. Drop the A flag since the compiler
104 * is allowed to generate unaligned accesses.
106 mov_q x4, (SCTLR_EL2_RES1 | (SCTLR_ELx_FLAGS & ~SCTLR_ELx_A))
107 CPU_BE( orr x4, x4, #SCTLR_ELx_EE)
108 alternative_if ARM64_HAS_ADDRESS_AUTH
109 mov_q x5, (SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | \
110 SCTLR_ELx_ENDA | SCTLR_ELx_ENDB)
112 alternative_else_nop_endif
116 /* Set the stack and new vectors */
121 /* Set tpidr_el2 for use by HYP */
126 SYM_CODE_END(__kvm_hyp_init)
128 SYM_CODE_START(__kvm_handle_stub_hvc)
129 cmp x0, #HVC_SOFT_RESTART
132 /* This is where we're about to jump, staying at EL2 */
134 mov x0, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT | PSR_MODE_EL2h)
137 /* Shuffle the arguments, and don't come back */
143 1: cmp x0, #HVC_RESET_VECTORS
147 * Set the HVC_RESET_VECTORS return code before entering the common
148 * path so that we do not clobber x0-x2 in case we are coming via
153 /* Reset kvm back to the hyp stub. */
155 mov_q x6, SCTLR_ELx_FLAGS
156 bic x5, x5, x6 // Clear SCTL_M and etc
157 pre_disable_mmu_workaround
161 /* Install stub vectors */
162 adr_l x5, __hyp_stub_vectors
166 1: /* Bad stub call */
167 mov_q x0, HVC_STUB_ERR
170 SYM_CODE_END(__kvm_handle_stub_hvc)