target/arm/helper.c | 7 +++++-- tests/tcg/aarch64/sysregs.c | 31 ++++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-)
Since kernel commit b130a8f70cbbf9 (KVM: arm64: Check advertised
Stage-2 page size capability) the relevant Stage 2 have been pegged at
1 f(4KB granule not supported at stage 2) by the kernel. As a result
the behaviour of the test differs when run on real HW compared to
under emulation:
id_aa64mmfr0_el1 : 0x00000111ff000000
!!extra bits!! : 0x0000011100000000
Update the test with a new helper to explicitly test for fixed bits
and update v8_user_idregs to match real systems.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4566
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
target/arm/helper.c | 7 +++++--
tests/tcg/aarch64/sysregs.c | 31 ++++++++++++++++++++++++++++---
2 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index c3f607e6d6b..7e65f072a4a 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6902,8 +6902,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
R_ID_AA64FPFR0_F8CVT_MASK },
{ .name = "ID_AA64MMFR0_EL1",
.exported_bits = R_ID_AA64MMFR0_ECV_MASK,
- .fixed_bits = (0xfu << R_ID_AA64MMFR0_TGRAN64_SHIFT) |
- (0xfu << R_ID_AA64MMFR0_TGRAN4_SHIFT) },
+ .fixed_bits = (0xfULL << R_ID_AA64MMFR0_TGRAN64_SHIFT) |
+ (0xfULL << R_ID_AA64MMFR0_TGRAN4_SHIFT) |
+ (0x1ULL << R_ID_AA64MMFR0_TGRAN4_2_SHIFT) |
+ (0x1ULL << R_ID_AA64MMFR0_TGRAN64_2_SHIFT) |
+ (0x1ULL << R_ID_AA64MMFR0_TGRAN16_2_SHIFT) },
{ .name = "ID_AA64MMFR1_EL1",
.exported_bits = R_ID_AA64MMFR1_AFP_MASK },
{ .name = "ID_AA64MMFR2_EL1",
diff --git a/tests/tcg/aarch64/sysregs.c b/tests/tcg/aarch64/sysregs.c
index 301e61d0dd4..8f7c5303f77 100644
--- a/tests/tcg/aarch64/sysregs.c
+++ b/tests/tcg/aarch64/sysregs.c
@@ -54,6 +54,23 @@ int failed_bit_count;
} \
})
+/* As above but also check that required fixed bits have expected values */
+#define get_cpu_reg_check_fixed(id, allowed_mask, fixed_mask, expected_val) ({ \
+ unsigned long __cval = get_cpu_reg(id); \
+ unsigned long __extra = __cval & ~(allowed_mask); \
+ if (__extra) { \
+ printf("%-20s: 0x%016lx\n", " !!extra bits!!", __extra); \
+ failed_bit_count++; \
+ } \
+ if ((__cval & (fixed_mask)) != (expected_val)) { \
+ printf("%-20s: 0x%016llx (expected fixed 0x%016llx)\n", \
+ " !!fixed mismatch!!", \
+ (unsigned long long)(__cval & (fixed_mask)), \
+ (unsigned long long)(expected_val)); \
+ failed_bit_count++; \
+ } \
+})
+
/* As above but check RAZ */
#define get_cpu_reg_check_zero(id) ({ \
unsigned long __val = 0xdeadbeef; \
@@ -127,8 +144,16 @@ int main(void)
get_cpu_reg_check_mask(id_aa64isar0_el1, _m(f0ff,ffff,f0ff,fff0));
get_cpu_reg_check_mask(id_aa64isar1_el1, _m(00ff,f0ff,ffff,ffff));
get_cpu_reg_check_mask(SYS_ID_AA64ISAR2_EL1, _m(00ff,0000,00ff,ffff));
- /* TGran4 & TGran64 as pegged to -1 */
- get_cpu_reg_check_mask(id_aa64mmfr0_el1, _m(f000,0000,ff00,0000));
+ /*
+ * TGran4 & TGran64 are pegged to -1 (0xf).
+ * Stage 2 translation granule support (TGran4_2, TGran64_2, TGran16_2)
+ * are pegged to safe value 1 as exposed by Linux kernel since
+ * b130a8f70cbbf9 (KVM: arm64: Check advertised Stage-2 page size capability).
+ */
+ get_cpu_reg_check_fixed(id_aa64mmfr0_el1,
+ _m(f000, 0111, ff00, 0000),
+ _m(0000, 0111, ff00, 0000),
+ _m(0000, 0111, ff00, 0000));
get_cpu_reg_check_mask(id_aa64mmfr1_el1, _m(0000,f000,0000,0000));
get_cpu_reg_check_mask(SYS_ID_AA64MMFR2_EL1, _m(0000,000f,0000,0000));
/* EL1/EL0 reported as AA64 only */
@@ -179,7 +204,7 @@ int main(void)
}
if (failed_bit_count > 0) {
- printf("Extra information leaked to user-space!\n");
+ printf("Bit check failure or extra info leaked to user-space!\n");
return 1;
}
--
2.47.3
© 2016 - 2026 Red Hat, Inc.