1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * VGIC system registers handling functions for AArch64 mode
4 */
5
6#include <linux/irqchip/arm-gic-v3.h>
7#include <linux/kvm.h>
8#include <linux/kvm_host.h>
9#include <asm/kvm_emulate.h>
10#include "vgic/vgic.h"
11#include "sys_regs.h"
12
13static int set_gic_ctlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
14 u64 val)
15{
16 u32 host_pri_bits, host_id_bits, host_seis, host_a3v, seis, a3v;
17 struct vgic_cpu *vgic_v3_cpu = &vcpu->arch.vgic_cpu;
18 struct vgic_vmcr vmcr;
19
20 vgic_get_vmcr(vcpu, vmcr: &vmcr);
21
22 /*
23 * Disallow restoring VM state if not supported by this
24 * hardware.
25 */
26 host_pri_bits = FIELD_GET(ICC_CTLR_EL1_PRI_BITS_MASK, val) + 1;
27 if (host_pri_bits > vgic_v3_cpu->num_pri_bits)
28 return -EINVAL;
29
30 vgic_v3_cpu->num_pri_bits = host_pri_bits;
31
32 host_id_bits = FIELD_GET(ICC_CTLR_EL1_ID_BITS_MASK, val);
33 if (host_id_bits > vgic_v3_cpu->num_id_bits)
34 return -EINVAL;
35
36 vgic_v3_cpu->num_id_bits = host_id_bits;
37
38 host_seis = FIELD_GET(ICH_VTR_EL2_SEIS, kvm_vgic_global_state.ich_vtr_el2);
39 seis = FIELD_GET(ICC_CTLR_EL1_SEIS_MASK, val);
40 if (host_seis != seis)
41 return -EINVAL;
42
43 host_a3v = FIELD_GET(ICH_VTR_EL2_A3V, kvm_vgic_global_state.ich_vtr_el2);
44 a3v = FIELD_GET(ICC_CTLR_EL1_A3V_MASK, val);
45 if (host_a3v != a3v)
46 return -EINVAL;
47
48 /*
49 * Here set VMCR.CTLR in ICC_CTLR_EL1 layout.
50 * The vgic_set_vmcr() will convert to ICH_VMCR layout.
51 */
52 vmcr.cbpr = FIELD_GET(ICC_CTLR_EL1_CBPR_MASK, val);
53 vmcr.eoim = FIELD_GET(ICC_CTLR_EL1_EOImode_MASK, val);
54 vgic_set_vmcr(vcpu, vmcr: &vmcr);
55
56 return 0;
57}
58
59static int get_gic_ctlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
60 u64 *valp)
61{
62 struct vgic_cpu *vgic_v3_cpu = &vcpu->arch.vgic_cpu;
63 struct vgic_vmcr vmcr;
64 u64 val;
65
66 vgic_get_vmcr(vcpu, vmcr: &vmcr);
67 val = 0;
68 val |= FIELD_PREP(ICC_CTLR_EL1_PRI_BITS_MASK, vgic_v3_cpu->num_pri_bits - 1);
69 val |= FIELD_PREP(ICC_CTLR_EL1_ID_BITS_MASK, vgic_v3_cpu->num_id_bits);
70 val |= FIELD_PREP(ICC_CTLR_EL1_SEIS_MASK,
71 FIELD_GET(ICH_VTR_EL2_SEIS,
72 kvm_vgic_global_state.ich_vtr_el2));
73 val |= FIELD_PREP(ICC_CTLR_EL1_A3V_MASK,
74 FIELD_GET(ICH_VTR_EL2_A3V, kvm_vgic_global_state.ich_vtr_el2));
75 /*
76 * The VMCR.CTLR value is in ICC_CTLR_EL1 layout.
77 * Extract it directly using ICC_CTLR_EL1 reg definitions.
78 */
79 val |= FIELD_PREP(ICC_CTLR_EL1_CBPR_MASK, vmcr.cbpr);
80 val |= FIELD_PREP(ICC_CTLR_EL1_EOImode_MASK, vmcr.eoim);
81
82 *valp = val;
83
84 return 0;
85}
86
87static int set_gic_pmr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
88 u64 val)
89{
90 struct vgic_vmcr vmcr;
91
92 vgic_get_vmcr(vcpu, vmcr: &vmcr);
93 vmcr.pmr = FIELD_GET(ICC_PMR_EL1_MASK, val);
94 vgic_set_vmcr(vcpu, vmcr: &vmcr);
95
96 return 0;
97}
98
99static int get_gic_pmr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
100 u64 *val)
101{
102 struct vgic_vmcr vmcr;
103
104 vgic_get_vmcr(vcpu, vmcr: &vmcr);
105 *val = FIELD_PREP(ICC_PMR_EL1_MASK, vmcr.pmr);
106
107 return 0;
108}
109
110static int set_gic_bpr0(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
111 u64 val)
112{
113 struct vgic_vmcr vmcr;
114
115 vgic_get_vmcr(vcpu, vmcr: &vmcr);
116 vmcr.bpr = FIELD_GET(ICC_BPR0_EL1_MASK, val);
117 vgic_set_vmcr(vcpu, vmcr: &vmcr);
118
119 return 0;
120}
121
122static int get_gic_bpr0(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
123 u64 *val)
124{
125 struct vgic_vmcr vmcr;
126
127 vgic_get_vmcr(vcpu, vmcr: &vmcr);
128 *val = FIELD_PREP(ICC_BPR0_EL1_MASK, vmcr.bpr);
129
130 return 0;
131}
132
133static int set_gic_bpr1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
134 u64 val)
135{
136 struct vgic_vmcr vmcr;
137
138 vgic_get_vmcr(vcpu, vmcr: &vmcr);
139 if (!vmcr.cbpr) {
140 vmcr.abpr = FIELD_GET(ICC_BPR1_EL1_MASK, val);
141 vgic_set_vmcr(vcpu, vmcr: &vmcr);
142 }
143
144 return 0;
145}
146
147static int get_gic_bpr1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
148 u64 *val)
149{
150 struct vgic_vmcr vmcr;
151
152 vgic_get_vmcr(vcpu, vmcr: &vmcr);
153 if (!vmcr.cbpr)
154 *val = FIELD_PREP(ICC_BPR1_EL1_MASK, vmcr.abpr);
155 else
156 *val = min((vmcr.bpr + 1), 7U);
157
158
159 return 0;
160}
161
162static int set_gic_grpen0(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
163 u64 val)
164{
165 struct vgic_vmcr vmcr;
166
167 vgic_get_vmcr(vcpu, vmcr: &vmcr);
168 vmcr.grpen0 = FIELD_GET(ICC_IGRPEN0_EL1_MASK, val);
169 vgic_set_vmcr(vcpu, vmcr: &vmcr);
170
171 return 0;
172}
173
174static int get_gic_grpen0(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
175 u64 *val)
176{
177 struct vgic_vmcr vmcr;
178
179 vgic_get_vmcr(vcpu, vmcr: &vmcr);
180 *val = FIELD_PREP(ICC_IGRPEN0_EL1_MASK, vmcr.grpen0);
181
182 return 0;
183}
184
185static int set_gic_grpen1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
186 u64 val)
187{
188 struct vgic_vmcr vmcr;
189
190 vgic_get_vmcr(vcpu, vmcr: &vmcr);
191 vmcr.grpen1 = FIELD_GET(ICC_IGRPEN1_EL1_MASK, val);
192 vgic_set_vmcr(vcpu, vmcr: &vmcr);
193
194 return 0;
195}
196
197static int get_gic_grpen1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
198 u64 *val)
199{
200 struct vgic_vmcr vmcr;
201
202 vgic_get_vmcr(vcpu, vmcr: &vmcr);
203 *val = FIELD_GET(ICC_IGRPEN1_EL1_MASK, vmcr.grpen1);
204
205 return 0;
206}
207
208static void set_apr_reg(struct kvm_vcpu *vcpu, u64 val, u8 apr, u8 idx)
209{
210 struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
211
212 if (apr)
213 vgicv3->vgic_ap1r[idx] = val;
214 else
215 vgicv3->vgic_ap0r[idx] = val;
216}
217
218static u64 get_apr_reg(struct kvm_vcpu *vcpu, u8 apr, u8 idx)
219{
220 struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
221
222 if (apr)
223 return vgicv3->vgic_ap1r[idx];
224 else
225 return vgicv3->vgic_ap0r[idx];
226}
227
228static int set_gic_ap0r(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
229 u64 val)
230
231{
232 u8 idx = r->Op2 & 3;
233
234 if (idx > vgic_v3_max_apr_idx(vcpu))
235 return -EINVAL;
236
237 set_apr_reg(vcpu, val, apr: 0, idx);
238 return 0;
239}
240
241static int get_gic_ap0r(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
242 u64 *val)
243{
244 u8 idx = r->Op2 & 3;
245
246 if (idx > vgic_v3_max_apr_idx(vcpu))
247 return -EINVAL;
248
249 *val = get_apr_reg(vcpu, apr: 0, idx);
250
251 return 0;
252}
253
254static int set_gic_ap1r(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
255 u64 val)
256
257{
258 u8 idx = r->Op2 & 3;
259
260 if (idx > vgic_v3_max_apr_idx(vcpu))
261 return -EINVAL;
262
263 set_apr_reg(vcpu, val, apr: 1, idx);
264 return 0;
265}
266
267static int get_gic_ap1r(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
268 u64 *val)
269{
270 u8 idx = r->Op2 & 3;
271
272 if (idx > vgic_v3_max_apr_idx(vcpu))
273 return -EINVAL;
274
275 *val = get_apr_reg(vcpu, apr: 1, idx);
276
277 return 0;
278}
279
280static int set_gic_sre(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
281 u64 val)
282{
283 /* Validate SRE bit */
284 if (!(val & ICC_SRE_EL1_SRE))
285 return -EINVAL;
286
287 return 0;
288}
289
290static int get_gic_sre(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
291 u64 *val)
292{
293 struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
294
295 *val = vgicv3->vgic_sre;
296
297 return 0;
298}
299
300static int set_gic_ich_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
301 u64 val)
302{
303 __vcpu_assign_sys_reg(vcpu, r->reg, val);
304 return 0;
305}
306
307static int get_gic_ich_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
308 u64 *val)
309{
310 *val = __vcpu_sys_reg(vcpu, r->reg);
311 return 0;
312}
313
314static int set_gic_ich_apr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
315 u64 val)
316{
317 u8 idx = r->Op2 & 3;
318
319 if (idx > vgic_v3_max_apr_idx(vcpu))
320 return -EINVAL;
321
322 return set_gic_ich_reg(vcpu, r, val);
323}
324
325static int get_gic_ich_apr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
326 u64 *val)
327{
328 u8 idx = r->Op2 & 3;
329
330 if (idx > vgic_v3_max_apr_idx(vcpu))
331 return -EINVAL;
332
333 return get_gic_ich_reg(vcpu, r, val);
334}
335
336static int set_gic_icc_sre(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
337 u64 val)
338{
339 if (val != KVM_ICC_SRE_EL2)
340 return -EINVAL;
341 return 0;
342}
343
344static int get_gic_icc_sre(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
345 u64 *val)
346{
347 *val = KVM_ICC_SRE_EL2;
348 return 0;
349}
350
351static int set_gic_ich_vtr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
352 u64 val)
353{
354 if (val != kvm_get_guest_vtr_el2())
355 return -EINVAL;
356 return 0;
357}
358
359static int get_gic_ich_vtr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
360 u64 *val)
361{
362 *val = kvm_get_guest_vtr_el2();
363 return 0;
364}
365
366static unsigned int el2_visibility(const struct kvm_vcpu *vcpu,
367 const struct sys_reg_desc *rd)
368{
369 return vcpu_has_nv(vcpu) ? 0 : REG_HIDDEN;
370}
371
372#define __EL2_REG(r, acc, i) \
373 { \
374 SYS_DESC(SYS_ ## r), \
375 .get_user = get_gic_ ## acc, \
376 .set_user = set_gic_ ## acc, \
377 .reg = i, \
378 .visibility = el2_visibility, \
379 }
380
381#define EL2_REG(r, acc) __EL2_REG(r, acc, r)
382
383#define EL2_REG_RO(r, acc) __EL2_REG(r, acc, 0)
384
385static const struct sys_reg_desc gic_v3_icc_reg_descs[] = {
386 { SYS_DESC(SYS_ICC_PMR_EL1),
387 .set_user = set_gic_pmr, .get_user = get_gic_pmr, },
388 { SYS_DESC(SYS_ICC_BPR0_EL1),
389 .set_user = set_gic_bpr0, .get_user = get_gic_bpr0, },
390 { SYS_DESC(SYS_ICC_AP0R0_EL1),
391 .set_user = set_gic_ap0r, .get_user = get_gic_ap0r, },
392 { SYS_DESC(SYS_ICC_AP0R1_EL1),
393 .set_user = set_gic_ap0r, .get_user = get_gic_ap0r, },
394 { SYS_DESC(SYS_ICC_AP0R2_EL1),
395 .set_user = set_gic_ap0r, .get_user = get_gic_ap0r, },
396 { SYS_DESC(SYS_ICC_AP0R3_EL1),
397 .set_user = set_gic_ap0r, .get_user = get_gic_ap0r, },
398 { SYS_DESC(SYS_ICC_AP1R0_EL1),
399 .set_user = set_gic_ap1r, .get_user = get_gic_ap1r, },
400 { SYS_DESC(SYS_ICC_AP1R1_EL1),
401 .set_user = set_gic_ap1r, .get_user = get_gic_ap1r, },
402 { SYS_DESC(SYS_ICC_AP1R2_EL1),
403 .set_user = set_gic_ap1r, .get_user = get_gic_ap1r, },
404 { SYS_DESC(SYS_ICC_AP1R3_EL1),
405 .set_user = set_gic_ap1r, .get_user = get_gic_ap1r, },
406 { SYS_DESC(SYS_ICC_BPR1_EL1),
407 .set_user = set_gic_bpr1, .get_user = get_gic_bpr1, },
408 { SYS_DESC(SYS_ICC_CTLR_EL1),
409 .set_user = set_gic_ctlr, .get_user = get_gic_ctlr, },
410 { SYS_DESC(SYS_ICC_SRE_EL1),
411 .set_user = set_gic_sre, .get_user = get_gic_sre, },
412 { SYS_DESC(SYS_ICC_IGRPEN0_EL1),
413 .set_user = set_gic_grpen0, .get_user = get_gic_grpen0, },
414 { SYS_DESC(SYS_ICC_IGRPEN1_EL1),
415 .set_user = set_gic_grpen1, .get_user = get_gic_grpen1, },
416 EL2_REG(ICH_AP0R0_EL2, ich_apr),
417 EL2_REG(ICH_AP0R1_EL2, ich_apr),
418 EL2_REG(ICH_AP0R2_EL2, ich_apr),
419 EL2_REG(ICH_AP0R3_EL2, ich_apr),
420 EL2_REG(ICH_AP1R0_EL2, ich_apr),
421 EL2_REG(ICH_AP1R1_EL2, ich_apr),
422 EL2_REG(ICH_AP1R2_EL2, ich_apr),
423 EL2_REG(ICH_AP1R3_EL2, ich_apr),
424 EL2_REG_RO(ICC_SRE_EL2, icc_sre),
425 EL2_REG(ICH_HCR_EL2, ich_reg),
426 EL2_REG_RO(ICH_VTR_EL2, ich_vtr),
427 EL2_REG(ICH_VMCR_EL2, ich_reg),
428 EL2_REG(ICH_LR0_EL2, ich_reg),
429 EL2_REG(ICH_LR1_EL2, ich_reg),
430 EL2_REG(ICH_LR2_EL2, ich_reg),
431 EL2_REG(ICH_LR3_EL2, ich_reg),
432 EL2_REG(ICH_LR4_EL2, ich_reg),
433 EL2_REG(ICH_LR5_EL2, ich_reg),
434 EL2_REG(ICH_LR6_EL2, ich_reg),
435 EL2_REG(ICH_LR7_EL2, ich_reg),
436 EL2_REG(ICH_LR8_EL2, ich_reg),
437 EL2_REG(ICH_LR9_EL2, ich_reg),
438 EL2_REG(ICH_LR10_EL2, ich_reg),
439 EL2_REG(ICH_LR11_EL2, ich_reg),
440 EL2_REG(ICH_LR12_EL2, ich_reg),
441 EL2_REG(ICH_LR13_EL2, ich_reg),
442 EL2_REG(ICH_LR14_EL2, ich_reg),
443 EL2_REG(ICH_LR15_EL2, ich_reg),
444};
445
446const struct sys_reg_desc *vgic_v3_get_sysreg_table(unsigned int *sz)
447{
448 *sz = ARRAY_SIZE(gic_v3_icc_reg_descs);
449 return gic_v3_icc_reg_descs;
450}
451
452static u64 attr_to_id(u64 attr)
453{
454 return ARM64_SYS_REG(FIELD_GET(KVM_REG_ARM_VGIC_SYSREG_OP0_MASK, attr),
455 FIELD_GET(KVM_REG_ARM_VGIC_SYSREG_OP1_MASK, attr),
456 FIELD_GET(KVM_REG_ARM_VGIC_SYSREG_CRN_MASK, attr),
457 FIELD_GET(KVM_REG_ARM_VGIC_SYSREG_CRM_MASK, attr),
458 FIELD_GET(KVM_REG_ARM_VGIC_SYSREG_OP2_MASK, attr));
459}
460
461int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
462{
463 const struct sys_reg_desc *r;
464
465 r = get_reg_by_id(attr_to_id(attr->attr), gic_v3_icc_reg_descs,
466 ARRAY_SIZE(gic_v3_icc_reg_descs));
467
468 if (r && !sysreg_hidden(vcpu, r))
469 return 0;
470
471 return -ENXIO;
472}
473
474int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu,
475 struct kvm_device_attr *attr,
476 bool is_write)
477{
478 struct kvm_one_reg reg = {
479 .id = attr_to_id(attr: attr->attr),
480 .addr = attr->addr,
481 };
482
483 if (is_write)
484 return kvm_sys_reg_set_user(vcpu, &reg, gic_v3_icc_reg_descs,
485 ARRAY_SIZE(gic_v3_icc_reg_descs));
486 else
487 return kvm_sys_reg_get_user(vcpu, &reg, gic_v3_icc_reg_descs,
488 ARRAY_SIZE(gic_v3_icc_reg_descs));
489}
490

source code of linux/arch/arm64/kvm/vgic-sys-reg-v3.c