Commit | Line | Data |
---|---|---|
2b28162c MZ |
1 | /* |
2 | * Copyright (C) 2015 - 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 | */ | |
17 | ||
18 | #include <linux/linkage.h> | |
19 | ||
20 | #include <asm/alternative.h> | |
21 | #include <asm/assembler.h> | |
2b28162c MZ |
22 | #include <asm/cpufeature.h> |
23 | #include <asm/kvm_arm.h> | |
24 | #include <asm/kvm_asm.h> | |
25 | #include <asm/kvm_mmu.h> | |
26 | ||
27 | .text | |
28 | .pushsection .hyp.text, "ax" | |
29 | ||
30 | .macro save_x0_to_x3 | |
31 | stp x0, x1, [sp, #-16]! | |
32 | stp x2, x3, [sp, #-16]! | |
33 | .endm | |
34 | ||
35 | .macro restore_x0_to_x3 | |
36 | ldp x2, x3, [sp], #16 | |
37 | ldp x0, x1, [sp], #16 | |
38 | .endm | |
39 | ||
b81125c7 MZ |
40 | .macro do_el2_call |
41 | /* | |
42 | * Shuffle the parameters before calling the function | |
43 | * pointed to in x0. Assumes parameters in x[1,2,3]. | |
44 | */ | |
b81125c7 MZ |
45 | mov lr, x0 |
46 | mov x0, x1 | |
47 | mov x1, x2 | |
48 | mov x2, x3 | |
49 | blr lr | |
b81125c7 MZ |
50 | .endm |
51 | ||
52 | ENTRY(__vhe_hyp_call) | |
00a44cda | 53 | str lr, [sp, #-16]! |
b81125c7 | 54 | do_el2_call |
00a44cda | 55 | ldr lr, [sp], #16 |
b81125c7 MZ |
56 | /* |
57 | * We used to rely on having an exception return to get | |
58 | * an implicit isb. In the E2H case, we don't have it anymore. | |
59 | * rather than changing all the leaf functions, just do it here | |
60 | * before returning to the rest of the kernel. | |
61 | */ | |
62 | isb | |
63 | ret | |
64 | ENDPROC(__vhe_hyp_call) | |
3421e9d8 MZ |
65 | |
66 | /* | |
67 | * Compute the idmap address of __kvm_hyp_reset based on the idmap | |
68 | * start passed as a parameter, and jump there. | |
69 | * | |
70 | * x0: HYP phys_idmap_start | |
71 | */ | |
72 | ENTRY(__kvm_hyp_teardown) | |
73 | mov x4, x0 | |
74 | adr_l x3, __kvm_hyp_reset | |
75 | ||
76 | /* insert __kvm_hyp_reset()s offset into phys_idmap_start */ | |
77 | bfi x4, x3, #0, #PAGE_SHIFT | |
78 | br x4 | |
79 | ENDPROC(__kvm_hyp_teardown) | |
b81125c7 | 80 | |
2b28162c MZ |
81 | el1_sync: // Guest trapped into EL2 |
82 | save_x0_to_x3 | |
83 | ||
5f05a72a | 84 | alternative_if_not ARM64_HAS_VIRT_HOST_EXTN |
2b28162c | 85 | mrs x1, esr_el2 |
5f05a72a MZ |
86 | alternative_else |
87 | mrs x1, esr_el1 | |
88 | alternative_endif | |
2b28162c MZ |
89 | lsr x2, x1, #ESR_ELx_EC_SHIFT |
90 | ||
91 | cmp x2, #ESR_ELx_EC_HVC64 | |
92 | b.ne el1_trap | |
93 | ||
94 | mrs x3, vttbr_el2 // If vttbr is valid, the 64bit guest | |
95 | cbnz x3, el1_trap // called HVC | |
96 | ||
97 | /* Here, we're pretty sure the host called HVC. */ | |
98 | restore_x0_to_x3 | |
99 | ||
ad72e59f GL |
100 | cmp x0, #HVC_GET_VECTORS |
101 | b.ne 1f | |
2b28162c MZ |
102 | mrs x0, vbar_el2 |
103 | b 2f | |
104 | ||
b81125c7 | 105 | 1: |
2b28162c | 106 | /* |
b81125c7 | 107 | * Perform the EL2 call |
2b28162c MZ |
108 | */ |
109 | kern_hyp_va x0 | |
b81125c7 | 110 | do_el2_call |
2b28162c | 111 | |
2b28162c MZ |
112 | 2: eret |
113 | ||
114 | el1_trap: | |
115 | /* | |
116 | * x1: ESR | |
117 | * x2: ESR_EC | |
118 | */ | |
119 | ||
120 | /* Guest accessed VFP/SIMD registers, save host, restore Guest */ | |
121 | cmp x2, #ESR_ELx_EC_FP_ASIMD | |
122 | b.eq __fpsimd_guest_restore | |
123 | ||
5f05a72a | 124 | mrs x0, tpidr_el2 |
2b28162c MZ |
125 | mov x1, #ARM_EXCEPTION_TRAP |
126 | b __guest_exit | |
127 | ||
2b28162c MZ |
128 | el1_irq: |
129 | save_x0_to_x3 | |
130 | mrs x0, tpidr_el2 | |
131 | mov x1, #ARM_EXCEPTION_IRQ | |
132 | b __guest_exit | |
133 | ||
53fd5b64 MZ |
134 | ENTRY(__hyp_do_panic) |
135 | mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ | |
136 | PSR_MODE_EL1h) | |
137 | msr spsr_el2, lr | |
138 | ldr lr, =panic | |
139 | msr elr_el2, lr | |
140 | eret | |
141 | ENDPROC(__hyp_do_panic) | |
142 | ||
143 | .macro invalid_vector label, target = __hyp_panic | |
2b28162c MZ |
144 | .align 2 |
145 | \label: | |
146 | b \target | |
147 | ENDPROC(\label) | |
148 | .endm | |
149 | ||
150 | /* None of these should ever happen */ | |
151 | invalid_vector el2t_sync_invalid | |
152 | invalid_vector el2t_irq_invalid | |
153 | invalid_vector el2t_fiq_invalid | |
154 | invalid_vector el2t_error_invalid | |
155 | invalid_vector el2h_sync_invalid | |
156 | invalid_vector el2h_irq_invalid | |
157 | invalid_vector el2h_fiq_invalid | |
158 | invalid_vector el2h_error_invalid | |
159 | invalid_vector el1_sync_invalid | |
160 | invalid_vector el1_irq_invalid | |
161 | invalid_vector el1_fiq_invalid | |
162 | invalid_vector el1_error_invalid | |
163 | ||
164 | .ltorg | |
165 | ||
166 | .align 11 | |
167 | ||
044ac37d | 168 | ENTRY(__kvm_hyp_vector) |
2b28162c MZ |
169 | ventry el2t_sync_invalid // Synchronous EL2t |
170 | ventry el2t_irq_invalid // IRQ EL2t | |
171 | ventry el2t_fiq_invalid // FIQ EL2t | |
172 | ventry el2t_error_invalid // Error EL2t | |
173 | ||
174 | ventry el2h_sync_invalid // Synchronous EL2h | |
175 | ventry el2h_irq_invalid // IRQ EL2h | |
176 | ventry el2h_fiq_invalid // FIQ EL2h | |
177 | ventry el2h_error_invalid // Error EL2h | |
178 | ||
179 | ventry el1_sync // Synchronous 64-bit EL1 | |
180 | ventry el1_irq // IRQ 64-bit EL1 | |
181 | ventry el1_fiq_invalid // FIQ 64-bit EL1 | |
182 | ventry el1_error_invalid // Error 64-bit EL1 | |
183 | ||
184 | ventry el1_sync // Synchronous 32-bit EL1 | |
185 | ventry el1_irq // IRQ 32-bit EL1 | |
186 | ventry el1_fiq_invalid // FIQ 32-bit EL1 | |
187 | ventry el1_error_invalid // Error 32-bit EL1 | |
044ac37d | 188 | ENDPROC(__kvm_hyp_vector) |