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