GNU Linux-libre 4.14.290-gnu1
[releases.git] / arch / arm64 / kvm / hyp / hyp-entry.S
1 /*
2  * Copyright (C) 2015 - ARM Ltd
3  * Author: Marc Zyngier <marc.zyngier@arm.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <linux/arm-smccc.h>
19 #include <linux/linkage.h>
20
21 #include <asm/alternative.h>
22 #include <asm/assembler.h>
23 #include <asm/cpufeature.h>
24 #include <asm/kvm_arm.h>
25 #include <asm/kvm_asm.h>
26 #include <asm/kvm_mmu.h>
27
28 .macro save_caller_saved_regs_vect
29         stp     x0, x1,   [sp, #-16]!
30         stp     x2, x3,   [sp, #-16]!
31         stp     x4, x5,   [sp, #-16]!
32         stp     x6, x7,   [sp, #-16]!
33         stp     x8, x9,   [sp, #-16]!
34         stp     x10, x11, [sp, #-16]!
35         stp     x12, x13, [sp, #-16]!
36         stp     x14, x15, [sp, #-16]!
37         stp     x16, x17, [sp, #-16]!
38 .endm
39
40 .macro restore_caller_saved_regs_vect
41         ldp     x16, x17, [sp], #16
42         ldp     x14, x15, [sp], #16
43         ldp     x12, x13, [sp], #16
44         ldp     x10, x11, [sp], #16
45         ldp     x8, x9,   [sp], #16
46         ldp     x6, x7,   [sp], #16
47         ldp     x4, x5,   [sp], #16
48         ldp     x2, x3,   [sp], #16
49         ldp     x0, x1,   [sp], #16
50 .endm
51
52         .text
53         .pushsection    .hyp.text, "ax"
54
55 .macro do_el2_call
56         /*
57          * Shuffle the parameters before calling the function
58          * pointed to in x0. Assumes parameters in x[1,2,3].
59          */
60         str     lr, [sp, #-16]!
61         mov     lr, x0
62         mov     x0, x1
63         mov     x1, x2
64         mov     x2, x3
65         blr     lr
66         ldr     lr, [sp], #16
67 .endm
68
69 ENTRY(__vhe_hyp_call)
70         do_el2_call
71         /*
72          * We used to rely on having an exception return to get
73          * an implicit isb. In the E2H case, we don't have it anymore.
74          * rather than changing all the leaf functions, just do it here
75          * before returning to the rest of the kernel.
76          */
77         isb
78         ret
79 ENDPROC(__vhe_hyp_call)
80
81 el1_sync:                               // Guest trapped into EL2
82         stp     x0, x1, [sp, #-16]!
83
84         mrs     x0, esr_el2
85         lsr     x0, x0, #ESR_ELx_EC_SHIFT
86         cmp     x0, #ESR_ELx_EC_HVC64
87         ccmp    x0, #ESR_ELx_EC_HVC32, #4, ne
88         b.ne    el1_trap
89
90         mrs     x1, vttbr_el2           // If vttbr is valid, the guest
91         cbnz    x1, el1_hvc_guest       // called HVC
92
93         /* Here, we're pretty sure the host called HVC. */
94         ldp     x0, x1, [sp], #16
95
96         /* Check for a stub HVC call */
97         cmp     x0, #HVC_STUB_HCALL_NR
98         b.hs    1f
99
100         /*
101          * Compute the idmap address of __kvm_handle_stub_hvc and
102          * jump there. Since we use kimage_voffset, do not use the
103          * HYP VA for __kvm_handle_stub_hvc, but the kernel VA instead
104          * (by loading it from the constant pool).
105          *
106          * Preserve x0-x4, which may contain stub parameters.
107          */
108         ldr     x5, =__kvm_handle_stub_hvc
109         ldr_l   x6, kimage_voffset
110
111         /* x5 = __pa(x5) */
112         sub     x5, x5, x6
113         br      x5
114
115 1:
116         /*
117          * Perform the EL2 call
118          */
119         kern_hyp_va     x0
120         do_el2_call
121
122         eret
123
124 el1_hvc_guest:
125         /*
126          * Fastest possible path for ARM_SMCCC_ARCH_WORKAROUND_1.
127          * The workaround has already been applied on the host,
128          * so let's quickly get back to the guest. We don't bother
129          * restoring x1, as it can be clobbered anyway.
130          */
131         ldr     x1, [sp]                                // Guest's x0
132         eor     w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1
133         cbz     w1, wa_epilogue
134
135         /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */
136         eor     w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \
137                           ARM_SMCCC_ARCH_WORKAROUND_2)
138         cbz     w1, wa_epilogue
139
140         eor     w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_2 ^ \
141                           ARM_SMCCC_ARCH_WORKAROUND_3)
142         cbnz    w1, el1_trap
143
144 #ifdef CONFIG_ARM64_SSBD
145 alternative_cb  arm64_enable_wa2_handling
146         b       wa2_end
147 alternative_cb_end
148         get_vcpu_ptr    x2, x0
149         ldr     x0, [x2, #VCPU_WORKAROUND_FLAGS]
150
151         // Sanitize the argument and update the guest flags
152         ldr     x1, [sp, #8]                    // Guest's x1
153         clz     w1, w1                          // Murphy's device:
154         lsr     w1, w1, #5                      // w1 = !!w1 without using
155         eor     w1, w1, #1                      // the flags...
156         bfi     x0, x1, #VCPU_WORKAROUND_2_FLAG_SHIFT, #1
157         str     x0, [x2, #VCPU_WORKAROUND_FLAGS]
158
159         /* Check that we actually need to perform the call */
160         hyp_ldr_this_cpu x0, arm64_ssbd_callback_required, x2
161         cbz     x0, wa2_end
162
163         mov     w0, #ARM_SMCCC_ARCH_WORKAROUND_2
164         smc     #0
165
166         /* Don't leak data from the SMC call */
167         mov     x3, xzr
168 wa2_end:
169         mov     x2, xzr
170         mov     x1, xzr
171 #endif
172
173 wa_epilogue:
174         mov     x0, xzr
175         add     sp, sp, #16
176         eret
177
178 el1_trap:
179         get_vcpu_ptr    x1, x0
180
181         mrs             x0, esr_el2
182         lsr             x0, x0, #ESR_ELx_EC_SHIFT
183         /*
184          * x0: ESR_EC
185          * x1: vcpu pointer
186          */
187
188         /*
189          * We trap the first access to the FP/SIMD to save the host context
190          * and restore the guest context lazily.
191          * If FP/SIMD is not implemented, handle the trap and inject an
192          * undefined instruction exception to the guest.
193          */
194 alternative_if_not ARM64_HAS_NO_FPSIMD
195         cmp     x0, #ESR_ELx_EC_FP_ASIMD
196         b.eq    __fpsimd_guest_restore
197 alternative_else_nop_endif
198
199         mov     x0, #ARM_EXCEPTION_TRAP
200         b       __guest_exit
201
202 el1_irq:
203         stp     x0, x1, [sp, #-16]!
204         get_vcpu_ptr    x1, x0
205         mov     x0, #ARM_EXCEPTION_IRQ
206         b       __guest_exit
207
208 el1_error:
209         stp     x0, x1, [sp, #-16]!
210         get_vcpu_ptr    x1, x0
211         mov     x0, #ARM_EXCEPTION_EL1_SERROR
212         b       __guest_exit
213
214 el2_sync:
215         save_caller_saved_regs_vect
216         stp     x29, x30, [sp, #-16]!
217         bl      kvm_unexpected_el2_exception
218         ldp     x29, x30, [sp], #16
219         restore_caller_saved_regs_vect
220
221         eret
222
223 el2_error:
224         save_caller_saved_regs_vect
225         stp     x29, x30, [sp, #-16]!
226
227         bl      kvm_unexpected_el2_exception
228
229         ldp     x29, x30, [sp], #16
230         restore_caller_saved_regs_vect
231
232         eret
233
234 ENTRY(__hyp_do_panic)
235         mov     lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
236                       PSR_MODE_EL1h)
237         msr     spsr_el2, lr
238         ldr     lr, =panic
239         msr     elr_el2, lr
240         eret
241 ENDPROC(__hyp_do_panic)
242
243 ENTRY(__hyp_panic)
244         get_host_ctxt x0, x1
245         b       hyp_panic
246 ENDPROC(__hyp_panic)
247
248 .macro invalid_vector   label, target = __hyp_panic
249         .align  2
250 \label:
251         b \target
252 ENDPROC(\label)
253 .endm
254
255         /* None of these should ever happen */
256         invalid_vector  el2t_sync_invalid
257         invalid_vector  el2t_irq_invalid
258         invalid_vector  el2t_fiq_invalid
259         invalid_vector  el2t_error_invalid
260         invalid_vector  el2h_irq_invalid
261         invalid_vector  el2h_fiq_invalid
262         invalid_vector  el1_sync_invalid
263         invalid_vector  el1_irq_invalid
264         invalid_vector  el1_fiq_invalid
265
266         .ltorg
267
268         .align 11
269
270 ENTRY(__kvm_hyp_vector)
271         ventry  el2t_sync_invalid               // Synchronous EL2t
272         ventry  el2t_irq_invalid                // IRQ EL2t
273         ventry  el2t_fiq_invalid                // FIQ EL2t
274         ventry  el2t_error_invalid              // Error EL2t
275
276         ventry  el2_sync                        // Synchronous EL2h
277         ventry  el2h_irq_invalid                // IRQ EL2h
278         ventry  el2h_fiq_invalid                // FIQ EL2h
279         ventry  el2_error                       // Error EL2h
280
281         ventry  el1_sync                        // Synchronous 64-bit EL1
282         ventry  el1_irq                         // IRQ 64-bit EL1
283         ventry  el1_fiq_invalid                 // FIQ 64-bit EL1
284         ventry  el1_error                       // Error 64-bit EL1
285
286         ventry  el1_sync                        // Synchronous 32-bit EL1
287         ventry  el1_irq                         // IRQ 32-bit EL1
288         ventry  el1_fiq_invalid                 // FIQ 32-bit EL1
289         ventry  el1_error                       // Error 32-bit EL1
290 ENDPROC(__kvm_hyp_vector)