1
2
3
4
5
6 #include <linux/init.h>
7 #include <linux/irqchip/arm-gic-v3.h>
8 #include <linux/linkage.h>
9 #include <asm/assembler.h>
10 #include <asm/virt.h>
11
12 #ifndef ZIMAGE
13
14
15
16
17
18
19
20 .data
21 .align 2
22 ENTRY(__boot_cpu_mode)
23 .long 0
24 .text
25
26
27
28
29 .macro store_primary_cpu_mode reg1, reg2, reg3
30 mrs \reg1, cpsr
31 and \reg1, \reg1, #MODE_MASK
32 adr \reg2, .L__boot_cpu_mode_offset
33 ldr \reg3, [\reg2]
34 str \reg1, [\reg2, \reg3]
35 .endm
36
37
38
39
40
41
42
43 .macro compare_cpu_mode_with_primary mode, reg1, reg2, reg3
44 adr \reg2, .L__boot_cpu_mode_offset
45 ldr \reg3, [\reg2]
46 ldr \reg1, [\reg2, \reg3]
47 cmp \mode, \reg1 @ matches primary CPU boot mode?
48 orrne \reg1, \reg1, #BOOT_CPU_MODE_MISMATCH
49 strne \reg1, [\reg2, \reg3] @ record what happened and give up
50 .endm
51
52 #else
53
54 .macro store_primary_cpu_mode reg1:req, reg2:req, reg3:req
55 .endm
56
57
58
59
60
61 .macro compare_cpu_mode_with_primary mode, reg1, reg2, reg3
62 cmp \mode, \mode
63 .endm
64
65 #endif
66
67
68
69
70
71
72
73
74 @ Call this from the primary CPU
75 ENTRY(__hyp_stub_install)
76 store_primary_cpu_mode r4, r5, r6
77 ENDPROC(__hyp_stub_install)
78
79 @ fall through...
80
81 @ Secondary CPUs should call here
82 ENTRY(__hyp_stub_install_secondary)
83 mrs r4, cpsr
84 and r4, r4, #MODE_MASK
85
86
87
88
89
90 compare_cpu_mode_with_primary r4, r5, r6, r7
91 retne lr
92
93
94
95
96
97
98
99
100
101
102 cmp r4, #HYP_MODE
103 retne lr @ give up if the CPU is not in HYP mode
104
105
106
107
108
109
110
111
112
113
114
115 @ Now install the hypervisor stub:
116 W(adr) r7, __hyp_stub_vectors
117 mcr p15, 4, r7, c12, c0, 0 @ set hypervisor vector base (HVBAR)
118
119 @ Disable all traps, so we don't get any nasty surprise
120 mov r7, #0
121 mcr p15, 4, r7, c1, c1, 0 @ HCR
122 mcr p15, 4, r7, c1, c1, 2 @ HCPTR
123 mcr p15, 4, r7, c1, c1, 3 @ HSTR
124
125 THUMB( orr r7, #(1 << 30) ) @ HSCTLR.TE
126 ARM_BE8(orr r7, r7, #(1 << 25)) @ HSCTLR.EE
127 mcr p15, 4, r7, c1, c0, 0 @ HSCTLR
128
129 mrc p15, 4, r7, c1, c1, 1 @ HDCR
130 and r7, #0x1f @ Preserve HPMN
131 mcr p15, 4, r7, c1, c1, 1 @ HDCR
132
133 @ Make sure NS-SVC is initialised appropriately
134 mrc p15, 0, r7, c1, c0, 0 @ SCTLR
135 orr r7, #(1 << 5) @ CP15 barriers enabled
136 bic r7, #(3 << 7) @ Clear SED/ITD for v8 (RES0 for v7)
137 bic r7, #(3 << 19) @ WXN and UWXN disabled
138 mcr p15, 0, r7, c1, c0, 0 @ SCTLR
139
140 mrc p15, 0, r7, c0, c0, 0 @ MIDR
141 mcr p15, 4, r7, c0, c0, 0 @ VPIDR
142
143 mrc p15, 0, r7, c0, c0, 5 @ MPIDR
144 mcr p15, 4, r7, c0, c0, 5 @ VMPIDR
145
146 #if !defined(ZIMAGE) && defined(CONFIG_ARM_ARCH_TIMER)
147 @ make CNTP_* and CNTPCT accessible from PL1
148 mrc p15, 0, r7, c0, c1, 1 @ ID_PFR1
149 ubfx r7, r7, #16, #4
150 teq r7, #0
151 beq 1f
152 mrc p15, 4, r7, c14, c1, 0 @ CNTHCTL
153 orr r7, r7, #3 @ PL1PCEN | PL1PCTEN
154 mcr p15, 4, r7, c14, c1, 0 @ CNTHCTL
155 mov r7, #0
156 mcrr p15, 4, r7, r7, c14 @ CNTVOFF
157
158 @ Disable virtual timer in case it was counting
159 mrc p15, 0, r7, c14, c3, 1 @ CNTV_CTL
160 bic r7, #1 @ Clear ENABLE
161 mcr p15, 0, r7, c14, c3, 1 @ CNTV_CTL
162 1:
163 #endif
164
165 #ifdef CONFIG_ARM_GIC_V3
166 @ Check whether GICv3 system registers are available
167 mrc p15, 0, r7, c0, c1, 1 @ ID_PFR1
168 ubfx r7, r7, #28, #4
169 teq r7, #0
170 beq 2f
171
172 @ Enable system register accesses
173 mrc p15, 4, r7, c12, c9, 5 @ ICC_HSRE
174 orr r7, r7, #(ICC_SRE_EL2_ENABLE | ICC_SRE_EL2_SRE)
175 mcr p15, 4, r7, c12, c9, 5 @ ICC_HSRE
176 isb
177
178 @ SRE bit could be forced to 0 by firmware.
179 @ Check whether it sticks before accessing any other sysreg
180 mrc p15, 4, r7, c12, c9, 5 @ ICC_HSRE
181 tst r7, #ICC_SRE_EL2_SRE
182 beq 2f
183 mov r7, #0
184 mcr p15, 4, r7, c12, c11, 0 @ ICH_HCR
185 2:
186 #endif
187
188 bx lr @ The boot CPU mode is left in r4.
189 ENDPROC(__hyp_stub_install_secondary)
190
191 __hyp_stub_do_trap:
192 teq r0, #HVC_SET_VECTORS
193 bne 1f
194 mcr p15, 4, r1, c12, c0, 0 @ set HVBAR
195 b __hyp_stub_exit
196
197 1: teq r0, #HVC_SOFT_RESTART
198 bne 1f
199 bx r1
200
201 1: teq r0, #HVC_RESET_VECTORS
202 beq __hyp_stub_exit
203
204 ldr r0, =HVC_STUB_ERR
205 __ERET
206
207 __hyp_stub_exit:
208 mov r0, #0
209 __ERET
210 ENDPROC(__hyp_stub_do_trap)
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234 ENTRY(__hyp_set_vectors)
235 mov r1, r0
236 mov r0, #HVC_SET_VECTORS
237 __HVC(0)
238 ret lr
239 ENDPROC(__hyp_set_vectors)
240
241 ENTRY(__hyp_soft_restart)
242 mov r1, r0
243 mov r0, #HVC_SOFT_RESTART
244 __HVC(0)
245 ret lr
246 ENDPROC(__hyp_soft_restart)
247
248 ENTRY(__hyp_reset_vectors)
249 mov r0, #HVC_RESET_VECTORS
250 __HVC(0)
251 ret lr
252 ENDPROC(__hyp_reset_vectors)
253
254 #ifndef ZIMAGE
255 .align 2
256 .L__boot_cpu_mode_offset:
257 .long __boot_cpu_mode - .
258 #endif
259
260 .align 5
261 ENTRY(__hyp_stub_vectors)
262 __hyp_stub_reset: W(b) .
263 __hyp_stub_und: W(b) .
264 __hyp_stub_svc: W(b) .
265 __hyp_stub_pabort: W(b) .
266 __hyp_stub_dabort: W(b) .
267 __hyp_stub_trap: W(b) __hyp_stub_do_trap
268 __hyp_stub_irq: W(b) .
269 __hyp_stub_fiq: W(b) .
270 ENDPROC(__hyp_stub_vectors)
271