Thomas Gleixner | caab277 | 2019-06-03 07:44:50 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 2 | /* |
| 3 | * Hypervisor stub |
| 4 | * |
| 5 | * Copyright (C) 2012 ARM Ltd. |
| 6 | * Author: Marc Zyngier <marc.zyngier@arm.com> |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 7 | */ |
| 8 | |
| 9 | #include <linux/init.h> |
| 10 | #include <linux/linkage.h> |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 11 | |
| 12 | #include <asm/assembler.h> |
Marc Zyngier | f359182 | 2021-02-08 09:57:13 +0000 | [diff] [blame] | 13 | #include <asm/el2_setup.h> |
Geoff Levand | ad72e59 | 2016-04-27 17:47:03 +0100 | [diff] [blame] | 14 | #include <asm/kvm_arm.h> |
James Morse | c94b0cf | 2016-04-27 17:47:04 +0100 | [diff] [blame] | 15 | #include <asm/kvm_asm.h> |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 16 | #include <asm/ptrace.h> |
| 17 | #include <asm/virt.h> |
| 18 | |
Marc Zyngier | fa8aa59 | 2022-06-30 17:04:55 +0100 | [diff] [blame] | 19 | // Warning, hardcoded register allocation |
Marc Zyngier | 6ab7661 | 2022-06-30 17:04:57 +0100 | [diff] [blame] | 20 | // This will clobber x1 and x2, and expect x1 to contain |
| 21 | // the id register value as read from the HW |
| 22 | .macro __check_override idreg, fld, width, pass, fail |
| 23 | ubfx x1, x1, #\fld, #\width |
Marc Zyngier | fa8aa59 | 2022-06-30 17:04:55 +0100 | [diff] [blame] | 24 | cbz x1, \fail |
| 25 | |
| 26 | adr_l x1, \idreg\()_override |
| 27 | ldr x2, [x1, FTR_OVR_VAL_OFFSET] |
| 28 | ldr x1, [x1, FTR_OVR_MASK_OFFSET] |
Marc Zyngier | 6ab7661 | 2022-06-30 17:04:57 +0100 | [diff] [blame] | 29 | ubfx x2, x2, #\fld, #\width |
| 30 | ubfx x1, x1, #\fld, #\width |
Marc Zyngier | fa8aa59 | 2022-06-30 17:04:55 +0100 | [diff] [blame] | 31 | cmp x1, xzr |
| 32 | and x2, x2, x1 |
| 33 | csinv x2, x2, xzr, ne |
| 34 | cbnz x2, \pass |
| 35 | b \fail |
| 36 | .endm |
| 37 | |
Marc Zyngier | 6ab7661 | 2022-06-30 17:04:57 +0100 | [diff] [blame] | 38 | .macro check_override idreg, fld, pass, fail |
| 39 | mrs x1, \idreg\()_el1 |
| 40 | __check_override \idreg \fld 4 \pass \fail |
| 41 | .endm |
| 42 | |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 43 | .text |
James Morse | 8fac5cb | 2019-01-24 16:32:56 +0000 | [diff] [blame] | 44 | .pushsection .hyp.text, "ax" |
| 45 | |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 46 | .align 11 |
| 47 | |
Mark Brown | 0343a7e | 2020-05-01 12:54:29 +0100 | [diff] [blame] | 48 | SYM_CODE_START(__hyp_stub_vectors) |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 49 | ventry el2_sync_invalid // Synchronous EL2t |
| 50 | ventry el2_irq_invalid // IRQ EL2t |
| 51 | ventry el2_fiq_invalid // FIQ EL2t |
| 52 | ventry el2_error_invalid // Error EL2t |
| 53 | |
Marc Zyngier | 31a32b4 | 2021-04-08 14:10:09 +0100 | [diff] [blame] | 54 | ventry elx_sync // Synchronous EL2h |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 55 | ventry el2_irq_invalid // IRQ EL2h |
| 56 | ventry el2_fiq_invalid // FIQ EL2h |
| 57 | ventry el2_error_invalid // Error EL2h |
| 58 | |
Marc Zyngier | 31a32b4 | 2021-04-08 14:10:09 +0100 | [diff] [blame] | 59 | ventry elx_sync // Synchronous 64-bit EL1 |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 60 | ventry el1_irq_invalid // IRQ 64-bit EL1 |
| 61 | ventry el1_fiq_invalid // FIQ 64-bit EL1 |
| 62 | ventry el1_error_invalid // Error 64-bit EL1 |
| 63 | |
| 64 | ventry el1_sync_invalid // Synchronous 32-bit EL1 |
| 65 | ventry el1_irq_invalid // IRQ 32-bit EL1 |
| 66 | ventry el1_fiq_invalid // FIQ 32-bit EL1 |
| 67 | ventry el1_error_invalid // Error 32-bit EL1 |
Mark Brown | 0343a7e | 2020-05-01 12:54:29 +0100 | [diff] [blame] | 68 | SYM_CODE_END(__hyp_stub_vectors) |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 69 | |
| 70 | .align 11 |
| 71 | |
Marc Zyngier | 31a32b4 | 2021-04-08 14:10:09 +0100 | [diff] [blame] | 72 | SYM_CODE_START_LOCAL(elx_sync) |
Marc Zyngier | 0b51c54 | 2017-04-03 19:38:04 +0100 | [diff] [blame] | 73 | cmp x0, #HVC_SET_VECTORS |
Marc Zyngier | f359182 | 2021-02-08 09:57:13 +0000 | [diff] [blame] | 74 | b.ne 1f |
Geoff Levand | ad72e59 | 2016-04-27 17:47:03 +0100 | [diff] [blame] | 75 | msr vbar_el2, x1 |
| 76 | b 9f |
| 77 | |
Marc Zyngier | 7ddb0c3d | 2022-06-30 17:04:52 +0100 | [diff] [blame] | 78 | 1: cmp x0, #HVC_FINALISE_EL2 |
| 79 | b.eq __finalise_el2 |
Marc Zyngier | f359182 | 2021-02-08 09:57:13 +0000 | [diff] [blame] | 80 | |
Geoff Levand | f9076ec | 2016-06-23 17:54:48 +0000 | [diff] [blame] | 81 | 2: cmp x0, #HVC_SOFT_RESTART |
| 82 | b.ne 3f |
| 83 | mov x0, x2 |
| 84 | mov x2, x4 |
| 85 | mov x4, x1 |
| 86 | mov x1, x3 |
| 87 | br x4 // no return |
| 88 | |
Marc Zyngier | fd0e0c6 | 2017-04-03 19:37:39 +0100 | [diff] [blame] | 89 | 3: cmp x0, #HVC_RESET_VECTORS |
| 90 | beq 9f // Nothing to reset! |
| 91 | |
James Morse | c94b0cf | 2016-04-27 17:47:04 +0100 | [diff] [blame] | 92 | /* Someone called kvm_call_hyp() against the hyp-stub... */ |
Remi Denis-Courmont | dc374b4 | 2020-03-04 11:36:31 +0200 | [diff] [blame] | 93 | mov_q x0, HVC_STUB_ERR |
Marc Zyngier | af42f20 | 2017-04-03 19:38:05 +0100 | [diff] [blame] | 94 | eret |
Geoff Levand | ad72e59 | 2016-04-27 17:47:03 +0100 | [diff] [blame] | 95 | |
Marc Zyngier | af42f20 | 2017-04-03 19:38:05 +0100 | [diff] [blame] | 96 | 9: mov x0, xzr |
| 97 | eret |
Marc Zyngier | 31a32b4 | 2021-04-08 14:10:09 +0100 | [diff] [blame] | 98 | SYM_CODE_END(elx_sync) |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 99 | |
Marc Zyngier | 7ddb0c3d | 2022-06-30 17:04:52 +0100 | [diff] [blame] | 100 | SYM_CODE_START_LOCAL(__finalise_el2) |
Mark Brown | 55adc08 | 2022-09-05 23:54:03 +0100 | [diff] [blame] | 101 | check_override id_aa64pfr0 ID_AA64PFR0_EL1_SVE_SHIFT .Linit_sve .Lskip_sve |
Marc Zyngier | 504ee23 | 2022-06-30 17:04:59 +0100 | [diff] [blame] | 102 | |
| 103 | .Linit_sve: /* SVE register access */ |
| 104 | mrs x0, cptr_el2 // Disable SVE traps |
| 105 | bic x0, x0, #CPTR_EL2_TZ |
| 106 | msr cptr_el2, x0 |
| 107 | isb |
| 108 | mov x1, #ZCR_ELx_LEN_MASK // SVE: Enable full vector |
| 109 | msr_s SYS_ZCR_EL2, x1 // length for EL1. |
| 110 | |
| 111 | .Lskip_sve: |
Mark Brown | 6ca2b9c | 2022-09-05 23:54:04 +0100 | [diff] [blame] | 112 | check_override id_aa64pfr1 ID_AA64PFR1_EL1_SME_SHIFT .Linit_sme .Lskip_sme |
Marc Zyngier | b3000e2 | 2022-06-30 17:04:58 +0100 | [diff] [blame] | 113 | |
| 114 | .Linit_sme: /* SME register access and priority mapping */ |
| 115 | mrs x0, cptr_el2 // Disable SME traps |
| 116 | bic x0, x0, #CPTR_EL2_TSM |
| 117 | msr cptr_el2, x0 |
| 118 | isb |
| 119 | |
| 120 | mrs x1, sctlr_el2 |
| 121 | orr x1, x1, #SCTLR_ELx_ENTP2 // Disable TPIDR2 traps |
| 122 | msr sctlr_el2, x1 |
| 123 | isb |
| 124 | |
Marc Zyngier | 18c9aa4 | 2022-06-30 17:05:00 +0100 | [diff] [blame] | 125 | mov x0, #0 // SMCR controls |
Marc Zyngier | b3000e2 | 2022-06-30 17:04:58 +0100 | [diff] [blame] | 126 | |
Marc Zyngier | 18c9aa4 | 2022-06-30 17:05:00 +0100 | [diff] [blame] | 127 | // Full FP in SM? |
| 128 | mrs_s x1, SYS_ID_AA64SMFR0_EL1 |
Will Deacon | f96d67a | 2022-07-25 10:59:15 +0100 | [diff] [blame] | 129 | __check_override id_aa64smfr0 ID_AA64SMFR0_EL1_FA64_SHIFT 1 .Linit_sme_fa64 .Lskip_sme_fa64 |
Marc Zyngier | b3000e2 | 2022-06-30 17:04:58 +0100 | [diff] [blame] | 130 | |
Marc Zyngier | 18c9aa4 | 2022-06-30 17:05:00 +0100 | [diff] [blame] | 131 | .Linit_sme_fa64: |
| 132 | orr x0, x0, SMCR_ELx_FA64_MASK |
Marc Zyngier | b3000e2 | 2022-06-30 17:04:58 +0100 | [diff] [blame] | 133 | .Lskip_sme_fa64: |
| 134 | |
Marc Zyngier | 18c9aa4 | 2022-06-30 17:05:00 +0100 | [diff] [blame] | 135 | orr x0, x0, #SMCR_ELx_LEN_MASK // Enable full SME vector |
| 136 | msr_s SYS_SMCR_EL2, x0 // length for EL1. |
Marc Zyngier | b3000e2 | 2022-06-30 17:04:58 +0100 | [diff] [blame] | 137 | |
| 138 | mrs_s x1, SYS_SMIDR_EL1 // Priority mapping supported? |
| 139 | ubfx x1, x1, #SMIDR_EL1_SMPS_SHIFT, #1 |
| 140 | cbz x1, .Lskip_sme |
| 141 | |
| 142 | msr_s SYS_SMPRIMAP_EL2, xzr // Make all priorities equal |
| 143 | |
| 144 | mrs x1, id_aa64mmfr1_el1 // HCRX_EL2 present? |
Kristina Martsenko | 6fcd019 | 2022-09-05 23:54:07 +0100 | [diff] [blame] | 145 | ubfx x1, x1, #ID_AA64MMFR1_EL1_HCX_SHIFT, #4 |
Marc Zyngier | b3000e2 | 2022-06-30 17:04:58 +0100 | [diff] [blame] | 146 | cbz x1, .Lskip_sme |
| 147 | |
| 148 | mrs_s x1, SYS_HCRX_EL2 |
| 149 | orr x1, x1, #HCRX_EL2_SMPME_MASK // Enable priority mapping |
| 150 | msr_s SYS_HCRX_EL2, x1 |
| 151 | |
| 152 | .Lskip_sme: |
| 153 | |
Marc Zyngier | 7ddb0c3d | 2022-06-30 17:04:52 +0100 | [diff] [blame] | 154 | // nVHE? No way! Give me the real thing! |
Marc Zyngier | f359182 | 2021-02-08 09:57:13 +0000 | [diff] [blame] | 155 | // Sanity check: MMU *must* be off |
| 156 | mrs x1, sctlr_el2 |
| 157 | tbnz x1, #0, 1f |
| 158 | |
| 159 | // Needs to be VHE capable, obviously |
Kristina Martsenko | 6fcd019 | 2022-09-05 23:54:07 +0100 | [diff] [blame] | 160 | check_override id_aa64mmfr1 ID_AA64MMFR1_EL1_VH_SHIFT 2f 1f |
Marc Zyngier | 41fac42 | 2021-02-08 09:57:24 +0000 | [diff] [blame] | 161 | |
Marc Zyngier | f1b6cff | 2021-02-24 09:37:36 +0000 | [diff] [blame] | 162 | 1: mov_q x0, HVC_STUB_ERR |
| 163 | eret |
| 164 | 2: |
Marc Zyngier | f359182 | 2021-02-08 09:57:13 +0000 | [diff] [blame] | 165 | // Engage the VHE magic! |
| 166 | mov_q x0, HCR_HOST_VHE_FLAGS |
| 167 | msr hcr_el2, x0 |
| 168 | isb |
| 169 | |
Marc Zyngier | f359182 | 2021-02-08 09:57:13 +0000 | [diff] [blame] | 170 | // Use the EL1 allocated stack, per-cpu offset |
| 171 | mrs x0, sp_el1 |
| 172 | mov sp, x0 |
| 173 | mrs x0, tpidr_el1 |
| 174 | msr tpidr_el2, x0 |
| 175 | |
| 176 | // FP configuration, vectors |
| 177 | mrs_s x0, SYS_CPACR_EL12 |
| 178 | msr cpacr_el1, x0 |
| 179 | mrs_s x0, SYS_VBAR_EL12 |
| 180 | msr vbar_el1, x0 |
| 181 | |
Suzuki K Poulose | a131926 | 2021-04-05 17:42:54 +0100 | [diff] [blame] | 182 | // Use EL2 translations for SPE & TRBE and disable access from EL1 |
Marc Zyngier | 19e87e1 | 2021-02-08 09:57:16 +0000 | [diff] [blame] | 183 | mrs x0, mdcr_el2 |
| 184 | bic x0, x0, #(MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT) |
Suzuki K Poulose | a131926 | 2021-04-05 17:42:54 +0100 | [diff] [blame] | 185 | bic x0, x0, #(MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT) |
Marc Zyngier | 19e87e1 | 2021-02-08 09:57:16 +0000 | [diff] [blame] | 186 | msr mdcr_el2, x0 |
| 187 | |
Marc Zyngier | f359182 | 2021-02-08 09:57:13 +0000 | [diff] [blame] | 188 | // Transfer the MM state from EL1 to EL2 |
| 189 | mrs_s x0, SYS_TCR_EL12 |
| 190 | msr tcr_el1, x0 |
| 191 | mrs_s x0, SYS_TTBR0_EL12 |
| 192 | msr ttbr0_el1, x0 |
| 193 | mrs_s x0, SYS_TTBR1_EL12 |
| 194 | msr ttbr1_el1, x0 |
| 195 | mrs_s x0, SYS_MAIR_EL12 |
| 196 | msr mair_el1, x0 |
| 197 | isb |
| 198 | |
Marc Zyngier | f1b6cff | 2021-02-24 09:37:36 +0000 | [diff] [blame] | 199 | // Hack the exception return to stay at EL2 |
| 200 | mrs x0, spsr_el1 |
| 201 | and x0, x0, #~PSR_MODE_MASK |
| 202 | mov x1, #PSR_MODE_EL2h |
| 203 | orr x0, x0, x1 |
| 204 | msr spsr_el1, x0 |
| 205 | |
| 206 | b enter_vhe |
Marc Zyngier | 7ddb0c3d | 2022-06-30 17:04:52 +0100 | [diff] [blame] | 207 | SYM_CODE_END(__finalise_el2) |
Marc Zyngier | f1b6cff | 2021-02-24 09:37:36 +0000 | [diff] [blame] | 208 | |
| 209 | // At the point where we reach enter_vhe(), we run with |
Marc Zyngier | 7ddb0c3d | 2022-06-30 17:04:52 +0100 | [diff] [blame] | 210 | // the MMU off (which is enforced by __finalise_el2()). |
Marc Zyngier | f1b6cff | 2021-02-24 09:37:36 +0000 | [diff] [blame] | 211 | // We thus need to be in the idmap, or everything will |
| 212 | // explode when enabling the MMU. |
| 213 | |
| 214 | .pushsection .idmap.text, "ax" |
| 215 | |
| 216 | SYM_CODE_START_LOCAL(enter_vhe) |
Marc Zyngier | f359182 | 2021-02-08 09:57:13 +0000 | [diff] [blame] | 217 | // Invalidate TLBs before enabling the MMU |
| 218 | tlbi vmalle1 |
| 219 | dsb nsh |
Marc Zyngier | 430251c | 2021-02-24 09:37:38 +0000 | [diff] [blame] | 220 | isb |
Marc Zyngier | f359182 | 2021-02-08 09:57:13 +0000 | [diff] [blame] | 221 | |
| 222 | // Enable the EL2 S1 MMU, as set up from EL1 |
| 223 | mrs_s x0, SYS_SCTLR_EL12 |
| 224 | set_sctlr_el1 x0 |
| 225 | |
| 226 | // Disable the EL1 S1 MMU for a good measure |
| 227 | mov_q x0, INIT_SCTLR_EL1_MMU_OFF |
| 228 | msr_s SYS_SCTLR_EL12, x0 |
| 229 | |
Marc Zyngier | f359182 | 2021-02-08 09:57:13 +0000 | [diff] [blame] | 230 | mov x0, xzr |
| 231 | |
Marc Zyngier | f1b6cff | 2021-02-24 09:37:36 +0000 | [diff] [blame] | 232 | eret |
| 233 | SYM_CODE_END(enter_vhe) |
| 234 | |
| 235 | .popsection |
Marc Zyngier | f359182 | 2021-02-08 09:57:13 +0000 | [diff] [blame] | 236 | |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 237 | .macro invalid_vector label |
Mark Brown | 0343a7e | 2020-05-01 12:54:29 +0100 | [diff] [blame] | 238 | SYM_CODE_START_LOCAL(\label) |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 239 | b \label |
Mark Brown | 0343a7e | 2020-05-01 12:54:29 +0100 | [diff] [blame] | 240 | SYM_CODE_END(\label) |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 241 | .endm |
| 242 | |
| 243 | invalid_vector el2_sync_invalid |
| 244 | invalid_vector el2_irq_invalid |
| 245 | invalid_vector el2_fiq_invalid |
| 246 | invalid_vector el2_error_invalid |
| 247 | invalid_vector el1_sync_invalid |
| 248 | invalid_vector el1_irq_invalid |
| 249 | invalid_vector el1_fiq_invalid |
| 250 | invalid_vector el1_error_invalid |
| 251 | |
Quentin Perret | e30be14 | 2021-01-28 17:38:50 +0000 | [diff] [blame] | 252 | .popsection |
| 253 | |
Marc Zyngier | 712c6ff | 2012-10-19 17:46:27 +0100 | [diff] [blame] | 254 | /* |
| 255 | * __hyp_set_vectors: Call this after boot to set the initial hypervisor |
| 256 | * vectors as part of hypervisor installation. On an SMP system, this should |
| 257 | * be called on each CPU. |
| 258 | * |
| 259 | * x0 must be the physical address of the new vector table, and must be |
| 260 | * 2KB aligned. |
| 261 | * |
| 262 | * Before calling this, you must check that the stub hypervisor is installed |
| 263 | * everywhere, by waiting for any secondary CPUs to be brought up and then |
| 264 | * checking that is_hyp_mode_available() is true. |
| 265 | * |
| 266 | * If not, there is a pre-existing hypervisor, some CPUs failed to boot, or |
| 267 | * something else went wrong... in such cases, trying to install a new |
| 268 | * hypervisor is unlikely to work as desired. |
| 269 | * |
| 270 | * When you call into your shiny new hypervisor, sp_el2 will contain junk, |
| 271 | * so you will need to set that to something sensible at the new hypervisor's |
| 272 | * initialisation entry point. |
| 273 | */ |
| 274 | |
Mark Brown | 0343a7e | 2020-05-01 12:54:29 +0100 | [diff] [blame] | 275 | SYM_FUNC_START(__hyp_set_vectors) |
Geoff Levand | ad72e59 | 2016-04-27 17:47:03 +0100 | [diff] [blame] | 276 | mov x1, x0 |
| 277 | mov x0, #HVC_SET_VECTORS |
James Morse | 00a44cd | 2016-04-27 17:47:02 +0100 | [diff] [blame] | 278 | hvc #0 |
James Morse | 00a44cd | 2016-04-27 17:47:02 +0100 | [diff] [blame] | 279 | ret |
Mark Brown | 0343a7e | 2020-05-01 12:54:29 +0100 | [diff] [blame] | 280 | SYM_FUNC_END(__hyp_set_vectors) |
Marc Zyngier | fd0e0c6 | 2017-04-03 19:37:39 +0100 | [diff] [blame] | 281 | |
Mark Brown | 0343a7e | 2020-05-01 12:54:29 +0100 | [diff] [blame] | 282 | SYM_FUNC_START(__hyp_reset_vectors) |
Marc Zyngier | fd0e0c6 | 2017-04-03 19:37:39 +0100 | [diff] [blame] | 283 | mov x0, #HVC_RESET_VECTORS |
| 284 | hvc #0 |
| 285 | ret |
Mark Brown | 0343a7e | 2020-05-01 12:54:29 +0100 | [diff] [blame] | 286 | SYM_FUNC_END(__hyp_reset_vectors) |
Marc Zyngier | 0c93df96 | 2021-02-08 09:57:14 +0000 | [diff] [blame] | 287 | |
| 288 | /* |
Marc Zyngier | 7ddb0c3d | 2022-06-30 17:04:52 +0100 | [diff] [blame] | 289 | * Entry point to finalise EL2 and switch to VHE if deemed capable |
Ard Biesheuvel | 005e126 | 2022-06-24 17:06:48 +0200 | [diff] [blame] | 290 | * |
| 291 | * w0: boot mode, as returned by init_kernel_el() |
Marc Zyngier | 0c93df96 | 2021-02-08 09:57:14 +0000 | [diff] [blame] | 292 | */ |
Marc Zyngier | 7ddb0c3d | 2022-06-30 17:04:52 +0100 | [diff] [blame] | 293 | SYM_FUNC_START(finalise_el2) |
Marc Zyngier | 0c93df96 | 2021-02-08 09:57:14 +0000 | [diff] [blame] | 294 | // Need to have booted at EL2 |
Marc Zyngier | 0c93df96 | 2021-02-08 09:57:14 +0000 | [diff] [blame] | 295 | cmp w0, #BOOT_CPU_MODE_EL2 |
| 296 | b.ne 1f |
| 297 | |
| 298 | // and still be at EL1 |
| 299 | mrs x0, CurrentEL |
| 300 | cmp x0, #CurrentEL_EL1 |
| 301 | b.ne 1f |
| 302 | |
Marc Zyngier | 7ddb0c3d | 2022-06-30 17:04:52 +0100 | [diff] [blame] | 303 | mov x0, #HVC_FINALISE_EL2 |
Marc Zyngier | 0c93df96 | 2021-02-08 09:57:14 +0000 | [diff] [blame] | 304 | hvc #0 |
| 305 | 1: |
Marc Zyngier | 0c93df96 | 2021-02-08 09:57:14 +0000 | [diff] [blame] | 306 | ret |
Marc Zyngier | 7ddb0c3d | 2022-06-30 17:04:52 +0100 | [diff] [blame] | 307 | SYM_FUNC_END(finalise_el2) |