1
2
3
4
5
6
7#ifndef __ARM_KVM_ASM_H__
8#define __ARM_KVM_ASM_H__
9
10#include <asm/hyp_image.h>
11#include <asm/insn.h>
12#include <asm/virt.h>
13
14#define ARM_EXIT_WITH_SERROR_BIT 31
15#define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_SERROR_BIT))
16#define ARM_EXCEPTION_IS_TRAP(x) (ARM_EXCEPTION_CODE((x)) == ARM_EXCEPTION_TRAP)
17#define ARM_SERROR_PENDING(x) !!((x) & (1U << ARM_EXIT_WITH_SERROR_BIT))
18
19#define ARM_EXCEPTION_IRQ 0
20#define ARM_EXCEPTION_EL1_SERROR 1
21#define ARM_EXCEPTION_TRAP 2
22#define ARM_EXCEPTION_IL 3
23
24#define ARM_EXCEPTION_HYP_GONE HVC_STUB_ERR
25
26#define kvm_arm_exception_type \
27 {ARM_EXCEPTION_IRQ, "IRQ" }, \
28 {ARM_EXCEPTION_EL1_SERROR, "SERROR" }, \
29 {ARM_EXCEPTION_TRAP, "TRAP" }, \
30 {ARM_EXCEPTION_HYP_GONE, "HYP_GONE" }
31
32
33
34
35
36#define KVM_VECTOR_PREAMBLE (2 * AARCH64_INSN_SIZE)
37
38#define KVM_HOST_SMCCC_ID(id) \
39 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
40 ARM_SMCCC_SMC_64, \
41 ARM_SMCCC_OWNER_VENDOR_HYP, \
42 (id))
43
44#define KVM_HOST_SMCCC_FUNC(name) KVM_HOST_SMCCC_ID(__KVM_HOST_SMCCC_FUNC_##name)
45
46#define __KVM_HOST_SMCCC_FUNC___kvm_hyp_init 0
47#define __KVM_HOST_SMCCC_FUNC___kvm_vcpu_run 1
48#define __KVM_HOST_SMCCC_FUNC___kvm_flush_vm_context 2
49#define __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa 3
50#define __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid 4
51#define __KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context 5
52#define __KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff 6
53#define __KVM_HOST_SMCCC_FUNC___kvm_enable_ssbs 7
54#define __KVM_HOST_SMCCC_FUNC___vgic_v3_get_gic_config 8
55#define __KVM_HOST_SMCCC_FUNC___vgic_v3_read_vmcr 9
56#define __KVM_HOST_SMCCC_FUNC___vgic_v3_write_vmcr 10
57#define __KVM_HOST_SMCCC_FUNC___vgic_v3_init_lrs 11
58#define __KVM_HOST_SMCCC_FUNC___kvm_get_mdcr_el2 12
59#define __KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs 13
60#define __KVM_HOST_SMCCC_FUNC___vgic_v3_restore_aprs 14
61#define __KVM_HOST_SMCCC_FUNC___pkvm_init 15
62#define __KVM_HOST_SMCCC_FUNC___pkvm_create_mappings 16
63#define __KVM_HOST_SMCCC_FUNC___pkvm_create_private_mapping 17
64#define __KVM_HOST_SMCCC_FUNC___pkvm_cpu_set_vector 18
65#define __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize 19
66#define __KVM_HOST_SMCCC_FUNC___pkvm_mark_hyp 20
67#define __KVM_HOST_SMCCC_FUNC___kvm_adjust_pc 21
68
69#ifndef __ASSEMBLY__
70
71#include <linux/mm.h>
72
73#define DECLARE_KVM_VHE_SYM(sym) extern char sym[]
74#define DECLARE_KVM_NVHE_SYM(sym) extern char kvm_nvhe_sym(sym)[]
75
76
77
78
79
80#define DECLARE_KVM_HYP_SYM(sym) \
81 DECLARE_KVM_VHE_SYM(sym); \
82 DECLARE_KVM_NVHE_SYM(sym)
83
84#define DECLARE_KVM_VHE_PER_CPU(type, sym) \
85 DECLARE_PER_CPU(type, sym)
86#define DECLARE_KVM_NVHE_PER_CPU(type, sym) \
87 DECLARE_PER_CPU(type, kvm_nvhe_sym(sym))
88
89#define DECLARE_KVM_HYP_PER_CPU(type, sym) \
90 DECLARE_KVM_VHE_PER_CPU(type, sym); \
91 DECLARE_KVM_NVHE_PER_CPU(type, sym)
92
93
94
95
96
97#define this_cpu_ptr_nvhe_sym(sym) per_cpu_ptr_nvhe_sym(sym, smp_processor_id())
98#define per_cpu_ptr_nvhe_sym(sym, cpu) \
99 ({ \
100 unsigned long base, off; \
101 base = kvm_arm_hyp_percpu_base[cpu]; \
102 off = (unsigned long)&CHOOSE_NVHE_SYM(sym) - \
103 (unsigned long)&CHOOSE_NVHE_SYM(__per_cpu_start); \
104 base ? (typeof(CHOOSE_NVHE_SYM(sym))*)(base + off) : NULL; \
105 })
106
107#if defined(__KVM_NVHE_HYPERVISOR__)
108
109#define CHOOSE_NVHE_SYM(sym) sym
110#define CHOOSE_HYP_SYM(sym) CHOOSE_NVHE_SYM(sym)
111
112
113extern void *__nvhe_undefined_symbol;
114#define CHOOSE_VHE_SYM(sym) __nvhe_undefined_symbol
115#define this_cpu_ptr_hyp_sym(sym) (&__nvhe_undefined_symbol)
116#define per_cpu_ptr_hyp_sym(sym, cpu) (&__nvhe_undefined_symbol)
117
118#elif defined(__KVM_VHE_HYPERVISOR__)
119
120#define CHOOSE_VHE_SYM(sym) sym
121#define CHOOSE_HYP_SYM(sym) CHOOSE_VHE_SYM(sym)
122
123
124extern void *__vhe_undefined_symbol;
125#define CHOOSE_NVHE_SYM(sym) __vhe_undefined_symbol
126#define this_cpu_ptr_hyp_sym(sym) (&__vhe_undefined_symbol)
127#define per_cpu_ptr_hyp_sym(sym, cpu) (&__vhe_undefined_symbol)
128
129#else
130
131
132
133
134
135
136
137
138
139
140
141
142#define CHOOSE_HYP_SYM(sym) (is_kernel_in_hyp_mode() \
143 ? CHOOSE_VHE_SYM(sym) \
144 : CHOOSE_NVHE_SYM(sym))
145
146#define this_cpu_ptr_hyp_sym(sym) (is_kernel_in_hyp_mode() \
147 ? this_cpu_ptr(&sym) \
148 : this_cpu_ptr_nvhe_sym(sym))
149
150#define per_cpu_ptr_hyp_sym(sym, cpu) (is_kernel_in_hyp_mode() \
151 ? per_cpu_ptr(&sym, cpu) \
152 : per_cpu_ptr_nvhe_sym(sym, cpu))
153
154#define CHOOSE_VHE_SYM(sym) sym
155#define CHOOSE_NVHE_SYM(sym) kvm_nvhe_sym(sym)
156
157#endif
158
159struct kvm_nvhe_init_params {
160 unsigned long mair_el2;
161 unsigned long tcr_el2;
162 unsigned long tpidr_el2;
163 unsigned long stack_hyp_va;
164 phys_addr_t pgd_pa;
165 unsigned long hcr_el2;
166 unsigned long vttbr;
167 unsigned long vtcr;
168};
169
170
171#define kvm_ksym_ref(ptr) \
172 ({ \
173 void *val = (ptr); \
174 if (!is_kernel_in_hyp_mode()) \
175 val = lm_alias((ptr)); \
176 val; \
177 })
178#define kvm_ksym_ref_nvhe(sym) kvm_ksym_ref(kvm_nvhe_sym(sym))
179
180struct kvm;
181struct kvm_vcpu;
182struct kvm_s2_mmu;
183
184DECLARE_KVM_NVHE_SYM(__kvm_hyp_init);
185DECLARE_KVM_HYP_SYM(__kvm_hyp_vector);
186#define __kvm_hyp_init CHOOSE_NVHE_SYM(__kvm_hyp_init)
187#define __kvm_hyp_vector CHOOSE_HYP_SYM(__kvm_hyp_vector)
188
189extern unsigned long kvm_arm_hyp_percpu_base[NR_CPUS];
190DECLARE_KVM_NVHE_SYM(__per_cpu_start);
191DECLARE_KVM_NVHE_SYM(__per_cpu_end);
192
193DECLARE_KVM_HYP_SYM(__bp_harden_hyp_vecs);
194#define __bp_harden_hyp_vecs CHOOSE_HYP_SYM(__bp_harden_hyp_vecs)
195
196extern void __kvm_flush_vm_context(void);
197extern void __kvm_flush_cpu_context(struct kvm_s2_mmu *mmu);
198extern void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, phys_addr_t ipa,
199 int level);
200extern void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu);
201
202extern void __kvm_timer_set_cntvoff(u64 cntvoff);
203
204extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
205
206extern void __kvm_adjust_pc(struct kvm_vcpu *vcpu);
207
208extern u64 __vgic_v3_get_gic_config(void);
209extern u64 __vgic_v3_read_vmcr(void);
210extern void __vgic_v3_write_vmcr(u32 vmcr);
211extern void __vgic_v3_init_lrs(void);
212
213extern u32 __kvm_get_mdcr_el2(void);
214
215#define __KVM_EXTABLE(from, to) \
216 " .pushsection __kvm_ex_table, \"a\"\n" \
217 " .align 3\n" \
218 " .long (" #from " - .), (" #to " - .)\n" \
219 " .popsection\n"
220
221
222#define __kvm_at(at_op, addr) \
223( { \
224 int __kvm_at_err = 0; \
225 u64 spsr, elr; \
226 asm volatile( \
227 " mrs %1, spsr_el2\n" \
228 " mrs %2, elr_el2\n" \
229 "1: at "at_op", %3\n" \
230 " isb\n" \
231 " b 9f\n" \
232 "2: msr spsr_el2, %1\n" \
233 " msr elr_el2, %2\n" \
234 " mov %w0, %4\n" \
235 "9:\n" \
236 __KVM_EXTABLE(1b, 2b) \
237 : "+r" (__kvm_at_err), "=&r" (spsr), "=&r" (elr) \
238 : "r" (addr), "i" (-EFAULT)); \
239 __kvm_at_err; \
240} )
241
242
243#else
244
245.macro get_host_ctxt reg, tmp
246 adr_this_cpu \reg, kvm_host_data, \tmp
247 add \reg, \reg, #HOST_DATA_CONTEXT
248.endm
249
250.macro get_vcpu_ptr vcpu, ctxt
251 get_host_ctxt \ctxt, \vcpu
252 ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU]
253.endm
254
255.macro get_loaded_vcpu vcpu, ctxt
256 adr_this_cpu \ctxt, kvm_hyp_ctxt, \vcpu
257 ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU]
258.endm
259
260.macro set_loaded_vcpu vcpu, ctxt, tmp
261 adr_this_cpu \ctxt, kvm_hyp_ctxt, \tmp
262 str \vcpu, [\ctxt, #HOST_CONTEXT_VCPU]
263.endm
264
265
266
267
268
269
270
271
272
273.macro _kvm_extable, from, to
274 .pushsection __kvm_ex_table, "a"
275 .align 3
276 .long (\from - .), (\to - .)
277 .popsection
278.endm
279
280#define CPU_XREG_OFFSET(x) (CPU_USER_PT_REGS + 8*x)
281#define CPU_LR_OFFSET CPU_XREG_OFFSET(30)
282#define CPU_SP_EL0_OFFSET (CPU_LR_OFFSET + 8)
283
284
285
286
287
288.macro save_callee_saved_regs ctxt
289 str x18, [\ctxt, #CPU_XREG_OFFSET(18)]
290 stp x19, x20, [\ctxt, #CPU_XREG_OFFSET(19)]
291 stp x21, x22, [\ctxt, #CPU_XREG_OFFSET(21)]
292 stp x23, x24, [\ctxt, #CPU_XREG_OFFSET(23)]
293 stp x25, x26, [\ctxt, #CPU_XREG_OFFSET(25)]
294 stp x27, x28, [\ctxt, #CPU_XREG_OFFSET(27)]
295 stp x29, lr, [\ctxt, #CPU_XREG_OFFSET(29)]
296.endm
297
298.macro restore_callee_saved_regs ctxt
299
300 ldr x18, [\ctxt, #CPU_XREG_OFFSET(18)]
301 ldp x19, x20, [\ctxt, #CPU_XREG_OFFSET(19)]
302 ldp x21, x22, [\ctxt, #CPU_XREG_OFFSET(21)]
303 ldp x23, x24, [\ctxt, #CPU_XREG_OFFSET(23)]
304 ldp x25, x26, [\ctxt, #CPU_XREG_OFFSET(25)]
305 ldp x27, x28, [\ctxt, #CPU_XREG_OFFSET(27)]
306 ldp x29, lr, [\ctxt, #CPU_XREG_OFFSET(29)]
307.endm
308
309.macro save_sp_el0 ctxt, tmp
310 mrs \tmp, sp_el0
311 str \tmp, [\ctxt, #CPU_SP_EL0_OFFSET]
312.endm
313
314.macro restore_sp_el0 ctxt, tmp
315 ldr \tmp, [\ctxt, #CPU_SP_EL0_OFFSET]
316 msr sp_el0, \tmp
317.endm
318
319#endif
320
321#endif
322