]> Git Repo - linux.git/blob - arch/arm/include/asm/kvm_emulate.h
kvm: lapic: Introduce APICv update helper function
[linux.git] / arch / arm / include / asm / kvm_emulate.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2012 - Virtual Open Systems and Columbia University
4  * Author: Christoffer Dall <[email protected]>
5  */
6
7 #ifndef __ARM_KVM_EMULATE_H__
8 #define __ARM_KVM_EMULATE_H__
9
10 #include <linux/kvm_host.h>
11 #include <asm/kvm_asm.h>
12 #include <asm/kvm_arm.h>
13 #include <asm/cputype.h>
14
15 /* arm64 compatibility macros */
16 #define PSR_AA32_MODE_FIQ       FIQ_MODE
17 #define PSR_AA32_MODE_SVC       SVC_MODE
18 #define PSR_AA32_MODE_ABT       ABT_MODE
19 #define PSR_AA32_MODE_UND       UND_MODE
20 #define PSR_AA32_T_BIT          PSR_T_BIT
21 #define PSR_AA32_F_BIT          PSR_F_BIT
22 #define PSR_AA32_I_BIT          PSR_I_BIT
23 #define PSR_AA32_A_BIT          PSR_A_BIT
24 #define PSR_AA32_E_BIT          PSR_E_BIT
25 #define PSR_AA32_IT_MASK        PSR_IT_MASK
26 #define PSR_AA32_GE_MASK        0x000f0000
27 #define PSR_AA32_DIT_BIT        0x00200000
28 #define PSR_AA32_PAN_BIT        0x00400000
29 #define PSR_AA32_SSBS_BIT       0x00800000
30 #define PSR_AA32_Q_BIT          PSR_Q_BIT
31 #define PSR_AA32_V_BIT          PSR_V_BIT
32 #define PSR_AA32_C_BIT          PSR_C_BIT
33 #define PSR_AA32_Z_BIT          PSR_Z_BIT
34 #define PSR_AA32_N_BIT          PSR_N_BIT
35
36 unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
37
38 static inline unsigned long *vcpu_reg32(struct kvm_vcpu *vcpu, u8 reg_num)
39 {
40         return vcpu_reg(vcpu, reg_num);
41 }
42
43 unsigned long *__vcpu_spsr(struct kvm_vcpu *vcpu);
44
45 static inline unsigned long vpcu_read_spsr(struct kvm_vcpu *vcpu)
46 {
47         return *__vcpu_spsr(vcpu);
48 }
49
50 static inline void vcpu_write_spsr(struct kvm_vcpu *vcpu, unsigned long v)
51 {
52         *__vcpu_spsr(vcpu) = v;
53 }
54
55 static inline unsigned long host_spsr_to_spsr32(unsigned long spsr)
56 {
57         return spsr;
58 }
59
60 static inline unsigned long vcpu_get_reg(struct kvm_vcpu *vcpu,
61                                          u8 reg_num)
62 {
63         return *vcpu_reg(vcpu, reg_num);
64 }
65
66 static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
67                                 unsigned long val)
68 {
69         *vcpu_reg(vcpu, reg_num) = val;
70 }
71
72 bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
73 void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr);
74 void kvm_inject_undef32(struct kvm_vcpu *vcpu);
75 void kvm_inject_dabt32(struct kvm_vcpu *vcpu, unsigned long addr);
76 void kvm_inject_pabt32(struct kvm_vcpu *vcpu, unsigned long addr);
77 void kvm_inject_vabt(struct kvm_vcpu *vcpu);
78
79 static inline void kvm_inject_undefined(struct kvm_vcpu *vcpu)
80 {
81         kvm_inject_undef32(vcpu);
82 }
83
84 static inline void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr)
85 {
86         kvm_inject_dabt32(vcpu, addr);
87 }
88
89 static inline void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr)
90 {
91         kvm_inject_pabt32(vcpu, addr);
92 }
93
94 static inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
95 {
96         return kvm_condition_valid32(vcpu);
97 }
98
99 static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
100 {
101         kvm_skip_instr32(vcpu, is_wide_instr);
102 }
103
104 static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
105 {
106         vcpu->arch.hcr = HCR_GUEST_MASK;
107 }
108
109 static inline unsigned long *vcpu_hcr(const struct kvm_vcpu *vcpu)
110 {
111         return (unsigned long *)&vcpu->arch.hcr;
112 }
113
114 static inline void vcpu_clear_wfx_traps(struct kvm_vcpu *vcpu)
115 {
116         vcpu->arch.hcr &= ~HCR_TWE;
117 }
118
119 static inline void vcpu_set_wfx_traps(struct kvm_vcpu *vcpu)
120 {
121         vcpu->arch.hcr |= HCR_TWE;
122 }
123
124 static inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
125 {
126         return true;
127 }
128
129 static inline unsigned long *vcpu_pc(struct kvm_vcpu *vcpu)
130 {
131         return &vcpu->arch.ctxt.gp_regs.usr_regs.ARM_pc;
132 }
133
134 static inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
135 {
136         return (unsigned long *)&vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr;
137 }
138
139 static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
140 {
141         *vcpu_cpsr(vcpu) |= PSR_T_BIT;
142 }
143
144 static inline bool mode_has_spsr(struct kvm_vcpu *vcpu)
145 {
146         unsigned long cpsr_mode = vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr & MODE_MASK;
147         return (cpsr_mode > USR_MODE && cpsr_mode < SYSTEM_MODE);
148 }
149
150 static inline bool vcpu_mode_priv(struct kvm_vcpu *vcpu)
151 {
152         unsigned long cpsr_mode = vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr & MODE_MASK;
153         return cpsr_mode > USR_MODE;
154 }
155
156 static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu)
157 {
158         return vcpu->arch.fault.hsr;
159 }
160
161 static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
162 {
163         u32 hsr = kvm_vcpu_get_hsr(vcpu);
164
165         if (hsr & HSR_CV)
166                 return (hsr & HSR_COND) >> HSR_COND_SHIFT;
167
168         return -1;
169 }
170
171 static inline unsigned long kvm_vcpu_get_hfar(struct kvm_vcpu *vcpu)
172 {
173         return vcpu->arch.fault.hxfar;
174 }
175
176 static inline phys_addr_t kvm_vcpu_get_fault_ipa(struct kvm_vcpu *vcpu)
177 {
178         return ((phys_addr_t)vcpu->arch.fault.hpfar & HPFAR_MASK) << 8;
179 }
180
181 static inline bool kvm_vcpu_dabt_isvalid(struct kvm_vcpu *vcpu)
182 {
183         return kvm_vcpu_get_hsr(vcpu) & HSR_ISV;
184 }
185
186 static inline unsigned long kvm_vcpu_dabt_iss_nisv_sanitized(const struct kvm_vcpu *vcpu)
187 {
188         return kvm_vcpu_get_hsr(vcpu) & (HSR_CM | HSR_WNR | HSR_FSC);
189 }
190
191 static inline bool kvm_vcpu_dabt_iswrite(struct kvm_vcpu *vcpu)
192 {
193         return kvm_vcpu_get_hsr(vcpu) & HSR_WNR;
194 }
195
196 static inline bool kvm_vcpu_dabt_issext(struct kvm_vcpu *vcpu)
197 {
198         return kvm_vcpu_get_hsr(vcpu) & HSR_SSE;
199 }
200
201 static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
202 {
203         return false;
204 }
205
206 static inline int kvm_vcpu_dabt_get_rd(struct kvm_vcpu *vcpu)
207 {
208         return (kvm_vcpu_get_hsr(vcpu) & HSR_SRT_MASK) >> HSR_SRT_SHIFT;
209 }
210
211 static inline bool kvm_vcpu_dabt_iss1tw(struct kvm_vcpu *vcpu)
212 {
213         return kvm_vcpu_get_hsr(vcpu) & HSR_DABT_S1PTW;
214 }
215
216 static inline bool kvm_vcpu_dabt_is_cm(struct kvm_vcpu *vcpu)
217 {
218         return !!(kvm_vcpu_get_hsr(vcpu) & HSR_DABT_CM);
219 }
220
221 /* Get Access Size from a data abort */
222 static inline unsigned int kvm_vcpu_dabt_get_as(struct kvm_vcpu *vcpu)
223 {
224         switch ((kvm_vcpu_get_hsr(vcpu) >> 22) & 0x3) {
225         case 0:
226                 return 1;
227         case 1:
228                 return 2;
229         case 2:
230                 return 4;
231         default:
232                 kvm_err("Hardware is weird: SAS 0b11 is reserved\n");
233                 return 4;
234         }
235 }
236
237 /* This one is not specific to Data Abort */
238 static inline bool kvm_vcpu_trap_il_is32bit(struct kvm_vcpu *vcpu)
239 {
240         return kvm_vcpu_get_hsr(vcpu) & HSR_IL;
241 }
242
243 static inline u8 kvm_vcpu_trap_get_class(struct kvm_vcpu *vcpu)
244 {
245         return kvm_vcpu_get_hsr(vcpu) >> HSR_EC_SHIFT;
246 }
247
248 static inline bool kvm_vcpu_trap_is_iabt(struct kvm_vcpu *vcpu)
249 {
250         return kvm_vcpu_trap_get_class(vcpu) == HSR_EC_IABT;
251 }
252
253 static inline u8 kvm_vcpu_trap_get_fault(struct kvm_vcpu *vcpu)
254 {
255         return kvm_vcpu_get_hsr(vcpu) & HSR_FSC;
256 }
257
258 static inline u8 kvm_vcpu_trap_get_fault_type(struct kvm_vcpu *vcpu)
259 {
260         return kvm_vcpu_get_hsr(vcpu) & HSR_FSC_TYPE;
261 }
262
263 static inline bool kvm_vcpu_dabt_isextabt(struct kvm_vcpu *vcpu)
264 {
265         switch (kvm_vcpu_trap_get_fault(vcpu)) {
266         case FSC_SEA:
267         case FSC_SEA_TTW0:
268         case FSC_SEA_TTW1:
269         case FSC_SEA_TTW2:
270         case FSC_SEA_TTW3:
271         case FSC_SECC:
272         case FSC_SECC_TTW0:
273         case FSC_SECC_TTW1:
274         case FSC_SECC_TTW2:
275         case FSC_SECC_TTW3:
276                 return true;
277         default:
278                 return false;
279         }
280 }
281
282 static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
283 {
284         if (kvm_vcpu_trap_is_iabt(vcpu))
285                 return false;
286
287         return kvm_vcpu_dabt_iswrite(vcpu);
288 }
289
290 static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu *vcpu)
291 {
292         return kvm_vcpu_get_hsr(vcpu) & HSR_HVC_IMM_MASK;
293 }
294
295 static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
296 {
297         return vcpu_cp15(vcpu, c0_MPIDR) & MPIDR_HWID_BITMASK;
298 }
299
300 static inline bool kvm_arm_get_vcpu_workaround_2_flag(struct kvm_vcpu *vcpu)
301 {
302         return false;
303 }
304
305 static inline void kvm_arm_set_vcpu_workaround_2_flag(struct kvm_vcpu *vcpu,
306                                                       bool flag)
307 {
308 }
309
310 static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
311 {
312         *vcpu_cpsr(vcpu) |= PSR_E_BIT;
313 }
314
315 static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu)
316 {
317         return !!(*vcpu_cpsr(vcpu) & PSR_E_BIT);
318 }
319
320 static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu,
321                                                     unsigned long data,
322                                                     unsigned int len)
323 {
324         if (kvm_vcpu_is_be(vcpu)) {
325                 switch (len) {
326                 case 1:
327                         return data & 0xff;
328                 case 2:
329                         return be16_to_cpu(data & 0xffff);
330                 default:
331                         return be32_to_cpu(data);
332                 }
333         } else {
334                 switch (len) {
335                 case 1:
336                         return data & 0xff;
337                 case 2:
338                         return le16_to_cpu(data & 0xffff);
339                 default:
340                         return le32_to_cpu(data);
341                 }
342         }
343 }
344
345 static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
346                                                     unsigned long data,
347                                                     unsigned int len)
348 {
349         if (kvm_vcpu_is_be(vcpu)) {
350                 switch (len) {
351                 case 1:
352                         return data & 0xff;
353                 case 2:
354                         return cpu_to_be16(data & 0xffff);
355                 default:
356                         return cpu_to_be32(data);
357                 }
358         } else {
359                 switch (len) {
360                 case 1:
361                         return data & 0xff;
362                 case 2:
363                         return cpu_to_le16(data & 0xffff);
364                 default:
365                         return cpu_to_le32(data);
366                 }
367         }
368 }
369
370 static inline void vcpu_ptrauth_setup_lazy(struct kvm_vcpu *vcpu) {}
371
372 #endif /* __ARM_KVM_EMULATE_H__ */
This page took 0.051936 seconds and 4 git commands to generate.