ARM: KVM: move include of asm/idmap.h to kvm_mmu.h
[deliverable/linux.git] / arch / arm / kvm / interrupts.S
CommitLineData
749cf76c
CD
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.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, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
342cd0ab
CD
18
19#include <linux/linkage.h>
20#include <linux/const.h>
21#include <asm/unified.h>
22#include <asm/page.h>
f7ed45be 23#include <asm/ptrace.h>
749cf76c
CD
24#include <asm/asm-offsets.h>
25#include <asm/kvm_asm.h>
342cd0ab 26#include <asm/kvm_arm.h>
f7ed45be
CD
27#include <asm/vfpmacros.h>
28#include "interrupts_head.S"
342cd0ab
CD
29
30 .text
31
32__kvm_hyp_code_start:
33 .globl __kvm_hyp_code_start
34
35/********************************************************************
36 * Flush per-VMID TLBs
f7ed45be
CD
37 *
38 * void __kvm_tlb_flush_vmid(struct kvm *kvm);
39 *
40 * We rely on the hardware to broadcast the TLB invalidation to all CPUs
41 * inside the inner-shareable domain (which is the case for all v7
42 * implementations). If we come across a non-IS SMP implementation, we'll
43 * have to use an IPI based mechanism. Until then, we stick to the simple
44 * hardware assisted version.
342cd0ab 45 */
d5d8184d 46ENTRY(__kvm_tlb_flush_vmid)
f7ed45be
CD
47 push {r2, r3}
48
49 add r0, r0, #KVM_VTTBR
50 ldrd r2, r3, [r0]
51 mcrr p15, 6, r2, r3, c2 @ Write VTTBR
52 isb
53 mcr p15, 0, r0, c8, c3, 0 @ TLBIALLIS (rt ignored)
54 dsb
55 isb
56 mov r2, #0
57 mov r3, #0
58 mcrr p15, 6, r2, r3, c2 @ Back to VMID #0
59 isb @ Not necessary if followed by eret
60
61 pop {r2, r3}
d5d8184d
CD
62 bx lr
63ENDPROC(__kvm_tlb_flush_vmid)
64
65/********************************************************************
f7ed45be
CD
66 * Flush TLBs and instruction caches of all CPUs inside the inner-shareable
67 * domain, for all VMIDs
68 *
69 * void __kvm_flush_vm_context(void);
d5d8184d 70 */
342cd0ab 71ENTRY(__kvm_flush_vm_context)
f7ed45be
CD
72 mov r0, #0 @ rn parameter for c15 flushes is SBZ
73
74 /* Invalidate NS Non-Hyp TLB Inner Shareable (TLBIALLNSNHIS) */
75 mcr p15, 4, r0, c8, c3, 4
76 /* Invalidate instruction caches Inner Shareable (ICIALLUIS) */
77 mcr p15, 0, r0, c7, c1, 0
78 dsb
79 isb @ Not necessary if followed by eret
80
342cd0ab
CD
81 bx lr
82ENDPROC(__kvm_flush_vm_context)
83
f7ed45be 84
342cd0ab
CD
85/********************************************************************
86 * Hypervisor world-switch code
f7ed45be
CD
87 *
88 *
89 * int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
342cd0ab
CD
90 */
91ENTRY(__kvm_vcpu_run)
f7ed45be
CD
92 @ Save the vcpu pointer
93 mcr p15, 4, vcpu, c13, c0, 2 @ HTPIDR
94
95 save_host_regs
96
1a89dd91 97 restore_vgic_state
53e72406 98 restore_timer_state
1a89dd91 99
f7ed45be
CD
100 @ Store hardware CP15 state and load guest state
101 read_cp15_state store_to_vcpu = 0
102 write_cp15_state read_from_vcpu = 1
103
104 @ If the host kernel has not been configured with VFPv3 support,
105 @ then it is safer if we deny guests from using it as well.
106#ifdef CONFIG_VFPv3
107 @ Set FPEXC_EN so the guest doesn't trap floating point instructions
108 VFPFMRX r2, FPEXC @ VMRS
109 push {r2}
110 orr r2, r2, #FPEXC_EN
111 VFPFMXR FPEXC, r2 @ VMSR
112#endif
113
114 @ Configure Hyp-role
115 configure_hyp_role vmentry
116
117 @ Trap coprocessor CRx accesses
118 set_hstr vmentry
119 set_hcptr vmentry, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
120 set_hdcr vmentry
121
122 @ Write configured ID register into MIDR alias
123 ldr r1, [vcpu, #VCPU_MIDR]
124 mcr p15, 4, r1, c0, c0, 0
125
126 @ Write guest view of MPIDR into VMPIDR
127 ldr r1, [vcpu, #CP15_OFFSET(c0_MPIDR)]
128 mcr p15, 4, r1, c0, c0, 5
129
130 @ Set up guest memory translation
131 ldr r1, [vcpu, #VCPU_KVM]
132 add r1, r1, #KVM_VTTBR
133 ldrd r2, r3, [r1]
134 mcrr p15, 6, r2, r3, c2 @ Write VTTBR
135
136 @ We're all done, just restore the GPRs and go to the guest
137 restore_guest_regs
138 clrex @ Clear exclusive monitor
139 eret
140
141__kvm_vcpu_return:
142 /*
143 * return convention:
144 * guest r0, r1, r2 saved on the stack
145 * r0: vcpu pointer
146 * r1: exception code
147 */
148 save_guest_regs
149
150 @ Set VMID == 0
151 mov r2, #0
152 mov r3, #0
153 mcrr p15, 6, r2, r3, c2 @ Write VTTBR
154
155 @ Don't trap coprocessor accesses for host kernel
156 set_hstr vmexit
157 set_hdcr vmexit
158 set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
159
160#ifdef CONFIG_VFPv3
161 @ Save floating point registers we if let guest use them.
162 tst r2, #(HCPTR_TCP(10) | HCPTR_TCP(11))
163 bne after_vfp_restore
164
165 @ Switch VFP/NEON hardware state to the host's
166 add r7, vcpu, #VCPU_VFP_GUEST
167 store_vfp_state r7
168 add r7, vcpu, #VCPU_VFP_HOST
169 ldr r7, [r7]
170 restore_vfp_state r7
171
172after_vfp_restore:
173 @ Restore FPEXC_EN which we clobbered on entry
174 pop {r2}
175 VFPFMXR FPEXC, r2
176#endif
177
178 @ Reset Hyp-role
179 configure_hyp_role vmexit
180
181 @ Let host read hardware MIDR
182 mrc p15, 0, r2, c0, c0, 0
183 mcr p15, 4, r2, c0, c0, 0
184
185 @ Back to hardware MPIDR
186 mrc p15, 0, r2, c0, c0, 5
187 mcr p15, 4, r2, c0, c0, 5
188
189 @ Store guest CP15 state and restore host state
190 read_cp15_state store_to_vcpu = 1
191 write_cp15_state read_from_vcpu = 0
192
53e72406 193 save_timer_state
1a89dd91
MZ
194 save_vgic_state
195
f7ed45be
CD
196 restore_host_regs
197 clrex @ Clear exclusive monitor
198 mov r0, r1 @ Return the return code
199 mov r1, #0 @ Clear upper bits in return value
200 bx lr @ return to IOCTL
342cd0ab
CD
201
202/********************************************************************
203 * Call function in Hyp mode
204 *
205 *
206 * u64 kvm_call_hyp(void *hypfn, ...);
207 *
208 * This is not really a variadic function in the classic C-way and care must
209 * be taken when calling this to ensure parameters are passed in registers
210 * only, since the stack will change between the caller and the callee.
211 *
212 * Call the function with the first argument containing a pointer to the
213 * function you wish to call in Hyp mode, and subsequent arguments will be
214 * passed as r0, r1, and r2 (a maximum of 3 arguments in addition to the
215 * function pointer can be passed). The function being called must be mapped
216 * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c). Return values are
217 * passed in r0 and r1.
218 *
219 * The calling convention follows the standard AAPCS:
220 * r0 - r3: caller save
221 * r12: caller save
222 * rest: callee save
223 */
224ENTRY(kvm_call_hyp)
225 hvc #0
226 bx lr
227
228/********************************************************************
229 * Hypervisor exception vector and handlers
f7ed45be
CD
230 *
231 *
232 * The KVM/ARM Hypervisor ABI is defined as follows:
233 *
234 * Entry to Hyp mode from the host kernel will happen _only_ when an HVC
235 * instruction is issued since all traps are disabled when running the host
236 * kernel as per the Hyp-mode initialization at boot time.
237 *
0b5e3bac 238 * HVC instructions cause a trap to the vector page + offset 0x14 (see hyp_hvc
f7ed45be 239 * below) when the HVC instruction is called from SVC mode (i.e. a guest or the
0b5e3bac 240 * host kernel) and they cause a trap to the vector page + offset 0x8 when HVC
f7ed45be
CD
241 * instructions are called from within Hyp-mode.
242 *
243 * Hyp-ABI: Calling HYP-mode functions from host (in SVC mode):
244 * Switching to Hyp mode is done through a simple HVC #0 instruction. The
245 * exception vector code will check that the HVC comes from VMID==0 and if
246 * so will push the necessary state (SPSR, lr_usr) on the Hyp stack.
247 * - r0 contains a pointer to a HYP function
248 * - r1, r2, and r3 contain arguments to the above function.
249 * - The HYP function will be called with its arguments in r0, r1 and r2.
250 * On HYP function return, we return directly to SVC.
251 *
252 * Note that the above is used to execute code in Hyp-mode from a host-kernel
253 * point of view, and is a different concept from performing a world-switch and
254 * executing guest code SVC mode (with a VMID != 0).
342cd0ab
CD
255 */
256
f7ed45be
CD
257/* Handle undef, svc, pabt, or dabt by crashing with a user notice */
258.macro bad_exception exception_code, panic_str
259 push {r0-r2}
260 mrrc p15, 6, r0, r1, c2 @ Read VTTBR
261 lsr r1, r1, #16
262 ands r1, r1, #0xff
263 beq 99f
264
265 load_vcpu @ Load VCPU pointer
266 .if \exception_code == ARM_EXCEPTION_DATA_ABORT
267 mrc p15, 4, r2, c5, c2, 0 @ HSR
268 mrc p15, 4, r1, c6, c0, 0 @ HDFAR
269 str r2, [vcpu, #VCPU_HSR]
270 str r1, [vcpu, #VCPU_HxFAR]
271 .endif
272 .if \exception_code == ARM_EXCEPTION_PREF_ABORT
273 mrc p15, 4, r2, c5, c2, 0 @ HSR
274 mrc p15, 4, r1, c6, c0, 2 @ HIFAR
275 str r2, [vcpu, #VCPU_HSR]
276 str r1, [vcpu, #VCPU_HxFAR]
277 .endif
278 mov r1, #\exception_code
279 b __kvm_vcpu_return
280
281 @ We were in the host already. Let's craft a panic-ing return to SVC.
28299: mrs r2, cpsr
283 bic r2, r2, #MODE_MASK
284 orr r2, r2, #SVC_MODE
285THUMB( orr r2, r2, #PSR_T_BIT )
286 msr spsr_cxsf, r2
287 mrs r1, ELR_hyp
288 ldr r2, =BSYM(panic)
289 msr ELR_hyp, r2
290 ldr r0, =\panic_str
291 eret
292.endm
293
294 .text
295
342cd0ab
CD
296 .align 5
297__kvm_hyp_vector:
298 .globl __kvm_hyp_vector
f7ed45be
CD
299
300 @ Hyp-mode exception vector
301 W(b) hyp_reset
302 W(b) hyp_undef
303 W(b) hyp_svc
304 W(b) hyp_pabt
305 W(b) hyp_dabt
306 W(b) hyp_hvc
307 W(b) hyp_irq
308 W(b) hyp_fiq
309
310 .align
311hyp_reset:
312 b hyp_reset
313
314 .align
315hyp_undef:
316 bad_exception ARM_EXCEPTION_UNDEFINED, und_die_str
317
318 .align
319hyp_svc:
320 bad_exception ARM_EXCEPTION_HVC, svc_die_str
321
322 .align
323hyp_pabt:
324 bad_exception ARM_EXCEPTION_PREF_ABORT, pabt_die_str
325
326 .align
327hyp_dabt:
328 bad_exception ARM_EXCEPTION_DATA_ABORT, dabt_die_str
329
330 .align
331hyp_hvc:
332 /*
333 * Getting here is either becuase of a trap from a guest or from calling
334 * HVC from the host kernel, which means "switch to Hyp mode".
335 */
336 push {r0, r1, r2}
337
338 @ Check syndrome register
339 mrc p15, 4, r1, c5, c2, 0 @ HSR
340 lsr r0, r1, #HSR_EC_SHIFT
341#ifdef CONFIG_VFPv3
342 cmp r0, #HSR_EC_CP_0_13
343 beq switch_to_guest_vfp
344#endif
345 cmp r0, #HSR_EC_HVC
346 bne guest_trap @ Not HVC instr.
347
348 /*
349 * Let's check if the HVC came from VMID 0 and allow simple
350 * switch to Hyp mode
351 */
352 mrrc p15, 6, r0, r2, c2
353 lsr r2, r2, #16
354 and r2, r2, #0xff
355 cmp r2, #0
356 bne guest_trap @ Guest called HVC
357
358host_switch_to_hyp:
359 pop {r0, r1, r2}
360
361 push {lr}
362 mrs lr, SPSR
363 push {lr}
364
365 mov lr, r0
366 mov r0, r1
367 mov r1, r2
368 mov r2, r3
369
370THUMB( orr lr, #1)
371 blx lr @ Call the HYP function
372
373 pop {lr}
374 msr SPSR_csxf, lr
375 pop {lr}
376 eret
377
378guest_trap:
379 load_vcpu @ Load VCPU pointer to r0
380 str r1, [vcpu, #VCPU_HSR]
381
382 @ Check if we need the fault information
383 lsr r1, r1, #HSR_EC_SHIFT
384 cmp r1, #HSR_EC_IABT
385 mrceq p15, 4, r2, c6, c0, 2 @ HIFAR
386 beq 2f
387 cmp r1, #HSR_EC_DABT
388 bne 1f
389 mrc p15, 4, r2, c6, c0, 0 @ HDFAR
390
3912: str r2, [vcpu, #VCPU_HxFAR]
392
393 /*
394 * B3.13.5 Reporting exceptions taken to the Non-secure PL2 mode:
395 *
396 * Abort on the stage 2 translation for a memory access from a
397 * Non-secure PL1 or PL0 mode:
398 *
399 * For any Access flag fault or Translation fault, and also for any
400 * Permission fault on the stage 2 translation of a memory access
401 * made as part of a translation table walk for a stage 1 translation,
402 * the HPFAR holds the IPA that caused the fault. Otherwise, the HPFAR
403 * is UNKNOWN.
404 */
405
406 /* Check for permission fault, and S1PTW */
407 mrc p15, 4, r1, c5, c2, 0 @ HSR
408 and r0, r1, #HSR_FSC_TYPE
409 cmp r0, #FSC_PERM
410 tsteq r1, #(1 << 7) @ S1PTW
411 mrcne p15, 4, r2, c6, c0, 4 @ HPFAR
412 bne 3f
413
414 /* Resolve IPA using the xFAR */
415 mcr p15, 0, r2, c7, c8, 0 @ ATS1CPR
416 isb
417 mrrc p15, 0, r0, r1, c7 @ PAR
418 tst r0, #1
419 bne 4f @ Failed translation
420 ubfx r2, r0, #12, #20
421 lsl r2, r2, #4
422 orr r2, r2, r1, lsl #24
423
4243: load_vcpu @ Load VCPU pointer to r0
425 str r2, [r0, #VCPU_HPFAR]
426
4271: mov r1, #ARM_EXCEPTION_HVC
428 b __kvm_vcpu_return
429
4304: pop {r0, r1, r2} @ Failed translation, return to guest
431 eret
432
433/*
434 * If VFPv3 support is not available, then we will not switch the VFP
435 * registers; however cp10 and cp11 accesses will still trap and fallback
436 * to the regular coprocessor emulation code, which currently will
437 * inject an undefined exception to the guest.
438 */
439#ifdef CONFIG_VFPv3
440switch_to_guest_vfp:
441 load_vcpu @ Load VCPU pointer to r0
442 push {r3-r7}
443
444 @ NEON/VFP used. Turn on VFP access.
445 set_hcptr vmexit, (HCPTR_TCP(10) | HCPTR_TCP(11))
446
447 @ Switch VFP/NEON hardware state to the guest's
448 add r7, r0, #VCPU_VFP_HOST
449 ldr r7, [r7]
450 store_vfp_state r7
451 add r7, r0, #VCPU_VFP_GUEST
452 restore_vfp_state r7
453
454 pop {r3-r7}
455 pop {r0-r2}
456 eret
457#endif
458
459 .align
460hyp_irq:
461 push {r0, r1, r2}
462 mov r1, #ARM_EXCEPTION_IRQ
463 load_vcpu @ Load VCPU pointer to r0
464 b __kvm_vcpu_return
465
466 .align
467hyp_fiq:
468 b hyp_fiq
469
470 .ltorg
342cd0ab
CD
471
472__kvm_hyp_code_end:
473 .globl __kvm_hyp_code_end
f7ed45be
CD
474
475 .section ".rodata"
476
477und_die_str:
478 .ascii "unexpected undefined exception in Hyp mode at: %#08x"
479pabt_die_str:
480 .ascii "unexpected prefetch abort in Hyp mode at: %#08x"
481dabt_die_str:
482 .ascii "unexpected data abort in Hyp mode at: %#08x"
483svc_die_str:
484 .ascii "unexpected HVC/SVC trap in Hyp mode at: %#08x"
This page took 0.050009 seconds and 5 git commands to generate.