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