target/arm: Implement ID_AA64PFR2_EL1
Currently we define the ID_AA64PFR2_EL1 encoding as reserved (with
the required RAZ behaviour for unassigned system registers in the ID
register encoding space). Newer architecture versions start to
define fields in this ID register, so define the appropriate
constants and implement it as an ID register backed by a field in
cpu->isar. Since none of our CPUs set that isar field to non-zero,
there is no behavioural change here (other than the name exposed to
the user via the gdbstub), but this paves the way for implementing
the new features that use fields in this register.
The fields here are the ones documented in rev L.b of the Arm ARM.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index ad571e2..602f6a8 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -277,6 +277,11 @@
FIELD(ID_AA64PFR1, DF2, 56, 4)
FIELD(ID_AA64PFR1, PFAR, 60, 4)
+FIELD(ID_AA64PFR2, MTEPERM, 0, 4)
+FIELD(ID_AA64PFR2, MTESTOREONLY, 4, 4)
+FIELD(ID_AA64PFR2, MTEFAR, 8, 4)
+FIELD(ID_AA64PFR2, FPMR, 32, 4)
+
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
FIELD(ID_AA64MMFR0, BIGEND, 8, 4)
diff --git a/target/arm/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc
index f48a9da..2bb2861 100644
--- a/target/arm/cpu-sysregs.h.inc
+++ b/target/arm/cpu-sysregs.h.inc
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
DEF(ID_AA64PFR0_EL1, 3, 0, 0, 4, 0)
DEF(ID_AA64PFR1_EL1, 3, 0, 0, 4, 1)
+DEF(ID_AA64PFR2_EL1, 3, 0, 0, 4, 2)
DEF(ID_AA64SMFR0_EL1, 3, 0, 0, 4, 5)
DEF(ID_AA64DFR0_EL1, 3, 0, 0, 5, 0)
DEF(ID_AA64DFR1_EL1, 3, 0, 0, 5, 1)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a18d920..aa730ad 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6109,11 +6109,11 @@
.access = PL1_R, .type = ARM_CP_CONST,
.accessfn = access_aa64_tid3,
.resetvalue = GET_IDREG(isar, ID_AA64PFR1)},
- { .name = "ID_AA64PFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
+ { .name = "ID_AA64PFR2_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 2,
.access = PL1_R, .type = ARM_CP_CONST,
.accessfn = access_aa64_tid3,
- .resetvalue = 0 },
+ .resetvalue = GET_IDREG(isar, ID_AA64PFR2)},
{ .name = "ID_AA64PFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 3,
.access = PL1_R, .type = ARM_CP_CONST,
@@ -6341,6 +6341,8 @@
R_ID_AA64PFR1_SSBS_MASK |
R_ID_AA64PFR1_MTE_MASK |
R_ID_AA64PFR1_SME_MASK },
+ { .name = "ID_AA64PFR2_EL1",
+ .exported_bits = 0 },
{ .name = "ID_AA64PFR*_EL1_RESERVED",
.is_glob = true },
{ .name = "ID_AA64ZFR0_EL1",
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index 8b467b3..0658a99 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -744,6 +744,7 @@
} regs[] = {
{ HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.idregs[ID_AA64PFR0_EL1_IDX] },
{ HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.idregs[ID_AA64PFR1_EL1_IDX] },
+ /* Add ID_AA64PFR2_EL1 here when HVF supports it */
{ HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.idregs[ID_AA64DFR0_EL1_IDX] },
{ HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.idregs[ID_AA64DFR1_EL1_IDX] },
{ HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.idregs[ID_AA64ISAR0_EL1_IDX] },
diff --git a/target/arm/hvf/sysreg.c.inc b/target/arm/hvf/sysreg.c.inc
index f2276d5..067a860 100644
--- a/target/arm/hvf/sysreg.c.inc
+++ b/target/arm/hvf/sysreg.c.inc
@@ -92,6 +92,7 @@
#endif
DEF_SYSREG(HV_SYS_REG_ID_AA64PFR1_EL1, 3, 0, 0, 4, 1)
+/* Add ID_AA64PFR2_EL1 here when HVF supports it */
DEF_SYSREG(HV_SYS_REG_ID_AA64DFR0_EL1, 3, 0, 0, 5, 0)
DEF_SYSREG(HV_SYS_REG_ID_AA64DFR1_EL1, 3, 0, 0, 5, 1)
DEF_SYSREG(HV_SYS_REG_ID_AA64ISAR0_EL1, 3, 0, 0, 6, 0)
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 5a75ff5..b8a1c07 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -324,6 +324,7 @@
err = 0;
} else {
err |= get_host_cpu_reg(fd, ahcf, ID_AA64PFR1_EL1_IDX);
+ err |= get_host_cpu_reg(fd, ahcf, ID_AA64PFR2_EL1_IDX);
err |= get_host_cpu_reg(fd, ahcf, ID_AA64SMFR0_EL1_IDX);
err |= get_host_cpu_reg(fd, ahcf, ID_AA64DFR0_EL1_IDX);
err |= get_host_cpu_reg(fd, ahcf, ID_AA64DFR1_EL1_IDX);