Merge branches 'acpi-soc', 'acpi-misc', 'acpi-pci' and 'device-properties'
[deliverable/linux.git] / arch / arm / kvm / hyp / hyp-entry.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 <asm/kvm_arm.h>
21 #include <asm/kvm_asm.h>
22
23 .arch_extension virt
24
25 .text
26 .pushsection .hyp.text, "ax"
27
28 .macro load_vcpu reg
29 mrc p15, 4, \reg, c13, c0, 2 @ HTPIDR
30 .endm
31
32 /********************************************************************
33 * Hypervisor exception vector and handlers
34 *
35 *
36 * The KVM/ARM Hypervisor ABI is defined as follows:
37 *
38 * Entry to Hyp mode from the host kernel will happen _only_ when an HVC
39 * instruction is issued since all traps are disabled when running the host
40 * kernel as per the Hyp-mode initialization at boot time.
41 *
42 * HVC instructions cause a trap to the vector page + offset 0x14 (see hyp_hvc
43 * below) when the HVC instruction is called from SVC mode (i.e. a guest or the
44 * host kernel) and they cause a trap to the vector page + offset 0x8 when HVC
45 * instructions are called from within Hyp-mode.
46 *
47 * Hyp-ABI: Calling HYP-mode functions from host (in SVC mode):
48 * Switching to Hyp mode is done through a simple HVC #0 instruction. The
49 * exception vector code will check that the HVC comes from VMID==0.
50 * - r0 contains a pointer to a HYP function
51 * - r1, r2, and r3 contain arguments to the above function.
52 * - The HYP function will be called with its arguments in r0, r1 and r2.
53 * On HYP function return, we return directly to SVC.
54 *
55 * Note that the above is used to execute code in Hyp-mode from a host-kernel
56 * point of view, and is a different concept from performing a world-switch and
57 * executing guest code SVC mode (with a VMID != 0).
58 */
59
60 .align 5
61 __kvm_hyp_vector:
62 .global __kvm_hyp_vector
63
64 @ Hyp-mode exception vector
65 W(b) hyp_reset
66 W(b) hyp_undef
67 W(b) hyp_svc
68 W(b) hyp_pabt
69 W(b) hyp_dabt
70 W(b) hyp_hvc
71 W(b) hyp_irq
72 W(b) hyp_fiq
73
74 .macro invalid_vector label, cause
75 .align
76 \label: mov r0, #\cause
77 b __hyp_panic
78 .endm
79
80 invalid_vector hyp_reset ARM_EXCEPTION_RESET
81 invalid_vector hyp_undef ARM_EXCEPTION_UNDEFINED
82 invalid_vector hyp_svc ARM_EXCEPTION_SOFTWARE
83 invalid_vector hyp_pabt ARM_EXCEPTION_PREF_ABORT
84 invalid_vector hyp_dabt ARM_EXCEPTION_DATA_ABORT
85 invalid_vector hyp_fiq ARM_EXCEPTION_FIQ
86
87 ENTRY(__hyp_do_panic)
88 mrs lr, cpsr
89 bic lr, lr, #MODE_MASK
90 orr lr, lr, #SVC_MODE
91 THUMB( orr lr, lr, #PSR_T_BIT )
92 msr spsr_cxsf, lr
93 ldr lr, =panic
94 msr ELR_hyp, lr
95 ldr lr, =kvm_call_hyp
96 clrex
97 eret
98 ENDPROC(__hyp_do_panic)
99
100 hyp_hvc:
101 /*
102 * Getting here is either because of a trap from a guest,
103 * or from executing HVC from the host kernel, which means
104 * "do something in Hyp mode".
105 */
106 push {r0, r1, r2}
107
108 @ Check syndrome register
109 mrc p15, 4, r1, c5, c2, 0 @ HSR
110 lsr r0, r1, #HSR_EC_SHIFT
111 cmp r0, #HSR_EC_HVC
112 bne guest_trap @ Not HVC instr.
113
114 /*
115 * Let's check if the HVC came from VMID 0 and allow simple
116 * switch to Hyp mode
117 */
118 mrrc p15, 6, r0, r2, c2
119 lsr r2, r2, #16
120 and r2, r2, #0xff
121 cmp r2, #0
122 bne guest_trap @ Guest called HVC
123
124 /*
125 * Getting here means host called HVC, we shift parameters and branch
126 * to Hyp function.
127 */
128 pop {r0, r1, r2}
129
130 /* Check for __hyp_get_vectors */
131 cmp r0, #-1
132 mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR
133 beq 1f
134
135 push {lr}
136
137 mov lr, r0
138 mov r0, r1
139 mov r1, r2
140 mov r2, r3
141
142 THUMB( orr lr, #1)
143 blx lr @ Call the HYP function
144
145 pop {lr}
146 1: eret
147
148 guest_trap:
149 load_vcpu r0 @ Load VCPU pointer to r0
150
151 #ifdef CONFIG_VFPv3
152 @ Check for a VFP access
153 lsr r1, r1, #HSR_EC_SHIFT
154 cmp r1, #HSR_EC_CP_0_13
155 beq __vfp_guest_restore
156 #endif
157
158 mov r1, #ARM_EXCEPTION_HVC
159 b __guest_exit
160
161 hyp_irq:
162 push {r0, r1, r2}
163 mov r1, #ARM_EXCEPTION_IRQ
164 load_vcpu r0 @ Load VCPU pointer to r0
165 b __guest_exit
166
167 .ltorg
168
169 .popsection
This page took 0.035355 seconds and 5 git commands to generate.