Linux 3.12.28
[linux/fpc-iii.git] / arch / arm64 / kvm / hyp.S
blob1ac0bbbdddb27976ada4376fe4d28538fee7ccc4
1 /*
2  * Copyright (C) 2012,2013 - 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  */
18 #include <linux/linkage.h>
19 #include <linux/irqchip/arm-gic.h>
21 #include <asm/assembler.h>
22 #include <asm/memory.h>
23 #include <asm/asm-offsets.h>
24 #include <asm/fpsimdmacros.h>
25 #include <asm/kvm.h>
26 #include <asm/kvm_asm.h>
27 #include <asm/kvm_arm.h>
28 #include <asm/kvm_mmu.h>
30 #define CPU_GP_REG_OFFSET(x)    (CPU_GP_REGS + x)
31 #define CPU_XREG_OFFSET(x)      CPU_GP_REG_OFFSET(CPU_USER_PT_REGS + 8*x)
32 #define CPU_SPSR_OFFSET(x)      CPU_GP_REG_OFFSET(CPU_SPSR + 8*x)
33 #define CPU_SYSREG_OFFSET(x)    (CPU_SYSREGS + 8*x)
35         .text
36         .pushsection    .hyp.text, "ax"
37         .align  PAGE_SHIFT
39 __kvm_hyp_code_start:
40         .globl __kvm_hyp_code_start
42 .macro save_common_regs
43         // x2: base address for cpu context
44         // x3: tmp register
46         add     x3, x2, #CPU_XREG_OFFSET(19)
47         stp     x19, x20, [x3]
48         stp     x21, x22, [x3, #16]
49         stp     x23, x24, [x3, #32]
50         stp     x25, x26, [x3, #48]
51         stp     x27, x28, [x3, #64]
52         stp     x29, lr, [x3, #80]
54         mrs     x19, sp_el0
55         mrs     x20, elr_el2            // EL1 PC
56         mrs     x21, spsr_el2           // EL1 pstate
58         stp     x19, x20, [x3, #96]
59         str     x21, [x3, #112]
61         mrs     x22, sp_el1
62         mrs     x23, elr_el1
63         mrs     x24, spsr_el1
65         str     x22, [x2, #CPU_GP_REG_OFFSET(CPU_SP_EL1)]
66         str     x23, [x2, #CPU_GP_REG_OFFSET(CPU_ELR_EL1)]
67         str     x24, [x2, #CPU_SPSR_OFFSET(KVM_SPSR_EL1)]
68 .endm
70 .macro restore_common_regs
71         // x2: base address for cpu context
72         // x3: tmp register
74         ldr     x22, [x2, #CPU_GP_REG_OFFSET(CPU_SP_EL1)]
75         ldr     x23, [x2, #CPU_GP_REG_OFFSET(CPU_ELR_EL1)]
76         ldr     x24, [x2, #CPU_SPSR_OFFSET(KVM_SPSR_EL1)]
78         msr     sp_el1, x22
79         msr     elr_el1, x23
80         msr     spsr_el1, x24
82         add     x3, x2, #CPU_XREG_OFFSET(31)    // SP_EL0
83         ldp     x19, x20, [x3]
84         ldr     x21, [x3, #16]
86         msr     sp_el0, x19
87         msr     elr_el2, x20                            // EL1 PC
88         msr     spsr_el2, x21                           // EL1 pstate
90         add     x3, x2, #CPU_XREG_OFFSET(19)
91         ldp     x19, x20, [x3]
92         ldp     x21, x22, [x3, #16]
93         ldp     x23, x24, [x3, #32]
94         ldp     x25, x26, [x3, #48]
95         ldp     x27, x28, [x3, #64]
96         ldp     x29, lr, [x3, #80]
97 .endm
99 .macro save_host_regs
100         save_common_regs
101 .endm
103 .macro restore_host_regs
104         restore_common_regs
105 .endm
107 .macro save_fpsimd
108         // x2: cpu context address
109         // x3, x4: tmp regs
110         add     x3, x2, #CPU_GP_REG_OFFSET(CPU_FP_REGS)
111         fpsimd_save x3, 4
112 .endm
114 .macro restore_fpsimd
115         // x2: cpu context address
116         // x3, x4: tmp regs
117         add     x3, x2, #CPU_GP_REG_OFFSET(CPU_FP_REGS)
118         fpsimd_restore x3, 4
119 .endm
121 .macro save_guest_regs
122         // x0 is the vcpu address
123         // x1 is the return code, do not corrupt!
124         // x2 is the cpu context
125         // x3 is a tmp register
126         // Guest's x0-x3 are on the stack
128         // Compute base to save registers
129         add     x3, x2, #CPU_XREG_OFFSET(4)
130         stp     x4, x5, [x3]
131         stp     x6, x7, [x3, #16]
132         stp     x8, x9, [x3, #32]
133         stp     x10, x11, [x3, #48]
134         stp     x12, x13, [x3, #64]
135         stp     x14, x15, [x3, #80]
136         stp     x16, x17, [x3, #96]
137         str     x18, [x3, #112]
139         pop     x6, x7                  // x2, x3
140         pop     x4, x5                  // x0, x1
142         add     x3, x2, #CPU_XREG_OFFSET(0)
143         stp     x4, x5, [x3]
144         stp     x6, x7, [x3, #16]
146         save_common_regs
147 .endm
149 .macro restore_guest_regs
150         // x0 is the vcpu address.
151         // x2 is the cpu context
152         // x3 is a tmp register
154         // Prepare x0-x3 for later restore
155         add     x3, x2, #CPU_XREG_OFFSET(0)
156         ldp     x4, x5, [x3]
157         ldp     x6, x7, [x3, #16]
158         push    x4, x5          // Push x0-x3 on the stack
159         push    x6, x7
161         // x4-x18
162         ldp     x4, x5, [x3, #32]
163         ldp     x6, x7, [x3, #48]
164         ldp     x8, x9, [x3, #64]
165         ldp     x10, x11, [x3, #80]
166         ldp     x12, x13, [x3, #96]
167         ldp     x14, x15, [x3, #112]
168         ldp     x16, x17, [x3, #128]
169         ldr     x18, [x3, #144]
171         // x19-x29, lr, sp*, elr*, spsr*
172         restore_common_regs
174         // Last bits of the 64bit state
175         pop     x2, x3
176         pop     x0, x1
178         // Do not touch any register after this!
179 .endm
182  * Macros to perform system register save/restore.
184  * Ordering here is absolutely critical, and must be kept consistent
185  * in {save,restore}_sysregs, {save,restore}_guest_32bit_state,
186  * and in kvm_asm.h.
188  * In other words, don't touch any of these unless you know what
189  * you are doing.
190  */
191 .macro save_sysregs
192         // x2: base address for cpu context
193         // x3: tmp register
195         add     x3, x2, #CPU_SYSREG_OFFSET(MPIDR_EL1)
197         mrs     x4,     vmpidr_el2
198         mrs     x5,     csselr_el1
199         mrs     x6,     sctlr_el1
200         mrs     x7,     actlr_el1
201         mrs     x8,     cpacr_el1
202         mrs     x9,     ttbr0_el1
203         mrs     x10,    ttbr1_el1
204         mrs     x11,    tcr_el1
205         mrs     x12,    esr_el1
206         mrs     x13,    afsr0_el1
207         mrs     x14,    afsr1_el1
208         mrs     x15,    far_el1
209         mrs     x16,    mair_el1
210         mrs     x17,    vbar_el1
211         mrs     x18,    contextidr_el1
212         mrs     x19,    tpidr_el0
213         mrs     x20,    tpidrro_el0
214         mrs     x21,    tpidr_el1
215         mrs     x22,    amair_el1
216         mrs     x23,    cntkctl_el1
217         mrs     x24,    par_el1
219         stp     x4, x5, [x3]
220         stp     x6, x7, [x3, #16]
221         stp     x8, x9, [x3, #32]
222         stp     x10, x11, [x3, #48]
223         stp     x12, x13, [x3, #64]
224         stp     x14, x15, [x3, #80]
225         stp     x16, x17, [x3, #96]
226         stp     x18, x19, [x3, #112]
227         stp     x20, x21, [x3, #128]
228         stp     x22, x23, [x3, #144]
229         str     x24, [x3, #160]
230 .endm
232 .macro restore_sysregs
233         // x2: base address for cpu context
234         // x3: tmp register
236         add     x3, x2, #CPU_SYSREG_OFFSET(MPIDR_EL1)
238         ldp     x4, x5, [x3]
239         ldp     x6, x7, [x3, #16]
240         ldp     x8, x9, [x3, #32]
241         ldp     x10, x11, [x3, #48]
242         ldp     x12, x13, [x3, #64]
243         ldp     x14, x15, [x3, #80]
244         ldp     x16, x17, [x3, #96]
245         ldp     x18, x19, [x3, #112]
246         ldp     x20, x21, [x3, #128]
247         ldp     x22, x23, [x3, #144]
248         ldr     x24, [x3, #160]
250         msr     vmpidr_el2,     x4
251         msr     csselr_el1,     x5
252         msr     sctlr_el1,      x6
253         msr     actlr_el1,      x7
254         msr     cpacr_el1,      x8
255         msr     ttbr0_el1,      x9
256         msr     ttbr1_el1,      x10
257         msr     tcr_el1,        x11
258         msr     esr_el1,        x12
259         msr     afsr0_el1,      x13
260         msr     afsr1_el1,      x14
261         msr     far_el1,        x15
262         msr     mair_el1,       x16
263         msr     vbar_el1,       x17
264         msr     contextidr_el1, x18
265         msr     tpidr_el0,      x19
266         msr     tpidrro_el0,    x20
267         msr     tpidr_el1,      x21
268         msr     amair_el1,      x22
269         msr     cntkctl_el1,    x23
270         msr     par_el1,        x24
271 .endm
273 .macro skip_32bit_state tmp, target
274         // Skip 32bit state if not needed
275         mrs     \tmp, hcr_el2
276         tbnz    \tmp, #HCR_RW_SHIFT, \target
277 .endm
279 .macro skip_tee_state tmp, target
280         // Skip ThumbEE state if not needed
281         mrs     \tmp, id_pfr0_el1
282         tbz     \tmp, #12, \target
283 .endm
285 .macro save_guest_32bit_state
286         skip_32bit_state x3, 1f
288         add     x3, x2, #CPU_SPSR_OFFSET(KVM_SPSR_ABT)
289         mrs     x4, spsr_abt
290         mrs     x5, spsr_und
291         mrs     x6, spsr_irq
292         mrs     x7, spsr_fiq
293         stp     x4, x5, [x3]
294         stp     x6, x7, [x3, #16]
296         add     x3, x2, #CPU_SYSREG_OFFSET(DACR32_EL2)
297         mrs     x4, dacr32_el2
298         mrs     x5, ifsr32_el2
299         mrs     x6, fpexc32_el2
300         mrs     x7, dbgvcr32_el2
301         stp     x4, x5, [x3]
302         stp     x6, x7, [x3, #16]
304         skip_tee_state x8, 1f
306         add     x3, x2, #CPU_SYSREG_OFFSET(TEECR32_EL1)
307         mrs     x4, teecr32_el1
308         mrs     x5, teehbr32_el1
309         stp     x4, x5, [x3]
311 .endm
313 .macro restore_guest_32bit_state
314         skip_32bit_state x3, 1f
316         add     x3, x2, #CPU_SPSR_OFFSET(KVM_SPSR_ABT)
317         ldp     x4, x5, [x3]
318         ldp     x6, x7, [x3, #16]
319         msr     spsr_abt, x4
320         msr     spsr_und, x5
321         msr     spsr_irq, x6
322         msr     spsr_fiq, x7
324         add     x3, x2, #CPU_SYSREG_OFFSET(DACR32_EL2)
325         ldp     x4, x5, [x3]
326         ldp     x6, x7, [x3, #16]
327         msr     dacr32_el2, x4
328         msr     ifsr32_el2, x5
329         msr     fpexc32_el2, x6
330         msr     dbgvcr32_el2, x7
332         skip_tee_state x8, 1f
334         add     x3, x2, #CPU_SYSREG_OFFSET(TEECR32_EL1)
335         ldp     x4, x5, [x3]
336         msr     teecr32_el1, x4
337         msr     teehbr32_el1, x5
339 .endm
341 .macro activate_traps
342         ldr     x2, [x0, #VCPU_IRQ_LINES]
343         ldr     x1, [x0, #VCPU_HCR_EL2]
344         orr     x2, x2, x1
345         msr     hcr_el2, x2
347         ldr     x2, =(CPTR_EL2_TTA)
348         msr     cptr_el2, x2
350         ldr     x2, =(1 << 15)  // Trap CP15 Cr=15
351         msr     hstr_el2, x2
353         mrs     x2, mdcr_el2
354         and     x2, x2, #MDCR_EL2_HPMN_MASK
355         orr     x2, x2, #(MDCR_EL2_TPM | MDCR_EL2_TPMCR)
356         msr     mdcr_el2, x2
357 .endm
359 .macro deactivate_traps
360         mov     x2, #HCR_RW
361         msr     hcr_el2, x2
362         msr     cptr_el2, xzr
363         msr     hstr_el2, xzr
365         mrs     x2, mdcr_el2
366         and     x2, x2, #MDCR_EL2_HPMN_MASK
367         msr     mdcr_el2, x2
368 .endm
370 .macro activate_vm
371         ldr     x1, [x0, #VCPU_KVM]
372         kern_hyp_va     x1
373         ldr     x2, [x1, #KVM_VTTBR]
374         msr     vttbr_el2, x2
375 .endm
377 .macro deactivate_vm
378         msr     vttbr_el2, xzr
379 .endm
382  * Save the VGIC CPU state into memory
383  * x0: Register pointing to VCPU struct
384  * Do not corrupt x1!!!
385  */
386 .macro save_vgic_state
387         /* Get VGIC VCTRL base into x2 */
388         ldr     x2, [x0, #VCPU_KVM]
389         kern_hyp_va     x2
390         ldr     x2, [x2, #KVM_VGIC_VCTRL]
391         kern_hyp_va     x2
392         cbz     x2, 2f          // disabled
394         /* Compute the address of struct vgic_cpu */
395         add     x3, x0, #VCPU_VGIC_CPU
397         /* Save all interesting registers */
398         ldr     w4, [x2, #GICH_HCR]
399         ldr     w5, [x2, #GICH_VMCR]
400         ldr     w6, [x2, #GICH_MISR]
401         ldr     w7, [x2, #GICH_EISR0]
402         ldr     w8, [x2, #GICH_EISR1]
403         ldr     w9, [x2, #GICH_ELRSR0]
404         ldr     w10, [x2, #GICH_ELRSR1]
405         ldr     w11, [x2, #GICH_APR]
407         str     w4, [x3, #VGIC_CPU_HCR]
408         str     w5, [x3, #VGIC_CPU_VMCR]
409         str     w6, [x3, #VGIC_CPU_MISR]
410         str     w7, [x3, #VGIC_CPU_EISR]
411         str     w8, [x3, #(VGIC_CPU_EISR + 4)]
412         str     w9, [x3, #VGIC_CPU_ELRSR]
413         str     w10, [x3, #(VGIC_CPU_ELRSR + 4)]
414         str     w11, [x3, #VGIC_CPU_APR]
416         /* Clear GICH_HCR */
417         str     wzr, [x2, #GICH_HCR]
419         /* Save list registers */
420         add     x2, x2, #GICH_LR0
421         ldr     w4, [x3, #VGIC_CPU_NR_LR]
422         add     x3, x3, #VGIC_CPU_LR
423 1:      ldr     w5, [x2], #4
424         str     w5, [x3], #4
425         sub     w4, w4, #1
426         cbnz    w4, 1b
428 .endm
431  * Restore the VGIC CPU state from memory
432  * x0: Register pointing to VCPU struct
433  */
434 .macro restore_vgic_state
435         /* Get VGIC VCTRL base into x2 */
436         ldr     x2, [x0, #VCPU_KVM]
437         kern_hyp_va     x2
438         ldr     x2, [x2, #KVM_VGIC_VCTRL]
439         kern_hyp_va     x2
440         cbz     x2, 2f          // disabled
442         /* Compute the address of struct vgic_cpu */
443         add     x3, x0, #VCPU_VGIC_CPU
445         /* We only restore a minimal set of registers */
446         ldr     w4, [x3, #VGIC_CPU_HCR]
447         ldr     w5, [x3, #VGIC_CPU_VMCR]
448         ldr     w6, [x3, #VGIC_CPU_APR]
450         str     w4, [x2, #GICH_HCR]
451         str     w5, [x2, #GICH_VMCR]
452         str     w6, [x2, #GICH_APR]
454         /* Restore list registers */
455         add     x2, x2, #GICH_LR0
456         ldr     w4, [x3, #VGIC_CPU_NR_LR]
457         add     x3, x3, #VGIC_CPU_LR
458 1:      ldr     w5, [x3], #4
459         str     w5, [x2], #4
460         sub     w4, w4, #1
461         cbnz    w4, 1b
463 .endm
465 .macro save_timer_state
466         // x0: vcpu pointer
467         ldr     x2, [x0, #VCPU_KVM]
468         kern_hyp_va x2
469         ldr     w3, [x2, #KVM_TIMER_ENABLED]
470         cbz     w3, 1f
472         mrs     x3, cntv_ctl_el0
473         and     x3, x3, #3
474         str     w3, [x0, #VCPU_TIMER_CNTV_CTL]
475         bic     x3, x3, #1              // Clear Enable
476         msr     cntv_ctl_el0, x3
478         isb
480         mrs     x3, cntv_cval_el0
481         str     x3, [x0, #VCPU_TIMER_CNTV_CVAL]
484         // Allow physical timer/counter access for the host
485         mrs     x2, cnthctl_el2
486         orr     x2, x2, #3
487         msr     cnthctl_el2, x2
489         // Clear cntvoff for the host
490         msr     cntvoff_el2, xzr
491 .endm
493 .macro restore_timer_state
494         // x0: vcpu pointer
495         // Disallow physical timer access for the guest
496         // Physical counter access is allowed
497         mrs     x2, cnthctl_el2
498         orr     x2, x2, #1
499         bic     x2, x2, #2
500         msr     cnthctl_el2, x2
502         ldr     x2, [x0, #VCPU_KVM]
503         kern_hyp_va x2
504         ldr     w3, [x2, #KVM_TIMER_ENABLED]
505         cbz     w3, 1f
507         ldr     x3, [x2, #KVM_TIMER_CNTVOFF]
508         msr     cntvoff_el2, x3
509         ldr     x2, [x0, #VCPU_TIMER_CNTV_CVAL]
510         msr     cntv_cval_el0, x2
511         isb
513         ldr     w2, [x0, #VCPU_TIMER_CNTV_CTL]
514         and     x2, x2, #3
515         msr     cntv_ctl_el0, x2
517 .endm
519 __save_sysregs:
520         save_sysregs
521         ret
523 __restore_sysregs:
524         restore_sysregs
525         ret
527 __save_fpsimd:
528         save_fpsimd
529         ret
531 __restore_fpsimd:
532         restore_fpsimd
533         ret
536  * u64 __kvm_vcpu_run(struct kvm_vcpu *vcpu);
538  * This is the world switch. The first half of the function
539  * deals with entering the guest, and anything from __kvm_vcpu_return
540  * to the end of the function deals with reentering the host.
541  * On the enter path, only x0 (vcpu pointer) must be preserved until
542  * the last moment. On the exit path, x0 (vcpu pointer) and x1 (exception
543  * code) must both be preserved until the epilogue.
544  * In both cases, x2 points to the CPU context we're saving/restoring from/to.
545  */
546 ENTRY(__kvm_vcpu_run)
547         kern_hyp_va     x0
548         msr     tpidr_el2, x0   // Save the vcpu register
550         // Host context
551         ldr     x2, [x0, #VCPU_HOST_CONTEXT]
552         kern_hyp_va x2
554         save_host_regs
555         bl __save_fpsimd
556         bl __save_sysregs
558         activate_traps
559         activate_vm
561         restore_vgic_state
562         restore_timer_state
564         // Guest context
565         add     x2, x0, #VCPU_CONTEXT
567         bl __restore_sysregs
568         bl __restore_fpsimd
569         restore_guest_32bit_state
570         restore_guest_regs
572         // That's it, no more messing around.
573         eret
575 __kvm_vcpu_return:
576         // Assume x0 is the vcpu pointer, x1 the return code
577         // Guest's x0-x3 are on the stack
579         // Guest context
580         add     x2, x0, #VCPU_CONTEXT
582         save_guest_regs
583         bl __save_fpsimd
584         bl __save_sysregs
585         save_guest_32bit_state
587         save_timer_state
588         save_vgic_state
590         deactivate_traps
591         deactivate_vm
593         // Host context
594         ldr     x2, [x0, #VCPU_HOST_CONTEXT]
595         kern_hyp_va x2
597         bl __restore_sysregs
598         bl __restore_fpsimd
599         restore_host_regs
601         mov     x0, x1
602         ret
603 END(__kvm_vcpu_run)
605 // void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
606 ENTRY(__kvm_tlb_flush_vmid_ipa)
607         dsb     ishst
609         kern_hyp_va     x0
610         ldr     x2, [x0, #KVM_VTTBR]
611         msr     vttbr_el2, x2
612         isb
614         /*
615          * We could do so much better if we had the VA as well.
616          * Instead, we invalidate Stage-2 for this IPA, and the
617          * whole of Stage-1. Weep...
618          */
619         tlbi    ipas2e1is, x1
620         dsb     sy
621         tlbi    vmalle1is
622         dsb     sy
623         isb
625         msr     vttbr_el2, xzr
626         ret
627 ENDPROC(__kvm_tlb_flush_vmid_ipa)
629 ENTRY(__kvm_flush_vm_context)
630         dsb     ishst
631         tlbi    alle1is
632         ic      ialluis
633         dsb     sy
634         ret
635 ENDPROC(__kvm_flush_vm_context)
637 __kvm_hyp_panic:
638         // Guess the context by looking at VTTBR:
639         // If zero, then we're already a host.
640         // Otherwise restore a minimal host context before panicing.
641         mrs     x0, vttbr_el2
642         cbz     x0, 1f
644         mrs     x0, tpidr_el2
646         deactivate_traps
647         deactivate_vm
649         ldr     x2, [x0, #VCPU_HOST_CONTEXT]
650         kern_hyp_va x2
652         bl __restore_sysregs
654 1:      adr     x0, __hyp_panic_str
655         adr     x1, 2f
656         ldp     x2, x3, [x1]
657         sub     x0, x0, x2
658         add     x0, x0, x3
659         mrs     x1, spsr_el2
660         mrs     x2, elr_el2
661         mrs     x3, esr_el2
662         mrs     x4, far_el2
663         mrs     x5, hpfar_el2
664         mrs     x6, par_el1
665         mrs     x7, tpidr_el2
667         mov     lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
668                       PSR_MODE_EL1h)
669         msr     spsr_el2, lr
670         ldr     lr, =panic
671         msr     elr_el2, lr
672         eret
674         .align  3
675 2:      .quad   HYP_PAGE_OFFSET
676         .quad   PAGE_OFFSET
677 ENDPROC(__kvm_hyp_panic)
679 __hyp_panic_str:
680         .ascii  "HYP panic:\nPS:%08x PC:%p ESR:%p\nFAR:%p HPFAR:%p PAR:%p\nVCPU:%p\n\0"
682         .align  2
684 ENTRY(kvm_call_hyp)
685         hvc     #0
686         ret
687 ENDPROC(kvm_call_hyp)
689 .macro invalid_vector   label, target
690         .align  2
691 \label:
692         b \target
693 ENDPROC(\label)
694 .endm
696         /* None of these should ever happen */
697         invalid_vector  el2t_sync_invalid, __kvm_hyp_panic
698         invalid_vector  el2t_irq_invalid, __kvm_hyp_panic
699         invalid_vector  el2t_fiq_invalid, __kvm_hyp_panic
700         invalid_vector  el2t_error_invalid, __kvm_hyp_panic
701         invalid_vector  el2h_sync_invalid, __kvm_hyp_panic
702         invalid_vector  el2h_irq_invalid, __kvm_hyp_panic
703         invalid_vector  el2h_fiq_invalid, __kvm_hyp_panic
704         invalid_vector  el2h_error_invalid, __kvm_hyp_panic
705         invalid_vector  el1_sync_invalid, __kvm_hyp_panic
706         invalid_vector  el1_irq_invalid, __kvm_hyp_panic
707         invalid_vector  el1_fiq_invalid, __kvm_hyp_panic
708         invalid_vector  el1_error_invalid, __kvm_hyp_panic
710 el1_sync:                                       // Guest trapped into EL2
711         push    x0, x1
712         push    x2, x3
714         mrs     x1, esr_el2
715         lsr     x2, x1, #ESR_EL2_EC_SHIFT
717         cmp     x2, #ESR_EL2_EC_HVC64
718         b.ne    el1_trap
720         mrs     x3, vttbr_el2                   // If vttbr is valid, the 64bit guest
721         cbnz    x3, el1_trap                    // called HVC
723         /* Here, we're pretty sure the host called HVC. */
724         pop     x2, x3
725         pop     x0, x1
727         push    lr, xzr
729         /*
730          * Compute the function address in EL2, and shuffle the parameters.
731          */
732         kern_hyp_va     x0
733         mov     lr, x0
734         mov     x0, x1
735         mov     x1, x2
736         mov     x2, x3
737         blr     lr
739         pop     lr, xzr
740         eret
742 el1_trap:
743         /*
744          * x1: ESR
745          * x2: ESR_EC
746          */
747         cmp     x2, #ESR_EL2_EC_DABT
748         mov     x0, #ESR_EL2_EC_IABT
749         ccmp    x2, x0, #4, ne
750         b.ne    1f              // Not an abort we care about
752         /* This is an abort. Check for permission fault */
753         and     x2, x1, #ESR_EL2_FSC_TYPE
754         cmp     x2, #FSC_PERM
755         b.ne    1f              // Not a permission fault
757         /*
758          * Check for Stage-1 page table walk, which is guaranteed
759          * to give a valid HPFAR_EL2.
760          */
761         tbnz    x1, #7, 1f      // S1PTW is set
763         /* Preserve PAR_EL1 */
764         mrs     x3, par_el1
765         push    x3, xzr
767         /*
768          * Permission fault, HPFAR_EL2 is invalid.
769          * Resolve the IPA the hard way using the guest VA.
770          * Stage-1 translation already validated the memory access rights.
771          * As such, we can use the EL1 translation regime, and don't have
772          * to distinguish between EL0 and EL1 access.
773          */
774         mrs     x2, far_el2
775         at      s1e1r, x2
776         isb
778         /* Read result */
779         mrs     x3, par_el1
780         pop     x0, xzr                 // Restore PAR_EL1 from the stack
781         msr     par_el1, x0
782         tbnz    x3, #0, 3f              // Bail out if we failed the translation
783         ubfx    x3, x3, #12, #36        // Extract IPA
784         lsl     x3, x3, #4              // and present it like HPFAR
785         b       2f
787 1:      mrs     x3, hpfar_el2
788         mrs     x2, far_el2
790 2:      mrs     x0, tpidr_el2
791         str     x1, [x0, #VCPU_ESR_EL2]
792         str     x2, [x0, #VCPU_FAR_EL2]
793         str     x3, [x0, #VCPU_HPFAR_EL2]
795         mov     x1, #ARM_EXCEPTION_TRAP
796         b       __kvm_vcpu_return
798         /*
799          * Translation failed. Just return to the guest and
800          * let it fault again. Another CPU is probably playing
801          * behind our back.
802          */
803 3:      pop     x2, x3
804         pop     x0, x1
806         eret
808 el1_irq:
809         push    x0, x1
810         push    x2, x3
811         mrs     x0, tpidr_el2
812         mov     x1, #ARM_EXCEPTION_IRQ
813         b       __kvm_vcpu_return
815         .ltorg
817         .align 11
819 ENTRY(__kvm_hyp_vector)
820         ventry  el2t_sync_invalid               // Synchronous EL2t
821         ventry  el2t_irq_invalid                // IRQ EL2t
822         ventry  el2t_fiq_invalid                // FIQ EL2t
823         ventry  el2t_error_invalid              // Error EL2t
825         ventry  el2h_sync_invalid               // Synchronous EL2h
826         ventry  el2h_irq_invalid                // IRQ EL2h
827         ventry  el2h_fiq_invalid                // FIQ EL2h
828         ventry  el2h_error_invalid              // Error EL2h
830         ventry  el1_sync                        // Synchronous 64-bit EL1
831         ventry  el1_irq                         // IRQ 64-bit EL1
832         ventry  el1_fiq_invalid                 // FIQ 64-bit EL1
833         ventry  el1_error_invalid               // Error 64-bit EL1
835         ventry  el1_sync                        // Synchronous 32-bit EL1
836         ventry  el1_irq                         // IRQ 32-bit EL1
837         ventry  el1_fiq_invalid                 // FIQ 32-bit EL1
838         ventry  el1_error_invalid               // Error 32-bit EL1
839 ENDPROC(__kvm_hyp_vector)
841 __kvm_hyp_code_end:
842         .globl  __kvm_hyp_code_end
844         .popsection