GNU Linux-libre 4.14.266-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         cbnz    w1, el1_trap
139
140 #ifdef CONFIG_ARM64_SSBD
141 alternative_cb  arm64_enable_wa2_handling
142         b       wa2_end
143 alternative_cb_end
144         get_vcpu_ptr    x2, x0
145         ldr     x0, [x2, #VCPU_WORKAROUND_FLAGS]
146
147         // Sanitize the argument and update the guest flags
148         ldr     x1, [sp, #8]                    // Guest's x1
149         clz     w1, w1                          // Murphy's device:
150         lsr     w1, w1, #5                      // w1 = !!w1 without using
151         eor     w1, w1, #1                      // the flags...
152         bfi     x0, x1, #VCPU_WORKAROUND_2_FLAG_SHIFT, #1
153         str     x0, [x2, #VCPU_WORKAROUND_FLAGS]
154
155         /* Check that we actually need to perform the call */
156         hyp_ldr_this_cpu x0, arm64_ssbd_callback_required, x2
157         cbz     x0, wa2_end
158
159         mov     w0, #ARM_SMCCC_ARCH_WORKAROUND_2
160         smc     #0
161
162         /* Don't leak data from the SMC call */
163         mov     x3, xzr
164 wa2_end:
165         mov     x2, xzr
166         mov     x1, xzr
167 #endif
168
169 wa_epilogue:
170         mov     x0, xzr
171         add     sp, sp, #16
172         eret
173
174 el1_trap:
175         get_vcpu_ptr    x1, x0
176
177         mrs             x0, esr_el2
178         lsr             x0, x0, #ESR_ELx_EC_SHIFT
179         /*
180          * x0: ESR_EC
181          * x1: vcpu pointer
182          */
183
184         /*
185          * We trap the first access to the FP/SIMD to save the host context
186          * and restore the guest context lazily.
187          * If FP/SIMD is not implemented, handle the trap and inject an
188          * undefined instruction exception to the guest.
189          */
190 alternative_if_not ARM64_HAS_NO_FPSIMD
191         cmp     x0, #ESR_ELx_EC_FP_ASIMD
192         b.eq    __fpsimd_guest_restore
193 alternative_else_nop_endif
194
195         mov     x0, #ARM_EXCEPTION_TRAP
196         b       __guest_exit
197
198 el1_irq:
199         stp     x0, x1, [sp, #-16]!
200         get_vcpu_ptr    x1, x0
201         mov     x0, #ARM_EXCEPTION_IRQ
202         b       __guest_exit
203
204 el1_error:
205         stp     x0, x1, [sp, #-16]!
206         get_vcpu_ptr    x1, x0
207         mov     x0, #ARM_EXCEPTION_EL1_SERROR
208         b       __guest_exit
209
210 el2_sync:
211         save_caller_saved_regs_vect
212         stp     x29, x30, [sp, #-16]!
213         bl      kvm_unexpected_el2_exception
214         ldp     x29, x30, [sp], #16
215         restore_caller_saved_regs_vect
216
217         eret
218
219 el2_error:
220         save_caller_saved_regs_vect
221         stp     x29, x30, [sp, #-16]!
222
223         bl      kvm_unexpected_el2_exception
224
225         ldp     x29, x30, [sp], #16
226         restore_caller_saved_regs_vect
227
228         eret
229
230 ENTRY(__hyp_do_panic)
231         mov     lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
232                       PSR_MODE_EL1h)
233         msr     spsr_el2, lr
234         ldr     lr, =panic
235         msr     elr_el2, lr
236         eret
237 ENDPROC(__hyp_do_panic)
238
239 ENTRY(__hyp_panic)
240         get_host_ctxt x0, x1
241         b       hyp_panic
242 ENDPROC(__hyp_panic)
243
244 .macro invalid_vector   label, target = __hyp_panic
245         .align  2
246 \label:
247         b \target
248 ENDPROC(\label)
249 .endm
250
251         /* None of these should ever happen */
252         invalid_vector  el2t_sync_invalid
253         invalid_vector  el2t_irq_invalid
254         invalid_vector  el2t_fiq_invalid
255         invalid_vector  el2t_error_invalid
256         invalid_vector  el2h_irq_invalid
257         invalid_vector  el2h_fiq_invalid
258         invalid_vector  el1_sync_invalid
259         invalid_vector  el1_irq_invalid
260         invalid_vector  el1_fiq_invalid
261
262         .ltorg
263
264         .align 11
265
266 ENTRY(__kvm_hyp_vector)
267         ventry  el2t_sync_invalid               // Synchronous EL2t
268         ventry  el2t_irq_invalid                // IRQ EL2t
269         ventry  el2t_fiq_invalid                // FIQ EL2t
270         ventry  el2t_error_invalid              // Error EL2t
271
272         ventry  el2_sync                        // Synchronous EL2h
273         ventry  el2h_irq_invalid                // IRQ EL2h
274         ventry  el2h_fiq_invalid                // FIQ EL2h
275         ventry  el2_error                       // Error EL2h
276
277         ventry  el1_sync                        // Synchronous 64-bit EL1
278         ventry  el1_irq                         // IRQ 64-bit EL1
279         ventry  el1_fiq_invalid                 // FIQ 64-bit EL1
280         ventry  el1_error                       // Error 64-bit EL1
281
282         ventry  el1_sync                        // Synchronous 32-bit EL1
283         ventry  el1_irq                         // IRQ 32-bit EL1
284         ventry  el1_fiq_invalid                 // FIQ 32-bit EL1
285         ventry  el1_error                       // Error 32-bit EL1
286 ENDPROC(__kvm_hyp_vector)