qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model
@ 2024-10-25 10:17 Eric Auger
  2024-10-25 10:17 ` [RFC 01/21] kvm: kvm_get_writable_id_regs Eric Auger
                   ` (22 more replies)
  0 siblings, 23 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

This RFC series introduces a KVM host "custom" model.

Since v6.7 kernel, KVM/arm allows the userspace to overwrite the values
of a subset of ID regs. The list of writable fields continues to grow.
The feature ID range is defined as the AArch64 System register space
with op0==3, op1=={0, 1, 3}, CRn==0, CRm=={0-7}, op2=={0-7}.

The custom model uses this capability and allows to tune the host
passthrough model by overriding some of the host passthrough ID regs.

The end goal is to get more flexibility when migrating guests
between different machines. We would like the upper software layer
to be able detect how tunable the vpcu is on both source and destination
and accordingly define a customized KVM host model that can fit
both ends. With the legacy host passthrough model, this migration
use case would fail.

QEMU queries the host kernel to get the list of writable ID reg
fields and expose all the writable fields as uint64 properties. Those
are named "SYSREG_<REG>_<FIELD>". REG and FIELD names are those
described in ARM ARM Reference manual and linux arch/arm64/tools/sysreg.
Some awk scriptsintroduced in the series help parsing the sysreg file and
generate some code. those scripts are used in a similar way as
scripts/update-linux-headers.sh.  In case the ABI gets broken, it is
still possible to manually edit the generated code. However it is
globally expected the REG and FIELD names are stable.

The list of SYSREG_ID properties can be retrieved through the qmp
monitor using query-cpu-model-expansion [2].

The first part of the series mostly consists in migrating id reg
storage from named fields in ARMISARegisters to anonymous index
ordered storage in an IdRegMap struct array. The goal is to have
a generic way to store all id registers, also compatible with the
way we retrieve their writable capability at kernel level through
the KVM_ARM_GET_REG_WRITABLE_MASKS ioctl. Having named fields
prevented us from getting this scalability/genericity. Although the
change is invasive  it is quite straightforward and should be easy
to be reviewed.

Then the bulk of the job is to retrieve the writable ID fields and
match them against a "human readable" description of those fields.
We use awk scripts, derived from kernel arch/arm64/tools/gen-sysreg.awk
(so all the credit to Mark Rutland) that populates a data structure
which describes all the ID regs in sysreg and their fields. We match
writable ID reg fields with those latter and dynamically create a
uint64 property.

Then we need to extend the list of id regs read from the host
so that we get a chance to let their value overriden and write them
back into KVM .

This expectation is that this custom KVM host model can prepare for
the advent of named models. Introducing named models with reduced
and explicitly defined features is the next step.

Obviously this series is not able to cope with non writable ID regs.
For instance the problematic of MIDR/REVIDR setting is not handled
at the moment.

Connie & Eric

This series can be found at:
https://github.com/eauger/qemu/tree/custom-cpu-model-rfc

TESTS:
- with few IDREG fields that can be easily examined from guest
  userspace:
  -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0,SYSREG_ID_AA64ISAR1_EL1_DPB=0x0
- migration between custom models
- TCG A57 non regressions. Light testing for TCG though. Deep
  review may detect some mistakes when migrating between named fields
  and IDRegMap storage
- light testing of introspection. Testing a given writable ID field
  value with query-cpu-model-expansion is not supported yet.

TODO/QUESTIONS:
- Some idreg named fields are not yet migrated to an array storage.
  some of them are not in isar struct either. Maybe we could have
  handled TCG and KVM separately and it may turn out that this
  conversion is unneeded. So as it is quite cumbersome I prefered
  to keep it for a later stage.
- the custom model does not come with legacy host properties
  such as SVE, MTE, expecially those that induce some KVM
  settings. This needs to be fixed.
- The custom model and its exposed properties depend on the host
  capabilities. More and more IDREG become writable meaning that
  the custom model gains more properties over the time and it is
  host linux dependent. At the moment there is no versioning in
  place. By default the custom model is a host passthrough model
  (besides the legacy functions). So if the end-user tries to set
  a field that is not writable from a kernel pov, it will fail.
  Nevertheless a versionned custom model could constrain the props
  exposed, independently on the host linux capabilities.
- the QEMU layer does not take care of IDREG field value consistency.
  The kernel neither. I imagine this could be the role of the upper
  layer to implement a vcpu profile that makes sure settings are
  consistent. Here we come to "named" models. What should they look
  like on ARM?
- Implementation details:
  -  it seems there are a lot of duplications in
  the code. ID regs are described in different manners, with different
  data structs, for TCG, now for KVM.
  - The IdRegMap->regs is sparsely populated. Maybe a better data
  struct could be used, although this is the one chosen for the kernel
  uapi.

References:

[1] [PATCH v12 00/11] Support writable CPU ID registers from userspace
https://lore.kernel.org/all/20230609190054.1542113-1-oliver.upton@linux.dev/

[2]
qemu-system-aarch64 -qmp unix:/home/augere/TEST/QEMU/qmp-sock,server,nowait -M virt --enable-kvm -cpu custom
scripts/qmp/qmp-shell /home/augere/TEST/QEMU/qmp-sock
Welcome to the QMP low-level shell!
Connected to QEMU 9.0.50
(QEMU) query-cpu-model-expansion type=full model={"name":"custom"}

[3]
KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES
KVM_ARM_GET_REG_WRITABLE_MASKS
Documentation/virt/kvm/api.rst

[4] linux "sysreg" file
linux/arch/arm64/tools/sysreg and gen-sysreg.awk
./tools/include/generated/asm/sysreg-defs.h


Cornelia Huck (4):
  kvm: kvm_get_writable_id_regs
  virt: Allow custom vcpu model in arm virt
  arm-qmp-cmds: introspection for custom model
  arm/cpu-features: Document custom vcpu model

Eric Auger (17):
  arm/cpu: Add sysreg definitions in cpu-sysegs.h
  arm/cpu: Store aa64isar0 into the idregs arrays
  arm/cpu: Store aa64isar1/2 into the idregs array
  arm/cpu: Store aa64drf0/1 into the idregs array
  arm/cpu: Store aa64mmfr0-3 into the idregs array
  arm/cpu: Store aa64drf0/1 into the idregs array
  arm/cpu: Store aa64smfr0 into the idregs array
  arm/cpu: Store id_isar0-7 into the idregs array
  arm/cpu: Store id_mfr0/1 into the idregs array
  arm/cpu: Store id_dfr0/1 into the idregs array
  arm/cpu: Store id_mmfr0-5 into the idregs array
  arm/cpu: Add infra to handle generated ID register definitions
  arm/cpu: Add sysreg generation scripts
  arm/cpu: Add generated files
  arm/kvm: Allow reading all the writable ID registers
  arm/kvm: write back modified ID regs to KVM
  arm/cpu: Introduce a customizable kvm host cpu model

 docs/system/arm/cpu-features.rst      |  55 ++-
 target/arm/cpu-custom.h               |  58 +++
 target/arm/cpu-features.h             | 307 ++++++------
 target/arm/cpu-sysregs.h              | 152 ++++++
 target/arm/cpu.h                      | 120 +++--
 target/arm/internals.h                |   6 +-
 target/arm/kvm_arm.h                  |  16 +-
 hw/arm/virt.c                         |   3 +
 hw/intc/armv7m_nvic.c                 |  27 +-
 target/arm/arm-qmp-cmds.c             |  56 ++-
 target/arm/cpu-sysreg-properties.c    | 682 ++++++++++++++++++++++++++
 target/arm/cpu.c                      | 124 +++--
 target/arm/cpu64.c                    | 265 +++++++---
 target/arm/helper.c                   |  68 +--
 target/arm/kvm.c                      | 253 +++++++---
 target/arm/ptw.c                      |   6 +-
 target/arm/tcg/cpu-v7m.c              | 174 +++----
 target/arm/tcg/cpu32.c                | 320 ++++++------
 target/arm/tcg/cpu64.c                | 460 ++++++++---------
 scripts/gen-cpu-sysreg-properties.awk | 325 ++++++++++++
 scripts/gen-cpu-sysregs-header.awk    |  47 ++
 scripts/update-aarch64-sysreg-code.sh |  27 +
 target/arm/meson.build                |   1 +
 target/arm/trace-events               |   8 +
 24 files changed, 2646 insertions(+), 914 deletions(-)
 create mode 100644 target/arm/cpu-custom.h
 create mode 100644 target/arm/cpu-sysregs.h
 create mode 100644 target/arm/cpu-sysreg-properties.c
 create mode 100755 scripts/gen-cpu-sysreg-properties.awk
 create mode 100755 scripts/gen-cpu-sysregs-header.awk
 create mode 100755 scripts/update-aarch64-sysreg-code.sh

-- 
2.41.0



^ permalink raw reply	[flat|nested] 72+ messages in thread

* [RFC 01/21] kvm: kvm_get_writable_id_regs
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 02/21] arm/cpu: Add sysreg definitions in cpu-sysegs.h Eric Auger
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

From: Cornelia Huck <cohuck@redhat.com>

Add an helper to retrieve the writable id reg bitmask. The
status of the query is stored in the CPU struct so that an
an error, if any, can be reported on vcpu realize().

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 target/arm/cpu.h     | 19 +++++++++++++++++++
 target/arm/kvm_arm.h |  7 +++++++
 target/arm/kvm.c     | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index d8eb986a04..1493b35d99 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -821,6 +821,19 @@ typedef struct {
     uint32_t map, init, supported;
 } ARMVQMap;
 
+typedef enum ARMIdRegsState {
+    WRITABLE_ID_REGS_UNKNOWN,
+    WRITABLE_ID_REGS_NOT_DISCOVERABLE,
+    WRITABLE_ID_REGS_FAILED,
+    WRITABLE_ID_REGS_AVAIL,
+} ARMIdRegsState;
+
+#define NR_ID_REGS (3 * 8 * 8)
+
+typedef struct IdRegMap {
+    uint64_t regs[NR_ID_REGS];
+} IdRegMap;
+
 /**
  * ARMCPU:
  * @env: #CPUARMState
@@ -960,6 +973,12 @@ struct ArchCPU {
      */
     bool host_cpu_probe_failed;
 
+    /*
+     * state of writable id regs query used to report an error, if any,
+     * on KVM custom vcpu model realize
+     */
+    ARMIdRegsState writable_id_regs;
+
     /* QOM property to indicate we should use the back-compat CNTFRQ default */
     bool backcompat_cntfrq;
 
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index cfaa0d9bc7..9868065277 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -214,6 +214,8 @@ void kvm_arm_pvtime_init(ARMCPU *cpu, uint64_t ipa);
 
 int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
 
+int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap);
+
 #else
 
 /*
@@ -235,6 +237,11 @@ static inline bool kvm_arm_sve_supported(void)
     return false;
 }
 
+static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap)
+{
+    return -ENOSYS;
+}
+
 /*
  * These functions should never actually be called without KVM support.
  */
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 70f79eda33..be98f8be18 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -47,6 +47,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 static bool cap_has_mp_state;
 static bool cap_has_inject_serror_esr;
 static bool cap_has_inject_ext_dabt;
+static int cap_writable_id_regs;
 
 /**
  * ARMHostCPUFeatures: information about the host CPU (identified
@@ -478,6 +479,37 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
     env->features = arm_host_cpu_features.features;
 }
 
+int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap)
+{
+    struct reg_mask_range range = {
+        .range = 0, /* up to now only a single range is supported */
+        .addr = (uint64_t)idregmap,
+    };
+    int ret;
+
+    if (!kvm_enabled()) {
+        cpu->writable_id_regs = WRITABLE_ID_REGS_NOT_DISCOVERABLE;
+        return -ENOSYS;
+    }
+
+    cap_writable_id_regs =
+        kvm_check_extension(kvm_state, KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES);
+
+    if (!cap_writable_id_regs ||
+        !(cap_writable_id_regs & (1 << KVM_ARM_FEATURE_ID_RANGE))) {
+        cpu->writable_id_regs = WRITABLE_ID_REGS_NOT_DISCOVERABLE;
+        return -ENOSYS;
+    }
+
+    ret = kvm_vm_ioctl(kvm_state, KVM_ARM_GET_REG_WRITABLE_MASKS, &range);
+    if (ret) {
+        cpu->writable_id_regs = WRITABLE_ID_REGS_FAILED;
+        return ret;
+     }
+    cpu->writable_id_regs = WRITABLE_ID_REGS_AVAIL;
+    return ret;
+}
+
 static bool kvm_no_adjvtime_get(Object *obj, Error **errp)
 {
     return !ARM_CPU(obj)->kvm_adjvtime;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 02/21] arm/cpu: Add sysreg definitions in cpu-sysegs.h
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
  2024-10-25 10:17 ` [RFC 01/21] kvm: kvm_get_writable_id_regs Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 03/21] arm/cpu: Store aa64isar0 into the idregs arrays Eric Auger
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

This new header contains macros that define aarch64 regiters.
In a subsequent patche, this will be replaced by a more exhaustive
version that will be generated from linux arch/arm64/tools/sysreg
file. Those macros are sufficient to migrate the storage of those
ID regs from named fields in isar struct to an array cell.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-sysregs.h | 42 +++++++++++++++++++++++++++++++
 target/arm/cpu.h         | 54 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+)
 create mode 100644 target/arm/cpu-sysregs.h

diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h
new file mode 100644
index 0000000000..f4b63a3af7
--- /dev/null
+++ b/target/arm/cpu-sysregs.h
@@ -0,0 +1,42 @@
+#ifndef ARM_CPU_SYSREGS_H
+#define ARM_CPU_SYSREGS_H
+
+/* to be generated */
+
+#define SYS_ID_AA64PFR0_EL1                             sys_reg(3, 0, 0, 4, 0)
+#define SYS_ID_AA64PFR1_EL1                             sys_reg(3, 0, 0, 4, 1)
+#define SYS_ID_AA64SMFR0_EL1                            sys_reg(3, 0, 0, 4, 5)
+#define SYS_ID_AA64DFR0_EL1                             sys_reg(3, 0, 0, 5, 0)
+#define SYS_ID_AA64DFR1_EL1                             sys_reg(3, 0, 0, 5, 1)
+#define SYS_ID_AA64ISAR0_EL1                            sys_reg(3, 0, 0, 6, 0)
+#define SYS_ID_AA64ISAR1_EL1                            sys_reg(3, 0, 0, 6, 1)
+#define SYS_ID_AA64ISAR2_EL1                            sys_reg(3, 0, 0, 6, 2)
+#define SYS_ID_AA64MMFR0_EL1                            sys_reg(3, 0, 0, 7, 0)
+#define SYS_ID_AA64MMFR1_EL1                            sys_reg(3, 0, 0, 7, 1)
+#define SYS_ID_AA64MMFR2_EL1                            sys_reg(3, 0, 0, 7, 2)
+#define SYS_ID_AA64MMFR3_EL1                            sys_reg(3, 0, 0, 7, 3)
+
+#define SYS_ID_PFR0_EL1                                 sys_reg(3, 0, 0, 1, 0)
+#define SYS_ID_PFR1_EL1                                 sys_reg(3, 0, 0, 1, 1)
+#define SYS_ID_DFR0_EL1                                 sys_reg(3, 0, 0, 1, 2)
+#define SYS_ID_MMFR0_EL1                                sys_reg(3, 0, 0, 1, 4)
+#define SYS_ID_MMFR1_EL1                                sys_reg(3, 0, 0, 1, 5)
+#define SYS_ID_MMFR2_EL1                                sys_reg(3, 0, 0, 1, 6)
+#define SYS_ID_MMFR3_EL1                                sys_reg(3, 0, 0, 1, 7)
+#define SYS_ID_ISAR0_EL1                                sys_reg(3, 0, 0, 2, 0)
+#define SYS_ID_ISAR1_EL1                                sys_reg(3, 0, 0, 2, 1)
+#define SYS_ID_ISAR2_EL1                                sys_reg(3, 0, 0, 2, 2)
+#define SYS_ID_ISAR3_EL1                                sys_reg(3, 0, 0, 2, 3)
+#define SYS_ID_ISAR4_EL1                                sys_reg(3, 0, 0, 2, 4)
+#define SYS_ID_ISAR5_EL1                                sys_reg(3, 0, 0, 2, 5)
+#define SYS_ID_MMFR4_EL1                                sys_reg(3, 0, 0, 2, 6)
+#define SYS_ID_ISAR6_EL1                                sys_reg(3, 0, 0, 2, 7)
+#define SYS_MVFR0_EL1                                   sys_reg(3, 0, 0, 3, 0)
+#define SYS_MVFR1_EL1                                   sys_reg(3, 0, 0, 3, 1)
+#define SYS_MVFR2_EL1                                   sys_reg(3, 0, 0, 3, 2)
+#define SYS_ID_PFR2_EL1                                 sys_reg(3, 0, 0, 3, 4)
+#define SYS_ID_DFR1_EL1                                 sys_reg(3, 0, 0, 3, 5)
+#define SYS_ID_MMFR5_EL1                                sys_reg(3, 0, 0, 3, 6)
+#define SYS_ID_AA64ZFR0_EL1                             sys_reg(3, 0, 0, 4, 4)
+
+#endif
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 1493b35d99..0491a482f0 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -144,6 +144,14 @@ typedef struct ARMGenericTimer {
     uint64_t ctl; /* Timer Control register */
 } ARMGenericTimer;
 
+typedef struct ARMSysReg {
+    int op0;
+    int op1;
+    int crn;
+    int crm;
+    int op2;
+} ARMSysReg;
+
 /* Define a maximum sized vector register.
  * For 32-bit, this is a 128-bit NEON/AdvSIMD register.
  * For 64-bit, this is a 2048-bit SVE register.
@@ -834,6 +842,51 @@ typedef struct IdRegMap {
     uint64_t regs[NR_ID_REGS];
 } IdRegMap;
 
+#define ARM_FEATURE_ID_RANGE_IDX(op0, op1, crn, crm, op2)               \
+        ({                                                              \
+                __u64 __op1 = (op1) & 3;                                \
+                __op1 -= (__op1 == 3);                                  \
+                (__op1 << 6 | ((crm) & 7) << 3 | (op2));                \
+        })
+
+static inline uint64_t _get_idreg(const IdRegMap *map, ARMSysReg sr)
+{
+    int index = ARM_FEATURE_ID_RANGE_IDX(sr.op0, sr.op1, sr.crn, sr.crm, sr.op2);
+
+    return map->regs[index];
+}
+
+static inline void _set_idreg(IdRegMap *map, ARMSysReg sr, uint64_t value)
+{
+    int index = ARM_FEATURE_ID_RANGE_IDX(sr.op0, sr.op1, sr.crn, sr.crm, sr.op2);
+
+    map->regs[index] = value;
+}
+
+/* REG is ID_XXX */
+#define FIELD_DP64_IDREG(MAP, REG, FIELD, VALUE)              \
+{                                                             \
+uint64_t regval = _get_idreg(MAP, SYS_ ## REG ## _EL1);       \
+regval = FIELD_DP64(regval, REG, FIELD, VALUE);               \
+_set_idreg(MAP, SYS_ ## REG ## _EL1, regval);                 \
+}
+
+#define FIELD_EX64_IDREG(MAP, REG, FIELD)                     \
+FIELD_EX64(_get_idreg(MAP, SYS_ ## REG ## _EL1), REG, FIELD)  \
+
+#define SET_IDREG(MAP, REG, VALUE)                            \
+_set_idreg(MAP, SYS_ ## REG ## _EL1, VALUE)
+
+#define GET_IDREG(MAP, REG)                                   \
+_get_idreg(MAP, SYS_ ## REG ## _EL1)
+
+static inline ARMSysReg sys_reg(int op0, int op1, int crn, int crm, int op2)
+{
+        ARMSysReg sr = {op0, op1, crn, crm, op2};
+
+        return sr;
+}
+
 /**
  * ARMCPU:
  * @env: #CPUARMState
@@ -1043,6 +1096,7 @@ struct ArchCPU {
         uint64_t id_aa64zfr0;
         uint64_t id_aa64smfr0;
         uint64_t reset_pmcr_el0;
+        IdRegMap idregs;
     } isar;
     uint64_t midr;
     uint32_t revidr;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 03/21] arm/cpu: Store aa64isar0 into the idregs arrays
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
  2024-10-25 10:17 ` [RFC 01/21] kvm: kvm_get_writable_id_regs Eric Auger
  2024-10-25 10:17 ` [RFC 02/21] arm/cpu: Add sysreg definitions in cpu-sysegs.h Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 04/21] arm/cpu: Store aa64isar1/2 into the idregs array Eric Auger
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-features.h | 57 ++++++++++++++++++++-------------------
 target/arm/cpu.h          |  2 --
 target/arm/cpu.c          | 13 ++++-----
 target/arm/cpu64.c        |  8 +++---
 target/arm/helper.c       |  6 +++--
 target/arm/kvm.c          | 20 +++++++++++---
 target/arm/tcg/cpu64.c    | 44 ++++++++++++++++++------------
 7 files changed, 86 insertions(+), 64 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index c59ca104fe..4eb29d205c 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -21,6 +21,7 @@
 #define TARGET_ARM_FEATURES_H
 
 #include "hw/registerfields.h"
+#include "cpu-sysregs.h"
 
 /*
  * Naming convention for isar_feature functions:
@@ -375,92 +376,92 @@ static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id)
  */
 static inline bool isar_feature_aa64_aes(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, AES) != 0;
 }
 
 static inline bool isar_feature_aa64_pmull(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) > 1;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, AES) > 1;
 }
 
 static inline bool isar_feature_aa64_sha1(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA1) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, SHA1) != 0;
 }
 
 static inline bool isar_feature_aa64_sha256(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, SHA2) != 0;
 }
 
 static inline bool isar_feature_aa64_sha512(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) > 1;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, SHA2) > 1;
 }
 
 static inline bool isar_feature_aa64_crc32(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, CRC32) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, CRC32) != 0;
 }
 
 static inline bool isar_feature_aa64_atomics(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, ATOMIC) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, ATOMIC) != 0;
 }
 
 static inline bool isar_feature_aa64_rdm(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RDM) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, RDM) != 0;
 }
 
 static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA3) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, SHA3) != 0;
 }
 
 static inline bool isar_feature_aa64_sm3(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM3) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, SM3) != 0;
 }
 
 static inline bool isar_feature_aa64_sm4(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM4) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, SM4) != 0;
 }
 
 static inline bool isar_feature_aa64_dp(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, DP) != 0;
 }
 
 static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, FHM) != 0;
 }
 
 static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, TS) != 0;
 }
 
 static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, TS) >= 2;
 }
 
 static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RNDR) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, RNDR) != 0;
 }
 
 static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, TLB) == 2;
 }
 
 static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR0, TLB) != 0;
 }
 
 static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
@@ -901,52 +902,52 @@ static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ZFR0, SVEVER) != 0;
 }
 
 static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ZFR0, AES) != 0;
 }
 
 static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ZFR0, AES) >= 2;
 }
 
 static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BITPERM) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ZFR0, BITPERM) != 0;
 }
 
 static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BFLOAT16) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ZFR0, BFLOAT16) != 0;
 }
 
 static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SHA3) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ZFR0, SHA3) != 0;
 }
 
 static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SM4) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ZFR0, SM4) != 0;
 }
 
 static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, I8MM) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ZFR0, I8MM) != 0;
 }
 
 static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F32MM) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ZFR0, F32MM) != 0;
 }
 
 static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F64MM) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ZFR0, F64MM) != 0;
 }
 
 static inline bool isar_feature_aa64_sme_f64f64(const ARMISARegisters *id)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0491a482f0..aee8dfe439 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1082,7 +1082,6 @@ struct ArchCPU {
         uint32_t dbgdidr;
         uint32_t dbgdevid;
         uint32_t dbgdevid1;
-        uint64_t id_aa64isar0;
         uint64_t id_aa64isar1;
         uint64_t id_aa64isar2;
         uint64_t id_aa64pfr0;
@@ -1093,7 +1092,6 @@ struct ArchCPU {
         uint64_t id_aa64mmfr3;
         uint64_t id_aa64dfr0;
         uint64_t id_aa64dfr1;
-        uint64_t id_aa64zfr0;
         uint64_t id_aa64smfr0;
         uint64_t reset_pmcr_el0;
         IdRegMap idregs;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 14d4eca127..9521eed586 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1967,6 +1967,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     CPUState *cs = CPU(dev);
     ARMCPU *cpu = ARM_CPU(dev);
+    IdRegMap *idregs = &cpu->isar.idregs;
     ARMCPUClass *acc = ARM_CPU_GET_CLASS(dev);
     CPUARMState *env = &cpu->env;
     Error *local_err = NULL;
@@ -2168,7 +2169,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
 
         unset_feature(env, ARM_FEATURE_NEON);
 
-        t = cpu->isar.id_aa64isar0;
+        t = GET_IDREG(idregs, ID_AA64ISAR0);
         t = FIELD_DP64(t, ID_AA64ISAR0, AES, 0);
         t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 0);
         t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 0);
@@ -2176,7 +2177,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 0);
         t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 0);
         t = FIELD_DP64(t, ID_AA64ISAR0, DP, 0);
-        cpu->isar.id_aa64isar0 = t;
+        SET_IDREG(idregs, ID_AA64ISAR0, t);
 
         t = cpu->isar.id_aa64isar1;
         t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0);
@@ -2221,13 +2222,9 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         uint64_t t;
         uint32_t u;
 
-        t = cpu->isar.id_aa64isar0;
-        t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 0);
-        cpu->isar.id_aa64isar0 = t;
+        FIELD_DP64_IDREG(idregs, ID_AA64ISAR0, FHM, 0);
 
-        t = cpu->isar.id_aa64isar1;
-        t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 0);
-        cpu->isar.id_aa64isar1 = t;
+        FIELD_DP64_IDREG(idregs, ID_AA64ISAR1, FRINTTS, 0);
 
         u = cpu->isar.mvfr0;
         u = FIELD_DP32(u, MVFR0, SIMDREG, 0);
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 262a1d6c0b..1451b3e1b3 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -113,7 +113,7 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
              * SVE is disabled and so are all vector lengths.  Good.
              * Disable all SVE extensions as well.
              */
-            cpu->isar.id_aa64zfr0 = 0;
+            SET_IDREG(&cpu->isar.idregs, ID_AA64ZFR0, 0);
             return;
         }
 
@@ -598,6 +598,7 @@ void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp)
 static void aarch64_a57_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,cortex-a57";
     set_feature(&cpu->env, ARM_FEATURE_V8);
@@ -635,7 +636,7 @@ static void aarch64_a57_initfn(Object *obj)
     cpu->isar.id_isar6 = 0;
     cpu->isar.id_aa64pfr0 = 0x00002222;
     cpu->isar.id_aa64dfr0 = 0x10305106;
-    cpu->isar.id_aa64isar0 = 0x00011120;
+    SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     cpu->isar.id_aa64mmfr0 = 0x00001124;
     cpu->isar.dbgdidr = 0x3516d000;
     cpu->isar.dbgdevid = 0x01110f13;
@@ -656,6 +657,7 @@ static void aarch64_a57_initfn(Object *obj)
 static void aarch64_a53_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,cortex-a53";
     set_feature(&cpu->env, ARM_FEATURE_V8);
@@ -693,7 +695,7 @@ static void aarch64_a53_initfn(Object *obj)
     cpu->isar.id_isar6 = 0;
     cpu->isar.id_aa64pfr0 = 0x00002222;
     cpu->isar.id_aa64dfr0 = 0x10305106;
-    cpu->isar.id_aa64isar0 = 0x00011120;
+    SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
     cpu->isar.dbgdidr = 0x3516d000;
     cpu->isar.dbgdevid = 0x00110f13;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index ce31957235..8eae775d87 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8702,6 +8702,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 {
     /* Register all the coprocessor registers based on feature bits */
     CPUARMState *env = &cpu->env;
+    IdRegMap *idregs = &cpu->isar.idregs;
+
     if (arm_feature(env, ARM_FEATURE_M)) {
         /* M profile has no coprocessor registers */
         return;
@@ -8893,7 +8895,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 4,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64zfr0 },
+              .resetvalue = GET_IDREG(idregs, ID_AA64ZFR0)},
             { .name = "ID_AA64SMFR0_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5,
               .access = PL1_R, .type = ARM_CP_CONST,
@@ -8953,7 +8955,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 0,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64isar0 },
+              .resetvalue = GET_IDREG(idregs, ID_AA64ISAR0)},
             { .name = "ID_AA64ISAR1_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1,
               .access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index be98f8be18..7a2087c195 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -26,6 +26,7 @@
 #include "sysemu/kvm_int.h"
 #include "kvm_arm.h"
 #include "cpu.h"
+#include "cpu-sysregs.h"
 #include "trace.h"
 #include "internals.h"
 #include "hw/pci/pci.h"
@@ -230,6 +231,18 @@ static bool kvm_arm_pauth_supported(void)
             kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_GENERIC));
 }
 
+/* read a 64b sysreg value and store it in the idregs */
+static int get_host_cpu_reg64(int fd, ARMHostCPUFeatures *ahcf, ARMSysReg sr)
+{
+    int index = KVM_ARM_FEATURE_ID_RANGE_IDX(sr.op0, sr.op1, sr.crn, sr.crm, sr.op2);
+    uint64_t *reg = &ahcf->isar.idregs.regs[index];
+    int ret;
+
+    ret = read_sys_reg64(fd, reg,
+                         ARM64_SYS_REG(sr.op0, sr.op1, sr.crn, sr.crm, sr.op2));
+    return ret;
+}
+
 static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
 {
     /* Identify the feature bits corresponding to the host CPU, and
@@ -289,6 +302,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
 
     ahcf->target = init.target;
     ahcf->dtb_compatible = "arm,arm-v8";
+    int fd = fdarray[2];
 
     err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0,
                          ARM64_SYS_REG(3, 0, 0, 4, 0));
@@ -320,8 +334,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
                               ARM64_SYS_REG(3, 0, 0, 5, 0));
         err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1,
                               ARM64_SYS_REG(3, 0, 0, 5, 1));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0,
-                              ARM64_SYS_REG(3, 0, 0, 6, 0));
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ISAR0_EL1);
         err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1,
                               ARM64_SYS_REG(3, 0, 0, 6, 1));
         err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar2,
@@ -430,8 +443,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
              * enabled SVE support, which resulted in an error rather than RAZ.
              * So only read the register if we set KVM_ARM_VCPU_SVE above.
              */
-            err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0,
-                                  ARM64_SYS_REG(3, 0, 0, 4, 4));
+            err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ZFR0_EL1);
         }
     }
 
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index fe232eb306..1b25ca4382 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -58,6 +58,7 @@ static uint64_t make_ccsidr64(unsigned assoc, unsigned linesize,
 static void aarch64_a35_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,cortex-a35";
     set_feature(&cpu->env, ARM_FEATURE_V8);
@@ -92,7 +93,7 @@ static void aarch64_a35_initfn(Object *obj)
     cpu->isar.id_aa64pfr1 = 0;
     cpu->isar.id_aa64dfr0 = 0x10305106;
     cpu->isar.id_aa64dfr1 = 0;
-    cpu->isar.id_aa64isar0 = 0x00011120;
+    SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     cpu->isar.id_aa64isar1 = 0;
     cpu->isar.id_aa64mmfr0 = 0x00101122;
     cpu->isar.id_aa64mmfr1 = 0;
@@ -227,6 +228,7 @@ static Property arm_cpu_lpa2_property =
 static void aarch64_a55_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,cortex-a55";
     set_feature(&cpu->env, ARM_FEATURE_V8);
@@ -244,7 +246,7 @@ static void aarch64_a55_initfn(Object *obj)
     cpu->ctr = 0x84448004; /* L1Ip = VIPT */
     cpu->dcz_blocksize = 4; /* 64 bytes */
     cpu->isar.id_aa64dfr0  = 0x0000000010305408ull;
-    cpu->isar.id_aa64isar0 = 0x0000100010211120ull;
+    SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
     cpu->isar.id_aa64isar1 = 0x0000000000100001ull;
     cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
@@ -296,6 +298,7 @@ static void aarch64_a55_initfn(Object *obj)
 static void aarch64_a72_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,cortex-a72";
     set_feature(&cpu->env, ARM_FEATURE_V8);
@@ -331,7 +334,7 @@ static void aarch64_a72_initfn(Object *obj)
     cpu->isar.id_isar5 = 0x00011121;
     cpu->isar.id_aa64pfr0 = 0x00002222;
     cpu->isar.id_aa64dfr0 = 0x10305106;
-    cpu->isar.id_aa64isar0 = 0x00011120;
+    SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     cpu->isar.id_aa64mmfr0 = 0x00001124;
     cpu->isar.dbgdidr = 0x3516d000;
     cpu->isar.dbgdevid = 0x01110f13;
@@ -352,6 +355,7 @@ static void aarch64_a72_initfn(Object *obj)
 static void aarch64_a76_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,cortex-a76";
     set_feature(&cpu->env, ARM_FEATURE_V8);
@@ -369,7 +373,7 @@ static void aarch64_a76_initfn(Object *obj)
     cpu->ctr = 0x8444C004;
     cpu->dcz_blocksize = 4;
     cpu->isar.id_aa64dfr0  = 0x0000000010305408ull;
-    cpu->isar.id_aa64isar0 = 0x0000100010211120ull;
+    SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
     cpu->isar.id_aa64isar1 = 0x0000000000100001ull;
     cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
@@ -422,6 +426,7 @@ static void aarch64_a76_initfn(Object *obj)
 static void aarch64_a64fx_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,a64fx";
     set_feature(&cpu->env, ARM_FEATURE_V8);
@@ -445,9 +450,9 @@ static void aarch64_a64fx_initfn(Object *obj)
     cpu->isar.id_aa64mmfr0 = 0x0000000000001122;
     cpu->isar.id_aa64mmfr1 = 0x0000000011212100;
     cpu->isar.id_aa64mmfr2 = 0x0000000000001011;
-    cpu->isar.id_aa64isar0 = 0x0000000010211120;
+    SET_IDREG(idregs, ID_AA64ISAR0, 0x0000000010211120);
     cpu->isar.id_aa64isar1 = 0x0000000000010001;
-    cpu->isar.id_aa64zfr0 = 0x0000000000000000;
+    SET_IDREG(idregs, ID_AA64ZFR0, 0x0000000000000000);
     cpu->clidr = 0x0000000080000023;
     cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */
     cpu->ccsidr[1] = 0x2007e01c; /* 64KB L1 icache */
@@ -592,6 +597,7 @@ static void define_neoverse_v1_cp_reginfo(ARMCPU *cpu)
 static void aarch64_neoverse_n1_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,neoverse-n1";
     set_feature(&cpu->env, ARM_FEATURE_V8);
@@ -609,7 +615,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
     cpu->ctr = 0x8444c004;
     cpu->dcz_blocksize = 4;
     cpu->isar.id_aa64dfr0  = 0x0000000110305408ull;
-    cpu->isar.id_aa64isar0 = 0x0000100010211120ull;
+    SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
     cpu->isar.id_aa64isar1 = 0x0000000000100001ull;
     cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
@@ -664,6 +670,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
 static void aarch64_neoverse_v1_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,neoverse-v1";
     set_feature(&cpu->env, ARM_FEATURE_V8);
@@ -684,7 +691,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
     cpu->id_aa64afr1 = 0x00000000;
     cpu->isar.id_aa64dfr0  = 0x000001f210305519ull;
     cpu->isar.id_aa64dfr1 = 0x00000000;
-    cpu->isar.id_aa64isar0 = 0x1011111110212120ull; /* with FEAT_RNG */
+    SET_IDREG(idregs, ID_AA64ISAR0, 0x1011111110212120ull); /* with FEAT_RNG */
     cpu->isar.id_aa64isar1 = 0x0111000001211032ull;
     cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
@@ -740,7 +747,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
     cpu->isar.mvfr2 = 0x00000043;
 
     /* From 3.7.5 ID_AA64ZFR0_EL1 */
-    cpu->isar.id_aa64zfr0 = 0x0000100000100000;
+    SET_IDREG(idregs, ID_AA64ZFR0, 0x0000100000100000);
     cpu->sve_vq.supported = (1 << 0)  /* 128bit */
                             | (1 << 1);  /* 256bit */
 
@@ -887,6 +894,7 @@ static const ARMCPRegInfo cortex_a710_cp_reginfo[] = {
 static void aarch64_a710_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,cortex-a710";
     set_feature(&cpu->env, ARM_FEATURE_V8);
@@ -924,12 +932,12 @@ static void aarch64_a710_initfn(Object *obj)
     cpu->isar.id_pfr2  = 0x00000011;
     cpu->isar.id_aa64pfr0  = 0x1201111120111112ull; /* GIC filled in later */
     cpu->isar.id_aa64pfr1  = 0x0000000000000221ull;
-    cpu->isar.id_aa64zfr0  = 0x0000110100110021ull; /* with Crypto */
+    SET_IDREG(idregs, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */
     cpu->isar.id_aa64dfr0  = 0x000011f010305619ull;
     cpu->isar.id_aa64dfr1  = 0;
     cpu->id_aa64afr0       = 0;
     cpu->id_aa64afr1       = 0;
-    cpu->isar.id_aa64isar0 = 0x0221111110212120ull; /* with Crypto */
+    SET_IDREG(idregs, ID_AA64ISAR0, 0x0221111110212120ull); /* with Crypto */
     cpu->isar.id_aa64isar1 = 0x0010111101211052ull;
     cpu->isar.id_aa64mmfr0 = 0x0000022200101122ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
@@ -985,6 +993,7 @@ static const ARMCPRegInfo neoverse_n2_cp_reginfo[] = {
 static void aarch64_neoverse_n2_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,neoverse-n2";
     set_feature(&cpu->env, ARM_FEATURE_V8);
@@ -1022,12 +1031,12 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
     cpu->isar.id_pfr2  = 0x00000011;
     cpu->isar.id_aa64pfr0  = 0x1201111120111112ull; /* GIC filled in later */
     cpu->isar.id_aa64pfr1  = 0x0000000000000221ull;
-    cpu->isar.id_aa64zfr0  = 0x0000110100110021ull; /* with Crypto */
+    SET_IDREG(idregs, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */
     cpu->isar.id_aa64dfr0  = 0x000011f210305619ull;
     cpu->isar.id_aa64dfr1  = 0;
     cpu->id_aa64afr0       = 0;
     cpu->id_aa64afr1       = 0;
-    cpu->isar.id_aa64isar0 = 0x1221111110212120ull; /* with Crypto and FEAT_RNG */
+    SET_IDREG(idregs, ID_AA64ISAR0, 0x1221111110212120ull); /* with Crypto and FEAT_RNG */
     cpu->isar.id_aa64isar1 = 0x0011111101211052ull;
     cpu->isar.id_aa64mmfr0 = 0x0000022200101125ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
@@ -1083,6 +1092,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
 void aarch64_max_tcg_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
     uint64_t t;
     uint32_t u;
 
@@ -1133,7 +1143,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, CTR_EL0, DIC, 1);
     cpu->ctr = t;
 
-    t = cpu->isar.id_aa64isar0;
+    t = GET_IDREG(idregs, ID_AA64ISAR0);
     t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2);      /* FEAT_PMULL */
     t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1);     /* FEAT_SHA1 */
     t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2);     /* FEAT_SHA512 */
@@ -1148,7 +1158,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2);       /* FEAT_FlagM2 */
     t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2);      /* FEAT_TLBIRANGE */
     t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1);     /* FEAT_RNG */
-    cpu->isar.id_aa64isar0 = t;
+    SET_IDREG(idregs, ID_AA64ISAR0, t);
 
     t = cpu->isar.id_aa64isar1;
     t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2);      /* FEAT_DPB2 */
@@ -1240,7 +1250,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
     cpu->isar.id_aa64mmfr3 = t;
 
-    t = cpu->isar.id_aa64zfr0;
+    t = GET_IDREG(idregs, ID_AA64ZFR0);
     t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1);
     t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2);       /* FEAT_SVE_PMULL128 */
     t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1);   /* FEAT_SVE_BitPerm */
@@ -1250,7 +1260,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1);      /* FEAT_I8MM */
     t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1);     /* FEAT_F32MM */
     t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1);     /* FEAT_F64MM */
-    cpu->isar.id_aa64zfr0 = t;
+    SET_IDREG(idregs, ID_AA64ZFR0, t);
 
     t = cpu->isar.id_aa64dfr0;
     t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 10); /* FEAT_Debugv8p8 */
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 04/21] arm/cpu: Store aa64isar1/2 into the idregs array
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (2 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 03/21] arm/cpu: Store aa64isar0 into the idregs arrays Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 05/21] arm/cpu: Store aa64drf0/1 " Eric Auger
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-features.h | 38 +++++++++++++++++++-------------------
 target/arm/cpu.h          |  2 --
 target/arm/cpu.c          |  9 +++------
 target/arm/cpu64.c        |  9 +++++----
 target/arm/helper.c       |  4 ++--
 target/arm/kvm.c          |  6 ++----
 target/arm/tcg/cpu64.c    | 24 ++++++++++++------------
 7 files changed, 43 insertions(+), 49 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 4eb29d205c..de571b520f 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -466,12 +466,12 @@ static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, JSCVT) != 0;
 }
 
 static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, FCMA) != 0;
 }
 
 /*
@@ -495,9 +495,9 @@ isar_feature_pauth_feature(const ARMISARegisters *id)
      * Architecturally, only one of {APA,API,APA3} may be active (non-zero)
      * and the other two must be zero.  Thus we may avoid conditionals.
      */
-    return (FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) |
-            FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, API) |
-            FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3));
+    return (FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, APA) |
+            FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, API) |
+            FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR2, APA3));
 }
 
 static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id)
@@ -515,7 +515,7 @@ static inline bool isar_feature_aa64_pauth_qarma5(const ARMISARegisters *id)
      * Return true if pauth is enabled with the architected QARMA5 algorithm.
      * QEMU will always enable or disable both APA and GPA.
      */
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, APA) != 0;
 }
 
 static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id)
@@ -524,67 +524,67 @@ static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id)
      * Return true if pauth is enabled with the architected QARMA3 algorithm.
      * QEMU will always enable or disable both APA3 and GPA3.
      */
-    return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR2, APA3) != 0;
 }
 
 static inline bool isar_feature_aa64_sb(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, SB) != 0;
 }
 
 static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, SPECRES) != 0;
 }
 
 static inline bool isar_feature_aa64_frint(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, FRINTTS) != 0;
 }
 
 static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, DPB) != 0;
 }
 
 static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, DPB) >= 2;
 }
 
 static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, BF16) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, BF16) != 0;
 }
 
 static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, LRCPC) != 0;
 }
 
 static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, LRCPC) >= 2;
 }
 
 static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR1, I8MM) != 0;
 }
 
 static inline bool isar_feature_aa64_wfxt(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, WFXT) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR2, WFXT) >= 2;
 }
 
 static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR2, BC) != 0;
 }
 
 static inline bool isar_feature_aa64_mops(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS);
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64ISAR2, MOPS);
 }
 
 static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index aee8dfe439..87df224121 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1082,8 +1082,6 @@ struct ArchCPU {
         uint32_t dbgdidr;
         uint32_t dbgdevid;
         uint32_t dbgdevid1;
-        uint64_t id_aa64isar1;
-        uint64_t id_aa64isar2;
         uint64_t id_aa64pfr0;
         uint64_t id_aa64pfr1;
         uint64_t id_aa64mmfr0;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 9521eed586..a4b59b259c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2124,9 +2124,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         uint64_t t;
         uint32_t u;
 
-        t = cpu->isar.id_aa64isar1;
-        t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 0);
-        cpu->isar.id_aa64isar1 = t;
+        FIELD_DP64_IDREG(idregs, ID_AA64ISAR1, JSCVT, 0);
 
         t = cpu->isar.id_aa64pfr0;
         t = FIELD_DP64(t, ID_AA64PFR0, FP, 0xf);
@@ -2179,11 +2177,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         t = FIELD_DP64(t, ID_AA64ISAR0, DP, 0);
         SET_IDREG(idregs, ID_AA64ISAR0, t);
 
-        t = cpu->isar.id_aa64isar1;
+        t = GET_IDREG(idregs, ID_AA64ISAR1);
         t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0);
         t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 0);
         t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 0);
-        cpu->isar.id_aa64isar1 = t;
+        SET_IDREG(idregs, ID_AA64ISAR1, t);
 
         t = cpu->isar.id_aa64pfr0;
         t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 0xf);
@@ -2219,7 +2217,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
     }
 
     if (!cpu->has_neon && !cpu->has_vfp) {
-        uint64_t t;
         uint32_t u;
 
         FIELD_DP64_IDREG(idregs, ID_AA64ISAR0, FHM, 0);
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 1451b3e1b3..d16c7487ac 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -479,6 +479,7 @@ void aarch64_add_sme_properties(Object *obj)
 void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
 {
     ARMPauthFeature features = cpu_isar_feature(pauth_feature, cpu);
+    IdRegMap *idregs = &cpu->isar.idregs;
     uint64_t isar1, isar2;
 
     /*
@@ -489,13 +490,13 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
      *
      * Begin by disabling all fields.
      */
-    isar1 = cpu->isar.id_aa64isar1;
+    isar1 = GET_IDREG(idregs, ID_AA64ISAR1);
     isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, 0);
     isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 0);
     isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, 0);
     isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 0);
 
-    isar2 = cpu->isar.id_aa64isar2;
+    isar2 = GET_IDREG(idregs, ID_AA64ISAR2);
     isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, 0);
     isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 0);
 
@@ -542,8 +543,8 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
         }
     }
 
-    cpu->isar.id_aa64isar1 = isar1;
-    cpu->isar.id_aa64isar2 = isar2;
+    SET_IDREG(idregs, ID_AA64ISAR1, isar1);
+    SET_IDREG(idregs, ID_AA64ISAR2, isar2);
 }
 
 static Property arm_cpu_pauth_property =
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 8eae775d87..209b7c22b6 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8960,12 +8960,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64isar1 },
+              .resetvalue = GET_IDREG(idregs, ID_AA64ISAR1)},
             { .name = "ID_AA64ISAR2_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64isar2 },
+              .resetvalue = GET_IDREG(idregs, ID_AA64ISAR2)},
             { .name = "ID_AA64ISAR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 3,
               .access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 7a2087c195..c30dc53622 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -335,10 +335,8 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
         err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1,
                               ARM64_SYS_REG(3, 0, 0, 5, 1));
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ISAR0_EL1);
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1,
-                              ARM64_SYS_REG(3, 0, 0, 6, 1));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar2,
-                              ARM64_SYS_REG(3, 0, 0, 6, 2));
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ISAR1_EL1);
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ISAR2_EL1);
         err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0,
                               ARM64_SYS_REG(3, 0, 0, 7, 0));
         err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1,
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 1b25ca4382..7be63f21a1 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -94,7 +94,7 @@ static void aarch64_a35_initfn(Object *obj)
     cpu->isar.id_aa64dfr0 = 0x10305106;
     cpu->isar.id_aa64dfr1 = 0;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
-    cpu->isar.id_aa64isar1 = 0;
+    SET_IDREG(idregs, ID_AA64ISAR1, 0);
     cpu->isar.id_aa64mmfr0 = 0x00101122;
     cpu->isar.id_aa64mmfr1 = 0;
     cpu->clidr = 0x0a200023;
@@ -247,7 +247,7 @@ static void aarch64_a55_initfn(Object *obj)
     cpu->dcz_blocksize = 4; /* 64 bytes */
     cpu->isar.id_aa64dfr0  = 0x0000000010305408ull;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
-    cpu->isar.id_aa64isar1 = 0x0000000000100001ull;
+    SET_IDREG(idregs, ID_AA64ISAR1, 0x0000000000100001ull);
     cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
     cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
@@ -374,7 +374,7 @@ static void aarch64_a76_initfn(Object *obj)
     cpu->dcz_blocksize = 4;
     cpu->isar.id_aa64dfr0  = 0x0000000010305408ull;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
-    cpu->isar.id_aa64isar1 = 0x0000000000100001ull;
+    SET_IDREG(idregs, ID_AA64ISAR1, 0x0000000000100001ull);
     cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
     cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
@@ -451,7 +451,7 @@ static void aarch64_a64fx_initfn(Object *obj)
     cpu->isar.id_aa64mmfr1 = 0x0000000011212100;
     cpu->isar.id_aa64mmfr2 = 0x0000000000001011;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0000000010211120);
-    cpu->isar.id_aa64isar1 = 0x0000000000010001;
+    SET_IDREG(idregs, ID_AA64ISAR1, 0x0000000000010001);
     SET_IDREG(idregs, ID_AA64ZFR0, 0x0000000000000000);
     cpu->clidr = 0x0000000080000023;
     cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */
@@ -616,7 +616,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
     cpu->dcz_blocksize = 4;
     cpu->isar.id_aa64dfr0  = 0x0000000110305408ull;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
-    cpu->isar.id_aa64isar1 = 0x0000000000100001ull;
+    SET_IDREG(idregs, ID_AA64ISAR1, 0x0000000000100001ull);
     cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
     cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
@@ -692,7 +692,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
     cpu->isar.id_aa64dfr0  = 0x000001f210305519ull;
     cpu->isar.id_aa64dfr1 = 0x00000000;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x1011111110212120ull); /* with FEAT_RNG */
-    cpu->isar.id_aa64isar1 = 0x0111000001211032ull;
+    SET_IDREG(idregs, ID_AA64ISAR1, 0x0111000001211032ull);
     cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
     cpu->isar.id_aa64mmfr2 = 0x0220011102101011ull;
@@ -938,7 +938,7 @@ static void aarch64_a710_initfn(Object *obj)
     cpu->id_aa64afr0       = 0;
     cpu->id_aa64afr1       = 0;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0221111110212120ull); /* with Crypto */
-    cpu->isar.id_aa64isar1 = 0x0010111101211052ull;
+    SET_IDREG(idregs, ID_AA64ISAR1, 0x0010111101211052ull);
     cpu->isar.id_aa64mmfr0 = 0x0000022200101122ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
     cpu->isar.id_aa64mmfr2 = 0x1221011110101011ull;
@@ -1037,7 +1037,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
     cpu->id_aa64afr0       = 0;
     cpu->id_aa64afr1       = 0;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x1221111110212120ull); /* with Crypto and FEAT_RNG */
-    cpu->isar.id_aa64isar1 = 0x0011111101211052ull;
+    SET_IDREG(idregs, ID_AA64ISAR1, 0x0011111101211052ull);
     cpu->isar.id_aa64mmfr0 = 0x0000022200101125ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
     cpu->isar.id_aa64mmfr2 = 0x1221011112101011ull;
@@ -1160,7 +1160,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1);     /* FEAT_RNG */
     SET_IDREG(idregs, ID_AA64ISAR0, t);
 
-    t = cpu->isar.id_aa64isar1;
+    t = GET_IDREG(idregs, ID_AA64ISAR1);
     t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2);      /* FEAT_DPB2 */
     t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_FPACCOMBINED);
     t = FIELD_DP64(t, ID_AA64ISAR1, API, 1);
@@ -1173,13 +1173,13 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 1);     /* FEAT_BF16 */
     t = FIELD_DP64(t, ID_AA64ISAR1, DGH, 1);      /* FEAT_DGH */
     t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1);     /* FEAT_I8MM */
-    cpu->isar.id_aa64isar1 = t;
+    SET_IDREG(idregs, ID_AA64ISAR1, t);
 
-    t = cpu->isar.id_aa64isar2;
+    t = GET_IDREG(idregs, ID_AA64ISAR2);
     t = FIELD_DP64(t, ID_AA64ISAR2, MOPS, 1);     /* FEAT_MOPS */
     t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1);       /* FEAT_HBC */
     t = FIELD_DP64(t, ID_AA64ISAR2, WFXT, 2);     /* FEAT_WFxT */
-    cpu->isar.id_aa64isar2 = t;
+    SET_IDREG(idregs, ID_AA64ISAR2, t);
 
     t = cpu->isar.id_aa64pfr0;
     t = FIELD_DP64(t, ID_AA64PFR0, FP, 1);        /* FEAT_FP16 */
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 05/21] arm/cpu: Store aa64drf0/1 into the idregs array
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (3 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 04/21] arm/cpu: Store aa64isar1/2 into the idregs array Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 06/21] arm/cpu: Store aa64mmfr0-3 " Eric Auger
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-features.h | 40 ++++++++++++++++-----------------
 target/arm/cpu.h          |  5 +++--
 target/arm/cpu.c          | 27 +++++++---------------
 target/arm/cpu64.c        | 14 ++++--------
 target/arm/helper.c       |  6 ++---
 target/arm/kvm.c          | 24 +++++++++-----------
 target/arm/tcg/cpu64.c    | 47 ++++++++++++++++++---------------------
 7 files changed, 70 insertions(+), 93 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index de571b520f..5e195f117d 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -590,68 +590,68 @@ static inline bool isar_feature_aa64_mops(const ARMISARegisters *id)
 static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id)
 {
     /* We always set the AdvSIMD and FP fields identically.  */
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) != 0xf;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, FP) != 0xf;
 }
 
 static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
 {
     /* We always set the AdvSIMD and FP fields identically wrt FP16.  */
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, FP) == 1;
 }
 
 static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, EL0) >= 2;
 }
 
 static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, EL1) >= 2;
 }
 
 static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, EL2) >= 2;
 }
 
 static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, RAS) != 0;
 }
 
 static inline bool isar_feature_aa64_doublefault(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, RAS) >= 2;
 }
 
 static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, SVE) != 0;
 }
 
 static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, SEL2) != 0;
 }
 
 static inline bool isar_feature_aa64_rme(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RME) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, RME) != 0;
 }
 
 static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, DIT) != 0;
 }
 
 static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id)
 {
-    int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2);
+    int key = FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR0, CSV2);
     if (key >= 2) {
         return true;      /* FEAT_CSV2_2 */
     }
     if (key == 1) {
-        key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC);
+        key = FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR1, CSV2_FRAC);
         return key >= 2;  /* FEAT_CSV2_1p2 */
     }
     return false;
@@ -659,37 +659,37 @@ static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR1, SSBS) != 0;
 }
 
 static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR1, BT) != 0;
 }
 
 static inline bool isar_feature_aa64_mte_insn_reg(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR1, MTE) != 0;
 }
 
 static inline bool isar_feature_aa64_mte(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR1, MTE) >= 2;
 }
 
 static inline bool isar_feature_aa64_mte3(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 3;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR1, MTE) >= 3;
 }
 
 static inline bool isar_feature_aa64_sme(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR1, SME) != 0;
 }
 
 static inline bool isar_feature_aa64_nmi(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, NMI) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64PFR1, NMI) != 0;
 }
 
 static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 87df224121..bebee2e694 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -874,6 +874,9 @@ _set_idreg(MAP, SYS_ ## REG ## _EL1, regval);                 \
 #define FIELD_EX64_IDREG(MAP, REG, FIELD)                     \
 FIELD_EX64(_get_idreg(MAP, SYS_ ## REG ## _EL1), REG, FIELD)  \
 
+#define FIELD_EX32_IDREG(MAP, REG, FIELD)                     \
+FIELD_EX32(_get_idreg(MAP, SYS_ ## REG ## _EL1), REG, FIELD)  \
+
 #define SET_IDREG(MAP, REG, VALUE)                            \
 _set_idreg(MAP, SYS_ ## REG ## _EL1, VALUE)
 
@@ -1082,8 +1085,6 @@ struct ArchCPU {
         uint32_t dbgdidr;
         uint32_t dbgdevid;
         uint32_t dbgdevid1;
-        uint64_t id_aa64pfr0;
-        uint64_t id_aa64pfr1;
         uint64_t id_aa64mmfr0;
         uint64_t id_aa64mmfr1;
         uint64_t id_aa64mmfr2;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index a4b59b259c..cbfb6df435 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2121,14 +2121,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
     }
 
     if (!cpu->has_vfp) {
-        uint64_t t;
         uint32_t u;
 
         FIELD_DP64_IDREG(idregs, ID_AA64ISAR1, JSCVT, 0);
 
-        t = cpu->isar.id_aa64pfr0;
-        t = FIELD_DP64(t, ID_AA64PFR0, FP, 0xf);
-        cpu->isar.id_aa64pfr0 = t;
+        FIELD_DP64_IDREG(idregs, ID_AA64PFR0, FP, 0xf);
 
         u = cpu->isar.id_isar6;
         u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0);
@@ -2183,9 +2180,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 0);
         SET_IDREG(idregs, ID_AA64ISAR1, t);
 
-        t = cpu->isar.id_aa64pfr0;
-        t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 0xf);
-        cpu->isar.id_aa64pfr0 = t;
+        FIELD_DP64_IDREG(idregs, ID_AA64PFR0, ADVSIMD, 0xf);
 
         u = cpu->isar.id_isar5;
         u = FIELD_DP32(u, ID_ISAR5, AES, 0);
@@ -2327,12 +2322,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
          */
         cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1, ID_PFR1, SECURITY, 0);
         cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPSDBG, 0);
-        cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
-                                           ID_AA64PFR0, EL3, 0);
+        FIELD_DP64_IDREG(idregs, ID_AA64PFR0, EL3, 0);
 
         /* Disable the realm management extension, which requires EL3. */
-        cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
-                                           ID_AA64PFR0, RME, 0);
+        FIELD_DP64_IDREG(idregs, ID_AA64PFR0, RME, 0);
     }
 
     if (!cpu->has_el2) {
@@ -2367,8 +2360,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
          * Disable the hypervisor feature bits in the processor feature
          * registers if we don't have EL2.
          */
-        cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
-                                           ID_AA64PFR0, EL2, 0);
+        FIELD_DP64_IDREG(idregs, ID_AA64PFR0, EL2, 0);
         cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1,
                                        ID_PFR1, VIRTUALIZATION, 0);
     }
@@ -2389,8 +2381,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
          * This matches Cortex-A710 BROADCASTMTE input being LOW.
          */
         if (cpu->tag_memory == NULL) {
-            cpu->isar.id_aa64pfr1 =
-                FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 1);
+            FIELD_DP64_IDREG(idregs, ID_AA64PFR1, MTE, 1);
         }
 #endif
     }
@@ -2429,13 +2420,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         cpu->isar.id_dfr0 =
             FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, MMAPTRC, 0);
         /* FEAT_AMU (Activity Monitors Extension) */
-        cpu->isar.id_aa64pfr0 =
-            FIELD_DP64(cpu->isar.id_aa64pfr0, ID_AA64PFR0, AMU, 0);
+        FIELD_DP64_IDREG(idregs, ID_AA64PFR0, AMU, 0);
         cpu->isar.id_pfr0 =
             FIELD_DP32(cpu->isar.id_pfr0, ID_PFR0, AMU, 0);
         /* FEAT_MPAM (Memory Partitioning and Monitoring Extension) */
-        cpu->isar.id_aa64pfr0 =
-            FIELD_DP64(cpu->isar.id_aa64pfr0, ID_AA64PFR0, MPAM, 0);
+        FIELD_DP64_IDREG(idregs, ID_AA64PFR0, MPAM, 0);
     }
 
     /* MPU can be configured out of a PMSA CPU either by setting has-mpu
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index d16c7487ac..7dd458012a 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -287,16 +287,13 @@ static bool cpu_arm_get_sve(Object *obj, Error **errp)
 static void cpu_arm_set_sve(Object *obj, bool value, Error **errp)
 {
     ARMCPU *cpu = ARM_CPU(obj);
-    uint64_t t;
 
     if (value && kvm_enabled() && !kvm_arm_sve_supported()) {
         error_setg(errp, "'sve' feature not supported by KVM on this host");
         return;
     }
 
-    t = cpu->isar.id_aa64pfr0;
-    t = FIELD_DP64(t, ID_AA64PFR0, SVE, value);
-    cpu->isar.id_aa64pfr0 = t;
+    FIELD_DP64_IDREG(&cpu->isar.idregs, ID_AA64PFR0, SVE, value);
 }
 
 void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp)
@@ -347,11 +344,8 @@ static bool cpu_arm_get_sme(Object *obj, Error **errp)
 static void cpu_arm_set_sme(Object *obj, bool value, Error **errp)
 {
     ARMCPU *cpu = ARM_CPU(obj);
-    uint64_t t;
 
-    t = cpu->isar.id_aa64pfr1;
-    t = FIELD_DP64(t, ID_AA64PFR1, SME, value);
-    cpu->isar.id_aa64pfr1 = t;
+    FIELD_DP64_IDREG(&cpu->isar.idregs, ID_AA64PFR1, SME, value);
 }
 
 static bool cpu_arm_get_sme_fa64(Object *obj, Error **errp)
@@ -635,7 +629,7 @@ static void aarch64_a57_initfn(Object *obj)
     cpu->isar.id_isar4 = 0x00011142;
     cpu->isar.id_isar5 = 0x00011121;
     cpu->isar.id_isar6 = 0;
-    cpu->isar.id_aa64pfr0 = 0x00002222;
+    SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
     cpu->isar.id_aa64dfr0 = 0x10305106;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     cpu->isar.id_aa64mmfr0 = 0x00001124;
@@ -694,7 +688,7 @@ static void aarch64_a53_initfn(Object *obj)
     cpu->isar.id_isar4 = 0x00011142;
     cpu->isar.id_isar5 = 0x00011121;
     cpu->isar.id_isar6 = 0;
-    cpu->isar.id_aa64pfr0 = 0x00002222;
+    SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
     cpu->isar.id_aa64dfr0 = 0x10305106;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 209b7c22b6..541bc27587 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7688,7 +7688,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri)
 static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
     ARMCPU *cpu = env_archcpu(env);
-    uint64_t pfr0 = cpu->isar.id_aa64pfr0;
+    uint64_t pfr0 = GET_IDREG(&cpu->isar.idregs, ID_AA64PFR0);
 
     if (env->gicv3state) {
         pfr0 |= 1 << 24;
@@ -8868,7 +8868,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .access = PL1_R,
 #ifdef CONFIG_USER_ONLY
               .type = ARM_CP_CONST,
-              .resetvalue = cpu->isar.id_aa64pfr0
+              .resetvalue = GET_IDREG(idregs, ID_AA64PFR0)
 #else
               .type = ARM_CP_NO_RAW,
               .accessfn = access_aa64_tid3,
@@ -8880,7 +8880,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64pfr1},
+              .resetvalue = GET_IDREG(idregs, ID_AA64PFR1)},
             { .name = "ID_AA64PFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 2,
               .access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index c30dc53622..888b10213c 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -304,8 +304,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
     ahcf->dtb_compatible = "arm,arm-v8";
     int fd = fdarray[2];
 
-    err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0,
-                         ARM64_SYS_REG(3, 0, 0, 4, 0));
+    err = get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64PFR0_EL1);
     if (unlikely(err < 0)) {
         /*
          * Before v4.15, the kernel only exposed a limited number of system
@@ -323,11 +322,10 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
          * ??? Either of these sounds like too much effort just
          *     to work around running a modern host kernel.
          */
-        ahcf->isar.id_aa64pfr0 = 0x00000011; /* EL1&0, AArch64 only */
+        SET_IDREG(&ahcf->isar.idregs, ID_AA64PFR0, 0x00000011); /* EL1&0, AArch64 only */
         err = 0;
     } else {
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1,
-                              ARM64_SYS_REG(3, 0, 0, 4, 1));
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64PFR1_EL1);
         err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64smfr0,
                               ARM64_SYS_REG(3, 0, 0, 4, 5));
         err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0,
@@ -353,10 +351,8 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
          * than skipping the reads and leaving 0, as we must avoid
          * considering the values in every case.
          */
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr0,
-                              ARM64_SYS_REG(3, 0, 0, 1, 0));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1,
-                              ARM64_SYS_REG(3, 0, 0, 1, 1));
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64PFR0_EL1);
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64PFR1_EL1);
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
                               ARM64_SYS_REG(3, 0, 0, 1, 2));
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
@@ -407,14 +403,14 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
          * arch/arm64/kvm/sys_regs.c:trap_dbgidr() does.
          * We only do this if the CPU supports AArch32 at EL1.
          */
-        if (FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL1) >= 2) {
-            int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS);
-            int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS);
+        if (FIELD_EX32_IDREG(&ahcf->isar.idregs, ID_AA64PFR0, EL1) >= 2) {
+            int wrps = FIELD_EX64_IDREG(&ahcf->isar.idregs, ID_AA64DFR0, WRPS);
+            int brps = FIELD_EX64_IDREG(&ahcf->isar.idregs, ID_AA64DFR0, BRPS);
             int ctx_cmps =
-                FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS);
+                FIELD_EX64_IDREG(&ahcf->isar.idregs, ID_AA64DFR0, CTX_CMPS);
             int version = 6; /* ARMv8 debug architecture */
             bool has_el3 =
-                !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3);
+                !!FIELD_EX32_IDREG(&ahcf->isar.idregs, ID_AA64PFR0, EL3);
             uint32_t dbgdidr = 0;
 
             dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps);
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 7be63f21a1..b2a88a0ebd 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -89,8 +89,8 @@ static void aarch64_a35_initfn(Object *obj)
     cpu->isar.id_isar3 = 0x01112131;
     cpu->isar.id_isar4 = 0x00011142;
     cpu->isar.id_isar5 = 0x00011121;
-    cpu->isar.id_aa64pfr0 = 0x00002222;
-    cpu->isar.id_aa64pfr1 = 0;
+    SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
+    SET_IDREG(idregs, ID_AA64PFR1, 0);
     cpu->isar.id_aa64dfr0 = 0x10305106;
     cpu->isar.id_aa64dfr1 = 0;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
@@ -181,11 +181,8 @@ static bool cpu_arm_get_rme(Object *obj, Error **errp)
 static void cpu_arm_set_rme(Object *obj, bool value, Error **errp)
 {
     ARMCPU *cpu = ARM_CPU(obj);
-    uint64_t t;
 
-    t = cpu->isar.id_aa64pfr0;
-    t = FIELD_DP64(t, ID_AA64PFR0, RME, value);
-    cpu->isar.id_aa64pfr0 = t;
+    FIELD_DP64_IDREG(&cpu->isar.idregs, ID_AA64PFR0, RME, value);
 }
 
 static void cpu_max_set_l0gptsz(Object *obj, Visitor *v, const char *name,
@@ -251,8 +248,8 @@ static void aarch64_a55_initfn(Object *obj)
     cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
     cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
-    cpu->isar.id_aa64pfr0  = 0x0000000010112222ull;
-    cpu->isar.id_aa64pfr1  = 0x0000000000000010ull;
+    SET_IDREG(idregs, ID_AA64PFR0, 0x0000000010112222ull);
+    SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000010ull);
     cpu->id_afr0       = 0x00000000;
     cpu->isar.id_dfr0  = 0x04010088;
     cpu->isar.id_isar0 = 0x02101110;
@@ -332,7 +329,7 @@ static void aarch64_a72_initfn(Object *obj)
     cpu->isar.id_isar3 = 0x01112131;
     cpu->isar.id_isar4 = 0x00011142;
     cpu->isar.id_isar5 = 0x00011121;
-    cpu->isar.id_aa64pfr0 = 0x00002222;
+    SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
     cpu->isar.id_aa64dfr0 = 0x10305106;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     cpu->isar.id_aa64mmfr0 = 0x00001124;
@@ -378,8 +375,8 @@ static void aarch64_a76_initfn(Object *obj)
     cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
     cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
-    cpu->isar.id_aa64pfr0  = 0x1100000010111112ull; /* GIC filled in later */
-    cpu->isar.id_aa64pfr1  = 0x0000000000000010ull;
+    SET_IDREG(idregs, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */
+    SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000010ull);
     cpu->id_afr0       = 0x00000000;
     cpu->isar.id_dfr0  = 0x04010088;
     cpu->isar.id_isar0 = 0x02101110;
@@ -441,8 +438,8 @@ static void aarch64_a64fx_initfn(Object *obj)
     cpu->revidr = 0x00000000;
     cpu->ctr = 0x86668006;
     cpu->reset_sctlr = 0x30000180;
-    cpu->isar.id_aa64pfr0 =   0x0000000101111111; /* No RAS Extensions */
-    cpu->isar.id_aa64pfr1 = 0x0000000000000000;
+    SET_IDREG(idregs, ID_AA64PFR0, 0x0000000101111111); /* No RAS Extensions */
+    SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000000);
     cpu->isar.id_aa64dfr0 = 0x0000000010305408;
     cpu->isar.id_aa64dfr1 = 0x0000000000000000;
     cpu->id_aa64afr0 = 0x0000000000000000;
@@ -620,8 +617,8 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
     cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
     cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
-    cpu->isar.id_aa64pfr0  = 0x1100000010111112ull; /* GIC filled in later */
-    cpu->isar.id_aa64pfr1  = 0x0000000000000020ull;
+    SET_IDREG(idregs, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */
+    SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000020ull);
     cpu->id_afr0       = 0x00000000;
     cpu->isar.id_dfr0  = 0x04010088;
     cpu->isar.id_isar0 = 0x02101110;
@@ -696,8 +693,8 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
     cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull;
     cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
     cpu->isar.id_aa64mmfr2 = 0x0220011102101011ull;
-    cpu->isar.id_aa64pfr0  = 0x1101110120111112ull; /* GIC filled in later */
-    cpu->isar.id_aa64pfr1  = 0x0000000000000020ull;
+    SET_IDREG(idregs, ID_AA64PFR0, 0x1101110120111112ull); /* GIC filled in later */
+    SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000020ull);
     cpu->id_afr0       = 0x00000000;
     cpu->isar.id_dfr0  = 0x15011099;
     cpu->isar.id_isar0 = 0x02101110;
@@ -930,8 +927,8 @@ static void aarch64_a710_initfn(Object *obj)
     cpu->isar.mvfr1    = 0x13211111;
     cpu->isar.mvfr2    = 0x00000043;
     cpu->isar.id_pfr2  = 0x00000011;
-    cpu->isar.id_aa64pfr0  = 0x1201111120111112ull; /* GIC filled in later */
-    cpu->isar.id_aa64pfr1  = 0x0000000000000221ull;
+    SET_IDREG(idregs, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */
+    SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000221ull);
     SET_IDREG(idregs, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */
     cpu->isar.id_aa64dfr0  = 0x000011f010305619ull;
     cpu->isar.id_aa64dfr1  = 0;
@@ -1029,8 +1026,8 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
     cpu->isar.mvfr1    = 0x13211111;
     cpu->isar.mvfr2    = 0x00000043;
     cpu->isar.id_pfr2  = 0x00000011;
-    cpu->isar.id_aa64pfr0  = 0x1201111120111112ull; /* GIC filled in later */
-    cpu->isar.id_aa64pfr1  = 0x0000000000000221ull;
+    SET_IDREG(idregs, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */
+    SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000221ull);
     SET_IDREG(idregs, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */
     cpu->isar.id_aa64dfr0  = 0x000011f210305619ull;
     cpu->isar.id_aa64dfr1  = 0;
@@ -1181,7 +1178,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64ISAR2, WFXT, 2);     /* FEAT_WFxT */
     SET_IDREG(idregs, ID_AA64ISAR2, t);
 
-    t = cpu->isar.id_aa64pfr0;
+    t = GET_IDREG(idregs, ID_AA64PFR0);
     t = FIELD_DP64(t, ID_AA64PFR0, FP, 1);        /* FEAT_FP16 */
     t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1);   /* FEAT_FP16 */
     t = FIELD_DP64(t, ID_AA64PFR0, RAS, 2);       /* FEAT_RASv1p1 + FEAT_DoubleFault */
@@ -1190,9 +1187,9 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1);       /* FEAT_DIT */
     t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 3);      /* FEAT_CSV2_3 */
     t = FIELD_DP64(t, ID_AA64PFR0, CSV3, 1);      /* FEAT_CSV3 */
-    cpu->isar.id_aa64pfr0 = t;
+    SET_IDREG(idregs, ID_AA64PFR0, t);
 
-    t = cpu->isar.id_aa64pfr1;
+    t = GET_IDREG(idregs, ID_AA64PFR1);
     t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);        /* FEAT_BTI */
     t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2);      /* FEAT_SSBS2 */
     /*
@@ -1205,7 +1202,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64PFR1, SME, 1);       /* FEAT_SME */
     t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_3 */
     t = FIELD_DP64(t, ID_AA64PFR1, NMI, 1);       /* FEAT_NMI */
-    cpu->isar.id_aa64pfr1 = t;
+    SET_IDREG(idregs, ID_AA64PFR1, t);
 
     t = cpu->isar.id_aa64mmfr0;
     t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 06/21] arm/cpu: Store aa64mmfr0-3 into the idregs array
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (4 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 05/21] arm/cpu: Store aa64drf0/1 " Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 07/21] arm/cpu: Store aa64drf0/1 " Eric Auger
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-features.h | 70 +++++++++++++++++++--------------------
 target/arm/cpu.h          |  7 ++--
 target/arm/cpu64.c        |  8 ++---
 target/arm/helper.c       |  8 ++---
 target/arm/kvm.c          | 12 +++----
 target/arm/ptw.c          |  6 ++--
 target/arm/tcg/cpu64.c    | 64 +++++++++++++++++------------------
 7 files changed, 84 insertions(+), 91 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 5e195f117d..45f315df7b 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -694,182 +694,182 @@ static inline bool isar_feature_aa64_nmi(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
 {
-    return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1;
+    return FIELD_SEX64_IDREG(&id->idregs, ID_AA64MMFR0, TGRAN4) >= 1;
 }
 
 static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id)
 {
-    unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2);
+    unsigned t = FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR0, TGRAN4_2);
     return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id));
 }
 
 static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR0, TGRAN16) >= 2;
 }
 
 static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id)
 {
-    unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2);
+    unsigned t = FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR0, TGRAN16_2);
     return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id));
 }
 
 static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id)
 {
-    return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0;
+    return FIELD_SEX64_IDREG(&id->idregs, ID_AA64MMFR0, TGRAN4) >= 0;
 }
 
 static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR0, TGRAN16) >= 1;
 }
 
 static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id)
 {
-    return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0;
+    return FIELD_SEX64_IDREG(&id->idregs, ID_AA64MMFR0, TGRAN64) >= 0;
 }
 
 static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id)
 {
-    unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2);
+    unsigned t = FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR0, TGRAN4_2);
     return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id));
 }
 
 static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id)
 {
-    unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2);
+    unsigned t = FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR0, TGRAN16_2);
     return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id));
 }
 
 static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id)
 {
-    unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2);
+    unsigned t = FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR0, TGRAN64_2);
     return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id));
 }
 
 static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR0, FGT) != 0;
 }
 
 static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR0, ECV) > 0;
 }
 
 static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 1;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR0, ECV) > 1;
 }
 
 static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR1, VH) != 0;
 }
 
 static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR1, LO) != 0;
 }
 
 static inline bool isar_feature_aa64_pan(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR1, PAN) != 0;
 }
 
 static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR1, PAN) >= 2;
 }
 
 static inline bool isar_feature_aa64_pan3(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 3;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR1, PAN) >= 3;
 }
 
 static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR1, HCX) != 0;
 }
 
 static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, TIDCP1) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR1, TIDCP1) != 0;
 }
 
 static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR1, HAFDBS) != 0;
 }
 
 static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR1, HAFDBS) >= 2;
 }
 
 static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR1, XNX) != 0;
 }
 
 static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, UAO) != 0;
 }
 
 static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, ST) != 0;
 }
 
 static inline bool isar_feature_aa64_lse2(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, AT) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, AT) != 0;
 }
 
 static inline bool isar_feature_aa64_fwb(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, FWB) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, FWB) != 0;
 }
 
 static inline bool isar_feature_aa64_ids(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, IDS) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, IDS) != 0;
 }
 
 static inline bool isar_feature_aa64_half_evt(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 1;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, EVT) >= 1;
 }
 
 static inline bool isar_feature_aa64_evt(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, EVT) >= 2;
 }
 
 static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, CCIDX) != 0;
 }
 
 static inline bool isar_feature_aa64_lva(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, VARANGE) != 0;
 }
 
 static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, E0PD) != 0;
 }
 
 static inline bool isar_feature_aa64_nv(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, NV) != 0;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, NV) != 0;
 }
 
 static inline bool isar_feature_aa64_nv2(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, NV) >= 2;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64MMFR2, NV) >= 2;
 }
 
 static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index bebee2e694..419dfde638 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -874,6 +874,9 @@ _set_idreg(MAP, SYS_ ## REG ## _EL1, regval);                 \
 #define FIELD_EX64_IDREG(MAP, REG, FIELD)                     \
 FIELD_EX64(_get_idreg(MAP, SYS_ ## REG ## _EL1), REG, FIELD)  \
 
+#define FIELD_SEX64_IDREG(MAP, REG, FIELD)                     \
+FIELD_SEX64(_get_idreg(MAP, SYS_ ## REG ## _EL1), REG, FIELD)  \
+
 #define FIELD_EX32_IDREG(MAP, REG, FIELD)                     \
 FIELD_EX32(_get_idreg(MAP, SYS_ ## REG ## _EL1), REG, FIELD)  \
 
@@ -1085,10 +1088,6 @@ struct ArchCPU {
         uint32_t dbgdidr;
         uint32_t dbgdevid;
         uint32_t dbgdevid1;
-        uint64_t id_aa64mmfr0;
-        uint64_t id_aa64mmfr1;
-        uint64_t id_aa64mmfr2;
-        uint64_t id_aa64mmfr3;
         uint64_t id_aa64dfr0;
         uint64_t id_aa64dfr1;
         uint64_t id_aa64smfr0;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 7dd458012a..594778a031 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -582,12 +582,12 @@ void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp)
         return;
     }
 
-    t = cpu->isar.id_aa64mmfr0;
+    t = GET_IDREG(&cpu->isar.idregs, ID_AA64MMFR0);
     t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 2);   /* 16k pages w/ LPA2 */
     t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4, 1);    /*  4k pages w/ LPA2 */
     t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 3); /* 16k stage2 w/ LPA2 */
     t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 3);  /*  4k stage2 w/ LPA2 */
-    cpu->isar.id_aa64mmfr0 = t;
+    SET_IDREG(&cpu->isar.idregs, ID_AA64MMFR0, t);
 }
 
 static void aarch64_a57_initfn(Object *obj)
@@ -632,7 +632,7 @@ static void aarch64_a57_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
     cpu->isar.id_aa64dfr0 = 0x10305106;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
-    cpu->isar.id_aa64mmfr0 = 0x00001124;
+    SET_IDREG(idregs, ID_AA64MMFR0, 0x00001124);
     cpu->isar.dbgdidr = 0x3516d000;
     cpu->isar.dbgdevid = 0x01110f13;
     cpu->isar.dbgdevid1 = 0x2;
@@ -691,7 +691,7 @@ static void aarch64_a53_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
     cpu->isar.id_aa64dfr0 = 0x10305106;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
-    cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
+    SET_IDREG(idregs, ID_AA64MMFR0, 0x00001122); /* 40 bit physical addr */
     cpu->isar.dbgdidr = 0x3516d000;
     cpu->isar.dbgdevid = 0x00110f13;
     cpu->isar.dbgdevid1 = 0x1;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 541bc27587..fa04383921 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8995,22 +8995,22 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64mmfr0 },
+              .resetvalue = GET_IDREG(idregs, ID_AA64MMFR0)},
             { .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64mmfr1 },
+              .resetvalue = GET_IDREG(idregs, ID_AA64MMFR1) },
             { .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64mmfr2 },
+              .resetvalue = GET_IDREG(idregs, ID_AA64MMFR2) },
             { .name = "ID_AA64MMFR3_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64mmfr3 },
+              .resetvalue = GET_IDREG(idregs, ID_AA64MMFR3) },
             { .name = "ID_AA64MMFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 4,
               .access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 888b10213c..c9b99bf5ee 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -335,14 +335,10 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ISAR0_EL1);
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ISAR1_EL1);
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ISAR2_EL1);
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0,
-                              ARM64_SYS_REG(3, 0, 0, 7, 0));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1,
-                              ARM64_SYS_REG(3, 0, 0, 7, 1));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2,
-                              ARM64_SYS_REG(3, 0, 0, 7, 2));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr3,
-                              ARM64_SYS_REG(3, 0, 0, 7, 3));
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64MMFR0_EL1);
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64MMFR1_EL1);
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64MMFR2_EL1);
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64MMFR3_EL1);
 
         /*
          * Note that if AArch32 support is not present in the host,
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 4476b32ff5..dea4621352 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -104,7 +104,7 @@ unsigned int arm_pamax(ARMCPU *cpu)
 {
     if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
         unsigned int parange =
-            FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE);
+            FIELD_EX64_IDREG(&cpu->isar.idregs, ID_AA64MMFR0, PARANGE);
 
         /*
          * id_aa64mmfr0 is a read-only register so values outside of the
@@ -312,7 +312,7 @@ static bool granule_protection_check(CPUARMState *env, uint64_t paddress,
      * physical address size is invalid.
      */
     pps = FIELD_EX64(gpccr, GPCCR, PPS);
-    if (pps > FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE)) {
+    if (pps > FIELD_EX64_IDREG(&cpu->isar.idregs, ID_AA64MMFR0, PARANGE)) {
         goto fault_walk;
     }
     pps = pamax_map[pps];
@@ -1727,7 +1727,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
          * ID_AA64MMFR0 is a read-only register so values outside of the
          * supported mappings can be considered an implementation error.
          */
-        ps = FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE);
+        ps = FIELD_EX64_IDREG(&cpu->isar.idregs, ID_AA64MMFR0, PARANGE);
         ps = MIN(ps, param.ps);
         assert(ps < ARRAY_SIZE(pamax_map));
         outputsize = pamax_map[ps];
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index b2a88a0ebd..64473fc3c7 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -95,8 +95,8 @@ static void aarch64_a35_initfn(Object *obj)
     cpu->isar.id_aa64dfr1 = 0;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     SET_IDREG(idregs, ID_AA64ISAR1, 0);
-    cpu->isar.id_aa64mmfr0 = 0x00101122;
-    cpu->isar.id_aa64mmfr1 = 0;
+    SET_IDREG(idregs, ID_AA64MMFR0, 0x00101122);
+    SET_IDREG(idregs, ID_AA64MMFR1, 0);
     cpu->clidr = 0x0a200023;
     cpu->dcz_blocksize = 4;
 
@@ -245,9 +245,9 @@ static void aarch64_a55_initfn(Object *obj)
     cpu->isar.id_aa64dfr0  = 0x0000000010305408ull;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
     SET_IDREG(idregs, ID_AA64ISAR1, 0x0000000000100001ull);
-    cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull;
-    cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
-    cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
+    SET_IDREG(idregs, ID_AA64MMFR0, 0x0000000000101122ull);
+    SET_IDREG(idregs, ID_AA64MMFR1, 0x0000000010212122ull);
+    SET_IDREG(idregs, ID_AA64MMFR2, 0x0000000000001011ull);
     SET_IDREG(idregs, ID_AA64PFR0, 0x0000000010112222ull);
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000010ull);
     cpu->id_afr0       = 0x00000000;
@@ -332,7 +332,7 @@ static void aarch64_a72_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
     cpu->isar.id_aa64dfr0 = 0x10305106;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
-    cpu->isar.id_aa64mmfr0 = 0x00001124;
+    SET_IDREG(idregs, ID_AA64MMFR0, 0x00001124);
     cpu->isar.dbgdidr = 0x3516d000;
     cpu->isar.dbgdevid = 0x01110f13;
     cpu->isar.dbgdevid1 = 0x2;
@@ -372,9 +372,9 @@ static void aarch64_a76_initfn(Object *obj)
     cpu->isar.id_aa64dfr0  = 0x0000000010305408ull;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
     SET_IDREG(idregs, ID_AA64ISAR1, 0x0000000000100001ull);
-    cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull;
-    cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
-    cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
+    SET_IDREG(idregs, ID_AA64MMFR0, 0x0000000000101122ull);
+    SET_IDREG(idregs, ID_AA64MMFR1, 0x0000000010212122ull);
+    SET_IDREG(idregs, ID_AA64MMFR2, 0x0000000000001011ull);
     SET_IDREG(idregs, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000010ull);
     cpu->id_afr0       = 0x00000000;
@@ -444,9 +444,9 @@ static void aarch64_a64fx_initfn(Object *obj)
     cpu->isar.id_aa64dfr1 = 0x0000000000000000;
     cpu->id_aa64afr0 = 0x0000000000000000;
     cpu->id_aa64afr1 = 0x0000000000000000;
-    cpu->isar.id_aa64mmfr0 = 0x0000000000001122;
-    cpu->isar.id_aa64mmfr1 = 0x0000000011212100;
-    cpu->isar.id_aa64mmfr2 = 0x0000000000001011;
+    SET_IDREG(idregs, ID_AA64MMFR0, 0x0000000000001122);
+    SET_IDREG(idregs, ID_AA64MMFR1, 0x0000000011212100);
+    SET_IDREG(idregs, ID_AA64MMFR2, 0x0000000000001011);
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0000000010211120);
     SET_IDREG(idregs, ID_AA64ISAR1, 0x0000000000010001);
     SET_IDREG(idregs, ID_AA64ZFR0, 0x0000000000000000);
@@ -614,9 +614,9 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
     cpu->isar.id_aa64dfr0  = 0x0000000110305408ull;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
     SET_IDREG(idregs, ID_AA64ISAR1, 0x0000000000100001ull);
-    cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull;
-    cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
-    cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
+    SET_IDREG(idregs, ID_AA64MMFR0, 0x0000000000101125ull);
+    SET_IDREG(idregs, ID_AA64MMFR1, 0x0000000010212122ull);
+    SET_IDREG(idregs, ID_AA64MMFR2, 0x0000000000001011ull);
     SET_IDREG(idregs, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000020ull);
     cpu->id_afr0       = 0x00000000;
@@ -690,9 +690,9 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
     cpu->isar.id_aa64dfr1 = 0x00000000;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x1011111110212120ull); /* with FEAT_RNG */
     SET_IDREG(idregs, ID_AA64ISAR1, 0x0111000001211032ull);
-    cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull;
-    cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
-    cpu->isar.id_aa64mmfr2 = 0x0220011102101011ull;
+    SET_IDREG(idregs, ID_AA64MMFR0, 0x0000000000101125ull);
+    SET_IDREG(idregs, ID_AA64MMFR1, 0x0000000010212122ull),
+    SET_IDREG(idregs, ID_AA64MMFR2, 0x0220011102101011ull),
     SET_IDREG(idregs, ID_AA64PFR0, 0x1101110120111112ull); /* GIC filled in later */
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000020ull);
     cpu->id_afr0       = 0x00000000;
@@ -936,9 +936,9 @@ static void aarch64_a710_initfn(Object *obj)
     cpu->id_aa64afr1       = 0;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0221111110212120ull); /* with Crypto */
     SET_IDREG(idregs, ID_AA64ISAR1, 0x0010111101211052ull);
-    cpu->isar.id_aa64mmfr0 = 0x0000022200101122ull;
-    cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
-    cpu->isar.id_aa64mmfr2 = 0x1221011110101011ull;
+    SET_IDREG(idregs, ID_AA64MMFR0, 0x0000022200101122ull);
+    SET_IDREG(idregs, ID_AA64MMFR1, 0x0000000010212122ull);
+    SET_IDREG(idregs, ID_AA64MMFR2, 0x1221011110101011ull);
     cpu->clidr             = 0x0000001482000023ull;
     cpu->gm_blocksize      = 4;
     cpu->ctr               = 0x000000049444c004ull;
@@ -1035,9 +1035,9 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
     cpu->id_aa64afr1       = 0;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x1221111110212120ull); /* with Crypto and FEAT_RNG */
     SET_IDREG(idregs, ID_AA64ISAR1, 0x0011111101211052ull);
-    cpu->isar.id_aa64mmfr0 = 0x0000022200101125ull;
-    cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
-    cpu->isar.id_aa64mmfr2 = 0x1221011112101011ull;
+    SET_IDREG(idregs, ID_AA64MMFR0, 0x0000022200101125ull);
+    SET_IDREG(idregs, ID_AA64MMFR1, 0x0000000010212122ull);
+    SET_IDREG(idregs, ID_AA64MMFR2, 0x1221011112101011ull);
     cpu->clidr             = 0x0000001482000023ull;
     cpu->gm_blocksize      = 4;
     cpu->ctr               = 0x00000004b444c004ull;
@@ -1204,7 +1204,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64PFR1, NMI, 1);       /* FEAT_NMI */
     SET_IDREG(idregs, ID_AA64PFR1, t);
 
-    t = cpu->isar.id_aa64mmfr0;
+    t = GET_IDREG(idregs, ID_AA64MMFR0);
     t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */
     t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 1);   /* 16k pages supported */
     t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 2); /* 16k stage2 supported */
@@ -1212,9 +1212,9 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2);  /*  4k stage2 supported */
     t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1);       /* FEAT_FGT */
     t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2);       /* FEAT_ECV */
-    cpu->isar.id_aa64mmfr0 = t;
+    SET_IDREG(idregs, ID_AA64MMFR0, t);
 
-    t = cpu->isar.id_aa64mmfr1;
+    t = GET_IDREG(idregs, ID_AA64MMFR1);
     t = FIELD_DP64(t, ID_AA64MMFR1, HAFDBS, 2);   /* FEAT_HAFDBS */
     t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* FEAT_VMID16 */
     t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);       /* FEAT_VHE */
@@ -1225,9 +1225,9 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 2);      /* FEAT_ETS2 */
     t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1);      /* FEAT_HCX */
     t = FIELD_DP64(t, ID_AA64MMFR1, TIDCP1, 1);   /* FEAT_TIDCP1 */
-    cpu->isar.id_aa64mmfr1 = t;
+    SET_IDREG(idregs, ID_AA64MMFR1, t);
 
-    t = cpu->isar.id_aa64mmfr2;
+    t = GET_IDREG(idregs, ID_AA64MMFR2);
     t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1);      /* FEAT_TTCNP */
     t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);      /* FEAT_UAO */
     t = FIELD_DP64(t, ID_AA64MMFR2, IESB, 1);     /* FEAT_IESB */
@@ -1241,11 +1241,9 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64MMFR2, BBM, 2);      /* FEAT_BBM at level 2 */
     t = FIELD_DP64(t, ID_AA64MMFR2, EVT, 2);      /* FEAT_EVT */
     t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1);     /* FEAT_E0PD */
-    cpu->isar.id_aa64mmfr2 = t;
+    SET_IDREG(idregs, ID_AA64MMFR2, t);
 
-    t = cpu->isar.id_aa64mmfr3;
-    t = FIELD_DP64(t, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
-    cpu->isar.id_aa64mmfr3 = t;
+    FIELD_DP64_IDREG(idregs, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
 
     t = GET_IDREG(idregs, ID_AA64ZFR0);
     t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1);
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 07/21] arm/cpu: Store aa64drf0/1 into the idregs array
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (5 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 06/21] arm/cpu: Store aa64mmfr0-3 " Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 08/21] arm/cpu: Store aa64smfr0 " Eric Auger
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-features.h | 16 ++++++++--------
 target/arm/cpu.h          |  2 --
 target/arm/internals.h    |  6 +++---
 target/arm/cpu.c          | 15 +++++----------
 target/arm/cpu64.c        |  4 ++--
 target/arm/helper.c       |  4 ++--
 target/arm/kvm.c          |  6 ++----
 target/arm/tcg/cpu64.c    | 33 +++++++++++++++++----------------
 8 files changed, 39 insertions(+), 47 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 45f315df7b..9b0d5157bf 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -874,30 +874,30 @@ static inline bool isar_feature_aa64_nv2(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 &&
-        FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64DFR0, PMUVER) >= 4 &&
+        FIELD_EX64_IDREG(&id->idregs, ID_AA64DFR0, PMUVER) != 0xf;
 }
 
 static inline bool isar_feature_aa64_pmuv3p4(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 &&
-        FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64DFR0, PMUVER) >= 5 &&
+        FIELD_EX64_IDREG(&id->idregs, ID_AA64DFR0, PMUVER) != 0xf;
 }
 
 static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 6 &&
-        FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64DFR0, PMUVER) >= 6 &&
+        FIELD_EX64_IDREG(&id->idregs, ID_AA64DFR0, PMUVER) != 0xf;
 }
 
 static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64DFR0, DEBUGVER) >= 8;
 }
 
 static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id)
 {
-    return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0;
+    return FIELD_SEX64_IDREG(&id->idregs, ID_AA64DFR0, DOUBLELOCK) >= 0;
 }
 
 static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 419dfde638..6954952d5f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1088,8 +1088,6 @@ struct ArchCPU {
         uint32_t dbgdidr;
         uint32_t dbgdevid;
         uint32_t dbgdevid1;
-        uint64_t id_aa64dfr0;
-        uint64_t id_aa64dfr1;
         uint64_t id_aa64smfr0;
         uint64_t reset_pmcr_el0;
         IdRegMap idregs;
diff --git a/target/arm/internals.h b/target/arm/internals.h
index e1aa1a63b9..02c57f546b 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1002,7 +1002,7 @@ static inline bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
 static inline int arm_num_brps(ARMCPU *cpu)
 {
     if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
-        return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1;
+        return FIELD_EX64_IDREG(&cpu->isar.idregs, ID_AA64DFR0, BRPS) + 1;
     } else {
         return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, BRPS) + 1;
     }
@@ -1016,7 +1016,7 @@ static inline int arm_num_brps(ARMCPU *cpu)
 static inline int arm_num_wrps(ARMCPU *cpu)
 {
     if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
-        return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1;
+        return FIELD_EX64_IDREG(&cpu->isar.idregs, ID_AA64DFR0, WRPS) + 1;
     } else {
         return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, WRPS) + 1;
     }
@@ -1030,7 +1030,7 @@ static inline int arm_num_wrps(ARMCPU *cpu)
 static inline int arm_num_ctx_cmps(ARMCPU *cpu)
 {
     if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
-        return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1;
+        return FIELD_EX64_IDREG(&cpu->isar.idregs, ID_AA64DFR0, CTX_CMPS) + 1;
     } else {
         return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, CTX_CMPS) + 1;
     }
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index cbfb6df435..42664dbfc1 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2348,8 +2348,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
                 cpu);
 #endif
     } else {
-        cpu->isar.id_aa64dfr0 =
-            FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMUVER, 0);
+        FIELD_DP64_IDREG(idregs, ID_AA64DFR0, PMUVER, 0);
         cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0);
         cpu->pmceid0 = 0;
         cpu->pmceid1 = 0;
@@ -2401,19 +2400,15 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
          * try to access the non-existent system registers for them.
          */
         /* FEAT_SPE (Statistical Profiling Extension) */
-        cpu->isar.id_aa64dfr0 =
-            FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMSVER, 0);
+        FIELD_DP64_IDREG(idregs, ID_AA64DFR0, PMSVER, 0);
         /* FEAT_TRBE (Trace Buffer Extension) */
-        cpu->isar.id_aa64dfr0 =
-            FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEBUFFER, 0);
+        FIELD_DP64_IDREG(idregs, ID_AA64DFR0, TRACEBUFFER, 0);
         /* FEAT_TRF (Self-hosted Trace Extension) */
-        cpu->isar.id_aa64dfr0 =
-            FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEFILT, 0);
+        FIELD_DP64_IDREG(idregs, ID_AA64DFR0, TRACEFILT, 0);
         cpu->isar.id_dfr0 =
             FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, TRACEFILT, 0);
         /* Trace Macrocell system register access */
-        cpu->isar.id_aa64dfr0 =
-            FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEVER, 0);
+        FIELD_DP64_IDREG(idregs, ID_AA64DFR0, TRACEVER, 0);
         cpu->isar.id_dfr0 =
             FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPTRC, 0);
         /* Memory mapped trace */
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 594778a031..85f581edb7 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -630,7 +630,7 @@ static void aarch64_a57_initfn(Object *obj)
     cpu->isar.id_isar5 = 0x00011121;
     cpu->isar.id_isar6 = 0;
     SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
-    cpu->isar.id_aa64dfr0 = 0x10305106;
+    SET_IDREG(idregs, ID_AA64DFR0, 0x10305106);
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     SET_IDREG(idregs, ID_AA64MMFR0, 0x00001124);
     cpu->isar.dbgdidr = 0x3516d000;
@@ -689,7 +689,7 @@ static void aarch64_a53_initfn(Object *obj)
     cpu->isar.id_isar5 = 0x00011121;
     cpu->isar.id_isar6 = 0;
     SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
-    cpu->isar.id_aa64dfr0 = 0x10305106;
+    SET_IDREG(idregs, ID_AA64DFR0, 0x10305106);
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     SET_IDREG(idregs, ID_AA64MMFR0, 0x00001122); /* 40 bit physical addr */
     cpu->isar.dbgdidr = 0x3516d000;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index fa04383921..c15b24933d 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8915,12 +8915,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64dfr0 },
+              .resetvalue = GET_IDREG(idregs, ID_AA64DFR0) },
             { .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64dfr1 },
+              .resetvalue = GET_IDREG(idregs, ID_AA64DFR1) },
             { .name = "ID_AA64DFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 2,
               .access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index c9b99bf5ee..7377e4a133 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -328,10 +328,8 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64PFR1_EL1);
         err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64smfr0,
                               ARM64_SYS_REG(3, 0, 0, 4, 5));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0,
-                              ARM64_SYS_REG(3, 0, 0, 5, 0));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1,
-                              ARM64_SYS_REG(3, 0, 0, 5, 1));
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64DFR0_EL1);
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64DFR1_EL1);
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ISAR0_EL1);
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ISAR1_EL1);
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ISAR2_EL1);
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 64473fc3c7..56f086cb28 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -91,8 +91,8 @@ static void aarch64_a35_initfn(Object *obj)
     cpu->isar.id_isar5 = 0x00011121;
     SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
     SET_IDREG(idregs, ID_AA64PFR1, 0);
-    cpu->isar.id_aa64dfr0 = 0x10305106;
-    cpu->isar.id_aa64dfr1 = 0;
+    SET_IDREG(idregs, ID_AA64DFR0, 0x10305106);
+    SET_IDREG(idregs, ID_AA64DFR1, 0);
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     SET_IDREG(idregs, ID_AA64ISAR1, 0);
     SET_IDREG(idregs, ID_AA64MMFR0, 0x00101122);
@@ -242,7 +242,7 @@ static void aarch64_a55_initfn(Object *obj)
     cpu->clidr = 0x82000023;
     cpu->ctr = 0x84448004; /* L1Ip = VIPT */
     cpu->dcz_blocksize = 4; /* 64 bytes */
-    cpu->isar.id_aa64dfr0  = 0x0000000010305408ull;
+    SET_IDREG(idregs, ID_AA64DFR0, 0x0000000010305408ull);
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
     SET_IDREG(idregs, ID_AA64ISAR1, 0x0000000000100001ull);
     SET_IDREG(idregs, ID_AA64MMFR0, 0x0000000000101122ull);
@@ -330,7 +330,7 @@ static void aarch64_a72_initfn(Object *obj)
     cpu->isar.id_isar4 = 0x00011142;
     cpu->isar.id_isar5 = 0x00011121;
     SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
-    cpu->isar.id_aa64dfr0 = 0x10305106;
+    SET_IDREG(idregs, ID_AA64DFR0, 0x10305106);
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
     SET_IDREG(idregs, ID_AA64MMFR0, 0x00001124);
     cpu->isar.dbgdidr = 0x3516d000;
@@ -369,7 +369,7 @@ static void aarch64_a76_initfn(Object *obj)
     cpu->clidr = 0x82000023;
     cpu->ctr = 0x8444C004;
     cpu->dcz_blocksize = 4;
-    cpu->isar.id_aa64dfr0  = 0x0000000010305408ull;
+    SET_IDREG(idregs, ID_AA64DFR0, 0x0000000010305408ull),
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
     SET_IDREG(idregs, ID_AA64ISAR1, 0x0000000000100001ull);
     SET_IDREG(idregs, ID_AA64MMFR0, 0x0000000000101122ull);
@@ -440,8 +440,8 @@ static void aarch64_a64fx_initfn(Object *obj)
     cpu->reset_sctlr = 0x30000180;
     SET_IDREG(idregs, ID_AA64PFR0, 0x0000000101111111); /* No RAS Extensions */
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000000);
-    cpu->isar.id_aa64dfr0 = 0x0000000010305408;
-    cpu->isar.id_aa64dfr1 = 0x0000000000000000;
+    SET_IDREG(idregs, ID_AA64DFR0, 0x0000000010305408),
+    SET_IDREG(idregs, ID_AA64DFR1, 0x0000000000000000),
     cpu->id_aa64afr0 = 0x0000000000000000;
     cpu->id_aa64afr1 = 0x0000000000000000;
     SET_IDREG(idregs, ID_AA64MMFR0, 0x0000000000001122);
@@ -611,7 +611,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
     cpu->clidr = 0x82000023;
     cpu->ctr = 0x8444c004;
     cpu->dcz_blocksize = 4;
-    cpu->isar.id_aa64dfr0  = 0x0000000110305408ull;
+    SET_IDREG(idregs, ID_AA64DFR0, 0x0000000110305408ull);
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0000100010211120ull);
     SET_IDREG(idregs, ID_AA64ISAR1, 0x0000000000100001ull);
     SET_IDREG(idregs, ID_AA64MMFR0, 0x0000000000101125ull);
@@ -686,8 +686,8 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
     cpu->dcz_blocksize = 4;
     cpu->id_aa64afr0 = 0x00000000;
     cpu->id_aa64afr1 = 0x00000000;
-    cpu->isar.id_aa64dfr0  = 0x000001f210305519ull;
-    cpu->isar.id_aa64dfr1 = 0x00000000;
+    SET_IDREG(idregs, ID_AA64DFR0, 0x000001f210305519ull),
+    SET_IDREG(idregs, ID_AA64DFR1, 0x00000000),
     SET_IDREG(idregs, ID_AA64ISAR0, 0x1011111110212120ull); /* with FEAT_RNG */
     SET_IDREG(idregs, ID_AA64ISAR1, 0x0111000001211032ull);
     SET_IDREG(idregs, ID_AA64MMFR0, 0x0000000000101125ull);
@@ -930,8 +930,9 @@ static void aarch64_a710_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000221ull);
     SET_IDREG(idregs, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */
-    cpu->isar.id_aa64dfr0  = 0x000011f010305619ull;
-    cpu->isar.id_aa64dfr1  = 0;
+    SET_IDREG(idregs, ID_AA64DFR0, 0x000011f010305619ull);
+    SET_IDREG(idregs, ID_AA64DFR0, 0x000011f010305619ull);
+    SET_IDREG(idregs, ID_AA64DFR1, 0);
     cpu->id_aa64afr0       = 0;
     cpu->id_aa64afr1       = 0;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x0221111110212120ull); /* with Crypto */
@@ -1029,8 +1030,8 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000221ull);
     SET_IDREG(idregs, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */
-    cpu->isar.id_aa64dfr0  = 0x000011f210305619ull;
-    cpu->isar.id_aa64dfr1  = 0;
+    SET_IDREG(idregs, ID_AA64DFR0, 0x000011f210305619ull);
+    SET_IDREG(idregs, ID_AA64DFR1, 0);
     cpu->id_aa64afr0       = 0;
     cpu->id_aa64afr1       = 0;
     SET_IDREG(idregs, ID_AA64ISAR0, 0x1221111110212120ull); /* with Crypto and FEAT_RNG */
@@ -1257,11 +1258,11 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1);     /* FEAT_F64MM */
     SET_IDREG(idregs, ID_AA64ZFR0, t);
 
-    t = cpu->isar.id_aa64dfr0;
+    t = GET_IDREG(idregs, ID_AA64DFR0);
     t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 10); /* FEAT_Debugv8p8 */
     t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 6);    /* FEAT_PMUv3p5 */
     t = FIELD_DP64(t, ID_AA64DFR0, HPMN0, 1);     /* FEAT_HPMN0 */
-    cpu->isar.id_aa64dfr0 = t;
+    SET_IDREG(idregs, ID_AA64DFR0, t);
 
     t = cpu->isar.id_aa64smfr0;
     t = FIELD_DP64(t, ID_AA64SMFR0, F32F32, 1);   /* FEAT_SME */
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 08/21] arm/cpu: Store aa64smfr0 into the idregs array
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (6 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 07/21] arm/cpu: Store aa64drf0/1 " Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 09/21] arm/cpu: Store id_isar0-7 " Eric Auger
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-features.h | 6 +++---
 target/arm/cpu.h          | 1 -
 target/arm/cpu64.c        | 7 ++-----
 target/arm/helper.c       | 2 +-
 target/arm/kvm.c          | 3 +--
 target/arm/tcg/cpu64.c    | 4 ++--
 6 files changed, 9 insertions(+), 14 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 9b0d5157bf..ada5d7eccc 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -952,17 +952,17 @@ static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa64_sme_f64f64(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, F64F64);
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64SMFR0, F64F64);
 }
 
 static inline bool isar_feature_aa64_sme_i16i64(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, I16I64) == 0xf;
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64SMFR0, I16I64) == 0xf;
 }
 
 static inline bool isar_feature_aa64_sme_fa64(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, FA64);
+    return FIELD_EX64_IDREG(&id->idregs, ID_AA64SMFR0, FA64);
 }
 
 /*
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 6954952d5f..7f808e5772 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1088,7 +1088,6 @@ struct ArchCPU {
         uint32_t dbgdidr;
         uint32_t dbgdevid;
         uint32_t dbgdevid1;
-        uint64_t id_aa64smfr0;
         uint64_t reset_pmcr_el0;
         IdRegMap idregs;
     } isar;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 85f581edb7..bf3eb5d0b5 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -305,7 +305,7 @@ void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp)
 
     if (vq_map == 0) {
         if (!cpu_isar_feature(aa64_sme, cpu)) {
-            cpu->isar.id_aa64smfr0 = 0;
+            SET_IDREG(&cpu->isar.idregs, ID_AA64SMFR0, 0);
             return;
         }
 
@@ -358,11 +358,8 @@ static bool cpu_arm_get_sme_fa64(Object *obj, Error **errp)
 static void cpu_arm_set_sme_fa64(Object *obj, bool value, Error **errp)
 {
     ARMCPU *cpu = ARM_CPU(obj);
-    uint64_t t;
 
-    t = cpu->isar.id_aa64smfr0;
-    t = FIELD_DP64(t, ID_AA64SMFR0, FA64, value);
-    cpu->isar.id_aa64smfr0 = t;
+    FIELD_DP64_IDREG(&cpu->isar.idregs, ID_AA64SMFR0, FA64, value);
 }
 
 #ifdef CONFIG_USER_ONLY
diff --git a/target/arm/helper.c b/target/arm/helper.c
index c15b24933d..7e73130d35 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8900,7 +8900,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64smfr0 },
+              .resetvalue = GET_IDREG(idregs, ID_AA64SMFR0)},
             { .name = "ID_AA64PFR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 6,
               .access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 7377e4a133..e899f180f8 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -326,8 +326,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
         err = 0;
     } else {
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64PFR1_EL1);
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64smfr0,
-                              ARM64_SYS_REG(3, 0, 0, 4, 5));
+        err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64SMFR0_EL1);
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64DFR0_EL1);
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64DFR1_EL1);
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64ISAR0_EL1);
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 56f086cb28..611c252eae 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1264,7 +1264,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64DFR0, HPMN0, 1);     /* FEAT_HPMN0 */
     SET_IDREG(idregs, ID_AA64DFR0, t);
 
-    t = cpu->isar.id_aa64smfr0;
+    t = GET_IDREG(idregs, ID_AA64SMFR0);
     t = FIELD_DP64(t, ID_AA64SMFR0, F32F32, 1);   /* FEAT_SME */
     t = FIELD_DP64(t, ID_AA64SMFR0, B16F32, 1);   /* FEAT_SME */
     t = FIELD_DP64(t, ID_AA64SMFR0, F16F32, 1);   /* FEAT_SME */
@@ -1272,7 +1272,7 @@ void aarch64_max_tcg_initfn(Object *obj)
     t = FIELD_DP64(t, ID_AA64SMFR0, F64F64, 1);   /* FEAT_SME_F64F64 */
     t = FIELD_DP64(t, ID_AA64SMFR0, I16I64, 0xf); /* FEAT_SME_I16I64 */
     t = FIELD_DP64(t, ID_AA64SMFR0, FA64, 1);     /* FEAT_SME_FA64 */
-    cpu->isar.id_aa64smfr0 = t;
+    SET_IDREG(idregs, ID_AA64SMFR0, t);
 
     /* Replicate the same data to the 32-bit id registers.  */
     aa32_max_features(cpu);
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 09/21] arm/cpu: Store id_isar0-7 into the idregs array
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (7 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 08/21] arm/cpu: Store aa64smfr0 " Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 10/21] arm/cpu: Store id_mfr0/1 " Eric Auger
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-features.h |  36 +++++-----
 target/arm/cpu.h          |  14 ++--
 hw/intc/armv7m_nvic.c     |  12 ++--
 target/arm/cpu.c          |  24 +++----
 target/arm/cpu64.c        |  28 ++++----
 target/arm/helper.c       |  14 ++--
 target/arm/kvm.c          |  34 +++++----
 target/arm/tcg/cpu-v7m.c  |  90 +++++++++++++-----------
 target/arm/tcg/cpu32.c    | 143 ++++++++++++++++++++------------------
 target/arm/tcg/cpu64.c    | 108 ++++++++++++++--------------
 10 files changed, 262 insertions(+), 241 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index ada5d7eccc..306e6fa29f 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -44,93 +44,93 @@
  */
 static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR0, DIVIDE) != 0;
 }
 
 static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR0, DIVIDE) > 1;
 }
 
 static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
 {
     /* (M-profile) low-overhead loops and branch future */
-    return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR0, CMPBRANCH) >= 3;
 }
 
 static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR1, JAZELLE) != 0;
 }
 
 static inline bool isar_feature_aa32_aes(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR5, AES) != 0;
 }
 
 static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) > 1;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR5, AES) > 1;
 }
 
 static inline bool isar_feature_aa32_sha1(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA1) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR5, SHA1) != 0;
 }
 
 static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA2) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR5, SHA2) != 0;
 }
 
 static inline bool isar_feature_aa32_crc32(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar5, ID_ISAR5, CRC32) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR5, CRC32) != 0;
 }
 
 static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar5, ID_ISAR5, RDM) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR5, RDM) != 0;
 }
 
 static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR5, VCMA) != 0;
 }
 
 static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR6, JSCVT) != 0;
 }
 
 static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR6, DP) != 0;
 }
 
 static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR6, FHM) != 0;
 }
 
 static inline bool isar_feature_aa32_sb(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR6, SB) != 0;
 }
 
 static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR6, SPECRES) != 0;
 }
 
 static inline bool isar_feature_aa32_bf16(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar6, ID_ISAR6, BF16) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR6, BF16) != 0;
 }
 
 static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar6, ID_ISAR6, I8MM) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_ISAR6, I8MM) != 0;
 }
 
 static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 7f808e5772..1c4fa6a561 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -871,6 +871,13 @@ regval = FIELD_DP64(regval, REG, FIELD, VALUE);               \
 _set_idreg(MAP, SYS_ ## REG ## _EL1, regval);                 \
 }
 
+#define FIELD_DP32_IDREG(MAP, REG, FIELD, VALUE)              \
+{                                                             \
+uint64_t regval = _get_idreg(MAP, SYS_ ## REG ## _EL1);       \
+regval = FIELD_DP32(regval, REG, FIELD, VALUE);               \
+_set_idreg(MAP, SYS_ ## REG ## _EL1, regval);                 \
+}
+
 #define FIELD_EX64_IDREG(MAP, REG, FIELD)                     \
 FIELD_EX64(_get_idreg(MAP, SYS_ ## REG ## _EL1), REG, FIELD)  \
 
@@ -1064,13 +1071,6 @@ struct ArchCPU {
      * field by reading the value from the KVM vCPU.
      */
     struct ARMISARegisters {
-        uint32_t id_isar0;
-        uint32_t id_isar1;
-        uint32_t id_isar2;
-        uint32_t id_isar3;
-        uint32_t id_isar4;
-        uint32_t id_isar5;
-        uint32_t id_isar6;
         uint32_t id_mmfr0;
         uint32_t id_mmfr1;
         uint32_t id_mmfr2;
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 404a445138..818f6fdfa9 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -1303,32 +1303,32 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_isar0;
+        return GET_IDREG(&cpu->isar.idregs, ID_ISAR0);
     case 0xd64: /* ISAR1.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_isar1;
+        return GET_IDREG(&cpu->isar.idregs, ID_ISAR1);
     case 0xd68: /* ISAR2.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_isar2;
+        return GET_IDREG(&cpu->isar.idregs, ID_ISAR2);
     case 0xd6c: /* ISAR3.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_isar3;
+        return GET_IDREG(&cpu->isar.idregs, ID_ISAR3);
     case 0xd70: /* ISAR4.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_isar4;
+        return GET_IDREG(&cpu->isar.idregs, ID_ISAR4);
     case 0xd74: /* ISAR5.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_isar5;
+        return GET_IDREG(&cpu->isar.idregs, ID_ISAR5);
     case 0xd78: /* CLIDR */
         return cpu->clidr;
     case 0xd7c: /* CTR */
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 42664dbfc1..bc80945da1 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2127,10 +2127,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
 
         FIELD_DP64_IDREG(idregs, ID_AA64PFR0, FP, 0xf);
 
-        u = cpu->isar.id_isar6;
+        u = GET_IDREG(idregs, ID_ISAR6);
         u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0);
         u = FIELD_DP32(u, ID_ISAR6, BF16, 0);
-        cpu->isar.id_isar6 = u;
+        SET_IDREG(idregs, ID_ISAR6, u);
 
         u = cpu->isar.mvfr0;
         u = FIELD_DP32(u, MVFR0, FPSP, 0);
@@ -2182,20 +2182,20 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
 
         FIELD_DP64_IDREG(idregs, ID_AA64PFR0, ADVSIMD, 0xf);
 
-        u = cpu->isar.id_isar5;
+        u = GET_IDREG(idregs, ID_ISAR5);
         u = FIELD_DP32(u, ID_ISAR5, AES, 0);
         u = FIELD_DP32(u, ID_ISAR5, SHA1, 0);
         u = FIELD_DP32(u, ID_ISAR5, SHA2, 0);
         u = FIELD_DP32(u, ID_ISAR5, RDM, 0);
         u = FIELD_DP32(u, ID_ISAR5, VCMA, 0);
-        cpu->isar.id_isar5 = u;
+        SET_IDREG(idregs, ID_ISAR5, u);
 
-        u = cpu->isar.id_isar6;
+        u = GET_IDREG(idregs, ID_ISAR6);
         u = FIELD_DP32(u, ID_ISAR6, DP, 0);
         u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
         u = FIELD_DP32(u, ID_ISAR6, BF16, 0);
         u = FIELD_DP32(u, ID_ISAR6, I8MM, 0);
-        cpu->isar.id_isar6 = u;
+        SET_IDREG(idregs, ID_ISAR6, u);
 
         if (!arm_feature(env, ARM_FEATURE_M)) {
             u = cpu->isar.mvfr1;
@@ -2233,19 +2233,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
 
         unset_feature(env, ARM_FEATURE_THUMB_DSP);
 
-        u = cpu->isar.id_isar1;
-        u = FIELD_DP32(u, ID_ISAR1, EXTEND, 1);
-        cpu->isar.id_isar1 = u;
+        FIELD_DP32_IDREG(idregs, ID_ISAR1, EXTEND, 1);
 
-        u = cpu->isar.id_isar2;
+        u = GET_IDREG(idregs, ID_ISAR2);
         u = FIELD_DP32(u, ID_ISAR2, MULTU, 1);
         u = FIELD_DP32(u, ID_ISAR2, MULTS, 1);
-        cpu->isar.id_isar2 = u;
+        SET_IDREG(idregs, ID_ISAR2, u);
 
-        u = cpu->isar.id_isar3;
+        u = GET_IDREG(idregs, ID_ISAR3);
         u = FIELD_DP32(u, ID_ISAR3, SIMD, 1);
         u = FIELD_DP32(u, ID_ISAR3, SATURATE, 0);
-        cpu->isar.id_isar3 = u;
+        SET_IDREG(idregs, ID_ISAR3, u);
     }
 
 
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index bf3eb5d0b5..9c3784a35f 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -619,13 +619,13 @@ static void aarch64_a57_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x40000000;
     cpu->isar.id_mmfr2 = 0x01260000;
     cpu->isar.id_mmfr3 = 0x02102211;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232042;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00011142;
-    cpu->isar.id_isar5 = 0x00011121;
-    cpu->isar.id_isar6 = 0;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232042);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00011142);
+    SET_IDREG(idregs, ID_ISAR5, 0x00011121);
+    SET_IDREG(idregs, ID_ISAR6, 0);
     SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
     SET_IDREG(idregs, ID_AA64DFR0, 0x10305106);
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
@@ -678,13 +678,13 @@ static void aarch64_a53_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x40000000;
     cpu->isar.id_mmfr2 = 0x01260000;
     cpu->isar.id_mmfr3 = 0x02102211;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232042;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00011142;
-    cpu->isar.id_isar5 = 0x00011121;
-    cpu->isar.id_isar6 = 0;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232042);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00011142);
+    SET_IDREG(idregs, ID_ISAR5, 0x00011121);
+    SET_IDREG(idregs, ID_ISAR6, 0);
     SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
     SET_IDREG(idregs, ID_AA64DFR0, 0x10305106);
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 7e73130d35..1782de26f5 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8778,32 +8778,32 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_isar0 },
+              .resetvalue = GET_IDREG(idregs, ID_ISAR0)},
             { .name = "ID_ISAR1", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 1,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_isar1 },
+              .resetvalue = GET_IDREG(idregs, ID_ISAR1)},
             { .name = "ID_ISAR2", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_isar2 },
+              .resetvalue = GET_IDREG(idregs, ID_ISAR2)},
             { .name = "ID_ISAR3", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 3,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_isar3 },
+              .resetvalue = GET_IDREG(idregs, ID_ISAR3) },
             { .name = "ID_ISAR4", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 4,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_isar4 },
+              .resetvalue = GET_IDREG(idregs, ID_ISAR4) },
             { .name = "ID_ISAR5", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 5,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_isar5 },
+              .resetvalue = GET_IDREG(idregs, ID_ISAR5) },
             { .name = "ID_MMFR4", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6,
               .access = PL1_R, .type = ARM_CP_CONST,
@@ -8813,7 +8813,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_isar6 },
+              .resetvalue = GET_IDREG(idregs, ID_ISAR6) },
         };
         define_arm_cp_regs(cpu, v6_idregs);
         define_arm_cp_regs(cpu, v6_cp_reginfo);
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index e899f180f8..9873f8e849 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -231,6 +231,18 @@ static bool kvm_arm_pauth_supported(void)
             kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_GENERIC));
 }
 
+/* read a 32b sysreg value and store it in the idregs */
+static int get_host_cpu_reg32(int fd, ARMHostCPUFeatures *ahcf, ARMSysReg sr)
+{
+    int index = KVM_ARM_FEATURE_ID_RANGE_IDX(sr.op0, sr.op1, sr.crn, sr.crm, sr.op2);
+    uint64_t *reg = &ahcf->isar.idregs.regs[index];
+    int ret;
+
+    ret = read_sys_reg32(fd, (uint32_t *)reg,
+                         ARM64_SYS_REG(sr.op0, sr.op1, sr.crn, sr.crm, sr.op2));
+    return ret;
+}
+
 /* read a 64b sysreg value and store it in the idregs */
 static int get_host_cpu_reg64(int fd, ARMHostCPUFeatures *ahcf, ARMSysReg sr)
 {
@@ -243,6 +255,7 @@ static int get_host_cpu_reg64(int fd, ARMHostCPUFeatures *ahcf, ARMSysReg sr)
     return ret;
 }
 
+
 static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
 {
     /* Identify the feature bits corresponding to the host CPU, and
@@ -356,22 +369,15 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
                               ARM64_SYS_REG(3, 0, 0, 1, 6));
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
                               ARM64_SYS_REG(3, 0, 0, 1, 7));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0,
-                              ARM64_SYS_REG(3, 0, 0, 2, 0));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1,
-                              ARM64_SYS_REG(3, 0, 0, 2, 1));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2,
-                              ARM64_SYS_REG(3, 0, 0, 2, 2));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3,
-                              ARM64_SYS_REG(3, 0, 0, 2, 3));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4,
-                              ARM64_SYS_REG(3, 0, 0, 2, 4));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5,
-                              ARM64_SYS_REG(3, 0, 0, 2, 5));
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR0_EL1);
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR1_EL1);
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR2_EL1);
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR3_EL1);
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR4_EL1);
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR5_EL1);
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR6_EL1);
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
                               ARM64_SYS_REG(3, 0, 0, 2, 6));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6,
-                              ARM64_SYS_REG(3, 0, 0, 2, 7));
 
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0,
                               ARM64_SYS_REG(3, 0, 0, 3, 0));
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
index c059c681e9..fbde43d45e 100644
--- a/target/arm/tcg/cpu-v7m.c
+++ b/target/arm/tcg/cpu-v7m.c
@@ -46,6 +46,7 @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 static void cortex_m0_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
     set_feature(&cpu->env, ARM_FEATURE_V6);
     set_feature(&cpu->env, ARM_FEATURE_M);
 
@@ -67,18 +68,19 @@ static void cortex_m0_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x00000000;
     cpu->isar.id_mmfr2 = 0x00000000;
     cpu->isar.id_mmfr3 = 0x00000000;
-    cpu->isar.id_isar0 = 0x01141110;
-    cpu->isar.id_isar1 = 0x02111000;
-    cpu->isar.id_isar2 = 0x21112231;
-    cpu->isar.id_isar3 = 0x01111110;
-    cpu->isar.id_isar4 = 0x01310102;
-    cpu->isar.id_isar5 = 0x00000000;
-    cpu->isar.id_isar6 = 0x00000000;
+    SET_IDREG(idregs, ID_ISAR0, 0x01141110);
+    SET_IDREG(idregs, ID_ISAR1, 0x02111000);
+    SET_IDREG(idregs, ID_ISAR2, 0x21112231);
+    SET_IDREG(idregs, ID_ISAR3, 0x01111110);
+    SET_IDREG(idregs, ID_ISAR4, 0x01310102);
+    SET_IDREG(idregs, ID_ISAR5, 0x00000000);
+    SET_IDREG(idregs, ID_ISAR6, 0x00000000);
 }
 
 static void cortex_m3_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
     set_feature(&cpu->env, ARM_FEATURE_V7);
     set_feature(&cpu->env, ARM_FEATURE_M);
     set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
@@ -92,18 +94,19 @@ static void cortex_m3_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x00000000;
     cpu->isar.id_mmfr2 = 0x00000000;
     cpu->isar.id_mmfr3 = 0x00000000;
-    cpu->isar.id_isar0 = 0x01141110;
-    cpu->isar.id_isar1 = 0x02111000;
-    cpu->isar.id_isar2 = 0x21112231;
-    cpu->isar.id_isar3 = 0x01111110;
-    cpu->isar.id_isar4 = 0x01310102;
-    cpu->isar.id_isar5 = 0x00000000;
-    cpu->isar.id_isar6 = 0x00000000;
+    SET_IDREG(idregs, ID_ISAR0, 0x01141110);
+    SET_IDREG(idregs, ID_ISAR1, 0x02111000);
+    SET_IDREG(idregs, ID_ISAR2, 0x21112231);
+    SET_IDREG(idregs, ID_ISAR3, 0x01111110);
+    SET_IDREG(idregs, ID_ISAR4, 0x01310102);
+    SET_IDREG(idregs, ID_ISAR5, 0x00000000);
+    SET_IDREG(idregs, ID_ISAR6, 0x00000000);
 }
 
 static void cortex_m4_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     set_feature(&cpu->env, ARM_FEATURE_V7);
     set_feature(&cpu->env, ARM_FEATURE_M);
@@ -122,18 +125,19 @@ static void cortex_m4_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x00000000;
     cpu->isar.id_mmfr2 = 0x00000000;
     cpu->isar.id_mmfr3 = 0x00000000;
-    cpu->isar.id_isar0 = 0x01141110;
-    cpu->isar.id_isar1 = 0x02111000;
-    cpu->isar.id_isar2 = 0x21112231;
-    cpu->isar.id_isar3 = 0x01111110;
-    cpu->isar.id_isar4 = 0x01310102;
-    cpu->isar.id_isar5 = 0x00000000;
-    cpu->isar.id_isar6 = 0x00000000;
+    SET_IDREG(idregs, ID_ISAR0, 0x01141110);
+    SET_IDREG(idregs, ID_ISAR1, 0x02111000);
+    SET_IDREG(idregs, ID_ISAR2, 0x21112231);
+    SET_IDREG(idregs, ID_ISAR3, 0x01111110);
+    SET_IDREG(idregs, ID_ISAR4, 0x01310102);
+    SET_IDREG(idregs, ID_ISAR5, 0x00000000);
+    SET_IDREG(idregs, ID_ISAR6, 0x00000000);
 }
 
 static void cortex_m7_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     set_feature(&cpu->env, ARM_FEATURE_V7);
     set_feature(&cpu->env, ARM_FEATURE_M);
@@ -152,18 +156,19 @@ static void cortex_m7_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x00000000;
     cpu->isar.id_mmfr2 = 0x01000000;
     cpu->isar.id_mmfr3 = 0x00000000;
-    cpu->isar.id_isar0 = 0x01101110;
-    cpu->isar.id_isar1 = 0x02112000;
-    cpu->isar.id_isar2 = 0x20232231;
-    cpu->isar.id_isar3 = 0x01111131;
-    cpu->isar.id_isar4 = 0x01310132;
-    cpu->isar.id_isar5 = 0x00000000;
-    cpu->isar.id_isar6 = 0x00000000;
+    SET_IDREG(idregs, ID_ISAR0, 0x01101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x02112000);
+    SET_IDREG(idregs, ID_ISAR2, 0x20232231);
+    SET_IDREG(idregs, ID_ISAR3, 0x01111131);
+    SET_IDREG(idregs, ID_ISAR4, 0x01310132);
+    SET_IDREG(idregs, ID_ISAR5, 0x00000000);
+    SET_IDREG(idregs, ID_ISAR6, 0x00000000);
 }
 
 static void cortex_m33_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     set_feature(&cpu->env, ARM_FEATURE_V8);
     set_feature(&cpu->env, ARM_FEATURE_M);
@@ -184,13 +189,13 @@ static void cortex_m33_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x00000000;
     cpu->isar.id_mmfr2 = 0x01000000;
     cpu->isar.id_mmfr3 = 0x00000000;
-    cpu->isar.id_isar0 = 0x01101110;
-    cpu->isar.id_isar1 = 0x02212000;
-    cpu->isar.id_isar2 = 0x20232232;
-    cpu->isar.id_isar3 = 0x01111131;
-    cpu->isar.id_isar4 = 0x01310132;
-    cpu->isar.id_isar5 = 0x00000000;
-    cpu->isar.id_isar6 = 0x00000000;
+    SET_IDREG(idregs, ID_ISAR0, 0x01101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x02212000);
+    SET_IDREG(idregs, ID_ISAR2, 0x20232232);
+    SET_IDREG(idregs, ID_ISAR3, 0x01111131);
+    SET_IDREG(idregs, ID_ISAR4, 0x01310132);
+    SET_IDREG(idregs, ID_ISAR5, 0x00000000);
+    SET_IDREG(idregs, ID_ISAR6, 0x00000000);
     cpu->clidr = 0x00000000;
     cpu->ctr = 0x8000c000;
 }
@@ -198,6 +203,7 @@ static void cortex_m33_initfn(Object *obj)
 static void cortex_m55_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     set_feature(&cpu->env, ARM_FEATURE_V8);
     set_feature(&cpu->env, ARM_FEATURE_V8_1M);
@@ -221,13 +227,13 @@ static void cortex_m55_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x00000000;
     cpu->isar.id_mmfr2 = 0x01000000;
     cpu->isar.id_mmfr3 = 0x00000011;
-    cpu->isar.id_isar0 = 0x01103110;
-    cpu->isar.id_isar1 = 0x02212000;
-    cpu->isar.id_isar2 = 0x20232232;
-    cpu->isar.id_isar3 = 0x01111131;
-    cpu->isar.id_isar4 = 0x01310132;
-    cpu->isar.id_isar5 = 0x00000000;
-    cpu->isar.id_isar6 = 0x00000000;
+    SET_IDREG(idregs, ID_ISAR0, 0x01103110);
+    SET_IDREG(idregs, ID_ISAR1, 0x02212000);
+    SET_IDREG(idregs, ID_ISAR2, 0x20232232);
+    SET_IDREG(idregs, ID_ISAR3, 0x01111131);
+    SET_IDREG(idregs, ID_ISAR4, 0x01310132);
+    SET_IDREG(idregs, ID_ISAR5, 0x00000000);
+    SET_IDREG(idregs, ID_ISAR6, 0x00000000);
     cpu->clidr = 0x00000000; /* caches not implemented */
     cpu->ctr = 0x8303c003;
 }
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
index 20c2737f17..ae5c909048 100644
--- a/target/arm/tcg/cpu32.c
+++ b/target/arm/tcg/cpu32.c
@@ -25,16 +25,16 @@ void aa32_max_features(ARMCPU *cpu)
     uint32_t t;
 
     /* Add additional features supported by QEMU */
-    t = cpu->isar.id_isar5;
+    t = GET_IDREG(&cpu->isar.idregs, ID_ISAR5);
     t = FIELD_DP32(t, ID_ISAR5, AES, 2);          /* FEAT_PMULL */
     t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);         /* FEAT_SHA1 */
     t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);         /* FEAT_SHA256 */
     t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
     t = FIELD_DP32(t, ID_ISAR5, RDM, 1);          /* FEAT_RDM */
     t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);         /* FEAT_FCMA */
-    cpu->isar.id_isar5 = t;
+    SET_IDREG(&cpu->isar.idregs, ID_ISAR5, t);
 
-    t = cpu->isar.id_isar6;
+    t = GET_IDREG(&cpu->isar.idregs, ID_ISAR6);
     t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);        /* FEAT_JSCVT */
     t = FIELD_DP32(t, ID_ISAR6, DP, 1);           /* Feat_DotProd */
     t = FIELD_DP32(t, ID_ISAR6, FHM, 1);          /* FEAT_FHM */
@@ -42,7 +42,7 @@ void aa32_max_features(ARMCPU *cpu)
     t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);      /* FEAT_SPECRES */
     t = FIELD_DP32(t, ID_ISAR6, BF16, 1);         /* FEAT_AA32BF16 */
     t = FIELD_DP32(t, ID_ISAR6, I8MM, 1);         /* FEAT_AA32I8MM */
-    cpu->isar.id_isar6 = t;
+    SET_IDREG(&cpu->isar.idregs, ID_ISAR6, t);
 
     t = cpu->isar.mvfr1;
     t = FIELD_DP32(t, MVFR1, FPHP, 3);            /* FEAT_FP16 */
@@ -140,7 +140,7 @@ static void arm926_initfn(Object *obj)
      * ARMv5 does not have the ID_ISAR registers, but we can still
      * set the field to indicate Jazelle support within QEMU.
      */
-    cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1);
+    FIELD_DP32_IDREG(&cpu->isar.idregs, ID_ISAR1, JAZELLE, 1);
     /*
      * Similarly, we need to set MVFR0 fields to enable vfp and short vector
      * support even though ARMv5 doesn't have this register.
@@ -182,7 +182,7 @@ static void arm1026_initfn(Object *obj)
      * ARMv5 does not have the ID_ISAR registers, but we can still
      * set the field to indicate Jazelle support within QEMU.
      */
-    cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1);
+    FIELD_DP32_IDREG(&cpu->isar.idregs, ID_ISAR1, JAZELLE, 1);
     /*
      * Similarly, we need to set MVFR0 fields to enable vfp and short vector
      * support even though ARMv5 doesn't have this register.
@@ -206,6 +206,7 @@ static void arm1026_initfn(Object *obj)
 static void arm1136_r2_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
     /*
      * What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an
      * older core than plain "arm1136". In particular this does not
@@ -233,17 +234,18 @@ static void arm1136_r2_initfn(Object *obj)
     cpu->isar.id_mmfr0 = 0x01130003;
     cpu->isar.id_mmfr1 = 0x10030302;
     cpu->isar.id_mmfr2 = 0x01222110;
-    cpu->isar.id_isar0 = 0x00140011;
-    cpu->isar.id_isar1 = 0x12002111;
-    cpu->isar.id_isar2 = 0x11231111;
-    cpu->isar.id_isar3 = 0x01102131;
-    cpu->isar.id_isar4 = 0x141;
+    SET_IDREG(idregs, ID_ISAR0, 0x00140011);
+    SET_IDREG(idregs, ID_ISAR1, 0x12002111);
+    SET_IDREG(idregs, ID_ISAR2, 0x11231111);
+    SET_IDREG(idregs, ID_ISAR3, 0x01102131);
+    SET_IDREG(idregs, ID_ISAR4, 0x141);
     cpu->reset_auxcr = 7;
 }
 
 static void arm1136_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,arm1136";
     set_feature(&cpu->env, ARM_FEATURE_V6K);
@@ -264,17 +266,18 @@ static void arm1136_initfn(Object *obj)
     cpu->isar.id_mmfr0 = 0x01130003;
     cpu->isar.id_mmfr1 = 0x10030302;
     cpu->isar.id_mmfr2 = 0x01222110;
-    cpu->isar.id_isar0 = 0x00140011;
-    cpu->isar.id_isar1 = 0x12002111;
-    cpu->isar.id_isar2 = 0x11231111;
-    cpu->isar.id_isar3 = 0x01102131;
-    cpu->isar.id_isar4 = 0x141;
+    SET_IDREG(idregs, ID_ISAR0, 0x00140011);
+    SET_IDREG(idregs, ID_ISAR1, 0x12002111);
+    SET_IDREG(idregs, ID_ISAR2, 0x11231111);
+    SET_IDREG(idregs, ID_ISAR3, 0x01102131);
+    SET_IDREG(idregs, ID_ISAR4, 0x141);
     cpu->reset_auxcr = 7;
 }
 
 static void arm1176_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,arm1176";
     set_feature(&cpu->env, ARM_FEATURE_V6K);
@@ -296,17 +299,18 @@ static void arm1176_initfn(Object *obj)
     cpu->isar.id_mmfr0 = 0x01130003;
     cpu->isar.id_mmfr1 = 0x10030302;
     cpu->isar.id_mmfr2 = 0x01222100;
-    cpu->isar.id_isar0 = 0x0140011;
-    cpu->isar.id_isar1 = 0x12002111;
-    cpu->isar.id_isar2 = 0x11231121;
-    cpu->isar.id_isar3 = 0x01102131;
-    cpu->isar.id_isar4 = 0x01141;
+    SET_IDREG(idregs, ID_ISAR0, 0x0140011);
+    SET_IDREG(idregs, ID_ISAR1, 0x12002111);
+    SET_IDREG(idregs, ID_ISAR2, 0x11231121);
+    SET_IDREG(idregs, ID_ISAR3, 0x01102131);
+    SET_IDREG(idregs, ID_ISAR4, 0x01141);
     cpu->reset_auxcr = 7;
 }
 
 static void arm11mpcore_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,arm11mpcore";
     set_feature(&cpu->env, ARM_FEATURE_V6K);
@@ -325,11 +329,11 @@ static void arm11mpcore_initfn(Object *obj)
     cpu->isar.id_mmfr0 = 0x01100103;
     cpu->isar.id_mmfr1 = 0x10020302;
     cpu->isar.id_mmfr2 = 0x01222000;
-    cpu->isar.id_isar0 = 0x00100011;
-    cpu->isar.id_isar1 = 0x12002111;
-    cpu->isar.id_isar2 = 0x11221011;
-    cpu->isar.id_isar3 = 0x01102131;
-    cpu->isar.id_isar4 = 0x141;
+    SET_IDREG(idregs, ID_ISAR0, 0x00100011);
+    SET_IDREG(idregs, ID_ISAR1, 0x12002111);
+    SET_IDREG(idregs, ID_ISAR2, 0x11221011);
+    SET_IDREG(idregs, ID_ISAR3, 0x01102131);
+    SET_IDREG(idregs, ID_ISAR4, 0x141);
     cpu->reset_auxcr = 1;
 }
 
@@ -343,6 +347,7 @@ static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
 static void cortex_a8_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,cortex-a8";
     set_feature(&cpu->env, ARM_FEATURE_V7);
@@ -365,11 +370,11 @@ static void cortex_a8_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x20000000;
     cpu->isar.id_mmfr2 = 0x01202000;
     cpu->isar.id_mmfr3 = 0x11;
-    cpu->isar.id_isar0 = 0x00101111;
-    cpu->isar.id_isar1 = 0x12112111;
-    cpu->isar.id_isar2 = 0x21232031;
-    cpu->isar.id_isar3 = 0x11112131;
-    cpu->isar.id_isar4 = 0x00111142;
+    SET_IDREG(idregs, ID_ISAR0, 0x00101111);
+    SET_IDREG(idregs, ID_ISAR1, 0x12112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232031);
+    SET_IDREG(idregs, ID_ISAR3, 0x11112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00111142);
     cpu->isar.dbgdidr = 0x15141000;
     cpu->clidr = (1 << 27) | (2 << 24) | 3;
     cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
@@ -412,6 +417,7 @@ static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
 static void cortex_a9_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,cortex-a9";
     set_feature(&cpu->env, ARM_FEATURE_V7);
@@ -440,11 +446,11 @@ static void cortex_a9_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x20000000;
     cpu->isar.id_mmfr2 = 0x01230000;
     cpu->isar.id_mmfr3 = 0x00002111;
-    cpu->isar.id_isar0 = 0x00101111;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232041;
-    cpu->isar.id_isar3 = 0x11112131;
-    cpu->isar.id_isar4 = 0x00111142;
+    SET_IDREG(idregs, ID_ISAR0, 0x00101111);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232041);
+    SET_IDREG(idregs, ID_ISAR3, 0x11112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00111142);
     cpu->isar.dbgdidr = 0x35141000;
     cpu->clidr = (1 << 27) | (1 << 24) | 3;
     cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
@@ -479,6 +485,7 @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
 static void cortex_a7_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,cortex-a7";
     set_feature(&cpu->env, ARM_FEATURE_V7VE);
@@ -509,11 +516,11 @@ static void cortex_a7_initfn(Object *obj)
      * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
      * table 4-41 gives 0x02101110, which includes the arm div insns.
      */
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232041;
-    cpu->isar.id_isar3 = 0x11112131;
-    cpu->isar.id_isar4 = 0x10011142;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232041);
+    SET_IDREG(idregs, ID_ISAR3, 0x11112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x10011142);
     cpu->isar.dbgdidr = 0x3515f005;
     cpu->isar.dbgdevid = 0x01110f13;
     cpu->isar.dbgdevid1 = 0x1;
@@ -528,6 +535,7 @@ static void cortex_a7_initfn(Object *obj)
 static void cortex_a15_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     cpu->dtb_compatible = "arm,cortex-a15";
     set_feature(&cpu->env, ARM_FEATURE_V7VE);
@@ -556,11 +564,11 @@ static void cortex_a15_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x20000000;
     cpu->isar.id_mmfr2 = 0x01240000;
     cpu->isar.id_mmfr3 = 0x02102211;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232041;
-    cpu->isar.id_isar3 = 0x11112131;
-    cpu->isar.id_isar4 = 0x10011142;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232041);
+    SET_IDREG(idregs, ID_ISAR3, 0x11112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x10011142);
     cpu->isar.dbgdidr = 0x3515f021;
     cpu->isar.dbgdevid = 0x01110f13;
     cpu->isar.dbgdevid1 = 0x0;
@@ -585,6 +593,7 @@ static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
 static void cortex_r5_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     set_feature(&cpu->env, ARM_FEATURE_V7);
     set_feature(&cpu->env, ARM_FEATURE_V7MP);
@@ -599,13 +608,13 @@ static void cortex_r5_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x00000000;
     cpu->isar.id_mmfr2 = 0x01200000;
     cpu->isar.id_mmfr3 = 0x0211;
-    cpu->isar.id_isar0 = 0x02101111;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232141;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x0010142;
-    cpu->isar.id_isar5 = 0x0;
-    cpu->isar.id_isar6 = 0x0;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101111);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232141);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x0010142);
+    SET_IDREG(idregs, ID_ISAR5, 0x21232141);
+    SET_IDREG(idregs, ID_ISAR6, 0x0);
     cpu->mp_is_up = true;
     cpu->pmsav7_dregion = 16;
     cpu->isar.reset_pmcr_el0 = 0x41151800;
@@ -720,6 +729,7 @@ static const ARMCPRegInfo cortex_r52_cp_reginfo[] = {
 static void cortex_r52_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     set_feature(&cpu->env, ARM_FEATURE_V8);
     set_feature(&cpu->env, ARM_FEATURE_EL2);
@@ -746,12 +756,12 @@ static void cortex_r52_initfn(Object *obj)
     cpu->isar.id_mmfr2 = 0x01200000;
     cpu->isar.id_mmfr3 = 0xf0102211;
     cpu->isar.id_mmfr4 = 0x00000010;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232142;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00010142;
-    cpu->isar.id_isar5 = 0x00010001;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232142);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00010142);
+    SET_IDREG(idregs, ID_ISAR5, 0x00010001);
     cpu->isar.dbgdidr = 0x77168000;
     cpu->clidr = (1 << 27) | (1 << 24) | 0x3;
     cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */
@@ -949,6 +959,7 @@ static void pxa270c5_initfn(Object *obj)
 static void arm_max_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     /* aarch64_a57_initfn, advertising none of the aarch64 features */
     cpu->dtb_compatible = "arm,cortex-a57";
@@ -976,13 +987,13 @@ static void arm_max_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x40000000;
     cpu->isar.id_mmfr2 = 0x01260000;
     cpu->isar.id_mmfr3 = 0x02102211;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232042;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00011142;
-    cpu->isar.id_isar5 = 0x00011121;
-    cpu->isar.id_isar6 = 0;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232042);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00011142);
+    SET_IDREG(idregs, ID_ISAR5, 0x00011121);
+    SET_IDREG(idregs, ID_ISAR6, 0);
     cpu->isar.reset_pmcr_el0 = 0x41013000;
     cpu->clidr = 0x0a200023;
     cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 611c252eae..cdaba9b184 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -83,12 +83,12 @@ static void aarch64_a35_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x40000000;
     cpu->isar.id_mmfr2 = 0x01260000;
     cpu->isar.id_mmfr3 = 0x02102211;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232042;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00011142;
-    cpu->isar.id_isar5 = 0x00011121;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232042);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00011142);
+    SET_IDREG(idregs, ID_ISAR5, 0x00011121);
     SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
     SET_IDREG(idregs, ID_AA64PFR1, 0);
     SET_IDREG(idregs, ID_AA64DFR0, 0x10305106);
@@ -252,13 +252,13 @@ static void aarch64_a55_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000010ull);
     cpu->id_afr0       = 0x00000000;
     cpu->isar.id_dfr0  = 0x04010088;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232042;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00011142;
-    cpu->isar.id_isar5 = 0x01011121;
-    cpu->isar.id_isar6 = 0x00000010;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232042);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00011142);
+    SET_IDREG(idregs, ID_ISAR5, 0x01011121);
+    SET_IDREG(idregs, ID_ISAR6, 0x00000010);
     cpu->isar.id_mmfr0 = 0x10201105;
     cpu->isar.id_mmfr1 = 0x40000000;
     cpu->isar.id_mmfr2 = 0x01260000;
@@ -323,12 +323,12 @@ static void aarch64_a72_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x40000000;
     cpu->isar.id_mmfr2 = 0x01260000;
     cpu->isar.id_mmfr3 = 0x02102211;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232042;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00011142;
-    cpu->isar.id_isar5 = 0x00011121;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232042);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00011142);
+    SET_IDREG(idregs, ID_ISAR5, 0x00011121);
     SET_IDREG(idregs, ID_AA64PFR0, 0x00002222);
     SET_IDREG(idregs, ID_AA64DFR0, 0x10305106);
     SET_IDREG(idregs, ID_AA64ISAR0, 0x00011120);
@@ -379,13 +379,13 @@ static void aarch64_a76_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000010ull);
     cpu->id_afr0       = 0x00000000;
     cpu->isar.id_dfr0  = 0x04010088;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232042;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00010142;
-    cpu->isar.id_isar5 = 0x01011121;
-    cpu->isar.id_isar6 = 0x00000010;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232042);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00010142);
+    SET_IDREG(idregs, ID_ISAR5, 0x01011121);
+    SET_IDREG(idregs, ID_ISAR6, 0x00000010);
     cpu->isar.id_mmfr0 = 0x10201105;
     cpu->isar.id_mmfr1 = 0x40000000;
     cpu->isar.id_mmfr2 = 0x01260000;
@@ -621,13 +621,13 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000020ull);
     cpu->id_afr0       = 0x00000000;
     cpu->isar.id_dfr0  = 0x04010088;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232042;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00010142;
-    cpu->isar.id_isar5 = 0x01011121;
-    cpu->isar.id_isar6 = 0x00000010;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232042);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00010142);
+    SET_IDREG(idregs, ID_ISAR5, 0x01011121);
+    SET_IDREG(idregs, ID_ISAR6, 0x00000010);
     cpu->isar.id_mmfr0 = 0x10201105;
     cpu->isar.id_mmfr1 = 0x40000000;
     cpu->isar.id_mmfr2 = 0x01260000;
@@ -697,13 +697,13 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000020ull);
     cpu->id_afr0       = 0x00000000;
     cpu->isar.id_dfr0  = 0x15011099;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232042;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00010142;
-    cpu->isar.id_isar5 = 0x11011121;
-    cpu->isar.id_isar6 = 0x01100111;
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232042);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00010142);
+    SET_IDREG(idregs, ID_ISAR5, 0x11011121);
+    SET_IDREG(idregs, ID_ISAR6, 0x01100111);
     cpu->isar.id_mmfr0 = 0x10201105;
     cpu->isar.id_mmfr1 = 0x40000000;
     cpu->isar.id_mmfr2 = 0x01260000;
@@ -915,14 +915,14 @@ static void aarch64_a710_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x40000000;
     cpu->isar.id_mmfr2 = 0x01260000;
     cpu->isar.id_mmfr3 = 0x02122211;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232042;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00010142;
-    cpu->isar.id_isar5 = 0x11011121; /* with Crypto */
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232042);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00010142);
+    SET_IDREG(idregs, ID_ISAR5, 0x11011121); /* with Crypto */
     cpu->isar.id_mmfr4 = 0x21021110;
-    cpu->isar.id_isar6 = 0x01111111;
+    SET_IDREG(idregs, ID_ISAR6, 0x01111111);
     cpu->isar.mvfr0    = 0x10110222;
     cpu->isar.mvfr1    = 0x13211111;
     cpu->isar.mvfr2    = 0x00000043;
@@ -1015,14 +1015,14 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
     cpu->isar.id_mmfr1 = 0x40000000;
     cpu->isar.id_mmfr2 = 0x01260000;
     cpu->isar.id_mmfr3 = 0x02122211;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232042;
-    cpu->isar.id_isar3 = 0x01112131;
-    cpu->isar.id_isar4 = 0x00010142;
-    cpu->isar.id_isar5 = 0x11011121; /* with Crypto */
+    SET_IDREG(idregs, ID_ISAR0, 0x02101110);
+    SET_IDREG(idregs, ID_ISAR1, 0x13112111);
+    SET_IDREG(idregs, ID_ISAR2, 0x21232042);
+    SET_IDREG(idregs, ID_ISAR3, 0x01112131);
+    SET_IDREG(idregs, ID_ISAR4, 0x00010142);
+    SET_IDREG(idregs, ID_ISAR5, 0x11011121); /* with Crypto */
     cpu->isar.id_mmfr4 = 0x01021110;
-    cpu->isar.id_isar6 = 0x01111111;
+    SET_IDREG(idregs, ID_ISAR6, 0x01111111);
     cpu->isar.mvfr0    = 0x10110222;
     cpu->isar.mvfr1    = 0x13211111;
     cpu->isar.mvfr2    = 0x00000043;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 10/21] arm/cpu: Store id_mfr0/1 into the idregs array
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (8 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 09/21] arm/cpu: Store id_isar0-7 " Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 11/21] arm/cpu: Store id_dfr0/1 " Eric Auger
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-features.h | 10 +++----
 target/arm/cpu.h          |  3 --
 hw/intc/armv7m_nvic.c     |  5 ++--
 target/arm/cpu.c          |  8 ++---
 target/arm/cpu64.c        |  8 ++---
 target/arm/helper.c       |  8 ++---
 target/arm/kvm.c          |  3 +-
 target/arm/tcg/cpu-v7m.c  | 24 +++++++--------
 target/arm/tcg/cpu32.c    | 61 ++++++++++++++++++++-------------------
 target/arm/tcg/cpu64.c    | 44 ++++++++++++++--------------
 10 files changed, 85 insertions(+), 89 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 306e6fa29f..217de5769e 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -135,12 +135,12 @@ static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_PFR0, RAS) != 0;
 }
 
 static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_PFR1, MPROGMOD) != 0;
 }
 
 static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
@@ -149,7 +149,7 @@ static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
      * Return true if M-profile state handling insns
      * (VSCCLRM, CLRM, FPCTX access insns) are implemented
      */
-    return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3;
+    return FIELD_EX32_IDREG(&id->idregs, ID_PFR1, SECURITY) >= 3;
 }
 
 static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
@@ -348,12 +348,12 @@ static inline bool isar_feature_aa32_evt(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa32_dit(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_PFR0, DIT) != 0;
 }
 
 static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_PFR2, SSBS) != 0;
 }
 
 static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 1c4fa6a561..11c3b93a07 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1077,9 +1077,6 @@ struct ArchCPU {
         uint32_t id_mmfr3;
         uint32_t id_mmfr4;
         uint32_t id_mmfr5;
-        uint32_t id_pfr0;
-        uint32_t id_pfr1;
-        uint32_t id_pfr2;
         uint32_t mvfr0;
         uint32_t mvfr1;
         uint32_t mvfr2;
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 818f6fdfa9..8ab809eee9 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -988,6 +988,7 @@ static void nvic_nmi_trigger(void *opaque, int n, int level)
 static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
 {
     ARMCPU *cpu = s->cpu;
+    IdRegMap *idregs = &cpu->isar.idregs;
     uint32_t val;
 
     switch (offset) {
@@ -1263,12 +1264,12 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_pfr0;
+        return GET_IDREG(idregs, ID_PFR0);
     case 0xd44: /* PFR1.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_pfr1;
+        return GET_IDREG(idregs, ID_PFR1);
     case 0xd48: /* DFR0.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index bc80945da1..eeb5db6085 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2318,7 +2318,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
          * Disable the security extension feature bits in the processor
          * feature registers as well.
          */
-        cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1, ID_PFR1, SECURITY, 0);
+        FIELD_DP32_IDREG(idregs, ID_PFR1, SECURITY, 0);
         cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPSDBG, 0);
         FIELD_DP64_IDREG(idregs, ID_AA64PFR0, EL3, 0);
 
@@ -2358,8 +2358,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
          * registers if we don't have EL2.
          */
         FIELD_DP64_IDREG(idregs, ID_AA64PFR0, EL2, 0);
-        cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1,
-                                       ID_PFR1, VIRTUALIZATION, 0);
+        FIELD_DP32_IDREG(idregs, ID_PFR1, VIRTUALIZATION, 0);
     }
 
     if (cpu_isar_feature(aa64_mte, cpu)) {
@@ -2414,8 +2413,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
             FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, MMAPTRC, 0);
         /* FEAT_AMU (Activity Monitors Extension) */
         FIELD_DP64_IDREG(idregs, ID_AA64PFR0, AMU, 0);
-        cpu->isar.id_pfr0 =
-            FIELD_DP32(cpu->isar.id_pfr0, ID_PFR0, AMU, 0);
+        FIELD_DP32_IDREG(idregs, ID_PFR0, AMU, 0);
         /* FEAT_MPAM (Memory Partitioning and Monitoring Extension) */
         FIELD_DP64_IDREG(idregs, ID_AA64PFR0, MPAM, 0);
     }
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 9c3784a35f..7e39235900 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -611,8 +611,8 @@ static void aarch64_a57_initfn(Object *obj)
     cpu->isar.mvfr2 = 0x00000043;
     cpu->ctr = 0x8444c004;
     cpu->reset_sctlr = 0x00c50838;
-    cpu->isar.id_pfr0 = 0x00000131;
-    cpu->isar.id_pfr1 = 0x00011011;
+    SET_IDREG(idregs, ID_PFR0, 0x00000131);
+    SET_IDREG(idregs, ID_PFR1, 0x00011011);
     cpu->isar.id_dfr0 = 0x03010066;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10101105;
@@ -670,8 +670,8 @@ static void aarch64_a53_initfn(Object *obj)
     cpu->isar.mvfr2 = 0x00000043;
     cpu->ctr = 0x84448004; /* L1Ip = VIPT */
     cpu->reset_sctlr = 0x00c50838;
-    cpu->isar.id_pfr0 = 0x00000131;
-    cpu->isar.id_pfr1 = 0x00011011;
+    SET_IDREG(idregs, ID_PFR0, 0x00000131);
+    SET_IDREG(idregs, ID_PFR1, 0x00011011);
     cpu->isar.id_dfr0 = 0x03010066;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10101105;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 1782de26f5..5e0094458f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7677,7 +7677,7 @@ static void define_pmu_regs(ARMCPU *cpu)
 static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
     ARMCPU *cpu = env_archcpu(env);
-    uint64_t pfr1 = cpu->isar.id_pfr1;
+    uint64_t pfr1 = GET_IDREG(&cpu->isar.idregs, ID_PFR1);
 
     if (env->gicv3state) {
         pfr1 |= 1 << 28;
@@ -8725,7 +8725,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_pfr0 },
+              .resetvalue = GET_IDREG(idregs, ID_PFR0)},
             /*
              * ID_PFR1 is not a plain ARM_CP_CONST because we don't know
              * the value of the GIC field until after we define these regs.
@@ -8736,7 +8736,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .accessfn = access_aa32_tid3,
 #ifdef CONFIG_USER_ONLY
               .type = ARM_CP_CONST,
-              .resetvalue = cpu->isar.id_pfr1,
+              .resetvalue = GET_IDREG(idregs, ID_PFR0),
 #else
               .type = ARM_CP_NO_RAW,
               .accessfn = access_aa32_tid3,
@@ -9082,7 +9082,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_pfr2 },
+              .resetvalue = GET_IDREG(idregs, ID_PFR2)},
             { .name = "ID_DFR1", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5,
               .access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 9873f8e849..53e4216897 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -385,8 +385,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
                               ARM64_SYS_REG(3, 0, 0, 3, 1));
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2,
                               ARM64_SYS_REG(3, 0, 0, 3, 2));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2,
-                              ARM64_SYS_REG(3, 0, 0, 3, 4));
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_PFR2_EL1);
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr1,
                               ARM64_SYS_REG(3, 0, 0, 3, 5));
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr5,
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
index fbde43d45e..06f9dce6ee 100644
--- a/target/arm/tcg/cpu-v7m.c
+++ b/target/arm/tcg/cpu-v7m.c
@@ -60,8 +60,8 @@ static void cortex_m0_initfn(Object *obj)
      * by looking at ID register fields. We use the same values as
      * for the M3.
      */
-    cpu->isar.id_pfr0 = 0x00000030;
-    cpu->isar.id_pfr1 = 0x00000200;
+    SET_IDREG(idregs, ID_PFR0, 0x00000030);
+    SET_IDREG(idregs, ID_PFR1, 0x00000200);
     cpu->isar.id_dfr0 = 0x00100000;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00000030;
@@ -86,8 +86,8 @@ static void cortex_m3_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
     cpu->midr = 0x410fc231;
     cpu->pmsav7_dregion = 8;
-    cpu->isar.id_pfr0 = 0x00000030;
-    cpu->isar.id_pfr1 = 0x00000200;
+    SET_IDREG(idregs, ID_PFR0, 0x00000030);
+    SET_IDREG(idregs, ID_PFR1, 0x00000200);
     cpu->isar.id_dfr0 = 0x00100000;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00000030;
@@ -117,8 +117,8 @@ static void cortex_m4_initfn(Object *obj)
     cpu->isar.mvfr0 = 0x10110021;
     cpu->isar.mvfr1 = 0x11000011;
     cpu->isar.mvfr2 = 0x00000000;
-    cpu->isar.id_pfr0 = 0x00000030;
-    cpu->isar.id_pfr1 = 0x00000200;
+    SET_IDREG(idregs, ID_PFR0, 0x00000030);
+    SET_IDREG(idregs, ID_PFR1, 0x00000200);
     cpu->isar.id_dfr0 = 0x00100000;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00000030;
@@ -148,8 +148,8 @@ static void cortex_m7_initfn(Object *obj)
     cpu->isar.mvfr0 = 0x10110221;
     cpu->isar.mvfr1 = 0x12000011;
     cpu->isar.mvfr2 = 0x00000040;
-    cpu->isar.id_pfr0 = 0x00000030;
-    cpu->isar.id_pfr1 = 0x00000200;
+    SET_IDREG(idregs, ID_PFR0, 0x00000030);
+    SET_IDREG(idregs, ID_PFR1, 0x00000200);
     cpu->isar.id_dfr0 = 0x00100000;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00100030;
@@ -181,8 +181,8 @@ static void cortex_m33_initfn(Object *obj)
     cpu->isar.mvfr0 = 0x10110021;
     cpu->isar.mvfr1 = 0x11000011;
     cpu->isar.mvfr2 = 0x00000040;
-    cpu->isar.id_pfr0 = 0x00000030;
-    cpu->isar.id_pfr1 = 0x00000210;
+    SET_IDREG(idregs, ID_PFR0, 0x00000030);
+    SET_IDREG(idregs, ID_PFR1, 0x00000210);
     cpu->isar.id_dfr0 = 0x00200000;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00101F40;
@@ -219,8 +219,8 @@ static void cortex_m55_initfn(Object *obj)
     cpu->isar.mvfr0 = 0x10110221;
     cpu->isar.mvfr1 = 0x12100211;
     cpu->isar.mvfr2 = 0x00000040;
-    cpu->isar.id_pfr0 = 0x20000030;
-    cpu->isar.id_pfr1 = 0x00000230;
+    SET_IDREG(idregs, ID_PFR0, 0x20000030);
+    SET_IDREG(idregs, ID_PFR1, 0x00000230);
     cpu->isar.id_dfr0 = 0x10200000;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00111040;
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
index ae5c909048..ca771e54fc 100644
--- a/target/arm/tcg/cpu32.c
+++ b/target/arm/tcg/cpu32.c
@@ -23,18 +23,19 @@
 void aa32_max_features(ARMCPU *cpu)
 {
     uint32_t t;
+    IdRegMap *idregs = &cpu->isar.idregs;
 
     /* Add additional features supported by QEMU */
-    t = GET_IDREG(&cpu->isar.idregs, ID_ISAR5);
+    t = GET_IDREG(idregs, ID_ISAR5);
     t = FIELD_DP32(t, ID_ISAR5, AES, 2);          /* FEAT_PMULL */
     t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);         /* FEAT_SHA1 */
     t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);         /* FEAT_SHA256 */
     t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
     t = FIELD_DP32(t, ID_ISAR5, RDM, 1);          /* FEAT_RDM */
     t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);         /* FEAT_FCMA */
-    SET_IDREG(&cpu->isar.idregs, ID_ISAR5, t);
+    SET_IDREG(idregs, ID_ISAR5, t);
 
-    t = GET_IDREG(&cpu->isar.idregs, ID_ISAR6);
+    t = GET_IDREG(idregs, ID_ISAR6);
     t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);        /* FEAT_JSCVT */
     t = FIELD_DP32(t, ID_ISAR6, DP, 1);           /* Feat_DotProd */
     t = FIELD_DP32(t, ID_ISAR6, FHM, 1);          /* FEAT_FHM */
@@ -42,7 +43,7 @@ void aa32_max_features(ARMCPU *cpu)
     t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);      /* FEAT_SPECRES */
     t = FIELD_DP32(t, ID_ISAR6, BF16, 1);         /* FEAT_AA32BF16 */
     t = FIELD_DP32(t, ID_ISAR6, I8MM, 1);         /* FEAT_AA32I8MM */
-    SET_IDREG(&cpu->isar.idregs, ID_ISAR6, t);
+    SET_IDREG(idregs, ID_ISAR6, t);
 
     t = cpu->isar.mvfr1;
     t = FIELD_DP32(t, MVFR1, FPHP, 3);            /* FEAT_FP16 */
@@ -70,16 +71,16 @@ void aa32_max_features(ARMCPU *cpu)
     t = FIELD_DP32(t, ID_MMFR5, ETS, 2);          /* FEAT_ETS2 */
     cpu->isar.id_mmfr5 = t;
 
-    t = cpu->isar.id_pfr0;
+    t = GET_IDREG(idregs, ID_PFR0);
     t = FIELD_DP32(t, ID_PFR0, CSV2, 2);          /* FEAT_CVS2 */
     t = FIELD_DP32(t, ID_PFR0, DIT, 1);           /* FEAT_DIT */
     t = FIELD_DP32(t, ID_PFR0, RAS, 1);           /* FEAT_RAS */
-    cpu->isar.id_pfr0 = t;
+    SET_IDREG(idregs, ID_PFR0, t);
 
-    t = cpu->isar.id_pfr2;
+    t = GET_IDREG(idregs, ID_PFR2);
     t = FIELD_DP32(t, ID_PFR2, CSV3, 1);          /* FEAT_CSV3 */
     t = FIELD_DP32(t, ID_PFR2, SSBS, 1);          /* FEAT_SSBS */
-    cpu->isar.id_pfr2 = t;
+    SET_IDREG(idregs, ID_PFR2, t);
 
     t = cpu->isar.id_dfr0;
     t = FIELD_DP32(t, ID_DFR0, COPDBG, 10);       /* FEAT_Debugv8p8 */
@@ -227,8 +228,8 @@ static void arm1136_r2_initfn(Object *obj)
     cpu->isar.mvfr1 = 0x00000000;
     cpu->ctr = 0x1dd20d2;
     cpu->reset_sctlr = 0x00050078;
-    cpu->isar.id_pfr0 = 0x111;
-    cpu->isar.id_pfr1 = 0x1;
+    SET_IDREG(idregs, ID_PFR0, 0x111);
+    SET_IDREG(idregs, ID_PFR1, 0x1);
     cpu->isar.id_dfr0 = 0x2;
     cpu->id_afr0 = 0x3;
     cpu->isar.id_mmfr0 = 0x01130003;
@@ -259,8 +260,8 @@ static void arm1136_initfn(Object *obj)
     cpu->isar.mvfr1 = 0x00000000;
     cpu->ctr = 0x1dd20d2;
     cpu->reset_sctlr = 0x00050078;
-    cpu->isar.id_pfr0 = 0x111;
-    cpu->isar.id_pfr1 = 0x1;
+    SET_IDREG(idregs, ID_PFR0, 0x111);
+    SET_IDREG(idregs, ID_PFR1, 0x1);
     cpu->isar.id_dfr0 = 0x2;
     cpu->id_afr0 = 0x3;
     cpu->isar.id_mmfr0 = 0x01130003;
@@ -292,8 +293,8 @@ static void arm1176_initfn(Object *obj)
     cpu->isar.mvfr1 = 0x00000000;
     cpu->ctr = 0x1dd20d2;
     cpu->reset_sctlr = 0x00050078;
-    cpu->isar.id_pfr0 = 0x111;
-    cpu->isar.id_pfr1 = 0x11;
+    SET_IDREG(idregs, ID_PFR0, 0x111);
+    SET_IDREG(idregs, ID_PFR1, 0x11);
     cpu->isar.id_dfr0 = 0x33;
     cpu->id_afr0 = 0;
     cpu->isar.id_mmfr0 = 0x01130003;
@@ -322,8 +323,8 @@ static void arm11mpcore_initfn(Object *obj)
     cpu->isar.mvfr0 = 0x11111111;
     cpu->isar.mvfr1 = 0x00000000;
     cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */
-    cpu->isar.id_pfr0 = 0x111;
-    cpu->isar.id_pfr1 = 0x1;
+     SET_IDREG(idregs, ID_PFR0, 0x111);
+     SET_IDREG(idregs, ID_PFR1, 0x1);
     cpu->isar.id_dfr0 = 0;
     cpu->id_afr0 = 0x2;
     cpu->isar.id_mmfr0 = 0x01100103;
@@ -362,8 +363,8 @@ static void cortex_a8_initfn(Object *obj)
     cpu->isar.mvfr1 = 0x00011111;
     cpu->ctr = 0x82048004;
     cpu->reset_sctlr = 0x00c50078;
-    cpu->isar.id_pfr0 = 0x1031;
-    cpu->isar.id_pfr1 = 0x11;
+    SET_IDREG(idregs, ID_PFR0, 0x1031);
+    SET_IDREG(idregs, ID_PFR1, 0x11);
     cpu->isar.id_dfr0 = 0x400;
     cpu->id_afr0 = 0;
     cpu->isar.id_mmfr0 = 0x31100003;
@@ -438,8 +439,8 @@ static void cortex_a9_initfn(Object *obj)
     cpu->isar.mvfr1 = 0x01111111;
     cpu->ctr = 0x80038003;
     cpu->reset_sctlr = 0x00c50078;
-    cpu->isar.id_pfr0 = 0x1031;
-    cpu->isar.id_pfr1 = 0x11;
+    SET_IDREG(idregs, ID_PFR0, 0x1031);
+    SET_IDREG(idregs, ID_PFR1, 0x11);
     cpu->isar.id_dfr0 = 0x000;
     cpu->id_afr0 = 0;
     cpu->isar.id_mmfr0 = 0x00100103;
@@ -504,8 +505,8 @@ static void cortex_a7_initfn(Object *obj)
     cpu->isar.mvfr1 = 0x11111111;
     cpu->ctr = 0x84448003;
     cpu->reset_sctlr = 0x00c50078;
-    cpu->isar.id_pfr0 = 0x00001131;
-    cpu->isar.id_pfr1 = 0x00011011;
+    SET_IDREG(idregs, ID_PFR0, 0x00001131);
+    SET_IDREG(idregs, ID_PFR1, 0x00011011);
     cpu->isar.id_dfr0 = 0x02010555;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10101105;
@@ -556,8 +557,8 @@ static void cortex_a15_initfn(Object *obj)
     cpu->isar.mvfr1 = 0x11111111;
     cpu->ctr = 0x8444c004;
     cpu->reset_sctlr = 0x00c50078;
-    cpu->isar.id_pfr0 = 0x00001131;
-    cpu->isar.id_pfr1 = 0x00011011;
+    SET_IDREG(idregs, ID_PFR0, 0x00001131);
+    SET_IDREG(idregs, ID_PFR1, 0x00011011);
     cpu->isar.id_dfr0 = 0x02010555;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10201105;
@@ -600,8 +601,8 @@ static void cortex_r5_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_PMSA);
     set_feature(&cpu->env, ARM_FEATURE_PMU);
     cpu->midr = 0x411fc153; /* r1p3 */
-    cpu->isar.id_pfr0 = 0x0131;
-    cpu->isar.id_pfr1 = 0x001;
+    SET_IDREG(idregs, ID_PFR0, 0x0131);
+    SET_IDREG(idregs, ID_PFR1, 0x001);
     cpu->isar.id_dfr0 = 0x010400;
     cpu->id_afr0 = 0x0;
     cpu->isar.id_mmfr0 = 0x0210030;
@@ -747,8 +748,8 @@ static void cortex_r52_initfn(Object *obj)
     cpu->isar.mvfr2 = 0x00000043;
     cpu->ctr = 0x8144c004;
     cpu->reset_sctlr = 0x30c50838;
-    cpu->isar.id_pfr0 = 0x00000131;
-    cpu->isar.id_pfr1 = 0x10111001;
+    SET_IDREG(idregs, ID_PFR0, 0x00000131);
+    SET_IDREG(idregs, ID_PFR1, 0x10111001);
     cpu->isar.id_dfr0 = 0x03010006;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00211040;
@@ -979,8 +980,8 @@ static void arm_max_initfn(Object *obj)
     cpu->isar.mvfr2 = 0x00000043;
     cpu->ctr = 0x8444c004;
     cpu->reset_sctlr = 0x00c50838;
-    cpu->isar.id_pfr0 = 0x00000131;
-    cpu->isar.id_pfr1 = 0x00011011;
+    SET_IDREG(idregs, ID_PFR0, 0x00000131);
+    SET_IDREG(idregs, ID_PFR1, 0x00011011);
     cpu->isar.id_dfr0 = 0x03010066;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10101105;
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index cdaba9b184..9caa18f0dc 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -75,8 +75,8 @@ static void aarch64_a35_initfn(Object *obj)
     cpu->midr = 0x411fd040;
     cpu->revidr = 0;
     cpu->ctr = 0x84448004;
-    cpu->isar.id_pfr0 = 0x00000131;
-    cpu->isar.id_pfr1 = 0x00011011;
+    SET_IDREG(idregs, ID_PFR0, 0x00000131);
+    SET_IDREG(idregs, ID_PFR1, 0x00011011);
     cpu->isar.id_dfr0 = 0x03010066;
     cpu->id_afr0 = 0;
     cpu->isar.id_mmfr0 = 0x10201105;
@@ -264,9 +264,9 @@ static void aarch64_a55_initfn(Object *obj)
     cpu->isar.id_mmfr2 = 0x01260000;
     cpu->isar.id_mmfr3 = 0x02122211;
     cpu->isar.id_mmfr4 = 0x00021110;
-    cpu->isar.id_pfr0  = 0x10010131;
-    cpu->isar.id_pfr1  = 0x00011011;
-    cpu->isar.id_pfr2  = 0x00000011;
+    SET_IDREG(idregs, ID_PFR0, 0x10010131);
+    SET_IDREG(idregs, ID_PFR1, 0x00011011);
+    SET_IDREG(idregs, ID_PFR2, 0x00000011);
     cpu->midr = 0x412FD050;          /* r2p0 */
     cpu->revidr = 0;
 
@@ -315,8 +315,8 @@ static void aarch64_a72_initfn(Object *obj)
     cpu->isar.mvfr2 = 0x00000043;
     cpu->ctr = 0x8444c004;
     cpu->reset_sctlr = 0x00c50838;
-    cpu->isar.id_pfr0 = 0x00000131;
-    cpu->isar.id_pfr1 = 0x00011011;
+    SET_IDREG(idregs, ID_PFR0, 0x00000131);
+    SET_IDREG(idregs, ID_PFR1, 0x00011011);
     cpu->isar.id_dfr0 = 0x03010066;
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10201105;
@@ -391,9 +391,9 @@ static void aarch64_a76_initfn(Object *obj)
     cpu->isar.id_mmfr2 = 0x01260000;
     cpu->isar.id_mmfr3 = 0x02122211;
     cpu->isar.id_mmfr4 = 0x00021110;
-    cpu->isar.id_pfr0  = 0x10010131;
-    cpu->isar.id_pfr1  = 0x00010000; /* GIC filled in later */
-    cpu->isar.id_pfr2  = 0x00000011;
+    SET_IDREG(idregs, ID_PFR0, 0x10010131);
+    SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
+    SET_IDREG(idregs, ID_PFR2, 0x00000011);
     cpu->midr = 0x414fd0b1;          /* r4p1 */
     cpu->revidr = 0;
 
@@ -633,9 +633,9 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
     cpu->isar.id_mmfr2 = 0x01260000;
     cpu->isar.id_mmfr3 = 0x02122211;
     cpu->isar.id_mmfr4 = 0x00021110;
-    cpu->isar.id_pfr0  = 0x10010131;
-    cpu->isar.id_pfr1  = 0x00010000; /* GIC filled in later */
-    cpu->isar.id_pfr2  = 0x00000011;
+    SET_IDREG(idregs, ID_PFR0, 0x10010131);
+    SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
+    SET_IDREG(idregs, ID_PFR2, 0x00000011);
     cpu->midr = 0x414fd0c1;          /* r4p1 */
     cpu->revidr = 0;
 
@@ -709,9 +709,9 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
     cpu->isar.id_mmfr2 = 0x01260000;
     cpu->isar.id_mmfr3 = 0x02122211;
     cpu->isar.id_mmfr4 = 0x01021110;
-    cpu->isar.id_pfr0  = 0x21110131;
-    cpu->isar.id_pfr1  = 0x00010000; /* GIC filled in later */
-    cpu->isar.id_pfr2  = 0x00000011;
+    SET_IDREG(idregs, ID_PFR0, 0x21110131);
+    SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
+    SET_IDREG(idregs, ID_PFR2, 0x00000011);
     cpu->midr = 0x411FD402;          /* r1p2 */
     cpu->revidr = 0;
 
@@ -907,8 +907,8 @@ static void aarch64_a710_initfn(Object *obj)
     /* Ordered by Section B.4: AArch64 registers */
     cpu->midr          = 0x412FD471; /* r2p1 */
     cpu->revidr        = 0;
-    cpu->isar.id_pfr0  = 0x21110131;
-    cpu->isar.id_pfr1  = 0x00010000; /* GIC filled in later */
+    SET_IDREG(idregs, ID_PFR0, 0x21110131);
+    SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
     cpu->isar.id_dfr0  = 0x16011099;
     cpu->id_afr0       = 0;
     cpu->isar.id_mmfr0 = 0x10201105;
@@ -926,7 +926,7 @@ static void aarch64_a710_initfn(Object *obj)
     cpu->isar.mvfr0    = 0x10110222;
     cpu->isar.mvfr1    = 0x13211111;
     cpu->isar.mvfr2    = 0x00000043;
-    cpu->isar.id_pfr2  = 0x00000011;
+    SET_IDREG(idregs, ID_PFR2, 0x00000011);
     SET_IDREG(idregs, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000221ull);
     SET_IDREG(idregs, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */
@@ -1007,8 +1007,8 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
     /* Ordered by Section B.5: AArch64 ID registers */
     cpu->midr          = 0x410FD493; /* r0p3 */
     cpu->revidr        = 0;
-    cpu->isar.id_pfr0  = 0x21110131;
-    cpu->isar.id_pfr1  = 0x00010000; /* GIC filled in later */
+    SET_IDREG(idregs, ID_PFR0, 0x21110131);
+    SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
     cpu->isar.id_dfr0  = 0x16011099;
     cpu->id_afr0       = 0;
     cpu->isar.id_mmfr0 = 0x10201105;
@@ -1026,7 +1026,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
     cpu->isar.mvfr0    = 0x10110222;
     cpu->isar.mvfr1    = 0x13211111;
     cpu->isar.mvfr2    = 0x00000043;
-    cpu->isar.id_pfr2  = 0x00000011;
+    SET_IDREG(idregs, ID_PFR2, 0x00000011);
     SET_IDREG(idregs, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000221ull);
     SET_IDREG(idregs, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 11/21] arm/cpu: Store id_dfr0/1 into the idregs array
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (9 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 10/21] arm/cpu: Store id_mfr0/1 " Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 12/21] arm/cpu: Store id_mmfr0-5 " Eric Auger
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-features.h | 16 ++++++++--------
 target/arm/cpu.h          |  2 --
 hw/intc/armv7m_nvic.c     |  2 +-
 target/arm/cpu.c          | 13 +++++--------
 target/arm/cpu64.c        |  4 ++--
 target/arm/helper.c       |  4 ++--
 target/arm/kvm.c          |  6 ++----
 target/arm/tcg/cpu-v7m.c  | 12 ++++++------
 target/arm/tcg/cpu32.c    | 30 ++++++++++++++----------------
 target/arm/tcg/cpu64.c    | 16 ++++++++--------
 10 files changed, 48 insertions(+), 57 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 217de5769e..bd8a24169a 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -298,22 +298,22 @@ static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
 static inline bool isar_feature_aa32_pmuv3p1(const ARMISARegisters *id)
 {
     /* 0xf means "non-standard IMPDEF PMU" */
-    return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 4 &&
-        FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf;
+    return FIELD_EX32_IDREG(&id->idregs, ID_DFR0, PERFMON) >= 4 &&
+        FIELD_EX32_IDREG(&id->idregs, ID_DFR0, PERFMON) != 0xf;
 }
 
 static inline bool isar_feature_aa32_pmuv3p4(const ARMISARegisters *id)
 {
     /* 0xf means "non-standard IMPDEF PMU" */
-    return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 &&
-        FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf;
+    return FIELD_EX32_IDREG(&id->idregs, ID_DFR0, PERFMON) >= 5 &&
+        FIELD_EX32_IDREG(&id->idregs, ID_DFR0, PERFMON) != 0xf;
 }
 
 static inline bool isar_feature_aa32_pmuv3p5(const ARMISARegisters *id)
 {
     /* 0xf means "non-standard IMPDEF PMU" */
-    return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 6 &&
-        FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf;
+    return FIELD_EX32_IDREG(&id->idregs, ID_DFR0, PERFMON) >= 6 &&
+        FIELD_EX32_IDREG(&id->idregs, ID_DFR0, PERFMON) != 0xf;
 }
 
 static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id)
@@ -358,12 +358,12 @@ static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 5;
+    return FIELD_EX32_IDREG(&id->idregs, ID_DFR0, COPDBG) >= 5;
 }
 
 static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8;
+    return FIELD_EX32_IDREG(&id->idregs, ID_DFR0, COPDBG) >= 8;
 }
 
 static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 11c3b93a07..8fae42d5b9 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1080,8 +1080,6 @@ struct ArchCPU {
         uint32_t mvfr0;
         uint32_t mvfr1;
         uint32_t mvfr2;
-        uint32_t id_dfr0;
-        uint32_t id_dfr1;
         uint32_t dbgdidr;
         uint32_t dbgdevid;
         uint32_t dbgdevid1;
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 8ab809eee9..7a11322b2c 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -1274,7 +1274,7 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_dfr0;
+        return GET_IDREG(idregs, ID_DFR0);
     case 0xd4c: /* AFR0.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index eeb5db6085..454d546feb 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2319,7 +2319,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
          * feature registers as well.
          */
         FIELD_DP32_IDREG(idregs, ID_PFR1, SECURITY, 0);
-        cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPSDBG, 0);
+        FIELD_DP32_IDREG(idregs, ID_DFR0, COPSDBG, 0);
         FIELD_DP64_IDREG(idregs, ID_AA64PFR0, EL3, 0);
 
         /* Disable the realm management extension, which requires EL3. */
@@ -2347,7 +2347,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
 #endif
     } else {
         FIELD_DP64_IDREG(idregs, ID_AA64DFR0, PMUVER, 0);
-        cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0);
+        FIELD_DP32_IDREG(idregs, ID_DFR0, PERFMON, 0);
         cpu->pmceid0 = 0;
         cpu->pmceid1 = 0;
     }
@@ -2402,15 +2402,12 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         FIELD_DP64_IDREG(idregs, ID_AA64DFR0, TRACEBUFFER, 0);
         /* FEAT_TRF (Self-hosted Trace Extension) */
         FIELD_DP64_IDREG(idregs, ID_AA64DFR0, TRACEFILT, 0);
-        cpu->isar.id_dfr0 =
-            FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, TRACEFILT, 0);
+        FIELD_DP32_IDREG(idregs, ID_DFR0, TRACEFILT, 0);
         /* Trace Macrocell system register access */
         FIELD_DP64_IDREG(idregs, ID_AA64DFR0, TRACEVER, 0);
-        cpu->isar.id_dfr0 =
-            FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPTRC, 0);
+        FIELD_DP32_IDREG(idregs, ID_DFR0, COPTRC, 0);
         /* Memory mapped trace */
-        cpu->isar.id_dfr0 =
-            FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, MMAPTRC, 0);
+        FIELD_DP32_IDREG(idregs, ID_DFR0, MMAPTRC, 0);
         /* FEAT_AMU (Activity Monitors Extension) */
         FIELD_DP64_IDREG(idregs, ID_AA64PFR0, AMU, 0);
         FIELD_DP32_IDREG(idregs, ID_PFR0, AMU, 0);
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 7e39235900..6b8fdd8678 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -613,7 +613,7 @@ static void aarch64_a57_initfn(Object *obj)
     cpu->reset_sctlr = 0x00c50838;
     SET_IDREG(idregs, ID_PFR0, 0x00000131);
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
-    cpu->isar.id_dfr0 = 0x03010066;
+    SET_IDREG(idregs, ID_DFR0, 0x03010066);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10101105;
     cpu->isar.id_mmfr1 = 0x40000000;
@@ -672,7 +672,7 @@ static void aarch64_a53_initfn(Object *obj)
     cpu->reset_sctlr = 0x00c50838;
     SET_IDREG(idregs, ID_PFR0, 0x00000131);
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
-    cpu->isar.id_dfr0 = 0x03010066;
+    SET_IDREG(idregs, ID_DFR0, 0x03010066);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10101105;
     cpu->isar.id_mmfr1 = 0x40000000;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 5e0094458f..81c2caee2c 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8748,7 +8748,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_dfr0 },
+              .resetvalue = GET_IDREG(idregs, ID_DFR0)},
             { .name = "ID_AFR0", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 3,
               .access = PL1_R, .type = ARM_CP_CONST,
@@ -9087,7 +9087,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_dfr1 },
+              .resetvalue = GET_IDREG(idregs, ID_DFR1)},
             { .name = "ID_MMFR5", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 6,
               .access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 53e4216897..144764cc54 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -359,8 +359,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
          */
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64PFR0_EL1);
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64PFR1_EL1);
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
-                              ARM64_SYS_REG(3, 0, 0, 1, 2));
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_DFR0_EL1);
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
                               ARM64_SYS_REG(3, 0, 0, 1, 4));
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
@@ -386,8 +385,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2,
                               ARM64_SYS_REG(3, 0, 0, 3, 2));
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_PFR2_EL1);
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr1,
-                              ARM64_SYS_REG(3, 0, 0, 3, 5));
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_DFR1_EL1);
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr5,
                               ARM64_SYS_REG(3, 0, 0, 3, 6));
 
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
index 06f9dce6ee..369e3e4c59 100644
--- a/target/arm/tcg/cpu-v7m.c
+++ b/target/arm/tcg/cpu-v7m.c
@@ -62,7 +62,7 @@ static void cortex_m0_initfn(Object *obj)
      */
     SET_IDREG(idregs, ID_PFR0, 0x00000030);
     SET_IDREG(idregs, ID_PFR1, 0x00000200);
-    cpu->isar.id_dfr0 = 0x00100000;
+    SET_IDREG(idregs, ID_DFR0, 0x00100000);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00000030;
     cpu->isar.id_mmfr1 = 0x00000000;
@@ -88,7 +88,7 @@ static void cortex_m3_initfn(Object *obj)
     cpu->pmsav7_dregion = 8;
     SET_IDREG(idregs, ID_PFR0, 0x00000030);
     SET_IDREG(idregs, ID_PFR1, 0x00000200);
-    cpu->isar.id_dfr0 = 0x00100000;
+    SET_IDREG(idregs, ID_DFR0, 0x00100000);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00000030;
     cpu->isar.id_mmfr1 = 0x00000000;
@@ -119,7 +119,7 @@ static void cortex_m4_initfn(Object *obj)
     cpu->isar.mvfr2 = 0x00000000;
     SET_IDREG(idregs, ID_PFR0, 0x00000030);
     SET_IDREG(idregs, ID_PFR1, 0x00000200);
-    cpu->isar.id_dfr0 = 0x00100000;
+    SET_IDREG(idregs, ID_DFR0, 0x00100000);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00000030;
     cpu->isar.id_mmfr1 = 0x00000000;
@@ -150,7 +150,7 @@ static void cortex_m7_initfn(Object *obj)
     cpu->isar.mvfr2 = 0x00000040;
     SET_IDREG(idregs, ID_PFR0, 0x00000030);
     SET_IDREG(idregs, ID_PFR1, 0x00000200);
-    cpu->isar.id_dfr0 = 0x00100000;
+    SET_IDREG(idregs, ID_DFR0, 0x00100000);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00100030;
     cpu->isar.id_mmfr1 = 0x00000000;
@@ -183,7 +183,7 @@ static void cortex_m33_initfn(Object *obj)
     cpu->isar.mvfr2 = 0x00000040;
     SET_IDREG(idregs, ID_PFR0, 0x00000030);
     SET_IDREG(idregs, ID_PFR1, 0x00000210);
-    cpu->isar.id_dfr0 = 0x00200000;
+    SET_IDREG(idregs, ID_DFR0, 0x00200000);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00101F40;
     cpu->isar.id_mmfr1 = 0x00000000;
@@ -221,7 +221,7 @@ static void cortex_m55_initfn(Object *obj)
     cpu->isar.mvfr2 = 0x00000040;
     SET_IDREG(idregs, ID_PFR0, 0x20000030);
     SET_IDREG(idregs, ID_PFR1, 0x00000230);
-    cpu->isar.id_dfr0 = 0x10200000;
+    SET_IDREG(idregs, ID_DFR0, 0x10200000);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00111040;
     cpu->isar.id_mmfr1 = 0x00000000;
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
index ca771e54fc..d1712216ff 100644
--- a/target/arm/tcg/cpu32.c
+++ b/target/arm/tcg/cpu32.c
@@ -82,11 +82,11 @@ void aa32_max_features(ARMCPU *cpu)
     t = FIELD_DP32(t, ID_PFR2, SSBS, 1);          /* FEAT_SSBS */
     SET_IDREG(idregs, ID_PFR2, t);
 
-    t = cpu->isar.id_dfr0;
+    t = GET_IDREG(idregs, ID_DFR0);
     t = FIELD_DP32(t, ID_DFR0, COPDBG, 10);       /* FEAT_Debugv8p8 */
     t = FIELD_DP32(t, ID_DFR0, COPSDBG, 10);      /* FEAT_Debugv8p8 */
     t = FIELD_DP32(t, ID_DFR0, PERFMON, 6);       /* FEAT_PMUv3p5 */
-    cpu->isar.id_dfr0 = t;
+    SET_IDREG(idregs, ID_DFR0, t);
 
     /* Debug ID registers. */
 
@@ -116,9 +116,7 @@ void aa32_max_features(ARMCPU *cpu)
     t = FIELD_DP32(t, DBGDEVID1, PCSROFFSET, 2);
     cpu->isar.dbgdevid1 = t;
 
-    t = cpu->isar.id_dfr1;
-    t = FIELD_DP32(t, ID_DFR1, HPMN0, 1);         /* FEAT_HPMN0 */
-    cpu->isar.id_dfr1 = t;
+    FIELD_DP32_IDREG(idregs, ID_DFR1, HPMN0, 1);         /* FEAT_HPMN0 */
 }
 
 /* CPU models. These are not needed for the AArch64 linux-user build. */
@@ -230,7 +228,7 @@ static void arm1136_r2_initfn(Object *obj)
     cpu->reset_sctlr = 0x00050078;
     SET_IDREG(idregs, ID_PFR0, 0x111);
     SET_IDREG(idregs, ID_PFR1, 0x1);
-    cpu->isar.id_dfr0 = 0x2;
+    SET_IDREG(idregs, ID_DFR0, 0x2);
     cpu->id_afr0 = 0x3;
     cpu->isar.id_mmfr0 = 0x01130003;
     cpu->isar.id_mmfr1 = 0x10030302;
@@ -262,7 +260,7 @@ static void arm1136_initfn(Object *obj)
     cpu->reset_sctlr = 0x00050078;
     SET_IDREG(idregs, ID_PFR0, 0x111);
     SET_IDREG(idregs, ID_PFR1, 0x1);
-    cpu->isar.id_dfr0 = 0x2;
+    SET_IDREG(idregs, ID_DFR0, 0x2);
     cpu->id_afr0 = 0x3;
     cpu->isar.id_mmfr0 = 0x01130003;
     cpu->isar.id_mmfr1 = 0x10030302;
@@ -295,7 +293,7 @@ static void arm1176_initfn(Object *obj)
     cpu->reset_sctlr = 0x00050078;
     SET_IDREG(idregs, ID_PFR0, 0x111);
     SET_IDREG(idregs, ID_PFR1, 0x11);
-    cpu->isar.id_dfr0 = 0x33;
+    SET_IDREG(idregs, ID_DFR0, 0x33);
     cpu->id_afr0 = 0;
     cpu->isar.id_mmfr0 = 0x01130003;
     cpu->isar.id_mmfr1 = 0x10030302;
@@ -325,7 +323,7 @@ static void arm11mpcore_initfn(Object *obj)
     cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */
      SET_IDREG(idregs, ID_PFR0, 0x111);
      SET_IDREG(idregs, ID_PFR1, 0x1);
-    cpu->isar.id_dfr0 = 0;
+    SET_IDREG(idregs, ID_DFR0, 0);
     cpu->id_afr0 = 0x2;
     cpu->isar.id_mmfr0 = 0x01100103;
     cpu->isar.id_mmfr1 = 0x10020302;
@@ -365,7 +363,7 @@ static void cortex_a8_initfn(Object *obj)
     cpu->reset_sctlr = 0x00c50078;
     SET_IDREG(idregs, ID_PFR0, 0x1031);
     SET_IDREG(idregs, ID_PFR1, 0x11);
-    cpu->isar.id_dfr0 = 0x400;
+    SET_IDREG(idregs, ID_DFR0, 0x400);
     cpu->id_afr0 = 0;
     cpu->isar.id_mmfr0 = 0x31100003;
     cpu->isar.id_mmfr1 = 0x20000000;
@@ -441,7 +439,7 @@ static void cortex_a9_initfn(Object *obj)
     cpu->reset_sctlr = 0x00c50078;
     SET_IDREG(idregs, ID_PFR0, 0x1031);
     SET_IDREG(idregs, ID_PFR1, 0x11);
-    cpu->isar.id_dfr0 = 0x000;
+    SET_IDREG(idregs, ID_DFR0, 0x000);
     cpu->id_afr0 = 0;
     cpu->isar.id_mmfr0 = 0x00100103;
     cpu->isar.id_mmfr1 = 0x20000000;
@@ -507,7 +505,7 @@ static void cortex_a7_initfn(Object *obj)
     cpu->reset_sctlr = 0x00c50078;
     SET_IDREG(idregs, ID_PFR0, 0x00001131);
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
-    cpu->isar.id_dfr0 = 0x02010555;
+    SET_IDREG(idregs, ID_DFR0, 0x02010555);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10101105;
     cpu->isar.id_mmfr1 = 0x40000000;
@@ -559,7 +557,7 @@ static void cortex_a15_initfn(Object *obj)
     cpu->reset_sctlr = 0x00c50078;
     SET_IDREG(idregs, ID_PFR0, 0x00001131);
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
-    cpu->isar.id_dfr0 = 0x02010555;
+    SET_IDREG(idregs, ID_DFR0, 0x02010555);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10201105;
     cpu->isar.id_mmfr1 = 0x20000000;
@@ -603,7 +601,7 @@ static void cortex_r5_initfn(Object *obj)
     cpu->midr = 0x411fc153; /* r1p3 */
     SET_IDREG(idregs, ID_PFR0, 0x0131);
     SET_IDREG(idregs, ID_PFR1, 0x001);
-    cpu->isar.id_dfr0 = 0x010400;
+    SET_IDREG(idregs, ID_DFR0, 0x010400);
     cpu->id_afr0 = 0x0;
     cpu->isar.id_mmfr0 = 0x0210030;
     cpu->isar.id_mmfr1 = 0x00000000;
@@ -750,7 +748,7 @@ static void cortex_r52_initfn(Object *obj)
     cpu->reset_sctlr = 0x30c50838;
     SET_IDREG(idregs, ID_PFR0, 0x00000131);
     SET_IDREG(idregs, ID_PFR1, 0x10111001);
-    cpu->isar.id_dfr0 = 0x03010006;
+    SET_IDREG(idregs, ID_DFR0, 0x03010006);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x00211040;
     cpu->isar.id_mmfr1 = 0x40000000;
@@ -982,7 +980,7 @@ static void arm_max_initfn(Object *obj)
     cpu->reset_sctlr = 0x00c50838;
     SET_IDREG(idregs, ID_PFR0, 0x00000131);
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
-    cpu->isar.id_dfr0 = 0x03010066;
+    SET_IDREG(idregs, ID_DFR0, 0x03010066);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10101105;
     cpu->isar.id_mmfr1 = 0x40000000;
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 9caa18f0dc..aee36fabc1 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -77,7 +77,7 @@ static void aarch64_a35_initfn(Object *obj)
     cpu->ctr = 0x84448004;
     SET_IDREG(idregs, ID_PFR0, 0x00000131);
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
-    cpu->isar.id_dfr0 = 0x03010066;
+    SET_IDREG(idregs, ID_DFR0, 0x03010066);
     cpu->id_afr0 = 0;
     cpu->isar.id_mmfr0 = 0x10201105;
     cpu->isar.id_mmfr1 = 0x40000000;
@@ -251,7 +251,7 @@ static void aarch64_a55_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR0, 0x0000000010112222ull);
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000010ull);
     cpu->id_afr0       = 0x00000000;
-    cpu->isar.id_dfr0  = 0x04010088;
+    SET_IDREG(idregs, ID_DFR0, 0x04010088);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232042);
@@ -317,7 +317,7 @@ static void aarch64_a72_initfn(Object *obj)
     cpu->reset_sctlr = 0x00c50838;
     SET_IDREG(idregs, ID_PFR0, 0x00000131);
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
-    cpu->isar.id_dfr0 = 0x03010066;
+    SET_IDREG(idregs, ID_DFR0, 0x03010066);
     cpu->id_afr0 = 0x00000000;
     cpu->isar.id_mmfr0 = 0x10201105;
     cpu->isar.id_mmfr1 = 0x40000000;
@@ -378,7 +378,7 @@ static void aarch64_a76_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000010ull);
     cpu->id_afr0       = 0x00000000;
-    cpu->isar.id_dfr0  = 0x04010088;
+    SET_IDREG(idregs, ID_DFR0, 0x04010088);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232042);
@@ -620,7 +620,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000020ull);
     cpu->id_afr0       = 0x00000000;
-    cpu->isar.id_dfr0  = 0x04010088;
+    SET_IDREG(idregs, ID_DFR0, 0x04010088);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232042);
@@ -696,7 +696,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
     SET_IDREG(idregs, ID_AA64PFR0, 0x1101110120111112ull); /* GIC filled in later */
     SET_IDREG(idregs, ID_AA64PFR1, 0x0000000000000020ull);
     cpu->id_afr0       = 0x00000000;
-    cpu->isar.id_dfr0  = 0x15011099;
+    SET_IDREG(idregs, ID_DFR0, 0x15011099);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232042);
@@ -909,7 +909,7 @@ static void aarch64_a710_initfn(Object *obj)
     cpu->revidr        = 0;
     SET_IDREG(idregs, ID_PFR0, 0x21110131);
     SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
-    cpu->isar.id_dfr0  = 0x16011099;
+    SET_IDREG(idregs, ID_DFR0, 0x16011099);
     cpu->id_afr0       = 0;
     cpu->isar.id_mmfr0 = 0x10201105;
     cpu->isar.id_mmfr1 = 0x40000000;
@@ -1009,7 +1009,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
     cpu->revidr        = 0;
     SET_IDREG(idregs, ID_PFR0, 0x21110131);
     SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
-    cpu->isar.id_dfr0  = 0x16011099;
+    SET_IDREG(idregs, ID_DFR0, 0x16011099);
     cpu->id_afr0       = 0;
     cpu->isar.id_mmfr0 = 0x10201105;
     cpu->isar.id_mmfr1 = 0x40000000;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 12/21] arm/cpu: Store id_mmfr0-5 into the idregs array
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (10 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 11/21] arm/cpu: Store id_dfr0/1 " Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 13/21] arm/cpu: Add infra to handle generated ID register definitions Eric Auger
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-features.h | 18 ++++----
 target/arm/cpu.h          |  6 ---
 hw/intc/armv7m_nvic.c     |  8 ++--
 target/arm/cpu64.c        | 16 +++----
 target/arm/helper.c       | 12 ++---
 target/arm/kvm.c          | 18 +++-----
 target/arm/tcg/cpu-v7m.c  | 48 ++++++++++----------
 target/arm/tcg/cpu32.c    | 94 +++++++++++++++++++--------------------
 target/arm/tcg/cpu64.c    | 76 +++++++++++++++----------------
 9 files changed, 140 insertions(+), 156 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index bd8a24169a..93e5288539 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -282,17 +282,17 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4;
+    return FIELD_EX32_IDREG(&id->idregs, ID_MMFR0, VMSA) >= 4;
 }
 
 static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_MMFR3, PAN) != 0;
 }
 
 static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) >= 2;
+    return FIELD_EX32_IDREG(&id->idregs, ID_MMFR3, PAN) >= 2;
 }
 
 static inline bool isar_feature_aa32_pmuv3p1(const ARMISARegisters *id)
@@ -318,32 +318,32 @@ static inline bool isar_feature_aa32_pmuv3p5(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_MMFR4, HPDS) != 0;
 }
 
 static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_MMFR4, AC2) != 0;
 }
 
 static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_MMFR4, CCIDX) != 0;
 }
 
 static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0;
+    return FIELD_EX32_IDREG(&id->idregs, ID_MMFR4, XNX) != 0;
 }
 
 static inline bool isar_feature_aa32_half_evt(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 1;
+    return FIELD_EX32_IDREG(&id->idregs, ID_MMFR4, EVT) >= 1;
 }
 
 static inline bool isar_feature_aa32_evt(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 2;
+    return FIELD_EX32_IDREG(&id->idregs, ID_MMFR4, EVT) >= 2;
 }
 
 static inline bool isar_feature_aa32_dit(const ARMISARegisters *id)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 8fae42d5b9..30b265e9b0 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1071,12 +1071,6 @@ struct ArchCPU {
      * field by reading the value from the KVM vCPU.
      */
     struct ARMISARegisters {
-        uint32_t id_mmfr0;
-        uint32_t id_mmfr1;
-        uint32_t id_mmfr2;
-        uint32_t id_mmfr3;
-        uint32_t id_mmfr4;
-        uint32_t id_mmfr5;
         uint32_t mvfr0;
         uint32_t mvfr1;
         uint32_t mvfr2;
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 7a11322b2c..3ad4418302 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -1284,22 +1284,22 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_mmfr0;
+        return GET_IDREG(idregs, ID_MMFR0);
     case 0xd54: /* MMFR1.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_mmfr1;
+        return GET_IDREG(idregs, ID_MMFR1);
     case 0xd58: /* MMFR2.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_mmfr2;
+        return GET_IDREG(idregs, ID_MMFR2);
     case 0xd5c: /* MMFR3.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
         }
-        return cpu->isar.id_mmfr3;
+        return GET_IDREG(idregs, ID_MMFR3);
     case 0xd60: /* ISAR0.  */
         if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
             goto bad_offset;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 6b8fdd8678..57e73fdd38 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -615,10 +615,10 @@ static void aarch64_a57_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
     SET_IDREG(idregs, ID_DFR0, 0x03010066);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x10101105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01260000;
-    cpu->isar.id_mmfr3 = 0x02102211;
+    SET_IDREG(idregs, ID_MMFR0, 0x10101105);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01260000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02102211);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232042);
@@ -674,10 +674,10 @@ static void aarch64_a53_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
     SET_IDREG(idregs, ID_DFR0, 0x03010066);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x10101105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01260000;
-    cpu->isar.id_mmfr3 = 0x02102211;
+    SET_IDREG(idregs, ID_MMFR0, 0x10101105);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01260000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02102211);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232042);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 81c2caee2c..978b9ed44a 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8758,22 +8758,22 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_mmfr0 },
+              .resetvalue = GET_IDREG(idregs, ID_MMFR0)},
             { .name = "ID_MMFR1", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 5,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_mmfr1 },
+              .resetvalue = GET_IDREG(idregs, ID_MMFR1)},
             { .name = "ID_MMFR2", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 6,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_mmfr2 },
+              .resetvalue = GET_IDREG(idregs, ID_MMFR2)},
             { .name = "ID_MMFR3", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 7,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_mmfr3 },
+              .resetvalue = GET_IDREG(idregs, ID_MMFR3)},
             { .name = "ID_ISAR0", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
               .access = PL1_R, .type = ARM_CP_CONST,
@@ -8808,7 +8808,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_mmfr4 },
+              .resetvalue = GET_IDREG(idregs, ID_MMFR4)},
             { .name = "ID_ISAR6", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7,
               .access = PL1_R, .type = ARM_CP_CONST,
@@ -9092,7 +9092,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 6,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_mmfr5 },
+              .resetvalue = GET_IDREG(idregs, ID_MMFR5)},
             { .name = "RES_0_C0_C3_7", .state = ARM_CP_STATE_BOTH,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 7,
               .access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 144764cc54..bd53554832 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -360,14 +360,10 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64PFR0_EL1);
         err |= get_host_cpu_reg64(fd, ahcf, SYS_ID_AA64PFR1_EL1);
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_DFR0_EL1);
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
-                              ARM64_SYS_REG(3, 0, 0, 1, 4));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
-                              ARM64_SYS_REG(3, 0, 0, 1, 5));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2,
-                              ARM64_SYS_REG(3, 0, 0, 1, 6));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
-                              ARM64_SYS_REG(3, 0, 0, 1, 7));
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_MMFR0_EL1);
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_MMFR1_EL1);
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_MMFR2_EL1);
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_MMFR3_EL1);
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR0_EL1);
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR1_EL1);
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR2_EL1);
@@ -375,8 +371,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR4_EL1);
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR5_EL1);
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_ISAR6_EL1);
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
-                              ARM64_SYS_REG(3, 0, 0, 2, 6));
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_MMFR4_EL1);
 
         err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0,
                               ARM64_SYS_REG(3, 0, 0, 3, 0));
@@ -386,8 +381,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
                               ARM64_SYS_REG(3, 0, 0, 3, 2));
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_PFR2_EL1);
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_DFR1_EL1);
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr5,
-                              ARM64_SYS_REG(3, 0, 0, 3, 6));
+        err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_MMFR5_EL1);
 
         /*
          * DBGDIDR is a bit complicated because the kernel doesn't
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
index 369e3e4c59..cbf1c03d68 100644
--- a/target/arm/tcg/cpu-v7m.c
+++ b/target/arm/tcg/cpu-v7m.c
@@ -64,10 +64,10 @@ static void cortex_m0_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00000200);
     SET_IDREG(idregs, ID_DFR0, 0x00100000);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x00000030;
-    cpu->isar.id_mmfr1 = 0x00000000;
-    cpu->isar.id_mmfr2 = 0x00000000;
-    cpu->isar.id_mmfr3 = 0x00000000;
+    SET_IDREG(idregs, ID_MMFR0, 0x00000030);
+    SET_IDREG(idregs, ID_MMFR1, 0x00000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x00000000);
+    SET_IDREG(idregs, ID_MMFR3, 0x00000000);
     SET_IDREG(idregs, ID_ISAR0, 0x01141110);
     SET_IDREG(idregs, ID_ISAR1, 0x02111000);
     SET_IDREG(idregs, ID_ISAR2, 0x21112231);
@@ -90,10 +90,10 @@ static void cortex_m3_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00000200);
     SET_IDREG(idregs, ID_DFR0, 0x00100000);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x00000030;
-    cpu->isar.id_mmfr1 = 0x00000000;
-    cpu->isar.id_mmfr2 = 0x00000000;
-    cpu->isar.id_mmfr3 = 0x00000000;
+    SET_IDREG(idregs, ID_MMFR0, 0x00000030);
+    SET_IDREG(idregs, ID_MMFR1, 0x00000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x00000000);
+    SET_IDREG(idregs, ID_MMFR3, 0x00000000);
     SET_IDREG(idregs, ID_ISAR0, 0x01141110);
     SET_IDREG(idregs, ID_ISAR1, 0x02111000);
     SET_IDREG(idregs, ID_ISAR2, 0x21112231);
@@ -121,10 +121,10 @@ static void cortex_m4_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00000200);
     SET_IDREG(idregs, ID_DFR0, 0x00100000);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x00000030;
-    cpu->isar.id_mmfr1 = 0x00000000;
-    cpu->isar.id_mmfr2 = 0x00000000;
-    cpu->isar.id_mmfr3 = 0x00000000;
+    SET_IDREG(idregs, ID_MMFR0, 0x00000030);
+    SET_IDREG(idregs, ID_MMFR1, 0x00000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x00000000);
+    SET_IDREG(idregs, ID_MMFR3, 0x00000000);
     SET_IDREG(idregs, ID_ISAR0, 0x01141110);
     SET_IDREG(idregs, ID_ISAR1, 0x02111000);
     SET_IDREG(idregs, ID_ISAR2, 0x21112231);
@@ -152,10 +152,10 @@ static void cortex_m7_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00000200);
     SET_IDREG(idregs, ID_DFR0, 0x00100000);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x00100030;
-    cpu->isar.id_mmfr1 = 0x00000000;
-    cpu->isar.id_mmfr2 = 0x01000000;
-    cpu->isar.id_mmfr3 = 0x00000000;
+    SET_IDREG(idregs, ID_MMFR0, 0x00100030);
+    SET_IDREG(idregs, ID_MMFR1, 0x00000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01000000);
+    SET_IDREG(idregs, ID_MMFR3, 0x00000000);
     SET_IDREG(idregs, ID_ISAR0, 0x01101110);
     SET_IDREG(idregs, ID_ISAR1, 0x02112000);
     SET_IDREG(idregs, ID_ISAR2, 0x20232231);
@@ -185,10 +185,10 @@ static void cortex_m33_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00000210);
     SET_IDREG(idregs, ID_DFR0, 0x00200000);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x00101F40;
-    cpu->isar.id_mmfr1 = 0x00000000;
-    cpu->isar.id_mmfr2 = 0x01000000;
-    cpu->isar.id_mmfr3 = 0x00000000;
+    SET_IDREG(idregs, ID_MMFR0, 0x00101F40);
+    SET_IDREG(idregs, ID_MMFR1, 0x00000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01000000);
+    SET_IDREG(idregs, ID_MMFR3, 0x00000000);
     SET_IDREG(idregs, ID_ISAR0, 0x01101110);
     SET_IDREG(idregs, ID_ISAR1, 0x02212000);
     SET_IDREG(idregs, ID_ISAR2, 0x20232232);
@@ -223,10 +223,10 @@ static void cortex_m55_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00000230);
     SET_IDREG(idregs, ID_DFR0, 0x10200000);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x00111040;
-    cpu->isar.id_mmfr1 = 0x00000000;
-    cpu->isar.id_mmfr2 = 0x01000000;
-    cpu->isar.id_mmfr3 = 0x00000011;
+    SET_IDREG(idregs, ID_MMFR0, 0x00111040);
+    SET_IDREG(idregs, ID_MMFR1, 0x00000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01000000);
+    SET_IDREG(idregs, ID_MMFR3, 0x00000011);
     SET_IDREG(idregs, ID_ISAR0, 0x01103110);
     SET_IDREG(idregs, ID_ISAR1, 0x02212000);
     SET_IDREG(idregs, ID_ISAR2, 0x20232232);
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
index d1712216ff..6620260480 100644
--- a/target/arm/tcg/cpu32.c
+++ b/target/arm/tcg/cpu32.c
@@ -55,21 +55,17 @@ void aa32_max_features(ARMCPU *cpu)
     t = FIELD_DP32(t, MVFR2, FPMISC, 4);          /* FP MaxNum */
     cpu->isar.mvfr2 = t;
 
-    t = cpu->isar.id_mmfr3;
-    t = FIELD_DP32(t, ID_MMFR3, PAN, 2);          /* FEAT_PAN2 */
-    cpu->isar.id_mmfr3 = t;
+    FIELD_DP32_IDREG(idregs, ID_MMFR3, PAN, 2);          /* FEAT_PAN2 */
 
-    t = cpu->isar.id_mmfr4;
+    t = GET_IDREG(idregs, ID_MMFR4);
     t = FIELD_DP32(t, ID_MMFR4, HPDS, 2);         /* FEAT_HPDS2 */
     t = FIELD_DP32(t, ID_MMFR4, AC2, 1);          /* ACTLR2, HACTLR2 */
     t = FIELD_DP32(t, ID_MMFR4, CNP, 1);          /* FEAT_TTCNP */
     t = FIELD_DP32(t, ID_MMFR4, XNX, 1);          /* FEAT_XNX */
     t = FIELD_DP32(t, ID_MMFR4, EVT, 2);          /* FEAT_EVT */
-    cpu->isar.id_mmfr4 = t;
+    SET_IDREG(idregs, ID_MMFR4, t);
 
-    t = cpu->isar.id_mmfr5;
-    t = FIELD_DP32(t, ID_MMFR5, ETS, 2);          /* FEAT_ETS2 */
-    cpu->isar.id_mmfr5 = t;
+    FIELD_DP32_IDREG(idregs, ID_MMFR5, ETS, 2);          /* FEAT_ETS2 */
 
     t = GET_IDREG(idregs, ID_PFR0);
     t = FIELD_DP32(t, ID_PFR0, CSV2, 2);          /* FEAT_CVS2 */
@@ -230,9 +226,9 @@ static void arm1136_r2_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x1);
     SET_IDREG(idregs, ID_DFR0, 0x2);
     cpu->id_afr0 = 0x3;
-    cpu->isar.id_mmfr0 = 0x01130003;
-    cpu->isar.id_mmfr1 = 0x10030302;
-    cpu->isar.id_mmfr2 = 0x01222110;
+    SET_IDREG(idregs, ID_MMFR0, 0x01130003);
+    SET_IDREG(idregs, ID_MMFR1, 0x10030302);
+    SET_IDREG(idregs, ID_MMFR2, 0x01222110);
     SET_IDREG(idregs, ID_ISAR0, 0x00140011);
     SET_IDREG(idregs, ID_ISAR1, 0x12002111);
     SET_IDREG(idregs, ID_ISAR2, 0x11231111);
@@ -262,9 +258,9 @@ static void arm1136_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x1);
     SET_IDREG(idregs, ID_DFR0, 0x2);
     cpu->id_afr0 = 0x3;
-    cpu->isar.id_mmfr0 = 0x01130003;
-    cpu->isar.id_mmfr1 = 0x10030302;
-    cpu->isar.id_mmfr2 = 0x01222110;
+    SET_IDREG(idregs, ID_MMFR0, 0x01130003);
+    SET_IDREG(idregs, ID_MMFR1, 0x10030302);
+    SET_IDREG(idregs, ID_MMFR2, 0x01222110);
     SET_IDREG(idregs, ID_ISAR0, 0x00140011);
     SET_IDREG(idregs, ID_ISAR1, 0x12002111);
     SET_IDREG(idregs, ID_ISAR2, 0x11231111);
@@ -295,9 +291,9 @@ static void arm1176_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x11);
     SET_IDREG(idregs, ID_DFR0, 0x33);
     cpu->id_afr0 = 0;
-    cpu->isar.id_mmfr0 = 0x01130003;
-    cpu->isar.id_mmfr1 = 0x10030302;
-    cpu->isar.id_mmfr2 = 0x01222100;
+    SET_IDREG(idregs, ID_MMFR0, 0x01130003);
+    SET_IDREG(idregs, ID_MMFR1, 0x10030302);
+    SET_IDREG(idregs, ID_MMFR2, 0x01222100);
     SET_IDREG(idregs, ID_ISAR0, 0x0140011);
     SET_IDREG(idregs, ID_ISAR1, 0x12002111);
     SET_IDREG(idregs, ID_ISAR2, 0x11231121);
@@ -325,9 +321,9 @@ static void arm11mpcore_initfn(Object *obj)
      SET_IDREG(idregs, ID_PFR1, 0x1);
     SET_IDREG(idregs, ID_DFR0, 0);
     cpu->id_afr0 = 0x2;
-    cpu->isar.id_mmfr0 = 0x01100103;
-    cpu->isar.id_mmfr1 = 0x10020302;
-    cpu->isar.id_mmfr2 = 0x01222000;
+    SET_IDREG(idregs, ID_MMFR0, 0x01100103);
+    SET_IDREG(idregs, ID_MMFR1, 0x10020302);
+    SET_IDREG(idregs, ID_MMFR2, 0x01222000);
     SET_IDREG(idregs, ID_ISAR0, 0x00100011);
     SET_IDREG(idregs, ID_ISAR1, 0x12002111);
     SET_IDREG(idregs, ID_ISAR2, 0x11221011);
@@ -365,10 +361,10 @@ static void cortex_a8_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x11);
     SET_IDREG(idregs, ID_DFR0, 0x400);
     cpu->id_afr0 = 0;
-    cpu->isar.id_mmfr0 = 0x31100003;
-    cpu->isar.id_mmfr1 = 0x20000000;
-    cpu->isar.id_mmfr2 = 0x01202000;
-    cpu->isar.id_mmfr3 = 0x11;
+    SET_IDREG(idregs, ID_MMFR0, 0x31100003);
+    SET_IDREG(idregs, ID_MMFR1, 0x20000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01202000);
+    SET_IDREG(idregs, ID_MMFR3, 0x11);
     SET_IDREG(idregs, ID_ISAR0, 0x00101111);
     SET_IDREG(idregs, ID_ISAR1, 0x12112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232031);
@@ -441,10 +437,10 @@ static void cortex_a9_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x11);
     SET_IDREG(idregs, ID_DFR0, 0x000);
     cpu->id_afr0 = 0;
-    cpu->isar.id_mmfr0 = 0x00100103;
-    cpu->isar.id_mmfr1 = 0x20000000;
-    cpu->isar.id_mmfr2 = 0x01230000;
-    cpu->isar.id_mmfr3 = 0x00002111;
+    SET_IDREG(idregs, ID_MMFR0, 0x00100103);
+    SET_IDREG(idregs, ID_MMFR1, 0x20000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01230000);
+    SET_IDREG(idregs, ID_MMFR3, 0x00002111);
     SET_IDREG(idregs, ID_ISAR0, 0x00101111);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232041);
@@ -507,10 +503,10 @@ static void cortex_a7_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
     SET_IDREG(idregs, ID_DFR0, 0x02010555);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x10101105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01240000;
-    cpu->isar.id_mmfr3 = 0x02102211;
+    SET_IDREG(idregs, ID_MMFR0, 0x10101105);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01240000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02102211);
     /*
      * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
      * table 4-41 gives 0x02101110, which includes the arm div insns.
@@ -559,10 +555,10 @@ static void cortex_a15_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
     SET_IDREG(idregs, ID_DFR0, 0x02010555);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x10201105;
-    cpu->isar.id_mmfr1 = 0x20000000;
-    cpu->isar.id_mmfr2 = 0x01240000;
-    cpu->isar.id_mmfr3 = 0x02102211;
+    SET_IDREG(idregs, ID_MMFR0, 0x10201105);
+    SET_IDREG(idregs, ID_MMFR1, 0x20000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01240000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02102211);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232041);
@@ -603,10 +599,10 @@ static void cortex_r5_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x001);
     SET_IDREG(idregs, ID_DFR0, 0x010400);
     cpu->id_afr0 = 0x0;
-    cpu->isar.id_mmfr0 = 0x0210030;
-    cpu->isar.id_mmfr1 = 0x00000000;
-    cpu->isar.id_mmfr2 = 0x01200000;
-    cpu->isar.id_mmfr3 = 0x0211;
+    SET_IDREG(idregs, ID_MMFR0, 0x0210030);
+    SET_IDREG(idregs, ID_MMFR1, 0x00000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01200000);
+    SET_IDREG(idregs, ID_MMFR3, 0x0211);
     SET_IDREG(idregs, ID_ISAR0, 0x02101111);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232141);
@@ -750,11 +746,11 @@ static void cortex_r52_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x10111001);
     SET_IDREG(idregs, ID_DFR0, 0x03010006);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x00211040;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01200000;
-    cpu->isar.id_mmfr3 = 0xf0102211;
-    cpu->isar.id_mmfr4 = 0x00000010;
+    SET_IDREG(idregs, ID_MMFR0, 0x00211040);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01200000);
+    SET_IDREG(idregs, ID_MMFR3, 0xf0102211);
+    SET_IDREG(idregs, ID_MMFR4, 0x00000010);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232142);
@@ -982,10 +978,10 @@ static void arm_max_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
     SET_IDREG(idregs, ID_DFR0, 0x03010066);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x10101105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01260000;
-    cpu->isar.id_mmfr3 = 0x02102211;
+    ET_IDREG(idregs, ID_MMFR0, 0x10101105);
+    ET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    ET_IDREG(idregs, ID_MMFR2, 0x01260000);
+    ET_IDREG(idregs, ID_MMFR3, 0x02102211);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232042);
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index aee36fabc1..ac54fd2083 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -79,10 +79,10 @@ static void aarch64_a35_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
     SET_IDREG(idregs, ID_DFR0, 0x03010066);
     cpu->id_afr0 = 0;
-    cpu->isar.id_mmfr0 = 0x10201105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01260000;
-    cpu->isar.id_mmfr3 = 0x02102211;
+    SET_IDREG(idregs, ID_MMFR0, 0x10201105);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01260000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02102211);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232042);
@@ -259,11 +259,11 @@ static void aarch64_a55_initfn(Object *obj)
     SET_IDREG(idregs, ID_ISAR4, 0x00011142);
     SET_IDREG(idregs, ID_ISAR5, 0x01011121);
     SET_IDREG(idregs, ID_ISAR6, 0x00000010);
-    cpu->isar.id_mmfr0 = 0x10201105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01260000;
-    cpu->isar.id_mmfr3 = 0x02122211;
-    cpu->isar.id_mmfr4 = 0x00021110;
+    SET_IDREG(idregs, ID_MMFR0, 0x10201105);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01260000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02122211);
+    SET_IDREG(idregs, ID_MMFR4, 0x00021110);
     SET_IDREG(idregs, ID_PFR0, 0x10010131);
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
     SET_IDREG(idregs, ID_PFR2, 0x00000011);
@@ -319,10 +319,10 @@ static void aarch64_a72_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00011011);
     SET_IDREG(idregs, ID_DFR0, 0x03010066);
     cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x10201105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01260000;
-    cpu->isar.id_mmfr3 = 0x02102211;
+    SET_IDREG(idregs, ID_MMFR0, 0x10201105);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01260000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02102211);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232042);
@@ -386,11 +386,11 @@ static void aarch64_a76_initfn(Object *obj)
     SET_IDREG(idregs, ID_ISAR4, 0x00010142);
     SET_IDREG(idregs, ID_ISAR5, 0x01011121);
     SET_IDREG(idregs, ID_ISAR6, 0x00000010);
-    cpu->isar.id_mmfr0 = 0x10201105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01260000;
-    cpu->isar.id_mmfr3 = 0x02122211;
-    cpu->isar.id_mmfr4 = 0x00021110;
+    SET_IDREG(idregs, ID_MMFR0, 0x10201105);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01260000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02122211);
+    SET_IDREG(idregs, ID_MMFR4, 0x00021110);
     SET_IDREG(idregs, ID_PFR0, 0x10010131);
     SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
     SET_IDREG(idregs, ID_PFR2, 0x00000011);
@@ -628,11 +628,11 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
     SET_IDREG(idregs, ID_ISAR4, 0x00010142);
     SET_IDREG(idregs, ID_ISAR5, 0x01011121);
     SET_IDREG(idregs, ID_ISAR6, 0x00000010);
-    cpu->isar.id_mmfr0 = 0x10201105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01260000;
-    cpu->isar.id_mmfr3 = 0x02122211;
-    cpu->isar.id_mmfr4 = 0x00021110;
+    SET_IDREG(idregs, ID_MMFR0, 0x10201105);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01260000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02122211);
+    SET_IDREG(idregs, ID_MMFR4, 0x00021110);
     SET_IDREG(idregs, ID_PFR0, 0x10010131);
     SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
     SET_IDREG(idregs, ID_PFR2, 0x00000011);
@@ -704,11 +704,11 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
     SET_IDREG(idregs, ID_ISAR4, 0x00010142);
     SET_IDREG(idregs, ID_ISAR5, 0x11011121);
     SET_IDREG(idregs, ID_ISAR6, 0x01100111);
-    cpu->isar.id_mmfr0 = 0x10201105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01260000;
-    cpu->isar.id_mmfr3 = 0x02122211;
-    cpu->isar.id_mmfr4 = 0x01021110;
+    SET_IDREG(idregs, ID_MMFR0, 0x10201105);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01260000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02122211);
+    SET_IDREG(idregs, ID_MMFR4, 0x01021110);
     SET_IDREG(idregs, ID_PFR0, 0x21110131);
     SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
     SET_IDREG(idregs, ID_PFR2, 0x00000011);
@@ -911,17 +911,17 @@ static void aarch64_a710_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
     SET_IDREG(idregs, ID_DFR0, 0x16011099);
     cpu->id_afr0       = 0;
-    cpu->isar.id_mmfr0 = 0x10201105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01260000;
-    cpu->isar.id_mmfr3 = 0x02122211;
+    SET_IDREG(idregs, ID_MMFR0, 0x10201105);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01260000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02122211);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232042);
     SET_IDREG(idregs, ID_ISAR3, 0x01112131);
     SET_IDREG(idregs, ID_ISAR4, 0x00010142);
     SET_IDREG(idregs, ID_ISAR5, 0x11011121); /* with Crypto */
-    cpu->isar.id_mmfr4 = 0x21021110;
+    SET_IDREG(idregs, ID_MMFR4, 0x21021110);
     SET_IDREG(idregs, ID_ISAR6, 0x01111111);
     cpu->isar.mvfr0    = 0x10110222;
     cpu->isar.mvfr1    = 0x13211111;
@@ -1011,17 +1011,17 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
     SET_IDREG(idregs, ID_PFR1, 0x00010000); /* GIC filled in later */
     SET_IDREG(idregs, ID_DFR0, 0x16011099);
     cpu->id_afr0       = 0;
-    cpu->isar.id_mmfr0 = 0x10201105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01260000;
-    cpu->isar.id_mmfr3 = 0x02122211;
+    SET_IDREG(idregs, ID_MMFR0, 0x10201105);
+    SET_IDREG(idregs, ID_MMFR1, 0x40000000);
+    SET_IDREG(idregs, ID_MMFR2, 0x01260000);
+    SET_IDREG(idregs, ID_MMFR3, 0x02122211);
     SET_IDREG(idregs, ID_ISAR0, 0x02101110);
     SET_IDREG(idregs, ID_ISAR1, 0x13112111);
     SET_IDREG(idregs, ID_ISAR2, 0x21232042);
     SET_IDREG(idregs, ID_ISAR3, 0x01112131);
     SET_IDREG(idregs, ID_ISAR4, 0x00010142);
     SET_IDREG(idregs, ID_ISAR5, 0x11011121); /* with Crypto */
-    cpu->isar.id_mmfr4 = 0x01021110;
+    SET_IDREG(idregs, ID_MMFR4, 0x01021110);
     SET_IDREG(idregs, ID_ISAR6, 0x01111111);
     cpu->isar.mvfr0    = 0x10110222;
     cpu->isar.mvfr1    = 0x13211111;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 13/21] arm/cpu: Add infra to handle generated ID register definitions
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (11 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 12/21] arm/cpu: Store id_mmfr0-5 " Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 12:55   ` Daniel P. Berrangé
  2024-10-25 10:17 ` [RFC 14/21] arm/cpu: Add sysreg generation scripts Eric Auger
                   ` (9 subsequent siblings)
  22 siblings, 1 reply; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

The known ID regs are described in a new initialization function
dubbed initialize_cpu_sysreg_properties(). That code will be
automatically generated from linux arch/arm64/tools/sysreg. For the
time being let's just describe a single id reg, CTR_EL0. In this
description we only care about non RES/RAZ fields, ie. named fields.

The registers are populated in a 3x8x8 array and their fields are
added in a sorted list.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-custom.h            | 58 ++++++++++++++++++++++++++++++
 target/arm/cpu-sysreg-properties.c | 41 +++++++++++++++++++++
 target/arm/cpu64.c                 |  2 ++
 target/arm/meson.build             |  1 +
 4 files changed, 102 insertions(+)
 create mode 100644 target/arm/cpu-custom.h
 create mode 100644 target/arm/cpu-sysreg-properties.c

diff --git a/target/arm/cpu-custom.h b/target/arm/cpu-custom.h
new file mode 100644
index 0000000000..1952095bf7
--- /dev/null
+++ b/target/arm/cpu-custom.h
@@ -0,0 +1,58 @@
+#ifndef ARM_CPU_CUSTOM_H
+#define ARM_CPU_CUSTOM_H
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "cpu.h"
+#include "cpu-sysregs.h"
+
+typedef struct ARM64SysRegField {
+    const char *name; /* name of the field, for instance CTR_EL0_IDC */
+    int index;
+    int lower;
+    int upper;
+} ARM64SysRegField;
+
+typedef struct ARM64SysReg {
+    const char *name;   /* name of the sysreg, for instance CTR_EL0 */
+    ARMSysReg *sysreg;
+    int index;
+    GList *fields; /* list of named fields, excluding RES* */
+} ARM64SysReg;
+
+void initialize_cpu_sysreg_properties(void);
+
+/*
+ * List of exposed ID regs (automatically populated from linux
+ * arch/arm64/tools/sysreg)
+ */
+extern ARM64SysReg arm64_id_regs[NR_ID_REGS];
+
+/* Allocate a new field and insert it at the head of the @reg list */
+static inline GList *arm64_sysreg_add_field(ARM64SysReg *reg, const char *name,
+                                     uint8_t min, uint8_t max) {
+
+     ARM64SysRegField *field = g_new0(ARM64SysRegField, 1);
+
+     field->name = name;
+     field->lower = min;
+     field->upper = max;
+     field->index = reg->index;
+
+     reg->fields = g_list_append(reg->fields, field);
+     return reg->fields;
+}
+
+static inline ARM64SysReg *
+arm64_sysreg_get(int op0, int op1, int crn, int crm, int op2)
+{
+        uint64_t index = ARM_FEATURE_ID_RANGE_IDX(op0, op1, crn, crm, op2);
+        ARM64SysReg *reg = &arm64_id_regs[index];
+
+        reg->index = index;
+        reg->sysreg = g_new(ARMSysReg, 1);
+        *reg->sysreg = sys_reg(op0, op1, crn, crm, op2);
+        return reg;
+}
+
+#endif
diff --git a/target/arm/cpu-sysreg-properties.c b/target/arm/cpu-sysreg-properties.c
new file mode 100644
index 0000000000..753e7c9127
--- /dev/null
+++ b/target/arm/cpu-sysreg-properties.c
@@ -0,0 +1,41 @@
+/*
+ * QEMU ARM CPU SYSREG PROPERTIES
+ * to be generated from linux sysreg
+ *
+ * Copyright (c) 2024, Inc. 2024
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ */
+
+#include "cpu-custom.h"
+
+ARM64SysReg arm64_id_regs[NR_ID_REGS];
+
+void initialize_cpu_sysreg_properties(void)
+{
+    memset(arm64_id_regs, 0, sizeof(ARM64SysReg) * NR_ID_REGS);
+    /* CTR_EL0 */
+    ARM64SysReg *CTR_EL0 = arm64_sysreg_get(3, 3, 0, 0, 1);
+    CTR_EL0->name = "CTR_EL0";
+    arm64_sysreg_add_field(CTR_EL0, "TMinline", 32, 37);
+    arm64_sysreg_add_field(CTR_EL0, "DIC", 29, 29);
+    arm64_sysreg_add_field(CTR_EL0, "IDC", 28, 28);
+    arm64_sysreg_add_field(CTR_EL0, "CWG", 24, 27);
+    arm64_sysreg_add_field(CTR_EL0, "ERG", 20, 23);
+    arm64_sysreg_add_field(CTR_EL0, "DMinLine", 16, 19);
+    arm64_sysreg_add_field(CTR_EL0, "L1Ip", 14, 15);
+    arm64_sysreg_add_field(CTR_EL0, "IminLine", 0, 3);
+}
+
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 57e73fdd38..9f20886668 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -34,6 +34,7 @@
 #include "internals.h"
 #include "cpu-features.h"
 #include "cpregs.h"
+#include "cpu-custom.h"
 
 void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
 {
@@ -844,6 +845,7 @@ static void aarch64_cpu_register_types(void)
 {
     size_t i;
 
+    initialize_cpu_sysreg_properties();
     type_register_static(&aarch64_cpu_type_info);
 
     for (i = 0; i < ARRAY_SIZE(aarch64_cpus); ++i) {
diff --git a/target/arm/meson.build b/target/arm/meson.build
index 2e10464dbb..9c7a04ee1b 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -14,6 +14,7 @@ arm_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c'))
 arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
   'cpu64.c',
   'gdbstub64.c',
+  'cpu-sysreg-properties.c',
 ))
 
 arm_system_ss = ss.source_set()
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 14/21] arm/cpu: Add sysreg generation scripts
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (12 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 13/21] arm/cpu: Add infra to handle generated ID register definitions Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 17:05   ` Marc Zyngier
  2024-10-25 10:17 ` [RFC 15/21] arm/cpu: Add generated files Eric Auger
                   ` (8 subsequent siblings)
  22 siblings, 1 reply; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Introduce scripts that automate the generation of system register
definitions from a given linux source tree arch/arm64/tools/sysreg.

Invocation of
./update-aarch64-sysreg-code.sh $PATH_TO_LINUX_SOURCE_TREE
in scripts directory do generate 2 qemu files:
- target/arm/cpu-sysreg-properties.c
- target/arm/cpu-sysregs.h

cpu-sysregs.h creates defined for all system registers.
However cpu-sysreg-properties.c only cares about feature ID registers.

update-aarch64-sysreg-code.sh calls two awk scripts.
gen-cpu-sysreg-properties.awk is inherited from kernel
arch/arm64/tools/gen-sysreg.awk. All credits to Mark Rutland
the original author of this script.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 scripts/gen-cpu-sysreg-properties.awk | 325 ++++++++++++++++++++++++++
 scripts/gen-cpu-sysregs-header.awk    |  47 ++++
 scripts/update-aarch64-sysreg-code.sh |  27 +++
 3 files changed, 399 insertions(+)
 create mode 100755 scripts/gen-cpu-sysreg-properties.awk
 create mode 100755 scripts/gen-cpu-sysregs-header.awk
 create mode 100755 scripts/update-aarch64-sysreg-code.sh

diff --git a/scripts/gen-cpu-sysreg-properties.awk b/scripts/gen-cpu-sysreg-properties.awk
new file mode 100755
index 0000000000..b0ed55e059
--- /dev/null
+++ b/scripts/gen-cpu-sysreg-properties.awk
@@ -0,0 +1,325 @@
+#!/bin/awk -f
+# SPDX-License-Identifier: GPL-2.0
+# gen-sysreg.awk: arm64 sysreg header generator
+#
+# Usage: awk -f gen-custom-sysreg.awk $LINUX_PATH/arch/arm64/tools/sysreg
+
+function block_current() {
+	return __current_block[__current_block_depth];
+}
+
+# Log an error and terminate
+function fatal(msg) {
+	print "Error at " NR ": " msg > "/dev/stderr"
+
+	printf "Current block nesting:"
+
+	for (i = 0; i <= __current_block_depth; i++) {
+		printf " " __current_block[i]
+	}
+	printf "\n"
+
+	exit 1
+}
+
+# Enter a new block, setting the active block to @block
+function block_push(block) {
+	__current_block[++__current_block_depth] = block
+}
+
+# Exit a block, setting the active block to the parent block
+function block_pop() {
+	if (__current_block_depth == 0)
+		fatal("error: block_pop() in root block")
+
+	__current_block_depth--;
+}
+
+# Sanity check the number of records for a field makes sense. If not, produce
+# an error and terminate.
+function expect_fields(nf) {
+	if (NF != nf)
+		fatal(NF " fields found where " nf " expected")
+}
+
+# Print a CPP macro definition, padded with spaces so that the macro bodies
+# line up in a column
+function define(name, val) {
+	printf "%-56s%s\n", "#define " name, val
+}
+
+# Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field
+function define_field(reg, field, msb, lsb, idreg) {
+	if (idreg)
+            print "    arm64_sysreg_add_field("reg", \""field"\", "lsb", "msb");"
+}
+
+# Print a field _SIGNED definition for a field
+function define_field_sign(reg, field, sign, idreg) {
+	if (idreg)
+            print "    arm64_sysreg_add_field("reg", \""field"\", "lsb", "msb");"
+}
+
+# Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb
+function parse_bitdef(reg, field, bitdef, _bits)
+{
+	if (bitdef ~ /^[0-9]+$/) {
+		msb = bitdef
+		lsb = bitdef
+	} else if (split(bitdef, _bits, ":") == 2) {
+		msb = _bits[1]
+		lsb = _bits[2]
+	} else {
+		fatal("invalid bit-range definition '" bitdef "'")
+	}
+
+
+	if (msb != next_bit)
+		fatal(reg "." field " starts at " msb " not " next_bit)
+	if (63 < msb || msb < 0)
+		fatal(reg "." field " invalid high bit in '" bitdef "'")
+	if (63 < lsb || lsb < 0)
+		fatal(reg "." field " invalid low bit in '" bitdef "'")
+	if (msb < lsb)
+		fatal(reg "." field " invalid bit-range '" bitdef "'")
+	if (low > high)
+		fatal(reg "." field " has invalid range " high "-" low)
+
+	next_bit = lsb - 1
+}
+
+BEGIN {
+	print "#include \"cpu-custom.h\""
+	print ""
+	print "ARM64SysReg arm64_id_regs[NR_ID_REGS];"
+	print ""
+	print "void initialize_cpu_sysreg_properties(void)"
+	print "{"
+        print "    memset(arm64_id_regs, 0, sizeof(ARM64SysReg) * NR_ID_REGS);"
+        print ""
+
+	__current_block_depth = 0
+	__current_block[__current_block_depth] = "Root"
+}
+
+END {
+	if (__current_block_depth != 0)
+		fatal("Missing terminator for " block_current() " block")
+
+	print "}"
+}
+
+# skip blank lines and comment lines
+/^$/ { next }
+/^[\t ]*#/ { next }
+
+/^SysregFields/ && block_current() == "Root" {
+	block_push("SysregFields")
+
+	expect_fields(2)
+
+	reg = $2
+
+	res0 = "UL(0)"
+	res1 = "UL(0)"
+	unkn = "UL(0)"
+
+	next_bit = 63
+
+	next
+}
+
+/^EndSysregFields/ && block_current() == "SysregFields" {
+	if (next_bit > 0)
+		fatal("Unspecified bits in " reg)
+
+	reg = null
+	res0 = null
+	res1 = null
+	unkn = null
+
+	block_pop()
+	next
+}
+
+/^Sysreg/ && block_current() == "Root" {
+	block_push("Sysreg")
+
+	expect_fields(7)
+
+	reg = $2
+	op0 = $3
+	op1 = $4
+	crn = $5
+	crm = $6
+	op2 = $7
+
+	res0 = "UL(0)"
+	res1 = "UL(0)"
+	unkn = "UL(0)"
+
+	if (op0 == 3 && (op1>=0 && op1<=3) && crn==0 && (crm>=0 && crm<=7) && (op2>=0 && op2<=7)) {
+	    idreg = 1
+        } else {
+	    idreg = 0
+	}
+
+	if (idreg == 1) {
+	   print "    /* "reg" */"
+	   print "    ARM64SysReg *"reg" = arm64_sysreg_get("op0", "op1", "crn", "crm", "op2");"
+	   print "    "reg"->name = \""reg"\";"
+	}
+
+	next_bit = 63
+
+	next
+}
+
+/^EndSysreg/ && block_current() == "Sysreg" {
+	if (next_bit > 0)
+		fatal("Unspecified bits in " reg)
+
+	reg = null
+	op0 = null
+	op1 = null
+	crn = null
+	crm = null
+	op2 = null
+	res0 = null
+	res1 = null
+	unkn = null
+
+	if (idreg==1)
+	    print ""
+	block_pop()
+	next
+}
+
+# Currently this is effectivey a comment, in future we may want to emit
+# defines for the fields.
+/^Fields/ && block_current() == "Sysreg" {
+	expect_fields(2)
+
+	if (next_bit != 63)
+		fatal("Some fields already defined for " reg)
+
+	print "/* For " reg " fields see " $2 " */"
+	print ""
+
+        next_bit = 0
+	res0 = null
+	res1 = null
+	unkn = null
+
+	next
+}
+
+
+/^Res0/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+	expect_fields(2)
+	parse_bitdef(reg, "RES0", $2)
+	field = "RES0_" msb "_" lsb
+
+	res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")"
+
+	next
+}
+
+/^Res1/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+	expect_fields(2)
+	parse_bitdef(reg, "RES1", $2)
+	field = "RES1_" msb "_" lsb
+
+	res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")"
+
+	next
+}
+
+/^Unkn/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+	expect_fields(2)
+	parse_bitdef(reg, "UNKN", $2)
+	field = "UNKN_" msb "_" lsb
+
+	unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")"
+
+	next
+}
+
+/^Field/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+	expect_fields(3)
+	field = $3
+	parse_bitdef(reg, field, $2)
+
+
+	define_field(reg, field, msb, lsb, idreg)
+
+	next
+}
+
+/^Raz/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+	expect_fields(2)
+	parse_bitdef(reg, field, $2)
+
+	next
+}
+
+/^SignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+	block_push("Enum")
+
+	expect_fields(3)
+	field = $3
+	parse_bitdef(reg, field, $2)
+
+	define_field(reg, field, msb, lsb, idreg)
+	define_field_sign(reg, field, "true", idreg)
+
+	next
+}
+
+/^UnsignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+	block_push("Enum")
+
+	expect_fields(3)
+	field = $3
+	parse_bitdef(reg, field, $2)
+
+	define_field(reg, field, msb, lsb, idreg)
+	#define_field_sign(reg, field, "false", idreg)
+
+	next
+}
+
+/^Enum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+	block_push("Enum")
+
+	expect_fields(3)
+	field = $3
+	parse_bitdef(reg, field, $2)
+
+	define_field(reg, field, msb, lsb, idreg)
+
+	next
+}
+
+/^EndEnum/ && block_current() == "Enum" {
+
+	field = null
+	msb = null
+	lsb = null
+
+	block_pop()
+	next
+}
+
+/0b[01]+/ && block_current() == "Enum" {
+	expect_fields(2)
+	val = $1
+	name = $2
+
+	next
+}
+
+# Any lines not handled by previous rules are unexpected
+{
+	fatal("unhandled statement")
+}
diff --git a/scripts/gen-cpu-sysregs-header.awk b/scripts/gen-cpu-sysregs-header.awk
new file mode 100755
index 0000000000..cdad686a53
--- /dev/null
+++ b/scripts/gen-cpu-sysregs-header.awk
@@ -0,0 +1,47 @@
+#!/bin/awk -f
+# SPDX-License-Identifier: GPL-2.0
+# gen-sysreg.awk: arm64 sysreg header generator
+#
+# Usage: awk -f gen-custom-sysreg.awk $LINUX_PATH/arch/arm64/tools/sysreg
+
+# Sanity check the number of records for a field makes sense. If not, produce
+# an error and terminate.
+
+# Print a CPP macro definition, padded with spaces so that the macro bodies
+# line up in a column
+function define(name, val) {
+	printf "%-56s%s\n", "#define " name, val
+}
+
+BEGIN {
+	print "#ifndef ARM_CPU_SYSREGS_H"
+	print "#define ARM_CPU_SYSREGS_H"
+	print ""
+	print "/* Generated file - do not edit */"
+	print ""
+} END {
+	print ""
+	print "#endif /* ARM_CPU_SYSREGS_H */"
+}
+
+# skip blank lines and comment lines
+/^$/ { next }
+/^[\t ]*#/ { next }
+
+/^Sysreg\t/ || /^Sysreg /{
+
+	reg = $2
+	op0 = $3
+	op1 = $4
+	crn = $5
+	crm = $6
+	op2 = $7
+
+	define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")")
+	next
+}
+
+{
+	/* skip all other lines */
+	next
+}
diff --git a/scripts/update-aarch64-sysreg-code.sh b/scripts/update-aarch64-sysreg-code.sh
new file mode 100755
index 0000000000..e1fe40308b
--- /dev/null
+++ b/scripts/update-aarch64-sysreg-code.sh
@@ -0,0 +1,27 @@
+#!/bin/sh -e
+#
+# Update target/arm/cpu-sysreg-properties.c and target/arm/cpu-sysregs.h
+# from a linux source tree (arch/arm64/tools/sysreg)
+#
+# Copyright Red Hat, Inc. 2024
+#
+# Authors:
+#          Eric Auger <eric.auger@redhat.com>
+#
+
+linux="$1"
+output="$PWD"
+
+if [ -z "$linux" ] || ! [ -d "$linux" ]; then
+    cat << EOF
+usage: update-aarch64-sysreg-code.sh LINUX_PATH
+
+LINUX_PATH      Linux kernel directory to obtain the headers from
+EOF
+    exit 1
+fi
+
+awk -f gen-cpu-sysregs-header.awk \
+       $linux/arch/arm64/tools/sysreg > ../target/arm/cpu-sysregs.h
+awk -f gen-cpu-sysreg-properties.awk \
+       $linux/arch/arm64/tools/sysreg > ../target/arm/cpu-sysreg-properties.c
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 15/21] arm/cpu: Add generated files
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (13 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 14/21] arm/cpu: Add sysreg generation scripts Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 16/21] arm/kvm: Allow reading all the writable ID registers Eric Auger
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu-sysregs.h           | 142 +++++-
 target/arm/cpu-sysreg-properties.c | 689 ++++++++++++++++++++++++++++-
 2 files changed, 791 insertions(+), 40 deletions(-)

diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h
index f4b63a3af7..8c4cd0f2b4 100644
--- a/target/arm/cpu-sysregs.h
+++ b/target/arm/cpu-sysregs.h
@@ -1,24 +1,18 @@
 #ifndef ARM_CPU_SYSREGS_H
 #define ARM_CPU_SYSREGS_H
 
-/* to be generated */
-
-#define SYS_ID_AA64PFR0_EL1                             sys_reg(3, 0, 0, 4, 0)
-#define SYS_ID_AA64PFR1_EL1                             sys_reg(3, 0, 0, 4, 1)
-#define SYS_ID_AA64SMFR0_EL1                            sys_reg(3, 0, 0, 4, 5)
-#define SYS_ID_AA64DFR0_EL1                             sys_reg(3, 0, 0, 5, 0)
-#define SYS_ID_AA64DFR1_EL1                             sys_reg(3, 0, 0, 5, 1)
-#define SYS_ID_AA64ISAR0_EL1                            sys_reg(3, 0, 0, 6, 0)
-#define SYS_ID_AA64ISAR1_EL1                            sys_reg(3, 0, 0, 6, 1)
-#define SYS_ID_AA64ISAR2_EL1                            sys_reg(3, 0, 0, 6, 2)
-#define SYS_ID_AA64MMFR0_EL1                            sys_reg(3, 0, 0, 7, 0)
-#define SYS_ID_AA64MMFR1_EL1                            sys_reg(3, 0, 0, 7, 1)
-#define SYS_ID_AA64MMFR2_EL1                            sys_reg(3, 0, 0, 7, 2)
-#define SYS_ID_AA64MMFR3_EL1                            sys_reg(3, 0, 0, 7, 3)
+/* Generated file - do not edit */
 
+#define SYS_OSDTRRX_EL1                                 sys_reg(2, 0, 0, 0, 2)
+#define SYS_MDCCINT_EL1                                 sys_reg(2, 0, 0, 2, 0)
+#define SYS_MDSCR_EL1                                   sys_reg(2, 0, 0, 2, 2)
+#define SYS_OSDTRTX_EL1                                 sys_reg(2, 0, 0, 3, 2)
+#define SYS_OSECCR_EL1                                  sys_reg(2, 0, 0, 6, 2)
+#define SYS_OSLAR_EL1                                   sys_reg(2, 0, 1, 0, 4)
 #define SYS_ID_PFR0_EL1                                 sys_reg(3, 0, 0, 1, 0)
 #define SYS_ID_PFR1_EL1                                 sys_reg(3, 0, 0, 1, 1)
 #define SYS_ID_DFR0_EL1                                 sys_reg(3, 0, 0, 1, 2)
+#define SYS_ID_AFR0_EL1                                 sys_reg(3, 0, 0, 1, 3)
 #define SYS_ID_MMFR0_EL1                                sys_reg(3, 0, 0, 1, 4)
 #define SYS_ID_MMFR1_EL1                                sys_reg(3, 0, 0, 1, 5)
 #define SYS_ID_MMFR2_EL1                                sys_reg(3, 0, 0, 1, 6)
@@ -29,14 +23,130 @@
 #define SYS_ID_ISAR3_EL1                                sys_reg(3, 0, 0, 2, 3)
 #define SYS_ID_ISAR4_EL1                                sys_reg(3, 0, 0, 2, 4)
 #define SYS_ID_ISAR5_EL1                                sys_reg(3, 0, 0, 2, 5)
-#define SYS_ID_MMFR4_EL1                                sys_reg(3, 0, 0, 2, 6)
 #define SYS_ID_ISAR6_EL1                                sys_reg(3, 0, 0, 2, 7)
+#define SYS_ID_MMFR4_EL1                                sys_reg(3, 0, 0, 2, 6)
 #define SYS_MVFR0_EL1                                   sys_reg(3, 0, 0, 3, 0)
 #define SYS_MVFR1_EL1                                   sys_reg(3, 0, 0, 3, 1)
 #define SYS_MVFR2_EL1                                   sys_reg(3, 0, 0, 3, 2)
 #define SYS_ID_PFR2_EL1                                 sys_reg(3, 0, 0, 3, 4)
 #define SYS_ID_DFR1_EL1                                 sys_reg(3, 0, 0, 3, 5)
 #define SYS_ID_MMFR5_EL1                                sys_reg(3, 0, 0, 3, 6)
+#define SYS_ID_AA64PFR0_EL1                             sys_reg(3, 0, 0, 4, 0)
+#define SYS_ID_AA64PFR1_EL1                             sys_reg(3, 0, 0, 4, 1)
+#define SYS_ID_AA64PFR2_EL1                             sys_reg(3, 0, 0, 4, 2)
 #define SYS_ID_AA64ZFR0_EL1                             sys_reg(3, 0, 0, 4, 4)
+#define SYS_ID_AA64SMFR0_EL1                            sys_reg(3, 0, 0, 4, 5)
+#define SYS_ID_AA64FPFR0_EL1                            sys_reg(3, 0, 0, 4, 7)
+#define SYS_ID_AA64DFR0_EL1                             sys_reg(3, 0, 0, 5, 0)
+#define SYS_ID_AA64DFR1_EL1                             sys_reg(3, 0, 0, 5, 1)
+#define SYS_ID_AA64AFR0_EL1                             sys_reg(3, 0, 0, 5, 4)
+#define SYS_ID_AA64AFR1_EL1                             sys_reg(3, 0, 0, 5, 5)
+#define SYS_ID_AA64ISAR0_EL1                            sys_reg(3, 0, 0, 6, 0)
+#define SYS_ID_AA64ISAR1_EL1                            sys_reg(3, 0, 0, 6, 1)
+#define SYS_ID_AA64ISAR2_EL1                            sys_reg(3, 0, 0, 6, 2)
+#define SYS_ID_AA64ISAR3_EL1                            sys_reg(3, 0, 0, 6, 3)
+#define SYS_ID_AA64MMFR0_EL1                            sys_reg(3, 0, 0, 7, 0)
+#define SYS_ID_AA64MMFR1_EL1                            sys_reg(3, 0, 0, 7, 1)
+#define SYS_ID_AA64MMFR2_EL1                            sys_reg(3, 0, 0, 7, 2)
+#define SYS_ID_AA64MMFR3_EL1                            sys_reg(3, 0, 0, 7, 3)
+#define SYS_ID_AA64MMFR4_EL1                            sys_reg(3, 0, 0, 7, 4)
+#define SYS_SCTLR_EL1                                   sys_reg(3, 0, 1, 0, 0)
+#define SYS_CPACR_EL1                                   sys_reg(3, 0, 1, 0, 2)
+#define SYS_SMPRI_EL1                                   sys_reg(3, 0, 1, 2, 4)
+#define SYS_ZCR_EL1                                     sys_reg(3, 0, 1, 2, 0)
+#define SYS_SMCR_EL1                                    sys_reg(3, 0, 1, 2, 6)
+#define SYS_GCSCR_EL1                                   sys_reg(3, 0, 2, 5, 0)
+#define SYS_GCSPR_EL1                                   sys_reg(3, 0, 2, 5, 1)
+#define SYS_GCSCRE0_EL1                                 sys_reg(3, 0, 2, 5, 2)
+#define SYS_ALLINT                                      sys_reg(3, 0, 4, 3, 0)
+#define SYS_FAR_EL1                                     sys_reg(3, 0, 6, 0, 0)
+#define SYS_PMICNTR_EL0                                 sys_reg(3, 3, 9, 4, 0)
+#define SYS_PMICFILTR_EL0                               sys_reg(3, 3, 9, 6, 0)
+#define SYS_PMSCR_EL1                                   sys_reg(3, 0, 9, 9, 0)
+#define SYS_PMSNEVFR_EL1                                sys_reg(3, 0, 9, 9, 1)
+#define SYS_PMSICR_EL1                                  sys_reg(3, 0, 9, 9, 2)
+#define SYS_PMSIRR_EL1                                  sys_reg(3, 0, 9, 9, 3)
+#define SYS_PMSFCR_EL1                                  sys_reg(3, 0, 9, 9, 4)
+#define SYS_PMSEVFR_EL1                                 sys_reg(3, 0, 9, 9, 5)
+#define SYS_PMSLATFR_EL1                                sys_reg(3, 0, 9, 9, 6)
+#define SYS_PMSIDR_EL1                                  sys_reg(3, 0, 9, 9, 7)
+#define SYS_PMBLIMITR_EL1                               sys_reg(3, 0, 9, 10, 0)
+#define SYS_PMBPTR_EL1                                  sys_reg(3, 0, 9, 10, 1)
+#define SYS_PMBSR_EL1                                   sys_reg(3, 0, 9, 10, 3)
+#define SYS_PMBIDR_EL1                                  sys_reg(3, 0, 9, 10, 7)
+#define SYS_PMSELR_EL0                                  sys_reg(3, 3, 9, 12, 5)
+#define SYS_CONTEXTIDR_EL1                              sys_reg(3, 0, 13, 0, 1)
+#define SYS_RCWSMASK_EL1                                sys_reg(3, 0, 13, 0, 3)
+#define SYS_TPIDR_EL1                                   sys_reg(3, 0, 13, 0, 4)
+#define SYS_RCWMASK_EL1                                 sys_reg(3, 0, 13, 0, 6)
+#define SYS_SCXTNUM_EL1                                 sys_reg(3, 0, 13, 0, 7)
+#define SYS_CCSIDR_EL1                                  sys_reg(3, 1, 0, 0, 0)
+#define SYS_CLIDR_EL1                                   sys_reg(3, 1, 0, 0, 1)
+#define SYS_CCSIDR2_EL1                                 sys_reg(3, 1, 0, 0, 2)
+#define SYS_GMID_EL1                                    sys_reg(3, 1, 0, 0, 4)
+#define SYS_SMIDR_EL1                                   sys_reg(3, 1, 0, 0, 6)
+#define SYS_CSSELR_EL1                                  sys_reg(3, 2, 0, 0, 0)
+#define SYS_CTR_EL0                                     sys_reg(3, 3, 0, 0, 1)
+#define SYS_DCZID_EL0                                   sys_reg(3, 3, 0, 0, 7)
+#define SYS_GCSPR_EL0                                   sys_reg(3, 3, 2, 5, 1)
+#define SYS_SVCR                                        sys_reg(3, 3, 4, 2, 2)
+#define SYS_FPMR                                        sys_reg(3, 3, 4, 4, 2)
+#define SYS_HFGRTR_EL2                                  sys_reg(3, 4, 1, 1, 4)
+#define SYS_HFGWTR_EL2                                  sys_reg(3, 4, 1, 1, 5)
+#define SYS_HFGITR_EL2                                  sys_reg(3, 4, 1, 1, 6)
+#define SYS_HDFGRTR_EL2                                 sys_reg(3, 4, 3, 1, 4)
+#define SYS_HDFGWTR_EL2                                 sys_reg(3, 4, 3, 1, 5)
+#define SYS_HAFGRTR_EL2                                 sys_reg(3, 4, 3, 1, 6)
+#define SYS_ZCR_EL2                                     sys_reg(3, 4, 1, 2, 0)
+#define SYS_HCRX_EL2                                    sys_reg(3, 4, 1, 2, 2)
+#define SYS_SMPRIMAP_EL2                                sys_reg(3, 4, 1, 2, 5)
+#define SYS_SMCR_EL2                                    sys_reg(3, 4, 1, 2, 6)
+#define SYS_GCSCR_EL2                                   sys_reg(3, 4, 2, 5, 0)
+#define SYS_GCSPR_EL2                                   sys_reg(3, 4, 2, 5, 1)
+#define SYS_DACR32_EL2                                  sys_reg(3, 4, 3, 0, 0)
+#define SYS_FAR_EL2                                     sys_reg(3, 4, 6, 0, 0)
+#define SYS_PMSCR_EL2                                   sys_reg(3, 4, 9, 9, 0)
+#define SYS_CONTEXTIDR_EL2                              sys_reg(3, 4, 13, 0, 1)
+#define SYS_CNTPOFF_EL2                                 sys_reg(3, 4, 14, 0, 6)
+#define SYS_CPACR_EL12                                  sys_reg(3, 5, 1, 0, 2)
+#define SYS_ZCR_EL12                                    sys_reg(3, 5, 1, 2, 0)
+#define SYS_SMCR_EL12                                   sys_reg(3, 5, 1, 2, 6)
+#define SYS_GCSCR_EL12                                  sys_reg(3, 5, 2, 5, 0)
+#define SYS_GCSPR_EL12                                  sys_reg(3, 5, 2, 5, 1)
+#define SYS_FAR_EL12                                    sys_reg(3, 5, 6, 0, 0)
+#define SYS_CONTEXTIDR_EL12                             sys_reg(3, 5, 13, 0, 1)
+#define SYS_TTBR0_EL1                                   sys_reg(3, 0, 2, 0, 0)
+#define SYS_TTBR1_EL1                                   sys_reg(3, 0, 2, 0, 1)
+#define SYS_TCR2_EL1                                    sys_reg(3, 0, 2, 0, 3)
+#define SYS_TCR2_EL12                                   sys_reg(3, 5, 2, 0, 3)
+#define SYS_TCR2_EL2                                    sys_reg(3, 4, 2, 0, 3)
+#define SYS_MAIR2_EL1                                   sys_reg(3, 0, 10, 2, 1)
+#define SYS_MAIR2_EL2                                   sys_reg(3, 4, 10, 1, 1)
+#define SYS_AMAIR2_EL1                                  sys_reg(3, 0, 10, 3, 1)
+#define SYS_AMAIR2_EL2                                  sys_reg(3, 4, 10, 3, 1)
+#define SYS_PIRE0_EL1                                   sys_reg(3, 0, 10, 2, 2)
+#define SYS_PIRE0_EL12                                  sys_reg(3, 5, 10, 2, 2)
+#define SYS_PIR_EL1                                     sys_reg(3, 0, 10, 2, 3)
+#define SYS_PIR_EL12                                    sys_reg(3, 5, 10, 2, 3)
+#define SYS_PIR_EL2                                     sys_reg(3, 4, 10, 2, 3)
+#define SYS_POR_EL0                                     sys_reg(3, 3, 10, 2, 4)
+#define SYS_POR_EL1                                     sys_reg(3, 0, 10, 2, 4)
+#define SYS_POR_EL12                                    sys_reg(3, 5, 10, 2, 4)
+#define SYS_S2POR_EL1                                   sys_reg(3, 0, 10, 2, 5)
+#define SYS_S2PIR_EL2                                   sys_reg(3, 4, 10, 2, 5)
+#define SYS_LORSA_EL1                                   sys_reg(3, 0, 10, 4, 0)
+#define SYS_LOREA_EL1                                   sys_reg(3, 0, 10, 4, 1)
+#define SYS_LORN_EL1                                    sys_reg(3, 0, 10, 4, 2)
+#define SYS_LORC_EL1                                    sys_reg(3, 0, 10, 4, 3)
+#define SYS_LORID_EL1                                   sys_reg(3, 0, 10, 4, 7)
+#define SYS_ISR_EL1                                     sys_reg(3, 0, 12, 1, 0)
+#define SYS_ICC_NMIAR1_EL1                              sys_reg(3, 0, 12, 9, 5)
+#define SYS_TRBLIMITR_EL1                               sys_reg(3, 0, 9, 11, 0)
+#define SYS_TRBPTR_EL1                                  sys_reg(3, 0, 9, 11, 1)
+#define SYS_TRBBASER_EL1                                sys_reg(3, 0, 9, 11, 2)
+#define SYS_TRBSR_EL1                                   sys_reg(3, 0, 9, 11, 3)
+#define SYS_TRBMAR_EL1                                  sys_reg(3, 0, 9, 11, 4)
+#define SYS_TRBTRG_EL1                                  sys_reg(3, 0, 9, 11, 6)
+#define SYS_TRBIDR_EL1                                  sys_reg(3, 0, 9, 11, 7)
 
-#endif
+#endif /* ARM_CPU_SYSREGS_H */
diff --git a/target/arm/cpu-sysreg-properties.c b/target/arm/cpu-sysreg-properties.c
index 753e7c9127..4a3106cc48 100644
--- a/target/arm/cpu-sysreg-properties.c
+++ b/target/arm/cpu-sysreg-properties.c
@@ -1,24 +1,3 @@
-/*
- * QEMU ARM CPU SYSREG PROPERTIES
- * to be generated from linux sysreg
- *
- * Copyright (c) 2024, Inc. 2024
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see
- * <http://www.gnu.org/licenses/gpl-2.0.html>
- */
-
 #include "cpu-custom.h"
 
 ARM64SysReg arm64_id_regs[NR_ID_REGS];
@@ -26,16 +5,678 @@ ARM64SysReg arm64_id_regs[NR_ID_REGS];
 void initialize_cpu_sysreg_properties(void)
 {
     memset(arm64_id_regs, 0, sizeof(ARM64SysReg) * NR_ID_REGS);
+
+    /* ID_PFR0_EL1 */
+    ARM64SysReg *ID_PFR0_EL1 = arm64_sysreg_get(3, 0, 0, 1, 0);
+    ID_PFR0_EL1->name = "ID_PFR0_EL1";
+    arm64_sysreg_add_field(ID_PFR0_EL1, "RAS", 28, 31);
+    arm64_sysreg_add_field(ID_PFR0_EL1, "DIT", 24, 27);
+    arm64_sysreg_add_field(ID_PFR0_EL1, "AMU", 20, 23);
+    arm64_sysreg_add_field(ID_PFR0_EL1, "CSV2", 16, 19);
+    arm64_sysreg_add_field(ID_PFR0_EL1, "State3", 12, 15);
+    arm64_sysreg_add_field(ID_PFR0_EL1, "State2", 8, 11);
+    arm64_sysreg_add_field(ID_PFR0_EL1, "State1", 4, 7);
+    arm64_sysreg_add_field(ID_PFR0_EL1, "State0", 0, 3);
+
+    /* ID_PFR1_EL1 */
+    ARM64SysReg *ID_PFR1_EL1 = arm64_sysreg_get(3, 0, 0, 1, 1);
+    ID_PFR1_EL1->name = "ID_PFR1_EL1";
+    arm64_sysreg_add_field(ID_PFR1_EL1, "GIC", 28, 31);
+    arm64_sysreg_add_field(ID_PFR1_EL1, "Virt_frac", 24, 27);
+    arm64_sysreg_add_field(ID_PFR1_EL1, "Sec_frac", 20, 23);
+    arm64_sysreg_add_field(ID_PFR1_EL1, "GenTimer", 16, 19);
+    arm64_sysreg_add_field(ID_PFR1_EL1, "Virtualization", 12, 15);
+    arm64_sysreg_add_field(ID_PFR1_EL1, "MProgMod", 8, 11);
+    arm64_sysreg_add_field(ID_PFR1_EL1, "Security", 4, 7);
+    arm64_sysreg_add_field(ID_PFR1_EL1, "ProgMod", 0, 3);
+
+    /* ID_DFR0_EL1 */
+    ARM64SysReg *ID_DFR0_EL1 = arm64_sysreg_get(3, 0, 0, 1, 2);
+    ID_DFR0_EL1->name = "ID_DFR0_EL1";
+    arm64_sysreg_add_field(ID_DFR0_EL1, "TraceFilt", 28, 31);
+    arm64_sysreg_add_field(ID_DFR0_EL1, "PerfMon", 24, 27);
+    arm64_sysreg_add_field(ID_DFR0_EL1, "MProfDbg", 20, 23);
+    arm64_sysreg_add_field(ID_DFR0_EL1, "MMapTrc", 16, 19);
+    arm64_sysreg_add_field(ID_DFR0_EL1, "CopTrc", 12, 15);
+    arm64_sysreg_add_field(ID_DFR0_EL1, "MMapDbg", 8, 11);
+    arm64_sysreg_add_field(ID_DFR0_EL1, "CopSDbg", 4, 7);
+    arm64_sysreg_add_field(ID_DFR0_EL1, "CopDbg", 0, 3);
+
+    /* ID_AFR0_EL1 */
+    ARM64SysReg *ID_AFR0_EL1 = arm64_sysreg_get(3, 0, 0, 1, 3);
+    ID_AFR0_EL1->name = "ID_AFR0_EL1";
+    arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF3", 12, 15);
+    arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF2", 8, 11);
+    arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF1", 4, 7);
+    arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF0", 0, 3);
+
+    /* ID_MMFR0_EL1 */
+    ARM64SysReg *ID_MMFR0_EL1 = arm64_sysreg_get(3, 0, 0, 1, 4);
+    ID_MMFR0_EL1->name = "ID_MMFR0_EL1";
+    arm64_sysreg_add_field(ID_MMFR0_EL1, "InnerShr", 28, 31);
+    arm64_sysreg_add_field(ID_MMFR0_EL1, "FCSE", 24, 27);
+    arm64_sysreg_add_field(ID_MMFR0_EL1, "AuxReg", 20, 23);
+    arm64_sysreg_add_field(ID_MMFR0_EL1, "TCM", 16, 19);
+    arm64_sysreg_add_field(ID_MMFR0_EL1, "ShareLvl", 12, 15);
+    arm64_sysreg_add_field(ID_MMFR0_EL1, "OuterShr", 8, 11);
+    arm64_sysreg_add_field(ID_MMFR0_EL1, "PMSA", 4, 7);
+    arm64_sysreg_add_field(ID_MMFR0_EL1, "VMSA", 0, 3);
+
+    /* ID_MMFR1_EL1 */
+    ARM64SysReg *ID_MMFR1_EL1 = arm64_sysreg_get(3, 0, 0, 1, 5);
+    ID_MMFR1_EL1->name = "ID_MMFR1_EL1";
+    arm64_sysreg_add_field(ID_MMFR1_EL1, "BPred", 28, 31);
+    arm64_sysreg_add_field(ID_MMFR1_EL1, "L1TstCln", 24, 27);
+    arm64_sysreg_add_field(ID_MMFR1_EL1, "L1Uni", 20, 23);
+    arm64_sysreg_add_field(ID_MMFR1_EL1, "L1Hvd", 16, 19);
+    arm64_sysreg_add_field(ID_MMFR1_EL1, "L1UniSW", 12, 15);
+    arm64_sysreg_add_field(ID_MMFR1_EL1, "L1HvdSW", 8, 11);
+    arm64_sysreg_add_field(ID_MMFR1_EL1, "L1UniVA", 4, 7);
+    arm64_sysreg_add_field(ID_MMFR1_EL1, "L1HvdVA", 0, 3);
+
+    /* ID_MMFR2_EL1 */
+    ARM64SysReg *ID_MMFR2_EL1 = arm64_sysreg_get(3, 0, 0, 1, 6);
+    ID_MMFR2_EL1->name = "ID_MMFR2_EL1";
+    arm64_sysreg_add_field(ID_MMFR2_EL1, "HWAccFlg", 28, 31);
+    arm64_sysreg_add_field(ID_MMFR2_EL1, "WFIStall", 24, 27);
+    arm64_sysreg_add_field(ID_MMFR2_EL1, "MemBarr", 20, 23);
+    arm64_sysreg_add_field(ID_MMFR2_EL1, "UniTLB", 16, 19);
+    arm64_sysreg_add_field(ID_MMFR2_EL1, "HvdTLB", 12, 15);
+    arm64_sysreg_add_field(ID_MMFR2_EL1, "L1HvdRng", 8, 11);
+    arm64_sysreg_add_field(ID_MMFR2_EL1, "L1HvdBG", 4, 7);
+    arm64_sysreg_add_field(ID_MMFR2_EL1, "L1HvdFG", 0, 3);
+
+    /* ID_MMFR3_EL1 */
+    ARM64SysReg *ID_MMFR3_EL1 = arm64_sysreg_get(3, 0, 0, 1, 7);
+    ID_MMFR3_EL1->name = "ID_MMFR3_EL1";
+    arm64_sysreg_add_field(ID_MMFR3_EL1, "Supersec", 28, 31);
+    arm64_sysreg_add_field(ID_MMFR3_EL1, "CMemSz", 24, 27);
+    arm64_sysreg_add_field(ID_MMFR3_EL1, "CohWalk", 20, 23);
+    arm64_sysreg_add_field(ID_MMFR3_EL1, "PAN", 16, 19);
+    arm64_sysreg_add_field(ID_MMFR3_EL1, "MaintBcst", 12, 15);
+    arm64_sysreg_add_field(ID_MMFR3_EL1, "BPMaint", 8, 11);
+    arm64_sysreg_add_field(ID_MMFR3_EL1, "CMaintSW", 4, 7);
+    arm64_sysreg_add_field(ID_MMFR3_EL1, "CMaintVA", 0, 3);
+
+    /* ID_ISAR0_EL1 */
+    ARM64SysReg *ID_ISAR0_EL1 = arm64_sysreg_get(3, 0, 0, 2, 0);
+    ID_ISAR0_EL1->name = "ID_ISAR0_EL1";
+    arm64_sysreg_add_field(ID_ISAR0_EL1, "Divide", 24, 27);
+    arm64_sysreg_add_field(ID_ISAR0_EL1, "Debug", 20, 23);
+    arm64_sysreg_add_field(ID_ISAR0_EL1, "Coproc", 16, 19);
+    arm64_sysreg_add_field(ID_ISAR0_EL1, "CmpBranch", 12, 15);
+    arm64_sysreg_add_field(ID_ISAR0_EL1, "BitField", 8, 11);
+    arm64_sysreg_add_field(ID_ISAR0_EL1, "BitCount", 4, 7);
+    arm64_sysreg_add_field(ID_ISAR0_EL1, "Swap", 0, 3);
+
+    /* ID_ISAR1_EL1 */
+    ARM64SysReg *ID_ISAR1_EL1 = arm64_sysreg_get(3, 0, 0, 2, 1);
+    ID_ISAR1_EL1->name = "ID_ISAR1_EL1";
+    arm64_sysreg_add_field(ID_ISAR1_EL1, "Jazelle", 28, 31);
+    arm64_sysreg_add_field(ID_ISAR1_EL1, "Interwork", 24, 27);
+    arm64_sysreg_add_field(ID_ISAR1_EL1, "Immediate", 20, 23);
+    arm64_sysreg_add_field(ID_ISAR1_EL1, "IfThen", 16, 19);
+    arm64_sysreg_add_field(ID_ISAR1_EL1, "Extend", 12, 15);
+    arm64_sysreg_add_field(ID_ISAR1_EL1, "Except_AR", 8, 11);
+    arm64_sysreg_add_field(ID_ISAR1_EL1, "Except", 4, 7);
+    arm64_sysreg_add_field(ID_ISAR1_EL1, "Endian", 0, 3);
+
+    /* ID_ISAR2_EL1 */
+    ARM64SysReg *ID_ISAR2_EL1 = arm64_sysreg_get(3, 0, 0, 2, 2);
+    ID_ISAR2_EL1->name = "ID_ISAR2_EL1";
+    arm64_sysreg_add_field(ID_ISAR2_EL1, "Reversal", 28, 31);
+    arm64_sysreg_add_field(ID_ISAR2_EL1, "PSR_AR", 24, 27);
+    arm64_sysreg_add_field(ID_ISAR2_EL1, "MultU", 20, 23);
+    arm64_sysreg_add_field(ID_ISAR2_EL1, "MultS", 16, 19);
+    arm64_sysreg_add_field(ID_ISAR2_EL1, "Mult", 12, 15);
+    arm64_sysreg_add_field(ID_ISAR2_EL1, "MultiAccessInt", 8, 11);
+    arm64_sysreg_add_field(ID_ISAR2_EL1, "MemHint", 4, 7);
+    arm64_sysreg_add_field(ID_ISAR2_EL1, "LoadStore", 0, 3);
+
+    /* ID_ISAR3_EL1 */
+    ARM64SysReg *ID_ISAR3_EL1 = arm64_sysreg_get(3, 0, 0, 2, 3);
+    ID_ISAR3_EL1->name = "ID_ISAR3_EL1";
+    arm64_sysreg_add_field(ID_ISAR3_EL1, "T32EE", 28, 31);
+    arm64_sysreg_add_field(ID_ISAR3_EL1, "TrueNOP", 24, 27);
+    arm64_sysreg_add_field(ID_ISAR3_EL1, "T32Copy", 20, 23);
+    arm64_sysreg_add_field(ID_ISAR3_EL1, "TabBranch", 16, 19);
+    arm64_sysreg_add_field(ID_ISAR3_EL1, "SynchPrim", 12, 15);
+    arm64_sysreg_add_field(ID_ISAR3_EL1, "SVC", 8, 11);
+    arm64_sysreg_add_field(ID_ISAR3_EL1, "SIMD", 4, 7);
+    arm64_sysreg_add_field(ID_ISAR3_EL1, "Saturate", 0, 3);
+
+    /* ID_ISAR4_EL1 */
+    ARM64SysReg *ID_ISAR4_EL1 = arm64_sysreg_get(3, 0, 0, 2, 4);
+    ID_ISAR4_EL1->name = "ID_ISAR4_EL1";
+    arm64_sysreg_add_field(ID_ISAR4_EL1, "SWP_frac", 28, 31);
+    arm64_sysreg_add_field(ID_ISAR4_EL1, "PSR_M", 24, 27);
+    arm64_sysreg_add_field(ID_ISAR4_EL1, "SynchPrim_frac", 20, 23);
+    arm64_sysreg_add_field(ID_ISAR4_EL1, "Barrier", 16, 19);
+    arm64_sysreg_add_field(ID_ISAR4_EL1, "SMC", 12, 15);
+    arm64_sysreg_add_field(ID_ISAR4_EL1, "Writeback", 8, 11);
+    arm64_sysreg_add_field(ID_ISAR4_EL1, "WithShifts", 4, 7);
+    arm64_sysreg_add_field(ID_ISAR4_EL1, "Unpriv", 0, 3);
+
+    /* ID_ISAR5_EL1 */
+    ARM64SysReg *ID_ISAR5_EL1 = arm64_sysreg_get(3, 0, 0, 2, 5);
+    ID_ISAR5_EL1->name = "ID_ISAR5_EL1";
+    arm64_sysreg_add_field(ID_ISAR5_EL1, "VCMA", 28, 31);
+    arm64_sysreg_add_field(ID_ISAR5_EL1, "RDM", 24, 27);
+    arm64_sysreg_add_field(ID_ISAR5_EL1, "CRC32", 16, 19);
+    arm64_sysreg_add_field(ID_ISAR5_EL1, "SHA2", 12, 15);
+    arm64_sysreg_add_field(ID_ISAR5_EL1, "SHA1", 8, 11);
+    arm64_sysreg_add_field(ID_ISAR5_EL1, "AES", 4, 7);
+    arm64_sysreg_add_field(ID_ISAR5_EL1, "SEVL", 0, 3);
+
+    /* ID_ISAR6_EL1 */
+    ARM64SysReg *ID_ISAR6_EL1 = arm64_sysreg_get(3, 0, 0, 2, 7);
+    ID_ISAR6_EL1->name = "ID_ISAR6_EL1";
+    arm64_sysreg_add_field(ID_ISAR6_EL1, "I8MM", 24, 27);
+    arm64_sysreg_add_field(ID_ISAR6_EL1, "BF16", 20, 23);
+    arm64_sysreg_add_field(ID_ISAR6_EL1, "SPECRES", 16, 19);
+    arm64_sysreg_add_field(ID_ISAR6_EL1, "SB", 12, 15);
+    arm64_sysreg_add_field(ID_ISAR6_EL1, "FHM", 8, 11);
+    arm64_sysreg_add_field(ID_ISAR6_EL1, "DP", 4, 7);
+    arm64_sysreg_add_field(ID_ISAR6_EL1, "JSCVT", 0, 3);
+
+    /* ID_MMFR4_EL1 */
+    ARM64SysReg *ID_MMFR4_EL1 = arm64_sysreg_get(3, 0, 0, 2, 6);
+    ID_MMFR4_EL1->name = "ID_MMFR4_EL1";
+    arm64_sysreg_add_field(ID_MMFR4_EL1, "EVT", 28, 31);
+    arm64_sysreg_add_field(ID_MMFR4_EL1, "CCIDX", 24, 27);
+    arm64_sysreg_add_field(ID_MMFR4_EL1, "LSM", 20, 23);
+    arm64_sysreg_add_field(ID_MMFR4_EL1, "HPDS", 16, 19);
+    arm64_sysreg_add_field(ID_MMFR4_EL1, "CnP", 12, 15);
+    arm64_sysreg_add_field(ID_MMFR4_EL1, "XNX", 8, 11);
+    arm64_sysreg_add_field(ID_MMFR4_EL1, "AC2", 4, 7);
+    arm64_sysreg_add_field(ID_MMFR4_EL1, "SpecSEI", 0, 3);
+
+    /* MVFR0_EL1 */
+    ARM64SysReg *MVFR0_EL1 = arm64_sysreg_get(3, 0, 0, 3, 0);
+    MVFR0_EL1->name = "MVFR0_EL1";
+    arm64_sysreg_add_field(MVFR0_EL1, "FPRound", 28, 31);
+    arm64_sysreg_add_field(MVFR0_EL1, "FPShVec", 24, 27);
+    arm64_sysreg_add_field(MVFR0_EL1, "FPSqrt", 20, 23);
+    arm64_sysreg_add_field(MVFR0_EL1, "FPDivide", 16, 19);
+    arm64_sysreg_add_field(MVFR0_EL1, "FPTrap", 12, 15);
+    arm64_sysreg_add_field(MVFR0_EL1, "FPDP", 8, 11);
+    arm64_sysreg_add_field(MVFR0_EL1, "FPSP", 4, 7);
+    arm64_sysreg_add_field(MVFR0_EL1, "SIMDReg", 0, 3);
+
+    /* MVFR1_EL1 */
+    ARM64SysReg *MVFR1_EL1 = arm64_sysreg_get(3, 0, 0, 3, 1);
+    MVFR1_EL1->name = "MVFR1_EL1";
+    arm64_sysreg_add_field(MVFR1_EL1, "SIMDFMAC", 28, 31);
+    arm64_sysreg_add_field(MVFR1_EL1, "FPHP", 24, 27);
+    arm64_sysreg_add_field(MVFR1_EL1, "SIMDHP", 20, 23);
+    arm64_sysreg_add_field(MVFR1_EL1, "SIMDSP", 16, 19);
+    arm64_sysreg_add_field(MVFR1_EL1, "SIMDInt", 12, 15);
+    arm64_sysreg_add_field(MVFR1_EL1, "SIMDLS", 8, 11);
+    arm64_sysreg_add_field(MVFR1_EL1, "FPDNaN", 4, 7);
+    arm64_sysreg_add_field(MVFR1_EL1, "FPFtZ", 0, 3);
+
+    /* MVFR2_EL1 */
+    ARM64SysReg *MVFR2_EL1 = arm64_sysreg_get(3, 0, 0, 3, 2);
+    MVFR2_EL1->name = "MVFR2_EL1";
+    arm64_sysreg_add_field(MVFR2_EL1, "FPMisc", 4, 7);
+    arm64_sysreg_add_field(MVFR2_EL1, "SIMDMisc", 0, 3);
+
+    /* ID_PFR2_EL1 */
+    ARM64SysReg *ID_PFR2_EL1 = arm64_sysreg_get(3, 0, 0, 3, 4);
+    ID_PFR2_EL1->name = "ID_PFR2_EL1";
+    arm64_sysreg_add_field(ID_PFR2_EL1, "RAS_frac", 8, 11);
+    arm64_sysreg_add_field(ID_PFR2_EL1, "SSBS", 4, 7);
+    arm64_sysreg_add_field(ID_PFR2_EL1, "CSV3", 0, 3);
+
+    /* ID_DFR1_EL1 */
+    ARM64SysReg *ID_DFR1_EL1 = arm64_sysreg_get(3, 0, 0, 3, 5);
+    ID_DFR1_EL1->name = "ID_DFR1_EL1";
+    arm64_sysreg_add_field(ID_DFR1_EL1, "HPMN0", 4, 7);
+    arm64_sysreg_add_field(ID_DFR1_EL1, "MTPMU", 0, 3);
+
+    /* ID_MMFR5_EL1 */
+    ARM64SysReg *ID_MMFR5_EL1 = arm64_sysreg_get(3, 0, 0, 3, 6);
+    ID_MMFR5_EL1->name = "ID_MMFR5_EL1";
+    arm64_sysreg_add_field(ID_MMFR5_EL1, "nTLBPA", 4, 7);
+    arm64_sysreg_add_field(ID_MMFR5_EL1, "ETS", 0, 3);
+
+    /* ID_AA64PFR0_EL1 */
+    ARM64SysReg *ID_AA64PFR0_EL1 = arm64_sysreg_get(3, 0, 0, 4, 0);
+    ID_AA64PFR0_EL1->name = "ID_AA64PFR0_EL1";
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "CSV3", 60, 63);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "CSV2", 56, 59);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "RME", 52, 55);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "DIT", 48, 51);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "AMU", 44, 47);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "MPAM", 40, 43);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "SEL2", 36, 39);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "SVE", 32, 35);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "RAS", 28, 31);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "GIC", 24, 27);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "AdvSIMD", 20, 23);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "AdvSIMD", 20, 23);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "FP", 16, 19);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "FP", 16, 19);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL3", 12, 15);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL2", 8, 11);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL1", 4, 7);
+    arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL0", 0, 3);
+
+    /* ID_AA64PFR1_EL1 */
+    ARM64SysReg *ID_AA64PFR1_EL1 = arm64_sysreg_get(3, 0, 0, 4, 1);
+    ID_AA64PFR1_EL1->name = "ID_AA64PFR1_EL1";
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "PFAR", 60, 63);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "DF2", 56, 59);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MTEX", 52, 55);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "THE", 48, 51);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "GCS", 44, 47);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MTE_frac", 40, 43);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "NMI", 36, 39);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "CSV2_frac", 32, 35);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "RNDR_trap", 28, 31);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "SME", 24, 27);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MPAM_frac", 16, 19);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "RAS_frac", 12, 15);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MTE", 8, 11);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "SSBS", 4, 7);
+    arm64_sysreg_add_field(ID_AA64PFR1_EL1, "BT", 0, 3);
+
+    /* ID_AA64PFR2_EL1 */
+    ARM64SysReg *ID_AA64PFR2_EL1 = arm64_sysreg_get(3, 0, 0, 4, 2);
+    ID_AA64PFR2_EL1->name = "ID_AA64PFR2_EL1";
+    arm64_sysreg_add_field(ID_AA64PFR2_EL1, "FPMR", 32, 35);
+    arm64_sysreg_add_field(ID_AA64PFR2_EL1, "MTEFAR", 8, 11);
+    arm64_sysreg_add_field(ID_AA64PFR2_EL1, "MTESTOREONLY", 4, 7);
+    arm64_sysreg_add_field(ID_AA64PFR2_EL1, "MTEPERM", 0, 3);
+
+    /* ID_AA64ZFR0_EL1 */
+    ARM64SysReg *ID_AA64ZFR0_EL1 = arm64_sysreg_get(3, 0, 0, 4, 4);
+    ID_AA64ZFR0_EL1->name = "ID_AA64ZFR0_EL1";
+    arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "F64MM", 56, 59);
+    arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "F32MM", 52, 55);
+    arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "I8MM", 44, 47);
+    arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "SM4", 40, 43);
+    arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "SHA3", 32, 35);
+    arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "B16B16", 24, 27);
+    arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "BF16", 20, 23);
+    arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "BitPerm", 16, 19);
+    arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "AES", 4, 7);
+    arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "SVEver", 0, 3);
+
+    /* ID_AA64SMFR0_EL1 */
+    ARM64SysReg *ID_AA64SMFR0_EL1 = arm64_sysreg_get(3, 0, 0, 4, 5);
+    ID_AA64SMFR0_EL1->name = "ID_AA64SMFR0_EL1";
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "FA64", 63, 63);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "LUTv2", 60, 60);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SMEver", 56, 59);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "I16I64", 52, 55);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F64F64", 48, 48);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "I16I32", 44, 47);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "B16B16", 43, 43);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F16F16", 42, 42);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F8F16", 41, 41);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F8F32", 40, 40);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "I8I32", 36, 39);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F16F32", 35, 35);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "B16F32", 34, 34);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "BI32I32", 33, 33);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F32F32", 32, 32);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SF8FMA", 30, 30);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SF8DP4", 29, 29);
+    arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SF8DP2", 28, 28);
+
+    /* ID_AA64FPFR0_EL1 */
+    ARM64SysReg *ID_AA64FPFR0_EL1 = arm64_sysreg_get(3, 0, 0, 4, 7);
+    ID_AA64FPFR0_EL1->name = "ID_AA64FPFR0_EL1";
+    arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8CVT", 31, 31);
+    arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8FMA", 30, 30);
+    arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8DP4", 29, 29);
+    arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8DP2", 28, 28);
+    arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8E4M3", 1, 1);
+    arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8E5M2", 0, 0);
+
+    /* ID_AA64DFR0_EL1 */
+    ARM64SysReg *ID_AA64DFR0_EL1 = arm64_sysreg_get(3, 0, 0, 5, 0);
+    ID_AA64DFR0_EL1->name = "ID_AA64DFR0_EL1";
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "HPMN0", 60, 63);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "ExtTrcBuff", 56, 59);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "BRBE", 52, 55);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "MTPMU", 48, 51);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "TraceBuffer", 44, 47);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "TraceFilt", 40, 43);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "DoubleLock", 36, 39);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "PMSVer", 32, 35);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "CTX_CMPs", 28, 31);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "WRPs", 20, 23);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "BRPs", 12, 15);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "PMUVer", 8, 11);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "TraceVer", 4, 7);
+    arm64_sysreg_add_field(ID_AA64DFR0_EL1, "DebugVer", 0, 3);
+
+    /* ID_AA64DFR1_EL1 */
+    ARM64SysReg *ID_AA64DFR1_EL1 = arm64_sysreg_get(3, 0, 0, 5, 1);
+    ID_AA64DFR1_EL1->name = "ID_AA64DFR1_EL1";
+    arm64_sysreg_add_field(ID_AA64DFR1_EL1, "ABL_CMPs", 56, 63);
+    arm64_sysreg_add_field(ID_AA64DFR1_EL1, "DPFZS", 52, 55);
+    arm64_sysreg_add_field(ID_AA64DFR1_EL1, "EBEP", 48, 51);
+    arm64_sysreg_add_field(ID_AA64DFR1_EL1, "ITE", 44, 47);
+    arm64_sysreg_add_field(ID_AA64DFR1_EL1, "ABLE", 40, 43);
+    arm64_sysreg_add_field(ID_AA64DFR1_EL1, "PMICNTR", 36, 39);
+    arm64_sysreg_add_field(ID_AA64DFR1_EL1, "SPMU", 32, 35);
+    arm64_sysreg_add_field(ID_AA64DFR1_EL1, "CTX_CMPs", 24, 31);
+    arm64_sysreg_add_field(ID_AA64DFR1_EL1, "WRPs", 16, 23);
+    arm64_sysreg_add_field(ID_AA64DFR1_EL1, "BRPs", 8, 15);
+    arm64_sysreg_add_field(ID_AA64DFR1_EL1, "SYSPMUID", 0, 7);
+
+    /* ID_AA64AFR0_EL1 */
+    ARM64SysReg *ID_AA64AFR0_EL1 = arm64_sysreg_get(3, 0, 0, 5, 4);
+    ID_AA64AFR0_EL1->name = "ID_AA64AFR0_EL1";
+    arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF7", 28, 31);
+    arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF6", 24, 27);
+    arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF5", 20, 23);
+    arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF4", 16, 19);
+    arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF3", 12, 15);
+    arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF2", 8, 11);
+    arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF1", 4, 7);
+    arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF0", 0, 3);
+
+    /* ID_AA64AFR1_EL1 */
+    ARM64SysReg *ID_AA64AFR1_EL1 = arm64_sysreg_get(3, 0, 0, 5, 5);
+    ID_AA64AFR1_EL1->name = "ID_AA64AFR1_EL1";
+
+    /* ID_AA64ISAR0_EL1 */
+    ARM64SysReg *ID_AA64ISAR0_EL1 = arm64_sysreg_get(3, 0, 0, 6, 0);
+    ID_AA64ISAR0_EL1->name = "ID_AA64ISAR0_EL1";
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "RNDR", 60, 63);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "TLB", 56, 59);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "TS", 52, 55);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "FHM", 48, 51);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "DP", 44, 47);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SM4", 40, 43);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SM3", 36, 39);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SHA3", 32, 35);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "RDM", 28, 31);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "TME", 24, 27);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "ATOMIC", 20, 23);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "CRC32", 16, 19);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SHA2", 12, 15);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SHA1", 8, 11);
+    arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "AES", 4, 7);
+
+    /* ID_AA64ISAR1_EL1 */
+    ARM64SysReg *ID_AA64ISAR1_EL1 = arm64_sysreg_get(3, 0, 0, 6, 1);
+    ID_AA64ISAR1_EL1->name = "ID_AA64ISAR1_EL1";
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "LS64", 60, 63);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "XS", 56, 59);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "I8MM", 52, 55);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "DGH", 48, 51);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "BF16", 44, 47);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "SPECRES", 40, 43);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "SB", 36, 39);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "FRINTTS", 32, 35);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "GPI", 28, 31);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "GPA", 24, 27);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "LRCPC", 20, 23);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "FCMA", 16, 19);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "JSCVT", 12, 15);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "API", 8, 11);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "APA", 4, 7);
+    arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "DPB", 0, 3);
+
+    /* ID_AA64ISAR2_EL1 */
+    ARM64SysReg *ID_AA64ISAR2_EL1 = arm64_sysreg_get(3, 0, 0, 6, 2);
+    ID_AA64ISAR2_EL1->name = "ID_AA64ISAR2_EL1";
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "ATS1A", 60, 63);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "LUT", 56, 59);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "CSSC", 52, 55);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "RPRFM", 48, 51);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "PRFMSLC", 40, 43);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "SYSINSTR_128", 36, 39);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "SYSREG_128", 32, 35);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "CLRBHB", 28, 31);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "PAC_frac", 24, 27);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "BC", 20, 23);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "MOPS", 16, 19);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "APA3", 12, 15);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "GPA3", 8, 11);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "RPRES", 4, 7);
+    arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "WFxT", 0, 3);
+
+    /* ID_AA64ISAR3_EL1 */
+    ARM64SysReg *ID_AA64ISAR3_EL1 = arm64_sysreg_get(3, 0, 0, 6, 3);
+    ID_AA64ISAR3_EL1->name = "ID_AA64ISAR3_EL1";
+    arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "PACM", 12, 15);
+    arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "TLBIW", 8, 11);
+    arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "FAMINMAX", 4, 7);
+    arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "CPA", 0, 3);
+
+    /* ID_AA64MMFR0_EL1 */
+    ARM64SysReg *ID_AA64MMFR0_EL1 = arm64_sysreg_get(3, 0, 0, 7, 0);
+    ID_AA64MMFR0_EL1->name = "ID_AA64MMFR0_EL1";
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "ECV", 60, 63);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "FGT", 56, 59);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "EXS", 44, 47);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN4_2", 40, 43);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN64_2", 36, 39);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN16_2", 32, 35);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN4", 28, 31);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN4", 28, 31);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN64", 24, 27);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN64", 24, 27);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN16", 20, 23);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "BIGENDEL0", 16, 19);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "SNSMEM", 12, 15);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "BIGEND", 8, 11);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "ASIDBITS", 4, 7);
+    arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "PARANGE", 0, 3);
+
+    /* ID_AA64MMFR1_EL1 */
+    ARM64SysReg *ID_AA64MMFR1_EL1 = arm64_sysreg_get(3, 0, 0, 7, 1);
+    ID_AA64MMFR1_EL1->name = "ID_AA64MMFR1_EL1";
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "ECBHB", 60, 63);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "CMOW", 56, 59);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "TIDCP1", 52, 55);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "nTLBPA", 48, 51);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "AFP", 44, 47);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "HCX", 40, 43);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "ETS", 36, 39);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "TWED", 32, 35);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "XNX", 28, 31);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "SpecSEI", 24, 27);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "PAN", 20, 23);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "LO", 16, 19);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "HPDS", 12, 15);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "VH", 8, 11);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "VMIDBits", 4, 7);
+    arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "HAFDBS", 0, 3);
+
+    /* ID_AA64MMFR2_EL1 */
+    ARM64SysReg *ID_AA64MMFR2_EL1 = arm64_sysreg_get(3, 0, 0, 7, 2);
+    ID_AA64MMFR2_EL1->name = "ID_AA64MMFR2_EL1";
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "E0PD", 60, 63);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "EVT", 56, 59);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "BBM", 52, 55);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "TTL", 48, 51);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "FWB", 40, 43);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "IDS", 36, 39);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "AT", 32, 35);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "ST", 28, 31);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "NV", 24, 27);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "CCIDX", 20, 23);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "VARange", 16, 19);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "IESB", 12, 15);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "LSM", 8, 11);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "UAO", 4, 7);
+    arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "CnP", 0, 3);
+
+    /* ID_AA64MMFR3_EL1 */
+    ARM64SysReg *ID_AA64MMFR3_EL1 = arm64_sysreg_get(3, 0, 0, 7, 3);
+    ID_AA64MMFR3_EL1->name = "ID_AA64MMFR3_EL1";
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "Spec_FPACC", 60, 63);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "ADERR", 56, 59);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "SDERR", 52, 55);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "ANERR", 44, 47);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "SNERR", 40, 43);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "D128_2", 36, 39);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "D128", 32, 35);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "MEC", 28, 31);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "AIE", 24, 27);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S2POE", 20, 23);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S1POE", 16, 19);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S2PIE", 12, 15);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S1PIE", 8, 11);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "SCTLRX", 4, 7);
+    arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "TCRX", 0, 3);
+
+    /* ID_AA64MMFR4_EL1 */
+    ARM64SysReg *ID_AA64MMFR4_EL1 = arm64_sysreg_get(3, 0, 0, 7, 4);
+    ID_AA64MMFR4_EL1->name = "ID_AA64MMFR4_EL1";
+    arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "E3DSE", 36, 39);
+    arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "E2H0", 24, 27);
+    arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "E2H0", 24, 27);
+    arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "NV_frac", 20, 23);
+    arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "FGWTE3", 16, 19);
+    arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "HACDBS", 12, 15);
+    arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "ASID2", 8, 11);
+    arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "EIESB", 4, 7);
+    arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "EIESB", 4, 7);
+
+/* For CPACR_EL1 fields see CPACR_ELx */
+
+/* For ZCR_EL1 fields see ZCR_ELx */
+
+/* For SMCR_EL1 fields see SMCR_ELx */
+
+/* For GCSCR_EL1 fields see GCSCR_ELx */
+
+/* For GCSPR_EL1 fields see GCSPR_ELx */
+
+/* For CONTEXTIDR_EL1 fields see CONTEXTIDR_ELx */
+
+    /* CCSIDR_EL1 */
+    ARM64SysReg *CCSIDR_EL1 = arm64_sysreg_get(3, 1, 0, 0, 0);
+    CCSIDR_EL1->name = "CCSIDR_EL1";
+    arm64_sysreg_add_field(CCSIDR_EL1, "NumSets", 13, 27);
+    arm64_sysreg_add_field(CCSIDR_EL1, "Associativity", 3, 12);
+    arm64_sysreg_add_field(CCSIDR_EL1, "LineSize", 0, 2);
+
+    /* CLIDR_EL1 */
+    ARM64SysReg *CLIDR_EL1 = arm64_sysreg_get(3, 1, 0, 0, 1);
+    CLIDR_EL1->name = "CLIDR_EL1";
+    arm64_sysreg_add_field(CLIDR_EL1, "Ttypen", 33, 46);
+    arm64_sysreg_add_field(CLIDR_EL1, "ICB", 30, 32);
+    arm64_sysreg_add_field(CLIDR_EL1, "LoUU", 27, 29);
+    arm64_sysreg_add_field(CLIDR_EL1, "LoC", 24, 26);
+    arm64_sysreg_add_field(CLIDR_EL1, "LoUIS", 21, 23);
+    arm64_sysreg_add_field(CLIDR_EL1, "Ctype7", 18, 20);
+    arm64_sysreg_add_field(CLIDR_EL1, "Ctype6", 15, 17);
+    arm64_sysreg_add_field(CLIDR_EL1, "Ctype5", 12, 14);
+    arm64_sysreg_add_field(CLIDR_EL1, "Ctype4", 9, 11);
+    arm64_sysreg_add_field(CLIDR_EL1, "Ctype3", 6, 8);
+    arm64_sysreg_add_field(CLIDR_EL1, "Ctype2", 3, 5);
+    arm64_sysreg_add_field(CLIDR_EL1, "Ctype1", 0, 2);
+
+    /* CCSIDR2_EL1 */
+    ARM64SysReg *CCSIDR2_EL1 = arm64_sysreg_get(3, 1, 0, 0, 2);
+    CCSIDR2_EL1->name = "CCSIDR2_EL1";
+    arm64_sysreg_add_field(CCSIDR2_EL1, "NumSets", 0, 23);
+
+    /* GMID_EL1 */
+    ARM64SysReg *GMID_EL1 = arm64_sysreg_get(3, 1, 0, 0, 4);
+    GMID_EL1->name = "GMID_EL1";
+    arm64_sysreg_add_field(GMID_EL1, "BS", 0, 3);
+
+    /* SMIDR_EL1 */
+    ARM64SysReg *SMIDR_EL1 = arm64_sysreg_get(3, 1, 0, 0, 6);
+    SMIDR_EL1->name = "SMIDR_EL1";
+    arm64_sysreg_add_field(SMIDR_EL1, "IMPLEMENTER", 24, 31);
+    arm64_sysreg_add_field(SMIDR_EL1, "REVISION", 16, 23);
+    arm64_sysreg_add_field(SMIDR_EL1, "SMPS", 15, 15);
+    arm64_sysreg_add_field(SMIDR_EL1, "AFFINITY", 0, 11);
+
+    /* CSSELR_EL1 */
+    ARM64SysReg *CSSELR_EL1 = arm64_sysreg_get(3, 2, 0, 0, 0);
+    CSSELR_EL1->name = "CSSELR_EL1";
+    arm64_sysreg_add_field(CSSELR_EL1, "TnD", 4, 4);
+    arm64_sysreg_add_field(CSSELR_EL1, "Level", 1, 3);
+    arm64_sysreg_add_field(CSSELR_EL1, "InD", 0, 0);
+
     /* CTR_EL0 */
     ARM64SysReg *CTR_EL0 = arm64_sysreg_get(3, 3, 0, 0, 1);
     CTR_EL0->name = "CTR_EL0";
-    arm64_sysreg_add_field(CTR_EL0, "TMinline", 32, 37);
+    arm64_sysreg_add_field(CTR_EL0, "TminLine", 32, 37);
     arm64_sysreg_add_field(CTR_EL0, "DIC", 29, 29);
     arm64_sysreg_add_field(CTR_EL0, "IDC", 28, 28);
     arm64_sysreg_add_field(CTR_EL0, "CWG", 24, 27);
     arm64_sysreg_add_field(CTR_EL0, "ERG", 20, 23);
-    arm64_sysreg_add_field(CTR_EL0, "DMinLine", 16, 19);
+    arm64_sysreg_add_field(CTR_EL0, "DminLine", 16, 19);
     arm64_sysreg_add_field(CTR_EL0, "L1Ip", 14, 15);
     arm64_sysreg_add_field(CTR_EL0, "IminLine", 0, 3);
-}
 
+    /* DCZID_EL0 */
+    ARM64SysReg *DCZID_EL0 = arm64_sysreg_get(3, 3, 0, 0, 7);
+    DCZID_EL0->name = "DCZID_EL0";
+    arm64_sysreg_add_field(DCZID_EL0, "DZP", 4, 4);
+    arm64_sysreg_add_field(DCZID_EL0, "BS", 0, 3);
+
+/* For GCSPR_EL0 fields see GCSPR_ELx */
+
+/* For HFGRTR_EL2 fields see HFGxTR_EL2 */
+
+/* For HFGWTR_EL2 fields see HFGxTR_EL2 */
+
+/* For ZCR_EL2 fields see ZCR_ELx */
+
+/* For SMCR_EL2 fields see SMCR_ELx */
+
+/* For GCSCR_EL2 fields see GCSCR_ELx */
+
+/* For GCSPR_EL2 fields see GCSPR_ELx */
+
+/* For CONTEXTIDR_EL2 fields see CONTEXTIDR_ELx */
+
+/* For CPACR_EL12 fields see CPACR_ELx */
+
+/* For ZCR_EL12 fields see ZCR_ELx */
+
+/* For SMCR_EL12 fields see SMCR_ELx */
+
+/* For GCSCR_EL12 fields see GCSCR_ELx */
+
+/* For GCSPR_EL12 fields see GCSPR_ELx */
+
+/* For CONTEXTIDR_EL12 fields see CONTEXTIDR_ELx */
+
+/* For TTBR0_EL1 fields see TTBRx_EL1 */
+
+/* For TTBR1_EL1 fields see TTBRx_EL1 */
+
+/* For TCR2_EL1 fields see TCR2_EL1x */
+
+/* For TCR2_EL12 fields see TCR2_EL1x */
+
+/* For MAIR2_EL1 fields see MAIR2_ELx */
+
+/* For MAIR2_EL2 fields see MAIR2_ELx */
+
+/* For PIRE0_EL1 fields see PIRx_ELx */
+
+/* For PIRE0_EL12 fields see PIRx_ELx */
+
+/* For PIR_EL1 fields see PIRx_ELx */
+
+/* For PIR_EL12 fields see PIRx_ELx */
+
+/* For PIR_EL2 fields see PIRx_ELx */
+
+/* For POR_EL0 fields see PIRx_ELx */
+
+/* For POR_EL1 fields see PIRx_ELx */
+
+/* For POR_EL12 fields see PIRx_ELx */
+
+/* For S2POR_EL1 fields see PIRx_ELx */
+
+/* For S2PIR_EL2 fields see PIRx_ELx */
+
+}
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 16/21] arm/kvm: Allow reading all the writable ID registers
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (14 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 15/21] arm/cpu: Add generated files Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 17/21] arm/kvm: write back modified ID regs to KVM Eric Auger
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

At the moment kvm_arm_get_host_cpu_features() reads a subset of the
ID regs. As we want to introduce properties for all writable ID reg
fields, we want more genericity and read more default host register
values.

Introduce a new get_host_cpu_idregs() helper and add a new exhaustive
boolean parameter to kvm_arm_get_host_cpu_features() and
kvm_arm_set_cpu_features_from_host() to select the right behavior.
the host cpu model keeps the legacy behavior while the new custom
model will read the legacy regs plus all the writable ones. This
definitively brings some redundancy.

A writable_map IdRegMap is introduced in the CPU object. A subsequent
patch will populate it.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/cpu.h        |  3 +++
 target/arm/kvm_arm.h    |  9 +++++--
 target/arm/cpu64.c      |  4 ++--
 target/arm/kvm.c        | 53 ++++++++++++++++++++++++++++++++++++++---
 target/arm/trace-events |  1 +
 5 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 30b265e9b0..96c42ac410 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1045,6 +1045,9 @@ struct ArchCPU {
      */
     ARMIdRegsState writable_id_regs;
 
+    /* ID reg writable bitmask (KVM only) */
+    IdRegMap *writable_map;
+
     /* QOM property to indicate we should use the back-compat CNTFRQ default */
     bool backcompat_cntfrq;
 
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 9868065277..c2da1dffb2 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -143,8 +143,12 @@ uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu);
  *
  * Set up the ARMCPU struct fields up to match the information probed
  * from the host CPU.
+ *
+ * @cpu: cpu object
+ * @exhaustive: if true, all the feature ID regs are queried instead of
+ *              a subset
  */
-void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool exhaustive);
 
 /**
  * kvm_arm_add_vcpu_properties:
@@ -245,7 +249,8 @@ static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap)
 /*
  * These functions should never actually be called without KVM support.
  */
-static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
+static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu,
+                                                      bool exhaustive)
 {
     g_assert_not_reached();
 }
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 9f20886668..86b0797d4b 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -710,14 +710,14 @@ static void aarch64_host_initfn(Object *obj)
 {
 #if defined(CONFIG_KVM)
     ARMCPU *cpu = ARM_CPU(obj);
-    kvm_arm_set_cpu_features_from_host(cpu);
+    kvm_arm_set_cpu_features_from_host(cpu, false);
     if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
         aarch64_add_sve_properties(obj);
         aarch64_add_pauth_properties(obj);
     }
 #elif defined(CONFIG_HVF)
     ARMCPU *cpu = ARM_CPU(obj);
-    hvf_arm_set_cpu_features_from_host(cpu);
+    hvf_arm_set_cpu_features_from_host(cpu, false);
     aarch64_add_pauth_properties(obj);
 #else
     g_assert_not_reached();
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index bd53554832..a0daf4c382 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -40,6 +40,7 @@
 #include "hw/acpi/acpi.h"
 #include "hw/acpi/ghes.h"
 #include "target/arm/gtimer.h"
+#include "cpu-custom.h"
 
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
@@ -255,8 +256,49 @@ static int get_host_cpu_reg64(int fd, ARMHostCPUFeatures *ahcf, ARMSysReg sr)
     return ret;
 }
 
+/*
+ * get_host_cpu_idregs: Read all the writable ID reg host values
+ *
+ * Need to be called once the writable mask has been populated
+ * Note we may want to read all the known id regs but some of them are not
+ * writable and return an error, hence the choice of reading only those which
+ * are writable. Those are aslo readable!
+ */
+static int get_host_cpu_idregs(ARMCPU *cpu, int fd, ARMHostCPUFeatures *ahcf)
+{
+    int err = 0;
+    int i;
 
-static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
+    for (i = 0; i < NR_ID_REGS; i++) {
+        ARM64SysReg *sysregdesc = &arm64_id_regs[i];
+        ARMSysReg *sysreg = sysregdesc->sysreg;
+        uint64_t writable_mask = cpu->writable_map->regs[i];
+        uint64_t *reg;
+        int ret;
+
+        if (!sysreg || !writable_mask) {
+            continue;
+        }
+
+        reg = &ahcf->isar.idregs.regs[i];
+        ret = read_sys_reg64(fd, reg,
+                             ARM64_SYS_REG(sysreg->op0, sysreg->op1,
+                                           sysreg->crn, sysreg->crm,
+                                           sysreg->op2));
+        trace_get_host_cpu_idregs(sysregdesc->name, *reg);
+        if (ret) {
+            error_report("%s error reading value of host %s register (%m)",
+                         __func__, sysregdesc->name);
+
+            err = ret;
+        }
+    }
+    return err;
+}
+
+static bool
+kvm_arm_get_host_cpu_features(ARMCPU *cpu, ARMHostCPUFeatures *ahcf,
+                              bool exhaustive)
 {
     /* Identify the feature bits corresponding to the host CPU, and
      * fill out the ARMHostCPUClass fields accordingly. To do this
@@ -383,6 +425,11 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_DFR1_EL1);
         err |= get_host_cpu_reg32(fd, ahcf, SYS_ID_MMFR5_EL1);
 
+        /* Make sure writable ID reg values are read */
+        if (exhaustive) {
+            err |= get_host_cpu_idregs(cpu, fd, ahcf);
+        }
+
         /*
          * DBGDIDR is a bit complicated because the kernel doesn't
          * provide an accessor for it in 64-bit mode, which is what this
@@ -453,13 +500,13 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
     return true;
 }
 
-void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool exhaustive)
 {
     CPUARMState *env = &cpu->env;
 
     if (!arm_host_cpu_features.dtb_compatible) {
         if (!kvm_enabled() ||
-            !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) {
+            !kvm_arm_get_host_cpu_features(cpu, &arm_host_cpu_features, exhaustive)) {
             /* We can't report this error yet, so flag that we need to
              * in arm_cpu_realizefn().
              */
diff --git a/target/arm/trace-events b/target/arm/trace-events
index 4438dce7be..0df3bfafff 100644
--- a/target/arm/trace-events
+++ b/target/arm/trace-events
@@ -13,3 +13,4 @@ arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
 
 # kvm.c
 kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64
+get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu gost value for %s is 0x%"PRIx64
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 17/21] arm/kvm: write back modified ID regs to KVM
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (15 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 16/21] arm/kvm: Allow reading all the writable ID registers Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model Eric Auger
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

We want to give a chance to override the value of host ID regs.
In a previous patch we made sure all their values could be fetched
through kvm_get_one_reg() calls before their modification. After
their potential modification we need to make sure we write back
the values through kvm_set_one_reg() calls.

Make sure the cpreg_list is modified with updated values and
transfer those values back to kvm.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 target/arm/kvm.c        | 36 +++++++++++++++++++++++++++++++++++-
 target/arm/trace-events |  1 +
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index a0daf4c382..b63578789d 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -1052,6 +1052,31 @@ void kvm_arm_cpu_post_load(ARMCPU *cpu)
     }
 }
 
+static void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu)
+{
+    for (int i = 0; i < NR_ID_REGS; i++) {
+        uint64_t writable_mask = cpu->writable_map->regs[i];
+        uint64_t *cpreg;
+
+        if (writable_mask) {
+            uint64_t regidx;
+            uint64_t previous, new;
+            ARM64SysReg *sysregdesc = &arm64_id_regs[i];
+            ARMSysReg *sr = sysregdesc->sysreg;
+
+            regidx = ARM64_SYS_REG(sr->op0, sr->op1, sr->crn, sr->crm, sr->op2);
+            cpreg = kvm_arm_get_cpreg_ptr(cpu, regidx);
+            previous = *cpreg;
+            new = cpu->isar.idregs.regs[i];
+            if (previous != new) {
+                *cpreg = new;
+                trace_kvm_arm_writable_idregs_to_cpreg_list(sysregdesc->name,
+                                                            previous, new);
+            }
+        }
+    }
+}
+
 void kvm_arm_reset_vcpu(ARMCPU *cpu)
 {
     int ret;
@@ -2019,7 +2044,16 @@ int kvm_arch_init_vcpu(CPUState *cs)
     }
     cpu->mp_affinity = mpidr & ARM64_AFFINITY_MASK;
 
-    return kvm_arm_init_cpreg_list(cpu);
+    ret = kvm_arm_init_cpreg_list(cpu);
+    if (ret) {
+        return ret;
+    }
+    /* overwrite writable ID regs with their updated property values */
+    kvm_arm_writable_idregs_to_cpreg_list(cpu);
+
+    write_list_to_kvmstate(cpu, 3);
+
+    return 0;
 }
 
 int kvm_arch_destroy_vcpu(CPUState *cs)
diff --git a/target/arm/trace-events b/target/arm/trace-events
index 0df3bfafff..668acf94ab 100644
--- a/target/arm/trace-events
+++ b/target/arm/trace-events
@@ -14,3 +14,4 @@ arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
 # kvm.c
 kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64
 get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu gost value for %s is 0x%"PRIx64
+kvm_arm_writable_idregs_to_cpreg_list(const char *name, uint64_t previous, uint64_t new) "%s overwrite default 0x%"PRIx64" with 0x%"PRIx64
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (16 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 17/21] arm/kvm: write back modified ID regs to KVM Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 13:06   ` Daniel P. Berrangé
  2024-10-25 10:17 ` [RFC 19/21] virt: Allow custom vcpu model in arm virt Eric Auger
                   ` (4 subsequent siblings)
  22 siblings, 1 reply; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

This new cpu model takes by default the host cpu values.
However it exposes uint64 SYSREG properties for writable ID reg
fields exposed by the host kernel. Properties are named
SYSREG_<REG>_<FIELD> with REG and FIELD being those used
in linux arch/arm64/tools/sysreg. This done by matching the
writable fields retrieved from the host kernel against the
generated description of sysregs.

An example of invocation is:
-cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
which sets DP field of ID_AA64ISAR0_EL1 to 0.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>

---

At the moment, the custom model does not support legacy options
of the host cpu model. We need to understand what we do with those
latter (SVE, ...). This means that related KVM ioctl are
not called yet.
---
 target/arm/cpu.c        |  15 ++++
 target/arm/cpu64.c      | 153 ++++++++++++++++++++++++++++++++++++++++
 target/arm/trace-events |   6 ++
 3 files changed, 174 insertions(+)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 454d546feb..e5ac3c3e75 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1990,6 +1990,21 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         return;
     }
 
+    /*
+     * If we failed to retrieve the set of writable ID registers for a "custom"
+     * CPU model, report it here.
+     * In case we did get the set of writable ID registers, set the features to
+     * the configured values here and perform some sanity checks.
+     */
+    if (cpu->writable_id_regs == WRITABLE_ID_REGS_NOT_DISCOVERABLE) {
+        error_setg(errp, "Host kernel does not support discovering "
+                         "writable id registers");
+        return;
+    } else if (cpu->writable_id_regs == WRITABLE_ID_REGS_FAILED) {
+        error_setg(errp, "Failed to discover writable id registers");
+        return;
+    }
+
     if (!cpu->gt_cntfrq_hz) {
         /*
          * 0 means "the board didn't set a value, use the default". (We also
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 86b0797d4b..f10cc4ef8f 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -20,6 +20,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qemu/error-report.h"
 #include "cpu.h"
 #include "cpregs.h"
 #include "qemu/module.h"
@@ -35,6 +36,8 @@
 #include "cpu-features.h"
 #include "cpregs.h"
 #include "cpu-custom.h"
+#include "cpu-sysregs.h"
+#include "trace.h"
 
 void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
 {
@@ -742,6 +745,153 @@ static void aarch64_max_initfn(Object *obj)
     }
 }
 
+#ifdef CONFIG_KVM
+
+static ARM64SysRegField *get_field(int i, ARM64SysReg *reg)
+{
+    GList *l;
+
+    for (l = reg->fields; l; l = l->next) {
+        ARM64SysRegField *field = (ARM64SysRegField *)l->data;
+
+        if (i >= field->lower && i <= field->upper) {
+            return field;
+        }
+    }
+    return NULL;
+}
+
+static void set_sysreg_prop(Object *obj, Visitor *v,
+                            const char *name, void *opaque,
+                            Error **errp)
+{
+    ARM64SysRegField *field = (ARM64SysRegField *)opaque;
+    ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
+    uint64_t old, value, mask;
+    int lower = field->lower;
+    int upper = field->upper;
+    int length = upper - lower + 1;
+    int index = field->index;
+
+    if (!visit_type_uint64(v, name, &value, errp)) {
+        return;
+    }
+
+    if (length < 64 && value > ((1 << length) - 1)) {
+        error_setg(errp,
+                   "idreg %s set value (0x%lx) exceeds length of field (%d)!",
+                   name, value, length);
+        return;
+    }
+
+    mask = MAKE_64BIT_MASK(lower, length);
+    value = value << lower;
+    old = idregs->regs[index];
+    idregs->regs[index] = old & ~mask;
+    idregs->regs[index] |= value;
+    trace_set_sysreg_prop(name, old, mask, value, idregs->regs[index]);
+}
+
+static void get_sysreg_prop(Object *obj, Visitor *v,
+                            const char *name, void *opaque,
+                            Error **errp)
+{
+    ARM64SysRegField *field = (ARM64SysRegField *)opaque;
+    ARMCPU *cpu = ARM_CPU(obj);
+    IdRegMap *idregs = &cpu->isar.idregs;
+    int index = field->index;
+
+    error_report("%s %s", __func__, name);
+    visit_type_uint64(v, name, &idregs->regs[index], errp);
+    trace_get_sysreg_prop(name, idregs->regs[index]);
+}
+
+/*
+ * decode_idreg_writemap: Generate props for writable fields
+ *
+ * @obj: CPU object
+ * @index: index of the sysreg
+ * @map: writable map for the sysreg
+ * @reg: description of the sysreg
+ */
+static int
+decode_idreg_writemap(Object *obj, int index, uint64_t map, ARM64SysReg *reg)
+{
+    int i = ctz64(map);
+    int nb_sysreg_props = 0;
+
+    while (map) {
+        ARM64SysRegField *field = get_field(i, reg);
+        int lower, upper;
+        uint64_t mask;
+        char *prop_name;
+
+        if (!field) {
+            /* the field cannot be matched to any know id named field */
+            warn_report("%s bit %d of %s is writable but cannot be matched",
+                        __func__, i, reg->name);
+            warn_report("%s is cpu-sysreg-properties.c up to date?", __func__);
+            map =  map & ~BIT_ULL(i);
+            i = ctz64(map);
+            continue;
+        }
+        lower = field->lower;
+        upper = field->upper;
+        prop_name = g_strdup_printf("SYSREG_%s_%s", reg->name, field->name);
+        trace_decode_idreg_writemap(field->name, lower, upper, prop_name);
+        object_property_add(obj, prop_name, "uint64",
+                            get_sysreg_prop, set_sysreg_prop, NULL, field);
+        nb_sysreg_props++;
+
+        mask = MAKE_64BIT_MASK(lower, upper - lower + 1);
+        map = map & ~mask;
+        i = ctz64(map);
+    }
+    trace_nb_sysreg_props(reg->name, nb_sysreg_props);
+    return 0;
+}
+
+/* analyze the writable mask and generate properties for writable fields */
+static int expose_idreg_properties(Object *obj, IdRegMap *map,
+                                   ARM64SysReg *regs)
+{
+    int i;
+
+    for (i = 0; i < NR_ID_REGS; i++) {
+        uint64_t mask = map->regs[i];
+
+        if (mask) {
+            /* reg @i has some writable fields, decode them */
+            decode_idreg_writemap(obj, i, mask, &regs[i]);
+        }
+    }
+    return 0;
+}
+
+static void aarch64_customcpu_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    int ret;
+
+    cpu->writable_map = g_malloc(sizeof(IdRegMap));
+
+    /* discover via KVM_ARM_GET_REG_WRITABLE_MASKS */
+    ret = kvm_arm_get_writable_id_regs(cpu, cpu->writable_map);
+    if (ret) {
+        /* function will have marked an error */
+        return;
+    }
+
+    /* populate from the host (exhaustive) , validate during realize */
+    kvm_arm_set_cpu_features_from_host(cpu, true);
+
+    /* generate SYSREG properties according to writable masks */
+    expose_idreg_properties(obj, cpu->writable_map, arm64_id_regs);
+}
+
+#endif
+
 static const ARMCPUInfo aarch64_cpus[] = {
     { .name = "cortex-a57",         .initfn = aarch64_a57_initfn },
     { .name = "cortex-a53",         .initfn = aarch64_a53_initfn },
@@ -749,6 +899,9 @@ static const ARMCPUInfo aarch64_cpus[] = {
 #if defined(CONFIG_KVM) || defined(CONFIG_HVF)
     { .name = "host",               .initfn = aarch64_host_initfn },
 #endif
+#ifdef CONFIG_KVM
+    { .name = "custom",             .initfn = aarch64_customcpu_initfn },
+#endif
 };
 
 static bool aarch64_cpu_get_aarch64(Object *obj, Error **errp)
diff --git a/target/arm/trace-events b/target/arm/trace-events
index 668acf94ab..1b4bd5ab14 100644
--- a/target/arm/trace-events
+++ b/target/arm/trace-events
@@ -15,3 +15,9 @@ arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
 kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64
 get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu gost value for %s is 0x%"PRIx64
 kvm_arm_writable_idregs_to_cpreg_list(const char *name, uint64_t previous, uint64_t new) "%s overwrite default 0x%"PRIx64" with 0x%"PRIx64
+
+# cpu64.c
+decode_idreg_writemap(const char* name, int lower, int upper, char *prop_name) "%s [%d:%d] is writable (prop %s)"
+get_sysreg_prop(const char *name, uint64_t value) "%s 0x%"PRIx64
+set_sysreg_prop(const char *name, uint64_t old, uint64_t mask, uint64_t field_value, uint64_t new) "%s old reg value=0x%"PRIx64" mask=0x%"PRIx64" new field value=0x%"PRIx64" new reg value=0x%"PRIx64
+nb_sysreg_props(const char *name, int count) "%s: %d SYSREG properties"
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 19/21] virt: Allow custom vcpu model in arm virt
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (17 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 20/21] arm-qmp-cmds: introspection for custom model Eric Auger
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

From: Cornelia Huck <cohuck@redhat.com>

Allowing the use of the custom vcpu model in ARM virt.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 hw/arm/virt.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index b0c68d66a3..edde4b5007 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -3052,6 +3052,9 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
 #if defined(CONFIG_KVM) || defined(CONFIG_HVF)
         ARM_CPU_TYPE_NAME("host"),
 #endif /* CONFIG_KVM || CONFIG_HVF */
+#ifdef CONFIG_KVM
+        ARM_CPU_TYPE_NAME("custom"),
+#endif /* CONFIG_KVM */
 #endif /* TARGET_AARCH64 */
         ARM_CPU_TYPE_NAME("max"),
         NULL
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 20/21] arm-qmp-cmds: introspection for custom model
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (18 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 19/21] virt: Allow custom vcpu model in arm virt Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 10:17 ` [RFC 21/21] arm/cpu-features: Document custom vcpu model Eric Auger
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

From: Cornelia Huck <cohuck@redhat.com>

Implement the capability to query available options for the
custom model.

At the moment it only returns SYSREG_* options and values.
Excerpt:
(QEMU) query-cpu-model-expansion type=full model={"name":"custom"}
{"return": {"model": {"name": "custom", "props":
{"SYSREG_ID_AA64PFR0_EL1_EL3": 1224979098931106066,
"SYSREG_ID_AA64ISAR2_EL1_CLRBHB": 0,
../..

So this allows the upper stack to detect available writable ID
regs and the "host passthrough model" values.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>

---

TODO: Add the moment there is no way to test changing a given
ID reg field value. ie:

(QEMU) query-cpu-model-expansion type=full model={"name":"custom", "prop":{"SYSREG_ID_AA64ISAR0_EL1_DP":0x13}}
---
 target/arm/arm-qmp-cmds.c | 56 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
index 3cc8cc738b..4a3f0e6ac6 100644
--- a/target/arm/arm-qmp-cmds.c
+++ b/target/arm/arm-qmp-cmds.c
@@ -21,6 +21,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "hw/boards.h"
 #include "kvm_arm.h"
 #include "qapi/error.h"
@@ -98,6 +99,47 @@ static const char *cpu_model_advertised_features[] = {
     NULL
 };
 
+static CpuModelExpansionInfo *
+arm_query_custom_cpu_model_expansion(Object *obj, CpuModelExpansionType type,
+                                     CpuModelInfo *model,
+                                     Error **errp)
+{
+    /* returns id register map */
+    CpuModelExpansionInfo *expansion_info;
+    ObjectProperty *prop;
+    ObjectPropertyIterator iter;
+    QDict *qdict_out;
+
+    expansion_info = g_new0(CpuModelExpansionInfo, 1);
+    expansion_info->model = g_malloc0(sizeof(*expansion_info->model));
+    expansion_info->model->name = g_strdup(model->name);
+
+    qdict_out = qdict_new();
+
+    object_property_iter_init(&iter, obj);
+
+    while ((prop = object_property_iter_next(&iter))) {
+        QObject *value;
+
+        if (!g_str_has_prefix(prop->name, "SYSREG_")) {
+            continue;
+        }
+        value = object_property_get_qobject(obj, prop->name, &error_abort);
+        qdict_put_obj(qdict_out, prop->name, value);
+    }
+
+    if (!qdict_size(qdict_out)) {
+        qobject_unref(qdict_out);
+    } else {
+        expansion_info->model->props = QOBJECT(qdict_out);
+    }
+
+    object_unref(obj);
+
+
+    return expansion_info;
+}
+
 CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
                                                      CpuModelInfo *model,
                                                      Error **errp)
@@ -130,7 +172,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
     if (kvm_enabled()) {
         bool supported = false;
 
-        if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
+        if (!strcmp(model->name, "host") || !strcmp(model->name, "max") ||
+            !strcmp(model->name, "custom")) {
             /* These are kvmarm's recommended cpu types */
             supported = true;
         } else if (current_machine->cpu_type) {
@@ -152,6 +195,17 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
 
     obj = object_new(object_class_get_name(oc));
 
+    /* The "custom" model is handled differently. */
+    if (!strcmp(model->name, "custom")) {
+        expansion_info = arm_query_custom_cpu_model_expansion(obj, type, model,
+                                                              errp);
+        if (*errp) {
+            object_unref(obj);
+            return NULL;
+        }
+        return expansion_info;
+    }
+
     if (model->props) {
         Visitor *visitor;
         Error *err = NULL;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (19 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 20/21] arm-qmp-cmds: introspection for custom model Eric Auger
@ 2024-10-25 10:17 ` Eric Auger
  2024-10-25 13:13   ` Daniel P. Berrangé
  2024-10-28 21:17   ` Kashyap Chamarthy
  2024-10-25 12:49 ` [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Cornelia Huck
  2024-10-25 14:51 ` Kashyap Chamarthy
  22 siblings, 2 replies; 72+ messages in thread
From: Eric Auger @ 2024-10-25 10:17 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

From: Cornelia Huck <cohuck@redhat.com>

Add some documentation for the custom model.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 8 deletions(-)

diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
index a5fb929243..962a2c6c26 100644
--- a/docs/system/arm/cpu-features.rst
+++ b/docs/system/arm/cpu-features.rst
@@ -2,7 +2,10 @@ Arm CPU Features
 ================
 
 CPU features are optional features that a CPU of supporting type may
-choose to implement or not.  In QEMU, optional CPU features have
+choose to implement or not.  QEMU provides two different mechanisms
+to configure those features:
+
+1. For most CPU models, optional CPU features may have
 corresponding boolean CPU proprieties that, when enabled, indicate
 that the feature is implemented, and, conversely, when disabled,
 indicate that it is not implemented. An example of an Arm CPU feature
@@ -29,6 +32,16 @@ supports the feature.  While ``aarch64`` currently only works with KVM,
 it could work with TCG.  CPU features that are specific to KVM are
 prefixed with "kvm-" and are described in "KVM VCPU Features".
 
+2. Alternatively, the ``custom`` CPU model allows to configure optional
+CPU features via the corresponding ID registers. The host kernel allows
+to write a subset of ID register fields. The custom model exposes
+properties for each write ID register fields. Those options are named
+SYSREG_<IDREG>_<FIELD>. IDREG and FIELD names are those used in the
+ARM ARM Reference Manual. They can also be found in the linux
+arch/arm64/tool/sysreg file which is used to automatically generate the
+description for those registers and fields. The custom model is currently
+only implemented for KVM.
+
 CPU Feature Probing
 ===================
 
@@ -106,6 +119,10 @@ As expected they are now all ``false``.
 
 Only the ``pmu`` CPU feature is available.
 
+Probing for the ``custom`` CPU model is working differently. CPU model
+expansion will return the list of available SYSREG properties (matching
+writable ID register fields)
+
 A note about CPU feature dependencies
 -------------------------------------
 
@@ -119,18 +136,30 @@ independently without error.  For these reasons callers should always
 attempt to make their desired changes all at once in order to ensure the
 collection is valid.
 
+When using the ``custom`` CPU model, the provided set of ID registers
+is always evaluated as a whole.
+
 A note about CPU models and KVM
 -------------------------------
 
 Named CPU models generally do not work with KVM.  There are a few cases
 that do work, e.g. using the named CPU model ``cortex-a57`` with KVM on a
-seattle host, but mostly if KVM is enabled the ``host`` CPU type must be
-used.  This means the guest is provided all the same CPU features as the
-host CPU type has.  And, for this reason, the ``host`` CPU type should
-enable all CPU features that the host has by default.  Indeed it's even
-a bit strange to allow disabling CPU features that the host has when using
-the ``host`` CPU type, but in the absence of CPU models it's the best we can
-do if we want to launch guests without all the host's CPU features enabled.
+seattle host, but mostly if KVM is enabled, either the ``host`` or the
+``custom`` CPU types must be used.
+
+Using the ``host`` type means the guest is provided all the same CPU
+features as the host CPU type has.  And, for this reason, the ``host``
+CPU type should enable all CPU features that the host has by default.
+
+In case some features need to be hidden to the guest, ``custom`` model
+shall be used instead. This is especially useful for migration purpose.
+
+The ``custom`` CPU model generally is the better choice if you want more
+flexibility or stability across different machines or with different kernel
+versions. However, even the ``custom`` CPU model will not allow configuring
+an arbitrary set of features; the ID registers must describe a subset of the
+host's features, and all differences to the host's configuration must actually
+be supported by the kernel to be deconfigured.
 
 Enabling KVM also affects the ``query-cpu-model-expansion`` QMP command.  The
 affect is not only limited to specific features, as pointed out in example
@@ -167,6 +196,16 @@ disabling many SVE vector lengths would be quite verbose, the ``sve<N>`` CPU
 properties have special semantics (see "SVE CPU Property Parsing
 Semantics").
 
+The ``custom`` CPU model needs to be configured via individual ID register
+field properties, for example::
+
+  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
+
+This forces ID_AA64ISAR0_EL1 DP field to 0.
+
+Note that the other CPU feature properties are not supported when using
+this model.
+
 KVM VCPU Features
 =================
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 72+ messages in thread

* Re: [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (20 preceding siblings ...)
  2024-10-25 10:17 ` [RFC 21/21] arm/cpu-features: Document custom vcpu model Eric Auger
@ 2024-10-25 12:49 ` Cornelia Huck
  2024-10-25 14:51 ` Kashyap Chamarthy
  22 siblings, 0 replies; 72+ messages in thread
From: Cornelia Huck @ 2024-10-25 12:49 UTC (permalink / raw)
  To: Eric Auger, eric.auger.pro, eric.auger, qemu-devel, qemu-arm,
	kvmarm, peter.maydell, richard.henderson, alex.bennee, maz,
	oliver.upton, sebott, shameerali.kolothum.thodi, armbru, berrange,
	abologna, jdenemar
  Cc: shahuang, mark.rutland, philmd, pbonzini

On Fri, Oct 25 2024, Eric Auger <eric.auger@redhat.com> wrote:

> This RFC series introduces a KVM host "custom" model.
>
> Since v6.7 kernel, KVM/arm allows the userspace to overwrite the values
> of a subset of ID regs. The list of writable fields continues to grow.
> The feature ID range is defined as the AArch64 System register space
> with op0==3, op1=={0, 1, 3}, CRn==0, CRm=={0-7}, op2=={0-7}.
>
> The custom model uses this capability and allows to tune the host
> passthrough model by overriding some of the host passthrough ID regs.
>
> The end goal is to get more flexibility when migrating guests
> between different machines. We would like the upper software layer
> to be able detect how tunable the vpcu is on both source and destination
> and accordingly define a customized KVM host model that can fit
> both ends. With the legacy host passthrough model, this migration
> use case would fail.
>
> QEMU queries the host kernel to get the list of writable ID reg
> fields and expose all the writable fields as uint64 properties. Those
> are named "SYSREG_<REG>_<FIELD>". REG and FIELD names are those
> described in ARM ARM Reference manual and linux arch/arm64/tools/sysreg.
> Some awk scriptsintroduced in the series help parsing the sysreg file and
> generate some code. those scripts are used in a similar way as
> scripts/update-linux-headers.sh.  In case the ABI gets broken, it is
> still possible to manually edit the generated code. However it is
> globally expected the REG and FIELD names are stable.
>
> The list of SYSREG_ID properties can be retrieved through the qmp
> monitor using query-cpu-model-expansion [2].
>
> The first part of the series mostly consists in migrating id reg
> storage from named fields in ARMISARegisters to anonymous index
> ordered storage in an IdRegMap struct array. The goal is to have
> a generic way to store all id registers, also compatible with the
> way we retrieve their writable capability at kernel level through
> the KVM_ARM_GET_REG_WRITABLE_MASKS ioctl. Having named fields
> prevented us from getting this scalability/genericity. Although the
> change is invasive  it is quite straightforward and should be easy
> to be reviewed.
>
> Then the bulk of the job is to retrieve the writable ID fields and
> match them against a "human readable" description of those fields.
> We use awk scripts, derived from kernel arch/arm64/tools/gen-sysreg.awk
> (so all the credit to Mark Rutland) that populates a data structure
> which describes all the ID regs in sysreg and their fields. We match
> writable ID reg fields with those latter and dynamically create a
> uint64 property.
>
> Then we need to extend the list of id regs read from the host
> so that we get a chance to let their value overriden and write them
> back into KVM .
>
> This expectation is that this custom KVM host model can prepare for
> the advent of named models. Introducing named models with reduced
> and explicitly defined features is the next step.
>
> Obviously this series is not able to cope with non writable ID regs.
> For instance the problematic of MIDR/REVIDR setting is not handled
> at the moment.
>
> Connie & Eric
>
> This series can be found at:
> https://github.com/eauger/qemu/tree/custom-cpu-model-rfc
>
> TESTS:
> - with few IDREG fields that can be easily examined from guest
>   userspace:
>   -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0,SYSREG_ID_AA64ISAR1_EL1_DPB=0x0
> - migration between custom models
> - TCG A57 non regressions. Light testing for TCG though. Deep
>   review may detect some mistakes when migrating between named fields
>   and IDRegMap storage
> - light testing of introspection. Testing a given writable ID field
>   value with query-cpu-model-expansion is not supported yet.
>
> TODO/QUESTIONS:
> - Some idreg named fields are not yet migrated to an array storage.
>   some of them are not in isar struct either. Maybe we could have
>   handled TCG and KVM separately and it may turn out that this
>   conversion is unneeded. So as it is quite cumbersome I prefered
>   to keep it for a later stage.
> - the custom model does not come with legacy host properties
>   such as SVE, MTE, expecially those that induce some KVM
>   settings. This needs to be fixed.

One idea would be to convert these to sugar and configure the relevant
features instead. The accelerator-specific properties would need to
either stay or be deprecated and later removed, I think; I'd hope there
are as few as possible of those. The ones requiring to actively do
something (e.g. enable MTE with KVM) are the fun ones.

> - The custom model and its exposed properties depend on the host
>   capabilities. More and more IDREG become writable meaning that
>   the custom model gains more properties over the time and it is
>   host linux dependent. At the moment there is no versioning in
>   place. By default the custom model is a host passthrough model
>   (besides the legacy functions). So if the end-user tries to set
>   a field that is not writable from a kernel pov, it will fail.
>   Nevertheless a versionned custom model could constrain the props
>   exposed, independently on the host linux capabilities.

Alternatively (or additionally?), provide a way to discover the set of
writable id regs, e.g. via a qmp command that returns what QEMU got from
KVM_ARM_GET_REG_WRITABLE_MASKS.

> - the QEMU layer does not take care of IDREG field value consistency.
>   The kernel neither. I imagine this could be the role of the upper
>   layer to implement a vcpu profile that makes sure settings are
>   consistent. Here we come to "named" models. What should they look
>   like on ARM?

I would go with Armv8.6, Armv9.2, etc. that include the mandatory
features, and additionally the features that can go on top (base model,
can be extended; this is similar to what we already have e.g. for s390
z<whatever> models, but allows for the complication that we have many
vendors doing many different designs.) Not sure if we'd also want models
for specific cpus, but that could go on top, I guess.

> - Implementation details:
>   -  it seems there are a lot of duplications in
>   the code. ID regs are described in different manners, with different
>   data structs, for TCG, now for KVM.

Base data struct for all accelerators and used for accelerator-agnostic
code, accelerator-specific structures on top (so that we can add new
accelerators, if wanted?) Once the cpu is up and running, we're not
manipulating the regs anyway.

>   - The IdRegMap->regs is sparsely populated. Maybe a better data
>   struct could be used, although this is the one chosen for the kernel
>   uapi.
>
> References:
>
> [1] [PATCH v12 00/11] Support writable CPU ID registers from userspace
> https://lore.kernel.org/all/20230609190054.1542113-1-oliver.upton@linux.dev/
>
> [2]
> qemu-system-aarch64 -qmp unix:/home/augere/TEST/QEMU/qmp-sock,server,nowait -M virt --enable-kvm -cpu custom
> scripts/qmp/qmp-shell /home/augere/TEST/QEMU/qmp-sock
> Welcome to the QMP low-level shell!
> Connected to QEMU 9.0.50
> (QEMU) query-cpu-model-expansion type=full model={"name":"custom"}
>
> [3]
> KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES
> KVM_ARM_GET_REG_WRITABLE_MASKS
> Documentation/virt/kvm/api.rst
>
> [4] linux "sysreg" file
> linux/arch/arm64/tools/sysreg and gen-sysreg.awk
> ./tools/include/generated/asm/sysreg-defs.h
>
>
> Cornelia Huck (4):
>   kvm: kvm_get_writable_id_regs
>   virt: Allow custom vcpu model in arm virt
>   arm-qmp-cmds: introspection for custom model
>   arm/cpu-features: Document custom vcpu model
>
> Eric Auger (17):
>   arm/cpu: Add sysreg definitions in cpu-sysegs.h
>   arm/cpu: Store aa64isar0 into the idregs arrays
>   arm/cpu: Store aa64isar1/2 into the idregs array
>   arm/cpu: Store aa64drf0/1 into the idregs array
>   arm/cpu: Store aa64mmfr0-3 into the idregs array
>   arm/cpu: Store aa64drf0/1 into the idregs array
>   arm/cpu: Store aa64smfr0 into the idregs array
>   arm/cpu: Store id_isar0-7 into the idregs array
>   arm/cpu: Store id_mfr0/1 into the idregs array
>   arm/cpu: Store id_dfr0/1 into the idregs array
>   arm/cpu: Store id_mmfr0-5 into the idregs array
>   arm/cpu: Add infra to handle generated ID register definitions
>   arm/cpu: Add sysreg generation scripts
>   arm/cpu: Add generated files
>   arm/kvm: Allow reading all the writable ID registers
>   arm/kvm: write back modified ID regs to KVM
>   arm/cpu: Introduce a customizable kvm host cpu model
>
>  docs/system/arm/cpu-features.rst      |  55 ++-
>  target/arm/cpu-custom.h               |  58 +++
>  target/arm/cpu-features.h             | 307 ++++++------
>  target/arm/cpu-sysregs.h              | 152 ++++++
>  target/arm/cpu.h                      | 120 +++--
>  target/arm/internals.h                |   6 +-
>  target/arm/kvm_arm.h                  |  16 +-
>  hw/arm/virt.c                         |   3 +
>  hw/intc/armv7m_nvic.c                 |  27 +-
>  target/arm/arm-qmp-cmds.c             |  56 ++-
>  target/arm/cpu-sysreg-properties.c    | 682 ++++++++++++++++++++++++++
>  target/arm/cpu.c                      | 124 +++--
>  target/arm/cpu64.c                    | 265 +++++++---
>  target/arm/helper.c                   |  68 +--
>  target/arm/kvm.c                      | 253 +++++++---
>  target/arm/ptw.c                      |   6 +-
>  target/arm/tcg/cpu-v7m.c              | 174 +++----
>  target/arm/tcg/cpu32.c                | 320 ++++++------
>  target/arm/tcg/cpu64.c                | 460 ++++++++---------
>  scripts/gen-cpu-sysreg-properties.awk | 325 ++++++++++++
>  scripts/gen-cpu-sysregs-header.awk    |  47 ++
>  scripts/update-aarch64-sysreg-code.sh |  27 +
>  target/arm/meson.build                |   1 +
>  target/arm/trace-events               |   8 +
>  24 files changed, 2646 insertions(+), 914 deletions(-)
>  create mode 100644 target/arm/cpu-custom.h
>  create mode 100644 target/arm/cpu-sysregs.h
>  create mode 100644 target/arm/cpu-sysreg-properties.c
>  create mode 100755 scripts/gen-cpu-sysreg-properties.awk
>  create mode 100755 scripts/gen-cpu-sysregs-header.awk
>  create mode 100755 scripts/update-aarch64-sysreg-code.sh
>
> -- 
> 2.41.0



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 13/21] arm/cpu: Add infra to handle generated ID register definitions
  2024-10-25 10:17 ` [RFC 13/21] arm/cpu: Add infra to handle generated ID register definitions Eric Auger
@ 2024-10-25 12:55   ` Daniel P. Berrangé
  0 siblings, 0 replies; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-10-25 12:55 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Fri, Oct 25, 2024 at 12:17:32PM +0200, Eric Auger wrote:
> The known ID regs are described in a new initialization function
> dubbed initialize_cpu_sysreg_properties(). That code will be
> automatically generated from linux arch/arm64/tools/sysreg. For the
> time being let's just describe a single id reg, CTR_EL0. In this
> description we only care about non RES/RAZ fields, ie. named fields.
> 
> The registers are populated in a 3x8x8 array and their fields are
> added in a sorted list.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> ---
>  target/arm/cpu-custom.h            | 58 ++++++++++++++++++++++++++++++
>  target/arm/cpu-sysreg-properties.c | 41 +++++++++++++++++++++
>  target/arm/cpu64.c                 |  2 ++
>  target/arm/meson.build             |  1 +
>  4 files changed, 102 insertions(+)
>  create mode 100644 target/arm/cpu-custom.h
>  create mode 100644 target/arm/cpu-sysreg-properties.c
> 
> diff --git a/target/arm/cpu-custom.h b/target/arm/cpu-custom.h
> new file mode 100644
> index 0000000000..1952095bf7
> --- /dev/null
> +++ b/target/arm/cpu-custom.h
> @@ -0,0 +1,58 @@
> +#ifndef ARM_CPU_CUSTOM_H
> +#define ARM_CPU_CUSTOM_H

License header her.


> diff --git a/target/arm/cpu-sysreg-properties.c b/target/arm/cpu-sysreg-properties.c
> new file mode 100644
> index 0000000000..753e7c9127
> --- /dev/null
> +++ b/target/arm/cpu-sysreg-properties.c
> @@ -0,0 +1,41 @@
> +/*
> + * QEMU ARM CPU SYSREG PROPERTIES
> + * to be generated from linux sysreg
> + *
> + * Copyright (c) 2024, Inc. 2024

                        ^^^^  missing company name :-)


> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see
> + * <http://www.gnu.org/licenses/gpl-2.0.html>
> + */
> +
> +#include "cpu-custom.h"
> +
> +ARM64SysReg arm64_id_regs[NR_ID_REGS];
> +
> +void initialize_cpu_sysreg_properties(void)
> +{
> +    memset(arm64_id_regs, 0, sizeof(ARM64SysReg) * NR_ID_REGS);

                                ^^^ just sizeof(arm64_id_regs)

> +    /* CTR_EL0 */
> +    ARM64SysReg *CTR_EL0 = arm64_sysreg_get(3, 3, 0, 0, 1);
> +    CTR_EL0->name = "CTR_EL0";
> +    arm64_sysreg_add_field(CTR_EL0, "TMinline", 32, 37);
> +    arm64_sysreg_add_field(CTR_EL0, "DIC", 29, 29);
> +    arm64_sysreg_add_field(CTR_EL0, "IDC", 28, 28);
> +    arm64_sysreg_add_field(CTR_EL0, "CWG", 24, 27);
> +    arm64_sysreg_add_field(CTR_EL0, "ERG", 20, 23);
> +    arm64_sysreg_add_field(CTR_EL0, "DMinLine", 16, 19);
> +    arm64_sysreg_add_field(CTR_EL0, "L1Ip", 14, 15);
> +    arm64_sysreg_add_field(CTR_EL0, "IminLine", 0, 3);
> +}
> +

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-25 10:17 ` [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model Eric Auger
@ 2024-10-25 13:06   ` Daniel P. Berrangé
  2024-10-25 13:18     ` Eric Auger
  0 siblings, 1 reply; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-10-25 13:06 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Fri, Oct 25, 2024 at 12:17:37PM +0200, Eric Auger wrote:
> This new cpu model takes by default the host cpu values.
> However it exposes uint64 SYSREG properties for writable ID reg
> fields exposed by the host kernel. Properties are named
> SYSREG_<REG>_<FIELD> with REG and FIELD being those used
> in linux arch/arm64/tools/sysreg. This done by matching the
> writable fields retrieved from the host kernel against the
> generated description of sysregs.
> 
> An example of invocation is:
> -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
> which sets DP field of ID_AA64ISAR0_EL1 to 0.

"SYSREG_" feels kinda redundant to repeat on every single
feature. 

Also, is this naming convention really the same one that users
will see when they look at /proc/cpuinfo to view features ? It
feels pretty low level to me ?  Naming after the registers &
fields, would be like configuring x86 CPU features by asking
for "SYSREG_EAX_1_ECX_20" instead of saying "vmx" which is the
human friendly name.


> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> 
> ---
> 
> At the moment, the custom model does not support legacy options
> of the host cpu model. We need to understand what we do with those
> latter (SVE, ...). This means that related KVM ioctl are
> not called yet.

It will be pretty painful to have to use different feature
terminology for different CPU models. Everything in libvirt
assuming feature terminology varies per-arch, not per-CPU
model.


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-25 10:17 ` [RFC 21/21] arm/cpu-features: Document custom vcpu model Eric Auger
@ 2024-10-25 13:13   ` Daniel P. Berrangé
  2024-10-25 13:28     ` Eric Auger
  2024-10-28 21:17   ` Kashyap Chamarthy
  1 sibling, 1 reply; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-10-25 13:13 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
> From: Cornelia Huck <cohuck@redhat.com>
> 
> Add some documentation for the custom model.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> ---
>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
>  1 file changed, 47 insertions(+), 8 deletions(-)


> @@ -167,6 +196,16 @@ disabling many SVE vector lengths would be quite verbose, the ``sve<N>`` CPU
>  properties have special semantics (see "SVE CPU Property Parsing
>  Semantics").
>  
> +The ``custom`` CPU model needs to be configured via individual ID register
> +field properties, for example::
> +
> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
> +
> +This forces ID_AA64ISAR0_EL1 DP field to 0.

What is the "baseline" featureset implied by 'custom' ?

On x86 we have the named CPU models each setting a baseline that matches
some corresponding real world silicon. Arm has that too, with TCG at
least. So that way you know what the baseline is that you're toggling
features against.

Experiance on x86 was that making arbitrary feature changes on top of the
named models could often backfire, as there are too many scenarios where
code will check for feature "Y", and assume that existance of "Y" implies
existance of "A", "B" and "C" too. So if you invent custom models where
Y is set, but B is missing, there's decent risk of things going wrong in
horrible to debug ways.  With that in mind, best practice is to try to
just the vanilla named CPU models to the greatest extent possible, and
keep feature toggling to an absolute minimum.  This 'custom' model does
not seem to give us such ability for arm.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-25 13:06   ` Daniel P. Berrangé
@ 2024-10-25 13:18     ` Eric Auger
  2024-10-25 13:23       ` Daniel P. Berrangé
  0 siblings, 1 reply; 72+ messages in thread
From: Eric Auger @ 2024-10-25 13:18 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

Hi Daniel,

On 10/25/24 15:06, Daniel P. Berrangé wrote:
> On Fri, Oct 25, 2024 at 12:17:37PM +0200, Eric Auger wrote:
>> This new cpu model takes by default the host cpu values.
>> However it exposes uint64 SYSREG properties for writable ID reg
>> fields exposed by the host kernel. Properties are named
>> SYSREG_<REG>_<FIELD> with REG and FIELD being those used
>> in linux arch/arm64/tools/sysreg. This done by matching the
>> writable fields retrieved from the host kernel against the
>> generated description of sysregs.
>>
>> An example of invocation is:
>> -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
>> which sets DP field of ID_AA64ISAR0_EL1 to 0.
> "SYSREG_" feels kinda redundant to repeat on every single
> feature. 

I do agree. To be honest this was mostly driven my implementation need
for cpu model expansion. Given the high number of props which are
getting exposed, I iterate on all props and having a prefix let me
return only those SYSREG props. Most probably we can get rid of the
prefix by using some generated code as well.
>
> Also, is this naming convention really the same one that users
> will see when they look at /proc/cpuinfo to view features ? It
No it is not. I do agree that the custom cpu model is very low level. It
is very well suited to test all series turning ID regs as writable but
this would require an extra layer that adapts /proc/cpuinfo feature
level to this regid/field abstraction.

In /cpu/proc you will see somethink like:
 Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
asimdhp cpuid asimdrdm lrcpc dcpop asimddp
> feels pretty low level to me ?  Naming after the registers &
> fields, would be like configuring x86 CPU features by asking
> for "SYSREG_EAX_1_ECX_20" instead of saying "vmx" which is the
> human friendly name.
agreed.
>
>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
>>
>> ---
>>
>> At the moment, the custom model does not support legacy options
>> of the host cpu model. We need to understand what we do with those
>> latter (SVE, ...). This means that related KVM ioctl are
>> not called yet.
> It will be pretty painful to have to use different feature
> terminology for different CPU models. Everything in libvirt
> assuming feature terminology varies per-arch, not per-CPU
> model.
Actually as far as I understand those regids/fields would fit all kind
of aarch64 Cortex-A CPUs. So they wouldn't vary per-CPU (I mean their
terminology. Their availability will).

Thanks

Eric
>
>
> With regards,
> Daniel



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-25 13:18     ` Eric Auger
@ 2024-10-25 13:23       ` Daniel P. Berrangé
  2024-10-28 16:00         ` Cornelia Huck
  2024-10-28 16:16         ` Peter Maydell
  0 siblings, 2 replies; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-10-25 13:23 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
> Hi Daniel,
> 
> On 10/25/24 15:06, Daniel P. Berrangé wrote:
> > On Fri, Oct 25, 2024 at 12:17:37PM +0200, Eric Auger wrote:
> >> This new cpu model takes by default the host cpu values.
> >> However it exposes uint64 SYSREG properties for writable ID reg
> >> fields exposed by the host kernel. Properties are named
> >> SYSREG_<REG>_<FIELD> with REG and FIELD being those used
> >> in linux arch/arm64/tools/sysreg. This done by matching the
> >> writable fields retrieved from the host kernel against the
> >> generated description of sysregs.
> >>
> >> An example of invocation is:
> >> -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
> >> which sets DP field of ID_AA64ISAR0_EL1 to 0.
> > "SYSREG_" feels kinda redundant to repeat on every single
> > feature. 
> 
> I do agree. To be honest this was mostly driven my implementation need
> for cpu model expansion. Given the high number of props which are
> getting exposed, I iterate on all props and having a prefix let me
> return only those SYSREG props. Most probably we can get rid of the
> prefix by using some generated code as well.
> >
> > Also, is this naming convention really the same one that users
> > will see when they look at /proc/cpuinfo to view features ? It
> No it is not. I do agree that the custom cpu model is very low level. It
> is very well suited to test all series turning ID regs as writable but
> this would require an extra layer that adapts /proc/cpuinfo feature
> level to this regid/field abstraction.
> 
> In /cpu/proc you will see somethink like:
>  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
> asimdhp cpuid asimdrdm lrcpc dcpop asimddp

Right, IMHO, this is the terminology that QEMU must use in user
facing APIs.

On x86 we have a conversion tables for named features to register
bits

  https://gitlab.com/qemu-project/qemu/-/blob/master/target/i386/cpu.c#L914

and libvirt does similar

  https://gitlab.com/libvirt/libvirt/-/blob/master/src/cpu_map/x86_features.xml

Yep, it is more work, but it is also much better for humans IMHO.

> > feels pretty low level to me ?  Naming after the registers &
> > fields, would be like configuring x86 CPU features by asking
> > for "SYSREG_EAX_1_ECX_20" instead of saying "vmx" which is the
> > human friendly name.
> agreed.

> >> At the moment, the custom model does not support legacy options
> >> of the host cpu model. We need to understand what we do with those
> >> latter (SVE, ...). This means that related KVM ioctl are
> >> not called yet.
> > It will be pretty painful to have to use different feature
> > terminology for different CPU models. Everything in libvirt
> > assuming feature terminology varies per-arch, not per-CPU
> > model.
> Actually as far as I understand those regids/fields would fit all kind
> of aarch64 Cortex-A CPUs. So they wouldn't vary per-CPU (I mean their
> terminology. Their availability will).

What I mean is can we define  named models for various different
vendor's Cortex-A silicon and just use that without needing to
toggle features, except in rare cases.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-25 13:13   ` Daniel P. Berrangé
@ 2024-10-25 13:28     ` Eric Auger
  2024-10-25 13:31       ` Daniel P. Berrangé
  0 siblings, 1 reply; 72+ messages in thread
From: Eric Auger @ 2024-10-25 13:28 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

Hi Daniel,

On 10/25/24 15:13, Daniel P. Berrangé wrote:
> On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
>> From: Cornelia Huck <cohuck@redhat.com>
>>
>> Add some documentation for the custom model.
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
>> ---
>>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
>>  1 file changed, 47 insertions(+), 8 deletions(-)
>
>> @@ -167,6 +196,16 @@ disabling many SVE vector lengths would be quite verbose, the ``sve<N>`` CPU
>>  properties have special semantics (see "SVE CPU Property Parsing
>>  Semantics").
>>  
>> +The ``custom`` CPU model needs to be configured via individual ID register
>> +field properties, for example::
>> +
>> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
>> +
>> +This forces ID_AA64ISAR0_EL1 DP field to 0.
> What is the "baseline" featureset implied by 'custom' ?
there is no baseline at the moment. By default this is a host
passthrough model.
>
> On x86 we have the named CPU models each setting a baseline that matches
> some corresponding real world silicon. Arm has that too, with TCG at
> least. So that way you know what the baseline is that you're toggling
> features against.
Having named models is the next thing. custom vcpu model is not a named
model. But we don't want to TCG like CPU model (like A57) because we
want to be able to migrate between different machines like Ampere to
NVidia or different Ampere systems. So the baseline must be something
usable by both hosts.
>
> Experiance on x86 was that making arbitrary feature changes on top of the
> named models could often backfire, as there are too many scenarios where
> code will check for feature "Y", and assume that existance of "Y" implies
> existance of "A", "B" and "C" too. So if you invent custom models where
> Y is set, but B is missing, there's decent risk of things going wrong in
> horrible to debug ways.  With that in mind, best practice is to try to
> just the vanilla named CPU models to the greatest extent possible, and
> keep feature toggling to an absolute minimum.  This 'custom' model does
> not seem to give us such ability for arm.
The custom model is not yet a named model. This is rather something to
start this kind of discussion.
The code used by the custom vcpu model allows fine tuning of the ID reg
fields. This code could be reused by named models. We can also imagine
that libvirt does implement the named models, ie. hardcodes some IDReg
fields and thus implement the named model instead. Libvirt could
identify what is the baseline source and dest are the closest to, choose
this baseline and tune few reg id fields if some additional tuning are
needed.

Thanks

Eric
>
> With regards,
> Daniel



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-25 13:28     ` Eric Auger
@ 2024-10-25 13:31       ` Daniel P. Berrangé
  2024-10-28 16:05         ` Cornelia Huck
  0 siblings, 1 reply; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-10-25 13:31 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Fri, Oct 25, 2024 at 03:28:35PM +0200, Eric Auger wrote:
> Hi Daniel,
> 
> On 10/25/24 15:13, Daniel P. Berrangé wrote:
> > On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
> >> From: Cornelia Huck <cohuck@redhat.com>
> >>
> >> Add some documentation for the custom model.
> >>
> >> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> >> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> >> ---
> >>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
> >>  1 file changed, 47 insertions(+), 8 deletions(-)
> >
> >> @@ -167,6 +196,16 @@ disabling many SVE vector lengths would be quite verbose, the ``sve<N>`` CPU
> >>  properties have special semantics (see "SVE CPU Property Parsing
> >>  Semantics").
> >>  
> >> +The ``custom`` CPU model needs to be configured via individual ID register
> >> +field properties, for example::
> >> +
> >> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
> >> +
> >> +This forces ID_AA64ISAR0_EL1 DP field to 0.
> > What is the "baseline" featureset implied by 'custom' ?
> there is no baseline at the moment. By default this is a host
> passthrough model.

Why do we need to create "custom" at all, as opposed to just letting
users toggle features on "-cpu host" ? 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model
  2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
                   ` (21 preceding siblings ...)
  2024-10-25 12:49 ` [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Cornelia Huck
@ 2024-10-25 14:51 ` Kashyap Chamarthy
  2024-10-28 16:20   ` Cornelia Huck
  2024-11-04 15:52   ` Eric Auger
  22 siblings, 2 replies; 72+ messages in thread
From: Kashyap Chamarthy @ 2024-10-25 14:51 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar, shahuang, mark.rutland, philmd, pbonzini

On Fri, Oct 25, 2024 at 12:17:19PM +0200, Eric Auger wrote:

Hi Eric,

I'm new to Arm, so please bear with my questions :)

> This RFC series introduces a KVM host "custom" model.

(a) On terminology: as we know, in the x86 world, QEMU uses these
    terms[1]:

    - Host passthrough
    - Named CPU models
    - Then there's the libvirt abstraction, "host-model", that aims to
      provide the best of 'host-passthrough' + named CPU models.

    Now I see the term "host 'custom' model" here.  Most
    management-layer tools and libvirt users are familiar with the
    classic terms "host-model" or "custom".  If we now say "host
    'custom' model", it can create confusion.  I hope we can settle on
    one of the existing terms, or create a new term if need be.

    (I'll share one more thought on how layers above libvirt tend to use
    the term "custom", as a reply to patch 21/21, "arm/cpu-features:
    Document custom vcpu model".)

(b) The current CPU features doc[2] for Arm doesn't mention "host
    passthrough" at all.  It is only implied by the last part of this
    paragraph, from the section titled "A note about CPU models and
    KVM"[3]:

      "Named CPU models generally do not work with KVM. There are a few
      cases that do work [...] but mostly if KVM is enabled the 'host'
      CPU type must be used."

    Related: in your reply[4] to Dan in this series, you write: "Having
    named models is the next thing".  So named CPU models will be a
    thing in Arm, too?  Then the above statement in the Arm
    'cpu-features' will need updating :-)

[...]

> - the QEMU layer does not take care of IDREG field value consistency.
>   The kernel neither. I imagine this could be the role of the upper
>   layer to implement a vcpu profile that makes sure settings are
>   consistent. Here we come to "named" models. What should they look
>   like on ARM?

Are there reasons why they can't be similar to how x86 reports in
`qemu-system-x86 -cpu help`?  

E.g. If it's an NVIDIA "Grace A02" (Neoverse-V2) host, it can report:

    [gracehopper] $> qemu-kvm -cpu help
    Available CPUs:
      gracehopper-neoverse-v2
      cortex-a57 (deprecated)
      host
      max

Or whatever is the preferred nomenclature for ARM.  It also gives users
of both x86 and ARM deployments a consistent expectation.  

Currently on a "Grace A02" ("Neoverse-V2") machine, it reports:

    [gracehopper] $> qemu-kvm -cpu help
    Available CPUs:
      cortex-a57 (deprecated)
      host
      max

I see it's because there are no named models yet on ARM :-)

[...]

[1] https://www.qemu.org/docs/master/system/i386/cpu.html
[2] https://www.qemu.org/docs/master/system/arm/cpu-features.html
[3] https://www.qemu.org/docs/master/system/arm/cpu-features.html#a-note-about-cpu-models-and-kvm
[4] https://lists.nongnu.org/archive/html/qemu-arm/2024-10/msg00891.html


-- 
/kashyap



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 14/21] arm/cpu: Add sysreg generation scripts
  2024-10-25 10:17 ` [RFC 14/21] arm/cpu: Add sysreg generation scripts Eric Auger
@ 2024-10-25 17:05   ` Marc Zyngier
  2024-11-04 13:33     ` Eric Auger
  0 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2024-10-25 17:05 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar, shahuang, mark.rutland, philmd, pbonzini

On Fri, 25 Oct 2024 11:17:33 +0100,
Eric Auger <eric.auger@redhat.com> wrote:
> 
> Introduce scripts that automate the generation of system register
> definitions from a given linux source tree arch/arm64/tools/sysreg.
> 
> Invocation of
> ./update-aarch64-sysreg-code.sh $PATH_TO_LINUX_SOURCE_TREE
> in scripts directory do generate 2 qemu files:
> - target/arm/cpu-sysreg-properties.c
> - target/arm/cpu-sysregs.h
> 
> cpu-sysregs.h creates defined for all system registers.
> However cpu-sysreg-properties.c only cares about feature ID registers.
> 
> update-aarch64-sysreg-code.sh calls two awk scripts.
> gen-cpu-sysreg-properties.awk is inherited from kernel
> arch/arm64/tools/gen-sysreg.awk. All credits to Mark Rutland
> the original author of this script.

You really want to be careful with this. Both the script and the
source file describing the registers are submitted to regular outburst
of churn (I'm currently sitting on such a series). You really have to
be prepared to see things breaking on each import.

That file has also been known to contain annoying mistakes, as it is
all written by hand.

Ideally, this would be directly generated from the ARM XML, which is a
public set of files. However, the license attached to this package
strictly prohibits its use in QEMU (or anywhere else). One day...

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-25 13:23       ` Daniel P. Berrangé
@ 2024-10-28 16:00         ` Cornelia Huck
  2024-10-28 16:15           ` Daniel P. Berrangé
  2024-10-28 16:16         ` Peter Maydell
  1 sibling, 1 reply; 72+ messages in thread
From: Cornelia Huck @ 2024-10-28 16:00 UTC (permalink / raw)
  To: Daniel P. Berrangé, Eric Auger
  Cc: eric.auger.pro, qemu-devel, qemu-arm, kvmarm, peter.maydell,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

On Fri, Oct 25 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:

> On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
>> Hi Daniel,
>> 
>> On 10/25/24 15:06, Daniel P. Berrangé wrote:
>> > On Fri, Oct 25, 2024 at 12:17:37PM +0200, Eric Auger wrote:
>> >> At the moment, the custom model does not support legacy options
>> >> of the host cpu model. We need to understand what we do with those
>> >> latter (SVE, ...). This means that related KVM ioctl are
>> >> not called yet.
>> > It will be pretty painful to have to use different feature
>> > terminology for different CPU models. Everything in libvirt
>> > assuming feature terminology varies per-arch, not per-CPU
>> > model.
>> Actually as far as I understand those regids/fields would fit all kind
>> of aarch64 Cortex-A CPUs. So they wouldn't vary per-CPU (I mean their
>> terminology. Their availability will).
>
> What I mean is can we define  named models for various different
> vendor's Cortex-A silicon and just use that without needing to
> toggle features, except in rare cases.

I'm not sure whether creating named models for various cpus would
actually scale; what we probably could do is come up with some Armv8.6,
Armv8.7, ... models and have additional models for some well-known cpus.
That would also give us some basic sanity checks for feature
combinations, if we do not want to support completely custom
frankencpus.



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-25 13:31       ` Daniel P. Berrangé
@ 2024-10-28 16:05         ` Cornelia Huck
  2024-10-28 16:09           ` Daniel P. Berrangé
  0 siblings, 1 reply; 72+ messages in thread
From: Cornelia Huck @ 2024-10-28 16:05 UTC (permalink / raw)
  To: Daniel P. Berrangé, Eric Auger
  Cc: eric.auger.pro, qemu-devel, qemu-arm, kvmarm, peter.maydell,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

On Fri, Oct 25 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:

> On Fri, Oct 25, 2024 at 03:28:35PM +0200, Eric Auger wrote:
>> Hi Daniel,
>> 
>> On 10/25/24 15:13, Daniel P. Berrangé wrote:
>> > On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
>> >> From: Cornelia Huck <cohuck@redhat.com>
>> >>
>> >> Add some documentation for the custom model.
>> >>
>> >> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>> >> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
>> >> ---
>> >>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
>> >>  1 file changed, 47 insertions(+), 8 deletions(-)
>> >
>> >> @@ -167,6 +196,16 @@ disabling many SVE vector lengths would be quite verbose, the ``sve<N>`` CPU
>> >>  properties have special semantics (see "SVE CPU Property Parsing
>> >>  Semantics").
>> >>  
>> >> +The ``custom`` CPU model needs to be configured via individual ID register
>> >> +field properties, for example::
>> >> +
>> >> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
>> >> +
>> >> +This forces ID_AA64ISAR0_EL1 DP field to 0.
>> > What is the "baseline" featureset implied by 'custom' ?
>> there is no baseline at the moment. By default this is a host
>> passthrough model.
>
> Why do we need to create "custom" at all, as opposed to just letting
> users toggle features on "-cpu host" ? 

We could consolidate that to the current "host" model, once we figure
out how to handle the currently already existing properties. Models
based on the different architecture extensions would probably be more
useable in the long run; maybe "custom" has a place for testing.



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-28 16:05         ` Cornelia Huck
@ 2024-10-28 16:09           ` Daniel P. Berrangé
  2024-10-28 16:29             ` Cornelia Huck
  2024-11-04 14:45             ` Eric Auger
  0 siblings, 2 replies; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-10-28 16:09 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Eric Auger, eric.auger.pro, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Mon, Oct 28, 2024 at 05:05:44PM +0100, Cornelia Huck wrote:
> On Fri, Oct 25 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:
> 
> > On Fri, Oct 25, 2024 at 03:28:35PM +0200, Eric Auger wrote:
> >> Hi Daniel,
> >> 
> >> On 10/25/24 15:13, Daniel P. Berrangé wrote:
> >> > On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
> >> >> From: Cornelia Huck <cohuck@redhat.com>
> >> >>
> >> >> Add some documentation for the custom model.
> >> >>
> >> >> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> >> >> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> >> >> ---
> >> >>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
> >> >>  1 file changed, 47 insertions(+), 8 deletions(-)
> >> >
> >> >> @@ -167,6 +196,16 @@ disabling many SVE vector lengths would be quite verbose, the ``sve<N>`` CPU
> >> >>  properties have special semantics (see "SVE CPU Property Parsing
> >> >>  Semantics").
> >> >>  
> >> >> +The ``custom`` CPU model needs to be configured via individual ID register
> >> >> +field properties, for example::
> >> >> +
> >> >> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
> >> >> +
> >> >> +This forces ID_AA64ISAR0_EL1 DP field to 0.
> >> > What is the "baseline" featureset implied by 'custom' ?
> >> there is no baseline at the moment. By default this is a host
> >> passthrough model.
> >
> > Why do we need to create "custom" at all, as opposed to just letting
> > users toggle features on "-cpu host" ? 
> 
> We could consolidate that to the current "host" model, once we figure
> out how to handle the currently already existing properties. Models
> based on the different architecture extensions would probably be more
> useable in the long run; maybe "custom" has a place for testing.

If you can set the features against "host", then any testing could
be done with "host" surely, making 'custom' pointless ?

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-28 16:00         ` Cornelia Huck
@ 2024-10-28 16:15           ` Daniel P. Berrangé
  0 siblings, 0 replies; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-10-28 16:15 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Eric Auger, eric.auger.pro, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Mon, Oct 28, 2024 at 05:00:46PM +0100, Cornelia Huck wrote:
> On Fri, Oct 25 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:
> 
> > On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
> >> Hi Daniel,
> >> 
> >> On 10/25/24 15:06, Daniel P. Berrangé wrote:
> >> > On Fri, Oct 25, 2024 at 12:17:37PM +0200, Eric Auger wrote:
> >> >> At the moment, the custom model does not support legacy options
> >> >> of the host cpu model. We need to understand what we do with those
> >> >> latter (SVE, ...). This means that related KVM ioctl are
> >> >> not called yet.
> >> > It will be pretty painful to have to use different feature
> >> > terminology for different CPU models. Everything in libvirt
> >> > assuming feature terminology varies per-arch, not per-CPU
> >> > model.
> >> Actually as far as I understand those regids/fields would fit all kind
> >> of aarch64 Cortex-A CPUs. So they wouldn't vary per-CPU (I mean their
> >> terminology. Their availability will).
> >
> > What I mean is can we define  named models for various different
> > vendor's Cortex-A silicon and just use that without needing to
> > toggle features, except in rare cases.
> 
> I'm not sure whether creating named models for various cpus would
> actually scale; what we probably could do is come up with some Armv8.6,
> Armv8.7, ... models and have additional models for some well-known cpus.
> That would also give us some basic sanity checks for feature
> combinations, if we do not want to support completely custom
> frankencpus.

Yep, even on x86 we don't add named models for every conceivable
CPU SKU variant, just one so called "typical" variant for a given
microarchiteture level [1].

The vendor independent Arm CPU spec versions are a good enough
match for typical real world silicon, then it would make sense
to focus mostly on such named CPU models, not try to make an
exhaustive definition of every vendor's impl. I could see there
might be some exceptions where adding a vendor specific named
model would be worthwhile, but hopefully that'd be relatively
uncommon and   -cpu Armv8.6,+feat1,+feat2 would be sufficient.

eg toggling 1/2/3 extra features to precise match a vendor's
named mode is ok, but adding 20-30 extra features get a match
is painful. That's the kind of rule of thumb that could be
used when deciding whether its worth adding a vendor specific
named model, vs relying on the generic spec based models.

With regards,
Daniel

[1] we do have CPU model versions, as a way to "bugfix" our
    CPU definitions. 
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-25 13:23       ` Daniel P. Berrangé
  2024-10-28 16:00         ` Cornelia Huck
@ 2024-10-28 16:16         ` Peter Maydell
  2024-10-28 16:25           ` Cornelia Huck
  2024-10-28 16:35           ` Daniel P. Berrangé
  1 sibling, 2 replies; 72+ messages in thread
From: Peter Maydell @ 2024-10-28 16:16 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Eric Auger, eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
> On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
> > On 10/25/24 15:06, Daniel P. Berrangé wrote:
> > > Also, is this naming convention really the same one that users
> > > will see when they look at /proc/cpuinfo to view features ? It
> > No it is not. I do agree that the custom cpu model is very low level. It
> > is very well suited to test all series turning ID regs as writable but
> > this would require an extra layer that adapts /proc/cpuinfo feature
> > level to this regid/field abstraction.
> >
> > In /cpu/proc you will see somethink like:
> >  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
> > asimdhp cpuid asimdrdm lrcpc dcpop asimddp
>
> Right, IMHO, this is the terminology that QEMU must use in user
> facing APIs.

/proc/cpuinfo's naming is rather weird for historical
reasons (for instance there is only one FEAT_FP16 feature
but cpuinfo lists "fphp" and "asimdhp" separately).
Currently QEMU only has to care about cpuinfo name tags
in linux-user/elfload.c where there's a bunch of data
structures for "what hwcaps do we need to advertise
given what the CPU has?". I would definitely prefer it if
we could use architectural feature names...

On other architectures do we do anything to forbid
invalid combinations? For Arm there are architectural
rules about feature X requiring features Y and Z.
Are we going to just let the user create a CPU that
the guest OS will barf on if they want to? (The
user-experience for that is potentially not very nice,
because something like "-cpu cortex-a57,+sve" seems like
something you might want to do but isn't actually valid;
even listing the direct required dependency of FEAT_SVE
like "-cpu cortex-a57,+sve,+fp16" isn't sufficient
because SVE is optional-from-v8.2 and so a guest could
in theory assume the presence of anything mandatory in
v8.1 and v8.2. But even merely diagnosing invalid
combinations is a huge pain, and automagically pulling
in every mandatory implicit or explicit dependency
seems like it might be surprising to users, as well as
being annoying to implement. Currently we sidestep
all of these problems by (a) only allowing the command
line to disable a feature, not to enable it where it
didn't previously exist and (b) mostly not providing
command line flags for individual features...)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model
  2024-10-25 14:51 ` Kashyap Chamarthy
@ 2024-10-28 16:20   ` Cornelia Huck
  2024-10-28 16:44     ` Peter Maydell
  2024-11-04 15:52   ` Eric Auger
  1 sibling, 1 reply; 72+ messages in thread
From: Cornelia Huck @ 2024-10-28 16:20 UTC (permalink / raw)
  To: Kashyap Chamarthy, Eric Auger
  Cc: eric.auger.pro, qemu-devel, qemu-arm, kvmarm, peter.maydell,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, berrange, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Fri, Oct 25 2024, Kashyap Chamarthy <kchamart@redhat.com> wrote:

> On Fri, Oct 25, 2024 at 12:17:19PM +0200, Eric Auger wrote:
>
> Hi Eric,
>
> I'm new to Arm, so please bear with my questions :)
>
>> This RFC series introduces a KVM host "custom" model.
>
> (a) On terminology: as we know, in the x86 world, QEMU uses these
>     terms[1]:
>
>     - Host passthrough
>     - Named CPU models
>     - Then there's the libvirt abstraction, "host-model", that aims to
>       provide the best of 'host-passthrough' + named CPU models.
>
>     Now I see the term "host 'custom' model" here.  Most
>     management-layer tools and libvirt users are familiar with the
>     classic terms "host-model" or "custom".  If we now say "host
>     'custom' model", it can create confusion.  I hope we can settle on
>     one of the existing terms, or create a new term if need be.
>
>     (I'll share one more thought on how layers above libvirt tend to use
>     the term "custom", as a reply to patch 21/21, "arm/cpu-features:
>     Document custom vcpu model".)

I came up with the "custom" name just to have something to differentiate
from the currently existing "host" model (which supports a number of
properties that do not translate to id regs.) It is certainly not set in
stone; I expect us to end up with named models and a handling of the
"host" model which is more similar to what is done for other
archs. Maybe we can then rename "custom" to "franken" so that people do
not try to use it for productive work ;)

>
> (b) The current CPU features doc[2] for Arm doesn't mention "host
>     passthrough" at all.  It is only implied by the last part of this
>     paragraph, from the section titled "A note about CPU models and
>     KVM"[3]:
>
>       "Named CPU models generally do not work with KVM. There are a few
>       cases that do work [...] but mostly if KVM is enabled the 'host'
>       CPU type must be used."
>
>     Related: in your reply[4] to Dan in this series, you write: "Having
>     named models is the next thing".  So named CPU models will be a
>     thing in Arm, too?  Then the above statement in the Arm
>     'cpu-features' will need updating :-)

The currently existing named models are for cpus like cortex-a57; you
can use them for KVM if you happen to run on a matching host cpu, but
they only really make sense for use with tcg.

I currently think that an Armv9.0 or whatever model would make the most
sense, but that's certainly still up for discussion :)



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-28 16:16         ` Peter Maydell
@ 2024-10-28 16:25           ` Cornelia Huck
  2024-10-28 16:35           ` Daniel P. Berrangé
  1 sibling, 0 replies; 72+ messages in thread
From: Cornelia Huck @ 2024-10-28 16:25 UTC (permalink / raw)
  To: Peter Maydell, Daniel P. Berrangé
  Cc: Eric Auger, eric.auger.pro, qemu-devel, qemu-arm, kvmarm,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

On Mon, Oct 28 2024, Peter Maydell <peter.maydell@linaro.org> wrote:

> On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
>> On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
>> > On 10/25/24 15:06, Daniel P. Berrangé wrote:
>> > > Also, is this naming convention really the same one that users
>> > > will see when they look at /proc/cpuinfo to view features ? It
>> > No it is not. I do agree that the custom cpu model is very low level. It
>> > is very well suited to test all series turning ID regs as writable but
>> > this would require an extra layer that adapts /proc/cpuinfo feature
>> > level to this regid/field abstraction.
>> >
>> > In /cpu/proc you will see somethink like:
>> >  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
>> > asimdhp cpuid asimdrdm lrcpc dcpop asimddp
>>
>> Right, IMHO, this is the terminology that QEMU must use in user
>> facing APIs.
>
> /proc/cpuinfo's naming is rather weird for historical
> reasons (for instance there is only one FEAT_FP16 feature
> but cpuinfo lists "fphp" and "asimdhp" separately).
> Currently QEMU only has to care about cpuinfo name tags
> in linux-user/elfload.c where there's a bunch of data
> structures for "what hwcaps do we need to advertise
> given what the CPU has?". I would definitely prefer it if
> we could use architectural feature names...
>
> On other architectures do we do anything to forbid
> invalid combinations? For Arm there are architectural
> rules about feature X requiring features Y and Z.
> Are we going to just let the user create a CPU that
> the guest OS will barf on if they want to? (The
> user-experience for that is potentially not very nice,
> because something like "-cpu cortex-a57,+sve" seems like
> something you might want to do but isn't actually valid;
> even listing the direct required dependency of FEAT_SVE
> like "-cpu cortex-a57,+sve,+fp16" isn't sufficient
> because SVE is optional-from-v8.2 and so a guest could
> in theory assume the presence of anything mandatory in
> v8.1 and v8.2. But even merely diagnosing invalid
> combinations is a huge pain, and automagically pulling
> in every mandatory implicit or explicit dependency
> seems like it might be surprising to users, as well as
> being annoying to implement. Currently we sidestep
> all of these problems by (a) only allowing the command
> line to disable a feature, not to enable it where it
> didn't previously exist and (b) mostly not providing
> command line flags for individual features...)

I think s390 does some dependency checking on features, and also rejects
features that are "too new".



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-28 16:09           ` Daniel P. Berrangé
@ 2024-10-28 16:29             ` Cornelia Huck
  2024-10-31 12:24               ` Kashyap Chamarthy
  2024-11-04 14:45             ` Eric Auger
  1 sibling, 1 reply; 72+ messages in thread
From: Cornelia Huck @ 2024-10-28 16:29 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Eric Auger, eric.auger.pro, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Mon, Oct 28 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:

> On Mon, Oct 28, 2024 at 05:05:44PM +0100, Cornelia Huck wrote:
>> On Fri, Oct 25 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:
>> 
>> > On Fri, Oct 25, 2024 at 03:28:35PM +0200, Eric Auger wrote:
>> >> Hi Daniel,
>> >> 
>> >> On 10/25/24 15:13, Daniel P. Berrangé wrote:
>> >> > On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
>> >> >> From: Cornelia Huck <cohuck@redhat.com>
>> >> >>
>> >> >> Add some documentation for the custom model.
>> >> >>
>> >> >> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>> >> >> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
>> >> >> ---
>> >> >>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
>> >> >>  1 file changed, 47 insertions(+), 8 deletions(-)
>> >> >
>> >> >> @@ -167,6 +196,16 @@ disabling many SVE vector lengths would be quite verbose, the ``sve<N>`` CPU
>> >> >>  properties have special semantics (see "SVE CPU Property Parsing
>> >> >>  Semantics").
>> >> >>  
>> >> >> +The ``custom`` CPU model needs to be configured via individual ID register
>> >> >> +field properties, for example::
>> >> >> +
>> >> >> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
>> >> >> +
>> >> >> +This forces ID_AA64ISAR0_EL1 DP field to 0.
>> >> > What is the "baseline" featureset implied by 'custom' ?
>> >> there is no baseline at the moment. By default this is a host
>> >> passthrough model.
>> >
>> > Why do we need to create "custom" at all, as opposed to just letting
>> > users toggle features on "-cpu host" ? 
>> 
>> We could consolidate that to the current "host" model, once we figure
>> out how to handle the currently already existing properties. Models
>> based on the different architecture extensions would probably be more
>> useable in the long run; maybe "custom" has a place for testing.
>
> If you can set the features against "host", then any testing could
> be done with "host" surely, making 'custom' pointless ?

We might differentiate between "do some consistency checks" and "allow
a completely weird wolpertinger"; if we agree that we don't need it,
then we surely could drop it again.



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-28 16:16         ` Peter Maydell
  2024-10-28 16:25           ` Cornelia Huck
@ 2024-10-28 16:35           ` Daniel P. Berrangé
  2024-10-28 16:48             ` Peter Maydell
  1 sibling, 1 reply; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-10-28 16:35 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Eric Auger, eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

On Mon, Oct 28, 2024 at 04:16:31PM +0000, Peter Maydell wrote:
> On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
> > On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
> > > On 10/25/24 15:06, Daniel P. Berrangé wrote:
> > > > Also, is this naming convention really the same one that users
> > > > will see when they look at /proc/cpuinfo to view features ? It
> > > No it is not. I do agree that the custom cpu model is very low level. It
> > > is very well suited to test all series turning ID regs as writable but
> > > this would require an extra layer that adapts /proc/cpuinfo feature
> > > level to this regid/field abstraction.
> > >
> > > In /cpu/proc you will see somethink like:
> > >  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
> > > asimdhp cpuid asimdrdm lrcpc dcpop asimddp
> >
> > Right, IMHO, this is the terminology that QEMU must use in user
> > facing APIs.
> 
> /proc/cpuinfo's naming is rather weird for historical
> reasons (for instance there is only one FEAT_FP16 feature
> but cpuinfo lists "fphp" and "asimdhp" separately).

There's plenty of wierd history in x86 too. In this
case I might suggest just picking one of the two
common names, and ignoring the other.

If we really wanted to, we could alias the 2nd name
to the first, but its likely not worth the bother.

> Currently QEMU only has to care about cpuinfo name tags
> in linux-user/elfload.c where there's a bunch of data
> structures for "what hwcaps do we need to advertise
> given what the CPU has?". I would definitely prefer it if
> we could use architectural feature names...
> 
> On other architectures do we do anything to forbid
> invalid combinations? For Arm there are architectural
> rules about feature X requiring features Y and Z.
> Are we going to just let the user create a CPU that
> the guest OS will barf on if they want to? (The
> user-experience for that is potentially not very nice,
> because something like "-cpu cortex-a57,+sve" seems like
> something you might want to do but isn't actually valid;
> even listing the direct required dependency of FEAT_SVE
> like "-cpu cortex-a57,+sve,+fp16" isn't sufficient
> because SVE is optional-from-v8.2 and so a guest could
> in theory assume the presence of anything mandatory in
> v8.1 and v8.2. But even merely diagnosing invalid
> combinations is a huge pain, and automagically pulling
> in every mandatory implicit or explicit dependency
> seems like it might be surprising to users, as well as
> being annoying to implement. Currently we sidestep
> all of these problems by (a) only allowing the command
> line to disable a feature, not to enable it where it
> didn't previously exist and (b) mostly not providing
> command line flags for individual features...)

AFAICT, in x86 world, there's no generally documented dependancies
between features. I imagine there might be deps mentioned in an
adhoc basis in docs/specs.  There are certainly implicit deps though
where apps check for X, and blindly assume it means Y+Z also exist.

In the QEMU  & libvirt world though, there's no deps. This is generally
why we discourage apps/users from trying to enable arbitrarily many
features. People should stick to the named CPU models, and just use
feature enablement as an exception.

Enabling individual features *is* certainly a critically important
benefit though, even with the risks from implicit undocumented
dependencies.

Most notably, it has been used to turn on fixes for hardware CVEs,
where microcode introduces a new named feature. Your named CPU
model may not be updated, but as long as QEMU knows the feature
name, you can turn it on.

Overall, while it would be desirable to have a way to express
feature dependencies, I wouldn't call that a blocker for enabling
the ability to turn features on & off.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model
  2024-10-28 16:20   ` Cornelia Huck
@ 2024-10-28 16:44     ` Peter Maydell
  0 siblings, 0 replies; 72+ messages in thread
From: Peter Maydell @ 2024-10-28 16:44 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Kashyap Chamarthy, Eric Auger, eric.auger.pro, qemu-devel,
	qemu-arm, kvmarm, richard.henderson, alex.bennee, maz,
	oliver.upton, sebott, shameerali.kolothum.thodi, armbru, berrange,
	abologna, jdenemar, shahuang, mark.rutland, philmd, pbonzini

On Mon, 28 Oct 2024 at 16:20, Cornelia Huck <cohuck@redhat.com> wrote:
> On Fri, Oct 25 2024, Kashyap Chamarthy <kchamart@redhat.com> wrote:
> > (b) The current CPU features doc[2] for Arm doesn't mention "host
> >     passthrough" at all.  It is only implied by the last part of this
> >     paragraph, from the section titled "A note about CPU models and
> >     KVM"[3]:
> >
> >       "Named CPU models generally do not work with KVM. There are a few
> >       cases that do work [...] but mostly if KVM is enabled the 'host'
> >       CPU type must be used."
> >
> >     Related: in your reply[4] to Dan in this series, you write: "Having
> >     named models is the next thing".  So named CPU models will be a
> >     thing in Arm, too?  Then the above statement in the Arm
> >     'cpu-features' will need updating :-)
>
> The currently existing named models are for cpus like cortex-a57; you
> can use them for KVM if you happen to run on a matching host cpu, but
> they only really make sense for use with tcg.

Note that those are a relic of an old and quickly abandoned
design direction in KVM for Arm, where the idea was that
userspace would specify the target CPU via a KVM_ARM_TARGET_*
constant (initially only permitted on the matching host CPU
but with some vague idea that eventually KVM would emulate
the specified CPU type on different host CPUs also)
On the QEMU side we feed the KVM_ARM_TARGET_* through for the two
CPU models we support in TCG which also have a KVM_ARM_TARGET_*
constant, which is to say Cortex-A57 and Cortex-A53. But none
of the other named CPU models QEMU supports for TCG have that
kind of constant.

Presumably now that KVM supports "pass the guest ID regs
that don't match the host" we would want to support our
existing TCG-modelled named CPU types (for which we
already know the ID register values, for TCG) by telling
the kernel what the ID register values are.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-28 16:35           ` Daniel P. Berrangé
@ 2024-10-28 16:48             ` Peter Maydell
  2024-10-28 16:56               ` Oliver Upton
  2024-10-28 17:04               ` Daniel P. Berrangé
  0 siblings, 2 replies; 72+ messages in thread
From: Peter Maydell @ 2024-10-28 16:48 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Eric Auger, eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

On Mon, 28 Oct 2024 at 16:35, Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> On Mon, Oct 28, 2024 at 04:16:31PM +0000, Peter Maydell wrote:
> > On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
> > > On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
> > > > On 10/25/24 15:06, Daniel P. Berrangé wrote:
> > > > > Also, is this naming convention really the same one that users
> > > > > will see when they look at /proc/cpuinfo to view features ? It
> > > > No it is not. I do agree that the custom cpu model is very low level. It
> > > > is very well suited to test all series turning ID regs as writable but
> > > > this would require an extra layer that adapts /proc/cpuinfo feature
> > > > level to this regid/field abstraction.
> > > >
> > > > In /cpu/proc you will see somethink like:
> > > >  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
> > > > asimdhp cpuid asimdrdm lrcpc dcpop asimddp
> > >
> > > Right, IMHO, this is the terminology that QEMU must use in user
> > > facing APIs.
> >
> > /proc/cpuinfo's naming is rather weird for historical
> > reasons (for instance there is only one FEAT_FP16 feature
> > but cpuinfo lists "fphp" and "asimdhp" separately).
>
> There's plenty of wierd history in x86 too. In this
> case I might suggest just picking one of the two
> common names, and ignoring the other.
>
> If we really wanted to, we could alias the 2nd name
> to the first, but its likely not worth the bother.

Or we could use the standard set of architectural
feature names, and not have the problem at all, and not
have to document what we mean by our nonstandard names.
(cpuinfo names do actually mostly line up with the
standard names, just not 100%. Similarly gcc/clang command
line options are mostly the architectural feature name.)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-28 16:48             ` Peter Maydell
@ 2024-10-28 16:56               ` Oliver Upton
  2024-10-30 16:15                 ` Cornelia Huck
  2024-11-04 17:09                 ` Eric Auger
  2024-10-28 17:04               ` Daniel P. Berrangé
  1 sibling, 2 replies; 72+ messages in thread
From: Oliver Upton @ 2024-10-28 16:56 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Daniel P. Berrangé, Eric Auger, eric.auger.pro, cohuck,
	qemu-devel, qemu-arm, kvmarm, richard.henderson, alex.bennee, maz,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Mon, Oct 28, 2024 at 04:48:18PM +0000, Peter Maydell wrote:
> On Mon, 28 Oct 2024 at 16:35, Daniel P. Berrangé <berrange@redhat.com> wrote:
> >
> > On Mon, Oct 28, 2024 at 04:16:31PM +0000, Peter Maydell wrote:
> > > On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
> > > > On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
> > > > > On 10/25/24 15:06, Daniel P. Berrangé wrote:
> > > > > > Also, is this naming convention really the same one that users
> > > > > > will see when they look at /proc/cpuinfo to view features ? It
> > > > > No it is not. I do agree that the custom cpu model is very low level. It
> > > > > is very well suited to test all series turning ID regs as writable but
> > > > > this would require an extra layer that adapts /proc/cpuinfo feature
> > > > > level to this regid/field abstraction.
> > > > >
> > > > > In /cpu/proc you will see somethink like:
> > > > >  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
> > > > > asimdhp cpuid asimdrdm lrcpc dcpop asimddp
> > > >
> > > > Right, IMHO, this is the terminology that QEMU must use in user
> > > > facing APIs.
> > >
> > > /proc/cpuinfo's naming is rather weird for historical
> > > reasons (for instance there is only one FEAT_FP16 feature
> > > but cpuinfo lists "fphp" and "asimdhp" separately).
> >
> > There's plenty of wierd history in x86 too. In this
> > case I might suggest just picking one of the two
> > common names, and ignoring the other.
> >
> > If we really wanted to, we could alias the 2nd name
> > to the first, but its likely not worth the bother.
> 
> Or we could use the standard set of architectural
> feature names, and not have the problem at all, and not
> have to document what we mean by our nonstandard names.

+1

There's existing documentation [*] for the standard feature names, which
provides:

 - A short description of what the feature does
 - Any dependencies a particular feature has (e.g.FEAT_VHE implies
   FEAT_LSE, FEAT_Debugv8p1, and FEAT_AA64EL2)
 - The register fields/values that are used to discover the feature.

This seems like the most user-friendly option...

[*]: https://developer.arm.com/documentation/109697/2024_09

-- 
Thanks,
Oliver


^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-28 16:48             ` Peter Maydell
  2024-10-28 16:56               ` Oliver Upton
@ 2024-10-28 17:04               ` Daniel P. Berrangé
  2024-11-04 14:27                 ` Eric Auger
  1 sibling, 1 reply; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-10-28 17:04 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Eric Auger, eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

On Mon, Oct 28, 2024 at 04:48:18PM +0000, Peter Maydell wrote:
> On Mon, 28 Oct 2024 at 16:35, Daniel P. Berrangé <berrange@redhat.com> wrote:
> >
> > On Mon, Oct 28, 2024 at 04:16:31PM +0000, Peter Maydell wrote:
> > > On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
> > > > On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
> > > > > On 10/25/24 15:06, Daniel P. Berrangé wrote:
> > > > > > Also, is this naming convention really the same one that users
> > > > > > will see when they look at /proc/cpuinfo to view features ? It
> > > > > No it is not. I do agree that the custom cpu model is very low level. It
> > > > > is very well suited to test all series turning ID regs as writable but
> > > > > this would require an extra layer that adapts /proc/cpuinfo feature
> > > > > level to this regid/field abstraction.
> > > > >
> > > > > In /cpu/proc you will see somethink like:
> > > > >  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
> > > > > asimdhp cpuid asimdrdm lrcpc dcpop asimddp
> > > >
> > > > Right, IMHO, this is the terminology that QEMU must use in user
> > > > facing APIs.
> > >
> > > /proc/cpuinfo's naming is rather weird for historical
> > > reasons (for instance there is only one FEAT_FP16 feature
> > > but cpuinfo lists "fphp" and "asimdhp" separately).
> >
> > There's plenty of wierd history in x86 too. In this
> > case I might suggest just picking one of the two
> > common names, and ignoring the other.
> >
> > If we really wanted to, we could alias the 2nd name
> > to the first, but its likely not worth the bother.
> 
> Or we could use the standard set of architectural
> feature names, and not have the problem at all, and not
> have to document what we mean by our nonstandard names.
> (cpuinfo names do actually mostly line up with the
> standard names, just not 100%. Similarly gcc/clang command
> line options are mostly the architectural feature name.)

Ah, right, yes. Sorry I mis-understood you originally to be suggesting
the same low level names as this patch.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-25 10:17 ` [RFC 21/21] arm/cpu-features: Document custom vcpu model Eric Auger
  2024-10-25 13:13   ` Daniel P. Berrangé
@ 2024-10-28 21:17   ` Kashyap Chamarthy
  2024-11-04 15:34     ` Eric Auger
  1 sibling, 1 reply; 72+ messages in thread
From: Kashyap Chamarthy @ 2024-10-28 21:17 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar, shahuang, mark.rutland, philmd, pbonzini

On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
> From: Cornelia Huck <cohuck@redhat.com>
> 
> Add some documentation for the custom model.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> ---
>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
>  1 file changed, 47 insertions(+), 8 deletions(-)
> 
> diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
> index a5fb929243..962a2c6c26 100644
> --- a/docs/system/arm/cpu-features.rst
> +++ b/docs/system/arm/cpu-features.rst
> @@ -2,7 +2,10 @@ Arm CPU Features

[...]

> +Using the ``host`` type means the guest is provided all the same CPU
> +features as the host CPU type has.  And, for this reason, the ``host``
> +CPU type should enable all CPU features that the host has by default.
> +
> +In case some features need to be hidden to the guest, ``custom`` model
> +shall be used instead. This is especially useful for migration purpose.
> +
> +The ``custom`` CPU model generally is the better choice if you want more
> +flexibility or stability across different machines or with different kernel
> +versions. 

Does "more flexibility or stability across different machines" also
imply "live migration compatiblity across host CPUs"?

> However, even the ``custom`` CPU model will not allow configuring
> +an arbitrary set of features; the ID registers must describe a subset of the
> +host's features, and all differences to the host's configuration must actually
> +be supported by the kernel to be deconfigured.

[...]

> +The ``custom`` CPU model needs to be configured via individual ID register
> +field properties, for example::
> +
> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0

If possible, it would be really helpful (and user-friendly) to be able
to specify the CPU feature names as you see under /proc/cpuinfo, and be
able to turn the flags on or off:
    
        -M virt -cpu franken,rndr=on,ts=on,fhm=off

(... instead of specifying long system register IDs that groups together
a bunch of CPU features.  If I understand it correctly, the register
"ID_AA64ISAR0_EL1" maps to a set of visible features listed here:
https://docs.kernel.org/arch/arm64/cpu-feature-registers.html)


Next, I prefix the below by noting that I wrote it before seeing
Cornelia's reply that the name "custom" is not set in stone:
https://lists.nongnu.org/archive/html/qemu-arm/2024-10/msg00987.html.

I wonder if the word "custom" is starting to get overloaded; on x86:

  - Libvirt itself uses the term "custom" this way, to quote its
    documentation[1] for the 'custom' XML attribute:

      custom
    
      In this mode, the 'cpu' element describes the CPU that should be
      presented to the guest. This is the default when no 'mode'
      attribute is specified. This mode makes it so that a persistent
      guest will see the same hardware no matter what host the guest is
      booted on.

  - Some management tools also follow libvirt and use the term "custom"
    to refer to one of two things, (a) a specific named CPU model that
    libvirt and QEMU recognize, e.g. "Cascadelake-Server"; or (b) a
    named CPU model + extra CPU flags, e.g. this is how OpenStack
    uses[2] "custom" to configure CPU models, and flags that can be
    enabled or disabled via "+" or "-":

      [libvirt]
      cpu_mode = custom
      cpu_model = IvyBridge-IBRS
      cpu_model_extra_flags="ss,+vmx,-pcid [...]"

    (Note the "cpu_mode" there: it is referring to the three possible
    modes that libvirt and QEMU support today: 'host-passthrough',
    'host-model', and named CPU models via "custom".)

    The above config translates to this QEMU command-line:

        -cpu IvyBridge-IBRS,ss=on,vmx=on,pcid=off [...]

Now if QEMU introduces "custom", it is likely to create some confusion.
But luckily, as referenced above, it is open to change. :)

    * * *

FWIW, I agree with Dan here[3] that it would cause less future pain if
Arm's named CPU models also decides on a "baseline that matches some
corresponding real world silicon".  I've experienced plenty of such
debugging pain in x86-land from years of troubleshooting live migration
bugs involving CPU model (in)compatibility.  (Often, with help from
DanPB and Jiri Denemark).

[1] https://docs.openstack.org/nova/latest/admin/cpu-models.html#cpu-modes
[2] https://libvirt.org/formatdomain.html#cpu-model-and-topology
[3] https://lists.nongnu.org/archive/html/qemu-arm/2024-10/msg00888.html
    — [RFC 21/21] arm/cpu-features: Document custom vcpu model

[...]

-- 
/kashyap



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-28 16:56               ` Oliver Upton
@ 2024-10-30 16:15                 ` Cornelia Huck
  2024-10-30 16:27                   ` Daniel P. Berrangé
  2024-11-04 17:09                 ` Eric Auger
  1 sibling, 1 reply; 72+ messages in thread
From: Cornelia Huck @ 2024-10-30 16:15 UTC (permalink / raw)
  To: Oliver Upton, Peter Maydell
  Cc: Daniel P. Berrangé, Eric Auger, eric.auger.pro, qemu-devel,
	qemu-arm, kvmarm, richard.henderson, alex.bennee, maz, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

On Mon, Oct 28 2024, Oliver Upton <oliver.upton@linux.dev> wrote:

> On Mon, Oct 28, 2024 at 04:48:18PM +0000, Peter Maydell wrote:
>> On Mon, 28 Oct 2024 at 16:35, Daniel P. Berrangé <berrange@redhat.com> wrote:
>> >
>> > On Mon, Oct 28, 2024 at 04:16:31PM +0000, Peter Maydell wrote:
>> > > On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
>> > > > On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
>> > > > > On 10/25/24 15:06, Daniel P. Berrangé wrote:
>> > > > > > Also, is this naming convention really the same one that users
>> > > > > > will see when they look at /proc/cpuinfo to view features ? It
>> > > > > No it is not. I do agree that the custom cpu model is very low level. It
>> > > > > is very well suited to test all series turning ID regs as writable but
>> > > > > this would require an extra layer that adapts /proc/cpuinfo feature
>> > > > > level to this regid/field abstraction.
>> > > > >
>> > > > > In /cpu/proc you will see somethink like:
>> > > > >  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
>> > > > > asimdhp cpuid asimdrdm lrcpc dcpop asimddp
>> > > >
>> > > > Right, IMHO, this is the terminology that QEMU must use in user
>> > > > facing APIs.
>> > >
>> > > /proc/cpuinfo's naming is rather weird for historical
>> > > reasons (for instance there is only one FEAT_FP16 feature
>> > > but cpuinfo lists "fphp" and "asimdhp" separately).
>> >
>> > There's plenty of wierd history in x86 too. In this
>> > case I might suggest just picking one of the two
>> > common names, and ignoring the other.
>> >
>> > If we really wanted to, we could alias the 2nd name
>> > to the first, but its likely not worth the bother.
>> 
>> Or we could use the standard set of architectural
>> feature names, and not have the problem at all, and not
>> have to document what we mean by our nonstandard names.
>
> +1
>
> There's existing documentation [*] for the standard feature names, which
> provides:
>
>  - A short description of what the feature does
>  - Any dependencies a particular feature has (e.g.FEAT_VHE implies
>    FEAT_LSE, FEAT_Debugv8p1, and FEAT_AA64EL2)
>  - The register fields/values that are used to discover the feature.
>
> This seems like the most user-friendly option...
>
> [*]: https://developer.arm.com/documentation/109697/2024_09

FEAT_XXX sounds good, would be a different approach than this series
obviously, since the user resp. upper software layers would operate on a
per-feature basis, and QEMU would translate to and from registers.

I'm wondering about the amount of translation that would be needed, and
what information would be best exposed via QEMU, given that a feature
may or may not be toggable not only because of what the Arm revision
specifies, but what registers the host kernel allows to be written.

I.e. if we have two cpus that differ in whether FEAT_FOO is provided,
would it make sense to have an extra QMP command so that you can find
out whether FEAT_FOO can be switched off, with QEMU translating from the
set of writable id registers to the set of features that can be changed?



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-30 16:15                 ` Cornelia Huck
@ 2024-10-30 16:27                   ` Daniel P. Berrangé
  0 siblings, 0 replies; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-10-30 16:27 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Oliver Upton, Peter Maydell, Eric Auger, eric.auger.pro,
	qemu-devel, qemu-arm, kvmarm, richard.henderson, alex.bennee, maz,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Wed, Oct 30, 2024 at 05:15:05PM +0100, Cornelia Huck wrote:
> On Mon, Oct 28 2024, Oliver Upton <oliver.upton@linux.dev> wrote:
> 
> > On Mon, Oct 28, 2024 at 04:48:18PM +0000, Peter Maydell wrote:
> >> On Mon, 28 Oct 2024 at 16:35, Daniel P. Berrangé <berrange@redhat.com> wrote:
> >> >
> >> > On Mon, Oct 28, 2024 at 04:16:31PM +0000, Peter Maydell wrote:
> >> > > On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
> >> > > > On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
> >> > > > > On 10/25/24 15:06, Daniel P. Berrangé wrote:
> >> > > > > > Also, is this naming convention really the same one that users
> >> > > > > > will see when they look at /proc/cpuinfo to view features ? It
> >> > > > > No it is not. I do agree that the custom cpu model is very low level. It
> >> > > > > is very well suited to test all series turning ID regs as writable but
> >> > > > > this would require an extra layer that adapts /proc/cpuinfo feature
> >> > > > > level to this regid/field abstraction.
> >> > > > >
> >> > > > > In /cpu/proc you will see somethink like:
> >> > > > >  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
> >> > > > > asimdhp cpuid asimdrdm lrcpc dcpop asimddp
> >> > > >
> >> > > > Right, IMHO, this is the terminology that QEMU must use in user
> >> > > > facing APIs.
> >> > >
> >> > > /proc/cpuinfo's naming is rather weird for historical
> >> > > reasons (for instance there is only one FEAT_FP16 feature
> >> > > but cpuinfo lists "fphp" and "asimdhp" separately).
> >> >
> >> > There's plenty of wierd history in x86 too. In this
> >> > case I might suggest just picking one of the two
> >> > common names, and ignoring the other.
> >> >
> >> > If we really wanted to, we could alias the 2nd name
> >> > to the first, but its likely not worth the bother.
> >> 
> >> Or we could use the standard set of architectural
> >> feature names, and not have the problem at all, and not
> >> have to document what we mean by our nonstandard names.
> >
> > +1
> >
> > There's existing documentation [*] for the standard feature names, which
> > provides:
> >
> >  - A short description of what the feature does
> >  - Any dependencies a particular feature has (e.g.FEAT_VHE implies
> >    FEAT_LSE, FEAT_Debugv8p1, and FEAT_AA64EL2)
> >  - The register fields/values that are used to discover the feature.
> >
> > This seems like the most user-friendly option...
> >
> > [*]: https://developer.arm.com/documentation/109697/2024_09
> 
> FEAT_XXX sounds good, would be a different approach than this series
> obviously, since the user resp. upper software layers would operate on a
> per-feature basis, and QEMU would translate to and from registers.
> 
> I'm wondering about the amount of translation that would be needed, and
> what information would be best exposed via QEMU, given that a feature
> may or may not be toggable not only because of what the Arm revision
> specifies, but what registers the host kernel allows to be written.
> 
> I.e. if we have two cpus that differ in whether FEAT_FOO is provided,
> would it make sense to have an extra QMP command so that you can find
> out whether FEAT_FOO can be switched off, with QEMU translating from the
> set of writable id registers to the set of features that can be changed?

If there are restrictions on what features can be turned off, then yes,
we should add that in QMP, as x86 doesn't have such a restriction
currently.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-28 16:29             ` Cornelia Huck
@ 2024-10-31 12:24               ` Kashyap Chamarthy
  2024-10-31 12:59                 ` Peter Maydell
  0 siblings, 1 reply; 72+ messages in thread
From: Kashyap Chamarthy @ 2024-10-31 12:24 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Daniel P. Berrangé, Eric Auger, eric.auger.pro, qemu-devel,
	qemu-arm, kvmarm, peter.maydell, richard.henderson, alex.bennee,
	maz, oliver.upton, sebott, shameerali.kolothum.thodi, armbru,
	abologna, jdenemar, shahuang, mark.rutland, philmd, pbonzini

On Mon, Oct 28, 2024 at 05:29:11PM +0100, Cornelia Huck wrote:
> On Mon, Oct 28 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:

[...]

> >> We could consolidate that to the current "host" model, once we figure
> >> out how to handle the currently already existing properties. Models
> >> based on the different architecture extensions would probably be more
> >> useable in the long run; maybe "custom" has a place for testing.
> >
> > If you can set the features against "host", then any testing could
> > be done with "host" surely, making 'custom' pointless ?
> 
> We might differentiate between "do some consistency checks" and "allow
> a completely weird wolpertinger"; if we agree that we don't need it,
> then we surely could drop it again.

Yeah, FWIW, I agree that it's best to drop "custom" if all the
meaningful tests can be handled by being able to add/remove CPU flags
from `-cpu host`.


Related: I don't see any mention of `-cpu max` here.  Is it not
relevant?  It is currently defined as: "enables all features supported
by the accelerator in the current host".  Does it make sense for `max`
to allow disabling features?  Or is the idea that, why would you choose
`-cpu max` if you want to disable features?  In that case, go with
either:

    -cpu host,feat1=off

Or:

    -cpu some_future_named_model,$feat1=off

?

-- 
/kashyap



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-31 12:24               ` Kashyap Chamarthy
@ 2024-10-31 12:59                 ` Peter Maydell
  0 siblings, 0 replies; 72+ messages in thread
From: Peter Maydell @ 2024-10-31 12:59 UTC (permalink / raw)
  To: Kashyap Chamarthy
  Cc: Cornelia Huck, Daniel P. Berrangé, Eric Auger,
	eric.auger.pro, qemu-devel, qemu-arm, kvmarm, richard.henderson,
	alex.bennee, maz, oliver.upton, sebott, shameerali.kolothum.thodi,
	armbru, abologna, jdenemar, shahuang, mark.rutland, philmd,
	pbonzini

On Thu, 31 Oct 2024 at 12:24, Kashyap Chamarthy <kchamart@redhat.com> wrote:
>
> On Mon, Oct 28, 2024 at 05:29:11PM +0100, Cornelia Huck wrote:
> > On Mon, Oct 28 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> [...]
>
> > >> We could consolidate that to the current "host" model, once we figure
> > >> out how to handle the currently already existing properties. Models
> > >> based on the different architecture extensions would probably be more
> > >> useable in the long run; maybe "custom" has a place for testing.
> > >
> > > If you can set the features against "host", then any testing could
> > > be done with "host" surely, making 'custom' pointless ?
> >
> > We might differentiate between "do some consistency checks" and "allow
> > a completely weird wolpertinger"; if we agree that we don't need it,
> > then we surely could drop it again.
>
> Yeah, FWIW, I agree that it's best to drop "custom" if all the
> meaningful tests can be handled by being able to add/remove CPU flags
> from `-cpu host`.
>
>
> Related: I don't see any mention of `-cpu max` here.  Is it not
> relevant?  It is currently defined as: "enables all features supported
> by the accelerator in the current host".  Does it make sense for `max`
> to allow disabling features?  Or is the idea that, why would you choose
> `-cpu max` if you want to disable features?

Ideally, disabling features would work with any '-cpu' option
(including our existing TCG CPUs). (The main reason for 'max'
is as an option that works whether you're using TCG or KVM.)

-- PMM


^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 14/21] arm/cpu: Add sysreg generation scripts
  2024-10-25 17:05   ` Marc Zyngier
@ 2024-11-04 13:33     ` Eric Auger
  0 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-11-04 13:33 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar, shahuang, mark.rutland, philmd, pbonzini

Hi Marc,
On 10/25/24 19:05, Marc Zyngier wrote:
> On Fri, 25 Oct 2024 11:17:33 +0100,
> Eric Auger <eric.auger@redhat.com> wrote:
>> Introduce scripts that automate the generation of system register
>> definitions from a given linux source tree arch/arm64/tools/sysreg.
>>
>> Invocation of
>> ./update-aarch64-sysreg-code.sh $PATH_TO_LINUX_SOURCE_TREE
>> in scripts directory do generate 2 qemu files:
>> - target/arm/cpu-sysreg-properties.c
>> - target/arm/cpu-sysregs.h
>>
>> cpu-sysregs.h creates defined for all system registers.
>> However cpu-sysreg-properties.c only cares about feature ID registers.
>>
>> update-aarch64-sysreg-code.sh calls two awk scripts.
>> gen-cpu-sysreg-properties.awk is inherited from kernel
>> arch/arm64/tools/gen-sysreg.awk. All credits to Mark Rutland
>> the original author of this script.
Sorry for the delay. I was out of the office last week.
> You really want to be careful with this. Both the script and the
> source file describing the registers are submitted to regular outburst
> of churn (I'm currently sitting on such a series). You really have to
> be prepared to see things breaking on each import.
OK thank you for the warning. It is now understood we cannot fully rely
on them and checks should be done on each run.
>
> That file has also been known to contain annoying mistakes, as it is
> all written by hand.
>
> Ideally, this would be directly generated from the ARM XML, which is a
> public set of files. However, the license attached to this package
> strictly prohibits its use in QEMU (or anywhere else). One day...
;-)

Eric
>
> Thanks,
>
> 	M.
>



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-28 17:04               ` Daniel P. Berrangé
@ 2024-11-04 14:27                 ` Eric Auger
  2024-11-11 14:29                   ` Cornelia Huck
  0 siblings, 1 reply; 72+ messages in thread
From: Eric Auger @ 2024-11-04 14:27 UTC (permalink / raw)
  To: Daniel P. Berrangé, Peter Maydell
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

Hi Daniel,

On 10/28/24 18:04, Daniel P. Berrangé wrote:
> On Mon, Oct 28, 2024 at 04:48:18PM +0000, Peter Maydell wrote:
>> On Mon, 28 Oct 2024 at 16:35, Daniel P. Berrangé <berrange@redhat.com> wrote:
>>> On Mon, Oct 28, 2024 at 04:16:31PM +0000, Peter Maydell wrote:
>>>> On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>> On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
>>>>>> On 10/25/24 15:06, Daniel P. Berrangé wrote:
>>>>>>> Also, is this naming convention really the same one that users
>>>>>>> will see when they look at /proc/cpuinfo to view features ? It
>>>>>> No it is not. I do agree that the custom cpu model is very low level. It
>>>>>> is very well suited to test all series turning ID regs as writable but
>>>>>> this would require an extra layer that adapts /proc/cpuinfo feature
>>>>>> level to this regid/field abstraction.
>>>>>>
>>>>>> In /cpu/proc you will see somethink like:
>>>>>>  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
>>>>>> asimdhp cpuid asimdrdm lrcpc dcpop asimddp
>>>>> Right, IMHO, this is the terminology that QEMU must use in user
>>>>> facing APIs.
>>>> /proc/cpuinfo's naming is rather weird for historical
>>>> reasons (for instance there is only one FEAT_FP16 feature
>>>> but cpuinfo lists "fphp" and "asimdhp" separately).
>>> There's plenty of wierd history in x86 too. In this
>>> case I might suggest just picking one of the two
>>> common names, and ignoring the other.
>>>
>>> If we really wanted to, we could alias the 2nd name
>>> to the first, but its likely not worth the bother.
>> Or we could use the standard set of architectural
>> feature names, and not have the problem at all, and not
>> have to document what we mean by our nonstandard names.
>> (cpuinfo names do actually mostly line up with the
>> standard names, just not 100%. Similarly gcc/clang command
>> line options are mostly the architectural feature name.)
> Ah, right, yes. Sorry I mis-understood you originally to be suggesting
> the same low level names as this patch.
If my understanding is correct, Peter suggested to rely on the
terminology used in

https://developer.arm.com/documentation/109697/2024_09

the doc pointed to by Oliver.

So I think the next step is to understand how those "high level" features do map onto low level ID register field values. I think a high level feature can map onto separate fields in separate ID regs. This may not be the most common case though. 

Thanks

Eric

>
> With regards,
> Daniel



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-28 16:09           ` Daniel P. Berrangé
  2024-10-28 16:29             ` Cornelia Huck
@ 2024-11-04 14:45             ` Eric Auger
  2024-11-04 14:55               ` Daniel P. Berrangé
  1 sibling, 1 reply; 72+ messages in thread
From: Eric Auger @ 2024-11-04 14:45 UTC (permalink / raw)
  To: Daniel P. Berrangé, Cornelia Huck
  Cc: eric.auger.pro, qemu-devel, qemu-arm, kvmarm, peter.maydell,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

Hi

On 10/28/24 17:09, Daniel P. Berrangé wrote:
> On Mon, Oct 28, 2024 at 05:05:44PM +0100, Cornelia Huck wrote:
>> On Fri, Oct 25 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:
>>
>>> On Fri, Oct 25, 2024 at 03:28:35PM +0200, Eric Auger wrote:
>>>> Hi Daniel,
>>>>
>>>> On 10/25/24 15:13, Daniel P. Berrangé wrote:
>>>>> On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
>>>>>> From: Cornelia Huck <cohuck@redhat.com>
>>>>>>
>>>>>> Add some documentation for the custom model.
>>>>>>
>>>>>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>>>>> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
>>>>>> ---
>>>>>>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
>>>>>>  1 file changed, 47 insertions(+), 8 deletions(-)
>>>>>> @@ -167,6 +196,16 @@ disabling many SVE vector lengths would be quite verbose, the ``sve<N>`` CPU
>>>>>>  properties have special semantics (see "SVE CPU Property Parsing
>>>>>>  Semantics").
>>>>>>  
>>>>>> +The ``custom`` CPU model needs to be configured via individual ID register
>>>>>> +field properties, for example::
>>>>>> +
>>>>>> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
>>>>>> +
>>>>>> +This forces ID_AA64ISAR0_EL1 DP field to 0.
>>>>> What is the "baseline" featureset implied by 'custom' ?
>>>> there is no baseline at the moment. By default this is a host
>>>> passthrough model.
>>> Why do we need to create "custom" at all, as opposed to just letting
>>> users toggle features on "-cpu host" ? 
>> We could consolidate that to the current "host" model, once we figure
>> out how to handle the currently already existing properties. Models
>> based on the different architecture extensions would probably be more
>> useable in the long run; maybe "custom" has a place for testing.
> If you can set the features against "host", then any testing could
> be done with "host" surely, making 'custom' pointless ?
Yeah I do agree that we may not need to introduce this "custom" model
bus just enhance the custom host model with the capability to tweek some
features. For instance we have the case where migration between 2 Ampere
systems fails with host model but if you tweek 1 field in CTR_EL0 it
passes. So I think in itself this modality can be useful. Same for
debug/test purpose. As mentionned in the cover letter the number of
writable ID regs continue to grow and this enhanced host model gives
flexibility to test new support and may provide enhanced debug
capabilities for migration (getting a straight understanding of which ID
reg field(s) causes the migration failure could be helpful I think)

Thanks

Eric
>
> With regards,
> Daniel



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-11-04 14:45             ` Eric Auger
@ 2024-11-04 14:55               ` Daniel P. Berrangé
  2024-11-04 15:10                 ` Cornelia Huck
  0 siblings, 1 reply; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-11-04 14:55 UTC (permalink / raw)
  To: Eric Auger
  Cc: Cornelia Huck, eric.auger.pro, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Mon, Nov 04, 2024 at 03:45:13PM +0100, Eric Auger wrote:
> Hi
> 
> On 10/28/24 17:09, Daniel P. Berrangé wrote:
> > On Mon, Oct 28, 2024 at 05:05:44PM +0100, Cornelia Huck wrote:
> >> On Fri, Oct 25 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:
> >>
> >>> On Fri, Oct 25, 2024 at 03:28:35PM +0200, Eric Auger wrote:
> >>>> Hi Daniel,
> >>>>
> >>>> On 10/25/24 15:13, Daniel P. Berrangé wrote:
> >>>>> On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
> >>>>>> From: Cornelia Huck <cohuck@redhat.com>
> >>>>>>
> >>>>>> Add some documentation for the custom model.
> >>>>>>
> >>>>>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> >>>>>> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> >>>>>> ---
> >>>>>>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
> >>>>>>  1 file changed, 47 insertions(+), 8 deletions(-)
> >>>>>> @@ -167,6 +196,16 @@ disabling many SVE vector lengths would be quite verbose, the ``sve<N>`` CPU
> >>>>>>  properties have special semantics (see "SVE CPU Property Parsing
> >>>>>>  Semantics").
> >>>>>>  
> >>>>>> +The ``custom`` CPU model needs to be configured via individual ID register
> >>>>>> +field properties, for example::
> >>>>>> +
> >>>>>> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
> >>>>>> +
> >>>>>> +This forces ID_AA64ISAR0_EL1 DP field to 0.
> >>>>> What is the "baseline" featureset implied by 'custom' ?
> >>>> there is no baseline at the moment. By default this is a host
> >>>> passthrough model.
> >>> Why do we need to create "custom" at all, as opposed to just letting
> >>> users toggle features on "-cpu host" ? 
> >> We could consolidate that to the current "host" model, once we figure
> >> out how to handle the currently already existing properties. Models
> >> based on the different architecture extensions would probably be more
> >> useable in the long run; maybe "custom" has a place for testing.
> > If you can set the features against "host", then any testing could
> > be done with "host" surely, making 'custom' pointless ?
> Yeah I do agree that we may not need to introduce this "custom" model
> bus just enhance the custom host model with the capability to tweek some
> features. For instance we have the case where migration between 2 Ampere
> systems fails with host model but if you tweek 1 field in CTR_EL0 it
> passes. So I think in itself this modality can be useful. Same for
> debug/test purpose. As mentionned in the cover letter the number of
> writable ID regs continue to grow and this enhanced host model gives
> flexibility to test new support and may provide enhanced debug
> capabilities for migration (getting a straight understanding of which ID
> reg field(s) causes the migration failure could be helpful I think)

FYI, in x86 target the -cpu command has had a "migratable=bool" property
for a long time , which defaults to 'true' for 'host' model. This causes
QEMU to explicitly drop features which would otherwise prevent migration
between two hosts with identical physical CPUs.

IOW, if there are some bits present in 'host' that cause migration
problems on Ampere hosts, ideally either QEMU (or KVM kmod) would
detect them and turn them off automatically if migratable=true is
set. See commit message in 84f1b92f & 120eee7d1fd for some background
info

NB "migratable" is defined in i386 target code today, but conceptually
we should expand/move that to apply to all targets for consistency,
even if it is effectively a no-op some targets (eg if they are
guaranteed migratable out of the box already with '-cpu host').

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-11-04 14:55               ` Daniel P. Berrangé
@ 2024-11-04 15:10                 ` Cornelia Huck
  2024-11-04 15:24                   ` Daniel P. Berrangé
  0 siblings, 1 reply; 72+ messages in thread
From: Cornelia Huck @ 2024-11-04 15:10 UTC (permalink / raw)
  To: Daniel P. Berrangé, Eric Auger
  Cc: eric.auger.pro, qemu-devel, qemu-arm, kvmarm, peter.maydell,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

On Mon, Nov 04 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:

> On Mon, Nov 04, 2024 at 03:45:13PM +0100, Eric Auger wrote:
>> Hi
>> 
>> On 10/28/24 17:09, Daniel P. Berrangé wrote:
>> > On Mon, Oct 28, 2024 at 05:05:44PM +0100, Cornelia Huck wrote:
>> >> On Fri, Oct 25 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:
>> >>
>> >>> On Fri, Oct 25, 2024 at 03:28:35PM +0200, Eric Auger wrote:
>> >>>> Hi Daniel,
>> >>>>
>> >>>> On 10/25/24 15:13, Daniel P. Berrangé wrote:
>> >>>>> On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
>> >>>>>> From: Cornelia Huck <cohuck@redhat.com>
>> >>>>>>
>> >>>>>> Add some documentation for the custom model.
>> >>>>>>
>> >>>>>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>> >>>>>> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
>> >>>>>> ---
>> >>>>>>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
>> >>>>>>  1 file changed, 47 insertions(+), 8 deletions(-)
>> >>>>>> @@ -167,6 +196,16 @@ disabling many SVE vector lengths would be quite verbose, the ``sve<N>`` CPU
>> >>>>>>  properties have special semantics (see "SVE CPU Property Parsing
>> >>>>>>  Semantics").
>> >>>>>>  
>> >>>>>> +The ``custom`` CPU model needs to be configured via individual ID register
>> >>>>>> +field properties, for example::
>> >>>>>> +
>> >>>>>> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
>> >>>>>> +
>> >>>>>> +This forces ID_AA64ISAR0_EL1 DP field to 0.
>> >>>>> What is the "baseline" featureset implied by 'custom' ?
>> >>>> there is no baseline at the moment. By default this is a host
>> >>>> passthrough model.
>> >>> Why do we need to create "custom" at all, as opposed to just letting
>> >>> users toggle features on "-cpu host" ? 
>> >> We could consolidate that to the current "host" model, once we figure
>> >> out how to handle the currently already existing properties. Models
>> >> based on the different architecture extensions would probably be more
>> >> useable in the long run; maybe "custom" has a place for testing.
>> > If you can set the features against "host", then any testing could
>> > be done with "host" surely, making 'custom' pointless ?
>> Yeah I do agree that we may not need to introduce this "custom" model
>> bus just enhance the custom host model with the capability to tweek some
>> features. For instance we have the case where migration between 2 Ampere
>> systems fails with host model but if you tweek 1 field in CTR_EL0 it
>> passes. So I think in itself this modality can be useful. Same for
>> debug/test purpose. As mentionned in the cover letter the number of
>> writable ID regs continue to grow and this enhanced host model gives
>> flexibility to test new support and may provide enhanced debug
>> capabilities for migration (getting a straight understanding of which ID
>> reg field(s) causes the migration failure could be helpful I think)
>
> FYI, in x86 target the -cpu command has had a "migratable=bool" property
> for a long time , which defaults to 'true' for 'host' model. This causes
> QEMU to explicitly drop features which would otherwise prevent migration
> between two hosts with identical physical CPUs.
>
> IOW, if there are some bits present in 'host' that cause migration
> problems on Ampere hosts, ideally either QEMU (or KVM kmod) would
> detect them and turn them off automatically if migratable=true is
> set. See commit message in 84f1b92f & 120eee7d1fd for some background
> info

How does this work for version-sensitive features -- are they always
defaulting to off? How many features are left with that in the end?

>
> NB "migratable" is defined in i386 target code today, but conceptually
> we should expand/move that to apply to all targets for consistency,
> even if it is effectively a no-op some targets (eg if they are
> guaranteed migratable out of the box already with '-cpu host').

How does this compare to s390x, which defines some migration-safe cpu
models, based upon the different hw generations? If I look at the QEMU
code for x86 and s390x, the s390x approach seems cleaner to me (probably
because it came later, and therefore could start afresh without having
to care for legacy things.) Given that we'll cook up a new model for Arm
migration as well, we might as well start with a clean implementation :)

(Not sure what this looks like on the libvirt side.)



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-11-04 15:10                 ` Cornelia Huck
@ 2024-11-04 15:24                   ` Daniel P. Berrangé
  2024-11-04 15:48                     ` Cornelia Huck
  0 siblings, 1 reply; 72+ messages in thread
From: Daniel P. Berrangé @ 2024-11-04 15:24 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Eric Auger, eric.auger.pro, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Mon, Nov 04, 2024 at 04:10:12PM +0100, Cornelia Huck wrote:
> On Mon, Nov 04 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:
> 
> >
> > FYI, in x86 target the -cpu command has had a "migratable=bool" property
> > for a long time , which defaults to 'true' for 'host' model. This causes
> > QEMU to explicitly drop features which would otherwise prevent migration
> > between two hosts with identical physical CPUs.
> >
> > IOW, if there are some bits present in 'host' that cause migration
> > problems on Ampere hosts, ideally either QEMU (or KVM kmod) would
> > detect them and turn them off automatically if migratable=true is
> > set. See commit message in 84f1b92f & 120eee7d1fd for some background
> > info
> 
> How does this work for version-sensitive features -- are they always
> defaulting to off? How many features are left with that in the end?

Do you mean QEMU versions here ? The non-migratable feature list is
just hardcoded in QEMU right now, and there's only 1 of them.
eg grep for 'unmigratable_flags'

Note, that "migratable" property is not defining a general purpose
migration mask between different hw generations. It was specifically
blocking just stuff that is known to make migration impossible, even
if HW is identical on both sides.

> > NB "migratable" is defined in i386 target code today, but conceptually
> > we should expand/move that to apply to all targets for consistency,
> > even if it is effectively a no-op some targets (eg if they are
> > guaranteed migratable out of the box already with '-cpu host').
> 
> How does this compare to s390x, which defines some migration-safe cpu
> models, based upon the different hw generations? If I look at the QEMU
> code for x86 and s390x, the s390x approach seems cleaner to me (probably
> because it came later, and therefore could start afresh without having
> to care for legacy things.) Given that we'll cook up a new model for Arm
> migration as well, we might as well start with a clean implementation :)

The impression I get (as an distant observer) is that CPUs on s390x in
general have less complexity to worry about. A combination of not having
a vendor who creates loads off different SKUs for the same CPU model
family with slight variations between each, and also not seeming to have
a situation where CPU flags a known to disappear (or appear) arbitrarily
in microcode updates.

The s390x idea of a "migratable" and "non migratable" model for each
HW generation is a nice simplification, but I can't see how it could
be made to work for x86 when you can't predict ahead of time what
features are going to be removed from existing HW definition by the
next microcode update, or by the next CPU SKU that removes a feature
you had assumed would always be present in a given HW generation.

I don't know much about how ARM world works, but having lots of vendors
competing with their own custom impls makes me worry complexity will
be closer to x86 than to s390.

If the ARM specifications define a minimum require featureset for each
HW generation, maybe you can define a model based on that ? You might
still want to have vendor specific models though, if there are compelling
features they expose which are optional, or non-standardized. 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-10-28 21:17   ` Kashyap Chamarthy
@ 2024-11-04 15:34     ` Eric Auger
  2024-11-04 16:30       ` Peter Maydell
  0 siblings, 1 reply; 72+ messages in thread
From: Eric Auger @ 2024-11-04 15:34 UTC (permalink / raw)
  To: Kashyap Chamarthy
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar, shahuang, mark.rutland, philmd, pbonzini

Hi Kashyap,

On 10/28/24 22:17, Kashyap Chamarthy wrote:
> On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
>> From: Cornelia Huck <cohuck@redhat.com>
>>
>> Add some documentation for the custom model.
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
>> ---
>>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
>>  1 file changed, 47 insertions(+), 8 deletions(-)
>>
>> diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
>> index a5fb929243..962a2c6c26 100644
>> --- a/docs/system/arm/cpu-features.rst
>> +++ b/docs/system/arm/cpu-features.rst
>> @@ -2,7 +2,10 @@ Arm CPU Features
> [...]
>
>> +Using the ``host`` type means the guest is provided all the same CPU
>> +features as the host CPU type has.  And, for this reason, the ``host``
>> +CPU type should enable all CPU features that the host has by default.
>> +
>> +In case some features need to be hidden to the guest, ``custom`` model
>> +shall be used instead. This is especially useful for migration purpose.
>> +
>> +The ``custom`` CPU model generally is the better choice if you want more
>> +flexibility or stability across different machines or with different kernel
>> +versions. 
> Does "more flexibility or stability across different machines" also
> imply "live migration compatiblity across host CPUs"?
yes that's the goal
>
>> However, even the ``custom`` CPU model will not allow configuring
>> +an arbitrary set of features; the ID registers must describe a subset of the
>> +host's features, and all differences to the host's configuration must actually
>> +be supported by the kernel to be deconfigured.
> [...]
>
>> +The ``custom`` CPU model needs to be configured via individual ID register
>> +field properties, for example::
>> +
>> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
> If possible, it would be really helpful (and user-friendly) to be able
> to specify the CPU feature names as you see under /proc/cpuinfo, and be
> able to turn the flags on or off:
>     
>         -M virt -cpu franken,rndr=on,ts=on,fhm=off
>
> (... instead of specifying long system register IDs that groups together
> a bunch of CPU features.  If I understand it correctly, the register
> "ID_AA64ISAR0_EL1" maps to a set of visible features listed here:
> https://docs.kernel.org/arch/arm64/cpu-feature-registers.html)
Not all the writable ID regs are visible through the above technique.
But indeed I think we converged on the idea to use higher level feature
names than ID reg field values.
However we need to study the feasibility and mappings between those high
level features and ID reg field values.
The cons is that we need to describe this mapping manually. Besides
being cumbersome this is also error prone.
>
>
> Next, I prefix the below by noting that I wrote it before seeing
> Cornelia's reply that the name "custom" is not set in stone:
> https://lists.nongnu.org/archive/html/qemu-arm/2024-10/msg00987.html.
>
> I wonder if the word "custom" is starting to get overloaded; on x86:
>
>   - Libvirt itself uses the term "custom" this way, to quote its
>     documentation[1] for the 'custom' XML attribute:
>
>       custom
>     
>       In this mode, the 'cpu' element describes the CPU that should be
>       presented to the guest. This is the default when no 'mode'
>       attribute is specified. This mode makes it so that a persistent
>       guest will see the same hardware no matter what host the guest is
>       booted on.
>
>   - Some management tools also follow libvirt and use the term "custom"
>     to refer to one of two things, (a) a specific named CPU model that
>     libvirt and QEMU recognize, e.g. "Cascadelake-Server"; or (b) a
>     named CPU model + extra CPU flags, e.g. this is how OpenStack
>     uses[2] "custom" to configure CPU models, and flags that can be
>     enabled or disabled via "+" or "-":
>
>       [libvirt]
>       cpu_mode = custom
>       cpu_model = IvyBridge-IBRS
>       cpu_model_extra_flags="ss,+vmx,-pcid [...]"
>
>     (Note the "cpu_mode" there: it is referring to the three possible
>     modes that libvirt and QEMU support today: 'host-passthrough',
>     'host-model', and named CPU models via "custom".)
>
>     The above config translates to this QEMU command-line:
>
>         -cpu IvyBridge-IBRS,ss=on,vmx=on,pcid=off [...]
>
> Now if QEMU introduces "custom", it is likely to create some confusion.
> But luckily, as referenced above, it is open to change. :)
Agreed! Thank you for the references!

Eric
>
>     * * *
>
> FWIW, I agree with Dan here[3] that it would cause less future pain if
> Arm's named CPU models also decides on a "baseline that matches some
> corresponding real world silicon".  I've experienced plenty of such
> debugging pain in x86-land from years of troubleshooting live migration
> bugs involving CPU model (in)compatibility.  (Often, with help from
> DanPB and Jiri Denemark).
>
> [1] https://docs.openstack.org/nova/latest/admin/cpu-models.html#cpu-modes
> [2] https://libvirt.org/formatdomain.html#cpu-model-and-topology
> [3] https://lists.nongnu.org/archive/html/qemu-arm/2024-10/msg00888.html
>     — [RFC 21/21] arm/cpu-features: Document custom vcpu model
>
> [...]
>



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-11-04 15:24                   ` Daniel P. Berrangé
@ 2024-11-04 15:48                     ` Cornelia Huck
  0 siblings, 0 replies; 72+ messages in thread
From: Cornelia Huck @ 2024-11-04 15:48 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Eric Auger, eric.auger.pro, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Mon, Nov 04 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:

> On Mon, Nov 04, 2024 at 04:10:12PM +0100, Cornelia Huck wrote:
>> On Mon, Nov 04 2024, Daniel P. Berrangé <berrange@redhat.com> wrote:
>> 
>> >
>> > FYI, in x86 target the -cpu command has had a "migratable=bool" property
>> > for a long time , which defaults to 'true' for 'host' model. This causes
>> > QEMU to explicitly drop features which would otherwise prevent migration
>> > between two hosts with identical physical CPUs.
>> >
>> > IOW, if there are some bits present in 'host' that cause migration
>> > problems on Ampere hosts, ideally either QEMU (or KVM kmod) would
>> > detect them and turn them off automatically if migratable=true is
>> > set. See commit message in 84f1b92f & 120eee7d1fd for some background
>> > info
>> 
>> How does this work for version-sensitive features -- are they always
>> defaulting to off? How many features are left with that in the end?
>
> Do you mean QEMU versions here ? The non-migratable feature list is
> just hardcoded in QEMU right now, and there's only 1 of them.
> eg grep for 'unmigratable_flags'
>
> Note, that "migratable" property is not defining a general purpose
> migration mask between different hw generations. It was specifically
> blocking just stuff that is known to make migration impossible, even
> if HW is identical on both sides.

I was more thinking of dependencies on the KVM version -- QEMU versions
are easier to control for, but you don't really know what kernel version
you are running with. In the end, we'd probably need to mark a lot of
things as unmigratable.

>
>> > NB "migratable" is defined in i386 target code today, but conceptually
>> > we should expand/move that to apply to all targets for consistency,
>> > even if it is effectively a no-op some targets (eg if they are
>> > guaranteed migratable out of the box already with '-cpu host').
>> 
>> How does this compare to s390x, which defines some migration-safe cpu
>> models, based upon the different hw generations? If I look at the QEMU
>> code for x86 and s390x, the s390x approach seems cleaner to me (probably
>> because it came later, and therefore could start afresh without having
>> to care for legacy things.) Given that we'll cook up a new model for Arm
>> migration as well, we might as well start with a clean implementation :)
>
> The impression I get (as an distant observer) is that CPUs on s390x in
> general have less complexity to worry about. A combination of not having
> a vendor who creates loads off different SKUs for the same CPU model
> family with slight variations between each, and also not seeming to have
> a situation where CPU flags a known to disappear (or appear) arbitrarily
> in microcode updates.
>
> The s390x idea of a "migratable" and "non migratable" model for each
> HW generation is a nice simplification, but I can't see how it could
> be made to work for x86 when you can't predict ahead of time what
> features are going to be removed from existing HW definition by the
> next microcode update, or by the next CPU SKU that removes a feature
> you had assumed would always be present in a given HW generation.
>
> I don't know much about how ARM world works, but having lots of vendors
> competing with their own custom impls makes me worry complexity will
> be closer to x86 than to s390.

My concern was more about code complexity, not hw complexity. We'll
probably end up with a zoo of weird creatures for Arm, but I don't see a
reason why the code would need to have strange things tacked
on. I.e. have a set of arch extensions that you can baseline to, and
have individual cpus on top, so you can deal with both well-known cpus
and more boutique ones.

>
> If the ARM specifications define a minimum require featureset for each
> HW generation, maybe you can define a model based on that ? You might
> still want to have vendor specific models though, if there are compelling
> features they expose which are optional, or non-standardized. 

We have a list of features that are optional for a given arch extension,
and a list of features that are mandatory, so I think we'd be able to
generate a model with the mandatory features only. Models for individual
cpus could base off these. (There are currently 13 vendors defined in
MIDR, but I'm not sure how often new vendors might be added, and vendors
may also be more or less active.) If you have a baseline of Arm v9.2 or
so, that might already go a long way.

[But I obviously have no idea how well that will work when it meats
reality :)]



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model
  2024-10-25 14:51 ` Kashyap Chamarthy
  2024-10-28 16:20   ` Cornelia Huck
@ 2024-11-04 15:52   ` Eric Auger
  1 sibling, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-11-04 15:52 UTC (permalink / raw)
  To: Kashyap Chamarthy
  Cc: eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	peter.maydell, richard.henderson, alex.bennee, maz, oliver.upton,
	sebott, shameerali.kolothum.thodi, armbru, berrange, abologna,
	jdenemar, shahuang, mark.rutland, philmd, pbonzini

Hi Kashyap,
On 10/25/24 16:51, Kashyap Chamarthy wrote:
> On Fri, Oct 25, 2024 at 12:17:19PM +0200, Eric Auger wrote:
>
> Hi Eric,
>
> I'm new to Arm, so please bear with my questions :)
>
>> This RFC series introduces a KVM host "custom" model.
> (a) On terminology: as we know, in the x86 world, QEMU uses these
>     terms[1]:
>
>     - Host passthrough
>     - Named CPU models
>     - Then there's the libvirt abstraction, "host-model", that aims to
>       provide the best of 'host-passthrough' + named CPU models.
>
>     Now I see the term "host 'custom' model" here.  Most
>     management-layer tools and libvirt users are familiar with the
>     classic terms "host-model" or "custom".  If we now say "host
>     'custom' model", it can create confusion.  I hope we can settle on
>     one of the existing terms, or create a new term if need be.
>
>     (I'll share one more thought on how layers above libvirt tend to use
>     the term "custom", as a reply to patch 21/21, "arm/cpu-features:
>     Document custom vcpu model".)
agreed, as replied earlier, custom terminology most probably will be
dropped.
>
> (b) The current CPU features doc[2] for Arm doesn't mention "host
>     passthrough" at all.  It is only implied by the last part of this
>     paragraph, from the section titled "A note about CPU models and
>     KVM"[3]:
>
>       "Named CPU models generally do not work with KVM. There are a few
>       cases that do work [...] but mostly if KVM is enabled the 'host'
>       CPU type must be used."
indeed
>
>     Related: in your reply[4] to Dan in this series, you write: "Having
>     named models is the next thing".  So named CPU models will be a
>     thing in Arm, too?  Then the above statement in the Arm
>     'cpu-features' will need updating :-)

Yes named models implementing a baseline are the end goal.
>
> [...]
>
>> - the QEMU layer does not take care of IDREG field value consistency.
>>   The kernel neither. I imagine this could be the role of the upper
>>   layer to implement a vcpu profile that makes sure settings are
>>   consistent. Here we come to "named" models. What should they look
>>   like on ARM?
> Are there reasons why they can't be similar to how x86 reports in
> `qemu-system-x86 -cpu help`?  
>
> E.g. If it's an NVIDIA "Grace A02" (Neoverse-V2) host, it can report:
>
>     [gracehopper] $> qemu-kvm -cpu help
>     Available CPUs:
>       gracehopper-neoverse-v2
>       cortex-a57 (deprecated)
>       host
>       max
>
> Or whatever is the preferred nomenclature for ARM.  It also gives users
> of both x86 and ARM deployments a consistent expectation.  
>
> Currently on a "Grace A02" ("Neoverse-V2") machine, it reports:
>
>     [gracehopper] $> qemu-kvm -cpu help
>     Available CPUs:
>       cortex-a57 (deprecated)
>       host
>       max
>
> I see it's because there are no named models yet on ARM :-)
yes this is definitively because on ARM there is no such named KVM model
besides cortex-a57 on aarch64.
on x86 does it return the closest named model?

Thanks

Eric
>
> [...]
>
> [1] https://www.qemu.org/docs/master/system/i386/cpu.html
> [2] https://www.qemu.org/docs/master/system/arm/cpu-features.html
> [3] https://www.qemu.org/docs/master/system/arm/cpu-features.html#a-note-about-cpu-models-and-kvm
> [4] https://lists.nongnu.org/archive/html/qemu-arm/2024-10/msg00891.html
>
>



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-11-04 15:34     ` Eric Auger
@ 2024-11-04 16:30       ` Peter Maydell
  2024-11-04 17:07         ` Eric Auger
  2024-11-04 18:29         ` Kashyap Chamarthy
  0 siblings, 2 replies; 72+ messages in thread
From: Peter Maydell @ 2024-11-04 16:30 UTC (permalink / raw)
  To: eric.auger
  Cc: Kashyap Chamarthy, eric.auger.pro, cohuck, qemu-devel, qemu-arm,
	kvmarm, richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, berrange, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Mon, 4 Nov 2024 at 15:34, Eric Auger <eric.auger@redhat.com> wrote:
>
> Hi Kashyap,
>
> On 10/28/24 22:17, Kashyap Chamarthy wrote:
> > On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
> >> From: Cornelia Huck <cohuck@redhat.com>
> >>
> >> Add some documentation for the custom model.
> >>
> >> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> >> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> >> ---
> >>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
> >>  1 file changed, 47 insertions(+), 8 deletions(-)
> >>
> >> diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
> >> index a5fb929243..962a2c6c26 100644
> >> --- a/docs/system/arm/cpu-features.rst
> >> +++ b/docs/system/arm/cpu-features.rst
> >> @@ -2,7 +2,10 @@ Arm CPU Features
> > [...]
> >
> >> +Using the ``host`` type means the guest is provided all the same CPU
> >> +features as the host CPU type has.  And, for this reason, the ``host``
> >> +CPU type should enable all CPU features that the host has by default.
> >> +
> >> +In case some features need to be hidden to the guest, ``custom`` model
> >> +shall be used instead. This is especially useful for migration purpose.
> >> +
> >> +The ``custom`` CPU model generally is the better choice if you want more
> >> +flexibility or stability across different machines or with different kernel
> >> +versions.
> > Does "more flexibility or stability across different machines" also
> > imply "live migration compatiblity across host CPUs"?
> yes that's the goal
> >
> >> However, even the ``custom`` CPU model will not allow configuring
> >> +an arbitrary set of features; the ID registers must describe a subset of the
> >> +host's features, and all differences to the host's configuration must actually
> >> +be supported by the kernel to be deconfigured.
> > [...]
> >
> >> +The ``custom`` CPU model needs to be configured via individual ID register
> >> +field properties, for example::
> >> +
> >> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
> > If possible, it would be really helpful (and user-friendly) to be able
> > to specify the CPU feature names as you see under /proc/cpuinfo, and be
> > able to turn the flags on or off:
> >
> >         -M virt -cpu franken,rndr=on,ts=on,fhm=off
> >
> > (... instead of specifying long system register IDs that groups together
> > a bunch of CPU features.  If I understand it correctly, the register
> > "ID_AA64ISAR0_EL1" maps to a set of visible features listed here:
> > https://docs.kernel.org/arch/arm64/cpu-feature-registers.html)
> Not all the writable ID regs are visible through the above technique.
> But indeed I think we converged on the idea to use higher level feature
> names than ID reg field values.
> However we need to study the feasibility and mappings between those high
> level features and ID reg field values.
> The cons is that we need to describe this mapping manually. Besides
> being cumbersome this is also error prone.

You might be interested in "Arm Architecture Features" on
https://developer.arm.com/Architectures/A-Profile%20Architecture#Downloads
which includes a 1.8MB Features.json which is a machine
readable version of the "what are the features and their
dependencies and ID registers and so on" information.

But note that (a) it is alpha quality and (b) I am not personally
going to try to interpret what might be reasonable to do with it
based on the legal notice attached to it: that's a matter for
you and your lawyer ;-)

-- PMM


^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-11-04 16:30       ` Peter Maydell
@ 2024-11-04 17:07         ` Eric Auger
  2024-11-04 18:29         ` Kashyap Chamarthy
  1 sibling, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-11-04 17:07 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Kashyap Chamarthy, eric.auger.pro, cohuck, qemu-devel, qemu-arm,
	kvmarm, richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, berrange, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

Hi Peter,

On 11/4/24 17:30, Peter Maydell wrote:
> On Mon, 4 Nov 2024 at 15:34, Eric Auger <eric.auger@redhat.com> wrote:
>> Hi Kashyap,
>>
>> On 10/28/24 22:17, Kashyap Chamarthy wrote:
>>> On Fri, Oct 25, 2024 at 12:17:40PM +0200, Eric Auger wrote:
>>>> From: Cornelia Huck <cohuck@redhat.com>
>>>>
>>>> Add some documentation for the custom model.
>>>>
>>>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>>> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
>>>> ---
>>>>  docs/system/arm/cpu-features.rst | 55 +++++++++++++++++++++++++++-----
>>>>  1 file changed, 47 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
>>>> index a5fb929243..962a2c6c26 100644
>>>> --- a/docs/system/arm/cpu-features.rst
>>>> +++ b/docs/system/arm/cpu-features.rst
>>>> @@ -2,7 +2,10 @@ Arm CPU Features
>>> [...]
>>>
>>>> +Using the ``host`` type means the guest is provided all the same CPU
>>>> +features as the host CPU type has.  And, for this reason, the ``host``
>>>> +CPU type should enable all CPU features that the host has by default.
>>>> +
>>>> +In case some features need to be hidden to the guest, ``custom`` model
>>>> +shall be used instead. This is especially useful for migration purpose.
>>>> +
>>>> +The ``custom`` CPU model generally is the better choice if you want more
>>>> +flexibility or stability across different machines or with different kernel
>>>> +versions.
>>> Does "more flexibility or stability across different machines" also
>>> imply "live migration compatiblity across host CPUs"?
>> yes that's the goal
>>>> However, even the ``custom`` CPU model will not allow configuring
>>>> +an arbitrary set of features; the ID registers must describe a subset of the
>>>> +host's features, and all differences to the host's configuration must actually
>>>> +be supported by the kernel to be deconfigured.
>>> [...]
>>>
>>>> +The ``custom`` CPU model needs to be configured via individual ID register
>>>> +field properties, for example::
>>>> +
>>>> +  $ qemu-system-aarch64 -M virt -cpu custom,SYSREG_ID_AA64ISAR0_EL1_DP=0x0
>>> If possible, it would be really helpful (and user-friendly) to be able
>>> to specify the CPU feature names as you see under /proc/cpuinfo, and be
>>> able to turn the flags on or off:
>>>
>>>         -M virt -cpu franken,rndr=on,ts=on,fhm=off
>>>
>>> (... instead of specifying long system register IDs that groups together
>>> a bunch of CPU features.  If I understand it correctly, the register
>>> "ID_AA64ISAR0_EL1" maps to a set of visible features listed here:
>>> https://docs.kernel.org/arch/arm64/cpu-feature-registers.html)
>> Not all the writable ID regs are visible through the above technique.
>> But indeed I think we converged on the idea to use higher level feature
>> names than ID reg field values.
>> However we need to study the feasibility and mappings between those high
>> level features and ID reg field values.
>> The cons is that we need to describe this mapping manually. Besides
>> being cumbersome this is also error prone.
> You might be interested in "Arm Architecture Features" on
> https://developer.arm.com/Architectures/A-Profile%20Architecture#Downloads
> which includes a 1.8MB Features.json which is a machine
> readable version of the "what are the features and their
> dependencies and ID registers and so on" information.
thank you for the link.
>
> But note that (a) it is alpha quality and (b) I am not personally
> going to try to interpret what might be reasonable to do with it
> based on the legal notice attached to it: that's a matter for
> you and your lawyer ;-)

Thank you for the notice. This may be similar to the ARM xml mentioned
by Marc...

Eric
>
> -- PMM
>



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-10-28 16:56               ` Oliver Upton
  2024-10-30 16:15                 ` Cornelia Huck
@ 2024-11-04 17:09                 ` Eric Auger
  2024-11-04 17:16                   ` Peter Maydell
  1 sibling, 1 reply; 72+ messages in thread
From: Eric Auger @ 2024-11-04 17:09 UTC (permalink / raw)
  To: Oliver Upton, Peter Maydell
  Cc: Daniel P. Berrangé, eric.auger.pro, cohuck, qemu-devel,
	qemu-arm, kvmarm, richard.henderson, alex.bennee, maz, sebott,
	shameerali.kolothum.thodi, armbru, abologna, jdenemar, shahuang,
	mark.rutland, philmd, pbonzini

Hi Oliver,

On 10/28/24 17:56, Oliver Upton wrote:
> On Mon, Oct 28, 2024 at 04:48:18PM +0000, Peter Maydell wrote:
>> On Mon, 28 Oct 2024 at 16:35, Daniel P. Berrangé <berrange@redhat.com> wrote:
>>> On Mon, Oct 28, 2024 at 04:16:31PM +0000, Peter Maydell wrote:
>>>> On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>> On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
>>>>>> On 10/25/24 15:06, Daniel P. Berrangé wrote:
>>>>>>> Also, is this naming convention really the same one that users
>>>>>>> will see when they look at /proc/cpuinfo to view features ? It
>>>>>> No it is not. I do agree that the custom cpu model is very low level. It
>>>>>> is very well suited to test all series turning ID regs as writable but
>>>>>> this would require an extra layer that adapts /proc/cpuinfo feature
>>>>>> level to this regid/field abstraction.
>>>>>>
>>>>>> In /cpu/proc you will see somethink like:
>>>>>>  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
>>>>>> asimdhp cpuid asimdrdm lrcpc dcpop asimddp
>>>>> Right, IMHO, this is the terminology that QEMU must use in user
>>>>> facing APIs.
>>>> /proc/cpuinfo's naming is rather weird for historical
>>>> reasons (for instance there is only one FEAT_FP16 feature
>>>> but cpuinfo lists "fphp" and "asimdhp" separately).
>>> There's plenty of wierd history in x86 too. In this
>>> case I might suggest just picking one of the two
>>> common names, and ignoring the other.
>>>
>>> If we really wanted to, we could alias the 2nd name
>>> to the first, but its likely not worth the bother.
>> Or we could use the standard set of architectural
>> feature names, and not have the problem at all, and not
>> have to document what we mean by our nonstandard names.
> +1
>
> There's existing documentation [*] for the standard feature names, which
> provides:
>
>  - A short description of what the feature does
>  - Any dependencies a particular feature has (e.g.FEAT_VHE implies
>    FEAT_LSE, FEAT_Debugv8p1, and FEAT_AA64EL2)
>  - The register fields/values that are used to discover the feature.
>
> This seems like the most user-friendly option...
>
> [*]: https://developer.arm.com/documentation/109697/2024_09

Was just wondering if all the writable ID reg fields were associated to
an official FEAT_ listed in this feature list.
Let's take for instance CTR_EL0.DIC. Is it associated to a given
extension or is it just implementation defined?

Thanks

Eric
>



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-11-04 17:09                 ` Eric Auger
@ 2024-11-04 17:16                   ` Peter Maydell
  2024-11-04 18:15                     ` Eric Auger
  0 siblings, 1 reply; 72+ messages in thread
From: Peter Maydell @ 2024-11-04 17:16 UTC (permalink / raw)
  To: eric.auger
  Cc: Oliver Upton, Daniel P. Berrangé, eric.auger.pro, cohuck,
	qemu-devel, qemu-arm, kvmarm, richard.henderson, alex.bennee, maz,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Mon, 4 Nov 2024 at 17:09, Eric Auger <eric.auger@redhat.com> wrote:
> Was just wondering if all the writable ID reg fields were associated to
> an official FEAT_ listed in this feature list.
> Let's take for instance CTR_EL0.DIC. Is it associated to a given
> extension or is it just implementation defined?

CTR_EL0.DIC is IMPDEF choice of 0 or 1. There's no associated
FEAT_* -- as an implementation, you are effectively just
reporting here what your implementation's properties are.

(CTR_EL0 is not an ID register in the architectural sense.)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-11-04 17:16                   ` Peter Maydell
@ 2024-11-04 18:15                     ` Eric Auger
  0 siblings, 0 replies; 72+ messages in thread
From: Eric Auger @ 2024-11-04 18:15 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Oliver Upton, Daniel P. Berrangé, eric.auger.pro, cohuck,
	qemu-devel, qemu-arm, kvmarm, richard.henderson, alex.bennee, maz,
	sebott, shameerali.kolothum.thodi, armbru, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

Hi Peter,

On 11/4/24 18:16, Peter Maydell wrote:
> On Mon, 4 Nov 2024 at 17:09, Eric Auger <eric.auger@redhat.com> wrote:
>> Was just wondering if all the writable ID reg fields were associated to
>> an official FEAT_ listed in this feature list.
>> Let's take for instance CTR_EL0.DIC. Is it associated to a given
>> extension or is it just implementation defined?
> CTR_EL0.DIC is IMPDEF choice of 0 or 1. There's no associated
> FEAT_* -- as an implementation, you are effectively just
> reporting here what your implementation's properties are.
>
> (CTR_EL0 is not an ID register in the architectural sense.)

thank you for the confirmation. So this means we also need to be able to
tune such bit although it does not have any fellow FEAT_*.

Eric
>
> thanks
> -- PMM
>



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 21/21] arm/cpu-features: Document custom vcpu model
  2024-11-04 16:30       ` Peter Maydell
  2024-11-04 17:07         ` Eric Auger
@ 2024-11-04 18:29         ` Kashyap Chamarthy
  1 sibling, 0 replies; 72+ messages in thread
From: Kashyap Chamarthy @ 2024-11-04 18:29 UTC (permalink / raw)
  To: Peter Maydell
  Cc: eric.auger, eric.auger.pro, cohuck, qemu-devel, qemu-arm, kvmarm,
	richard.henderson, alex.bennee, maz, oliver.upton, sebott,
	shameerali.kolothum.thodi, armbru, berrange, abologna, jdenemar,
	shahuang, mark.rutland, philmd, pbonzini

On Mon, Nov 04, 2024 at 04:30:17PM +0000, Peter Maydell wrote:
> On Mon, 4 Nov 2024 at 15:34, Eric Auger <eric.auger@redhat.com> wrote:

[...]

> > > If possible, it would be really helpful (and user-friendly) to be able
> > > to specify the CPU feature names as you see under /proc/cpuinfo, and be
> > > able to turn the flags on or off:
> > >
> > >         -M virt -cpu franken,rndr=on,ts=on,fhm=off
> > >
> > > (... instead of specifying long system register IDs that groups together
> > > a bunch of CPU features.  If I understand it correctly, the register
> > > "ID_AA64ISAR0_EL1" maps to a set of visible features listed here:
> > > https://docs.kernel.org/arch/arm64/cpu-feature-registers.html)
> > Not all the writable ID regs are visible through the above technique.
> > But indeed I think we converged on the idea to use higher level feature
> > names than ID reg field values.
> > However we need to study the feasibility and mappings between those high
> > level features and ID reg field values.
> > The cons is that we need to describe this mapping manually. Besides
> > being cumbersome this is also error prone.
> 
> You might be interested in "Arm Architecture Features" on
> https://developer.arm.com/Architectures/A-Profile%20Architecture#Downloads
> which includes a 1.8MB Features.json which is a machine
> readable version of the "what are the features and their
> dependencies and ID registers and so on" information.

I just took a quick at the JSON file.  It was a bit difficult to get a
sense of the structure of the file.  Maybe it makes more sense to those
who are more Arm-aware than me.  Or maybe that's what you meant by
"alpha quality" below :)

Out of curiosity, I tried to find the features for the register
"ID_AA64ISAR0_EL1".  I was navigating via trial-and-error with `jq`.
There's a lot of "right"/"left" traversing:

    $> jq '.parameters[136]|.constraints[1]|.right|.left|.value' Features.json 
    "FEAT_TME"

The register name is buried under this:

    $> jq '.parameters[136]|.constraints[1]|.right|.right|.left|.arguments' Features.json 
    [
      {
        "_type": "Types.Field",
        "value": {
          "field": "TME",
          "instance": null,
          "name": "ID_AA64ISAR0_EL1",
          "slices": null,
          "state": "AArch64"
        }
      }
    ]


I was niavely expecting a more predictable structure such as:

    $> jq '.register[ID_AA64ISAR0_EL1]|.fields' Features.json
    FEAT_RNG
    FEAT_TLBIOS
    ...

> But note that (a) it is alpha quality and (b) I am not personally
> going to try to interpret what might be reasonable to do with it
> based on the legal notice attached to it: that's a matter for
> you and your lawyer ;-)

Hmm, it sounds like until point (b) is clarified, this file is out of
consideration from an upstream point of view.

> -- PMM
> 

-- 
/kashyap



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-11-04 14:27                 ` Eric Auger
@ 2024-11-11 14:29                   ` Cornelia Huck
  2024-11-12 16:30                     ` Cornelia Huck
  2024-11-14 15:44                     ` Peter Maydell
  0 siblings, 2 replies; 72+ messages in thread
From: Cornelia Huck @ 2024-11-11 14:29 UTC (permalink / raw)
  To: eric.auger, Daniel P. Berrangé, Peter Maydell
  Cc: eric.auger.pro, qemu-devel, qemu-arm, kvmarm, richard.henderson,
	alex.bennee, maz, oliver.upton, sebott, shameerali.kolothum.thodi,
	armbru, abologna, jdenemar, shahuang, mark.rutland, philmd,
	pbonzini

On Mon, Nov 04 2024, Eric Auger <eric.auger@redhat.com> wrote:

> Hi Daniel,
>
> On 10/28/24 18:04, Daniel P. Berrangé wrote:
>> On Mon, Oct 28, 2024 at 04:48:18PM +0000, Peter Maydell wrote:
>>> On Mon, 28 Oct 2024 at 16:35, Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>> On Mon, Oct 28, 2024 at 04:16:31PM +0000, Peter Maydell wrote:
>>>>> On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>>> On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
>>>>>>> On 10/25/24 15:06, Daniel P. Berrangé wrote:
>>>>>>>> Also, is this naming convention really the same one that users
>>>>>>>> will see when they look at /proc/cpuinfo to view features ? It
>>>>>>> No it is not. I do agree that the custom cpu model is very low level. It
>>>>>>> is very well suited to test all series turning ID regs as writable but
>>>>>>> this would require an extra layer that adapts /proc/cpuinfo feature
>>>>>>> level to this regid/field abstraction.
>>>>>>>
>>>>>>> In /cpu/proc you will see somethink like:
>>>>>>>  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
>>>>>>> asimdhp cpuid asimdrdm lrcpc dcpop asimddp
>>>>>> Right, IMHO, this is the terminology that QEMU must use in user
>>>>>> facing APIs.
>>>>> /proc/cpuinfo's naming is rather weird for historical
>>>>> reasons (for instance there is only one FEAT_FP16 feature
>>>>> but cpuinfo lists "fphp" and "asimdhp" separately).
>>>> There's plenty of wierd history in x86 too. In this
>>>> case I might suggest just picking one of the two
>>>> common names, and ignoring the other.
>>>>
>>>> If we really wanted to, we could alias the 2nd name
>>>> to the first, but its likely not worth the bother.
>>> Or we could use the standard set of architectural
>>> feature names, and not have the problem at all, and not
>>> have to document what we mean by our nonstandard names.
>>> (cpuinfo names do actually mostly line up with the
>>> standard names, just not 100%. Similarly gcc/clang command
>>> line options are mostly the architectural feature name.)
>> Ah, right, yes. Sorry I mis-understood you originally to be suggesting
>> the same low level names as this patch.
> If my understanding is correct, Peter suggested to rely on the
> terminology used in
>
> https://developer.arm.com/documentation/109697/2024_09
>
> the doc pointed to by Oliver.
>
> So I think the next step is to understand how those "high level" features do map onto low level ID register field values. I think a high level feature can map onto separate fields in separate ID regs. This may not be the most common case though. 

I went through all the FEAT_xxx features defined so far and tried to
categorize them (probably with some errors here and there, but the
general trend should be correct.)

There's 335 features defined at the moment.

Of these, the majority (295 by my count) map to one or more values in
one or more id registers. These are what I'd consider the "easy" ones
(added complexity if we deal with serveral values, but in general, it is
clear how to handle them, and most of them actually map to a single
value.) Of course, dependencies may be on top of that.

Then, we have some features (~25 or so) that are actually defined by
dependencies (i.e. FEAT_FOO and FEAT_BAR mean that we have FEAT_BAZ,
sometimes with an architecture extension dependency thrown in as well.)
These features are not really relevant when we compare two cpus since
they do not map to registers directly, but they are relevant if we allow
them to be specified (and use them as a kind of shorthand.) IOW, we'd
need to think about how we'd handle them for comparisons and baselining.

Next, let's talk about architecture extensions. All features have a
level where they have been introduced as optional, some have an upper
limit (e.g. FEAT_AA32EL1 is not allowed from v9.0 onwards), and quite a
number of them (~65 or so) become mandatory with a certain architecture
extension. Sometimes, FEAT_FOO + arch ext also implies FEAT_BAR. If we
introduce Armvx.y named models, we'd need to enforce that some features
are (not) set for a certain model. Complex, but not a showstopper. (We'd
also need to deal with that if we worked on the register level.)

We also have some registers like MIDR/REVIDR that do not correlate with
any FEAT_xxx, but that we still need to handle; I would suggest to deal
with them via separate cpu properties (e.g. specify a list of possible
MIDR/REVIDR pairs.) I hope that there are not too many of them, although
we do have some impdef registers.

That leaves some headscratchers (at least for me.) E.g. FEAT_UINJ, which
is optional from v9.5, and mandatory from v9.6, but where I'm unsure how
we'd discover it, especially as we do not have a way to discover the
architecture extensions. Maybe this will work for named actual cpus
only? I'm also not sure if I understand FEAT_CHK, which is listed as
optional from v8.0 and mandatory from v9.4, but every aarch64 cpu is
supposed to be compliant, because CHKFEAT might be a NOP (and this is
only supposed to check for FEAT_GCS? Yes, I'm confused.)

So tl;dr, we cover a lot of the ID register space via FEAT_xxx (with
varying complexity), but we already know about some exceptions. For some
FEAT_xxx, I'm not sure if we want to handle them at all.

(I also seem to remember that there some things like perf counters that
don't map to any on/off features, but no idea about the details here.)



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-11-11 14:29                   ` Cornelia Huck
@ 2024-11-12 16:30                     ` Cornelia Huck
  2024-11-12 18:28                       ` Eric Auger
  2024-11-14 15:44                     ` Peter Maydell
  1 sibling, 1 reply; 72+ messages in thread
From: Cornelia Huck @ 2024-11-12 16:30 UTC (permalink / raw)
  To: eric.auger, Daniel P. Berrangé, Peter Maydell
  Cc: eric.auger.pro, qemu-devel, qemu-arm, kvmarm, richard.henderson,
	alex.bennee, maz, oliver.upton, sebott, shameerali.kolothum.thodi,
	armbru, abologna, jdenemar, shahuang, mark.rutland, philmd,
	pbonzini

On Mon, Nov 11 2024, Cornelia Huck <cohuck@redhat.com> wrote:

> On Mon, Nov 04 2024, Eric Auger <eric.auger@redhat.com> wrote:
>
>> Hi Daniel,
>>
>> On 10/28/24 18:04, Daniel P. Berrangé wrote:
>>> On Mon, Oct 28, 2024 at 04:48:18PM +0000, Peter Maydell wrote:
>>>> On Mon, 28 Oct 2024 at 16:35, Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>> On Mon, Oct 28, 2024 at 04:16:31PM +0000, Peter Maydell wrote:
>>>>>> On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>>>> On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
>>>>>>>> On 10/25/24 15:06, Daniel P. Berrangé wrote:
>>>>>>>>> Also, is this naming convention really the same one that users
>>>>>>>>> will see when they look at /proc/cpuinfo to view features ? It
>>>>>>>> No it is not. I do agree that the custom cpu model is very low level. It
>>>>>>>> is very well suited to test all series turning ID regs as writable but
>>>>>>>> this would require an extra layer that adapts /proc/cpuinfo feature
>>>>>>>> level to this regid/field abstraction.
>>>>>>>>
>>>>>>>> In /cpu/proc you will see somethink like:
>>>>>>>>  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
>>>>>>>> asimdhp cpuid asimdrdm lrcpc dcpop asimddp
>>>>>>> Right, IMHO, this is the terminology that QEMU must use in user
>>>>>>> facing APIs.
>>>>>> /proc/cpuinfo's naming is rather weird for historical
>>>>>> reasons (for instance there is only one FEAT_FP16 feature
>>>>>> but cpuinfo lists "fphp" and "asimdhp" separately).
>>>>> There's plenty of wierd history in x86 too. In this
>>>>> case I might suggest just picking one of the two
>>>>> common names, and ignoring the other.
>>>>>
>>>>> If we really wanted to, we could alias the 2nd name
>>>>> to the first, but its likely not worth the bother.
>>>> Or we could use the standard set of architectural
>>>> feature names, and not have the problem at all, and not
>>>> have to document what we mean by our nonstandard names.
>>>> (cpuinfo names do actually mostly line up with the
>>>> standard names, just not 100%. Similarly gcc/clang command
>>>> line options are mostly the architectural feature name.)
>>> Ah, right, yes. Sorry I mis-understood you originally to be suggesting
>>> the same low level names as this patch.
>> If my understanding is correct, Peter suggested to rely on the
>> terminology used in
>>
>> https://developer.arm.com/documentation/109697/2024_09
>>
>> the doc pointed to by Oliver.
>>
>> So I think the next step is to understand how those "high level" features do map onto low level ID register field values. I think a high level feature can map onto separate fields in separate ID regs. This may not be the most common case though. 
>
> I went through all the FEAT_xxx features defined so far and tried to
> categorize them (probably with some errors here and there, but the
> general trend should be correct.)
>
> There's 335 features defined at the moment.
>
> Of these, the majority (295 by my count) map to one or more values in
> one or more id registers. These are what I'd consider the "easy" ones
> (added complexity if we deal with serveral values, but in general, it is
> clear how to handle them, and most of them actually map to a single
> value.) Of course, dependencies may be on top of that.
>
> Then, we have some features (~25 or so) that are actually defined by
> dependencies (i.e. FEAT_FOO and FEAT_BAR mean that we have FEAT_BAZ,
> sometimes with an architecture extension dependency thrown in as well.)
> These features are not really relevant when we compare two cpus since
> they do not map to registers directly, but they are relevant if we allow
> them to be specified (and use them as a kind of shorthand.) IOW, we'd
> need to think about how we'd handle them for comparisons and baselining.
>
> Next, let's talk about architecture extensions. All features have a
> level where they have been introduced as optional, some have an upper
> limit (e.g. FEAT_AA32EL1 is not allowed from v9.0 onwards), and quite a
> number of them (~65 or so) become mandatory with a certain architecture
> extension. Sometimes, FEAT_FOO + arch ext also implies FEAT_BAR. If we
> introduce Armvx.y named models, we'd need to enforce that some features
> are (not) set for a certain model. Complex, but not a showstopper. (We'd
> also need to deal with that if we worked on the register level.)
>
> We also have some registers like MIDR/REVIDR that do not correlate with
> any FEAT_xxx, but that we still need to handle; I would suggest to deal
> with them via separate cpu properties (e.g. specify a list of possible
> MIDR/REVIDR pairs.) I hope that there are not too many of them, although
> we do have some impdef registers.
>
> That leaves some headscratchers (at least for me.) E.g. FEAT_UINJ, which
> is optional from v9.5, and mandatory from v9.6, but where I'm unsure how
> we'd discover it, especially as we do not have a way to discover the
> architecture extensions. Maybe this will work for named actual cpus
> only? I'm also not sure if I understand FEAT_CHK, which is listed as
> optional from v8.0 and mandatory from v9.4, but every aarch64 cpu is
> supposed to be compliant, because CHKFEAT might be a NOP (and this is
> only supposed to check for FEAT_GCS? Yes, I'm confused.)
>
> So tl;dr, we cover a lot of the ID register space via FEAT_xxx (with
> varying complexity), but we already know about some exceptions. For some
> FEAT_xxx, I'm not sure if we want to handle them at all.
>
> (I also seem to remember that there some things like perf counters that
> don't map to any on/off features, but no idea about the details here.)

Following up on this, some ideas/questions on how a command line could
look like and behave.

Let's say we introduce Armv80, Armv81, ... models for the architecture
extensions and optionally named models for individual cpus we care about
(e.g. My85BasedCpu which would be Armv85 + some stuff on top). The
Armv<xy> models would come with all mandatory features turned on and
would allow all optional features to be set or unset, with
(accelerator-specific) verification on top.

Let's assume that we have

-cpu Armv80,FEAT_AdvSIMD=on,FEAT_FP=on

Since the two features provide each other, I'd assume

-cpu Armv80,FEAT_AdvSIMD=on

or

-cpu Armv80,FEAT_FP=on

to be equivalent, and

-cpu Armv80,FEAT_AdvSIMD=on,FEAT_FP=off

to generate an error. Question: at which level? s390x does dependency
validation in QEMU, we could do it as well, but I think we have way more
dependencies on Arm.

Also, let's take FEAT_BTI, which is optional for 8.4 and mandatory from
8.5 onwards. I'd expect

-cpu Armv84,FEAT_BTI=on   <-- ok
-cpu Armv84  same as -cpu Armv84,FEAT_BTI=off
-cpu Armv85 same as -cpu Arm84,FEAT_BTI=on
-cpu Armv85,FEAT_BTI=off  <-- Error!

When doing baselining while looking at id registers, we'd get

ID_AA64PFR1_EL1.BT == 1 -> must use Armv84 or later
ID_AA64PFR1_EL1.BT == 0 -> must use Armv84 or earlier

(unfortunately, some other features are more complex...)

Would

-cpu Armv84,<all 8.5 mandatory bits>

generate the same cpu as

-cpu Armv85

(and therefore, the two be migratable between each other?)

If we create named cpu models for individual cpus, e.g.

-cpu My85BasedCpu

as equivalent to

-cpu Armv85,FEAT_FOO=on,FEAT_BAR=on

Should we allow

-cpu My85BasedCpu,FEAT_BAR=off

or would the command line need to be

-cpu Armv85,FEAT_FOO=on

(e.g. to deal with not all id regs being writable?)

Regardless of what we end up doing for features and cpu models, we'll
need to be able to specify registers that do not correlate to any
features; especially for things like MIDR/REVIDR, where we'll want to
provide a list of possible target values as pairs;

-cpu Armv85,midr_revidr=(<value>,<value>)

is ugly, and figuring the actual values is not user friendly at all, I
fear :(

And now, at the end of this long email, the most important questions:
What colour should the features have?

Matching the architecture: FEAT_AdvSIMD, FEAT_FP, FEAT_BTI

Dropping "FEAT_": AdvSIMD, FP, BTI

Less shouty: feat_advsimd, feat_fp, feat_bti

Less shouty and shorter: advsimd, fp, bti  -- in this case we'd need to
be careful because we already have sve/sme props, and I'm not sure if we
could do some sugaring without conflicts.

Thoughts?



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-11-12 16:30                     ` Cornelia Huck
@ 2024-11-12 18:28                       ` Eric Auger
  2024-11-29 15:10                         ` Cornelia Huck
  0 siblings, 1 reply; 72+ messages in thread
From: Eric Auger @ 2024-11-12 18:28 UTC (permalink / raw)
  To: Cornelia Huck, Daniel P. Berrangé, Peter Maydell
  Cc: eric.auger.pro, qemu-devel, qemu-arm, kvmarm, richard.henderson,
	alex.bennee, maz, oliver.upton, sebott, shameerali.kolothum.thodi,
	armbru, abologna, jdenemar, shahuang, mark.rutland, philmd,
	pbonzini

Hi Conny,

On 11/12/24 17:30, Cornelia Huck wrote:
> On Mon, Nov 11 2024, Cornelia Huck <cohuck@redhat.com> wrote:
>
>> On Mon, Nov 04 2024, Eric Auger <eric.auger@redhat.com> wrote:
>>
>>> Hi Daniel,
>>>
>>> On 10/28/24 18:04, Daniel P. Berrangé wrote:
>>>> On Mon, Oct 28, 2024 at 04:48:18PM +0000, Peter Maydell wrote:
>>>>> On Mon, 28 Oct 2024 at 16:35, Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>>> On Mon, Oct 28, 2024 at 04:16:31PM +0000, Peter Maydell wrote:
>>>>>>> On Fri, 25 Oct 2024 at 14:24, Daniel P. Berrangé <berrange@redhat.com> wrote:
>>>>>>>> On Fri, Oct 25, 2024 at 03:18:25PM +0200, Eric Auger wrote:
>>>>>>>>> On 10/25/24 15:06, Daniel P. Berrangé wrote:
>>>>>>>>>> Also, is this naming convention really the same one that users
>>>>>>>>>> will see when they look at /proc/cpuinfo to view features ? It
>>>>>>>>> No it is not. I do agree that the custom cpu model is very low level. It
>>>>>>>>> is very well suited to test all series turning ID regs as writable but
>>>>>>>>> this would require an extra layer that adapts /proc/cpuinfo feature
>>>>>>>>> level to this regid/field abstraction.
>>>>>>>>>
>>>>>>>>> In /cpu/proc you will see somethink like:
>>>>>>>>>  Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
>>>>>>>>> asimdhp cpuid asimdrdm lrcpc dcpop asimddp
>>>>>>>> Right, IMHO, this is the terminology that QEMU must use in user
>>>>>>>> facing APIs.
>>>>>>> /proc/cpuinfo's naming is rather weird for historical
>>>>>>> reasons (for instance there is only one FEAT_FP16 feature
>>>>>>> but cpuinfo lists "fphp" and "asimdhp" separately).
>>>>>> There's plenty of wierd history in x86 too. In this
>>>>>> case I might suggest just picking one of the two
>>>>>> common names, and ignoring the other.
>>>>>>
>>>>>> If we really wanted to, we could alias the 2nd name
>>>>>> to the first, but its likely not worth the bother.
>>>>> Or we could use the standard set of architectural
>>>>> feature names, and not have the problem at all, and not
>>>>> have to document what we mean by our nonstandard names.
>>>>> (cpuinfo names do actually mostly line up with the
>>>>> standard names, just not 100%. Similarly gcc/clang command
>>>>> line options are mostly the architectural feature name.)
>>>> Ah, right, yes. Sorry I mis-understood you originally to be suggesting
>>>> the same low level names as this patch.
>>> If my understanding is correct, Peter suggested to rely on the
>>> terminology used in
>>>
>>> https://developer.arm.com/documentation/109697/2024_09
>>>
>>> the doc pointed to by Oliver.
>>>
>>> So I think the next step is to understand how those "high level" features do map onto low level ID register field values. I think a high level feature can map onto separate fields in separate ID regs. This may not be the most common case though. 
>> I went through all the FEAT_xxx features defined so far and tried to
>> categorize them (probably with some errors here and there, but the
>> general trend should be correct.)
>>
>> There's 335 features defined at the moment.
>>
>> Of these, the majority (295 by my count) map to one or more values in
>> one or more id registers. These are what I'd consider the "easy" ones
>> (added complexity if we deal with serveral values, but in general, it is
>> clear how to handle them, and most of them actually map to a single
>> value.) Of course, dependencies may be on top of that.
>>
>> Then, we have some features (~25 or so) that are actually defined by
>> dependencies (i.e. FEAT_FOO and FEAT_BAR mean that we have FEAT_BAZ,
>> sometimes with an architecture extension dependency thrown in as well.)
>> These features are not really relevant when we compare two cpus since
>> they do not map to registers directly, but they are relevant if we allow
>> them to be specified (and use them as a kind of shorthand.) IOW, we'd
>> need to think about how we'd handle them for comparisons and baselining.
>>
>> Next, let's talk about architecture extensions. All features have a
>> level where they have been introduced as optional, some have an upper
>> limit (e.g. FEAT_AA32EL1 is not allowed from v9.0 onwards), and quite a
>> number of them (~65 or so) become mandatory with a certain architecture
>> extension. Sometimes, FEAT_FOO + arch ext also implies FEAT_BAR. If we
>> introduce Armvx.y named models, we'd need to enforce that some features
>> are (not) set for a certain model. Complex, but not a showstopper. (We'd
>> also need to deal with that if we worked on the register level.)
>>
>> We also have some registers like MIDR/REVIDR that do not correlate with
>> any FEAT_xxx, but that we still need to handle; I would suggest to deal
>> with them via separate cpu properties (e.g. specify a list of possible
>> MIDR/REVIDR pairs.) I hope that there are not too many of them, although
>> we do have some impdef registers.
>>
>> That leaves some headscratchers (at least for me.) E.g. FEAT_UINJ, which
>> is optional from v9.5, and mandatory from v9.6, but where I'm unsure how
>> we'd discover it, especially as we do not have a way to discover the
>> architecture extensions. Maybe this will work for named actual cpus
>> only? I'm also not sure if I understand FEAT_CHK, which is listed as
>> optional from v8.0 and mandatory from v9.4, but every aarch64 cpu is
>> supposed to be compliant, because CHKFEAT might be a NOP (and this is
>> only supposed to check for FEAT_GCS? Yes, I'm confused.)
>>
>> So tl;dr, we cover a lot of the ID register space via FEAT_xxx (with
>> varying complexity), but we already know about some exceptions. For some
>> FEAT_xxx, I'm not sure if we want to handle them at all.
>>
>> (I also seem to remember that there some things like perf counters that
>> don't map to any on/off features, but no idea about the details here.)
> Following up on this, some ideas/questions on how a command line could
> look like and behave.
>
> Let's say we introduce Armv80, Armv81, ... models for the architecture
> extensions and optionally named models for individual cpus we care about
> (e.g. My85BasedCpu which would be Armv85 + some stuff on top). The
> Armv<xy> models would come with all mandatory features turned on and
> would allow all optional features to be set or unset, with
> (accelerator-specific) verification on top.
>
> Let's assume that we have
>
> -cpu Armv80,FEAT_AdvSIMD=on,FEAT_FP=on
>
> Since the two features provide each other, I'd assume
>
> -cpu Armv80,FEAT_AdvSIMD=on
>
> or
>
> -cpu Armv80,FEAT_FP=on
>
> to be equivalent, and
>
> -cpu Armv80,FEAT_AdvSIMD=on,FEAT_FP=off
>
> to generate an error. Question: at which level? s390x does dependency
> validation in QEMU, we could do it as well, but I think we have way more
> dependencies on Arm.
>
> Also, let's take FEAT_BTI, which is optional for 8.4 and mandatory from
> 8.5 onwards. I'd expect
>
> -cpu Armv84,FEAT_BTI=on   <-- ok
> -cpu Armv84  same as -cpu Armv84,FEAT_BTI=off
> -cpu Armv85 same as -cpu Arm84,FEAT_BTI=on
except we may have plenty of other 8.5 mandatory features I guess
> -cpu Armv85,FEAT_BTI=off  <-- Error!
>
> When doing baselining while looking at id registers, we'd get
>
> ID_AA64PFR1_EL1.BT == 1 -> must use Armv84 or later
> ID_AA64PFR1_EL1.BT == 0 -> must use Armv84 or earlier
>
> (unfortunately, some other features are more complex...)
>
> Would
>
> -cpu Armv84,<all 8.5 mandatory bits>
>
> generate the same cpu as
>
> -cpu Armv85
>
> (and therefore, the two be migratable between each other?)
I don't think we want this capability. I guess we would support
migration between exact same cpu <type>,<feat list>
>
> If we create named cpu models for individual cpus, e.g.
>
> -cpu My85BasedCpu
>
> as equivalent to
>
> -cpu Armv85,FEAT_FOO=on,FEAT_BAR=on
>
> Should we allow
>
> -cpu My85BasedCpu,FEAT_BAR=off
> or would the command line need to be
>
> -cpu Armv85,FEAT_FOO=on
I am scared about the overall implementation/test matrix. Can we afford
supporting that many setups, revision based models, named models with
all kinds of features optim-in/opt-out. We should also keep in mind what
is our current goal, ie. supporting migration between different machines
but still with sufficient commonalities.

Shouldn't we try to collect community needs in that regard. I don't know
if people will/can tell us what they want to migrate from/to. At least
do the machines comply with the same spec rev or how large is the gap.
How many ID regs/features do mismatch in general. Are those ID regs
currently writable? What would be the best grouping model for them?

Also many ID regs are not writable, because we have not turned them yet
as writable or because they are not that much a problem at the moment.
Maybe some features are not fully turned as writable. I mean some ID
regs they depend on are but not all of them.

So maybe we should reduce the complexity by reducing the scope to the 16
writable regs we have atm (~ 126 writable ID reg fields).
>
> (e.g. to deal with not all id regs being writable?)
>
> Regardless of what we end up doing for features and cpu models, we'll
> need to be able to specify registers that do not correlate to any
> features; especially for things like MIDR/REVIDR, where we'll want to
> provide a list of possible target values as pairs;
>
> -cpu Armv85,midr_revidr=(<value>,<value>)
>
> is ugly, and figuring the actual values is not user friendly at all, I
> fear :(
>
> And now, at the end of this long email, the most important questions:
> What colour should the features have?
>
> Matching the architecture: FEAT_AdvSIMD, FEAT_FP, FEAT_BTI
>
> Dropping "FEAT_": AdvSIMD, FP, BTI
>
> Less shouty: feat_advsimd, feat_fp, feat_bti
>
> Less shouty and shorter: advsimd, fp, bti  -- in this case we'd need to
> be careful because we already have sve/sme props, and I'm not sure if we
> could do some sugaring without conflicts.

Another big question I think is how the upper layer will detect the
relevance of a named model and associated feature. We saw that

/proc/cpuinfo was not that much consistent with FEAT_xxx terminology. Many other features can't be queried I guess. I think it is also part of the problematic. Is it worth exposing stuff that cannot be simply introspected?

Thanks

Eric

>
> Thoughts?
>



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-11-11 14:29                   ` Cornelia Huck
  2024-11-12 16:30                     ` Cornelia Huck
@ 2024-11-14 15:44                     ` Peter Maydell
  1 sibling, 0 replies; 72+ messages in thread
From: Peter Maydell @ 2024-11-14 15:44 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: eric.auger, Daniel P. Berrangé, eric.auger.pro, qemu-devel,
	qemu-arm, kvmarm, richard.henderson, alex.bennee, maz,
	oliver.upton, sebott, shameerali.kolothum.thodi, armbru, abologna,
	jdenemar, shahuang, mark.rutland, philmd, pbonzini

On Mon, 11 Nov 2024 at 14:29, Cornelia Huck <cohuck@redhat.com> wrote:
> That leaves some headscratchers (at least for me.) E.g. FEAT_UINJ, which
> is optional from v9.5, and mandatory from v9.6, but where I'm unsure how
> we'd discover it, especially as we do not have a way to discover the
> architecture extensions.

I think that's just an accidental omission from the FEAT_UINJ
documentation. There's a UINJ field in ID_AA64PFR2_EL1 which
tells you whether FEAT_UINJ is implemented:

https://developer.arm.com/documentation/109697/2024_09/Feature-descriptions/The-Armv9-6-architecture-extension

> I'm also not sure if I understand FEAT_CHK, which is listed as
> optional from v8.0 and mandatory from v9.4, but every aarch64 cpu is
> supposed to be compliant, because CHKFEAT might be a NOP (and this is
> only supposed to check for FEAT_GCS? Yes, I'm confused.)

CHKFEAT is there for cases where software (especially EL0 software)
might need a fast cross-OS-portable way to detect whether a feature
is present and enabled -- for instance if you want the compiler
to emit a function prologue sequence that includes "do XYZ if
GCS is on". CHKFEAT is in the hint area of the encoding space,
so for any CPU that pre-dates FEAT_CHK it will do nothing (which is
how "no features detectable with CHKFEAT are present" is indicated:
if you look at what CHKFEAT actually does it has a definition that
isn't how you'd naturally implement a feature-detect unless you
needed to make NOP mean no-features-present.)

Currently FEAT_GCS is the only feature where it has been deemed
necessary to provide this kind of is-it-enabled detection, but some
future features might also use the CHKFEAT mechanism.

If you're a piece of system software wanting to see if FEAT_GCS
is present you would use ID_AA64PFR1_EL1.GCS. (In particular, if
you're an OS then until you have enabled GCS for yourself via
GCSCR_EL1, CHKFEAT will tell you "not enabled", so you first need
to look at the ID register to see if the GCSCR_EL1 register is
there at all...)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-11-12 18:28                       ` Eric Auger
@ 2024-11-29 15:10                         ` Cornelia Huck
  2024-11-29 15:42                           ` Peter Maydell
  0 siblings, 1 reply; 72+ messages in thread
From: Cornelia Huck @ 2024-11-29 15:10 UTC (permalink / raw)
  To: eric.auger, Daniel P. Berrangé, Peter Maydell
  Cc: eric.auger.pro, qemu-devel, qemu-arm, kvmarm, richard.henderson,
	alex.bennee, maz, oliver.upton, sebott, shameerali.kolothum.thodi,
	armbru, abologna, jdenemar, shahuang, mark.rutland, philmd,
	pbonzini

On Tue, Nov 12 2024, Eric Auger <eric.auger@redhat.com> wrote:
> I am scared about the overall implementation/test matrix. Can we afford
> supporting that many setups, revision based models, named models with
> all kinds of features optim-in/opt-out. We should also keep in mind what
> is our current goal, ie. supporting migration between different machines
> but still with sufficient commonalities.
>
> Shouldn't we try to collect community needs in that regard. I don't know
> if people will/can tell us what they want to migrate from/to. At least
> do the machines comply with the same spec rev or how large is the gap.
> How many ID regs/features do mismatch in general. Are those ID regs
> currently writable? What would be the best grouping model for them?
>
> Also many ID regs are not writable, because we have not turned them yet
> as writable or because they are not that much a problem at the moment.
> Maybe some features are not fully turned as writable. I mean some ID
> regs they depend on are but not all of them.
>
> So maybe we should reduce the complexity by reducing the scope to the 16
> writable regs we have atm (~ 126 writable ID reg fields).

Reducing scope is definetely needed here, I agree. Probably best to put
the design of named models on the backburner for now, until we've
figured out what we actually need/want to support.

In order to figure out how difficult/problematic mapping ID register
contents to features would be, I've been looking at some real world
examples, i.e. looking at register dumps on some servers that should be
reasonably close in capabilities and where we would like to be able to
migrate between them. "Reasonably close" is mostly "not more than two
handfuls of differences"; sometimes derived from a common base
(e.g. Neoverse-V2.)

The good news is that in many cases we only have differences in bits
that map to a feature (and are actually writable in current KVM.) The
bad news is that we have a number of exceptions.

Comparison #1:

ID_AA64DFR0
f010307009	#of breakpoints:7
f010305009	#of breakpoints:5

BRPs does not match to any feature (but has a different meaning when we
have FEAT_Debugv8p9 and 16+ breakpoints)
[this is a whole can of worms in general]

ID_AA64MMFR0
2100022200101026	FEAT_ECV, FEAT_FGT, 4PB
0000022200101125	mixed endian, 256TB

FEAT_ECV -> may be 1 or 2 in ECV, with different capabilities (I guess
we would need to allow something like FEAT_ECV=2 to expess this?)
support for mixed endian -> indicated in BigEnd, no feature (how
relevant is this in practice?)
PARange (52 bits/4PB vs 48 bits/256TB) -> no feature, but some values
depend on other features -- we care about this when creating a cpu, but
migrating to another system with a mismatched range would be
problematic, unless configuration outside of the cpu model would take
care of it

Comparison #2:

ID_AA64PFR0
1101011021111111	FEAT_AMUv1, GIC v3.0/4.0
1101001020111111

GIC == 1 indicates GIC CPU sysreg interface for 3.0/4.0, but no feature
(I'm not quite sure how we handle this in QEMU)

ID_AA64MMFR1
1000000010312122	FEAT_ECBHB, !FEAT_ETS2, FEAT_PAN3, FEAT_HPDS2, FEAT_HAFDBS
0000001010211120	!FEAT_ETS2, FEAT_PAN2, FEAT_HPDS

both ETS == 0 and ETS == 1 indicate that FEAT_ETS2 is not implememented
(ETS == 2 would indicate FEAT_ETS2) -- I guess we would want to
standardize on ETS == 0
FEAT_PAN3 implies FEAT_PAN2, and FEAT_HPDS2 implies FEAT_HPDS2, so
probably fine

ID_AA64MMFR2
1221011112001011	FEAT_BBM=2
1211011112011011	FEAT_BBM=1, FEAT_LVA

FEAT_BBM can have different values -- so not a neat boolean

So in summary, we have
(a) a few features that look a bit funky, but should be managable,
    especially if we accept non-boolean values
(b) things that are indicated in ID registers but do not map to any
    feature like mixed endian support
(c) things in (b) that we already know to be problematic, like the
    number of breakpoints
(d) things in (b) that actually interact with other configurations we
    might do via the commandline (PARange, probably GIC?)

and that's just from a sample of existing systems I was able to get data
from; I think we don't expect that there aren't any more of these in the
remainder of the architecture. (I'm excluding not-yet writable bits, as
I assume we'll eventually render everything writable that is feasible
and needed, although I suspect that there are problems lurking in there
as well.)

[I completely ignored aarch32 registers.]

My current plan is to push off features vs id regs into the future and
do a new version of this patch set that keeps id regs, but drops the
'custom' model, and that can be used to try migration between some hand
picked systems (to find out what other problems we will need to deal
with.)



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-11-29 15:10                         ` Cornelia Huck
@ 2024-11-29 15:42                           ` Peter Maydell
  2024-11-29 15:51                             ` Cornelia Huck
  0 siblings, 1 reply; 72+ messages in thread
From: Peter Maydell @ 2024-11-29 15:42 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: eric.auger, Daniel P. Berrangé, eric.auger.pro, qemu-devel,
	qemu-arm, kvmarm, richard.henderson, alex.bennee, maz,
	oliver.upton, sebott, shameerali.kolothum.thodi, armbru, abologna,
	jdenemar, shahuang, mark.rutland, philmd, pbonzini

On Fri, 29 Nov 2024 at 15:10, Cornelia Huck <cohuck@redhat.com> wrote:
> The good news is that in many cases we only have differences in bits
> that map to a feature (and are actually writable in current KVM.) The
> bad news is that we have a number of exceptions.
>
> Comparison #1:
>
> ID_AA64DFR0
> f010307009      #of breakpoints:7
> f010305009      #of breakpoints:5
>
> BRPs does not match to any feature (but has a different meaning when we
> have FEAT_Debugv8p9 and 16+ breakpoints)
> [this is a whole can of worms in general]
>
> ID_AA64MMFR0
> 2100022200101026        FEAT_ECV, FEAT_FGT, 4PB
> 0000022200101125        mixed endian, 256TB
>
> FEAT_ECV -> may be 1 or 2 in ECV, with different capabilities (I guess
> we would need to allow something like FEAT_ECV=2 to expess this?)

This one was an unfortunate oversight; I expect that there
will be a separate feature name for the =2 case in some future
spec release. But as you note for FEAT_BBM below, not
every different ID field value always has its own FEAT_ name.
(FEAT_HAFDBS is another -- it allows ID_AA64MMFR1_EL1.HAFDBS to
be 1 or 2.)

> support for mixed endian -> indicated in BigEnd, no feature (how
> relevant is this in practice?)

ID_AA64MMFR0_EL1.BigEnd == 1 is FEAT_MixedEnd. Relevant if your
guest or its userspace wants to use big-endian, which is probably
approximately nobody in a KVM context but is theoretically possible.

> PARange (52 bits/4PB vs 48 bits/256TB) -> no feature, but some values
> depend on other features -- we care about this when creating a cpu, but
> migrating to another system with a mismatched range would be
> problematic, unless configuration outside of the cpu model would take
> care of it
>
> Comparison #2:
>
> ID_AA64PFR0
> 1101011021111111        FEAT_AMUv1, GIC v3.0/4.0
> 1101001020111111
>
> GIC == 1 indicates GIC CPU sysreg interface for 3.0/4.0, but no feature
> (I'm not quite sure how we handle this in QEMU)

We basically defer GIC emulation almost entirely to the
kernel (which will set the GIC bit in the ID registers
according to whether userspace asked it for a GIC or not).

> ID_AA64MMFR1
> 1000000010312122        FEAT_ECBHB, !FEAT_ETS2, FEAT_PAN3, FEAT_HPDS2, FEAT_HAFDBS
> 0000001010211120        !FEAT_ETS2, FEAT_PAN2, FEAT_HPDS
>
> both ETS == 0 and ETS == 1 indicate that FEAT_ETS2 is not implememented
> (ETS == 2 would indicate FEAT_ETS2) -- I guess we would want to
> standardize on ETS == 0
> FEAT_PAN3 implies FEAT_PAN2, and FEAT_HPDS2 implies FEAT_HPDS2, so
> probably fine

Yes, in general if the number in the field gets bigger
this should be a backwards-compatible improvement in
the feature.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model
  2024-11-29 15:42                           ` Peter Maydell
@ 2024-11-29 15:51                             ` Cornelia Huck
  0 siblings, 0 replies; 72+ messages in thread
From: Cornelia Huck @ 2024-11-29 15:51 UTC (permalink / raw)
  To: Peter Maydell
  Cc: eric.auger, Daniel P. Berrangé, eric.auger.pro, qemu-devel,
	qemu-arm, kvmarm, richard.henderson, alex.bennee, maz,
	oliver.upton, sebott, shameerali.kolothum.thodi, armbru, abologna,
	jdenemar, shahuang, mark.rutland, philmd, pbonzini

On Fri, Nov 29 2024, Peter Maydell <peter.maydell@linaro.org> wrote:

> On Fri, 29 Nov 2024 at 15:10, Cornelia Huck <cohuck@redhat.com> wrote:
>> The good news is that in many cases we only have differences in bits
>> that map to a feature (and are actually writable in current KVM.) The
>> bad news is that we have a number of exceptions.
>>
>> Comparison #1:
>>
>> ID_AA64DFR0
>> f010307009      #of breakpoints:7
>> f010305009      #of breakpoints:5
>>
>> BRPs does not match to any feature (but has a different meaning when we
>> have FEAT_Debugv8p9 and 16+ breakpoints)
>> [this is a whole can of worms in general]
>>
>> ID_AA64MMFR0
>> 2100022200101026        FEAT_ECV, FEAT_FGT, 4PB
>> 0000022200101125        mixed endian, 256TB
>>
>> FEAT_ECV -> may be 1 or 2 in ECV, with different capabilities (I guess
>> we would need to allow something like FEAT_ECV=2 to expess this?)
>
> This one was an unfortunate oversight; I expect that there
> will be a separate feature name for the =2 case in some future
> spec release. But as you note for FEAT_BBM below, not
> every different ID field value always has its own FEAT_ name.
> (FEAT_HAFDBS is another -- it allows ID_AA64MMFR1_EL1.HAFDBS to
> be 1 or 2.)

Ah yes, I actually noticed FEAT_HAFDBS as well.

>
>> support for mixed endian -> indicated in BigEnd, no feature (how
>> relevant is this in practice?)
>
> ID_AA64MMFR0_EL1.BigEnd == 1 is FEAT_MixedEnd. Relevant if your
> guest or its userspace wants to use big-endian, which is probably
> approximately nobody in a KVM context but is theoretically possible.

Ok, that one I missed in the list; if there's a feature, we should be
able to use it.

>
>> PARange (52 bits/4PB vs 48 bits/256TB) -> no feature, but some values
>> depend on other features -- we care about this when creating a cpu, but
>> migrating to another system with a mismatched range would be
>> problematic, unless configuration outside of the cpu model would take
>> care of it
>>
>> Comparison #2:
>>
>> ID_AA64PFR0
>> 1101011021111111        FEAT_AMUv1, GIC v3.0/4.0
>> 1101001020111111
>>
>> GIC == 1 indicates GIC CPU sysreg interface for 3.0/4.0, but no feature
>> (I'm not quite sure how we handle this in QEMU)
>
> We basically defer GIC emulation almost entirely to the
> kernel (which will set the GIC bit in the ID registers
> according to whether userspace asked it for a GIC or not).
>
>> ID_AA64MMFR1
>> 1000000010312122        FEAT_ECBHB, !FEAT_ETS2, FEAT_PAN3, FEAT_HPDS2, FEAT_HAFDBS
>> 0000001010211120        !FEAT_ETS2, FEAT_PAN2, FEAT_HPDS
>>
>> both ETS == 0 and ETS == 1 indicate that FEAT_ETS2 is not implememented
>> (ETS == 2 would indicate FEAT_ETS2) -- I guess we would want to
>> standardize on ETS == 0
>> FEAT_PAN3 implies FEAT_PAN2, and FEAT_HPDS2 implies FEAT_HPDS2, so
>> probably fine
>
> Yes, in general if the number in the field gets bigger
> this should be a backwards-compatible improvement in
> the feature.

Indeed, I hope that this will be the case for new features.



^ permalink raw reply	[flat|nested] 72+ messages in thread

end of thread, other threads:[~2024-11-29 15:52 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-25 10:17 [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
2024-10-25 10:17 ` [RFC 01/21] kvm: kvm_get_writable_id_regs Eric Auger
2024-10-25 10:17 ` [RFC 02/21] arm/cpu: Add sysreg definitions in cpu-sysegs.h Eric Auger
2024-10-25 10:17 ` [RFC 03/21] arm/cpu: Store aa64isar0 into the idregs arrays Eric Auger
2024-10-25 10:17 ` [RFC 04/21] arm/cpu: Store aa64isar1/2 into the idregs array Eric Auger
2024-10-25 10:17 ` [RFC 05/21] arm/cpu: Store aa64drf0/1 " Eric Auger
2024-10-25 10:17 ` [RFC 06/21] arm/cpu: Store aa64mmfr0-3 " Eric Auger
2024-10-25 10:17 ` [RFC 07/21] arm/cpu: Store aa64drf0/1 " Eric Auger
2024-10-25 10:17 ` [RFC 08/21] arm/cpu: Store aa64smfr0 " Eric Auger
2024-10-25 10:17 ` [RFC 09/21] arm/cpu: Store id_isar0-7 " Eric Auger
2024-10-25 10:17 ` [RFC 10/21] arm/cpu: Store id_mfr0/1 " Eric Auger
2024-10-25 10:17 ` [RFC 11/21] arm/cpu: Store id_dfr0/1 " Eric Auger
2024-10-25 10:17 ` [RFC 12/21] arm/cpu: Store id_mmfr0-5 " Eric Auger
2024-10-25 10:17 ` [RFC 13/21] arm/cpu: Add infra to handle generated ID register definitions Eric Auger
2024-10-25 12:55   ` Daniel P. Berrangé
2024-10-25 10:17 ` [RFC 14/21] arm/cpu: Add sysreg generation scripts Eric Auger
2024-10-25 17:05   ` Marc Zyngier
2024-11-04 13:33     ` Eric Auger
2024-10-25 10:17 ` [RFC 15/21] arm/cpu: Add generated files Eric Auger
2024-10-25 10:17 ` [RFC 16/21] arm/kvm: Allow reading all the writable ID registers Eric Auger
2024-10-25 10:17 ` [RFC 17/21] arm/kvm: write back modified ID regs to KVM Eric Auger
2024-10-25 10:17 ` [RFC 18/21] arm/cpu: Introduce a customizable kvm host cpu model Eric Auger
2024-10-25 13:06   ` Daniel P. Berrangé
2024-10-25 13:18     ` Eric Auger
2024-10-25 13:23       ` Daniel P. Berrangé
2024-10-28 16:00         ` Cornelia Huck
2024-10-28 16:15           ` Daniel P. Berrangé
2024-10-28 16:16         ` Peter Maydell
2024-10-28 16:25           ` Cornelia Huck
2024-10-28 16:35           ` Daniel P. Berrangé
2024-10-28 16:48             ` Peter Maydell
2024-10-28 16:56               ` Oliver Upton
2024-10-30 16:15                 ` Cornelia Huck
2024-10-30 16:27                   ` Daniel P. Berrangé
2024-11-04 17:09                 ` Eric Auger
2024-11-04 17:16                   ` Peter Maydell
2024-11-04 18:15                     ` Eric Auger
2024-10-28 17:04               ` Daniel P. Berrangé
2024-11-04 14:27                 ` Eric Auger
2024-11-11 14:29                   ` Cornelia Huck
2024-11-12 16:30                     ` Cornelia Huck
2024-11-12 18:28                       ` Eric Auger
2024-11-29 15:10                         ` Cornelia Huck
2024-11-29 15:42                           ` Peter Maydell
2024-11-29 15:51                             ` Cornelia Huck
2024-11-14 15:44                     ` Peter Maydell
2024-10-25 10:17 ` [RFC 19/21] virt: Allow custom vcpu model in arm virt Eric Auger
2024-10-25 10:17 ` [RFC 20/21] arm-qmp-cmds: introspection for custom model Eric Auger
2024-10-25 10:17 ` [RFC 21/21] arm/cpu-features: Document custom vcpu model Eric Auger
2024-10-25 13:13   ` Daniel P. Berrangé
2024-10-25 13:28     ` Eric Auger
2024-10-25 13:31       ` Daniel P. Berrangé
2024-10-28 16:05         ` Cornelia Huck
2024-10-28 16:09           ` Daniel P. Berrangé
2024-10-28 16:29             ` Cornelia Huck
2024-10-31 12:24               ` Kashyap Chamarthy
2024-10-31 12:59                 ` Peter Maydell
2024-11-04 14:45             ` Eric Auger
2024-11-04 14:55               ` Daniel P. Berrangé
2024-11-04 15:10                 ` Cornelia Huck
2024-11-04 15:24                   ` Daniel P. Berrangé
2024-11-04 15:48                     ` Cornelia Huck
2024-10-28 21:17   ` Kashyap Chamarthy
2024-11-04 15:34     ` Eric Auger
2024-11-04 16:30       ` Peter Maydell
2024-11-04 17:07         ` Eric Auger
2024-11-04 18:29         ` Kashyap Chamarthy
2024-10-25 12:49 ` [RFC 00/21] kvm/arm: Introduce a customizable aarch64 KVM host model Cornelia Huck
2024-10-25 14:51 ` Kashyap Chamarthy
2024-10-28 16:20   ` Cornelia Huck
2024-10-28 16:44     ` Peter Maydell
2024-11-04 15:52   ` Eric Auger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).