GNU Linux-libre 5.4.274-gnu1
[releases.git] / arch / arm64 / kvm / hyp / hyp-entry.S
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2015-2018 - ARM Ltd
4  * Author: Marc Zyngier <marc.zyngier@arm.com>
5  */
6
7 #include <linux/arm-smccc.h>
8 #include <linux/linkage.h>
9
10 #include <asm/alternative.h>
11 #include <asm/assembler.h>
12 #include <asm/cpufeature.h>
13 #include <asm/kvm_arm.h>
14 #include <asm/kvm_asm.h>
15 #include <asm/kvm_mmu.h>
16 #include <asm/mmu.h>
17
18 .macro save_caller_saved_regs_vect
19         /* x0 and x1 were saved in the vector entry */
20         stp     x2, x3,   [sp, #-16]!
21         stp     x4, x5,   [sp, #-16]!
22         stp     x6, x7,   [sp, #-16]!
23         stp     x8, x9,   [sp, #-16]!
24         stp     x10, x11, [sp, #-16]!
25         stp     x12, x13, [sp, #-16]!
26         stp     x14, x15, [sp, #-16]!
27         stp     x16, x17, [sp, #-16]!
28 .endm
29
30 .macro restore_caller_saved_regs_vect
31         ldp     x16, x17, [sp], #16
32         ldp     x14, x15, [sp], #16
33         ldp     x12, x13, [sp], #16
34         ldp     x10, x11, [sp], #16
35         ldp     x8, x9,   [sp], #16
36         ldp     x6, x7,   [sp], #16
37         ldp     x4, x5,   [sp], #16
38         ldp     x2, x3,   [sp], #16
39         ldp     x0, x1,   [sp], #16
40 .endm
41
42         .text
43         .pushsection    .hyp.text, "ax"
44
45 .macro do_el2_call
46         /*
47          * Shuffle the parameters before calling the function
48          * pointed to in x0. Assumes parameters in x[1,2,3].
49          */
50         str     lr, [sp, #-16]!
51         mov     lr, x0
52         mov     x0, x1
53         mov     x1, x2
54         mov     x2, x3
55         blr     lr
56         ldr     lr, [sp], #16
57 .endm
58
59 el1_sync:                               // Guest trapped into EL2
60
61         mrs     x0, esr_el2
62         lsr     x0, x0, #ESR_ELx_EC_SHIFT
63         cmp     x0, #ESR_ELx_EC_HVC64
64         ccmp    x0, #ESR_ELx_EC_HVC32, #4, ne
65         b.ne    el1_trap
66
67         mrs     x1, vttbr_el2           // If vttbr is valid, the guest
68         cbnz    x1, el1_hvc_guest       // called HVC
69
70         /* Here, we're pretty sure the host called HVC. */
71         ldp     x0, x1, [sp], #16
72
73         /* Check for a stub HVC call */
74         cmp     x0, #HVC_STUB_HCALL_NR
75         b.hs    1f
76
77         /*
78          * Compute the idmap address of __kvm_handle_stub_hvc and
79          * jump there. Since we use kimage_voffset, do not use the
80          * HYP VA for __kvm_handle_stub_hvc, but the kernel VA instead
81          * (by loading it from the constant pool).
82          *
83          * Preserve x0-x4, which may contain stub parameters.
84          */
85         ldr     x5, =__kvm_handle_stub_hvc
86         ldr_l   x6, kimage_voffset
87
88         /* x5 = __pa(x5) */
89         sub     x5, x5, x6
90         br      x5
91
92 1:
93         /*
94          * Perform the EL2 call
95          */
96         kern_hyp_va     x0
97         do_el2_call
98
99         eret
100         sb
101
102 el1_hvc_guest:
103         /*
104          * Fastest possible path for ARM_SMCCC_ARCH_WORKAROUND_1.
105          * The workaround has already been applied on the host,
106          * so let's quickly get back to the guest. We don't bother
107          * restoring x1, as it can be clobbered anyway.
108          */
109         ldr     x1, [sp]                                // Guest's x0
110         eor     w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1
111         cbz     w1, wa_epilogue
112
113         /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */
114         eor     w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \
115                           ARM_SMCCC_ARCH_WORKAROUND_2)
116         cbz     w1, wa_epilogue
117
118         eor     w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_2 ^ \
119                           ARM_SMCCC_ARCH_WORKAROUND_3)
120         cbnz    w1, el1_trap
121
122 #ifdef CONFIG_ARM64_SSBD
123 alternative_cb  arm64_enable_wa2_handling
124         b       wa2_end
125 alternative_cb_end
126         get_vcpu_ptr    x2, x0
127         ldr     x0, [x2, #VCPU_WORKAROUND_FLAGS]
128
129         // Sanitize the argument and update the guest flags
130         ldr     x1, [sp, #8]                    // Guest's x1
131         clz     w1, w1                          // Murphy's device:
132         lsr     w1, w1, #5                      // w1 = !!w1 without using
133         eor     w1, w1, #1                      // the flags...
134         bfi     x0, x1, #VCPU_WORKAROUND_2_FLAG_SHIFT, #1
135         str     x0, [x2, #VCPU_WORKAROUND_FLAGS]
136
137         /* Check that we actually need to perform the call */
138         hyp_ldr_this_cpu x0, arm64_ssbd_callback_required, x2
139         cbz     x0, wa2_end
140
141         mov     w0, #ARM_SMCCC_ARCH_WORKAROUND_2
142         smc     #0
143
144         /* Don't leak data from the SMC call */
145         mov     x3, xzr
146 wa2_end:
147         mov     x2, xzr
148         mov     x1, xzr
149 #endif
150
151 wa_epilogue:
152         mov     x0, xzr
153         add     sp, sp, #16
154         eret
155         sb
156
157 el1_trap:
158         get_vcpu_ptr    x1, x0
159         mov     x0, #ARM_EXCEPTION_TRAP
160         b       __guest_exit
161
162 el1_irq:
163         get_vcpu_ptr    x1, x0
164         mov     x0, #ARM_EXCEPTION_IRQ
165         b       __guest_exit
166
167 el1_error:
168         get_vcpu_ptr    x1, x0
169         mov     x0, #ARM_EXCEPTION_EL1_SERROR
170         b       __guest_exit
171
172 el2_sync:
173         /* Check for illegal exception return */
174         mrs     x0, spsr_el2
175         tbnz    x0, #20, 1f
176
177         save_caller_saved_regs_vect
178         stp     x29, x30, [sp, #-16]!
179         bl      kvm_unexpected_el2_exception
180         ldp     x29, x30, [sp], #16
181         restore_caller_saved_regs_vect
182
183         eret
184
185 1:
186         /* Let's attempt a recovery from the illegal exception return */
187         get_vcpu_ptr    x1, x0
188         mov     x0, #ARM_EXCEPTION_IL
189         b       __guest_exit
190
191
192 el2_error:
193         save_caller_saved_regs_vect
194         stp     x29, x30, [sp, #-16]!
195
196         bl      kvm_unexpected_el2_exception
197
198         ldp     x29, x30, [sp], #16
199         restore_caller_saved_regs_vect
200
201         eret
202         sb
203
204 ENTRY(__hyp_do_panic)
205         mov     lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
206                       PSR_MODE_EL1h)
207         msr     spsr_el2, lr
208         ldr     lr, =panic
209         msr     elr_el2, lr
210         eret
211         sb
212 ENDPROC(__hyp_do_panic)
213
214 ENTRY(__hyp_panic)
215         get_host_ctxt x0, x1
216         b       hyp_panic
217 ENDPROC(__hyp_panic)
218
219 .macro invalid_vector   label, target = __hyp_panic
220         .align  2
221 \label:
222         b \target
223 ENDPROC(\label)
224 .endm
225
226         /* None of these should ever happen */
227         invalid_vector  el2t_sync_invalid
228         invalid_vector  el2t_irq_invalid
229         invalid_vector  el2t_fiq_invalid
230         invalid_vector  el2t_error_invalid
231         invalid_vector  el2h_sync_invalid
232         invalid_vector  el2h_irq_invalid
233         invalid_vector  el2h_fiq_invalid
234         invalid_vector  el1_fiq_invalid
235
236         .ltorg
237
238         .align 11
239
240 .macro check_preamble_length start, end
241 /* kvm_patch_vector_branch() generates code that jumps over the preamble. */
242 .if ((\end-\start) != KVM_VECTOR_PREAMBLE)
243         .error "KVM vector preamble length mismatch"
244 .endif
245 .endm
246
247 .macro valid_vect target
248         .align 7
249 661:
250         esb
251         stp     x0, x1, [sp, #-16]!
252 662:
253         b       \target
254
255 check_preamble_length 661b, 662b
256 .endm
257
258 .macro invalid_vect target
259         .align 7
260 661:
261         b       \target
262         nop
263 662:
264         ldp     x0, x1, [sp], #16
265         b       \target
266
267 check_preamble_length 661b, 662b
268 .endm
269
270 ENTRY(__kvm_hyp_vector)
271         invalid_vect    el2t_sync_invalid       // Synchronous EL2t
272         invalid_vect    el2t_irq_invalid        // IRQ EL2t
273         invalid_vect    el2t_fiq_invalid        // FIQ EL2t
274         invalid_vect    el2t_error_invalid      // Error EL2t
275
276         valid_vect      el2_sync                // Synchronous EL2h
277         invalid_vect    el2h_irq_invalid        // IRQ EL2h
278         invalid_vect    el2h_fiq_invalid        // FIQ EL2h
279         valid_vect      el2_error               // Error EL2h
280
281         valid_vect      el1_sync                // Synchronous 64-bit EL1
282         valid_vect      el1_irq                 // IRQ 64-bit EL1
283         invalid_vect    el1_fiq_invalid         // FIQ 64-bit EL1
284         valid_vect      el1_error               // Error 64-bit EL1
285
286         valid_vect      el1_sync                // Synchronous 32-bit EL1
287         valid_vect      el1_irq                 // IRQ 32-bit EL1
288         invalid_vect    el1_fiq_invalid         // FIQ 32-bit EL1
289         valid_vect      el1_error               // Error 32-bit EL1
290 ENDPROC(__kvm_hyp_vector)
291
292 #ifdef CONFIG_KVM_INDIRECT_VECTORS
293 .macro hyp_ventry
294         .align 7
295 1:      esb
296         .rept 26
297         nop
298         .endr
299 /*
300  * The default sequence is to directly branch to the KVM vectors,
301  * using the computed offset. This applies for VHE as well as
302  * !ARM64_HARDEN_EL2_VECTORS. The first vector must always run the preamble.
303  *
304  * For ARM64_HARDEN_EL2_VECTORS configurations, this gets replaced
305  * with:
306  *
307  * stp  x0, x1, [sp, #-16]!
308  * movz x0, #(addr & 0xffff)
309  * movk x0, #((addr >> 16) & 0xffff), lsl #16
310  * movk x0, #((addr >> 32) & 0xffff), lsl #32
311  * br   x0
312  *
313  * Where:
314  * addr = kern_hyp_va(__kvm_hyp_vector) + vector-offset + KVM_VECTOR_PREAMBLE.
315  * See kvm_patch_vector_branch for details.
316  */
317 alternative_cb  kvm_patch_vector_branch
318         stp     x0, x1, [sp, #-16]!
319         b       __kvm_hyp_vector + (1b - 0b + KVM_VECTOR_PREAMBLE)
320         nop
321         nop
322         nop
323 alternative_cb_end
324 .endm
325
326 .macro generate_vectors
327 0:
328         .rept 16
329         hyp_ventry
330         .endr
331         .org 0b + SZ_2K         // Safety measure
332 .endm
333
334         .align  11
335 ENTRY(__bp_harden_hyp_vecs_start)
336         .rept BP_HARDEN_EL2_SLOTS
337         generate_vectors
338         .endr
339 ENTRY(__bp_harden_hyp_vecs_end)
340
341         .popsection
342
343 ENTRY(__smccc_workaround_1_smc_start)
344         esb
345         sub     sp, sp, #(8 * 4)
346         stp     x2, x3, [sp, #(8 * 0)]
347         stp     x0, x1, [sp, #(8 * 2)]
348         mov     w0, #ARM_SMCCC_ARCH_WORKAROUND_1
349         smc     #0
350         ldp     x2, x3, [sp, #(8 * 0)]
351         ldp     x0, x1, [sp, #(8 * 2)]
352         add     sp, sp, #(8 * 4)
353 ENTRY(__smccc_workaround_1_smc_end)
354
355 ENTRY(__smccc_workaround_3_smc_start)
356         esb
357         sub     sp, sp, #(8 * 4)
358         stp     x2, x3, [sp, #(8 * 0)]
359         stp     x0, x1, [sp, #(8 * 2)]
360         mov     w0, #ARM_SMCCC_ARCH_WORKAROUND_3
361         smc     #0
362         ldp     x2, x3, [sp, #(8 * 0)]
363         ldp     x0, x1, [sp, #(8 * 2)]
364         add     sp, sp, #(8 * 4)
365 ENTRY(__smccc_workaround_3_smc_end)
366
367 ENTRY(__spectre_bhb_loop_k8_start)
368         esb
369         sub     sp, sp, #(8 * 2)
370         stp     x0, x1, [sp, #(8 * 0)]
371         mov     x0, #8
372 2:      b       . + 4
373         subs    x0, x0, #1
374         b.ne    2b
375         dsb     nsh
376         isb
377         ldp     x0, x1, [sp, #(8 * 0)]
378         add     sp, sp, #(8 * 2)
379 ENTRY(__spectre_bhb_loop_k8_end)
380
381 ENTRY(__spectre_bhb_loop_k24_start)
382         esb
383         sub     sp, sp, #(8 * 2)
384         stp     x0, x1, [sp, #(8 * 0)]
385         mov     x0, #24
386 2:      b       . + 4
387         subs    x0, x0, #1
388         b.ne    2b
389         dsb     nsh
390         isb
391         ldp     x0, x1, [sp, #(8 * 0)]
392         add     sp, sp, #(8 * 2)
393 ENTRY(__spectre_bhb_loop_k24_end)
394
395 ENTRY(__spectre_bhb_loop_k32_start)
396         esb
397         sub     sp, sp, #(8 * 2)
398         stp     x0, x1, [sp, #(8 * 0)]
399         mov     x0, #32
400 2:      b       . + 4
401         subs    x0, x0, #1
402         b.ne    2b
403         dsb     nsh
404         isb
405         ldp     x0, x1, [sp, #(8 * 0)]
406         add     sp, sp, #(8 * 2)
407 ENTRY(__spectre_bhb_loop_k32_end)
408
409 ENTRY(__spectre_bhb_clearbhb_start)
410         esb
411         clearbhb
412         isb
413 ENTRY(__spectre_bhb_clearbhb_end)
414 #endif