2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
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.
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.
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.
19 #include <linux/linkage.h>
20 #include <linux/const.h>
21 #include <asm/unified.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"
33 .globl __kvm_hyp_code_start
35 /********************************************************************
38 * void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
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.
46 * As v7 does not support flushing per IPA, just nuke the whole TLB
47 * instead, ignoring the ipa value.
49 ENTRY(__kvm_tlb_flush_vmid_ipa)
53 add r0, r0, #KVM_VTTBR
55 mcrr p15, 6, r2, r3, c2 @ Write VTTBR
57 mcr p15, 0, r0, c8, c3, 0 @ TLBIALLIS (rt ignored)
62 mcrr p15, 6, r2, r3, c2 @ Back to VMID #0
63 isb @ Not necessary if followed by eret
67 ENDPROC(__kvm_tlb_flush_vmid_ipa)
69 /********************************************************************
70 * Flush TLBs and instruction caches of all CPUs inside the inner-shareable
71 * domain, for all VMIDs
73 * void __kvm_flush_vm_context(void);
75 ENTRY(__kvm_flush_vm_context)
76 mov r0, #0 @ rn parameter for c15 flushes is SBZ
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
83 isb @ Not necessary if followed by eret
86 ENDPROC(__kvm_flush_vm_context)
89 /********************************************************************
90 * Hypervisor world-switch code
93 * int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
96 @ Save the vcpu pointer
97 mcr p15, 4, vcpu, c13, c0, 2 @ HTPIDR
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
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.
111 @ Set FPEXC_EN so the guest doesn't trap floating point instructions
112 VFPFMRX r2, FPEXC @ VMRS
114 orr r2, r2, #FPEXC_EN
115 VFPFMXR FPEXC, r2 @ VMSR
119 configure_hyp_role vmentry
121 @ Trap coprocessor CRx accesses
123 set_hcptr vmentry, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
126 @ Write configured ID register into MIDR alias
127 ldr r1, [vcpu, #VCPU_MIDR]
128 mcr p15, 4, r1, c0, c0, 0
130 @ Write guest view of MPIDR into VMPIDR
131 ldr r1, [vcpu, #CP15_OFFSET(c0_MPIDR)]
132 mcr p15, 4, r1, c0, c0, 5
134 @ Set up guest memory translation
135 ldr r1, [vcpu, #VCPU_KVM]
136 add r1, r1, #KVM_VTTBR
138 mcrr p15, 6, r2, r3, c2 @ Write VTTBR
140 @ We're all done, just restore the GPRs and go to the guest
142 clrex @ Clear exclusive monitor
148 * guest r0, r1, r2 saved on the stack
157 mcrr p15, 6, r2, r3, c2 @ Write VTTBR
159 @ Don't trap coprocessor accesses for host kernel
162 set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11)), after_vfp_restore
165 @ Switch VFP/NEON hardware state to the host's
166 add r7, vcpu, #VCPU_VFP_GUEST
168 add r7, vcpu, #VCPU_VFP_HOST
173 @ Restore FPEXC_EN which we clobbered on entry
181 configure_hyp_role vmexit
183 @ Let host read hardware MIDR
184 mrc p15, 0, r2, c0, c0, 0
185 mcr p15, 4, r2, c0, c0, 0
187 @ Back to hardware MPIDR
188 mrc p15, 0, r2, c0, c0, 5
189 mcr p15, 4, r2, c0, c0, 5
191 @ Store guest CP15 state and restore host state
192 read_cp15_state store_to_vcpu = 1
193 write_cp15_state read_from_vcpu = 0
199 clrex @ Clear exclusive monitor
200 mov r0, r1 @ Return the return code
201 mov r1, #0 @ Clear upper bits in return value
202 bx lr @ return to IOCTL
204 /********************************************************************
205 * Call function in Hyp mode
208 * u64 kvm_call_hyp(void *hypfn, ...);
210 * This is not really a variadic function in the classic C-way and care must
211 * be taken when calling this to ensure parameters are passed in registers
212 * only, since the stack will change between the caller and the callee.
214 * Call the function with the first argument containing a pointer to the
215 * function you wish to call in Hyp mode, and subsequent arguments will be
216 * passed as r0, r1, and r2 (a maximum of 3 arguments in addition to the
217 * function pointer can be passed). The function being called must be mapped
218 * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c). Return values are
219 * passed in r0 and r1.
221 * A function pointer with a value of 0xffffffff has a special meaning,
222 * and is used to implement __hyp_get_vectors in the same way as in
223 * arch/arm/kernel/hyp_stub.S.
225 * The calling convention follows the standard AAPCS:
226 * r0 - r3: caller save
234 /********************************************************************
235 * Hypervisor exception vector and handlers
238 * The KVM/ARM Hypervisor ABI is defined as follows:
240 * Entry to Hyp mode from the host kernel will happen _only_ when an HVC
241 * instruction is issued since all traps are disabled when running the host
242 * kernel as per the Hyp-mode initialization at boot time.
244 * HVC instructions cause a trap to the vector page + offset 0x14 (see hyp_hvc
245 * below) when the HVC instruction is called from SVC mode (i.e. a guest or the
246 * host kernel) and they cause a trap to the vector page + offset 0x8 when HVC
247 * instructions are called from within Hyp-mode.
249 * Hyp-ABI: Calling HYP-mode functions from host (in SVC mode):
250 * Switching to Hyp mode is done through a simple HVC #0 instruction. The
251 * exception vector code will check that the HVC comes from VMID==0 and if
252 * so will push the necessary state (SPSR, lr_usr) on the Hyp stack.
253 * - r0 contains a pointer to a HYP function
254 * - r1, r2, and r3 contain arguments to the above function.
255 * - The HYP function will be called with its arguments in r0, r1 and r2.
256 * On HYP function return, we return directly to SVC.
258 * Note that the above is used to execute code in Hyp-mode from a host-kernel
259 * point of view, and is a different concept from performing a world-switch and
260 * executing guest code SVC mode (with a VMID != 0).
263 /* Handle undef, svc, pabt, or dabt by crashing with a user notice */
264 .macro bad_exception exception_code, panic_str
266 mrrc p15, 6, r0, r1, c2 @ Read VTTBR
271 load_vcpu @ Load VCPU pointer
272 .if \exception_code == ARM_EXCEPTION_DATA_ABORT
273 mrc p15, 4, r2, c5, c2, 0 @ HSR
274 mrc p15, 4, r1, c6, c0, 0 @ HDFAR
275 str r2, [vcpu, #VCPU_HSR]
276 str r1, [vcpu, #VCPU_HxFAR]
278 .if \exception_code == ARM_EXCEPTION_PREF_ABORT
279 mrc p15, 4, r2, c5, c2, 0 @ HSR
280 mrc p15, 4, r1, c6, c0, 2 @ HIFAR
281 str r2, [vcpu, #VCPU_HSR]
282 str r1, [vcpu, #VCPU_HxFAR]
284 mov r1, #\exception_code
287 @ We were in the host already. Let's craft a panic-ing return to SVC.
289 bic r2, r2, #MODE_MASK
290 orr r2, r2, #SVC_MODE
291 THUMB( orr r2, r2, #PSR_T_BIT )
297 clrex @ Clear exclusive monitor
305 .globl __kvm_hyp_vector
307 @ Hyp-mode exception vector
323 bad_exception ARM_EXCEPTION_UNDEFINED, und_die_str
327 bad_exception ARM_EXCEPTION_HVC, svc_die_str
331 bad_exception ARM_EXCEPTION_PREF_ABORT, pabt_die_str
335 bad_exception ARM_EXCEPTION_DATA_ABORT, dabt_die_str
340 * Getting here is either becuase of a trap from a guest or from calling
341 * HVC from the host kernel, which means "switch to Hyp mode".
345 @ Check syndrome register
346 mrc p15, 4, r1, c5, c2, 0 @ HSR
347 lsr r0, r1, #HSR_EC_SHIFT
349 cmp r0, #HSR_EC_CP_0_13
350 beq switch_to_guest_vfp
353 bne guest_trap @ Not HVC instr.
356 * Let's check if the HVC came from VMID 0 and allow simple
359 mrrc p15, 6, r0, r2, c2
363 bne guest_trap @ Guest called HVC
368 /* Check for __hyp_get_vectors */
370 mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR
383 blx lr @ Call the HYP function
391 load_vcpu @ Load VCPU pointer to r0
392 str r1, [vcpu, #VCPU_HSR]
394 @ Check if we need the fault information
395 lsr r1, r1, #HSR_EC_SHIFT
397 mrceq p15, 4, r2, c6, c0, 2 @ HIFAR
401 mrc p15, 4, r2, c6, c0, 0 @ HDFAR
403 2: str r2, [vcpu, #VCPU_HxFAR]
406 * B3.13.5 Reporting exceptions taken to the Non-secure PL2 mode:
408 * Abort on the stage 2 translation for a memory access from a
409 * Non-secure PL1 or PL0 mode:
411 * For any Access flag fault or Translation fault, and also for any
412 * Permission fault on the stage 2 translation of a memory access
413 * made as part of a translation table walk for a stage 1 translation,
414 * the HPFAR holds the IPA that caused the fault. Otherwise, the HPFAR
418 /* Check for permission fault, and S1PTW */
419 mrc p15, 4, r1, c5, c2, 0 @ HSR
420 and r0, r1, #HSR_FSC_TYPE
422 tsteq r1, #(1 << 7) @ S1PTW
423 mrcne p15, 4, r2, c6, c0, 4 @ HPFAR
427 mrrc p15, 0, r0, r1, c7 @ PAR
430 /* Resolve IPA using the xFAR */
431 mcr p15, 0, r2, c7, c8, 0 @ ATS1CPR
433 mrrc p15, 0, r0, r1, c7 @ PAR
435 bne 4f @ Failed translation
436 ubfx r2, r0, #12, #20
438 orr r2, r2, r1, lsl #24
442 mcrr p15, 0, r0, r1, c7 @ PAR
444 3: load_vcpu @ Load VCPU pointer to r0
445 str r2, [r0, #VCPU_HPFAR]
447 1: mov r1, #ARM_EXCEPTION_HVC
450 4: pop {r0, r1} @ Failed translation, return to guest
451 mcrr p15, 0, r0, r1, c7 @ PAR
457 * If VFPv3 support is not available, then we will not switch the VFP
458 * registers; however cp10 and cp11 accesses will still trap and fallback
459 * to the regular coprocessor emulation code, which currently will
460 * inject an undefined exception to the guest.
464 load_vcpu @ Load VCPU pointer to r0
467 @ NEON/VFP used. Turn on VFP access.
468 set_hcptr vmtrap, (HCPTR_TCP(10) | HCPTR_TCP(11))
470 @ Switch VFP/NEON hardware state to the guest's
471 add r7, r0, #VCPU_VFP_HOST
474 add r7, r0, #VCPU_VFP_GUEST
486 mov r1, #ARM_EXCEPTION_IRQ
487 load_vcpu @ Load VCPU pointer to r0
497 .globl __kvm_hyp_code_end
502 .ascii "unexpected undefined exception in Hyp mode at: %#08x\n"
504 .ascii "unexpected prefetch abort in Hyp mode at: %#08x\n"
506 .ascii "unexpected data abort in Hyp mode at: %#08x\n"
508 .ascii "unexpected HVC/SVC trap in Hyp mode at: %#08x\n"