hvf: sync registers used at EL2
When starting up the VM at EL2, more sysregs are available. Sync the state of those. In addition, sync the state of the EL1 physical timer when the vGIC is used, even if running at EL1. However, no OS running at EL1 is expected to use those registers. Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20260429190532.26538-11-mohamed@unpredictable.fr Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Mohamed Mediouni committed
May 5, 2026 at 09:25 UTC
0a8113cf3010afceed5d5eac6d14476ab0725d77
2 files changed
+99
-6
target/arm/hvf/hvf.c
+55
-6
@@ -476,37 +476,75 @@ static const struct hvf_reg_match hvf_sme2_preg_match[] = {
476
*
477
* SME2 registers are guarded by a runtime availability attribute instead of a
478
* compile-time def, so verify those at runtime in hvf_arch_init_vcpu() below.
479
+ *
480
+ * Nested virt registers are handled via a runtime check, so override the
481
+ * guarded availability check done by Clang.
482
*/
483
484
+#pragma clang diagnostic push
485
+#pragma clang diagnostic ignored "-Wunguarded-availability"
486
+
487
#define DEF_SYSREG(HVF_ID, ...) \
488
QEMU_BUILD_BUG_ON(HVF_ID != KVMID_TO_HVF(KVMID_AA64_SYS_REG64(__VA_ARGS__)));
489
#define DEF_SYSREG_15_02(...)
490
491
+#define DEF_SYSREG_EL2(HVF_ID, ...) \
492
+ QEMU_BUILD_BUG_ON(HVF_ID != KVMID_TO_HVF(KVMID_AA64_SYS_REG64(__VA_ARGS__)));
493
+
494
+#define DEF_SYSREG_VGIC(HVF_ID, ...) \
495
+ QEMU_BUILD_BUG_ON(HVF_ID != KVMID_TO_HVF(KVMID_AA64_SYS_REG64(__VA_ARGS__)));
496
+
497
+#define DEF_SYSREG_VGIC_EL2(HVF_ID, ...) \
498
+ QEMU_BUILD_BUG_ON(HVF_ID != KVMID_TO_HVF(KVMID_AA64_SYS_REG64(__VA_ARGS__)));
499
+
500
#include "sysreg.c.inc"
501
502
#undef DEF_SYSREG
503
#undef DEF_SYSREG_15_02
504
+#undef DEF_SYSREG_EL2
505
+#undef DEF_SYSREG_VGIC
506
+#undef DEF_SYSREG_VGIC_EL2
507
490
-#define DEF_SYSREG(HVF_ID, op0, op1, crn, crm, op2) HVF_ID,
508
+#define DEF_SYSREG(HVF_ID, op0, op1, crn, crm, op2) {HVF_ID},
509
#define DEF_SYSREG_15_02(...)
510
+#define DEF_SYSREG_EL2(HVF_ID, op0, op1, crn, crm, op2) {HVF_ID, .el2 = true},
511
+#define DEF_SYSREG_VGIC(HVF_ID, op0, op1, crn, crm, op2) {HVF_ID, .vgic = true},
512
+#define DEF_SYSREG_VGIC_EL2(HVF_ID, op0, op1, crn, crm, op2) {HVF_ID, true, true},
513
+
514
+struct hvf_sreg {
515
+ hv_sys_reg_t sreg;
516
+ bool vgic;
517
+ bool el2;
518
+};
519
493
-static const hv_sys_reg_t hvf_sreg_list[] = {
520
+static struct hvf_sreg hvf_sreg_list[] = {
521
#include "sysreg.c.inc"
522
};
523
524
#undef DEF_SYSREG
525
#undef DEF_SYSREG_15_02
526
+#undef DEF_SYSREG_EL2
527
+#undef DEF_SYSREG_VGIC
528
+#undef DEF_SYSREG_VGIC_EL2
529
+
530
+#pragma clang diagnostic pop
531
532
#define DEF_SYSREG(...)
501
-#define DEF_SYSREG_15_02(HVF_ID, op0, op1, crn, crm, op2) HVF_ID,
533
+#define DEF_SYSREG_15_02(HVF_ID, op0, op1, crn, crm, op2) {HVF_ID},
534
+#define DEF_SYSREG_EL2(...)
535
+#define DEF_SYSREG_VGIC(...)
536
+#define DEF_SYSREG_VGIC_EL2(...)
537
538
API_AVAILABLE(macos(15.2))
504
-static const hv_sys_reg_t hvf_sreg_list_sme2[] = {
539
+static struct hvf_sreg hvf_sreg_list_sme2[] = {
540
#include "sysreg.c.inc"
541
};
542
543
#undef DEF_SYSREG
544
#undef DEF_SYSREG_15_02
545
+#undef DEF_SYSREG_EL2
546
+#undef DEF_SYSREG_VGIC
547
+#undef DEF_SYSREG_VGIC_EL2
548
549
/*
550
* For FEAT_SME2 migration, we need to store PSTATE.{SM,ZA} bits which are
@@ -1344,6 +1382,9 @@ int hvf_arch_init_vcpu(CPUState *cpu)
1382
#define DEF_SYSREG_15_02(HVF_ID, ...) \
1383
g_assert(HVF_ID == KVMID_TO_HVF(KVMID_AA64_SYS_REG64(__VA_ARGS__)));
1384
#define DEF_SYSREG(...)
1385
+#define DEF_SYSREG_EL2(...)
1386
+#define DEF_SYSREG_VGIC(...)
1387
+#define DEF_SYSREG_VGIC_EL2(...)
1388
1389
#include "sysreg.c.inc"
1390
@@ -1371,11 +1412,19 @@ int hvf_arch_init_vcpu(CPUState *cpu)
1412
1413
/* Populate cp list for all known sysregs */
1414
for (i = 0; i < ARRAY_SIZE(hvf_sreg_list); i++) {
1374
- hv_sys_reg_t hvf_id = hvf_sreg_list[i];
1415
+ hv_sys_reg_t hvf_id = hvf_sreg_list[i].sreg;
1416
uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
1417
uint32_t key = kvm_to_cpreg_id(kvm_id);
1418
const ARMCPRegInfo *ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
1419
1420
+ if (hvf_sreg_list[i].vgic && !hvf_irqchip_in_kernel()) {
1421
+ continue;
1422
+ }
1423
+
1424
+ if (hvf_sreg_list[i].el2 && !hvf_nested_virt_enabled()) {
1425
+ continue;
1426
+ }
1427
+
1428
if (ri) {
1429
assert(!(ri->type & ARM_CP_NO_RAW));
1430
arm_cpu->cpreg_indexes[sregs_cnt++] = kvm_id;
@@ -1384,7 +1433,7 @@ int hvf_arch_init_vcpu(CPUState *cpu)
1433
if (__builtin_available(macOS 15.2, *)) {
1434
if (hvf_arm_sme2_supported()) {
1435
for (i = 0; i < ARRAY_SIZE(hvf_sreg_list_sme2); i++) {
1387
- hv_sys_reg_t hvf_id = hvf_sreg_list_sme2[i];
1436
+ hv_sys_reg_t hvf_id = hvf_sreg_list_sme2[i].sreg;
1437
uint64_t kvm_id = HVF_TO_KVMID(hvf_id);
1438
uint32_t key = kvm_to_cpreg_id(kvm_id);
1439
const ARMCPRegInfo *ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
target/arm/hvf/sysreg.c.inc
+44
@@ -153,3 +153,47 @@ DEF_SYSREG_15_02(HV_SYS_REG_ID_AA64ZFR0_EL1, 3, 0, 0, 4, 4)
153
DEF_SYSREG_15_02(HV_SYS_REG_ID_AA64SMFR0_EL1, 3, 0, 0, 4, 5)
154
DEF_SYSREG_15_02(HV_SYS_REG_SMPRI_EL1, 3, 0, 1, 2, 4)
155
DEF_SYSREG_15_02(HV_SYS_REG_SMCR_EL1, 3, 0, 1, 2, 6)
156
+/*
157
+ * Block these because of the same issue as virtual counters in
158
+ * that caused the revert in 28b0ed32b32c7e5094cf2f1ec9c0645c65fad2aa
159
+ *
160
+ * DEF_SYSREG_VGIC(HV_SYS_REG_CNTP_CTL_EL0, 3, 3, 14, 2, 1)
161
+ * DEF_SYSREG_VGIC(HV_SYS_REG_CNTP_CVAL_EL0, 3, 3, 14, 2, 2)
162
+ */
163
+#ifdef SYNC_NO_RAW_REGS
164
+DEF_SYSREG_VGIC(HV_SYS_REG_CNTP_TVAL_EL0, 3, 3, 14, 2, 0)
165
+#endif
166
+
167
+/*
168
+ * Also block these because of the same issue as virtual counters in
169
+ * that caused the revert in 28b0ed32b32c7e5094cf2f1ec9c0645c65fad2aa
170
+ *
171
+ * DEF_SYSREG_VGIC_EL2(HV_SYS_REG_CNTHP_CVAL_EL2, 3, 4, 14, 2, 2)
172
+ * DEF_SYSREG_VGIC_EL2(HV_SYS_REG_CNTHP_CTL_EL2, 3, 4, 14, 2, 1)
173
+ */
174
+DEF_SYSREG_VGIC_EL2(HV_SYS_REG_CNTHCTL_EL2, 3, 4, 14, 1, 0)
175
+#ifdef SYNC_NO_RAW_REGS
176
+DEF_SYSREG_VGIC_EL2(HV_SYS_REG_CNTHP_TVAL_EL2, 3, 4, 14, 2, 0)
177
+#endif
178
+DEF_SYSREG_VGIC_EL2(HV_SYS_REG_CNTVOFF_EL2, 3, 4, 14, 0, 3)
179
+
180
+DEF_SYSREG_EL2(HV_SYS_REG_CPTR_EL2, 3, 4, 1, 1, 2)
181
+DEF_SYSREG_EL2(HV_SYS_REG_ELR_EL2, 3, 4, 4, 0, 1)
182
+DEF_SYSREG_EL2(HV_SYS_REG_ESR_EL2, 3, 4, 5, 2, 0)
183
+DEF_SYSREG_EL2(HV_SYS_REG_FAR_EL2, 3, 4, 6, 0, 0)
184
+DEF_SYSREG_EL2(HV_SYS_REG_HCR_EL2, 3, 4, 1, 1, 0)
185
+DEF_SYSREG_EL2(HV_SYS_REG_HPFAR_EL2, 3, 4, 6, 0, 4)
186
+DEF_SYSREG_EL2(HV_SYS_REG_MAIR_EL2, 3, 4, 10, 2, 0)
187
+DEF_SYSREG_EL2(HV_SYS_REG_MDCR_EL2, 3, 4, 1, 1, 1)
188
+DEF_SYSREG_EL2(HV_SYS_REG_SCTLR_EL2, 3, 4, 1, 0, 0)
189
+DEF_SYSREG_EL2(HV_SYS_REG_SPSR_EL2, 3, 4, 4, 0, 0)
190
+DEF_SYSREG_EL2(HV_SYS_REG_SP_EL2, 3, 6, 4, 1, 0)
191
+DEF_SYSREG_EL2(HV_SYS_REG_TCR_EL2, 3, 4, 2, 0, 2)
192
+DEF_SYSREG_EL2(HV_SYS_REG_TPIDR_EL2, 3, 4, 13, 0, 2)
193
+DEF_SYSREG_EL2(HV_SYS_REG_TTBR0_EL2, 3, 4, 2, 0, 0)
194
+DEF_SYSREG_EL2(HV_SYS_REG_TTBR1_EL2, 3, 4, 2, 0, 1)
195
+DEF_SYSREG_EL2(HV_SYS_REG_VBAR_EL2, 3, 4, 12, 0, 0)
196
+DEF_SYSREG_EL2(HV_SYS_REG_VMPIDR_EL2, 3, 4, 0, 0, 5)
197
+DEF_SYSREG_EL2(HV_SYS_REG_VPIDR_EL2, 3, 4, 0, 0, 0)
198
+DEF_SYSREG_EL2(HV_SYS_REG_VTCR_EL2, 3, 4, 2, 1, 2)
199
+DEF_SYSREG_EL2(HV_SYS_REG_VTTBR_EL2, 3, 4, 2, 1, 0)