* [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM
@ 2026-06-05 8:33 Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 01/29] target/arm: named_cpu_model: define containers for ID registers and fields Khushit Shah
` (29 more replies)
0 siblings, 30 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Hi All,
This is the v2 RFC of the Named CPU models support for Arm64 in QEMU.
v2 implements all of Planned items that were mentioned in v1.
v1 link: https://lore.kernel.org/qemu-arm/20260513163356.3033159-1-shaju.abraham@nutanix.com/
Background:
=============================================================
Currently QEMU only support -cpu host/max for KVM on Arm64. This disables
live migration of VMs between hosts that differ in CPU features.
This RFC proposes hierarchical named models for Arm64 under KVM, this
provides strict contract of CPU features that will be exposed to the guest
for a given named model. Models can be customized further with feature
properties (like feat_AES=off, pauth=on, sve=off, etc...).
The design has three layers: an ARM ID-register field table (single
source of truth for fields, safe-rules, defaults, arch-defined values); a
property layer on top (single-field, fractional, and composite properties);
and a hierarchical named-model layer that picks values for those properties
with parent-chain inheritance.
The series also implements QMP commands that lets the management layer query
which models a host can run, what each model resolves to, and which feature
values the host supports.
Relationship with "customizable host model" series:
============================================================
This RFC overlaps with customizable host model series [1]. The two series
solve different parts of the same problem: [1] provides the lower layer
(per-field SYSREG_<REG>_<FIELD> u64 properties on -cpu host,
writable-mask probing, ID-register writeback).
This series adds the layers above that, like:
hierarchical named CPU models, default-from-zero baselines, fractional and
composite properties for named models (sve, pauth, expose-cache),
property/value names, and QMP introspection (blockers via safe-rule
validation, supported values, new query-arm-cpu-props-info). This series
also fixes the host-supports-Nested-Virtualziation-while-qemu-booted-without-it
writeback case [2] that surfaces once [1]'s writeback lands.
Long term plan is to rebase this series on top of [1]. Few difficulties
in that will be augmenting the ID regs fields table with safe rules and
default values, which Eric correctly mentioned in [1] that it cannot
be inferred from Registers.json.
For property names and values we have no strong preference,
<SYSREG>_<REG>_<FIELD> with uint64 values or "feat_*" properties with
string values (SYSREG_ID_AA64ISAR0_AES=2/feat_AES="pmull").
[1]: https://lore.kernel.org/qemu-arm/20260519132905.145643-1-eric.auger@redhat.com/
[2]: See patch 29 of this series.
TL;DR examples:
# Boot with Grace
qemu-system-aarch64 -cpu grace-v1 -machine virt,accel=kvm ...
# Grace with a feature disabled
qemu-system-aarch64 -cpu grace-v1,feat_SHA1=off ...
# Host passthrough with individual feature control
qemu-system-aarch64 -cpu host,feat_AES=aes ...
# named CPU model with composite properties
qemu-system-aarch64 -cpu grace-v1,pauth=off,sve=on ...
# QMP -cpu host query-cpu-model-expansion:
"model": {
"name": "host",
"props": {
"cpu_partnum": 3407,
"feat_SM4": "on",
"feat_SM3": "on",
....
}
}
# QMP -cpu graviton3-v1 query-cpu-model-expansion:
"model": {
"name": "graviton3-v1",
"props": {
"cpu_partnum": 3392,
"feat_SM4": "on",
"feat_SM3": "on",
"feat_RNDR": "on",
....
}
}
# QMP query-cpu-definitions (on Grace host) (blockers for graviton3-v1):
{
"name": "grace-v1",
"typename": "grace-v1-arm-cpu",
"static": false,
"deprecated": false
},
{
"name": "graviton3-v1",
"typename": "graviton3-v1-arm-cpu",
"unavailable-features": [
"hw_prop_TGRAN4_2",
"hw_prop_TGRAN64_2",
"hw_prop_TGRAN16_2",
"hw_prop_APA",
"feat_RNDR"
],
"static": false,
"deprecated": false
},
....
# new QMP query-arm-cpu-props-info (on Grace host):
{
"name": "feat_SHA1",
"type": "boolean",
"supported-values": [
"on",
"off"
]
},
{
"name": "feat_AES",
"type": "string",
"supported-values": [
"off",
"aes",
"pmull"
]
},
....
Changes since v1:
- Added `query-cpu-definitions` and `query-cpu-model-expansion` QMP
support for named models and accompanying properties.
- Introduced `query-arm-cpu-props-info` QMP command that returns
list of all newly supported properties for -cpu host, and its supported
values.
- Add composite properties for named models which acts as master "on"/"off"
switches for features that compose of broader range of ID registers
fields like pauth and sve.
- Added `expose-cache` composite with other cache related properties to
allow named models to expose cache information to the guest.
- Cache the host isar view with and without EL2 support, and make
-cpu host with writeback work on host kernel that supports
virtualization.
- Validate the cpu->isar.idregs before writing back to KVM to catch early
errors.
- Properties and models are now defined in file rather than using .h.inc
files.
Tested on NVIDIA Grace and AWS Graviton3 hosts (6.18); booted grace-v1,
graviton3-v1, neoverse-v2-v1, neoverse-v1-v1, and -cpu host with per-feature
overrides.
Plans for v3:
- Some documentation and unit tests.
- More properties based on what more the latest kernel supports.
- pmu composite property.
- Trying to rebase on top of [1].
- Splitting this huge series into 3-4 sub series.
Warm Regards,
Khushit, Shaju
Khushit Shah (20):
target/arm: Introduce data-structures for the ARM property layer
target/arm: Add all ARM64 properties to host model
target/arm: Add Nvidia Grace named model
target/arm/kvm: enable writable implementation ID registers
target/aarm: Validate cpu->isar.idregs[] before writeback
target/arm/kvm: handle DCZID_EL0 specially
target/arm: skip GIC, COPDBG and PMU fields during KVM writeback
target/arm: Add composite property type to model definitions
target/arm: define pauth composite property
target/arm: define sve composite property
target/arm: Introduce stub files required for qmp support
target/arm/qmp: add named models and properties to cpu-model-expansion
target/arm/kvm: introduce kvm_arm_get_host_isar helper
target/arm/qmp: add query-arm-cpu-props-info
target/arm: Report "off" for ID fields gated by vCPU init flags
target/arm/qmp: hook blockers in query-cpu-definitions
target/arm: Support exposing cache information for named cpu models
target/arm: Provide default cache hierarchy
target/arm: supported-values and blockers for CCSIDR cache properties
target/arm/kvm: fix host model writeback when kernel supports EL2
Shaju Abraham (9):
target/arm: named_cpu_model: define containers for ID registers and
fields
target/arm: Add ID Register field descriptions in cpu-idregs.h.inc
target/arm: Add MIDR, REVIDR, AIDR and extra ID regs to cpu-sysregs
target/arm: Generate ARM64 ID registers and field tables
target/arm: Replace FIELD() macros with IDREG_FIELD expansion
target/arm: Define ARM properties
target/arm: Add ID register field helper functions
target/arm: Add named cpu model infra + graviton3 named model
target/arm/kvm: Writeback modified ID registers to KVM
hw/arm/virt.c | 28 +-
qapi/misc-arm.json | 41 +
stubs/qmp-arm-gic.c | 6 +
target/arm/arm-cpu-models-stub.c | 18 +
target/arm/arm-cpu-models.c | 620 ++++++++++
target/arm/arm-cpu-models.h | 49 +
target/arm/arm-cpu-props-stub.c | 36 +
target/arm/arm-cpu-props.c | 1212 +++++++++++++++++++
target/arm/arm-cpu-props.h | 70 ++
target/arm/arm-qmp-cmds.c | 128 +-
target/arm/cpu-features.h | 246 +---
target/arm/cpu-idregs.c | 508 ++++++++
target/arm/cpu-idregs.h | 119 ++
target/arm/cpu-idregs.h.inc | 1898 ++++++++++++++++++++++++++++++
target/arm/cpu-sysregs.h.inc | 5 +
target/arm/cpu.h | 3 +
target/arm/cpu64.c | 31 +-
target/arm/kvm-stub.c | 7 +-
target/arm/kvm.c | 356 +++++-
target/arm/kvm_arm.h | 7 +-
target/arm/meson.build | 11 +-
target/arm/trace-events | 1 +
22 files changed, 5148 insertions(+), 252 deletions(-)
create mode 100644 target/arm/arm-cpu-models-stub.c
create mode 100644 target/arm/arm-cpu-models.c
create mode 100644 target/arm/arm-cpu-models.h
create mode 100644 target/arm/arm-cpu-props-stub.c
create mode 100644 target/arm/arm-cpu-props.c
create mode 100644 target/arm/arm-cpu-props.h
create mode 100644 target/arm/cpu-idregs.c
create mode 100644 target/arm/cpu-idregs.h
create mode 100644 target/arm/cpu-idregs.h.inc
--
2.52.0
^ permalink raw reply [flat|nested] 41+ messages in thread
* [RFC PATCH v2 01/29] target/arm: named_cpu_model: define containers for ID registers and fields
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 02/29] target/arm: Add ID Register field descriptions in cpu-idregs.h.inc Khushit Shah
` (28 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
From: Shaju Abraham <shaju.abraham@nutanix.com>
Define data structures for mapping the ARM ID registers and ID register
fields.
Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/cpu-idregs.h | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 target/arm/cpu-idregs.h
diff --git a/target/arm/cpu-idregs.h b/target/arm/cpu-idregs.h
new file mode 100644
index 0000000000..514ec39106
--- /dev/null
+++ b/target/arm/cpu-idregs.h
@@ -0,0 +1,41 @@
+/*
+ * ARM ID register field table declarations
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef CPU_IDREGS_H
+#define CPU_IDREGS_H
+
+typedef enum ArmIdRegSafeRule {
+ IDREG_SAFE_LOWER,
+ IDREG_SAFE_HIGHER,
+ IDREG_SAFE_HIGHER_OR_ZERO,
+ IDREG_SAFE_SIGNED_LOWER,
+ IDREG_SAFE_EXACT,
+ IDREG_SAFE_ANY,
+} ArmIdRegSafeRule;
+
+typedef struct ArmIdRegArchVal {
+ uint64_t value;
+ const char *name;
+} ArmIdRegArchVal;
+
+typedef struct ArmIdRegField {
+ const char *name;
+ uint32_t shift;
+ uint32_t length;
+ ArmIdRegSafeRule safe_rule;
+ uint64_t default_val;
+ ArmIdRegArchVal *arch_vals;
+ uint32_t arch_vals_count;
+} ArmIdRegField;
+
+typedef struct ArmIdReg {
+ const char *name;
+ struct ArmIdRegField *fields;
+ uint32_t fields_count;
+} ArmIdReg;
+
+
+#endif /* CPU_IDREGS_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 02/29] target/arm: Add ID Register field descriptions in cpu-idregs.h.inc
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 01/29] target/arm: named_cpu_model: define containers for ID registers and fields Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-12 9:35 ` Eric Auger
2026-06-17 6:32 ` Eric Auger
2026-06-05 8:33 ` [RFC PATCH v2 03/29] target/arm: Add MIDR, REVIDR, AIDR and extra ID regs to cpu-sysregs Khushit Shah
` (27 subsequent siblings)
29 siblings, 2 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
From: Shaju Abraham <shaju.abraham@nutanix.com>
Add a declarative description of every architecturally defined field in
the Arm64 ID registers in cpu-idregs.h.inc file. This file will be
included multiple times with different definitions to build:
- per-field arch values,
- per-register field descriptor arrays,
- arm-idregs[] table etc.
The architecturally defined values for each ID register field is
extracted from 6.18 kernel's arch/arm64/tools/sysreg file.
The safe-value tags and default values are derived from the kernel's
ftr_bits array.
Aarch32 ID registers are added with dummy field so they can be
defaulted to 0 by later commits.
X-macro structure:
IDREG_START(REG)
IDREG_FIELD_START(REG, FIELD, SHIFT, LENGTH, SAFE_RULE, DEFAULT_VAL)
IDREG_FIELD_ARCH_VAL(VALUE, NAME)
...
IDREG_FIELD_END(REG, FIELD)
...
IDREG_END(REG)
Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/cpu-idregs.h.inc | 1807 +++++++++++++++++++++++++++++++++++
1 file changed, 1807 insertions(+)
create mode 100644 target/arm/cpu-idregs.h.inc
diff --git a/target/arm/cpu-idregs.h.inc b/target/arm/cpu-idregs.h.inc
new file mode 100644
index 0000000000..7e2bbf256d
--- /dev/null
+++ b/target/arm/cpu-idregs.h.inc
@@ -0,0 +1,1807 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* ID_AA64ISAR0_EL1 */
+IDREG_START(ID_AA64ISAR0_EL1)
+IDREG_FIELD_START(ID_AA64ISAR0, RES0_0, 0, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64ISAR0, RES0_0)
+
+IDREG_FIELD_START(ID_AA64ISAR0, AES, 4, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "aes")
+IDREG_FIELD_ARCH_VAL(0b0010, "pmull")
+IDREG_FIELD_END(ID_AA64ISAR0, AES)
+
+IDREG_FIELD_START(ID_AA64ISAR0, SHA1, 8, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR0, SHA1)
+
+IDREG_FIELD_START(ID_AA64ISAR0, SHA2, 12, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "sha256")
+IDREG_FIELD_ARCH_VAL(0b0010, "sha512")
+IDREG_FIELD_END(ID_AA64ISAR0, SHA2)
+
+IDREG_FIELD_START(ID_AA64ISAR0, CRC32, 16, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR0, CRC32)
+
+IDREG_FIELD_START(ID_AA64ISAR0, ATOMIC, 20, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0010, "on")
+IDREG_FIELD_ARCH_VAL(0b0011, "LSE128")
+IDREG_FIELD_END(ID_AA64ISAR0, ATOMIC)
+
+IDREG_FIELD_START(ID_AA64ISAR0, RES0_24, 24, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64ISAR0, RES0_24)
+
+IDREG_FIELD_START(ID_AA64ISAR0, RDM, 28, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR0, RDM)
+
+IDREG_FIELD_START(ID_AA64ISAR0, SHA3, 32, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR0, SHA3)
+
+IDREG_FIELD_START(ID_AA64ISAR0, SM3, 36, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR0, SM3)
+
+IDREG_FIELD_START(ID_AA64ISAR0, SM4, 40, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR0, SM4)
+
+IDREG_FIELD_START(ID_AA64ISAR0, DP, 44, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR0, DP)
+
+IDREG_FIELD_START(ID_AA64ISAR0, FHM, 48, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR0, FHM)
+
+IDREG_FIELD_START(ID_AA64ISAR0, TS, 52, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "flagm")
+IDREG_FIELD_ARCH_VAL(0b0010, "flagm2")
+IDREG_FIELD_END(ID_AA64ISAR0, TS)
+
+IDREG_FIELD_START(ID_AA64ISAR0, TLB, 56, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "os")
+IDREG_FIELD_ARCH_VAL(0b0010, "range")
+IDREG_FIELD_END(ID_AA64ISAR0, TLB)
+
+IDREG_FIELD_START(ID_AA64ISAR0, RNDR, 60, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR0, RNDR)
+
+IDREG_END(ID_AA64ISAR0_EL1)
+
+/* ID_AA64ISAR1_EL1 */
+IDREG_START(ID_AA64ISAR1_EL1)
+IDREG_FIELD_START(ID_AA64ISAR1, DPB, 0, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "dpb2")
+IDREG_FIELD_END(ID_AA64ISAR1, DPB)
+
+IDREG_FIELD_START(ID_AA64ISAR1, APA, 4, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "pauth")
+IDREG_FIELD_ARCH_VAL(0b0010, "epac")
+IDREG_FIELD_ARCH_VAL(0b0011, "pauth2")
+IDREG_FIELD_ARCH_VAL(0b0100, "fpac")
+IDREG_FIELD_ARCH_VAL(0b0101, "fpaccombine")
+IDREG_FIELD_ARCH_VAL(0b0110, "pauth_lr")
+IDREG_FIELD_END(ID_AA64ISAR1, APA)
+
+IDREG_FIELD_START(ID_AA64ISAR1, API, 8, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "pauth")
+IDREG_FIELD_ARCH_VAL(0b0010, "epac")
+IDREG_FIELD_ARCH_VAL(0b0011, "pauth2")
+IDREG_FIELD_ARCH_VAL(0b0100, "fpac")
+IDREG_FIELD_ARCH_VAL(0b0101, "fpaccombine")
+IDREG_FIELD_ARCH_VAL(0b0110, "pauth_lr")
+IDREG_FIELD_END(ID_AA64ISAR1, API)
+
+IDREG_FIELD_START(ID_AA64ISAR1, JSCVT, 12, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR1, JSCVT)
+
+IDREG_FIELD_START(ID_AA64ISAR1, FCMA, 16, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR1, FCMA)
+
+IDREG_FIELD_START(ID_AA64ISAR1, LRCPC, 20, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "lrcpc2")
+IDREG_FIELD_ARCH_VAL(0b0011, "lrcpc3")
+IDREG_FIELD_END(ID_AA64ISAR1, LRCPC)
+
+IDREG_FIELD_START(ID_AA64ISAR1, GPA, 24, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR1, GPA)
+
+IDREG_FIELD_START(ID_AA64ISAR1, GPI, 28, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR1, GPI)
+
+IDREG_FIELD_START(ID_AA64ISAR1, FRINTTS, 32, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR1, FRINTTS)
+
+IDREG_FIELD_START(ID_AA64ISAR1, SB, 36, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR1, SB)
+
+IDREG_FIELD_START(ID_AA64ISAR1, SPECRES, 40, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "cosp_rctx")
+IDREG_FIELD_END(ID_AA64ISAR1, SPECRES)
+
+IDREG_FIELD_START(ID_AA64ISAR1, BF16, 44, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "ebf16")
+IDREG_FIELD_END(ID_AA64ISAR1, BF16)
+
+IDREG_FIELD_START(ID_AA64ISAR1, DGH, 48, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR1, DGH)
+
+IDREG_FIELD_START(ID_AA64ISAR1, I8MM, 52, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR1, I8MM)
+
+IDREG_FIELD_START(ID_AA64ISAR1, XS, 56, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR1, XS)
+
+IDREG_FIELD_START(ID_AA64ISAR1, LS64, 60, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "ls64")
+IDREG_FIELD_ARCH_VAL(0b0010, "ls64_v")
+IDREG_FIELD_ARCH_VAL(0b0011, "ls64_accdata")
+IDREG_FIELD_ARCH_VAL(0b0100, "ls64wb")
+IDREG_FIELD_END(ID_AA64ISAR1, LS64)
+
+IDREG_END(ID_AA64ISAR1_EL1)
+
+/* ID_AA64ISAR2_EL1 */
+IDREG_START(ID_AA64ISAR2_EL1)
+IDREG_FIELD_START(ID_AA64ISAR2, WFXT, 0, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0010, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, WFXT)
+
+IDREG_FIELD_START(ID_AA64ISAR2, RPRES, 4, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, RPRES)
+
+IDREG_FIELD_START(ID_AA64ISAR2, GPA3, 8, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, GPA3)
+
+IDREG_FIELD_START(ID_AA64ISAR2, APA3, 12, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "pauth")
+IDREG_FIELD_ARCH_VAL(0b0010, "epac")
+IDREG_FIELD_ARCH_VAL(0b0011, "pauth2")
+IDREG_FIELD_ARCH_VAL(0b0100, "fpac")
+IDREG_FIELD_ARCH_VAL(0b0101, "fpaccombine")
+IDREG_FIELD_ARCH_VAL(0b0110, "pauth_lr")
+IDREG_FIELD_END(ID_AA64ISAR2, APA3)
+
+IDREG_FIELD_START(ID_AA64ISAR2, MOPS, 16, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, MOPS)
+
+IDREG_FIELD_START(ID_AA64ISAR2, BC, 20, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, BC)
+
+IDREG_FIELD_START(ID_AA64ISAR2, PAC_FRAC, 24, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, PAC_FRAC)
+
+IDREG_FIELD_START(ID_AA64ISAR2, CLRBHB, 28, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, CLRBHB)
+
+IDREG_FIELD_START(ID_AA64ISAR2, SYSREG_128, 32, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, SYSREG_128)
+
+IDREG_FIELD_START(ID_AA64ISAR2, SYSINSTR_128, 36, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, SYSINSTR_128)
+
+IDREG_FIELD_START(ID_AA64ISAR2, PRFMSLC, 40, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, PRFMSLC)
+
+IDREG_FIELD_START(ID_AA64ISAR2, PCDPHINT, 44, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, PCDPHINT)
+
+IDREG_FIELD_START(ID_AA64ISAR2, RPRFM, 48, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, RPRFM)
+
+IDREG_FIELD_START(ID_AA64ISAR2, CSSC, 52, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "cmpbr")
+IDREG_FIELD_END(ID_AA64ISAR2, CSSC)
+
+IDREG_FIELD_START(ID_AA64ISAR2, LUT, 56, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, LUT)
+
+IDREG_FIELD_START(ID_AA64ISAR2, ATS1A, 60, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR2, ATS1A)
+
+IDREG_END(ID_AA64ISAR2_EL1)
+
+/* ID_AA64PFR0_EL1 */
+IDREG_START(ID_AA64PFR0_EL1)
+IDREG_FIELD_START(ID_AA64PFR0, EL0, 0, 4, LOWER, 0b0001)
+IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
+IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
+IDREG_FIELD_END(ID_AA64PFR0, EL0)
+
+IDREG_FIELD_START(ID_AA64PFR0, EL1, 4, 4, LOWER, 0b0001)
+IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
+IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
+IDREG_FIELD_END(ID_AA64PFR0, EL1)
+
+IDREG_FIELD_START(ID_AA64PFR0, EL2, 8, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
+IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
+IDREG_FIELD_END(ID_AA64PFR0, EL2)
+
+IDREG_FIELD_START(ID_AA64PFR0, EL3, 12, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
+IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
+IDREG_FIELD_END(ID_AA64PFR0, EL3)
+
+IDREG_FIELD_START(ID_AA64PFR0, FP, 16, 4, SIGNED_LOWER, 0b1111)
+IDREG_FIELD_ARCH_VAL(0b0000, "on")
+IDREG_FIELD_ARCH_VAL(0b0001, "fp16")
+IDREG_FIELD_ARCH_VAL(0b1111, "off")
+IDREG_FIELD_END(ID_AA64PFR0, FP)
+
+IDREG_FIELD_START(ID_AA64PFR0, ADVSIMD, 20, 4, SIGNED_LOWER, 0b1111)
+IDREG_FIELD_ARCH_VAL(0b0000, "on")
+IDREG_FIELD_ARCH_VAL(0b0001, "fp16")
+IDREG_FIELD_ARCH_VAL(0b1111, "off")
+IDREG_FIELD_END(ID_AA64PFR0, ADVSIMD)
+
+IDREG_FIELD_START(ID_AA64PFR0, GIC, 24, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0011, "v4p1")
+IDREG_FIELD_END(ID_AA64PFR0, GIC)
+
+IDREG_FIELD_START(ID_AA64PFR0, RAS, 28, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "v1p1")
+IDREG_FIELD_ARCH_VAL(0b0011, "v2")
+IDREG_FIELD_END(ID_AA64PFR0, RAS)
+
+IDREG_FIELD_START(ID_AA64PFR0, SVE, 32, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR0, SVE)
+
+IDREG_FIELD_START(ID_AA64PFR0, SEL2, 36, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR0, SEL2)
+
+IDREG_FIELD_START(ID_AA64PFR0, MPAM, 40, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "0")
+IDREG_FIELD_ARCH_VAL(0b0001, "1")
+IDREG_FIELD_END(ID_AA64PFR0, MPAM)
+
+IDREG_FIELD_START(ID_AA64PFR0, AMU, 44, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "v1p1")
+IDREG_FIELD_END(ID_AA64PFR0, AMU)
+
+IDREG_FIELD_START(ID_AA64PFR0, DIT, 48, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR0, DIT)
+
+IDREG_FIELD_START(ID_AA64PFR0, RME, 52, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR0, RME)
+
+IDREG_FIELD_START(ID_AA64PFR0, CSV2, 56, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "csv2_2")
+IDREG_FIELD_ARCH_VAL(0b0011, "csv2_3")
+IDREG_FIELD_END(ID_AA64PFR0, CSV2)
+
+IDREG_FIELD_START(ID_AA64PFR0, CSV3, 60, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR0, CSV3)
+
+IDREG_END(ID_AA64PFR0_EL1)
+
+/* ID_AA64PFR1_EL1 */
+IDREG_START(ID_AA64PFR1_EL1)
+IDREG_FIELD_START(ID_AA64PFR1, BT, 0, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR1, BT)
+
+IDREG_FIELD_START(ID_AA64PFR1, SSBS, 4, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "ssbs2")
+IDREG_FIELD_END(ID_AA64PFR1, SSBS)
+
+IDREG_FIELD_START(ID_AA64PFR1, MTE, 8, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "mte2")
+IDREG_FIELD_ARCH_VAL(0b0011, "mte3")
+IDREG_FIELD_END(ID_AA64PFR1, MTE)
+
+IDREG_FIELD_START(ID_AA64PFR1, RAS_FRAC, 12, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "rasv1p1")
+IDREG_FIELD_END(ID_AA64PFR1, RAS_FRAC)
+
+IDREG_FIELD_START(ID_AA64PFR1, MPAM_FRAC, 16, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "minor_0")
+IDREG_FIELD_ARCH_VAL(0b0001, "minor_1")
+IDREG_FIELD_END(ID_AA64PFR1, MPAM_FRAC)
+
+IDREG_FIELD_START(ID_AA64PFR1, RES0_20, 20, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64PFR1, RES0_20)
+
+IDREG_FIELD_START(ID_AA64PFR1, SME, 24, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "sme2")
+IDREG_FIELD_END(ID_AA64PFR1, SME)
+
+IDREG_FIELD_START(ID_AA64PFR1, RNDR_TRAP, 28, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR1, RNDR_TRAP)
+
+IDREG_FIELD_START(ID_AA64PFR1, CSV2_FRAC, 32, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "csv2_1p1")
+IDREG_FIELD_ARCH_VAL(0b0010, "csv2_1p2")
+IDREG_FIELD_END(ID_AA64PFR1, CSV2_FRAC)
+
+IDREG_FIELD_START(ID_AA64PFR1, NMI, 36, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR1, NMI)
+
+IDREG_FIELD_START(ID_AA64PFR1, MTE_FRAC, 40, 4, SIGNED_LOWER, 0b1111)
+IDREG_FIELD_ARCH_VAL(0b0000, "async")
+IDREG_FIELD_ARCH_VAL(0b1111, "off")
+IDREG_FIELD_END(ID_AA64PFR1, MTE_FRAC)
+
+IDREG_FIELD_START(ID_AA64PFR1, GCS, 44, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR1, GCS)
+
+IDREG_FIELD_START(ID_AA64PFR1, THE, 48, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR1, THE)
+
+IDREG_FIELD_START(ID_AA64PFR1, MTEX, 52, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "mte")
+IDREG_FIELD_ARCH_VAL(0b0001, "mte4")
+IDREG_FIELD_END(ID_AA64PFR1, MTEX)
+
+IDREG_FIELD_START(ID_AA64PFR1, DF2, 56, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR1, DF2)
+
+IDREG_FIELD_START(ID_AA64PFR1, PFAR, 60, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR1, PFAR)
+
+IDREG_END(ID_AA64PFR1_EL1)
+
+/* ID_AA64MMFR0_EL1 */
+IDREG_START(ID_AA64MMFR0_EL1)
+IDREG_FIELD_START(ID_AA64MMFR0, PARANGE, 0, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "32")
+IDREG_FIELD_ARCH_VAL(0b0001, "36")
+IDREG_FIELD_ARCH_VAL(0b0010, "40")
+IDREG_FIELD_ARCH_VAL(0b0011, "42")
+IDREG_FIELD_ARCH_VAL(0b0100, "44")
+IDREG_FIELD_ARCH_VAL(0b0101, "48")
+IDREG_FIELD_ARCH_VAL(0b0110, "52")
+IDREG_FIELD_ARCH_VAL(0b0111, "56")
+IDREG_FIELD_END(ID_AA64MMFR0, PARANGE)
+
+IDREG_FIELD_START(ID_AA64MMFR0, ASIDBITS, 4, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "8")
+IDREG_FIELD_ARCH_VAL(0b0010, "16")
+IDREG_FIELD_END(ID_AA64MMFR0, ASIDBITS)
+
+IDREG_FIELD_START(ID_AA64MMFR0, BIGEND, 8, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR0, BIGEND)
+
+IDREG_FIELD_START(ID_AA64MMFR0, SNSMEM, 12, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR0, SNSMEM)
+
+IDREG_FIELD_START(ID_AA64MMFR0, BIGENDEL0, 16, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR0, BIGENDEL0)
+
+IDREG_FIELD_START(ID_AA64MMFR0, TGRAN16, 20, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "52_bit")
+IDREG_FIELD_END(ID_AA64MMFR0, TGRAN16)
+
+IDREG_FIELD_START(ID_AA64MMFR0, TGRAN64, 24, 4, SIGNED_LOWER, 0b1111)
+IDREG_FIELD_ARCH_VAL(0b0000, "on")
+IDREG_FIELD_ARCH_VAL(0b1111, "off")
+IDREG_FIELD_END(ID_AA64MMFR0, TGRAN64)
+
+IDREG_FIELD_START(ID_AA64MMFR0, TGRAN4, 28, 4, SIGNED_LOWER, 0b1111)
+IDREG_FIELD_ARCH_VAL(0b0000, "on")
+IDREG_FIELD_ARCH_VAL(0b0001, "52_bit")
+IDREG_FIELD_ARCH_VAL(0b1111, "off")
+IDREG_FIELD_END(ID_AA64MMFR0, TGRAN4)
+
+IDREG_FIELD_START(ID_AA64MMFR0, TGRAN16_2, 32, 4, EXACT, 0b0001)
+IDREG_FIELD_ARCH_VAL(0b0000, "tgran16")
+IDREG_FIELD_ARCH_VAL(0b0001, "off")
+IDREG_FIELD_ARCH_VAL(0b0010, "on")
+IDREG_FIELD_ARCH_VAL(0b0011, "52_bit")
+IDREG_FIELD_END(ID_AA64MMFR0, TGRAN16_2)
+
+IDREG_FIELD_START(ID_AA64MMFR0, TGRAN64_2, 36, 4, EXACT, 0b0001)
+IDREG_FIELD_ARCH_VAL(0b0000, "tgran64")
+IDREG_FIELD_ARCH_VAL(0b0001, "off")
+IDREG_FIELD_ARCH_VAL(0b0010, "on")
+IDREG_FIELD_END(ID_AA64MMFR0, TGRAN64_2)
+
+IDREG_FIELD_START(ID_AA64MMFR0, TGRAN4_2, 40, 4, EXACT, 0b0001)
+IDREG_FIELD_ARCH_VAL(0b0000, "tgran4")
+IDREG_FIELD_ARCH_VAL(0b0001, "off")
+IDREG_FIELD_ARCH_VAL(0b0010, "on")
+IDREG_FIELD_ARCH_VAL(0b0011, "52_bit")
+IDREG_FIELD_END(ID_AA64MMFR0, TGRAN4_2)
+
+IDREG_FIELD_START(ID_AA64MMFR0, EXS, 44, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR0, EXS)
+
+IDREG_FIELD_START(ID_AA64MMFR0, RES0_48, 48, 8, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64MMFR0, RES0_48)
+
+IDREG_FIELD_START(ID_AA64MMFR0, FGT, 56, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "fgt2")
+IDREG_FIELD_END(ID_AA64MMFR0, FGT)
+
+IDREG_FIELD_START(ID_AA64MMFR0, ECV, 60, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "cntpoff")
+IDREG_FIELD_END(ID_AA64MMFR0, ECV)
+
+IDREG_END(ID_AA64MMFR0_EL1)
+
+/* ID_AA64MMFR1_EL1 */
+IDREG_START(ID_AA64MMFR1_EL1)
+IDREG_FIELD_START(ID_AA64MMFR1, HAFDBS, 0, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "af")
+IDREG_FIELD_ARCH_VAL(0b0010, "dbm")
+IDREG_FIELD_ARCH_VAL(0b0011, "haft")
+IDREG_FIELD_ARCH_VAL(0b0100, "hdbss")
+IDREG_FIELD_END(ID_AA64MMFR1, HAFDBS)
+
+IDREG_FIELD_START(ID_AA64MMFR1, VMIDBITS, 4, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "8")
+IDREG_FIELD_ARCH_VAL(0b0010, "16")
+IDREG_FIELD_END(ID_AA64MMFR1, VMIDBITS)
+
+IDREG_FIELD_START(ID_AA64MMFR1, VH, 8, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR1, VH)
+
+IDREG_FIELD_START(ID_AA64MMFR1, HPDS, 12, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "hpds2")
+IDREG_FIELD_END(ID_AA64MMFR1, HPDS)
+
+IDREG_FIELD_START(ID_AA64MMFR1, LO, 16, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR1, LO)
+
+IDREG_FIELD_START(ID_AA64MMFR1, PAN, 20, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "pan2")
+IDREG_FIELD_ARCH_VAL(0b0011, "pan3")
+IDREG_FIELD_END(ID_AA64MMFR1, PAN)
+
+IDREG_FIELD_START(ID_AA64MMFR1, SPECSEI, 24, 4, HIGHER, 0b0001)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR1, SPECSEI)
+
+IDREG_FIELD_START(ID_AA64MMFR1, XNX, 28, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR1, XNX)
+
+IDREG_FIELD_START(ID_AA64MMFR1, TWED, 32, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR1, TWED)
+
+IDREG_FIELD_START(ID_AA64MMFR1, ETS, 36, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "ets2")
+IDREG_FIELD_ARCH_VAL(0b0011, "ets3")
+IDREG_FIELD_END(ID_AA64MMFR1, ETS)
+
+IDREG_FIELD_START(ID_AA64MMFR1, HCX, 40, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR1, HCX)
+
+IDREG_FIELD_START(ID_AA64MMFR1, AFP, 44, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR1, AFP)
+
+IDREG_FIELD_START(ID_AA64MMFR1, NTLBPA, 48, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR1, NTLBPA)
+
+IDREG_FIELD_START(ID_AA64MMFR1, TIDCP1, 52, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR1, TIDCP1)
+
+IDREG_FIELD_START(ID_AA64MMFR1, CMOW, 56, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR1, CMOW)
+
+IDREG_FIELD_START(ID_AA64MMFR1, ECBHB, 60, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR1, ECBHB)
+
+IDREG_END(ID_AA64MMFR1_EL1)
+
+/* ID_AA64MMFR2_EL1 */
+IDREG_START(ID_AA64MMFR2_EL1)
+IDREG_FIELD_START(ID_AA64MMFR2, CNP, 0, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR2, CNP)
+
+IDREG_FIELD_START(ID_AA64MMFR2, UAO, 4, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR2, UAO)
+
+IDREG_FIELD_START(ID_AA64MMFR2, LSM, 8, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR2, LSM)
+
+IDREG_FIELD_START(ID_AA64MMFR2, IESB, 12, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR2, IESB)
+
+IDREG_FIELD_START(ID_AA64MMFR2, VARANGE, 16, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "48")
+IDREG_FIELD_ARCH_VAL(0b0001, "52")
+IDREG_FIELD_END(ID_AA64MMFR2, VARANGE)
+
+IDREG_FIELD_START(ID_AA64MMFR2, CCIDX, 20, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "32")
+IDREG_FIELD_ARCH_VAL(0b0001, "64")
+IDREG_FIELD_END(ID_AA64MMFR2, CCIDX)
+
+IDREG_FIELD_START(ID_AA64MMFR2, NV, 24, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "nv2")
+IDREG_FIELD_END(ID_AA64MMFR2, NV)
+
+IDREG_FIELD_START(ID_AA64MMFR2, ST, 28, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "39")
+IDREG_FIELD_ARCH_VAL(0b0001, "48_47")
+IDREG_FIELD_END(ID_AA64MMFR2, ST)
+
+IDREG_FIELD_START(ID_AA64MMFR2, AT, 32, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR2, AT)
+
+IDREG_FIELD_START(ID_AA64MMFR2, IDS, 36, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "0x0")
+IDREG_FIELD_ARCH_VAL(0b0001, "0x18")
+IDREG_FIELD_END(ID_AA64MMFR2, IDS)
+
+IDREG_FIELD_START(ID_AA64MMFR2, FWB, 40, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR2, FWB)
+
+IDREG_FIELD_START(ID_AA64MMFR2, RES0_44, 44, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64MMFR2, RES0_44)
+
+IDREG_FIELD_START(ID_AA64MMFR2, TTL, 48, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR2, TTL)
+
+IDREG_FIELD_START(ID_AA64MMFR2, BBM, 52, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "0")
+IDREG_FIELD_ARCH_VAL(0b0001, "1")
+IDREG_FIELD_ARCH_VAL(0b0010, "2")
+IDREG_FIELD_END(ID_AA64MMFR2, BBM)
+
+IDREG_FIELD_START(ID_AA64MMFR2, EVT, 56, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "ttlbxs")
+IDREG_FIELD_END(ID_AA64MMFR2, EVT)
+
+IDREG_FIELD_START(ID_AA64MMFR2, E0PD, 60, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR2, E0PD)
+
+IDREG_END(ID_AA64MMFR2_EL1)
+
+/* ID_AA64MMFR3_EL1 */
+IDREG_START(ID_AA64MMFR3_EL1)
+IDREG_FIELD_START(ID_AA64MMFR3, TCRX, 0, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR3, TCRX)
+
+IDREG_FIELD_START(ID_AA64MMFR3, SCTLRX, 4, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR3, SCTLRX)
+
+IDREG_FIELD_START(ID_AA64MMFR3, S1PIE, 8, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR3, S1PIE)
+
+IDREG_FIELD_START(ID_AA64MMFR3, S2PIE, 12, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR3, S2PIE)
+
+IDREG_FIELD_START(ID_AA64MMFR3, S1POE, 16, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR3, S1POE)
+
+IDREG_FIELD_START(ID_AA64MMFR3, S2POE, 20, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR3, S2POE)
+
+IDREG_FIELD_START(ID_AA64MMFR3, AIE, 24, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR3, AIE)
+
+IDREG_FIELD_START(ID_AA64MMFR3, MEC, 28, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR3, MEC)
+
+IDREG_FIELD_START(ID_AA64MMFR3, D128, 32, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR3, D128)
+
+IDREG_FIELD_START(ID_AA64MMFR3, D128_2, 36, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR3, D128_2)
+
+IDREG_FIELD_START(ID_AA64MMFR3, SNERR, 40, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "sync")
+IDREG_FIELD_ARCH_VAL(0b0010, "ANERR")
+IDREG_FIELD_ARCH_VAL(0b0011, "ANERR_IND")
+IDREG_FIELD_END(ID_AA64MMFR3, SNERR)
+
+IDREG_FIELD_START(ID_AA64MMFR3, ANERR, 44, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "async")
+IDREG_FIELD_ARCH_VAL(0b0010, "ANERR")
+IDREG_FIELD_ARCH_VAL(0b0011, "ANERR_IND")
+IDREG_FIELD_END(ID_AA64MMFR3, ANERR)
+
+IDREG_FIELD_START(ID_AA64MMFR3, RES0_48, 48, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64MMFR3, RES0_48)
+
+IDREG_FIELD_START(ID_AA64MMFR3, SDERR, 52, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "dev_sync")
+IDREG_FIELD_ARCH_VAL(0b0010, "ADERR")
+IDREG_FIELD_ARCH_VAL(0b0011, "ADERR_IND")
+IDREG_FIELD_END(ID_AA64MMFR3, SDERR)
+
+IDREG_FIELD_START(ID_AA64MMFR3, ADERR, 56, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "dev_async")
+IDREG_FIELD_ARCH_VAL(0b0010, "ADERR")
+IDREG_FIELD_ARCH_VAL(0b0011, "ADERR_IND")
+IDREG_FIELD_END(ID_AA64MMFR3, ADERR)
+
+IDREG_FIELD_START(ID_AA64MMFR3, SPEC_FPACC, 60, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR3, SPEC_FPACC)
+
+IDREG_END(ID_AA64MMFR3_EL1)
+
+/* ID_AA64DFR0_EL1 */
+IDREG_START(ID_AA64DFR0_EL1)
+IDREG_FIELD_START(ID_AA64DFR0, DEBUGVER, 0, 4, LOWER, 0x6)
+IDREG_FIELD_ARCH_VAL(0b0110, "on")
+IDREG_FIELD_ARCH_VAL(0b0111, "vhe")
+IDREG_FIELD_ARCH_VAL(0b1000, "v8p2")
+IDREG_FIELD_ARCH_VAL(0b1001, "v8p4")
+IDREG_FIELD_ARCH_VAL(0b1010, "v8p8")
+IDREG_FIELD_ARCH_VAL(0b1011, "v8p9")
+IDREG_FIELD_END(ID_AA64DFR0, DEBUGVER)
+
+IDREG_FIELD_START(ID_AA64DFR0, TRACEVER, 4, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64DFR0, TRACEVER)
+
+IDREG_FIELD_START(ID_AA64DFR0, PMUVER, 8, 4, SIGNED_LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0100, "v3p1")
+IDREG_FIELD_ARCH_VAL(0b0101, "v3p4")
+IDREG_FIELD_ARCH_VAL(0b0110, "v3p5")
+IDREG_FIELD_ARCH_VAL(0b0111, "v3p7")
+IDREG_FIELD_ARCH_VAL(0b1000, "v3p8")
+IDREG_FIELD_ARCH_VAL(0b1001, "v3p9")
+IDREG_FIELD_ARCH_VAL(0b1111, "imp_def")
+IDREG_FIELD_END(ID_AA64DFR0, PMUVER)
+
+IDREG_FIELD_START(ID_AA64DFR0, BRPS, 12, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(ID_AA64DFR0, BRPS)
+
+IDREG_FIELD_START(ID_AA64DFR0, PMSS, 16, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64DFR0, PMSS)
+
+IDREG_FIELD_START(ID_AA64DFR0, WRPS, 20, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(ID_AA64DFR0, WRPS)
+
+IDREG_FIELD_START(ID_AA64DFR0, SEBEP, 24, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64DFR0, SEBEP)
+
+IDREG_FIELD_START(ID_AA64DFR0, CTX_CMPS, 28, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(ID_AA64DFR0, CTX_CMPS)
+
+IDREG_FIELD_START(ID_AA64DFR0, PMSVER, 32, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "v1p1")
+IDREG_FIELD_ARCH_VAL(0b0011, "v1p2")
+IDREG_FIELD_ARCH_VAL(0b0100, "v1p3")
+IDREG_FIELD_ARCH_VAL(0b0101, "v1p4")
+IDREG_FIELD_ARCH_VAL(0b0110, "v1p5")
+IDREG_FIELD_END(ID_AA64DFR0, PMSVER)
+
+IDREG_FIELD_START(ID_AA64DFR0, DOUBLELOCK, 36, 4, SIGNED_LOWER, 0b1111)
+IDREG_FIELD_ARCH_VAL(0b0000, "on")
+IDREG_FIELD_ARCH_VAL(0b1111, "off")
+IDREG_FIELD_END(ID_AA64DFR0, DOUBLELOCK)
+
+IDREG_FIELD_START(ID_AA64DFR0, TRACEFILT, 40, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64DFR0, TRACEFILT)
+
+IDREG_FIELD_START(ID_AA64DFR0, TRACEBUFFER, 44, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "trbe_v1p1")
+IDREG_FIELD_END(ID_AA64DFR0, TRACEBUFFER)
+
+IDREG_FIELD_START(ID_AA64DFR0, MTPMU, 48, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "ni_impdef")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b1111, "off")
+IDREG_FIELD_END(ID_AA64DFR0, MTPMU)
+
+IDREG_FIELD_START(ID_AA64DFR0, BRBE, 52, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "brbe_v1p1")
+IDREG_FIELD_END(ID_AA64DFR0, BRBE)
+
+IDREG_FIELD_START(ID_AA64DFR0, EXTTRCBUFF, 56, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64DFR0, EXTTRCBUFF)
+
+IDREG_FIELD_START(ID_AA64DFR0, HPMN0, 60, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "unpredictable")
+IDREG_FIELD_ARCH_VAL(0b0001, "def")
+IDREG_FIELD_END(ID_AA64DFR0, HPMN0)
+
+IDREG_END(ID_AA64DFR0_EL1)
+
+/* ID_AA64ZFR0_EL1 */
+IDREG_START(ID_AA64ZFR0_EL1)
+IDREG_FIELD_START(ID_AA64ZFR0, SVEVER, 0, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "on")
+IDREG_FIELD_ARCH_VAL(0b0001, "sve2")
+IDREG_FIELD_ARCH_VAL(0b0010, "sve2p1")
+IDREG_FIELD_ARCH_VAL(0b0011, "sve2p2")
+IDREG_FIELD_END(ID_AA64ZFR0, SVEVER)
+
+IDREG_FIELD_START(ID_AA64ZFR0, AES, 4, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "pmull128")
+IDREG_FIELD_ARCH_VAL(0b0011, "aes2")
+IDREG_FIELD_END(ID_AA64ZFR0, AES)
+
+IDREG_FIELD_START(ID_AA64ZFR0, RES0_8, 8, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64ZFR0, RES0_8)
+
+IDREG_FIELD_START(ID_AA64ZFR0, ELTPERM, 12, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ZFR0, ELTPERM)
+
+IDREG_FIELD_START(ID_AA64ZFR0, BITPERM, 16, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ZFR0, BITPERM)
+
+IDREG_FIELD_START(ID_AA64ZFR0, BFLOAT16, 20, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "ebf16")
+IDREG_FIELD_END(ID_AA64ZFR0, BFLOAT16)
+
+IDREG_FIELD_START(ID_AA64ZFR0, B16B16, 24, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "bfscale")
+IDREG_FIELD_END(ID_AA64ZFR0, B16B16)
+
+IDREG_FIELD_START(ID_AA64ZFR0, RES0_28, 28, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64ZFR0, RES0_28)
+
+IDREG_FIELD_START(ID_AA64ZFR0, SHA3, 32, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ZFR0, SHA3)
+
+IDREG_FIELD_START(ID_AA64ZFR0, RES0_36, 36, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64ZFR0, RES0_36)
+
+IDREG_FIELD_START(ID_AA64ZFR0, SM4, 40, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ZFR0, SM4)
+
+IDREG_FIELD_START(ID_AA64ZFR0, I8MM, 44, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ZFR0, I8MM)
+
+IDREG_FIELD_START(ID_AA64ZFR0, F16MM, 48, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ZFR0, F16MM)
+
+IDREG_FIELD_START(ID_AA64ZFR0, F32MM, 52, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ZFR0, F32MM)
+
+IDREG_FIELD_START(ID_AA64ZFR0, F64MM, 56, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ZFR0, F64MM)
+
+IDREG_FIELD_START(ID_AA64ZFR0, RES0_60, 60, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64ZFR0, RES0_60)
+
+IDREG_END(ID_AA64ZFR0_EL1)
+
+/* ID_AA64SMFR0_EL1 */
+IDREG_START(ID_AA64SMFR0_EL1)
+IDREG_FIELD_START(ID_AA64SMFR0, SMOP4, 0, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, SMOP4)
+
+IDREG_FIELD_START(ID_AA64SMFR0, RES0_1, 1, 15, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64SMFR0, RES0_1)
+
+IDREG_FIELD_START(ID_AA64SMFR0, STMOP, 16, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, STMOP)
+
+IDREG_FIELD_START(ID_AA64SMFR0, RES0_17, 17, 6, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64SMFR0, RES0_17)
+
+IDREG_FIELD_START(ID_AA64SMFR0, SFEXPA, 23, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, SFEXPA)
+
+IDREG_FIELD_START(ID_AA64SMFR0, AES, 24, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, AES)
+
+IDREG_FIELD_START(ID_AA64SMFR0, SBITPERM, 25, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, SBITPERM)
+
+IDREG_FIELD_START(ID_AA64SMFR0, RES0_26, 26, 2, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64SMFR0, RES0_26)
+
+IDREG_FIELD_START(ID_AA64SMFR0, SF8DP2, 28, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, SF8DP2)
+
+IDREG_FIELD_START(ID_AA64SMFR0, SF8DP4, 29, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, SF8DP4)
+
+IDREG_FIELD_START(ID_AA64SMFR0, SF8FMA, 30, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, SF8FMA)
+
+IDREG_FIELD_START(ID_AA64SMFR0, RES0_31, 31, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64SMFR0, RES0_31)
+
+IDREG_FIELD_START(ID_AA64SMFR0, F32F32, 32, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, F32F32)
+
+IDREG_FIELD_START(ID_AA64SMFR0, BI32I32, 33, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, BI32I32)
+
+IDREG_FIELD_START(ID_AA64SMFR0, B16F32, 34, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, B16F32)
+
+IDREG_FIELD_START(ID_AA64SMFR0, F16F32, 35, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, F16F32)
+
+IDREG_FIELD_START(ID_AA64SMFR0, I8I32, 36, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b1111, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, I8I32)
+
+IDREG_FIELD_START(ID_AA64SMFR0, F8F32, 40, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, F8F32)
+
+IDREG_FIELD_START(ID_AA64SMFR0, F8F16, 41, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, F8F16)
+
+IDREG_FIELD_START(ID_AA64SMFR0, F16F16, 42, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, F16F16)
+
+IDREG_FIELD_START(ID_AA64SMFR0, B16B16, 43, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, B16B16)
+
+IDREG_FIELD_START(ID_AA64SMFR0, I16I32, 44, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0101, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, I16I32)
+
+IDREG_FIELD_START(ID_AA64SMFR0, F64F64, 48, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, F64F64)
+
+IDREG_FIELD_START(ID_AA64SMFR0, RES0_49, 49, 3, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64SMFR0, RES0_49)
+
+IDREG_FIELD_START(ID_AA64SMFR0, I16I64, 52, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b1111, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, I16I64)
+
+IDREG_FIELD_START(ID_AA64SMFR0, SMEVER, 56, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "sme")
+IDREG_FIELD_ARCH_VAL(0b0001, "sme2")
+IDREG_FIELD_ARCH_VAL(0b0010, "sme2p1")
+IDREG_FIELD_ARCH_VAL(0b0011, "sme2p2")
+IDREG_FIELD_END(ID_AA64SMFR0, SMEVER)
+
+IDREG_FIELD_START(ID_AA64SMFR0, LUTV2, 60, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, LUTV2)
+
+IDREG_FIELD_START(ID_AA64SMFR0, RES0_61, 61, 2, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64SMFR0, RES0_61)
+
+IDREG_FIELD_START(ID_AA64SMFR0, FA64, 63, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64SMFR0, FA64)
+
+IDREG_END(ID_AA64SMFR0_EL1)
+
+/* CTR_EL0 */
+IDREG_START(CTR_EL0)
+IDREG_FIELD_START(CTR_EL0, IMINLINE, 0, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(CTR_EL0, IMINLINE)
+
+IDREG_FIELD_START(CTR_EL0, RES0_4, 4, 10, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(CTR_EL0, RES0_4)
+
+IDREG_FIELD_START(CTR_EL0, L1IP, 14, 2, EXACT, 0b10)
+IDREG_FIELD_ARCH_VAL(0b00, "reserved_vpipt")
+IDREG_FIELD_ARCH_VAL(0b01, "reserved_aivivt")
+IDREG_FIELD_ARCH_VAL(0b10, "vipt")
+IDREG_FIELD_ARCH_VAL(0b11, "pipt")
+IDREG_FIELD_END(CTR_EL0, L1IP)
+
+IDREG_FIELD_START(CTR_EL0, DMINLINE, 16, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(CTR_EL0, DMINLINE)
+
+IDREG_FIELD_START(CTR_EL0, ERG, 20, 4, HIGHER_OR_ZERO, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(CTR_EL0, ERG)
+
+IDREG_FIELD_START(CTR_EL0, CWG, 24, 4, HIGHER_OR_ZERO, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(CTR_EL0, CWG)
+
+IDREG_FIELD_START(CTR_EL0, IDC, 28, 1, LOWER, 0b1)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(CTR_EL0, IDC)
+
+IDREG_FIELD_START(CTR_EL0, DIC, 29, 1, LOWER, 0b1)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(CTR_EL0, DIC)
+
+IDREG_FIELD_START(CTR_EL0, RES0_30, 30, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(CTR_EL0, RES0_30)
+
+IDREG_FIELD_START(CTR_EL0, RES1_31, 31, 1, EXACT, 1)
+IDREG_FIELD_ARCH_VAL(1, NULL)
+IDREG_FIELD_END(CTR_EL0, RES1_31)
+
+IDREG_FIELD_START(CTR_EL0, TMINLINE, 32, 6, EXACT, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(CTR_EL0, TMINLINE)
+
+IDREG_FIELD_START(CTR_EL0, RES0_38, 38, 26, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(CTR_EL0, RES0_38)
+
+IDREG_END(CTR_EL0)
+
+/* ID_AA64ISAR3_EL1 */
+IDREG_START(ID_AA64ISAR3_EL1)
+IDREG_FIELD_START(ID_AA64ISAR3, CPA, 0, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "cpa2")
+IDREG_FIELD_END(ID_AA64ISAR3, CPA)
+
+IDREG_FIELD_START(ID_AA64ISAR3, FAMINMAX, 4, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR3, FAMINMAX)
+
+IDREG_FIELD_START(ID_AA64ISAR3, TLBIW, 8, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR3, TLBIW)
+
+IDREG_FIELD_START(ID_AA64ISAR3, PACM, 12, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "trivial_imp")
+IDREG_FIELD_ARCH_VAL(0b0010, "full_imp")
+IDREG_FIELD_END(ID_AA64ISAR3, PACM)
+
+IDREG_FIELD_START(ID_AA64ISAR3, LSFE, 16, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR3, LSFE)
+
+IDREG_FIELD_START(ID_AA64ISAR3, OCCMO, 20, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR3, OCCMO)
+
+IDREG_FIELD_START(ID_AA64ISAR3, LSUI, 24, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR3, LSUI)
+
+IDREG_FIELD_START(ID_AA64ISAR3, FPRCVT, 28, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64ISAR3, FPRCVT)
+
+IDREG_FIELD_START(ID_AA64ISAR3, RES0_32, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64ISAR3, RES0_32)
+
+IDREG_END(ID_AA64ISAR3_EL1)
+
+/* ID_AA64PFR2_EL1 */
+IDREG_START(ID_AA64PFR2_EL1)
+IDREG_FIELD_START(ID_AA64PFR2, MTEPERM, 0, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR2, MTEPERM)
+
+IDREG_FIELD_START(ID_AA64PFR2, MTESTOREONLY, 4, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR2, MTESTOREONLY)
+
+IDREG_FIELD_START(ID_AA64PFR2, MTEFAR, 8, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR2, MTEFAR)
+
+IDREG_FIELD_START(ID_AA64PFR2, GCIE, 12, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR2, GCIE)
+
+IDREG_FIELD_START(ID_AA64PFR2, UINJ, 16, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR2, UINJ)
+
+IDREG_FIELD_START(ID_AA64PFR2, RES0_20, 20, 12, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64PFR2, RES0_20)
+
+IDREG_FIELD_START(ID_AA64PFR2, FPMR, 32, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64PFR2, FPMR)
+
+IDREG_FIELD_START(ID_AA64PFR2, RES0_36, 36, 28, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64PFR2, RES0_36)
+
+IDREG_END(ID_AA64PFR2_EL1)
+
+/* ID_AA64FPFR0_EL1 */
+IDREG_START(ID_AA64FPFR0_EL1)
+IDREG_FIELD_START(ID_AA64FPFR0, F8E5M2, 0, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64FPFR0, F8E5M2)
+
+IDREG_FIELD_START(ID_AA64FPFR0, F8E4M3, 1, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64FPFR0, F8E4M3)
+
+IDREG_FIELD_START(ID_AA64FPFR0, RES0_2, 2, 24, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64FPFR0, RES0_2)
+
+IDREG_FIELD_START(ID_AA64FPFR0, F8MM4, 26, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64FPFR0, F8MM4)
+
+IDREG_FIELD_START(ID_AA64FPFR0, F8MM8, 27, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64FPFR0, F8MM8)
+
+IDREG_FIELD_START(ID_AA64FPFR0, F8DP2, 28, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64FPFR0, F8DP2)
+
+IDREG_FIELD_START(ID_AA64FPFR0, F8DP4, 29, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64FPFR0, F8DP4)
+
+IDREG_FIELD_START(ID_AA64FPFR0, F8FMA, 30, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64FPFR0, F8FMA)
+
+IDREG_FIELD_START(ID_AA64FPFR0, F8CVT, 31, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0, "off")
+IDREG_FIELD_ARCH_VAL(0b1, "on")
+IDREG_FIELD_END(ID_AA64FPFR0, F8CVT)
+
+IDREG_FIELD_START(ID_AA64FPFR0, RES0_32, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64FPFR0, RES0_32)
+
+IDREG_END(ID_AA64FPFR0_EL1)
+
+
+/* ID_AA64MMFR4_EL1 */
+IDREG_START(ID_AA64MMFR4_EL1)
+IDREG_FIELD_START(ID_AA64MMFR4, POPS, 0, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR4, POPS)
+
+IDREG_FIELD_START(ID_AA64MMFR4, EIESB, 4, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "toel3")
+IDREG_FIELD_ARCH_VAL(0b0010, "toelx")
+IDREG_FIELD_ARCH_VAL(0b1111, "any")
+IDREG_FIELD_END(ID_AA64MMFR4, EIESB)
+
+IDREG_FIELD_START(ID_AA64MMFR4, ASID2, 8, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR4, ASID2)
+
+IDREG_FIELD_START(ID_AA64MMFR4, HACDBS, 12, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR4, HACDBS)
+
+IDREG_FIELD_START(ID_AA64MMFR4, FGWTE3, 16, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR4, FGWTE3)
+
+IDREG_FIELD_START(ID_AA64MMFR4, NV_FRAC, 20, 4, LOWER, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "nv_nv2")
+IDREG_FIELD_ARCH_VAL(0b0001, "nv2_only")
+IDREG_FIELD_ARCH_VAL(0b0010, "nv2p1")
+IDREG_FIELD_END(ID_AA64MMFR4, NV_FRAC)
+
+IDREG_FIELD_START(ID_AA64MMFR4, E2H0, 24, 4, SIGNED_LOWER, 0b1111)
+IDREG_FIELD_ARCH_VAL(0b0000, "on")
+IDREG_FIELD_ARCH_VAL(0b1110, "ni_nv1")
+IDREG_FIELD_ARCH_VAL(0b1111, "off")
+IDREG_FIELD_END(ID_AA64MMFR4, E2H0)
+
+IDREG_FIELD_START(ID_AA64MMFR4, RMEGDI, 28, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR4, RMEGDI)
+
+IDREG_FIELD_START(ID_AA64MMFR4, RES0_32, 32, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64MMFR4, RES0_32)
+
+IDREG_FIELD_START(ID_AA64MMFR4, E3DSE, 36, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR4, E3DSE)
+
+IDREG_FIELD_START(ID_AA64MMFR4, RES0_40, 40, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64MMFR4, RES0_40)
+
+IDREG_FIELD_START(ID_AA64MMFR4, SRMASK, 44, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64MMFR4, SRMASK)
+
+IDREG_FIELD_START(ID_AA64MMFR4, RES0_48, 48, 16, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AA64MMFR4, RES0_48)
+
+IDREG_END(ID_AA64MMFR4_EL1)
+
+/* ID_AA64DFR1_EL1 */
+IDREG_START(ID_AA64DFR1_EL1)
+IDREG_FIELD_START(ID_AA64DFR1, SYSPMUID, 0, 8, EXACT, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(ID_AA64DFR1, SYSPMUID)
+
+IDREG_FIELD_START(ID_AA64DFR1, BRPS, 8, 8, EXACT, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(ID_AA64DFR1, BRPS)
+
+IDREG_FIELD_START(ID_AA64DFR1, WRPS, 16, 8, EXACT, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(ID_AA64DFR1, WRPS)
+
+IDREG_FIELD_START(ID_AA64DFR1, CTX_CMPS, 24, 8, EXACT, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(ID_AA64DFR1, CTX_CMPS)
+
+IDREG_FIELD_START(ID_AA64DFR1, SPMU, 32, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_ARCH_VAL(0b0010, "imp_spmzr")
+IDREG_FIELD_END(ID_AA64DFR1, SPMU)
+
+IDREG_FIELD_START(ID_AA64DFR1, PMICNTR, 36, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64DFR1, PMICNTR)
+
+IDREG_FIELD_START(ID_AA64DFR1, ABLE, 40, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64DFR1, ABLE)
+
+IDREG_FIELD_START(ID_AA64DFR1, ITE, 44, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64DFR1, ITE)
+
+IDREG_FIELD_START(ID_AA64DFR1, EBEP, 48, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "on")
+IDREG_FIELD_END(ID_AA64DFR1, EBEP)
+
+IDREG_FIELD_START(ID_AA64DFR1, DPFZS, 52, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "ignr")
+IDREG_FIELD_ARCH_VAL(0b0001, "frzn")
+IDREG_FIELD_END(ID_AA64DFR1, DPFZS)
+
+IDREG_FIELD_START(ID_AA64DFR1, ABL_CMPS, 56, 8, EXACT, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(ID_AA64DFR1, ABL_CMPS)
+
+IDREG_END(ID_AA64DFR1_EL1)
+
+/* MIDR_EL1 */
+IDREG_START(MIDR_EL1)
+IDREG_FIELD_START(MIDR, REVISION, 0, 4, ANY, 0)
+IDREG_FIELD_END(MIDR, REVISION)
+
+IDREG_FIELD_START(MIDR, PARTNUM, 4, 12, ANY, 0)
+IDREG_FIELD_END(MIDR, PARTNUM)
+
+IDREG_FIELD_START(MIDR, ARCHITECTURE, 16, 4, ANY, 0)
+IDREG_FIELD_END(MIDR, ARCHITECTURE)
+
+IDREG_FIELD_START(MIDR, VARIANT, 20, 4, ANY, 0)
+IDREG_FIELD_END(MIDR, VARIANT)
+
+IDREG_FIELD_START(MIDR, IMPLEMENTER, 24, 8, ANY, 0)
+IDREG_FIELD_END(MIDR, IMPLEMENTER)
+
+IDREG_FIELD_START(MIDR, RES0_32, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(MIDR, RES0_32)
+
+IDREG_END(MIDR_EL1)
+
+/* REVIDR_EL1 */
+IDREG_START(REVIDR_EL1)
+IDREG_FIELD_START(REVIDR, VAL, 0, 64, ANY, 0)
+IDREG_FIELD_END(REVIDR, VAL)
+
+IDREG_END(REVIDR_EL1)
+
+/* AIDR_EL1 */
+IDREG_START(AIDR_EL1)
+IDREG_FIELD_START(AIDR, VAL, 0, 64, ANY, 0)
+IDREG_FIELD_END(AIDR, VAL)
+
+IDREG_END(AIDR_EL1)
+
+/* DCZID_EL0 */
+IDREG_START(DCZID_EL0)
+IDREG_FIELD_START(DCZID_EL0, BS, 0, 4, EXACT, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(DCZID_EL0, BS)
+
+IDREG_FIELD_START(DCZID_EL0, DZP, 4, 1, EXACT, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(DCZID_EL0, DZP)
+
+IDREG_FIELD_START(DCZID_EL0, RES0_5, 5, 59, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(DCZID_EL0, RES0_5)
+
+IDREG_END(DCZID_EL0)
+
+
+/* ID_AA64AFR0_EL1 */
+IDREG_START(ID_AA64AFR0_EL1)
+IDREG_FIELD_START(ID_AA64AFR0, VAL, 0, 64, EXACT, 0)
+IDREG_FIELD_END(ID_AA64AFR0, VAL)
+
+IDREG_END(ID_AA64AFR0_EL1)
+
+/* ID_AA64AFR1_EL1 */
+IDREG_START(ID_AA64AFR1_EL1)
+IDREG_FIELD_START(ID_AA64AFR1, VAL, 0, 64, EXACT, 0)
+IDREG_FIELD_END(ID_AA64AFR1, VAL)
+
+IDREG_END(ID_AA64AFR1_EL1)
+
+/* AArch32 ID registers */
+
+/* ID_PFR0_EL1 */
+IDREG_START(ID_PFR0_EL1)
+IDREG_FIELD_START(ID_PFR0, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_PFR0, VAL)
+
+IDREG_FIELD_START(ID_PFR0, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_PFR0, RES0_HI)
+
+IDREG_END(ID_PFR0_EL1)
+
+/* ID_PFR1_EL1 */
+IDREG_START(ID_PFR1_EL1)
+IDREG_FIELD_START(ID_PFR1, VAL_LO, 0, 28, ANY, 0)
+IDREG_FIELD_END(ID_PFR1, VAL_LO)
+
+IDREG_FIELD_START(ID_PFR1, GIC, 28, 4, ANY, 0)
+IDREG_FIELD_ARCH_VAL(0b0000, "off")
+IDREG_FIELD_ARCH_VAL(0b0001, "gicv3")
+IDREG_FIELD_ARCH_VAL(0b0011, "gicv4p1")
+IDREG_FIELD_END(ID_PFR1, GIC)
+
+IDREG_FIELD_START(ID_PFR1, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_PFR1, RES0_HI)
+
+IDREG_END(ID_PFR1_EL1)
+
+/* ID_DFR0_EL1 */
+IDREG_START(ID_DFR0_EL1)
+IDREG_FIELD_START(ID_DFR0, COPDBG, 0, 4, ANY, 0)
+IDREG_FIELD_END(ID_DFR0, COPDBG)
+
+IDREG_FIELD_START(ID_DFR0, VAL_LO, 4, 20, ANY, 0)
+IDREG_FIELD_END(ID_DFR0, VAL_LO)
+
+IDREG_FIELD_START(ID_DFR0, PMU, 24, 4, ANY, 0)
+IDREG_FIELD_END(ID_DFR0, PMU)
+
+IDREG_FIELD_START(ID_DFR0, VAL_HI, 28, 4, ANY, 0)
+IDREG_FIELD_END(ID_DFR0, VAL_HI)
+
+IDREG_FIELD_START(ID_DFR0, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_DFR0, RES0_HI)
+
+IDREG_END(ID_DFR0_EL1)
+
+/* ID_AFR0_EL1 */
+IDREG_START(ID_AFR0_EL1)
+IDREG_FIELD_START(ID_AFR0, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_AFR0, VAL)
+
+IDREG_FIELD_START(ID_AFR0, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_AFR0, RES0_HI)
+
+IDREG_END(ID_AFR0_EL1)
+
+/* ID_MMFR0_EL1 */
+IDREG_START(ID_MMFR0_EL1)
+IDREG_FIELD_START(ID_MMFR0, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_MMFR0, VAL)
+
+IDREG_FIELD_START(ID_MMFR0, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_MMFR0, RES0_HI)
+
+IDREG_END(ID_MMFR0_EL1)
+
+/* ID_MMFR1_EL1 */
+IDREG_START(ID_MMFR1_EL1)
+IDREG_FIELD_START(ID_MMFR1, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_MMFR1, VAL)
+
+IDREG_FIELD_START(ID_MMFR1, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_MMFR1, RES0_HI)
+
+IDREG_END(ID_MMFR1_EL1)
+
+/* ID_MMFR2_EL1 */
+IDREG_START(ID_MMFR2_EL1)
+IDREG_FIELD_START(ID_MMFR2, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_MMFR2, VAL)
+
+IDREG_FIELD_START(ID_MMFR2, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_MMFR2, RES0_HI)
+
+IDREG_END(ID_MMFR2_EL1)
+
+/* ID_MMFR3_EL1 */
+IDREG_START(ID_MMFR3_EL1)
+IDREG_FIELD_START(ID_MMFR3, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_MMFR3, VAL)
+
+IDREG_FIELD_START(ID_MMFR3, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_MMFR3, RES0_HI)
+
+IDREG_END(ID_MMFR3_EL1)
+
+/* ID_MMFR4_EL1 */
+IDREG_START(ID_MMFR4_EL1)
+IDREG_FIELD_START(ID_MMFR4, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_MMFR4, VAL)
+
+IDREG_FIELD_START(ID_MMFR4, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_MMFR4, RES0_HI)
+
+IDREG_END(ID_MMFR4_EL1)
+
+/* ID_MMFR5_EL1 */
+IDREG_START(ID_MMFR5_EL1)
+IDREG_FIELD_START(ID_MMFR5, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_MMFR5, VAL)
+
+IDREG_FIELD_START(ID_MMFR5, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_MMFR5, RES0_HI)
+
+IDREG_END(ID_MMFR5_EL1)
+
+/* ID_ISAR0_EL1 */
+IDREG_START(ID_ISAR0_EL1)
+IDREG_FIELD_START(ID_ISAR0, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_ISAR0, VAL)
+
+IDREG_FIELD_START(ID_ISAR0, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_ISAR0, RES0_HI)
+
+IDREG_END(ID_ISAR0_EL1)
+
+/* ID_ISAR1_EL1 */
+IDREG_START(ID_ISAR1_EL1)
+IDREG_FIELD_START(ID_ISAR1, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_ISAR1, VAL)
+
+IDREG_FIELD_START(ID_ISAR1, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_ISAR1, RES0_HI)
+
+IDREG_END(ID_ISAR1_EL1)
+
+/* ID_ISAR2_EL1 */
+IDREG_START(ID_ISAR2_EL1)
+IDREG_FIELD_START(ID_ISAR2, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_ISAR2, VAL)
+
+IDREG_FIELD_START(ID_ISAR2, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_ISAR2, RES0_HI)
+
+IDREG_END(ID_ISAR2_EL1)
+
+/* ID_ISAR3_EL1 */
+IDREG_START(ID_ISAR3_EL1)
+IDREG_FIELD_START(ID_ISAR3, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_ISAR3, VAL)
+
+IDREG_FIELD_START(ID_ISAR3, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_ISAR3, RES0_HI)
+
+IDREG_END(ID_ISAR3_EL1)
+
+/* ID_ISAR4_EL1 */
+IDREG_START(ID_ISAR4_EL1)
+IDREG_FIELD_START(ID_ISAR4, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_ISAR4, VAL)
+
+IDREG_FIELD_START(ID_ISAR4, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_ISAR4, RES0_HI)
+
+IDREG_END(ID_ISAR4_EL1)
+
+/* ID_ISAR5_EL1 */
+IDREG_START(ID_ISAR5_EL1)
+IDREG_FIELD_START(ID_ISAR5, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_ISAR5, VAL)
+
+IDREG_FIELD_START(ID_ISAR5, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_ISAR5, RES0_HI)
+
+IDREG_END(ID_ISAR5_EL1)
+
+/* ID_ISAR6_EL1 */
+IDREG_START(ID_ISAR6_EL1)
+IDREG_FIELD_START(ID_ISAR6, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_ISAR6, VAL)
+
+IDREG_FIELD_START(ID_ISAR6, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_ISAR6, RES0_HI)
+
+IDREG_END(ID_ISAR6_EL1)
+
+/* ID_PFR2_EL1 */
+IDREG_START(ID_PFR2_EL1)
+IDREG_FIELD_START(ID_PFR2, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_PFR2, VAL)
+
+IDREG_FIELD_START(ID_PFR2, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_PFR2, RES0_HI)
+
+IDREG_END(ID_PFR2_EL1)
+
+/* ID_DFR1_EL1 */
+IDREG_START(ID_DFR1_EL1)
+IDREG_FIELD_START(ID_DFR1, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(ID_DFR1, VAL)
+
+IDREG_FIELD_START(ID_DFR1, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(ID_DFR1, RES0_HI)
+
+IDREG_END(ID_DFR1_EL1)
+
+/* MVFR0_EL1 */
+IDREG_START(MVFR0_EL1)
+IDREG_FIELD_START(MVFR0, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(MVFR0, VAL)
+
+IDREG_FIELD_START(MVFR0, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(MVFR0, RES0_HI)
+
+IDREG_END(MVFR0_EL1)
+
+/* MVFR1_EL1 */
+IDREG_START(MVFR1_EL1)
+IDREG_FIELD_START(MVFR1, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(MVFR1, VAL)
+
+IDREG_FIELD_START(MVFR1, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(MVFR1, RES0_HI)
+
+IDREG_END(MVFR1_EL1)
+
+/* MVFR2_EL1 */
+IDREG_START(MVFR2_EL1)
+IDREG_FIELD_START(MVFR2, VAL, 0, 32, ANY, 0)
+IDREG_FIELD_END(MVFR2, VAL)
+
+IDREG_FIELD_START(MVFR2, RES0_HI, 32, 32, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(MVFR2, RES0_HI)
+
+IDREG_END(MVFR2_EL1)
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 03/29] target/arm: Add MIDR, REVIDR, AIDR and extra ID regs to cpu-sysregs
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 01/29] target/arm: named_cpu_model: define containers for ID registers and fields Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 02/29] target/arm: Add ID Register field descriptions in cpu-idregs.h.inc Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 04/29] target/arm: Generate ARM64 ID registers and field tables Khushit Shah
` (26 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
From: Shaju Abraham <shaju.abraham@nutanix.com>
Add entries for sysregs MIDR_EL1, REVIDR_EL1, AIDR_EL1,
ID_AA64FPFR0_EL1, and ID_AA64ISAR3_EL1 to cpu-sysregs.h.inc
Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/cpu-sysregs.h.inc | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/target/arm/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc
index 3d1ed40f04..82a83d9d5c 100644
--- a/target/arm/cpu-sysregs.h.inc
+++ b/target/arm/cpu-sysregs.h.inc
@@ -41,3 +41,8 @@ DEF(CLIDR_EL1, 3, 1, 0, 0, 1)
DEF(ID_AA64ZFR0_EL1, 3, 0, 0, 4, 4)
DEF(CTR_EL0, 3, 3, 0, 0, 1)
DEF(DCZID_EL0, 3, 3, 0, 0, 7)
+DEF(MIDR_EL1, 3, 0, 0, 0, 0)
+DEF(REVIDR_EL1, 3, 0, 0, 0, 6)
+DEF(AIDR_EL1, 3, 1, 0, 0, 7)
+DEF(ID_AA64FPFR0_EL1, 3, 0, 0, 4, 7)
+DEF(ID_AA64ISAR3_EL1, 3, 0, 0, 6, 3)
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 04/29] target/arm: Generate ARM64 ID registers and field tables
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (2 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 03/29] target/arm: Add MIDR, REVIDR, AIDR and extra ID regs to cpu-sysregs Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 05/29] target/arm: Replace FIELD() macros with IDREG_FIELD expansion Khushit Shah
` (25 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
From: Shaju Abraham <shaju.abraham@nutanix.com>
Include cpu-idregs.h.inc multiple times with different definitions for
the X-macros. This will generate tables for all Arm64 ID registers and
their fields and their architecturally defined values. These tables
will be consumed by the property layer in future patches.
Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/cpu-idregs.c | 125 ++++++++++++++++++++++++++++++++++++++++
target/arm/cpu-idregs.h | 38 +++++++++++-
target/arm/meson.build | 3 +-
3 files changed, 164 insertions(+), 2 deletions(-)
create mode 100644 target/arm/cpu-idregs.c
diff --git a/target/arm/cpu-idregs.c b/target/arm/cpu-idregs.c
new file mode 100644
index 0000000000..81661dfca5
--- /dev/null
+++ b/target/arm/cpu-idregs.c
@@ -0,0 +1,125 @@
+/*
+ * ARM ID register field table.
+ *
+ * Builds the per-id-register field descriptor arrays and the global
+ * arm_idregs[] table.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "cpu-idregs.h"
+#include "cpu-sysregs.h"
+/*
+ * Generate an array of architecturely defined values for each field
+ * in arch-value format
+ */
+#define IDREG_START(reg)
+#define IDREG_END(reg)
+#define IDREG_FIELD_START(reg, field, shift, length, safe, defval) \
+ static const ArmIdRegArchVal reg##_##field##_arch_vals[] = {
+#define IDREG_FIELD_ARCH_VAL(v, n) { (v), (n) },
+#define IDREG_FIELD_ARCH_VAL_ANY { 0xffffffffUL, NULL },
+#define IDREG_FIELD_END(reg, field) \
+ };
+#include "cpu-idregs.h.inc"
+#undef IDREG_START
+#undef IDREG_END
+#undef IDREG_FIELD_START
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_ARCH_VAL_ANY
+#undef IDREG_FIELD_END
+/* generate an array of per-register ArmIdRegField[] descriptors */
+#define IDREG_FIELD_ARCH_VAL(v, n)
+#define IDREG_FIELD_ARCH_VAL_ANY
+#define IDREG_FIELD_END(reg, field)
+#define IDREG_START(reg) \
+ static ArmIdRegField reg##_fields[] = {
+
+#define IDREG_END(reg) \
+ };
+
+#define IDREG_FIELD_START(reg, field, _shift, _length, safe, defval) \
+ { \
+ .idx = ARM_FIELD_IDX(reg, field), \
+ .name = #field, \
+ .shift = (_shift), \
+ .length = (_length), \
+ .safe_rule = IDREG_SAFE_##safe, \
+ .default_val = (defval), \
+ .arch_vals = (ArmIdRegArchVal *)reg##_##field##_arch_vals, \
+ .arch_vals_count = ARRAY_SIZE(reg##_##field##_arch_vals), \
+ },
+#include "cpu-idregs.h.inc"
+#undef IDREG_START
+#undef IDREG_END
+#undef IDREG_FIELD_START
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_END
+
+/* generate an array of top level ID registers */
+#define IDREG_END(reg)
+#define IDREG_FIELD_START(reg, field, shift, length, safe, defval)
+#define IDREG_FIELD_ARCH_VAL(v, n)
+#define IDREG_FIELD_ARCH_VAL_ANY
+#define IDREG_FIELD_END(reg, field)
+
+#define IDREG_START(reg) \
+ [reg##_IDX] = { \
+ .name = #reg, \
+ .fields = reg##_fields, \
+ .fields_count = ARRAY_SIZE(reg##_fields), \
+ },
+
+ArmIdReg arm_idregs[NUM_ID_IDX] = {
+#include "cpu-idregs.h.inc"
+};
+#undef IDREG_START
+#undef IDREG_END
+#undef IDREG_FIELD_START
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_END
+
+
+/* Per-register field position enums (0..N-1 inside each register). */
+#define IDREG_START(reg) enum {
+#define IDREG_END(reg) reg##_FIELD_POS__MAX };
+#define IDREG_FIELD_START(reg, field, shift, length, safe, defval) \
+ reg##_FIELD_POS_##field,
+#define IDREG_FIELD_ARCH_VAL(v, n)
+#define IDREG_FIELD_ARCH_VAL_ANY
+#define IDREG_FIELD_END(reg, field)
+
+#include "cpu-idregs.h.inc"
+
+#undef IDREG_FIELD_END
+#undef IDREG_FIELD_ARCH_VAL_ANY
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_START
+#undef IDREG_END
+#undef IDREG_START
+
+/* Flat ArmFieldIdx -> {reg, field slot, shift, length}. */
+#define IDREG_START(reg)
+#define IDREG_END(reg)
+#define IDREG_FIELD_START(reg, field, _shift, _length, safe, defval) \
+ [ARM_FIELD_##reg##_##field] = { \
+ .reg_idx = reg##_EL1_IDX, \
+ .field_idx = reg##_FIELD_POS_##field, \
+ .shift = (_shift), \
+ .length = (_length), \
+ },
+#define IDREG_FIELD_ARCH_VAL(v, n)
+#define IDREG_FIELD_ARCH_VAL_ANY
+#define IDREG_FIELD_END(reg, field)
+
+const ArmIdRegFieldLoc arm_field_locs[ARM_FIELD__MAX] = {
+#include "cpu-idregs.h.inc"
+};
+
+#undef IDREG_FIELD_END
+#undef IDREG_FIELD_ARCH_VAL_ANY
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_START
+#undef IDREG_END
+#undef IDREG_START
diff --git a/target/arm/cpu-idregs.h b/target/arm/cpu-idregs.h
index 514ec39106..37a87e6d0b 100644
--- a/target/arm/cpu-idregs.h
+++ b/target/arm/cpu-idregs.h
@@ -16,12 +16,48 @@ typedef enum ArmIdRegSafeRule {
IDREG_SAFE_ANY,
} ArmIdRegSafeRule;
+#define DCZID_EL0_EL1_IDX DCZID_EL0_IDX
+#define CTR_EL0_EL1_IDX CTR_EL0_IDX
+
+/* ArmFieldIdx: per-field enum generated from cpu-idregs.h.inc */
+#define IDREG_START(reg)
+#define IDREG_END(reg)
+#define IDREG_FIELD_START(reg, field, shift, length, safe, defval) \
+ ARM_FIELD_##reg##_##field,
+#define IDREG_FIELD_ARCH_VAL(v, n)
+#define IDREG_FIELD_ARCH_VAL_ANY
+#define IDREG_FIELD_END(reg, field)
+typedef enum ArmFieldIdx {
+#include "cpu-idregs.h.inc"
+ ARM_FIELD__MAX,
+} ArmFieldIdx;
+#undef IDREG_FIELD_END
+#undef IDREG_FIELD_ARCH_VAL_ANY
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_START
+#undef IDREG_END
+#undef IDREG_START
+
+typedef struct ArmIdRegFieldLoc {
+ ARMIDRegisterIdx reg_idx;
+ uint16_t field_idx;
+ uint8_t shift;
+ uint8_t length;
+} ArmIdRegFieldLoc;
+extern const ArmIdRegFieldLoc arm_field_locs[ARM_FIELD__MAX];
+#define ARM_FIELD_REG(idx) (arm_field_locs[(idx)].reg_idx)
+#define ARM_FIELD_REG_FIELD(idx) (arm_field_locs[(idx)].field_idx)
+#define ARM_FIELD_SHIFT(idx) (arm_field_locs[(idx)].shift)
+#define ARM_FIELD_LENGTH(idx) (arm_field_locs[(idx)].length)
+#define ARM_FIELD_IDX(reg, field) ARM_FIELD_##reg##_##field
+
typedef struct ArmIdRegArchVal {
uint64_t value;
const char *name;
} ArmIdRegArchVal;
typedef struct ArmIdRegField {
+ ArmFieldIdx idx;
const char *name;
uint32_t shift;
uint32_t length;
@@ -37,5 +73,5 @@ typedef struct ArmIdReg {
uint32_t fields_count;
} ArmIdReg;
-
+extern ArmIdReg arm_idregs[NUM_ID_IDX];
#endif /* CPU_IDREGS_H */
diff --git a/target/arm/meson.build b/target/arm/meson.build
index 4723f9f170..be4361fbfd 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -10,7 +10,8 @@ arm_user_ss.add(files('gdbstub.c'))
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
'cpu64.c',
- 'gdbstub64.c'
+ 'gdbstub64.c',
+ 'cpu-idregs.c',
))
arm_common_ss.add(files(
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 05/29] target/arm: Replace FIELD() macros with IDREG_FIELD expansion
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (3 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 04/29] target/arm: Generate ARM64 ID registers and field tables Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 06/29] target/arm: Introduce data-structures for the ARM property layer Khushit Shah
` (24 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
From: Shaju Abraham <shaju.abraham@nutanix.com>
Replace the existing FIELD() macro with the newly introduced
IDREG_FIELD() macro to remove duplication.
All definitions for TCG remains the same.
Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/cpu-features.h | 235 +++-----------------------------------
1 file changed, 19 insertions(+), 216 deletions(-)
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 4e44245a8b..e162bdff9b 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -50,14 +50,6 @@ FIELD(CCSIDR_EL1, LINESIZE, 0, 3)
FIELD(CCSIDR_EL1, ASSOCIATIVITY, 3, 10)
FIELD(CCSIDR_EL1, NUMSETS, 13, 15)
-FIELD(CTR_EL0, IMINLINE, 0, 4)
-FIELD(CTR_EL0, L1IP, 14, 2)
-FIELD(CTR_EL0, DMINLINE, 16, 4)
-FIELD(CTR_EL0, ERG, 20, 4)
-FIELD(CTR_EL0, CWG, 24, 4)
-FIELD(CTR_EL0, IDC, 28, 1)
-FIELD(CTR_EL0, DIC, 29, 1)
-FIELD(CTR_EL0, TMINLINE, 32, 6)
FIELD(MIDR_EL1, REVISION, 0, 4)
FIELD(MIDR_EL1, PARTNUM, 4, 12)
@@ -189,219 +181,30 @@ FIELD(ID_PFR1, VIRTUALIZATION, 12, 4)
FIELD(ID_PFR1, GENTIMER, 16, 4)
FIELD(ID_PFR1, SEC_FRAC, 20, 4)
FIELD(ID_PFR1, VIRT_FRAC, 24, 4)
-FIELD(ID_PFR1, GIC, 28, 4)
FIELD(ID_PFR2, CSV3, 0, 4)
FIELD(ID_PFR2, SSBS, 4, 4)
FIELD(ID_PFR2, RAS_FRAC, 8, 4)
-FIELD(ID_AA64ISAR0, AES, 4, 4)
-FIELD(ID_AA64ISAR0, SHA1, 8, 4)
-FIELD(ID_AA64ISAR0, SHA2, 12, 4)
-FIELD(ID_AA64ISAR0, CRC32, 16, 4)
-FIELD(ID_AA64ISAR0, ATOMIC, 20, 4)
-FIELD(ID_AA64ISAR0, TME, 24, 4)
-FIELD(ID_AA64ISAR0, RDM, 28, 4)
-FIELD(ID_AA64ISAR0, SHA3, 32, 4)
-FIELD(ID_AA64ISAR0, SM3, 36, 4)
-FIELD(ID_AA64ISAR0, SM4, 40, 4)
-FIELD(ID_AA64ISAR0, DP, 44, 4)
-FIELD(ID_AA64ISAR0, FHM, 48, 4)
-FIELD(ID_AA64ISAR0, TS, 52, 4)
-FIELD(ID_AA64ISAR0, TLB, 56, 4)
-FIELD(ID_AA64ISAR0, RNDR, 60, 4)
-
-FIELD(ID_AA64ISAR1, DPB, 0, 4)
-FIELD(ID_AA64ISAR1, APA, 4, 4)
-FIELD(ID_AA64ISAR1, API, 8, 4)
-FIELD(ID_AA64ISAR1, JSCVT, 12, 4)
-FIELD(ID_AA64ISAR1, FCMA, 16, 4)
-FIELD(ID_AA64ISAR1, LRCPC, 20, 4)
-FIELD(ID_AA64ISAR1, GPA, 24, 4)
-FIELD(ID_AA64ISAR1, GPI, 28, 4)
-FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
-FIELD(ID_AA64ISAR1, SB, 36, 4)
-FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
-FIELD(ID_AA64ISAR1, BF16, 44, 4)
-FIELD(ID_AA64ISAR1, DGH, 48, 4)
-FIELD(ID_AA64ISAR1, I8MM, 52, 4)
-FIELD(ID_AA64ISAR1, XS, 56, 4)
-FIELD(ID_AA64ISAR1, LS64, 60, 4)
-
-FIELD(ID_AA64ISAR2, WFXT, 0, 4)
-FIELD(ID_AA64ISAR2, RPRES, 4, 4)
-FIELD(ID_AA64ISAR2, GPA3, 8, 4)
-FIELD(ID_AA64ISAR2, APA3, 12, 4)
-FIELD(ID_AA64ISAR2, MOPS, 16, 4)
-FIELD(ID_AA64ISAR2, BC, 20, 4)
-FIELD(ID_AA64ISAR2, PAC_FRAC, 24, 4)
-FIELD(ID_AA64ISAR2, CLRBHB, 28, 4)
-FIELD(ID_AA64ISAR2, SYSREG_128, 32, 4)
-FIELD(ID_AA64ISAR2, SYSINSTR_128, 36, 4)
-FIELD(ID_AA64ISAR2, PRFMSLC, 40, 4)
-FIELD(ID_AA64ISAR2, RPRFM, 48, 4)
-FIELD(ID_AA64ISAR2, CSSC, 52, 4)
-FIELD(ID_AA64ISAR2, LUT, 56, 4)
-FIELD(ID_AA64ISAR2, ATS1A, 60, 4)
-
-FIELD(ID_AA64PFR0, EL0, 0, 4)
-FIELD(ID_AA64PFR0, EL1, 4, 4)
-FIELD(ID_AA64PFR0, EL2, 8, 4)
-FIELD(ID_AA64PFR0, EL3, 12, 4)
-FIELD(ID_AA64PFR0, FP, 16, 4)
-FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
-FIELD(ID_AA64PFR0, GIC, 24, 4)
-FIELD(ID_AA64PFR0, RAS, 28, 4)
-FIELD(ID_AA64PFR0, SVE, 32, 4)
-FIELD(ID_AA64PFR0, SEL2, 36, 4)
-FIELD(ID_AA64PFR0, MPAM, 40, 4)
-FIELD(ID_AA64PFR0, AMU, 44, 4)
-FIELD(ID_AA64PFR0, DIT, 48, 4)
-FIELD(ID_AA64PFR0, RME, 52, 4)
-FIELD(ID_AA64PFR0, CSV2, 56, 4)
-FIELD(ID_AA64PFR0, CSV3, 60, 4)
-
-FIELD(ID_AA64PFR1, BT, 0, 4)
-FIELD(ID_AA64PFR1, SSBS, 4, 4)
-FIELD(ID_AA64PFR1, MTE, 8, 4)
-FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
-FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
-FIELD(ID_AA64PFR1, SME, 24, 4)
-FIELD(ID_AA64PFR1, RNDR_TRAP, 28, 4)
-FIELD(ID_AA64PFR1, CSV2_FRAC, 32, 4)
-FIELD(ID_AA64PFR1, NMI, 36, 4)
-FIELD(ID_AA64PFR1, MTE_FRAC, 40, 4)
-FIELD(ID_AA64PFR1, GCS, 44, 4)
-FIELD(ID_AA64PFR1, THE, 48, 4)
-FIELD(ID_AA64PFR1, MTEX, 52, 4)
-FIELD(ID_AA64PFR1, DF2, 56, 4)
-FIELD(ID_AA64PFR1, PFAR, 60, 4)
-
-FIELD(ID_AA64PFR2, MTEPERM, 0, 4)
-FIELD(ID_AA64PFR2, MTESTOREONLY, 4, 4)
-FIELD(ID_AA64PFR2, MTEFAR, 8, 4)
-FIELD(ID_AA64PFR2, GCIE, 12, 4)
-FIELD(ID_AA64PFR2, FPMR, 32, 4)
-
-FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
-FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
-FIELD(ID_AA64MMFR0, BIGEND, 8, 4)
-FIELD(ID_AA64MMFR0, SNSMEM, 12, 4)
-FIELD(ID_AA64MMFR0, BIGENDEL0, 16, 4)
-FIELD(ID_AA64MMFR0, TGRAN16, 20, 4)
-FIELD(ID_AA64MMFR0, TGRAN64, 24, 4)
-FIELD(ID_AA64MMFR0, TGRAN4, 28, 4)
-FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
-FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
-FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
-FIELD(ID_AA64MMFR0, EXS, 44, 4)
-FIELD(ID_AA64MMFR0, FGT, 56, 4)
-FIELD(ID_AA64MMFR0, ECV, 60, 4)
-
-FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
-FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
-FIELD(ID_AA64MMFR1, VH, 8, 4)
-FIELD(ID_AA64MMFR1, HPDS, 12, 4)
-FIELD(ID_AA64MMFR1, LO, 16, 4)
-FIELD(ID_AA64MMFR1, PAN, 20, 4)
-FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
-FIELD(ID_AA64MMFR1, XNX, 28, 4)
-FIELD(ID_AA64MMFR1, TWED, 32, 4)
-FIELD(ID_AA64MMFR1, ETS, 36, 4)
-FIELD(ID_AA64MMFR1, HCX, 40, 4)
-FIELD(ID_AA64MMFR1, AFP, 44, 4)
-FIELD(ID_AA64MMFR1, NTLBPA, 48, 4)
-FIELD(ID_AA64MMFR1, TIDCP1, 52, 4)
-FIELD(ID_AA64MMFR1, CMOW, 56, 4)
-FIELD(ID_AA64MMFR1, ECBHB, 60, 4)
-
-FIELD(ID_AA64MMFR2, CNP, 0, 4)
-FIELD(ID_AA64MMFR2, UAO, 4, 4)
-FIELD(ID_AA64MMFR2, LSM, 8, 4)
-FIELD(ID_AA64MMFR2, IESB, 12, 4)
-FIELD(ID_AA64MMFR2, VARANGE, 16, 4)
-FIELD(ID_AA64MMFR2, CCIDX, 20, 4)
-FIELD(ID_AA64MMFR2, NV, 24, 4)
-FIELD(ID_AA64MMFR2, ST, 28, 4)
-FIELD(ID_AA64MMFR2, AT, 32, 4)
-FIELD(ID_AA64MMFR2, IDS, 36, 4)
-FIELD(ID_AA64MMFR2, FWB, 40, 4)
-FIELD(ID_AA64MMFR2, TTL, 48, 4)
-FIELD(ID_AA64MMFR2, BBM, 52, 4)
-FIELD(ID_AA64MMFR2, EVT, 56, 4)
-FIELD(ID_AA64MMFR2, E0PD, 60, 4)
-
-FIELD(ID_AA64MMFR3, TCRX, 0, 4)
-FIELD(ID_AA64MMFR3, SCTLRX, 4, 4)
-FIELD(ID_AA64MMFR3, S1PIE, 8, 4)
-FIELD(ID_AA64MMFR3, S2PIE, 12, 4)
-FIELD(ID_AA64MMFR3, S1POE, 16, 4)
-FIELD(ID_AA64MMFR3, S2POE, 20, 4)
-FIELD(ID_AA64MMFR3, AIE, 24, 4)
-FIELD(ID_AA64MMFR3, MEC, 28, 4)
-FIELD(ID_AA64MMFR3, D128, 32, 4)
-FIELD(ID_AA64MMFR3, D128_2, 36, 4)
-FIELD(ID_AA64MMFR3, SNERR, 40, 4)
-FIELD(ID_AA64MMFR3, ANERR, 44, 4)
-FIELD(ID_AA64MMFR3, SDERR, 52, 4)
-FIELD(ID_AA64MMFR3, ADERR, 56, 4)
-FIELD(ID_AA64MMFR3, SPEC_FPACC, 60, 4)
-
-FIELD(ID_AA64MMFR4, POPS, 0, 4)
-FIELD(ID_AA64MMFR4, EIESB, 4, 4)
-FIELD(ID_AA64MMFR4, ASID2, 8, 4)
-FIELD(ID_AA64MMFR4, HACDBS, 12, 4)
-FIELD(ID_AA64MMFR4, FGWTE3, 16, 4)
-FIELD(ID_AA64MMFR4, NV_FRAC, 20, 4)
-FIELD(ID_AA64MMFR4, E2H0, 24, 4)
-FIELD(ID_AA64MMFR4, RMEGDI, 28, 4)
-FIELD(ID_AA64MMFR4, E3DSE, 36, 4)
-FIELD(ID_AA64MMFR4, SRMASK, 44, 4)
-
-FIELD(ID_AA64DFR0, DEBUGVER, 0, 4)
-FIELD(ID_AA64DFR0, TRACEVER, 4, 4)
-FIELD(ID_AA64DFR0, PMUVER, 8, 4)
-FIELD(ID_AA64DFR0, BRPS, 12, 4)
-FIELD(ID_AA64DFR0, PMSS, 16, 4)
-FIELD(ID_AA64DFR0, WRPS, 20, 4)
-FIELD(ID_AA64DFR0, SEBEP, 24, 4)
-FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
-FIELD(ID_AA64DFR0, PMSVER, 32, 4)
-FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
-FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
-FIELD(ID_AA64DFR0, TRACEBUFFER, 44, 4)
-FIELD(ID_AA64DFR0, MTPMU, 48, 4)
-FIELD(ID_AA64DFR0, BRBE, 52, 4)
-FIELD(ID_AA64DFR0, EXTTRCBUFF, 56, 4)
-FIELD(ID_AA64DFR0, HPMN0, 60, 4)
-
-FIELD(ID_AA64ZFR0, SVEVER, 0, 4)
-FIELD(ID_AA64ZFR0, AES, 4, 4)
-FIELD(ID_AA64ZFR0, ELTPERM, 12, 4)
-FIELD(ID_AA64ZFR0, BITPERM, 16, 4)
-FIELD(ID_AA64ZFR0, BFLOAT16, 20, 4)
-FIELD(ID_AA64ZFR0, B16B16, 24, 4)
-FIELD(ID_AA64ZFR0, SHA3, 32, 4)
-FIELD(ID_AA64ZFR0, SM4, 40, 4)
-FIELD(ID_AA64ZFR0, I8MM, 44, 4)
-FIELD(ID_AA64ZFR0, F16MM, 48, 4)
-FIELD(ID_AA64ZFR0, F32MM, 52, 4)
-FIELD(ID_AA64ZFR0, F64MM, 56, 4)
-
-FIELD(ID_AA64SMFR0, F32F32, 32, 1)
-FIELD(ID_AA64SMFR0, BI32I32, 33, 1)
-FIELD(ID_AA64SMFR0, B16F32, 34, 1)
-FIELD(ID_AA64SMFR0, F16F32, 35, 1)
-FIELD(ID_AA64SMFR0, I8I32, 36, 4)
-FIELD(ID_AA64SMFR0, F16F16, 42, 1)
-FIELD(ID_AA64SMFR0, B16B16, 43, 1)
-FIELD(ID_AA64SMFR0, I16I32, 44, 4)
-FIELD(ID_AA64SMFR0, F64F64, 48, 1)
-FIELD(ID_AA64SMFR0, I16I64, 52, 4)
-FIELD(ID_AA64SMFR0, SMEVER, 56, 4)
-FIELD(ID_AA64SMFR0, FA64, 63, 1)
-
-FIELD(ID_DFR0, COPDBG, 0, 4)
+/*
+ * Expand FIELD() declarations for every ID register field listed in
+ * cpu-idregs.h.inc .
+ */
+#define IDREG_START(reg)
+#define IDREG_END(reg)
+#define IDREG_FIELD_ARCH_VAL(v, n)
+#define IDREG_FIELD_ARCH_VAL_ANY
+#define IDREG_FIELD_END(reg, field)
+#define IDREG_FIELD_START(reg, field, _shift, _length, safe, defval) \
+ FIELD(reg, field, _shift, _length)
+#include "cpu-idregs.h.inc"
+#undef IDREG_FIELD_START
+#undef IDREG_FIELD_END
+#undef IDREG_FIELD_ARCH_VAL_ANY
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_END
+#undef IDREG_START
+
FIELD(ID_DFR0, COPSDBG, 4, 4)
FIELD(ID_DFR0, MMAPDBG, 8, 4)
FIELD(ID_DFR0, COPTRC, 12, 4)
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 06/29] target/arm: Introduce data-structures for the ARM property layer
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (4 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 05/29] target/arm: Replace FIELD() macros with IDREG_FIELD expansion Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 07/29] target/arm: Define ARM properties Khushit Shah
` (23 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Introduce the data-structures required for the ARM property layer
Initially support 4 types of properties:
- STRING: 1:1 mapping to fields that have architecturally defined
values. The value names are borrowed from kernel's
sysreg.
- NUMERIC: 1:1 mapping to fields that have implementation defined
values like cache line size, debug counters etc...
- BOOLEAN: 1:1 mapping to fields that are 1-bit wide.
- FRACTIONAL: maps two fields, BASE and _FRAC, the valid values
for the properties must be preset.
(Example: MPAM, CSV2, NV, etc..)
These data structure will be used by next patch to define ARM
properties.
Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-props.h | 41 ++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 target/arm/arm-cpu-props.h
diff --git a/target/arm/arm-cpu-props.h b/target/arm/arm-cpu-props.h
new file mode 100644
index 0000000000..2c9bca9d97
--- /dev/null
+++ b/target/arm/arm-cpu-props.h
@@ -0,0 +1,41 @@
+/*
+ * ARM CPU feature properties.
+ *
+ * User-facing QOM properties that map to fields of the AArch64 ID
+ * registers described in cpu-idregs.inc.h.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef ARM_CPU_PROPS_H
+#define ARM_CPU_PROPS_H
+
+#include "cpu-idregs.h"
+
+typedef enum ArmCpuPropType {
+ ARM_PROP_STRING,
+ ARM_PROP_BOOLEAN,
+ ARM_PROP_NUMERIC,
+ ARM_PROP_FRACTIONAL,
+} ArmCpuPropType;
+
+typedef struct ArmFracVal {
+ const char *name;
+ uint64_t base_val;
+ uint64_t frac_val;
+} ArmFracVal;
+
+typedef struct ArmCpuPropDesc {
+ const char *name;
+ ArmCpuPropType type;
+ union {
+ ArmFieldIdx field;
+ struct {
+ ArmFieldIdx base_field;
+ ArmFieldIdx frac_field;
+ const ArmFracVal *vals;
+ } frac;
+ } u;
+} ArmCpuPropDesc;
+
+#endif
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 07/29] target/arm: Define ARM properties
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (5 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 06/29] target/arm: Introduce data-structures for the ARM property layer Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 08/29] target/arm: Add ID register field helper functions Khushit Shah
` (22 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
From: Shaju Abraham <shaju.abraham@nutanix.com>
Add properties for most fields.
Properties that map to fields that are not supported by the linux kernel
(i.e. not in the ftr_bits array) are not included, as these fields
are already zeroed out by the kernel and are not writable.
Add new properties as kernel start supporting their respective fields.
These properties will be added to CPU objects in future patches.
Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-props.c | 242 +++++++++++++++++++++++++++++++++++++
target/arm/meson.build | 1 +
2 files changed, 243 insertions(+)
create mode 100644 target/arm/arm-cpu-props.c
diff --git a/target/arm/arm-cpu-props.c b/target/arm/arm-cpu-props.c
new file mode 100644
index 0000000000..1c5d4c5727
--- /dev/null
+++ b/target/arm/arm-cpu-props.c
@@ -0,0 +1,242 @@
+/*
+ * ARM CPU feature property definitions.
+ *
+ * Maps ID-register fields described in cpu-idregs.inc.h to user-facing
+ * QOM properties.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qom/object.h"
+#include "cpu.h"
+#include "arm-cpu-props.h"
+
+
+#define ARM_SINGLE_FIELD_PROP(prop_name, _type, reg, fld) \
+ { .name = (prop_name), .type = ARM_PROP_##_type, \
+ .u.field = ARM_FIELD_IDX(reg, fld) }
+
+#define ARM_FRAC_PROP(prop_name, base_reg, base_fld, frac_reg, frac_fld, valid_vals) \
+ { .name = (prop_name), .type = ARM_PROP_FRACTIONAL, \
+ .u.frac.base_field = ARM_FIELD_IDX(base_reg, base_fld), \
+ .u.frac.frac_field = ARM_FIELD_IDX(frac_reg, frac_fld), \
+ .u.frac.vals = valid_vals }
+
+const ArmFracVal csv2_frac_vals[] = {
+ { "0.0", 0, 0 },
+ { "1.0", 1, 0 },
+ { "1.1", 1, 1 },
+ { "1.2", 1, 2 },
+ { "2.0", 2, 0 },
+ { "3.0", 3, 0 },
+ { NULL }
+};
+
+const ArmFracVal mpam_frac_vals[] = {
+ { "0.0", 0, 0 },
+ { "0.1", 0, 1 },
+ { "1.0", 1, 0 },
+ { "1.1", 1, 1 },
+ { NULL }
+};
+
+const ArmFracVal ras_frac_vals[] = {
+ { "0.0", 0, 0 },
+ { "1.0", 1, 0 },
+ { "1.1", 1, 1 },
+ { "1.1_base", 2, 0 },
+ { "2.0", 3, 0 },
+ { NULL }
+};
+
+const ArmFracVal nv_frac_vals[] = {
+ { "0.0", 0, 0 },
+ { "nv2_only", 0, 1 }, /* KVM: MMFR2 always cleared */
+ { "1.0", 1, 0 },
+ { "2.0", 2, 0 },
+ { "2.0_only", 2, 1 },
+ { "2.1", 2, 2 },
+ { NULL }
+};
+
+const ArmCpuPropDesc arm_cpu_props[] = {
+ ARM_SINGLE_FIELD_PROP("feat_AES", STRING, ID_AA64ISAR0, AES),
+ ARM_SINGLE_FIELD_PROP("feat_SHA1", STRING, ID_AA64ISAR0, SHA1),
+ ARM_SINGLE_FIELD_PROP("feat_SHA2", STRING, ID_AA64ISAR0, SHA2),
+ ARM_SINGLE_FIELD_PROP("feat_CRC32", STRING, ID_AA64ISAR0, CRC32),
+ ARM_SINGLE_FIELD_PROP("feat_ATOMIC", STRING, ID_AA64ISAR0, ATOMIC),
+ ARM_SINGLE_FIELD_PROP("feat_RDM", STRING, ID_AA64ISAR0, RDM),
+ ARM_SINGLE_FIELD_PROP("feat_SHA3", STRING, ID_AA64ISAR0, SHA3),
+ ARM_SINGLE_FIELD_PROP("feat_SM3", STRING, ID_AA64ISAR0, SM3),
+ ARM_SINGLE_FIELD_PROP("feat_SM4", STRING, ID_AA64ISAR0, SM4),
+ ARM_SINGLE_FIELD_PROP("feat_DP", STRING, ID_AA64ISAR0, DP),
+ ARM_SINGLE_FIELD_PROP("feat_FHM", STRING, ID_AA64ISAR0, FHM),
+ ARM_SINGLE_FIELD_PROP("feat_TS", STRING, ID_AA64ISAR0, TS),
+ ARM_SINGLE_FIELD_PROP("feat_TLB", STRING, ID_AA64ISAR0, TLB),
+ ARM_SINGLE_FIELD_PROP("feat_RNDR", STRING, ID_AA64ISAR0, RNDR),
+
+ ARM_SINGLE_FIELD_PROP("feat_DPB", STRING, ID_AA64ISAR1, DPB),
+ ARM_SINGLE_FIELD_PROP("hw_prop_APA", STRING, ID_AA64ISAR1, APA),
+ ARM_SINGLE_FIELD_PROP("hw_prop_API", STRING, ID_AA64ISAR1, API),
+ ARM_SINGLE_FIELD_PROP("feat_JSCVT", STRING, ID_AA64ISAR1, JSCVT),
+ ARM_SINGLE_FIELD_PROP("feat_FCMA", STRING, ID_AA64ISAR1, FCMA),
+ ARM_SINGLE_FIELD_PROP("feat_LRCPC", STRING, ID_AA64ISAR1, LRCPC),
+ ARM_SINGLE_FIELD_PROP("hw_prop_GPA", STRING, ID_AA64ISAR1, GPA),
+ ARM_SINGLE_FIELD_PROP("hw_prop_GPI", STRING, ID_AA64ISAR1, GPI),
+ ARM_SINGLE_FIELD_PROP("feat_FRINTTS", STRING, ID_AA64ISAR1, FRINTTS),
+ ARM_SINGLE_FIELD_PROP("feat_SB", STRING, ID_AA64ISAR1, SB),
+ ARM_SINGLE_FIELD_PROP("feat_SPECRES", STRING, ID_AA64ISAR1, SPECRES),
+ ARM_SINGLE_FIELD_PROP("feat_BF16", STRING, ID_AA64ISAR1, BF16),
+ ARM_SINGLE_FIELD_PROP("feat_DGH", STRING, ID_AA64ISAR1, DGH),
+ ARM_SINGLE_FIELD_PROP("feat_I8MM", STRING, ID_AA64ISAR1, I8MM),
+ ARM_SINGLE_FIELD_PROP("feat_XS", STRING, ID_AA64ISAR1, XS),
+ ARM_SINGLE_FIELD_PROP("feat_LS64", STRING, ID_AA64ISAR1, LS64),
+
+ ARM_SINGLE_FIELD_PROP("feat_WFXT", STRING, ID_AA64ISAR2, WFXT),
+ ARM_SINGLE_FIELD_PROP("feat_RPRES", STRING, ID_AA64ISAR2, RPRES),
+ ARM_SINGLE_FIELD_PROP("hw_prop_GPA3", STRING, ID_AA64ISAR2, GPA3),
+ ARM_SINGLE_FIELD_PROP("hw_prop_APA3", STRING, ID_AA64ISAR2, APA3),
+ ARM_SINGLE_FIELD_PROP("feat_MOPS", STRING, ID_AA64ISAR2, MOPS),
+ ARM_SINGLE_FIELD_PROP("feat_BC", STRING, ID_AA64ISAR2, BC),
+ ARM_SINGLE_FIELD_PROP("feat_CLRBHB", STRING, ID_AA64ISAR2, CLRBHB),
+ ARM_SINGLE_FIELD_PROP("feat_RPRFM", STRING, ID_AA64ISAR2, RPRFM),
+ ARM_SINGLE_FIELD_PROP("feat_CSSC", STRING, ID_AA64ISAR2, CSSC),
+ ARM_SINGLE_FIELD_PROP("feat_LUT", STRING, ID_AA64ISAR2, LUT),
+
+ ARM_SINGLE_FIELD_PROP("feat_FAMINMAX", STRING, ID_AA64ISAR3, FAMINMAX),
+ ARM_SINGLE_FIELD_PROP("feat_LSFE", STRING, ID_AA64ISAR3, LSFE),
+ ARM_SINGLE_FIELD_PROP("feat_FPRCVT", STRING, ID_AA64ISAR3, FPRCVT),
+
+ ARM_SINGLE_FIELD_PROP("el0_mode", STRING, ID_AA64PFR0, EL0),
+ ARM_SINGLE_FIELD_PROP("el1_mode", STRING, ID_AA64PFR0, EL1),
+ ARM_SINGLE_FIELD_PROP("el2_mode", STRING, ID_AA64PFR0, EL2),
+ ARM_SINGLE_FIELD_PROP("el3_mode", STRING, ID_AA64PFR0, EL3),
+ ARM_SINGLE_FIELD_PROP("feat_FP", STRING, ID_AA64PFR0, FP),
+ ARM_SINGLE_FIELD_PROP("feat_AdvSIMD", STRING, ID_AA64PFR0, ADVSIMD),
+ ARM_SINGLE_FIELD_PROP("feat_SVE", STRING, ID_AA64PFR0, SVE),
+ ARM_SINGLE_FIELD_PROP("feat_SEL2", STRING, ID_AA64PFR0, SEL2),
+ ARM_SINGLE_FIELD_PROP("feat_AMU", STRING, ID_AA64PFR0, AMU),
+ ARM_SINGLE_FIELD_PROP("feat_DIT", STRING, ID_AA64PFR0, DIT),
+ ARM_SINGLE_FIELD_PROP("feat_CSV3", STRING, ID_AA64PFR0, CSV3),
+
+ ARM_SINGLE_FIELD_PROP("feat_BT", STRING, ID_AA64PFR1, BT),
+ ARM_SINGLE_FIELD_PROP("feat_SSBS", STRING, ID_AA64PFR1, SSBS),
+ ARM_SINGLE_FIELD_PROP("feat_MTE", STRING, ID_AA64PFR1, MTE),
+ ARM_SINGLE_FIELD_PROP("feat_NMI", STRING, ID_AA64PFR1, NMI),
+ ARM_SINGLE_FIELD_PROP("feat_MTE_FRAC", STRING, ID_AA64PFR1, MTE_FRAC),
+ ARM_SINGLE_FIELD_PROP("feat_GCS", STRING, ID_AA64PFR1, GCS),
+ ARM_SINGLE_FIELD_PROP("feat_DF2", STRING, ID_AA64PFR1, DF2),
+
+ ARM_SINGLE_FIELD_PROP("feat_MTESTOREONLY", STRING, ID_AA64PFR2, MTESTOREONLY),
+ ARM_SINGLE_FIELD_PROP("feat_MTEFAR", STRING, ID_AA64PFR2, MTEFAR),
+ ARM_SINGLE_FIELD_PROP("feat_FPMR", STRING, ID_AA64PFR2, FPMR),
+
+ ARM_SINGLE_FIELD_PROP("hw_prop_PARANGE", STRING, ID_AA64MMFR0, PARANGE),
+ ARM_SINGLE_FIELD_PROP("hw_prop_ASIDBITS", STRING, ID_AA64MMFR0, ASIDBITS),
+ ARM_SINGLE_FIELD_PROP("feat_BIGEND", STRING, ID_AA64MMFR0, BIGEND),
+ ARM_SINGLE_FIELD_PROP("feat_SNSMEM", STRING, ID_AA64MMFR0, SNSMEM),
+ ARM_SINGLE_FIELD_PROP("feat_BIGENDEL0", STRING, ID_AA64MMFR0, BIGENDEL0),
+ ARM_SINGLE_FIELD_PROP("hw_prop_TGRAN16", STRING, ID_AA64MMFR0, TGRAN16),
+ ARM_SINGLE_FIELD_PROP("hw_prop_TGRAN64", STRING, ID_AA64MMFR0, TGRAN64),
+ ARM_SINGLE_FIELD_PROP("hw_prop_TGRAN4", STRING, ID_AA64MMFR0, TGRAN4),
+ ARM_SINGLE_FIELD_PROP("hw_prop_TGRAN16_2", STRING, ID_AA64MMFR0, TGRAN16_2),
+ ARM_SINGLE_FIELD_PROP("hw_prop_TGRAN64_2", STRING, ID_AA64MMFR0, TGRAN64_2),
+ ARM_SINGLE_FIELD_PROP("hw_prop_TGRAN4_2", STRING, ID_AA64MMFR0, TGRAN4_2),
+ ARM_SINGLE_FIELD_PROP("feat_EXS", STRING, ID_AA64MMFR0, EXS),
+ ARM_SINGLE_FIELD_PROP("feat_FGT", STRING, ID_AA64MMFR0, FGT),
+ ARM_SINGLE_FIELD_PROP("feat_ECV", STRING, ID_AA64MMFR0, ECV),
+
+ ARM_SINGLE_FIELD_PROP("feat_HAFDBS", STRING, ID_AA64MMFR1, HAFDBS),
+ ARM_SINGLE_FIELD_PROP("hw_prop_VMIDBITS", STRING, ID_AA64MMFR1, VMIDBITS),
+ ARM_SINGLE_FIELD_PROP("feat_VH", STRING, ID_AA64MMFR1, VH),
+ ARM_SINGLE_FIELD_PROP("feat_HPDS", STRING, ID_AA64MMFR1, HPDS),
+ ARM_SINGLE_FIELD_PROP("feat_LO", STRING, ID_AA64MMFR1, LO),
+ ARM_SINGLE_FIELD_PROP("feat_PAN", STRING, ID_AA64MMFR1, PAN),
+ ARM_SINGLE_FIELD_PROP("feat_SpecSEI", STRING, ID_AA64MMFR1, SPECSEI),
+ ARM_SINGLE_FIELD_PROP("feat_XNX", STRING, ID_AA64MMFR1, XNX),
+ ARM_SINGLE_FIELD_PROP("feat_TWED", STRING, ID_AA64MMFR1, TWED),
+ ARM_SINGLE_FIELD_PROP("feat_ETS", STRING, ID_AA64MMFR1, ETS),
+ ARM_SINGLE_FIELD_PROP("feat_HCX", STRING, ID_AA64MMFR1, HCX),
+ ARM_SINGLE_FIELD_PROP("feat_AFP", STRING, ID_AA64MMFR1, AFP),
+ ARM_SINGLE_FIELD_PROP("feat_TIDCP1", STRING, ID_AA64MMFR1, TIDCP1),
+ ARM_SINGLE_FIELD_PROP("feat_ECBHB", STRING, ID_AA64MMFR1, ECBHB),
+
+ ARM_SINGLE_FIELD_PROP("feat_CNP", STRING, ID_AA64MMFR2, CNP),
+ ARM_SINGLE_FIELD_PROP("feat_UAO", STRING, ID_AA64MMFR2, UAO),
+ ARM_SINGLE_FIELD_PROP("feat_LSM", STRING, ID_AA64MMFR2, LSM),
+ ARM_SINGLE_FIELD_PROP("feat_IESB", STRING, ID_AA64MMFR2, IESB),
+ ARM_SINGLE_FIELD_PROP("hw_prop_VARANGE", STRING, ID_AA64MMFR2, VARANGE),
+ ARM_SINGLE_FIELD_PROP("hw_prop_CCIDX", STRING, ID_AA64MMFR2, CCIDX),
+ ARM_SINGLE_FIELD_PROP("hw_prop_ST", STRING, ID_AA64MMFR2, ST),
+ ARM_SINGLE_FIELD_PROP("feat_AT", STRING, ID_AA64MMFR2, AT),
+ ARM_SINGLE_FIELD_PROP("hw_prop_IDS", STRING, ID_AA64MMFR2, IDS),
+ ARM_SINGLE_FIELD_PROP("hw_prop_FWB", STRING, ID_AA64MMFR2, FWB),
+ ARM_SINGLE_FIELD_PROP("feat_TTL", STRING, ID_AA64MMFR2, TTL),
+ ARM_SINGLE_FIELD_PROP("feat_BBM", STRING, ID_AA64MMFR2, BBM),
+ ARM_SINGLE_FIELD_PROP("feat_EVT", STRING, ID_AA64MMFR2, EVT),
+ ARM_SINGLE_FIELD_PROP("feat_E0PD", STRING, ID_AA64MMFR2, E0PD),
+
+ ARM_SINGLE_FIELD_PROP("feat_TCRX", STRING, ID_AA64MMFR3, TCRX),
+ ARM_SINGLE_FIELD_PROP("feat_SCTLRX", STRING, ID_AA64MMFR3, SCTLRX),
+ ARM_SINGLE_FIELD_PROP("feat_S1PIE", STRING, ID_AA64MMFR3, S1PIE),
+ ARM_SINGLE_FIELD_PROP("feat_S1POE", STRING, ID_AA64MMFR3, S1POE),
+
+ ARM_SINGLE_FIELD_PROP("feat_E2H0", STRING, ID_AA64MMFR4, E2H0),
+
+ ARM_SINGLE_FIELD_PROP("feat_DBG", STRING, ID_AA64DFR0, DEBUGVER),
+ ARM_SINGLE_FIELD_PROP("feat_PMU", STRING, ID_AA64DFR0, PMUVER),
+ ARM_SINGLE_FIELD_PROP("hw_prop_BRPS", NUMERIC, ID_AA64DFR0, BRPS),
+ ARM_SINGLE_FIELD_PROP("hw_prop_WRPs", NUMERIC, ID_AA64DFR0, WRPS),
+ ARM_SINGLE_FIELD_PROP("hw_prop_CTX_CMPs", NUMERIC, ID_AA64DFR0, CTX_CMPS),
+ ARM_SINGLE_FIELD_PROP("hw_prop_PMSVer", STRING, ID_AA64DFR0, PMSVER),
+ ARM_SINGLE_FIELD_PROP("feat_DoubleLock", STRING, ID_AA64DFR0, DOUBLELOCK),
+
+ ARM_SINGLE_FIELD_PROP("hw_prop_SVEVer", STRING, ID_AA64ZFR0, SVEVER),
+ ARM_SINGLE_FIELD_PROP("feat_SVE_AES", STRING, ID_AA64ZFR0, AES),
+ ARM_SINGLE_FIELD_PROP("feat_SVE_ELTPERM", STRING, ID_AA64ZFR0, ELTPERM),
+ ARM_SINGLE_FIELD_PROP("feat_SVE_BITPERM", STRING, ID_AA64ZFR0, BITPERM),
+ ARM_SINGLE_FIELD_PROP("feat_SVE_BFLOAT16", STRING, ID_AA64ZFR0, BFLOAT16),
+ ARM_SINGLE_FIELD_PROP("feat_SVE_B16B16", STRING, ID_AA64ZFR0, B16B16),
+ ARM_SINGLE_FIELD_PROP("feat_SVE_SHA3", STRING, ID_AA64ZFR0, SHA3),
+ ARM_SINGLE_FIELD_PROP("feat_SVE_SM4", STRING, ID_AA64ZFR0, SM4),
+ ARM_SINGLE_FIELD_PROP("feat_SVE_I8MM", STRING, ID_AA64ZFR0, I8MM),
+ ARM_SINGLE_FIELD_PROP("feat_SVE_F16MM", STRING, ID_AA64ZFR0, F16MM),
+ ARM_SINGLE_FIELD_PROP("feat_SVE_F32MM", STRING, ID_AA64ZFR0, F32MM),
+ ARM_SINGLE_FIELD_PROP("feat_SVE_F64MM", STRING, ID_AA64ZFR0, F64MM),
+
+ ARM_SINGLE_FIELD_PROP("feat_F8E5M2", BOOLEAN, ID_AA64FPFR0, F8E5M2),
+ ARM_SINGLE_FIELD_PROP("feat_F8E4M3", BOOLEAN, ID_AA64FPFR0, F8E4M3),
+ ARM_SINGLE_FIELD_PROP("feat_F8MM4", BOOLEAN, ID_AA64FPFR0, F8MM4),
+ ARM_SINGLE_FIELD_PROP("feat_F8MM8", BOOLEAN, ID_AA64FPFR0, F8MM8),
+ ARM_SINGLE_FIELD_PROP("feat_F8DP2", BOOLEAN, ID_AA64FPFR0, F8DP2),
+ ARM_SINGLE_FIELD_PROP("feat_F8DP4", BOOLEAN, ID_AA64FPFR0, F8DP4),
+ ARM_SINGLE_FIELD_PROP("feat_F8FMA", BOOLEAN, ID_AA64FPFR0, F8FMA),
+ ARM_SINGLE_FIELD_PROP("feat_F8CVT", BOOLEAN, ID_AA64FPFR0, F8CVT),
+
+ ARM_SINGLE_FIELD_PROP("hw_prop_IMInline", NUMERIC, CTR_EL0, IMINLINE),
+ ARM_SINGLE_FIELD_PROP("hw_prop_L1IP", STRING, CTR_EL0, L1IP),
+ ARM_SINGLE_FIELD_PROP("hw_prop_DMInline", NUMERIC, CTR_EL0, DMINLINE),
+ ARM_SINGLE_FIELD_PROP("hw_prop_ERG", NUMERIC, CTR_EL0, ERG),
+ ARM_SINGLE_FIELD_PROP("hw_prop_CWG", NUMERIC, CTR_EL0, CWG),
+ ARM_SINGLE_FIELD_PROP("hw_prop_IDC", BOOLEAN, CTR_EL0, IDC),
+ ARM_SINGLE_FIELD_PROP("hw_prop_DIC", BOOLEAN, CTR_EL0, DIC),
+ ARM_SINGLE_FIELD_PROP("hw_prop_BS", NUMERIC, DCZID_EL0, BS),
+ ARM_SINGLE_FIELD_PROP("hw_prop_DZP", BOOLEAN, DCZID_EL0, DZP),
+
+ ARM_SINGLE_FIELD_PROP("cpu_revision", NUMERIC, MIDR, REVISION),
+ ARM_SINGLE_FIELD_PROP("cpu_partnum", NUMERIC, MIDR, PARTNUM),
+ ARM_SINGLE_FIELD_PROP("cpu_architecture", NUMERIC, MIDR, ARCHITECTURE),
+ ARM_SINGLE_FIELD_PROP("cpu_variant", NUMERIC, MIDR, VARIANT),
+ ARM_SINGLE_FIELD_PROP("cpu_implementer", NUMERIC, MIDR, IMPLEMENTER),
+ ARM_SINGLE_FIELD_PROP("cpu_revidr", NUMERIC, REVIDR, VAL),
+ ARM_SINGLE_FIELD_PROP("cpu_aidr", NUMERIC, AIDR, VAL),
+
+ /* Fractional properties */
+ ARM_FRAC_PROP("feat_CSV2", ID_AA64PFR0, CSV2, ID_AA64PFR1, CSV2_FRAC, csv2_frac_vals),
+ ARM_FRAC_PROP("feat_MPAM", ID_AA64PFR0, MPAM, ID_AA64PFR1, MPAM_FRAC, mpam_frac_vals),
+ ARM_FRAC_PROP("feat_RAS", ID_AA64PFR0, RAS, ID_AA64PFR1, RAS_FRAC, ras_frac_vals),
+ ARM_FRAC_PROP("feat_NV", ID_AA64MMFR2, NV, ID_AA64MMFR4, NV_FRAC, nv_frac_vals),
+ { .name = NULL }
+};
diff --git a/target/arm/meson.build b/target/arm/meson.build
index be4361fbfd..ae1c55c802 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -12,6 +12,7 @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
'cpu64.c',
'gdbstub64.c',
'cpu-idregs.c',
+ 'arm-cpu-props.c'
))
arm_common_ss.add(files(
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 08/29] target/arm: Add ID register field helper functions
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (6 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 07/29] target/arm: Define ARM properties Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 09/29] target/arm: Add all ARM64 properties to host model Khushit Shah
` (21 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
From: Shaju Abraham <shaju.abraham@nutanix.com>
Add helpers in cpu-idregs.c for working with individual ID registers
and fields. This includes:
- read/write specific field.
- look up architectural value name for a given field value and vice
versa.
- reset a field or ID register to it's default value.
Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-props.c | 246 +++++++++++++++++++++++++++++++++++++
target/arm/arm-cpu-props.h | 8 ++
target/arm/cpu-idregs.c | 119 ++++++++++++++++++
target/arm/cpu-idregs.h | 11 ++
target/arm/cpu64.c | 2 +-
5 files changed, 385 insertions(+), 1 deletion(-)
diff --git a/target/arm/arm-cpu-props.c b/target/arm/arm-cpu-props.c
index 1c5d4c5727..d5900c0e23 100644
--- a/target/arm/arm-cpu-props.c
+++ b/target/arm/arm-cpu-props.c
@@ -18,12 +18,26 @@
{ .name = (prop_name), .type = ARM_PROP_##_type, \
.u.field = ARM_FIELD_IDX(reg, fld) }
+#define ARM_SINGLE_FIELD_PROP_GS(prop_name, _type, reg, fld, _get, _set) \
+ { .name = (prop_name), .type = ARM_PROP_##_type, \
+ .u.field = ARM_FIELD_IDX(reg, fld), \
+ .get = _get, \
+ .set = _set }
+
#define ARM_FRAC_PROP(prop_name, base_reg, base_fld, frac_reg, frac_fld, valid_vals) \
{ .name = (prop_name), .type = ARM_PROP_FRACTIONAL, \
.u.frac.base_field = ARM_FIELD_IDX(base_reg, base_fld), \
.u.frac.frac_field = ARM_FIELD_IDX(frac_reg, frac_fld), \
.u.frac.vals = valid_vals }
+#define ARM_FRAC_PROP_GS(prop_name, b_reg, b_fld, f_reg, f_fld, valid_vals, _get, _set) \
+ { .name = (prop_name), .type = ARM_PROP_FRACTIONAL, \
+ .u.frac.base_field = ARM_FIELD_IDX(b_reg, b_fld), \
+ .u.frac.frac_field = ARM_FIELD_IDX(f_reg, f_fld), \
+ .u.frac.vals = valid_vals, \
+ .get = _get, \
+ .set = _set }
+
const ArmFracVal csv2_frac_vals[] = {
{ "0.0", 0, 0 },
{ "1.0", 1, 0 },
@@ -240,3 +254,235 @@ const ArmCpuPropDesc arm_cpu_props[] = {
ARM_FRAC_PROP("feat_NV", ID_AA64MMFR2, NV, ID_AA64MMFR4, NV_FRAC, nv_frac_vals),
{ .name = NULL }
};
+
+static const ArmCpuPropDesc *arm_find_prop(const char *name)
+{
+ const ArmCpuPropDesc *p;
+ for (p = arm_cpu_props; p->name; p++) {
+ if (g_str_equal(p->name, name)) {
+ return p;
+ }
+ }
+ return NULL;
+}
+
+static void arm_single_field_get(ARMCPU *cpu, const ArmCpuPropDesc *p,
+ Visitor *v, const char *name, Error **errp)
+{
+ uint64_t value;
+ char *s;
+ bool b;
+
+ arm_idreg_field_read(&cpu->isar, p->u.field, &value);
+
+ switch (p->type) {
+ case ARM_PROP_STRING: {
+ s = g_strdup(arm_arch_val_name(p->u.field, value));
+
+ if (!s) {
+ error_setg(errp, "Property '%s': unknown value %" PRIu64,
+ name, value);
+ return;
+ }
+ visit_type_str(v, name, &s, errp);
+ g_free(s);
+ break;
+ }
+ case ARM_PROP_BOOLEAN: {
+ b = value != 0;
+ visit_type_bool(v, name, &b, errp);
+ break;
+ }
+ case ARM_PROP_NUMERIC:
+ visit_type_uint64(v, name, &value, errp);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void arm_fractional_get(ARMCPU *cpu, const ArmCpuPropDesc *p,
+ Visitor *v, const char *name, Error **errp)
+{
+ uint64_t base_val, frac_val;
+ const ArmFracVal *val;
+ char *s;
+
+ arm_idreg_field_read(&cpu->isar, p->u.frac.base_field, &base_val);
+ arm_idreg_field_read(&cpu->isar, p->u.frac.frac_field, &frac_val);
+
+ for (val = p->u.frac.vals; val->name; val++) {
+ if (val->base_val == base_val && val->frac_val == frac_val) {
+ s = g_strdup(val->name);
+ visit_type_str(v, name, &s, errp);
+ g_free(s);
+ return;
+ }
+ }
+
+ error_setg(errp,
+ "Property '%s': unknown fractional value %" PRIu64
+ ".%" PRIu64, name, base_val, frac_val);
+}
+
+static void arm_cpu_prop_get(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+ const ArmCpuPropDesc *p = arm_find_prop(name);
+
+ if (!p) {
+ error_setg(errp, "Property %s not found", name);
+ return;
+ }
+
+ if (p->get) {
+ p->get(cpu, v, name, errp);
+ return;
+ }
+
+ switch (p->type) {
+ case ARM_PROP_STRING:
+ case ARM_PROP_BOOLEAN:
+ case ARM_PROP_NUMERIC:
+ arm_single_field_get(cpu, p, v, name, errp);
+ break;
+ case ARM_PROP_FRACTIONAL:
+ arm_fractional_get(cpu, p, v, name, errp);
+ break;
+ }
+}
+
+static void arm_single_field_set(ARMCPU *cpu, const ArmCpuPropDesc *p,
+ Visitor *v, const char *name, Error **errp)
+{
+ uint64_t value;
+ char *str = NULL;
+ bool b;
+
+ switch (p->type) {
+ case ARM_PROP_STRING: {
+
+ if (!visit_type_str(v, name, &str, errp)) {
+ return;
+ }
+ if (!arm_arch_val_from_name(p->u.field, str, &value)) {
+ error_setg(errp, "Property '%s': invalid value '%s'", name, str);
+ g_free(str);
+ return;
+ }
+ g_free(str);
+ break;
+ }
+ case ARM_PROP_BOOLEAN: {
+
+ if (!visit_type_bool(v, name, &b, errp)) {
+ return;
+ }
+ value = b ? 1 : 0;
+ break;
+ }
+ case ARM_PROP_NUMERIC:
+ if (!visit_type_uint64(v, name, &value, errp)) {
+ return;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if (!arm_idreg_field_write(cpu, p->u.field, value, errp)) {
+ error_prepend(errp, "Property '%s': ", name);
+ }
+}
+
+static void arm_fractional_set(ARMCPU *cpu, const ArmCpuPropDesc *p,
+ Visitor *v, const char *name, Error **errp)
+{
+ char *str = NULL;
+ const ArmFracVal *val;
+
+ if (!visit_type_str(v, name, &str, errp)) {
+ return;
+ }
+
+ for (val = p->u.frac.vals; val->name; val++) {
+ if (g_str_equal(val->name, str)) {
+ if (!arm_idreg_field_write(cpu, p->u.frac.base_field,
+ val->base_val, errp)) {
+ error_prepend(errp, "Property '%s': ", name);
+ g_free(str);
+ return;
+ }
+ if (!arm_idreg_field_write(cpu, p->u.frac.frac_field,
+ val->frac_val, errp)) {
+ error_prepend(errp, "Property '%s': ", name);
+ }
+ g_free(str);
+ return;
+ }
+ }
+
+ error_setg(errp, "Property '%s': invalid fractional value '%s'",
+ name, str);
+ g_free(str);
+}
+
+static void arm_cpu_prop_set(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+ const ArmCpuPropDesc *p = arm_find_prop(name);
+
+ if (!p) {
+ error_setg(errp, "Property %s not found", name);
+ return;
+ }
+
+ if (p->set) {
+ p->set(cpu, v, name, errp);
+ return;
+ }
+
+ switch (p->type) {
+ case ARM_PROP_STRING:
+ case ARM_PROP_BOOLEAN:
+ case ARM_PROP_NUMERIC:
+ arm_single_field_set(cpu, p, v, name, errp);
+ break;
+ case ARM_PROP_FRACTIONAL:
+ arm_fractional_set(cpu, p, v, name, errp);
+ break;
+ }
+}
+
+void arm_add_cpu_props(Object *obj)
+{
+ const char *type;
+ const ArmCpuPropDesc *p;
+
+ for (p = arm_cpu_props; p->name; p++) {
+ switch (p->type) {
+ case ARM_PROP_STRING:
+ case ARM_PROP_FRACTIONAL:
+ type = "string";
+ break;
+ case ARM_PROP_BOOLEAN:
+ type = "bool";
+ break;
+ case ARM_PROP_NUMERIC:
+ type = "number";
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ object_property_add(obj, p->name, type,
+ arm_cpu_prop_get, arm_cpu_prop_set,
+ NULL, NULL);
+ }
+}
+
+const ArmCpuPropDesc *get_arm_cpu_props(void)
+{
+ return arm_cpu_props;
+}
diff --git a/target/arm/arm-cpu-props.h b/target/arm/arm-cpu-props.h
index 2c9bca9d97..9ba3f4c100 100644
--- a/target/arm/arm-cpu-props.h
+++ b/target/arm/arm-cpu-props.h
@@ -11,6 +11,8 @@
#define ARM_CPU_PROPS_H
#include "cpu-idregs.h"
+#include "cpu.h"
+#include "qemu/typedefs.h"
typedef enum ArmCpuPropType {
ARM_PROP_STRING,
@@ -36,6 +38,12 @@ typedef struct ArmCpuPropDesc {
const ArmFracVal *vals;
} frac;
} u;
+
+ void (*get)(ARMCPU *cpu, Visitor *v, const char *name, Error **errp);
+ void (*set)(ARMCPU *cpu, Visitor *v, const char *name, Error **errp);
} ArmCpuPropDesc;
+void arm_add_cpu_props(Object *obj);
+
+const ArmCpuPropDesc *get_arm_cpu_props(void);
#endif
diff --git a/target/arm/cpu-idregs.c b/target/arm/cpu-idregs.c
index 81661dfca5..ee6165622a 100644
--- a/target/arm/cpu-idregs.c
+++ b/target/arm/cpu-idregs.c
@@ -10,6 +10,9 @@
#include "cpu.h"
#include "cpu-idregs.h"
#include "cpu-sysregs.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+
/*
* Generate an array of architecturely defined values for each field
* in arch-value format
@@ -123,3 +126,119 @@ const ArmIdRegFieldLoc arm_field_locs[ARM_FIELD__MAX] = {
#undef IDREG_FIELD_START
#undef IDREG_END
#undef IDREG_START
+
+void arm_idreg_field_read(const ARMISARegisters *isar, ArmFieldIdx field,
+ uint64_t *value)
+{
+ ARMIDRegisterIdx reg_idx = ARM_FIELD_REG(field);
+ uint64_t reg_value = isar->idregs[reg_idx];
+ uint32_t shift = ARM_FIELD_SHIFT(field);
+ uint32_t length = ARM_FIELD_LENGTH(field);
+
+ *value = extract64(reg_value, shift, length);
+}
+
+bool arm_idreg_field_write(ARMCPU *cpu, ArmFieldIdx field, uint64_t value,
+ Error **errp)
+{
+ ARMIDRegisterIdx reg_idx = ARM_FIELD_REG(field);
+ uint64_t reg_value = cpu->isar.idregs[reg_idx];
+ uint32_t shift = ARM_FIELD_SHIFT(field);
+ uint32_t length = ARM_FIELD_LENGTH(field);
+ ArmIdReg *reg;
+ ArmIdRegField *fdesc;
+
+ if (length < 64 && value > ((1ULL << length) - 1)) {
+ reg = &arm_idregs[reg_idx];
+ fdesc = ®->fields[ARM_FIELD_REG_FIELD(field)];
+
+ error_setg(errp, "value %" PRIu64 " is too large for field %s.%s",
+ value, reg->name, fdesc->name);
+ return false;
+ }
+
+ cpu->isar.idregs[reg_idx] = deposit64(reg_value, shift,
+ length, value);
+ return true;
+}
+
+static const ArmIdRegField *arm_get_field_desc(ArmFieldIdx field)
+{
+ ARMIDRegisterIdx reg_idx = ARM_FIELD_REG(field);
+ uint16_t field_idx = ARM_FIELD_REG_FIELD(field);
+ return &arm_idregs[reg_idx].fields[field_idx];
+}
+
+const char *arm_arch_val_name(ArmFieldIdx field, uint64_t val)
+{
+ uint32_t i;
+ const ArmIdRegField *f = arm_get_field_desc(field);
+
+ for (i = 0; i < f->arch_vals_count; i++) {
+ if (f->arch_vals[i].value == val && f->arch_vals[i].name) {
+ return f->arch_vals[i].name;
+ }
+ }
+ return NULL;
+}
+
+bool arm_arch_val_from_name(ArmFieldIdx field, const char *name,
+ uint64_t *val)
+{
+ uint32_t i;
+ ArmIdRegArchVal *av;
+ const ArmIdRegField *f = arm_get_field_desc(field);
+
+ for (i = 0; i < f->arch_vals_count; i++) {
+ av = &f->arch_vals[i];
+
+ if (av->name && g_ascii_strcasecmp(av->name, name) == 0) {
+ *val = av->value;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool arm_field_is_idreg_any(ArmFieldIdx field)
+{
+ const ArmIdRegField *f = arm_get_field_desc(field);
+
+ return f->arch_vals_count == 1 &&
+ f->arch_vals[0].value == 0xffffffffUL &&
+ f->arch_vals[0].name == NULL;
+}
+
+void arm_idreg_field_reset_to_default(ARMCPU *cpu, ArmFieldIdx field)
+{
+ const ArmIdRegField *f = arm_get_field_desc(field);
+ ARMIDRegisterIdx reg_idx = ARM_FIELD_REG(field);
+
+ cpu->isar.idregs[reg_idx] = deposit64(cpu->isar.idregs[reg_idx],
+ f->shift, f->length,
+ f->default_val);
+}
+
+void arm_idregs_reset_to_defaults(ARMCPU *cpu)
+{
+ int i;
+ uint32_t j;
+ ArmIdReg *reg;
+
+ for (i = 0; i < NUM_ID_IDX; i++) {
+ reg = &arm_idregs[i];
+
+ if (!reg->name) {
+ warn_report("target/arm: no field table for ID register slot"
+ " %d; cpu->isar.idregs[%d] left at 0x%016"
+ PRIx64, i,
+ i, cpu->isar.idregs[i]);
+ continue;
+ }
+
+ cpu->isar.idregs[i] = 0;
+ for (j = 0; j < reg->fields_count; j++) {
+ arm_idreg_field_reset_to_default(cpu, reg->fields[j].idx);
+ }
+ }
+}
diff --git a/target/arm/cpu-idregs.h b/target/arm/cpu-idregs.h
index 37a87e6d0b..01d1b8f797 100644
--- a/target/arm/cpu-idregs.h
+++ b/target/arm/cpu-idregs.h
@@ -74,4 +74,15 @@ typedef struct ArmIdReg {
} ArmIdReg;
extern ArmIdReg arm_idregs[NUM_ID_IDX];
+
+void arm_idreg_field_read(const ARMISARegisters *isar, ArmFieldIdx field,
+ uint64_t *value);
+bool arm_idreg_field_write(ARMCPU *cpu, ArmFieldIdx field,
+ uint64_t value, Error **errp);
+const char *arm_arch_val_name(ArmFieldIdx field, uint64_t val);
+bool arm_arch_val_from_name(ArmFieldIdx field, const char *name,
+ uint64_t *val);
+bool arm_field_is_idreg_any(ArmFieldIdx field);
+void arm_idreg_field_reset_to_default(ARMCPU *cpu, ArmFieldIdx field);
+void arm_idregs_reset_to_defaults(ARMCPU *cpu);
#endif /* CPU_IDREGS_H */
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index a93ad2da5a..7fb3791643 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -37,7 +37,7 @@
#include "hw/core/qdev-properties.h"
#include "internals.h"
#include "cpu-features.h"
-
+#include "arm-cpu-props.h"
/* convert between <register>_IDX and SYS_<register> */
#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \
[NAME##_IDX] = SYS_##NAME,
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 09/29] target/arm: Add all ARM64 properties to host model
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (7 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 08/29] target/arm: Add ID register field helper functions Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 10/29] target/arm: Add named cpu model infra + graviton3 named model Khushit Shah
` (20 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
All all properties defined in arm_cpu_props to the host model under
CONFIG_KVM.
Properties are processed in the order they appear in cmdline:
for example, saying -cpu host,sve=off,feat_SVE=on is same as saying
-cpu host,sve=off,sve=on.
There is an exception for pauth, as it is backed by cpu->prop_pauth,
doing -cpu host,pauth=on,hw_prop_APA/API/APA3=0 will lead to an error.
And just doing hw_prop_APA/API/APA3/GPA/GPI=<val> will not turn on
pauth.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/cpu64.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 7fb3791643..0300f8677f 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -863,6 +863,7 @@ static void aarch64_host_initfn(Object *obj)
kvm_arm_set_cpreg_mig_tolerances(cpu);
kvm_arm_set_cpu_features_from_host(cpu);
aarch64_add_sve_properties(obj);
+ arm_add_cpu_props(obj);
#elif defined(CONFIG_HVF)
hvf_arm_set_cpu_features_from_host(cpu);
#elif defined(CONFIG_WHPX)
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 10/29] target/arm: Add named cpu model infra + graviton3 named model
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (8 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 09/29] target/arm: Add all ARM64 properties to host model Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 11/29] target/arm: Add Nvidia Grace " Khushit Shah
` (19 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
From: Shaju Abraham <shaju.abraham@nutanix.com>
Introduce a small named-CPU-model layer on top of the field-backed
property infrastructure. Each model is a flat table of (name, value)
overrides and a parent pointer. At instance-init, the parent chain is
walked root-first and every level's properties are applied via QOM,
so a child entry overrides its ancestors for the same name.
For example, the graviton3-v1 named model hierarchy is:
kvm-base-v1 KVM-imposed quirks (chain root)
arm-v8_4-a-v1 ARMv8.4-A architectural mandate
neoverse-v1-v1 Neoverse V1
graviton3-v1 AWS Graviton3
arm-v8_4-a-v1:
Only features mandated by the ARM ARM.
neoverse-v1-v1:
Reference manual derived feature values for the reference core.
Values differ from TRM values based on what was exposed to the guest
with -cpu host.
graviton3-v1:
SoC integration choices (crypto pin, cache hints, PAuth alg).
The model values are figured out from ID register dump visible to
QEMU with -cpu host on Graviton3 machine.
Model realization:
1. arm_idregs_reset_to_defaults: Reset cpu->isar.idregs[] to the default
values.
2. Add all properties to the CPU Object
3. arm_realize_model_chain: Walk the parent chain from root first and
apply all the properties.
Realized model ID reg values will be written back to KVM in future
patch.
Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
hw/arm/virt.c | 5 +
target/arm/arm-cpu-models.c | 300 ++++++++++++++++++++++++++++++++++++
target/arm/arm-cpu-models.h | 35 +++++
target/arm/meson.build | 7 +-
4 files changed, 345 insertions(+), 2 deletions(-)
create mode 100644 target/arm/arm-cpu-models.c
create mode 100644 target/arm/arm-cpu-models.h
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 10b1954382..b8695b9286 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -4069,6 +4069,11 @@ static GPtrArray *virt_get_valid_cpu_types(const MachineState *ms)
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("host")));
}
}
+ if (kvm_enabled() && target_aarch64()) {
+ g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("arm-v8_4-a-v1")));
+ g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("neoverse-v1-v1")));
+ g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("graviton3-v1")));
+ }
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("max")));
return vct;
diff --git a/target/arm/arm-cpu-models.c b/target/arm/arm-cpu-models.c
new file mode 100644
index 0000000000..61d45619ba
--- /dev/null
+++ b/target/arm/arm-cpu-models.c
@@ -0,0 +1,300 @@
+/*
+ * ARM named CPU model definitions.
+ *
+ * Each model is defined as an array of MODEL_PROP macro, listing only
+ * the properties that DIFFER from the parent model.
+ *
+ * At realisation the parent chain is walked root-first and
+ * every level's props are applied via QOM, so the leaf's values
+ * naturally override its ancestors.
+ *
+ * Hierarchy:
+ *
+ * kvm-base-v1 KVM-imposed quirks (chain root)
+ * arm-v8_4-a-v1 ARMv8.4-A architectural mandate
+ * neoverse-v1-v1 Neoverse V1 (TRM 102649)
+ * graviton3-v1 AWS Graviton3
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "system/kvm.h"
+#include "cpu.h"
+#include "internals.h"
+#include "kvm_arm.h"
+#include "arm-cpu-models.h"
+#include "arm-cpu-props.h"
+#include "cpu-idregs.h"
+
+#define MODEL_PROP_FIELD_STR str
+#define MODEL_PROP_FIELD_BOOL b
+#define MODEL_PROP_FIELD_NUM num
+
+#define MODEL_PROP(_name, _type, _value) \
+ { .name = (_name), .type = ARM_MODEL_PROP_##_type, \
+ .u.MODEL_PROP_FIELD_##_type = (_value) }
+
+#define MODEL_PROP_END { .name = NULL }
+
+static const ArmModelPropValue kvm_base_v1_props[] = {
+ MODEL_PROP("el0_mode", STR, "aarch64"),
+ MODEL_PROP("el1_mode", STR, "aarch64"),
+ MODEL_PROP("el2_mode", STR, "off"),
+ MODEL_PROP("el3_mode", STR, "off"),
+ MODEL_PROP("feat_AMU", STR, "off"),
+ MODEL_PROP("feat_MPAM", STR, "0.0"),
+ MODEL_PROP("feat_NV", STR, "0.0"),
+ MODEL_PROP("feat_MTE_FRAC", STR, "async"),
+ MODEL_PROP("hw_prop_CCIDX", STR, "32"),
+
+ MODEL_PROP_END,
+};
+
+static const ArmModelPropValue armv8_4_a_v1_props[] = {
+ MODEL_PROP("feat_CRC32", STR, "on"),
+ MODEL_PROP("feat_ATOMIC", STR, "on"),
+ MODEL_PROP("feat_HPDS", STR, "on"),
+ MODEL_PROP("feat_LO", STR, "on"),
+
+ MODEL_PROP("feat_DPB", STR, "on"),
+ MODEL_PROP("feat_RAS", STR, "1.0"),
+ MODEL_PROP("feat_PAN", STR, "pan2"),
+ MODEL_PROP("feat_UAO", STR, "on"),
+ MODEL_PROP("feat_CNP", STR, "on"),
+ MODEL_PROP("feat_IESB", STR, "on"),
+
+ MODEL_PROP("feat_DIT", STR, "on"),
+ MODEL_PROP("feat_DBG", STR, "v8p4"),
+ MODEL_PROP("feat_PMU", STR, "v3p4"),
+ MODEL_PROP("feat_TS", STR, "flagm"),
+ MODEL_PROP("feat_LRCPC", STR, "lrcpc2"),
+ MODEL_PROP("feat_AT", STR, "on"),
+ MODEL_PROP("hw_prop_IDS", STR, "0x18"),
+
+ MODEL_PROP_END,
+};
+
+static const ArmModelPropValue neoverse_v1_v1_props[] = {
+ MODEL_PROP("cpu_implementer", NUM, 0x41),
+ MODEL_PROP("cpu_variant", NUM, 0x1),
+ MODEL_PROP("cpu_architecture", NUM, 0xF),
+ MODEL_PROP("cpu_partnum", NUM, 0xD40),
+ MODEL_PROP("cpu_revision", NUM, 0x1),
+
+ MODEL_PROP("hw_prop_BRPS", NUM, 0x5),
+ MODEL_PROP("hw_prop_WRPs", NUM, 0x3),
+ MODEL_PROP("hw_prop_CTX_CMPs", NUM, 0x1),
+ MODEL_PROP("feat_DoubleLock", STR, "off"),
+
+ MODEL_PROP("feat_RDM", STR, "on"),
+ MODEL_PROP("feat_DP", STR, "on"),
+ MODEL_PROP("feat_FHM", STR, "on"),
+
+ MODEL_PROP("feat_DPB", STR, "dpb2"),
+ MODEL_PROP("feat_JSCVT", STR, "on"),
+ MODEL_PROP("feat_FCMA", STR, "on"),
+ MODEL_PROP("feat_BF16", STR, "on"),
+ MODEL_PROP("feat_DGH", STR, "on"),
+ MODEL_PROP("feat_I8MM", STR, "on"),
+
+ MODEL_PROP("feat_FP", STR, "fp16"),
+ MODEL_PROP("feat_AdvSIMD", STR, "fp16"),
+ MODEL_PROP("feat_RAS", STR, "1.1_base"),
+ MODEL_PROP("feat_CSV2", STR, "1.0"),
+ MODEL_PROP("feat_CSV3", STR, "on"),
+
+ MODEL_PROP("feat_SSBS", STR, "ssbs2"),
+
+ MODEL_PROP("hw_prop_PARANGE", STR, "48"),
+ MODEL_PROP("hw_prop_ASIDBITS", STR, "16"),
+ MODEL_PROP("feat_BIGEND", STR, "on"),
+ MODEL_PROP("feat_SNSMEM", STR, "on"),
+ MODEL_PROP("hw_prop_TGRAN4", STR, "on"),
+ MODEL_PROP("hw_prop_TGRAN16", STR, "on"),
+ MODEL_PROP("hw_prop_TGRAN64", STR, "on"),
+ MODEL_PROP("hw_prop_TGRAN4_2", STR, "tgran4"),
+ MODEL_PROP("hw_prop_TGRAN16_2", STR, "tgran16"),
+ MODEL_PROP("hw_prop_TGRAN64_2", STR, "tgran64"),
+
+ MODEL_PROP("feat_HAFDBS", STR, "dbm"),
+ MODEL_PROP("hw_prop_VMIDBITS", STR, "16"),
+ MODEL_PROP("feat_VH", STR, "on"),
+ MODEL_PROP("feat_HPDS", STR, "hpds2"),
+ MODEL_PROP("feat_XNX", STR, "on"),
+ MODEL_PROP("feat_SpecSEI", STR, "off"),
+
+ MODEL_PROP("hw_prop_FWB", STR, "on"),
+ MODEL_PROP("feat_BBM", STR, "2"),
+ MODEL_PROP("feat_EVT", STR, "ttlbxs"),
+
+ MODEL_PROP("feat_E2H0", STR, "on"),
+
+ MODEL_PROP("hw_prop_IMInline", NUM, 4),
+ MODEL_PROP("hw_prop_L1IP", STR, "pipt"),
+ MODEL_PROP("hw_prop_DMInline", NUM, 4),
+ MODEL_PROP("hw_prop_ERG", NUM, 4),
+ MODEL_PROP("hw_prop_CWG", NUM, 4),
+
+ MODEL_PROP("hw_prop_BS", NUM, 0x4),
+
+ MODEL_PROP_END,
+};
+
+static const ArmModelPropValue graviton3_v1_props[] = {
+ MODEL_PROP("feat_AES", STR, "pmull"),
+ MODEL_PROP("feat_SHA1", STR, "on"),
+ MODEL_PROP("feat_SHA2", STR, "sha512"),
+ MODEL_PROP("feat_SHA3", STR, "on"),
+ MODEL_PROP("feat_SM3", STR, "on"),
+ MODEL_PROP("feat_SM4", STR, "on"),
+ MODEL_PROP("feat_RNDR", STR, "on"),
+
+ MODEL_PROP("hw_prop_IDC", BOOL, true),
+ MODEL_PROP("hw_prop_DIC", BOOL, true),
+
+ MODEL_PROP("cpu_revidr", NUM, 1),
+
+ MODEL_PROP_END,
+};
+
+static const ArmNamedCpuModel arm_cpu_models[] = {
+ {
+ .name = "kvm-base-v1",
+ .parent = NULL,
+ .props = kvm_base_v1_props,
+ },
+ {
+ .name = "arm-v8_4-a-v1",
+ .parent = "kvm-base-v1",
+ .props = armv8_4_a_v1_props,
+ },
+ {
+ .name = "neoverse-v1-v1",
+ .parent = "arm-v8_4-a-v1",
+ .props = neoverse_v1_v1_props,
+ },
+ {
+ .name = "graviton3-v1",
+ .parent = "neoverse-v1-v1",
+ .props = graviton3_v1_props,
+ },
+};
+
+static ARMCPUInfo arm_named_cpu_infos[ARRAY_SIZE(arm_cpu_models)];
+static const ArmNamedCpuModel *arm_find_model(const char *name)
+{
+ size_t i;
+ for (i = 0; i < ARRAY_SIZE(arm_cpu_models); i++) {
+ if (g_str_equal(arm_cpu_models[i].name, name)) {
+ return &arm_cpu_models[i];
+ }
+ }
+ return NULL;
+}
+
+static void arm_apply_model_props(Object *obj, const ArmModelPropValue *props,
+ Error **errp)
+{
+ const ArmModelPropValue *pv;
+ ERRP_GUARD();
+
+ for (pv = props; pv->name; pv++) {
+ switch (pv->type) {
+ case ARM_MODEL_PROP_STR:
+ object_property_set_str(obj, pv->name, pv->u.str, errp);
+ break;
+ case ARM_MODEL_PROP_BOOL:
+ object_property_set_bool(obj, pv->name, pv->u.b, errp);
+ break;
+ case ARM_MODEL_PROP_NUM:
+ object_property_set_uint(obj, pv->name, pv->u.num, errp);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ if (*errp) {
+ error_prepend(errp, "property '%s': ", pv->name);
+ return;
+ }
+ }
+}
+
+static void arm_realize_model_chain(Object *obj, const ArmNamedCpuModel *model,
+ Error **errp)
+{
+ const ArmNamedCpuModel *cur, *parent;
+ const ArmNamedCpuModel *chain[ARRAY_SIZE(arm_cpu_models)];
+ size_t depth = 0;
+ for (cur = model; cur; ) {
+ if (depth >= ARRAY_SIZE(chain)) {
+ error_setg(errp, "model '%s': parent chain too deep "
+ "(possible cycle)", model->name);
+ return;
+ }
+ chain[depth++] = cur;
+
+ if (!cur->parent) {
+ break;
+ }
+ parent = arm_find_model(cur->parent);
+ if (!parent) {
+ error_setg(errp, "model '%s': unknown parent '%s'",
+ cur->name, cur->parent);
+ return;
+ }
+ cur = parent;
+ }
+
+ while (depth--) {
+ arm_apply_model_props(obj, chain[depth]->props, errp);
+ if (*errp) {
+ return;
+ }
+ }
+}
+
+static void arm_named_cpu_initfn(Object *obj)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+ ARMCPUClass *acc = ARM_CPU_GET_CLASS(obj);
+ const ArmNamedCpuModel *model = arm_find_model(acc->info->name);
+ if (!model) {
+ error_report("'%s' CPU model entry not found)",
+ acc->info->name);
+ return;
+ }
+
+ if (!kvm_enabled()) {
+ error_report("'%s' CPU model requires KVM (-accel kvm)",
+ acc->info->name);
+ return;
+ }
+
+ kvm_arm_set_cpu_features_from_host(cpu);
+ if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
+ return;
+ }
+
+ arm_idregs_reset_to_defaults(cpu);
+
+ aarch64_add_sve_properties(obj);
+ aarch64_add_pauth_properties(obj);
+ arm_add_cpu_props(obj);
+
+ arm_realize_model_chain(obj, model, &error_abort);
+}
+
+void arm_register_named_cpu_models(void)
+{
+ size_t i;
+ for (i = 0; i < ARRAY_SIZE(arm_cpu_models); i++) {
+ arm_named_cpu_infos[i].name = arm_cpu_models[i].name;
+ arm_named_cpu_infos[i].initfn = arm_named_cpu_initfn;
+ arm_cpu_register(&arm_named_cpu_infos[i]);
+ }
+}
+
+type_init(arm_register_named_cpu_models)
diff --git a/target/arm/arm-cpu-models.h b/target/arm/arm-cpu-models.h
new file mode 100644
index 0000000000..297926e167
--- /dev/null
+++ b/target/arm/arm-cpu-models.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * ARM named CPU model definitions - public API.
+ */
+#ifndef ARM_CPU_MODELS_H
+#define ARM_CPU_MODELS_H
+
+#include "qapi/error.h"
+#include "qom/object.h"
+
+typedef enum ArmModelPropType {
+ ARM_MODEL_PROP_STR,
+ ARM_MODEL_PROP_BOOL,
+ ARM_MODEL_PROP_NUM,
+} ArmModelPropType;
+
+typedef struct ArmModelPropValue {
+ const char *name;
+ ArmModelPropType type;
+ union {
+ bool b;
+ uint64_t num;
+ const char *str;
+ } u;
+} ArmModelPropValue;
+
+typedef struct ArmNamedCpuModel {
+ const char *name;
+ const char *parent;
+ const ArmModelPropValue *props;
+} ArmNamedCpuModel;
+
+void arm_register_named_cpu_models(void);
+
+#endif /* ARM_CPU_MODELS_H */
diff --git a/target/arm/meson.build b/target/arm/meson.build
index ae1c55c802..a7638f8778 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -12,7 +12,8 @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
'cpu64.c',
'gdbstub64.c',
'cpu-idregs.c',
- 'arm-cpu-props.c'
+ 'arm-cpu-props.c',
+ 'arm-cpu-models.c',
))
arm_common_ss.add(files(
@@ -22,7 +23,9 @@ arm_common_ss.add(files(
arm_common_system_ss.add(files(
'arm-qmp-cmds.c',
))
-arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c'))
+arm_system_ss.add(when: 'CONFIG_KVM',
+ if_true: files('hyp_gdbstub.c',
+ 'kvm.c'))
arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c'))
arm_user_ss.add(files('cpu.c'))
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 11/29] target/arm: Add Nvidia Grace named model
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (9 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 10/29] target/arm: Add named cpu model infra + graviton3 named model Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 12/29] target/arm/kvm: Writeback modified ID registers to KVM Khushit Shah
` (18 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Add Nvidia Grace named model alongside its hierarchy (neoverse-v2,
armv9-a)
Field values were derived from the ID register view that KVM exposes to
QEMU with -cpu host on an Nvidia Grace system.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
hw/arm/virt.c | 3 +
target/arm/arm-cpu-models.c | 132 +++++++++++++++++++++++++++++++++++-
2 files changed, 134 insertions(+), 1 deletion(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index b8695b9286..117033115d 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -4073,6 +4073,9 @@ static GPtrArray *virt_get_valid_cpu_types(const MachineState *ms)
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("arm-v8_4-a-v1")));
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("neoverse-v1-v1")));
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("graviton3-v1")));
+ g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("arm-v9_0-a-v1")));
+ g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("neoverse-v2-v1")));
+ g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("grace-v1")));
}
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("max")));
diff --git a/target/arm/arm-cpu-models.c b/target/arm/arm-cpu-models.c
index 61d45619ba..230768019c 100644
--- a/target/arm/arm-cpu-models.c
+++ b/target/arm/arm-cpu-models.c
@@ -14,7 +14,9 @@
* arm-v8_4-a-v1 ARMv8.4-A architectural mandate
* neoverse-v1-v1 Neoverse V1 (TRM 102649)
* graviton3-v1 AWS Graviton3
- *
+ * arm-v9_0-a-v1 ARMv9.0-A architectural deltas
+ * neoverse-v2-v1 Neoverse V2 (TRM 102375)
+ * grace-v1 NVIDIA Grace
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@@ -160,6 +162,119 @@ static const ArmModelPropValue graviton3_v1_props[] = {
MODEL_PROP_END,
};
+static const ArmModelPropValue armv9_0_a_v1_props[] = {
+ MODEL_PROP("feat_BT", STR, "on"),
+ MODEL_PROP("feat_CSV2", STR, "1.0"),
+ MODEL_PROP("feat_CSV3", STR, "on"),
+ MODEL_PROP("feat_DPB", STR, "dpb2"),
+ MODEL_PROP("feat_E0PD", STR, "on"),
+ MODEL_PROP("feat_SB", STR, "on"),
+ MODEL_PROP("feat_SPECRES", STR, "on"),
+ MODEL_PROP("feat_SSBS", STR, "ssbs2"),
+
+ MODEL_PROP("feat_DoubleLock", STR, "off"),
+ MODEL_PROP("feat_FP", STR, "on"),
+ MODEL_PROP("feat_AdvSIMD", STR, "on"),
+ MODEL_PROP("feat_TS", STR, "flagm2"),
+ MODEL_PROP("feat_FRINTTS", STR, "on"),
+ MODEL_PROP("feat_RDM", STR, "on"),
+ MODEL_PROP("feat_DP", STR, "on"),
+ MODEL_PROP("feat_FHM", STR, "on"),
+ MODEL_PROP("feat_FCMA", STR, "on"),
+ MODEL_PROP("feat_JSCVT", STR, "on"),
+
+ MODEL_PROP("feat_SVE", STR, "on"),
+ MODEL_PROP("feat_SEL2", STR, "on"),
+ MODEL_PROP("feat_VH", STR, "on"),
+ MODEL_PROP("feat_XNX", STR, "on"),
+
+ MODEL_PROP_END,
+};
+
+
+static const ArmModelPropValue neoverse_v2_v1_props[] = {
+ MODEL_PROP("cpu_implementer", NUM, 0x41),
+ MODEL_PROP("cpu_variant", NUM, 0x0),
+ MODEL_PROP("cpu_architecture", NUM, 0xF),
+ MODEL_PROP("cpu_partnum", NUM, 0xD4F),
+ MODEL_PROP("cpu_revision", NUM, 0x2),
+
+ MODEL_PROP("hw_prop_BRPS", NUM, 0x5),
+ MODEL_PROP("hw_prop_WRPs", NUM, 0x3),
+ MODEL_PROP("hw_prop_CTX_CMPs", NUM, 0x1),
+ MODEL_PROP("feat_PMU", STR, "v3p5"),
+
+ MODEL_PROP("feat_TLB", STR, "range"),
+
+ MODEL_PROP("feat_BF16", STR, "on"),
+ MODEL_PROP("feat_DGH", STR, "on"),
+ MODEL_PROP("feat_I8MM", STR, "on"),
+
+ MODEL_PROP("feat_FP", STR, "fp16"),
+ MODEL_PROP("feat_AdvSIMD", STR, "fp16"),
+ MODEL_PROP("feat_RAS", STR, "1.1_base"),
+
+ /*
+ * V2 silicon may report CSV2=2 (FEAT_CSV2_2) per TRM page 392, but
+ * KVM clamps the guest-visible limit to 1.
+ */
+ MODEL_PROP("feat_CSV2", STR, "1.0"),
+
+ MODEL_PROP("hw_prop_PARANGE", STR, "48"),
+ MODEL_PROP("hw_prop_ASIDBITS", STR, "16"),
+ MODEL_PROP("feat_BIGEND", STR, "on"),
+ MODEL_PROP("feat_SNSMEM", STR, "on"),
+ MODEL_PROP("hw_prop_TGRAN16", STR, "on"),
+ MODEL_PROP("hw_prop_TGRAN64", STR, "on"),
+ MODEL_PROP("hw_prop_TGRAN4", STR, "on"),
+ MODEL_PROP("hw_prop_TGRAN16_2", STR, "on"),
+ MODEL_PROP("hw_prop_TGRAN64_2", STR, "on"),
+ MODEL_PROP("hw_prop_TGRAN4_2", STR, "on"),
+
+ MODEL_PROP("feat_HAFDBS", STR, "dbm"),
+ MODEL_PROP("hw_prop_VMIDBITS", STR, "16"),
+ MODEL_PROP("feat_HPDS", STR, "hpds2"),
+ MODEL_PROP("feat_PAN", STR, "pan3"),
+ MODEL_PROP("feat_ECBHB", STR, "off"),
+ MODEL_PROP("feat_SpecSEI", STR, "off"),
+
+ MODEL_PROP("hw_prop_FWB", STR, "on"),
+ MODEL_PROP("hw_prop_ST", STR, "48_47"),
+ MODEL_PROP("feat_TTL", STR, "on"),
+ MODEL_PROP("feat_BBM", STR, "2"),
+ MODEL_PROP("feat_EVT", STR, "ttlbxs"),
+ MODEL_PROP("feat_E2H0", STR, "on"),
+
+ MODEL_PROP("hw_prop_IMInline", NUM, 4),
+ MODEL_PROP("hw_prop_L1IP", STR, "pipt"),
+ MODEL_PROP("hw_prop_DMInline", NUM, 4),
+ MODEL_PROP("hw_prop_ERG", NUM, 4),
+ MODEL_PROP("hw_prop_CWG", NUM, 4),
+
+ MODEL_PROP("hw_prop_BS", NUM, 0x4),
+
+ MODEL_PROP_END,
+};
+
+
+static const ArmModelPropValue grace_v1_props[] = {
+ MODEL_PROP("cpu_revision", NUM, 0x0),
+
+ MODEL_PROP("feat_AES", STR, "pmull"),
+ MODEL_PROP("feat_SHA1", STR, "on"),
+ MODEL_PROP("feat_SHA2", STR, "sha512"),
+ MODEL_PROP("feat_SHA3", STR, "on"),
+ MODEL_PROP("feat_SM3", STR, "on"),
+ MODEL_PROP("feat_SM4", STR, "on"),
+
+ MODEL_PROP("hw_prop_IDC", BOOL, true),
+ MODEL_PROP("hw_prop_DIC", BOOL, true),
+
+ MODEL_PROP("cpu_revidr", NUM, 1),
+
+ MODEL_PROP_END,
+};
+
static const ArmNamedCpuModel arm_cpu_models[] = {
{
.name = "kvm-base-v1",
@@ -181,6 +296,21 @@ static const ArmNamedCpuModel arm_cpu_models[] = {
.parent = "neoverse-v1-v1",
.props = graviton3_v1_props,
},
+ {
+ .name = "arm-v9_0-a-v1",
+ .parent = "arm-v8_4-a-v1",
+ .props = armv9_0_a_v1_props,
+ },
+ {
+ .name = "neoverse-v2-v1",
+ .parent = "arm-v9_0-a-v1",
+ .props = neoverse_v2_v1_props,
+ },
+ {
+ .name = "grace-v1",
+ .parent = "neoverse-v2-v1",
+ .props = grace_v1_props,
+ },
};
static ARMCPUInfo arm_named_cpu_infos[ARRAY_SIZE(arm_cpu_models)];
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 12/29] target/arm/kvm: Writeback modified ID registers to KVM
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (10 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 11/29] target/arm: Add Nvidia Grace " Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 13/29] target/arm/kvm: enable writable implementation ID registers Khushit Shah
` (17 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
From: Shaju Abraham <shaju.abraham@nutanix.com>
After named CPU model is realized or host model is customized,
writeback the resulting cpu->isar.idregs[] back to KVM. Warns if
any non-writable bits differ.
For this:
- Fetch and maintain writable mask per ID register during scratch
vCPU creation.
- Try to read all ID registers values, so we don't writeback any
stale value to KVM for -cpu host.
Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/cpu-idregs.c | 1 +
target/arm/cpu-idregs.h | 1 +
target/arm/kvm.c | 160 +++++++++++++++++++++++++++++++++++++++-
target/arm/trace-events | 1 +
4 files changed, 162 insertions(+), 1 deletion(-)
diff --git a/target/arm/cpu-idregs.c b/target/arm/cpu-idregs.c
index ee6165622a..591ca54e39 100644
--- a/target/arm/cpu-idregs.c
+++ b/target/arm/cpu-idregs.c
@@ -72,6 +72,7 @@
.name = #reg, \
.fields = reg##_fields, \
.fields_count = ARRAY_SIZE(reg##_fields), \
+ .writable_mask = 0, \
},
ArmIdReg arm_idregs[NUM_ID_IDX] = {
diff --git a/target/arm/cpu-idregs.h b/target/arm/cpu-idregs.h
index 01d1b8f797..1389005099 100644
--- a/target/arm/cpu-idregs.h
+++ b/target/arm/cpu-idregs.h
@@ -71,6 +71,7 @@ typedef struct ArmIdReg {
const char *name;
struct ArmIdRegField *fields;
uint32_t fields_count;
+ uint64_t writable_mask;
} ArmIdReg;
extern ArmIdReg arm_idregs[NUM_ID_IDX];
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 7d194ea112..dc64cfbeb6 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -28,6 +28,7 @@
#include "kvm_arm.h"
#include "cpu.h"
#include "cpu-sysregs.h"
+#include "cpu-idregs.h"
#include "trace.h"
#include "internals.h"
#include "hw/pci/pci.h"
@@ -66,6 +67,12 @@ typedef struct ARMHostCPUFeatures {
static ARMHostCPUFeatures arm_host_cpu_features;
+#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) [NAME##_IDX] = #NAME,
+const char * const sysreg_names[NUM_ID_IDX] = {
+#include "cpu-sysregs.h.inc"
+};
+#undef DEF
+
/**
* kvm_arm_vcpu_init:
* @cpu: ARMCPU
@@ -244,6 +251,63 @@ static int get_host_cpu_reg(int fd, ARMHostCPUFeatures *ahcf,
return ret;
}
+static int get_host_cpu_idregs_all(int fd, ARMHostCPUFeatures *ahcf)
+{
+ int err = 0, i;
+ for (i = 0; i < NUM_ID_IDX; i++) {
+ /* Skip registers whose plumbing is not yet added. */
+ if (!arm_idregs[i].name) {
+ continue;
+ }
+
+ err |= get_host_cpu_reg(fd, ahcf, i);
+ }
+ return err;
+}
+
+static int idregs_idx_to_kvm_idx(ARMIDRegisterIdx idx)
+{
+ ARMSysRegs sysreg = id_register_sysreg[idx];
+
+ return KVM_ARM_FEATURE_ID_RANGE_IDX(
+ (sysreg >> CP_REG_ARM64_SYSREG_OP0_SHIFT) & 0x3,
+ (sysreg >> CP_REG_ARM64_SYSREG_OP1_SHIFT) & 0x7,
+ (sysreg >> CP_REG_ARM64_SYSREG_CRN_SHIFT) & 0xf,
+ (sysreg >> CP_REG_ARM64_SYSREG_CRM_SHIFT) & 0xf,
+ (sysreg >> CP_REG_ARM64_SYSREG_OP2_SHIFT) & 0x7);
+}
+
+static int get_writable_id_regs(int vmfd)
+{
+ int cap, ret, i;
+ uint64_t regs[KVM_ARM_FEATURE_ID_RANGE_SIZE] = { 0 };
+ struct reg_mask_range range = {
+ .addr = (uint64_t)(uintptr_t)regs,
+ .range = KVM_ARM_FEATURE_ID_RANGE,
+ };
+
+ cap = ioctl(vmfd, KVM_CHECK_EXTENSION,
+ KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES);
+ if (cap <= 0 || !(cap & (1 << KVM_ARM_FEATURE_ID_RANGE))) {
+ return -ENOSYS;
+ }
+
+ ret = ioctl(vmfd, KVM_ARM_GET_REG_WRITABLE_MASKS, &range);
+ if (ret) {
+ return -errno;
+ }
+
+ for (i = 0; i < NUM_ID_IDX; i++) {
+ int kidx = idregs_idx_to_kvm_idx(i);
+
+ if (kidx < 0 || kidx >= KVM_ARM_FEATURE_ID_RANGE_SIZE) {
+ continue;
+ }
+ arm_idregs[i].writable_mask = regs[kidx];
+ }
+ return 0;
+}
+
static uint32_t kvm_arm_sve_get_vls(int fd)
{
uint64_t vls[KVM_ARM64_SVE_VLS_WORDS];
@@ -455,6 +519,22 @@ static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
arm_host_cpu_features.sve_vq_supported = kvm_arm_sve_get_vls(fd);
}
}
+ /*
+ * Try to read all the ID registers. KVM does not yet support it
+ * for all registers, hence ignore the errors.
+ */
+ get_host_cpu_idregs_all(fd, ahcf);
+
+ {
+ int wret = get_writable_id_regs(fdarray[1]);
+ if (wret) {
+ warn_report("KVM_ARM_GET_REG_WRITABLE_MASKS"
+ "%s: %s",
+ wret == -ENOSYS ? " unsupported"
+ : " failed",
+ strerror(-wret));
+ }
+ }
kvm_arm_destroy_scratch_host_vcpu(fdarray);
@@ -1080,6 +1160,71 @@ void kvm_arm_cpu_pre_save(ARMCPU *cpu)
}
}
+/* same as kvm_arm_get_cpreg_ptr() but can return NULL. */
+static uint64_t *kvm_arm_find_cpreg_ptr(ARMCPU *cpu, uint64_t regidx)
+{
+ uint64_t *res;
+
+ res = bsearch(®idx, cpu->cpreg_indexes, cpu->cpreg_array_len,
+ sizeof(uint64_t), compare_u64);
+ if (!res) {
+ return NULL;
+ }
+ return &cpu->cpreg_values[res - cpu->cpreg_indexes];
+}
+
+static void kvm_arm_writeback_idregs(ARMCPU *cpu)
+{
+ for (int i = 0; i < NUM_ID_IDX; i++) {
+ uint64_t kvm_reg = idregs_sysreg_to_kvm_reg(id_register_sysreg[i]);
+ uint64_t *cpreg = kvm_arm_find_cpreg_ptr(cpu, kvm_reg);
+ const char *name = arm_idregs[i].name;
+ uint64_t writable_mask, previous, desired, diff;
+
+ if (!cpreg) {
+ warn_report("KVM does not expose ID register slot %d "
+ "(kvm_reg=0x%" PRIx64 "), %s; skipping writeback",
+ i, kvm_reg, sysreg_names[i]);
+ continue;
+ }
+
+ if (!name) {
+ /* No field table, don't push back. */
+ warn_report("ID register slot %d "
+ "(kvm_reg=0x%" PRIx64 "), %s: "
+ "no field table in cpu-idregs.inc.h",
+ i, kvm_reg, sysreg_names[i]);
+ continue;
+ }
+
+ writable_mask = arm_idregs[i].writable_mask;
+ previous = *cpreg;
+ desired = cpu->isar.idregs[i];
+ diff = previous ^ desired;
+
+ if (!diff) {
+ continue;
+ }
+
+ if (diff & ~writable_mask) {
+ warn_report("%s: non-writable bits differ: "
+ "kvm=0x%016" PRIx64
+ " desired=0x%016" PRIx64
+ " diff=0x%016" PRIx64
+ " writable=0x%016" PRIx64,
+ name, previous, desired,
+ diff & ~writable_mask,
+ writable_mask);
+ }
+
+ if (diff & writable_mask) {
+ *cpreg = (previous & ~writable_mask) |
+ (desired & writable_mask);
+ trace_kvm_arm_writeback_idreg(name, previous, *cpreg);
+ }
+ }
+}
+
bool kvm_arm_cpu_post_load(ARMCPU *cpu)
{
if (!write_list_to_kvmstate(cpu, KVM_PUT_FULL_STATE)) {
@@ -1116,6 +1261,10 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu)
fprintf(stderr, "write_kvmstate_to_list failed\n");
abort();
}
+
+ /* Re-apply named-model ID register overrides after KVM_ARM_VCPU_INIT. */
+ kvm_arm_writeback_idregs(cpu);
+
/*
* Sync the reset values also into the CPUState. This is necessary
* because the next thing we do will be a kvm_arch_put_registers()
@@ -2051,7 +2200,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;
+ }
+
+ /* Apply named-model ID register overrides on top of KVM's defaults. */
+ kvm_arm_writeback_idregs(cpu);
+ write_list_to_kvmstate(cpu, KVM_PUT_FULL_STATE);
+
+ return 0;
}
int kvm_arch_destroy_vcpu(CPUState *cs)
diff --git a/target/arm/trace-events b/target/arm/trace-events
index 8502fb3265..975236b24f 100644
--- a/target/arm/trace-events
+++ b/target/arm/trace-events
@@ -13,6 +13,7 @@ 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
+kvm_arm_writeback_idreg(const char *name, uint64_t previous, uint64_t desired) "%s overwrite 0x%"PRIx64" with 0x%"PRIx64
# cpu.c
arm_cpu_reset(uint64_t mp_aff) "cpu %" PRIu64
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 13/29] target/arm/kvm: enable writable implementation ID registers
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (11 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 12/29] target/arm/kvm: Writeback modified ID registers to KVM Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 14/29] target/arm: Validate cpu->isar.idregs[] before writeback Khushit Shah
` (16 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Enable KVM_CAP_ARM_WRITABLE_IMP_ID_REGS if the host kernel supports it.
This allows QEMU to write implementation-defined ID registers (MIDR,
REVIDR) so that named CPU models can present the correct values to the
guest instead of inheriting the host's identity.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/kvm.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index dc64cfbeb6..288b5ebe85 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -711,6 +711,13 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
}
}
+ if (kvm_check_extension(s, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS)) {
+ if (kvm_vm_enable_cap(s, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS, 0)) {
+ error_report("Failed to enable "
+ "KVM_CAP_ARM_WRITABLE_IMP_ID_REGS cap");
+ }
+ }
+
if (s->kvm_eager_split_size) {
uint32_t sizes;
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 14/29] target/arm: Validate cpu->isar.idregs[] before writeback
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (12 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 13/29] target/arm/kvm: enable writable implementation ID registers Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 15/29] target/arm/kvm: handle DCZID_EL0 specially Khushit Shah
` (15 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Before writing cpu->isar.idregs[] back to KVM, validate that every field
satisfies its declared safe-rule against the host isar->idregs[] view.
This catches values that would be unsafe to expose on the current host
(e.g. claiming a higher feature level than the host actually supports).
Introduce arm_idregs_validate_safe_rule(), which iterates over every
field defined in cpu-idregs.h.inc and checks the model value against
the host value accoiding to the field's ArmIdRegSafeRule. If the
requested value is invalid, error out, while also mentioning the
related property.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-props.c | 14 +++++++++
target/arm/arm-cpu-props.h | 1 +
target/arm/cpu-idregs.c | 64 ++++++++++++++++++++++++++++++++++++++
target/arm/cpu-idregs.h | 10 ++++++
target/arm/kvm.c | 7 +++++
5 files changed, 96 insertions(+)
diff --git a/target/arm/arm-cpu-props.c b/target/arm/arm-cpu-props.c
index d5900c0e23..3a02079ff2 100644
--- a/target/arm/arm-cpu-props.c
+++ b/target/arm/arm-cpu-props.c
@@ -486,3 +486,17 @@ const ArmCpuPropDesc *get_arm_cpu_props(void)
{
return arm_cpu_props;
}
+
+const ArmCpuPropDesc *arm_prop_for_field(ArmFieldIdx field)
+{
+ for (const ArmCpuPropDesc *p = arm_cpu_props; p->name; p++) {
+ if (p->type != ARM_PROP_FRACTIONAL && p->u.field == field) {
+ return p;
+ } else if (p->type == ARM_PROP_FRACTIONAL &&
+ (p->u.frac.base_field == field
+ || p->u.frac.frac_field == field)) {
+ return p;
+ }
+ }
+ return NULL;
+}
diff --git a/target/arm/arm-cpu-props.h b/target/arm/arm-cpu-props.h
index 9ba3f4c100..36ca39d1a7 100644
--- a/target/arm/arm-cpu-props.h
+++ b/target/arm/arm-cpu-props.h
@@ -45,5 +45,6 @@ typedef struct ArmCpuPropDesc {
void arm_add_cpu_props(Object *obj);
const ArmCpuPropDesc *get_arm_cpu_props(void);
+const ArmCpuPropDesc *arm_prop_for_field(ArmFieldIdx field);
#endif
diff --git a/target/arm/cpu-idregs.c b/target/arm/cpu-idregs.c
index 591ca54e39..84e1d8d9f1 100644
--- a/target/arm/cpu-idregs.c
+++ b/target/arm/cpu-idregs.c
@@ -12,6 +12,7 @@
#include "cpu-sysregs.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
+#include "arm-cpu-props.h"
/*
* Generate an array of architecturely defined values for each field
@@ -243,3 +244,66 @@ void arm_idregs_reset_to_defaults(ARMCPU *cpu)
}
}
}
+
+bool arm_field_check_val_safe(ArmFieldIdx field, uint64_t val,
+ const ARMISARegisters *host_isar)
+{
+ const ArmIdRegField *f = arm_get_field_desc(field);
+ uint64_t host_val;
+
+ arm_idreg_field_read(host_isar, f->idx, &host_val);
+ switch (f->safe_rule) {
+ case IDREG_SAFE_LOWER:
+ return val <= host_val;
+ case IDREG_SAFE_HIGHER:
+ return val >= host_val;
+ case IDREG_SAFE_HIGHER_OR_ZERO:
+ return val >= host_val || val == 0;
+ case IDREG_SAFE_SIGNED_LOWER:
+ return sextract64(val, 0, f->length) <=
+ sextract64(host_val, 0, f->length);
+ case IDREG_SAFE_EXACT:
+ return val == host_val || val == f->default_val;
+ case IDREG_SAFE_ANY:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+bool arm_idregs_validate_safe_rule(ARMCPU *cpu,
+ const ARMISARegisters *host_isar,
+ Error **errp)
+{
+ const ArmIdRegField *err_field = NULL;
+
+ for (int i = 0; i < NUM_ID_IDX; i++) {
+ const ArmIdReg *reg = &arm_idregs[i];
+ if (!reg->name) {
+ continue;
+ }
+
+ for (uint32_t j = 0; j < reg->fields_count; j++) {
+ uint64_t val;
+ const ArmIdRegField *f = ®->fields[j];
+ arm_idreg_field_read(&cpu->isar, f->idx, &val);
+ if (!arm_field_check_val_safe(f->idx, val, host_isar)) {
+ err_field = f;
+ error_setg(errp, "value %" PRIu64 " is not safe for field"
+ " %s.%s", val, reg->name, f->name);
+ goto ret;
+ }
+ }
+ }
+ret:
+ if (err_field) {
+ const ArmCpuPropDesc *prop = arm_prop_for_field(err_field->idx);
+ if (prop) {
+ error_prepend(errp, "Property %s: ", prop->name);
+ }
+ return false;
+ }
+
+ return true;
+}
diff --git a/target/arm/cpu-idregs.h b/target/arm/cpu-idregs.h
index 1389005099..c2ee82597e 100644
--- a/target/arm/cpu-idregs.h
+++ b/target/arm/cpu-idregs.h
@@ -86,4 +86,14 @@ bool arm_arch_val_from_name(ArmFieldIdx field, const char *name,
bool arm_field_is_idreg_any(ArmFieldIdx field);
void arm_idreg_field_reset_to_default(ARMCPU *cpu, ArmFieldIdx field);
void arm_idregs_reset_to_defaults(ARMCPU *cpu);
+
+/*
+ * Validate the ID registers values against safe values tags with host vals
+ */
+bool arm_idregs_validate_safe_rule(ARMCPU *cpu,
+ const ARMISARegisters *host_isar,
+ Error **errp);
+bool arm_field_check_val_safe(ArmFieldIdx field, uint64_t val,
+ const ARMISARegisters *host_isar);
+
#endif /* CPU_IDREGS_H */
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 288b5ebe85..46d5532061 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -2118,6 +2118,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
uint64_t psciver;
+ Error *err = NULL;
if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
error_report("KVM is not supported for this guest CPU type");
@@ -2212,6 +2213,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
return ret;
}
+ /* validate the cpu->isar.idregs[] against the host's isar.idregs[]*/
+ if (!arm_idregs_validate_safe_rule(cpu, &arm_host_cpu_features.isar, &err)) {
+ error_report_err(err);
+ return -EINVAL;
+ }
+
/* Apply named-model ID register overrides on top of KVM's defaults. */
kvm_arm_writeback_idregs(cpu);
write_list_to_kvmstate(cpu, KVM_PUT_FULL_STATE);
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 15/29] target/arm/kvm: handle DCZID_EL0 specially
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (13 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 14/29] target/arm: Validate cpu->isar.idregs[] before writeback Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 16/29] target/arm: skip GIC, COPDBG and PMU fields during KVM writeback Khushit Shah
` (14 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
DCZID_EL0 is not trapped by KVM and guest reads raw host values.
Read the host value directly and populate it in ahcf->isar.idreg.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/kvm.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 46d5532061..a12fa7571f 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -245,6 +245,18 @@ static int get_host_cpu_reg(int fd, ARMHostCPUFeatures *ahcf,
uint64_t *reg;
int ret;
+ /*
+ * DCZID_EL0 is not in KVM's sys_reg_descs[], so
+ * KVM_GET_ONE_REG will fail. Read it directly from
+ * hardware since KVM doesn't trap guest reads of it.
+ */
+ if (index == DCZID_EL0_IDX) {
+ uint64_t val;
+ asm volatile("mrs %0, DCZID_EL0" : "=r" (val));
+ ahcf->isar.idregs[index] = val;
+ return 0;
+ }
+
reg = &ahcf->isar.idregs[index];
ret = read_sys_reg64(fd, reg,
idregs_sysreg_to_kvm_reg(id_register_sysreg[index]));
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 16/29] target/arm: skip GIC, COPDBG and PMU fields during KVM writeback
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (14 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 15/29] target/arm/kvm: handle DCZID_EL0 specially Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 17/29] target/arm: Add composite property type to model definitions Khushit Shah
` (13 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
A few ID register fields must be skipped both during writeback to KVM
and during safe-rule validation:
- ID_AA64PFR0.GIC and ID_PFR1.GIC are owned by KVM's vGIC device:
when QEMU creates KVM_DEV_TYPE_ARM_VGIC_V3, the kernel sets GIC=IMP
in the VM's ID registers. named CPU model should not tamper with this
field. Hence, skip this fields during writeback and during
validation.
- Skip ID_DFR0.PMU when the field is not writable on the host, since
KVM populates it even for AArch64-only guests but does not expose it
as writable.
- ID_AA64DFR0_EL1.DebugVer (COPDBG) is always skipped because KVM
refuses writes of 0. Without this, realizing a model that does not
support AArch32 guests on a host that does support them fails.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/cpu-idregs.c | 47 +++++++++++++++++++++++++++++++++++++++++
target/arm/cpu-idregs.h | 8 +++++++
target/arm/kvm.c | 23 ++++++++++++++++++++
3 files changed, 78 insertions(+)
diff --git a/target/arm/cpu-idregs.c b/target/arm/cpu-idregs.c
index 84e1d8d9f1..91bb899571 100644
--- a/target/arm/cpu-idregs.c
+++ b/target/arm/cpu-idregs.c
@@ -307,3 +307,50 @@ ret:
return true;
}
+
+bool arm_field_is_writable(ArmFieldIdx field)
+{
+ uint64_t field_mask = arm_get_field_mask(field);
+
+ return (arm_idregs[ARM_FIELD_REG(field)].writable_mask & field_mask)
+ == field_mask;
+}
+
+bool arm_field_skip_writeback_always(ArmFieldIdx field)
+{
+ /*
+ * GIC is handled gic-version property, and the values are fabricated
+ * by KVM when the device is created. Skip writeback always.
+ *
+ * KVM does not allow writing 0 to COPDBG, this leads to an error
+ * when trying to boot model on hosts that supports Aarch32.
+ * So, skip writeback always for COPDBG for now.
+ */
+ return field == ARM_FIELD_ID_AA64PFR0_GIC
+ || field == ARM_FIELD_ID_PFR1_GIC
+ || field == ARM_FIELD_ID_DFR0_COPDBG;
+}
+
+bool arm_field_skip_writeback_if_not_writable(ArmFieldIdx field)
+{
+ /*
+ * Even for an AArch64 guest, KVM writes ARM_FIELD_ID_DFR0_PMU.
+ * Furthermore, they are not exposed as writable fields on fully
+ * AArch64 hosts. So, we skip writing them back to KVM if the field
+ * is not writable on host.
+ */
+ return field == ARM_FIELD_ID_DFR0_PMU;
+}
+
+uint64_t arm_get_field_mask(ArmFieldIdx field)
+{
+ uint64_t field_mask;
+
+ if (ARM_FIELD_LENGTH(field) == 64) {
+ field_mask = UINT64_MAX;
+ } else {
+ field_mask = ((1ULL << ARM_FIELD_LENGTH(field)) - 1)
+ << ARM_FIELD_SHIFT(field);
+ }
+ return field_mask;
+}
diff --git a/target/arm/cpu-idregs.h b/target/arm/cpu-idregs.h
index c2ee82597e..51cc5ec341 100644
--- a/target/arm/cpu-idregs.h
+++ b/target/arm/cpu-idregs.h
@@ -96,4 +96,12 @@ bool arm_idregs_validate_safe_rule(ARMCPU *cpu,
bool arm_field_check_val_safe(ArmFieldIdx field, uint64_t val,
const ARMISARegisters *host_isar);
+bool arm_field_is_writable(ArmFieldIdx field);
+
+bool arm_field_skip_writeback_always(ArmFieldIdx field);
+
+bool arm_field_skip_writeback_if_not_writable(ArmFieldIdx field);
+
+uint64_t arm_get_field_mask(ArmFieldIdx field);
+
#endif /* CPU_IDREGS_H */
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index a12fa7571f..cf6087d337 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -1225,6 +1225,29 @@ static void kvm_arm_writeback_idregs(ARMCPU *cpu)
continue;
}
+ /*
+ * Skips fields not to be written back.
+ */
+ for (int j = 0; j < arm_idregs[i].fields_count; j++) {
+ ArmFieldIdx field = arm_idregs[i].fields[j].idx;
+
+ if (arm_field_skip_writeback_always(field)) {
+ diff &= ~arm_get_field_mask(field);
+ writable_mask &= ~arm_get_field_mask(field);
+ continue;
+ }
+
+ if (arm_field_is_writable(field)) {
+ continue;
+ }
+
+ if (arm_field_skip_writeback_if_not_writable(field)) {
+ diff &= ~arm_get_field_mask(field);
+ writable_mask &= ~arm_get_field_mask(field);
+ continue;
+ }
+ }
+
if (diff & ~writable_mask) {
warn_report("%s: non-writable bits differ: "
"kvm=0x%016" PRIx64
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 17/29] target/arm: Add composite property type to model definitions
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (15 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 16/29] target/arm: skip GIC, COPDBG and PMU fields during KVM writeback Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 18/29] target/arm: define pauth composite property Khushit Shah
` (12 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Introduce ARM_MODEL_PROP_COMP, a composite type model property.
It will act as an master "on"/"off" switch for a list of sub-properties.
For example (pauth=on, appropiately set APA/GPA/...) based on the named
model.
A composite entry in the named model will have a default value either
"on" or "off" and a list of sub properties. Which will be applied on
the cpu model when the composite is turned on.
Add find_model_prop_in_chain() to walk the parent model hierarchy and
resolve a property entry (child-first). Expose arm_cpu_get_composite_
subprop() so the property layer (in a later commit) can retrieve a
composite's sub-prop values given a CPU.
Refactor arm_apply_model_props() into public arm_apply_model_prop().
Hierarchical inheritance for composite properties sub-props is not
added to avoid complexities.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-models.c | 81 +++++++++++++++----
target/arm/arm-cpu-models.h | 12 +++
target/arm/arm-cpu-props.c | 150 +++++++++++++++++++++++++++++++++++-
target/arm/arm-cpu-props.h | 7 +-
4 files changed, 233 insertions(+), 17 deletions(-)
diff --git a/target/arm/arm-cpu-models.c b/target/arm/arm-cpu-models.c
index 230768019c..4b19049205 100644
--- a/target/arm/arm-cpu-models.c
+++ b/target/arm/arm-cpu-models.c
@@ -39,6 +39,11 @@
{ .name = (_name), .type = ARM_MODEL_PROP_##_type, \
.u.MODEL_PROP_FIELD_##_type = (_value) }
+#define MODEL_PROP_COMP(_name, _b, _sub_props) \
+ { .name = (_name), .type = ARM_MODEL_PROP_COMP, \
+ .u.comp.b = (_b), \
+ .u.comp.sub_props = (_sub_props) }
+
#define MODEL_PROP_END { .name = NULL }
static const ArmModelPropValue kvm_base_v1_props[] = {
@@ -314,7 +319,7 @@ static const ArmNamedCpuModel arm_cpu_models[] = {
};
static ARMCPUInfo arm_named_cpu_infos[ARRAY_SIZE(arm_cpu_models)];
-static const ArmNamedCpuModel *arm_find_model(const char *name)
+const ArmNamedCpuModel *arm_find_model(const char *name)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(arm_cpu_models); i++) {
@@ -325,6 +330,64 @@ static const ArmNamedCpuModel *arm_find_model(const char *name)
return NULL;
}
+static const ArmModelPropValue *find_model_prop_in_chain(const char *model_name,
+ const char *prop_name)
+{
+ const ArmNamedCpuModel *model = arm_find_model(model_name);
+ if (!model) {
+ return NULL;
+ }
+
+ for (const ArmModelPropValue *prop = model->props; prop->name; prop++) {
+ if (g_str_equal(prop->name, prop_name)) {
+ return prop;
+ }
+ }
+
+ if (model->parent) {
+ return find_model_prop_in_chain(model->parent, prop_name);
+ }
+ return NULL;
+}
+
+const ArmModelPropValue *arm_cpu_get_composite_subprop(ARMCPU *cpu,
+ const char *comp)
+{
+ const char *model_name = ARM_CPU_GET_CLASS(cpu)->info->name;
+
+ const ArmModelPropValue *model_prop = find_model_prop_in_chain(model_name, comp);
+ if (!model_prop || model_prop->type != ARM_MODEL_PROP_COMP) {
+ return NULL;
+ }
+
+ return model_prop->u.comp.sub_props;
+}
+
+void arm_apply_model_prop(Object *obj, const ArmModelPropValue *prop, Error **errp)
+{
+ ERRP_GUARD();
+ switch (prop->type) {
+ case ARM_MODEL_PROP_STR:
+ object_property_set_str(obj, prop->name, prop->u.str, errp);
+ break;
+ case ARM_MODEL_PROP_BOOL:
+ object_property_set_bool(obj, prop->name, prop->u.b, errp);
+ break;
+ case ARM_MODEL_PROP_NUM:
+ object_property_set_uint(obj, prop->name, prop->u.num, errp);
+ break;
+ case ARM_MODEL_PROP_COMP:
+ object_property_set_bool(obj, prop->name, prop->u.comp.b, errp);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ if (*errp) {
+ error_prepend(errp, "property '%s': ", prop->name);
+ return;
+ }
+}
+
static void arm_apply_model_props(Object *obj, const ArmModelPropValue *props,
Error **errp)
{
@@ -332,21 +395,8 @@ static void arm_apply_model_props(Object *obj, const ArmModelPropValue *props,
ERRP_GUARD();
for (pv = props; pv->name; pv++) {
- switch (pv->type) {
- case ARM_MODEL_PROP_STR:
- object_property_set_str(obj, pv->name, pv->u.str, errp);
- break;
- case ARM_MODEL_PROP_BOOL:
- object_property_set_bool(obj, pv->name, pv->u.b, errp);
- break;
- case ARM_MODEL_PROP_NUM:
- object_property_set_uint(obj, pv->name, pv->u.num, errp);
- break;
- default:
- g_assert_not_reached();
- }
+ arm_apply_model_prop(obj, pv, errp);
if (*errp) {
- error_prepend(errp, "property '%s': ", pv->name);
return;
}
}
@@ -413,6 +463,7 @@ static void arm_named_cpu_initfn(Object *obj)
aarch64_add_sve_properties(obj);
aarch64_add_pauth_properties(obj);
arm_add_cpu_props(obj);
+ arm_add_composite_props(obj);
arm_realize_model_chain(obj, model, &error_abort);
}
diff --git a/target/arm/arm-cpu-models.h b/target/arm/arm-cpu-models.h
index 297926e167..3d4d805da8 100644
--- a/target/arm/arm-cpu-models.h
+++ b/target/arm/arm-cpu-models.h
@@ -7,11 +7,14 @@
#include "qapi/error.h"
#include "qom/object.h"
+#include "cpu.h"
+#include "qemu/typedefs.h"
typedef enum ArmModelPropType {
ARM_MODEL_PROP_STR,
ARM_MODEL_PROP_BOOL,
ARM_MODEL_PROP_NUM,
+ ARM_MODEL_PROP_COMP,
} ArmModelPropType;
typedef struct ArmModelPropValue {
@@ -21,6 +24,10 @@ typedef struct ArmModelPropValue {
bool b;
uint64_t num;
const char *str;
+ struct {
+ bool b;
+ const struct ArmModelPropValue *sub_props;
+ } comp;
} u;
} ArmModelPropValue;
@@ -32,4 +39,9 @@ typedef struct ArmNamedCpuModel {
void arm_register_named_cpu_models(void);
+const ArmNamedCpuModel *arm_find_model(const char *name);
+const ArmModelPropValue *arm_cpu_get_composite_subprop(ARMCPU *cpu, const char *comp);
+
+void arm_apply_model_prop(Object *obj, const ArmModelPropValue *prop, Error **errp);
+
#endif /* ARM_CPU_MODELS_H */
diff --git a/target/arm/arm-cpu-props.c b/target/arm/arm-cpu-props.c
index 3a02079ff2..5e876aa768 100644
--- a/target/arm/arm-cpu-props.c
+++ b/target/arm/arm-cpu-props.c
@@ -9,10 +9,12 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qapi/visitor.h"
+#include "qemu/typedefs.h"
#include "qom/object.h"
#include "cpu.h"
#include "arm-cpu-props.h"
-
+#include "cpu-idregs.h"
+#include "arm-cpu-models.h"
#define ARM_SINGLE_FIELD_PROP(prop_name, _type, reg, fld) \
{ .name = (prop_name), .type = ARM_PROP_##_type, \
@@ -38,6 +40,17 @@
.get = _get, \
.set = _set }
+#define ARM_COMPOSITE_PROP(prop_name, sub_props, _get) \
+ { .name = (prop_name), .type = ARM_PROP_COMPOSITE, \
+ .u.comp_sub_props = sub_props, \
+ .get = _get }
+
+#define ARM_COMPOSITE_PROP_GS(prop_name, sub_props, _get, _set) \
+ { .name = (prop_name), .type = ARM_PROP_COMPOSITE, \
+ .u.comp_sub_props = sub_props, \
+ .get = _get, \
+ .set = _set }
+
const ArmFracVal csv2_frac_vals[] = {
{ "0.0", 0, 0 },
{ "1.0", 1, 0 },
@@ -255,6 +268,10 @@ const ArmCpuPropDesc arm_cpu_props[] = {
{ .name = NULL }
};
+const ArmCpuPropDesc arm_composite_props[] = {
+ { .name = NULL }
+};
+
static const ArmCpuPropDesc *arm_find_prop(const char *name)
{
const ArmCpuPropDesc *p;
@@ -263,6 +280,12 @@ static const ArmCpuPropDesc *arm_find_prop(const char *name)
return p;
}
}
+
+ for (p = arm_composite_props; p->name; p++) {
+ if (g_str_equal(p->name, name)) {
+ return p;
+ }
+ }
return NULL;
}
@@ -350,6 +373,9 @@ static void arm_cpu_prop_get(Object *obj, Visitor *v, const char *name,
case ARM_PROP_FRACTIONAL:
arm_fractional_get(cpu, p, v, name, errp);
break;
+ case ARM_PROP_COMPOSITE:
+ /* Composite features must have a custom getter */
+ g_assert_not_reached();
}
}
@@ -428,6 +454,104 @@ static void arm_fractional_set(ARMCPU *cpu, const ArmCpuPropDesc *p,
g_free(str);
}
+static void arm_prop_set_default(ARMCPU *cpu, const char *name, Error **errp)
+{
+ const ArmCpuPropDesc *p = arm_find_prop(name);
+
+ if (!p) {
+ /* Sub-property can be a already present cpu property like sve* */
+ if (object_property_find(OBJECT(cpu), name)) {
+ object_property_set_bool(OBJECT(cpu), name, false, errp);
+ return;
+ }
+
+ error_setg(errp, "Property '%s': unknown sub-property", name);
+ return;
+ }
+
+ switch (p->type) {
+ case ARM_PROP_STRING:
+ case ARM_PROP_BOOLEAN:
+ case ARM_PROP_NUMERIC:
+ arm_idreg_field_reset_to_default(cpu, p->u.field);
+ break;
+ case ARM_PROP_FRACTIONAL:
+ arm_idreg_field_reset_to_default(cpu, p->u.frac.base_field);
+ arm_idreg_field_reset_to_default(cpu, p->u.frac.frac_field);
+ break;
+ case ARM_PROP_COMPOSITE:
+ object_property_set_bool(OBJECT(cpu), p->name, false, errp);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static const ArmModelPropValue *
+arm_model_prop_find_by_name(const ArmModelPropValue *props, const char *name)
+{
+ const ArmModelPropValue *pv;
+ for (pv = props; pv->name; pv++) {
+ if (g_str_equal(pv->name, name)) {
+ return pv;
+ }
+ }
+ return NULL;
+}
+
+static void arm_composite_set(ARMCPU *cpu, const ArmCpuPropDesc *p,
+ Visitor *v, const char *name, Error **errp)
+{
+ bool val;
+ const ArmModelPropValue *model_sub_props;
+ const char **sub_props;
+ ERRP_GUARD();
+
+ model_sub_props = arm_cpu_get_composite_subprop(cpu, name);
+ if (!model_sub_props) {
+ error_setg(errp, "Property '%s': unknown composite feature", name);
+ return;
+ }
+
+ sub_props = p->u.comp_sub_props;
+ if (!visit_type_bool(v, name, &val, errp)) {
+ return;
+ }
+
+ if (val) {
+ for (const char **sub_prop = sub_props; *sub_prop; sub_prop++) {
+ const ArmCpuPropDesc *sub_prop_desc = arm_find_prop(*sub_prop);
+ const ArmModelPropValue *model_sub_prop =
+ arm_model_prop_find_by_name(model_sub_props, *sub_prop);
+ if (!model_sub_prop) {
+ continue;
+ }
+ if (sub_prop_desc) {
+ assert(sub_prop_desc->type != ARM_PROP_COMPOSITE);
+ }
+
+ arm_apply_model_prop(OBJECT(cpu), model_sub_prop, errp);
+
+ if (*errp) {
+ return;
+ }
+ }
+ } else {
+ /* Disable all sub-properties */
+ for (const char **sub_prop = sub_props; *sub_prop; sub_prop++) {
+ const ArmCpuPropDesc *sub_prop_desc = arm_find_prop(*sub_prop);
+ if (sub_prop_desc) {
+ assert(sub_prop_desc->type != ARM_PROP_COMPOSITE);
+ }
+ arm_prop_set_default(cpu, *sub_prop, errp);
+
+ if (*errp) {
+ return;
+ }
+ }
+ }
+}
+
static void arm_cpu_prop_set(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -453,6 +577,9 @@ static void arm_cpu_prop_set(Object *obj, Visitor *v, const char *name,
case ARM_PROP_FRACTIONAL:
arm_fractional_set(cpu, p, v, name, errp);
break;
+ case ARM_PROP_COMPOSITE:
+ arm_composite_set(cpu, p, v, name, errp);
+ break;
}
}
@@ -487,6 +614,27 @@ const ArmCpuPropDesc *get_arm_cpu_props(void)
return arm_cpu_props;
}
+void arm_add_composite_props(Object *obj)
+{
+ const ArmCpuPropDesc *p;
+ for (p = arm_composite_props; p->name; p++) {
+ assert(p->type == ARM_PROP_COMPOSITE);
+
+ /* Replace the QEMU bare props if present. */
+ if (object_property_find(obj, p->name)) {
+ object_property_del(obj, p->name);
+ }
+
+ object_property_add(obj, p->name, "bool",
+ arm_cpu_prop_get, arm_cpu_prop_set, NULL, NULL);
+ }
+}
+
+const ArmCpuPropDesc *get_arm_composite_props(void)
+{
+ return arm_composite_props;
+}
+
const ArmCpuPropDesc *arm_prop_for_field(ArmFieldIdx field)
{
for (const ArmCpuPropDesc *p = arm_cpu_props; p->name; p++) {
diff --git a/target/arm/arm-cpu-props.h b/target/arm/arm-cpu-props.h
index 36ca39d1a7..392a0391d6 100644
--- a/target/arm/arm-cpu-props.h
+++ b/target/arm/arm-cpu-props.h
@@ -19,6 +19,7 @@ typedef enum ArmCpuPropType {
ARM_PROP_BOOLEAN,
ARM_PROP_NUMERIC,
ARM_PROP_FRACTIONAL,
+ ARM_PROP_COMPOSITE
} ArmCpuPropType;
typedef struct ArmFracVal {
@@ -37,14 +38,18 @@ typedef struct ArmCpuPropDesc {
ArmFieldIdx frac_field;
const ArmFracVal *vals;
} frac;
+ const char **comp_sub_props;
} u;
void (*get)(ARMCPU *cpu, Visitor *v, const char *name, Error **errp);
void (*set)(ARMCPU *cpu, Visitor *v, const char *name, Error **errp);
} ArmCpuPropDesc;
-void arm_add_cpu_props(Object *obj);
const ArmCpuPropDesc *get_arm_cpu_props(void);
+const ArmCpuPropDesc *get_arm_composite_props(void);
+
+void arm_add_cpu_props(Object *obj);
+void arm_add_composite_props(Object *obj);
const ArmCpuPropDesc *arm_prop_for_field(ArmFieldIdx field);
#endif
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 18/29] target/arm: define pauth composite property
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (16 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 17/29] target/arm: Add composite property type to model definitions Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 19/29] target/arm: define sve " Khushit Shah
` (11 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Define pauth composite property for named cpu model. Define a
custom getter which checks whether any PAuth algo is present.
The sub property list covers all six PAuth fields.
Add appropriate pauth composite model values for neoverse-v1-v1
and neoverse-v2-v1.
In arm_cpu_pauth_finalize(), return early if cpu is an instance of
named cpu model, as the authoritative ID regs fields values are provided
by the model in that case.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-models.c | 14 +++++++
target/arm/arm-cpu-props.c | 76 +++++++++++++++++++++++++++++++++----
target/arm/arm-cpu-props.h | 2 +
target/arm/cpu64.c | 16 ++++++++
4 files changed, 101 insertions(+), 7 deletions(-)
diff --git a/target/arm/arm-cpu-models.c b/target/arm/arm-cpu-models.c
index 4b19049205..1fe20b7d6e 100644
--- a/target/arm/arm-cpu-models.c
+++ b/target/arm/arm-cpu-models.c
@@ -84,6 +84,12 @@ static const ArmModelPropValue armv8_4_a_v1_props[] = {
MODEL_PROP_END,
};
+static const ArmModelPropValue neoverse_v1_v1_pauth_props[] = {
+ MODEL_PROP("hw_prop_APA", STR, "pauth2"),
+ MODEL_PROP("hw_prop_GPA", STR, "on"),
+ MODEL_PROP_END,
+};
+
static const ArmModelPropValue neoverse_v1_v1_props[] = {
MODEL_PROP("cpu_implementer", NUM, 0x41),
MODEL_PROP("cpu_variant", NUM, 0x1),
@@ -146,6 +152,7 @@ static const ArmModelPropValue neoverse_v1_v1_props[] = {
MODEL_PROP("hw_prop_CWG", NUM, 4),
MODEL_PROP("hw_prop_BS", NUM, 0x4),
+ MODEL_PROP_COMP("pauth", true, neoverse_v1_v1_pauth_props),
MODEL_PROP_END,
};
@@ -197,6 +204,12 @@ static const ArmModelPropValue armv9_0_a_v1_props[] = {
};
+static const ArmModelPropValue neoverse_v2_v1_pauth_props[] = {
+ MODEL_PROP("hw_prop_APA", STR, "fpaccombine"),
+ MODEL_PROP("hw_prop_GPA", STR, "on"),
+ MODEL_PROP_END,
+};
+
static const ArmModelPropValue neoverse_v2_v1_props[] = {
MODEL_PROP("cpu_implementer", NUM, 0x41),
MODEL_PROP("cpu_variant", NUM, 0x0),
@@ -257,6 +270,7 @@ static const ArmModelPropValue neoverse_v2_v1_props[] = {
MODEL_PROP("hw_prop_CWG", NUM, 4),
MODEL_PROP("hw_prop_BS", NUM, 0x4),
+ MODEL_PROP_COMP("pauth", true, neoverse_v2_v1_pauth_props),
MODEL_PROP_END,
};
diff --git a/target/arm/arm-cpu-props.c b/target/arm/arm-cpu-props.c
index 5e876aa768..11f45523a0 100644
--- a/target/arm/arm-cpu-props.c
+++ b/target/arm/arm-cpu-props.c
@@ -51,6 +51,30 @@
.get = _get, \
.set = _set }
+static void arm_composite_set_internal(ARMCPU *cpu,
+ const ArmCpuPropDesc *p,
+ bool val,
+ const char *name,
+ Error **errp);
+
+static void pauth_set(ARMCPU *cpu, Visitor *v, const char *name, Error **errp)
+{
+ bool val;
+ ERRP_GUARD();
+
+ if (!visit_type_bool(v, name, &val, errp)) {
+ return;
+ }
+
+ arm_composite_set_internal(cpu, arm_find_prop(name), val, name, errp);
+ if (*errp) {
+ error_prepend(errp, "Property '%s': ", name);
+ return;
+ }
+
+ cpu->prop_pauth = val;
+}
+
const ArmFracVal csv2_frac_vals[] = {
{ "0.0", 0, 0 },
{ "1.0", 1, 0 },
@@ -268,11 +292,32 @@ const ArmCpuPropDesc arm_cpu_props[] = {
{ .name = NULL }
};
+static const char *pauth_sub_props[] = {
+ "hw_prop_APA", "hw_prop_API", "hw_prop_APA3",
+ "hw_prop_GPA", "hw_prop_GPI", "hw_prop_GPA3",
+ NULL
+};
+
+static void pauth_get(ARMCPU *cpu, Visitor *v, const char *name, Error **errp)
+{
+ uint64_t apa, api, apa3;
+ bool pauth = false;
+
+ arm_idreg_field_read(&cpu->isar, ARM_FIELD_IDX(ID_AA64ISAR1, APA), &apa);
+ arm_idreg_field_read(&cpu->isar, ARM_FIELD_IDX(ID_AA64ISAR1, API), &api);
+ arm_idreg_field_read(&cpu->isar, ARM_FIELD_IDX(ID_AA64ISAR2, APA3), &apa3);
+
+ pauth = apa != 0 || api != 0 || apa3 != 0;
+
+ visit_type_bool(v, name, &pauth, errp);
+}
+
const ArmCpuPropDesc arm_composite_props[] = {
+ ARM_COMPOSITE_PROP_GS("pauth", pauth_sub_props, pauth_get, pauth_set),
{ .name = NULL }
};
-static const ArmCpuPropDesc *arm_find_prop(const char *name)
+const ArmCpuPropDesc *arm_find_prop(const char *name)
{
const ArmCpuPropDesc *p;
for (p = arm_cpu_props; p->name; p++) {
@@ -499,10 +544,12 @@ arm_model_prop_find_by_name(const ArmModelPropValue *props, const char *name)
return NULL;
}
-static void arm_composite_set(ARMCPU *cpu, const ArmCpuPropDesc *p,
- Visitor *v, const char *name, Error **errp)
+static void arm_composite_set_internal(ARMCPU *cpu,
+ const ArmCpuPropDesc *p,
+ bool val,
+ const char *name,
+ Error **errp)
{
- bool val;
const ArmModelPropValue *model_sub_props;
const char **sub_props;
ERRP_GUARD();
@@ -514,9 +561,6 @@ static void arm_composite_set(ARMCPU *cpu, const ArmCpuPropDesc *p,
}
sub_props = p->u.comp_sub_props;
- if (!visit_type_bool(v, name, &val, errp)) {
- return;
- }
if (val) {
for (const char **sub_prop = sub_props; *sub_prop; sub_prop++) {
@@ -552,6 +596,24 @@ static void arm_composite_set(ARMCPU *cpu, const ArmCpuPropDesc *p,
}
}
+static void arm_composite_set(ARMCPU *cpu, const ArmCpuPropDesc *p,
+ Visitor *v, const char *name, Error **errp)
+{
+ bool val;
+ ERRP_GUARD();
+
+ if (!visit_type_bool(v, name, &val, errp)) {
+ return;
+ }
+
+ arm_composite_set_internal(cpu, p, val, name, errp);
+
+ if (*errp) {
+ error_prepend(errp, "Property '%s': ", name);
+ return;
+ }
+}
+
static void arm_cpu_prop_set(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
diff --git a/target/arm/arm-cpu-props.h b/target/arm/arm-cpu-props.h
index 392a0391d6..a108dee1a4 100644
--- a/target/arm/arm-cpu-props.h
+++ b/target/arm/arm-cpu-props.h
@@ -48,6 +48,8 @@ typedef struct ArmCpuPropDesc {
const ArmCpuPropDesc *get_arm_cpu_props(void);
const ArmCpuPropDesc *get_arm_composite_props(void);
+const ArmCpuPropDesc *arm_find_prop(const char *name);
+
void arm_add_cpu_props(Object *obj);
void arm_add_composite_props(Object *obj);
const ArmCpuPropDesc *arm_prop_for_field(ArmFieldIdx field);
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 0300f8677f..d326b3220a 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -38,6 +38,8 @@
#include "internals.h"
#include "cpu-features.h"
#include "arm-cpu-props.h"
+#include "arm-cpu-models.h"
+
/* convert between <register>_IDX and SYS_<register> */
#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \
[NAME##_IDX] = SYS_##NAME,
@@ -554,6 +556,20 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
ARMISARegisters *isar = &cpu->isar;
uint64_t isar1, isar2;
+ /*
+ * For named CPU models, the model props (and the composite "pauth"
+ * setter) write the authoritative APA/API/APA3/GPA/GPI/GPA3
+ * directly into cpu->isar. Lets not override them.
+ */
+ {
+ ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu);
+ if (acc->info
+ && arm_find_model(acc->info->name)) {
+ return;
+ }
+ }
+
+
/*
* These properties enable or disable Pauth as a whole, or change
* the pauth algorithm, but do not change the set of features that
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 19/29] target/arm: define sve composite property
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (17 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 18/29] target/arm: define pauth composite property Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 20/29] target/arm: Introduce stub files required for qmp support Khushit Shah
` (10 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Define sve composite property for named cpu model. The sub-property
list contains: feat_SVE, hw_prop_SVEVer, feat_SVE_AES, feat_SVE_ELTPERM,
feat_SVE_BITPERM, feat_SVE_BFLOAT16, feat_SVE_B16B16, feat_SVE_SHA3,
feat_SVE_SM4, feat_SVE_I8MM, feat_SVE_F16MM, feat_SVE_F32MM,
feat_SVE_F64MM and sve* QEMU vector-length toggles.
Also add appropiate sve composite model values for neoverse-v1-v1,
neoverse-v2-v1 and grace-v1.
In cpu64.c mandate a SVE vector length if named cpu model enables SVE.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-models.c | 35 +++++++++++++++++++++++++++++++++++
target/arm/arm-cpu-props.c | 25 +++++++++++++++++++++++++
target/arm/cpu64.c | 14 +++++++++++++-
3 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/target/arm/arm-cpu-models.c b/target/arm/arm-cpu-models.c
index 1fe20b7d6e..8a725a0c26 100644
--- a/target/arm/arm-cpu-models.c
+++ b/target/arm/arm-cpu-models.c
@@ -90,6 +90,14 @@ static const ArmModelPropValue neoverse_v1_v1_pauth_props[] = {
MODEL_PROP_END,
};
+static const ArmModelPropValue neoverse_v1_v1_sve_props[] = {
+ MODEL_PROP("feat_SVE", STR, "on"),
+ MODEL_PROP("feat_SVE_BFLOAT16", STR, "on"),
+ MODEL_PROP("feat_SVE_I8MM", STR, "on"),
+ MODEL_PROP("sve128", BOOL, true),
+ MODEL_PROP_END,
+};
+
static const ArmModelPropValue neoverse_v1_v1_props[] = {
MODEL_PROP("cpu_implementer", NUM, 0x41),
MODEL_PROP("cpu_variant", NUM, 0x1),
@@ -153,6 +161,7 @@ static const ArmModelPropValue neoverse_v1_v1_props[] = {
MODEL_PROP("hw_prop_BS", NUM, 0x4),
MODEL_PROP_COMP("pauth", true, neoverse_v1_v1_pauth_props),
+ MODEL_PROP_COMP("sve", true, neoverse_v1_v1_sve_props),
MODEL_PROP_END,
};
@@ -210,6 +219,16 @@ static const ArmModelPropValue neoverse_v2_v1_pauth_props[] = {
MODEL_PROP_END,
};
+static const ArmModelPropValue neoverse_v2_v1_sve_props[] = {
+ MODEL_PROP("feat_SVE", STR, "on"),
+ MODEL_PROP("hw_prop_SVEVer", STR, "sve2"),
+ MODEL_PROP("feat_SVE_BFLOAT16", STR, "on"),
+ MODEL_PROP("feat_SVE_BITPERM", STR, "on"),
+ MODEL_PROP("feat_SVE_I8MM", STR, "on"),
+ MODEL_PROP("sve128", BOOL, true),
+ MODEL_PROP_END,
+};
+
static const ArmModelPropValue neoverse_v2_v1_props[] = {
MODEL_PROP("cpu_implementer", NUM, 0x41),
MODEL_PROP("cpu_variant", NUM, 0x0),
@@ -271,10 +290,25 @@ static const ArmModelPropValue neoverse_v2_v1_props[] = {
MODEL_PROP("hw_prop_BS", NUM, 0x4),
MODEL_PROP_COMP("pauth", true, neoverse_v2_v1_pauth_props),
+ MODEL_PROP_COMP("sve", true, neoverse_v2_v1_sve_props),
MODEL_PROP_END,
};
+static const ArmModelPropValue grace_v1_sve_props[] = {
+ MODEL_PROP("feat_SVE", STR, "on"),
+ MODEL_PROP("hw_prop_SVEVer", STR, "sve2"),
+ MODEL_PROP("feat_SVE_BFLOAT16", STR, "on"),
+ MODEL_PROP("feat_SVE_BITPERM", STR, "on"),
+ MODEL_PROP("feat_SVE_I8MM", STR, "on"),
+ MODEL_PROP("sve128", BOOL, true),
+
+ /* Grace SVE crypto adds */
+ MODEL_PROP("feat_SVE_AES", STR, "pmull128"),
+ MODEL_PROP("feat_SVE_SHA3", STR, "on"),
+ MODEL_PROP("feat_SVE_SM4", STR, "on"),
+ MODEL_PROP_END,
+};
static const ArmModelPropValue grace_v1_props[] = {
MODEL_PROP("cpu_revision", NUM, 0x0),
@@ -290,6 +324,7 @@ static const ArmModelPropValue grace_v1_props[] = {
MODEL_PROP("hw_prop_DIC", BOOL, true),
MODEL_PROP("cpu_revidr", NUM, 1),
+ MODEL_PROP_COMP("sve", true, grace_v1_sve_props),
MODEL_PROP_END,
};
diff --git a/target/arm/arm-cpu-props.c b/target/arm/arm-cpu-props.c
index 11f45523a0..94672040c5 100644
--- a/target/arm/arm-cpu-props.c
+++ b/target/arm/arm-cpu-props.c
@@ -298,6 +298,20 @@ static const char *pauth_sub_props[] = {
NULL
};
+static const char *sve_sub_props[] = {
+ "feat_SVE", "hw_prop_SVEVer", "feat_SVE_AES",
+ "feat_SVE_ELTPERM", "feat_SVE_BITPERM",
+ "feat_SVE_BFLOAT16", "feat_SVE_B16B16",
+ "feat_SVE_SHA3", "feat_SVE_SM4", "feat_SVE_I8MM",
+ "feat_SVE_F16MM", "feat_SVE_F32MM", "feat_SVE_F64MM",
+ /* QEMU vector-length toggles */
+ "sve128", "sve256", "sve384", "sve512",
+ "sve640", "sve768", "sve896", "sve1024",
+ "sve1152", "sve1280", "sve1408", "sve1536",
+ "sve1664", "sve1792", "sve1920", "sve2048",
+ NULL
+};
+
static void pauth_get(ARMCPU *cpu, Visitor *v, const char *name, Error **errp)
{
uint64_t apa, api, apa3;
@@ -312,8 +326,19 @@ static void pauth_get(ARMCPU *cpu, Visitor *v, const char *name, Error **errp)
visit_type_bool(v, name, &pauth, errp);
}
+static void sve_get(ARMCPU *cpu, Visitor *v, const char *name, Error **errp)
+{
+ uint64_t sve;
+ bool sve_enabled = false;
+
+ arm_idreg_field_read(&cpu->isar, ARM_FIELD_IDX(ID_AA64PFR0, SVE), &sve);
+ sve_enabled = sve != 0;
+ visit_type_bool(v, name, &sve_enabled, errp);
+}
+
const ArmCpuPropDesc arm_composite_props[] = {
ARM_COMPOSITE_PROP_GS("pauth", pauth_sub_props, pauth_get, pauth_set),
+ ARM_COMPOSITE_PROP("sve", sve_sub_props, sve_get),
{ .name = NULL }
};
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index d326b3220a..2fa5b4d9da 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -134,6 +134,19 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
return;
}
+ /*
+ * If SVE is enabled but no vector lengths are specified, we must not
+ * default to the host's supported lengths for named CPU models, as
+ * this breaks live migration.
+ */
+ {
+ ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu);
+ if (acc->info && arm_find_model(acc->info->name)) {
+ error_setg(errp, "Named CPU models with SVE must set vector lengths");
+ return;
+ }
+ }
+
if (kvm_enabled()) {
/* Disabling a supported length disables all larger lengths. */
tmp = vq_init & vq_supported;
@@ -569,7 +582,6 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
}
}
-
/*
* These properties enable or disable Pauth as a whole, or change
* the pauth algorithm, but do not change the set of features that
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 20/29] target/arm: Introduce stub files required for qmp support
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (18 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 19/29] target/arm: define sve " Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 21/29] target/arm/qmp: add named models and properties to cpu-model-expansion Khushit Shah
` (9 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Add arm-cpu-props-stub.c and arm-cpu-models-stub.c, which will be
required to add qmp support.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-models-stub.c | 13 +++++++++++++
target/arm/arm-cpu-props-stub.c | 23 +++++++++++++++++++++++
target/arm/meson.build | 2 +-
3 files changed, 37 insertions(+), 1 deletion(-)
create mode 100644 target/arm/arm-cpu-models-stub.c
create mode 100644 target/arm/arm-cpu-props-stub.c
diff --git a/target/arm/arm-cpu-models-stub.c b/target/arm/arm-cpu-models-stub.c
new file mode 100644
index 0000000000..0481f0f946
--- /dev/null
+++ b/target/arm/arm-cpu-models-stub.c
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * ARM named CPU model definitions - stub implementation.
+ */
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "arm-cpu-models.h"
+
+
+const ArmNamedCpuModel *arm_find_model(const char *name)
+{
+ return NULL;
+}
diff --git a/target/arm/arm-cpu-props-stub.c b/target/arm/arm-cpu-props-stub.c
new file mode 100644
index 0000000000..abac29ae50
--- /dev/null
+++ b/target/arm/arm-cpu-props-stub.c
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * ARM CPU feature properties - stub implementation.
+ */
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "arm-cpu-props.h"
+
+const ArmCpuPropDesc *arm_find_prop(const char *name)
+{
+ return NULL;
+}
+
+static const ArmCpuPropDesc empty_props[] = { {.name = NULL} };
+const ArmCpuPropDesc *get_arm_cpu_props(void)
+{
+ return empty_props;
+}
+
+const ArmCpuPropDesc *get_arm_composite_props(void)
+{
+ return empty_props;
+}
diff --git a/target/arm/meson.build b/target/arm/meson.build
index a7638f8778..63d038f285 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -14,7 +14,7 @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
'cpu-idregs.c',
'arm-cpu-props.c',
'arm-cpu-models.c',
-))
+), if_false: files('arm-cpu-props-stub.c', 'arm-cpu-models-stub.c'))
arm_common_ss.add(files(
'mmuidx.c',
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 21/29] target/arm/qmp: add named models and properties to cpu-model-expansion
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (19 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 20/29] target/arm: Introduce stub files required for qmp support Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 22/29] target/arm/kvm: introduce kvm_arm_get_host_isar helper Khushit Shah
` (8 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Update qmp_query_cpu_model_expansion() to include and process the new
arm_cpu_props and composite properties under KVM. Also, allow expansion
of the new named CPU models themselves.
Process named model properties separately from standard advertised
features to avoid double processing of properties like sve/pauth.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-qmp-cmds.c | 71 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)
diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
index 83ec95c290..7cb74b4b8d 100644
--- a/target/arm/arm-qmp-cmds.c
+++ b/target/arm/arm-qmp-cmds.c
@@ -32,6 +32,8 @@
#include "qobject/qdict.h"
#include "qom/qom-qobject.h"
#include "cpu.h"
+#include "arm-cpu-props.h"
+#include "arm-cpu-models.h"
static GICCapability *gic_cap_new(int version)
{
@@ -89,6 +91,7 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
ObjectClass *oc;
Object *obj;
const char *name;
+ bool named_model = (arm_find_model(model->name) != NULL);
int i;
if (type != CPU_MODEL_EXPANSION_TYPE_FULL) {
@@ -101,6 +104,11 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
return NULL;
}
+ if (!kvm_enabled() && named_model) {
+ error_setg(errp, "The CPU type '%s' requires KVM", model->name);
+ return NULL;
+ }
+
oc = cpu_class_by_name(TYPE_ARM_CPU, model->name);
if (!oc) {
error_setg(errp, "The CPU type '%s' is not a recognized ARM CPU type",
@@ -114,6 +122,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
/* These are kvmarm's recommended cpu types */
supported = true;
+ } else if (named_model) {
+ supported = true;
} else if (current_machine->cpu_type) {
const char *cpu_type = current_machine->cpu_type;
int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
@@ -148,12 +158,38 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
i = 0;
while ((name = cpu_model_advertised_features[i++]) != NULL) {
if (qdict_get(qdict_in, name)) {
+ if (named_model && arm_find_prop(name)) {
+ /*
+ * For named model prop; the processing is done later.
+ * for -cpu host this does not double process as the
+ * arm_cpu_props are distinct from
+ * cpu_model_advertised_features.
+ */
+ continue;
+ }
if (!object_property_set(obj, name, visitor, &err)) {
break;
}
}
}
+ if (kvm_enabled()) {
+ /* Set properties in order of model->props definition */
+ const QDictEntry *entry;
+ for (entry = qdict_first(qdict_in);
+ entry; entry = qdict_next(qdict_in, entry)) {
+ const char *nm = qdict_entry_key(entry);
+
+ if (!arm_find_prop(nm)) {
+ continue;
+ }
+
+ if (!object_property_set(obj, nm, visitor, &err)) {
+ break;
+ }
+ }
+ }
+
if (!err) {
visit_check_struct(visitor, &err);
}
@@ -180,7 +216,7 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
i = 0;
while ((name = cpu_model_advertised_features[i++]) != NULL) {
ObjectProperty *prop = object_property_find(obj, name);
- if (prop) {
+ if (prop && !(named_model && arm_find_prop(name))) {
QObject *value;
assert(prop->get);
@@ -190,6 +226,39 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
}
}
+ if (kvm_enabled()) {
+ const ArmCpuPropDesc *props = get_arm_cpu_props();
+ for (i = 0; props[i].name; i++) {
+ ObjectProperty *prop = object_property_find(obj, props[i].name);
+
+ if (prop) {
+ QObject *value;
+
+ assert(prop->get);
+ value = object_property_get_qobject(obj, props[i].name,
+ &error_abort);
+ qdict_put_obj(qdict_out, props[i].name, value);
+ }
+ }
+
+ if (named_model) {
+
+ const ArmCpuPropDesc *composite_props = get_arm_composite_props();
+ for (i = 0; composite_props[i].name; i++) {
+ ObjectProperty *prop = object_property_find(obj, composite_props[i].name);
+
+ if (prop) {
+ QObject *value;
+
+ assert(prop->get);
+ value = object_property_get_qobject(obj, composite_props[i].name,
+ &error_abort);
+ qdict_put_obj(qdict_out, composite_props[i].name, value);
+ }
+ }
+ }
+ }
+
if (!qdict_size(qdict_out)) {
qobject_unref(qdict_out);
} else {
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 22/29] target/arm/kvm: introduce kvm_arm_get_host_isar helper
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (20 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 21/29] target/arm/qmp: add named models and properties to cpu-model-expansion Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 23/29] target/arm/qmp: add query-arm-cpu-props-info Khushit Shah
` (7 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Introduce kvm_arm_get_host_isar() to provide scratch vCPU probed host
isar. Will be used in future commits.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/kvm-stub.c | 5 +++++
target/arm/kvm.c | 5 +++++
target/arm/kvm_arm.h | 4 ++++
3 files changed, 14 insertions(+)
diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c
index 88cbe8d85c..dd683beaaf 100644
--- a/target/arm/kvm-stub.c
+++ b/target/arm/kvm-stub.c
@@ -119,3 +119,8 @@ char *kvm_print_register_name(uint64_t regidx)
{
g_assert_not_reached();
}
+
+const ARMISARegisters *kvm_arm_get_host_isar(void)
+{
+ return NULL;
+}
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index cf6087d337..b4544f3514 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -597,6 +597,11 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
env->features = arm_host_cpu_features.features;
}
+const ARMISARegisters *kvm_arm_get_host_isar(void)
+{
+ return &arm_host_cpu_features.isar;
+}
+
static bool kvm_no_adjvtime_get(Object *obj, Error **errp)
{
return !ARM_CPU(obj)->kvm_adjvtime;
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index e7c40fb003..750dbe1ef4 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -15,6 +15,8 @@
#include "system/kvm.h"
#include "target/arm/cpu-qom.h"
+typedef struct ARMISARegisters ARMISARegisters;
+
#define KVM_ARM_VGIC_V2 (1 << 0)
#define KVM_ARM_VGIC_V3 (1 << 1)
@@ -229,6 +231,8 @@ void kvm_arm_enable_mte(Object *cpuobj, Error **errp);
void arm_cpu_kvm_set_irq(void *arm_cpu, int irq, int level);
+const ARMISARegisters *kvm_arm_get_host_isar(void);
+
void arm_gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3);
/*
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 23/29] target/arm/qmp: add query-arm-cpu-props-info
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (21 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 22/29] target/arm/kvm: introduce kvm_arm_get_host_isar helper Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-19 9:25 ` Markus Armbruster
2026-06-19 9:51 ` Daniel P. Berrangé
2026-06-05 8:33 ` [RFC PATCH v2 24/29] target/arm: Report "off" for ID fields gated by vCPU init flags Khushit Shah
` (6 subsequent siblings)
29 siblings, 2 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Introduce 'query-arm-cpu-props-info' QMP command. This command returns
information about ARM CPU model properties, including their name, type,
supported values on the given host, and composite parent if any.
This provides management layer necessary information to determine
migration compatibility off a VM on different host.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
qapi/misc-arm.json | 41 ++++++++++++++++
stubs/qmp-arm-gic.c | 6 +++
target/arm/arm-cpu-props-stub.c | 13 +++++
target/arm/arm-cpu-props.c | 85 +++++++++++++++++++++++++++++++++
target/arm/arm-cpu-props.h | 5 ++
target/arm/arm-qmp-cmds.c | 44 +++++++++++++++++
target/arm/cpu-idregs.c | 71 +++++++++++++++++++++++++++
target/arm/cpu-idregs.h | 8 ++++
8 files changed, 273 insertions(+)
diff --git a/qapi/misc-arm.json b/qapi/misc-arm.json
index 4dc66d00e5..1a3fb140c4 100644
--- a/qapi/misc-arm.json
+++ b/qapi/misc-arm.json
@@ -46,6 +46,47 @@
##
{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] }
+##
+# @CpuPropInfo:
+#
+# Information about a specific ARM CPU model property.
+#
+# @name: the name of the property
+#
+# @type: the type of the property, any of ('string', 'boolean',
+# 'number').
+#
+# @supported-values: the set of values the host hardware supports
+# for the property, a list of strings.
+#
+# @composite: name of the encapsulating composite property if any.
+#
+# Since: 11.1
+##
+{ 'struct': 'CpuPropInfo',
+ 'data': { 'name': 'str',
+ 'type': 'str',
+ 'supported-values': 'any',
+ '*composite': 'str' } }
+
+##
+# @query-arm-cpu-props-info:
+#
+# Returns information about most of ARM CPU named model properties.
+# This does not include composite properties or properties already
+# defined by QEMU like (sveNNNN, pmu, etc), This only returns all
+# the newly defined properties like ('feat_*', 'hw_prop_*', etc).
+#
+# With this upper management layers can find out what property values
+# are supported on the given host.
+#
+# Requires KVM to be enabled.
+#
+# Since: 11.1
+##
+{ 'command': 'query-arm-cpu-props-info',
+ 'returns': ['CpuPropInfo'] }
+
##
# @SsidSizeMode:
#
diff --git a/stubs/qmp-arm-gic.c b/stubs/qmp-arm-gic.c
index b3429243ef..1691401bf0 100644
--- a/stubs/qmp-arm-gic.c
+++ b/stubs/qmp-arm-gic.c
@@ -10,3 +10,9 @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
error_setg(errp, "GIC hardware is not available on this target");
return NULL;
}
+
+CpuPropInfoList *qmp_query_arm_cpu_props_info(Error **errp)
+{
+ error_setg(errp, "ARM CPU properties are not available on this target");
+ return NULL;
+}
diff --git a/target/arm/arm-cpu-props-stub.c b/target/arm/arm-cpu-props-stub.c
index abac29ae50..1d0a3f676c 100644
--- a/target/arm/arm-cpu-props-stub.c
+++ b/target/arm/arm-cpu-props-stub.c
@@ -11,6 +11,19 @@ const ArmCpuPropDesc *arm_find_prop(const char *name)
return NULL;
}
+void arm_prop_append_supported_values(const ArmCpuPropDesc *prop,
+ const ARMISARegisters *host_isar,
+ QList *out)
+{
+ return;
+
+}
+
+const ArmCpuPropDesc *arm_prop_get_composite_of(const ArmCpuPropDesc *prop)
+{
+ return NULL;
+}
+
static const ArmCpuPropDesc empty_props[] = { {.name = NULL} };
const ArmCpuPropDesc *get_arm_cpu_props(void)
{
diff --git a/target/arm/arm-cpu-props.c b/target/arm/arm-cpu-props.c
index 94672040c5..dab7786622 100644
--- a/target/arm/arm-cpu-props.c
+++ b/target/arm/arm-cpu-props.c
@@ -15,6 +15,8 @@
#include "arm-cpu-props.h"
#include "cpu-idregs.h"
#include "arm-cpu-models.h"
+#include "qobject/qlist.h"
+
#define ARM_SINGLE_FIELD_PROP(prop_name, _type, reg, fld) \
{ .name = (prop_name), .type = ARM_PROP_##_type, \
@@ -735,3 +737,86 @@ const ArmCpuPropDesc *arm_prop_for_field(ArmFieldIdx field)
}
return NULL;
}
+
+static void append_str_to_qlist(const char *name, uint64_t value, void *opaque)
+{
+ QList *list = opaque;
+ qlist_append_str(list, name);
+}
+
+void arm_prop_append_supported_values(const ArmCpuPropDesc *prop,
+ const ARMISARegisters *host_isar,
+ QList *out)
+{
+ switch (prop->type) {
+ case ARM_PROP_STRING:
+ arm_field_foreach_supported_arch_val(prop->u.field, host_isar,
+ append_str_to_qlist, out);
+ break;
+
+ case ARM_PROP_BOOLEAN: {
+ uint64_t host_val;
+ arm_idreg_field_read(host_isar, prop->u.field, &host_val);
+
+ if (!arm_field_is_writable(prop->u.field)) {
+ qlist_append_str(out, host_val ? "on" : "off");
+ } else {
+ if (arm_field_check_val_safe(prop->u.field, 0, host_isar)) {
+ qlist_append_str(out, "off");
+ }
+ if (arm_field_check_val_safe(prop->u.field, 1, host_isar)) {
+ qlist_append_str(out, "on");
+ }
+ }
+ break;
+ }
+
+ case ARM_PROP_NUMERIC: {
+ g_autofree char *range =
+ arm_field_supported_numeric_range(prop->u.field, host_isar);
+ qlist_append_str(out, range);
+ break;
+ }
+
+ case ARM_PROP_FRACTIONAL: {
+ const ArmFracVal *fv;
+ uint64_t host_base_val;
+ uint64_t host_frac_val;
+
+ arm_idreg_field_read(host_isar, prop->u.frac.base_field,
+ &host_base_val);
+ arm_idreg_field_read(host_isar, prop->u.frac.frac_field,
+ &host_frac_val);
+
+ for (fv = prop->u.frac.vals; fv->name; fv++) {
+ if (arm_field_check_val_safe(prop->u.frac.base_field,
+ fv->base_val, host_isar) &&
+ arm_field_check_val_safe(prop->u.frac.frac_field,
+ fv->frac_val, host_isar) &&
+ (arm_field_is_writable(prop->u.frac.base_field) ||
+ fv->base_val == host_base_val) &&
+ (arm_field_is_writable(prop->u.frac.frac_field) ||
+ fv->frac_val == host_frac_val)) {
+ qlist_append_str(out, fv->name);
+ }
+ }
+ break;
+ }
+
+ default:
+ g_assert_not_reached();
+ }
+}
+
+const ArmCpuPropDesc *arm_prop_get_composite_of(const ArmCpuPropDesc *prop)
+{
+ for (const ArmCpuPropDesc *p = arm_composite_props; p->name; p++) {
+ for (const char **sub_prop = p->u.comp_sub_props; *sub_prop; sub_prop++) {
+ if (g_str_equal(*sub_prop, prop->name)) {
+ return p;
+ }
+ }
+ }
+
+ return NULL;
+}
diff --git a/target/arm/arm-cpu-props.h b/target/arm/arm-cpu-props.h
index a108dee1a4..264a8a71de 100644
--- a/target/arm/arm-cpu-props.h
+++ b/target/arm/arm-cpu-props.h
@@ -13,6 +13,7 @@
#include "cpu-idregs.h"
#include "cpu.h"
#include "qemu/typedefs.h"
+#include "qobject/qlist.h"
typedef enum ArmCpuPropType {
ARM_PROP_STRING,
@@ -50,8 +51,12 @@ const ArmCpuPropDesc *get_arm_composite_props(void);
const ArmCpuPropDesc *arm_find_prop(const char *name);
+const ArmCpuPropDesc *arm_prop_get_composite_of(const ArmCpuPropDesc *prop);
void arm_add_cpu_props(Object *obj);
void arm_add_composite_props(Object *obj);
const ArmCpuPropDesc *arm_prop_for_field(ArmFieldIdx field);
+void arm_prop_append_supported_values(const ArmCpuPropDesc *prop,
+ const ARMISARegisters *host_isar,
+ QList *out);
#endif
diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
index 7cb74b4b8d..9bdf85885f 100644
--- a/target/arm/arm-qmp-cmds.c
+++ b/target/arm/arm-qmp-cmds.c
@@ -34,6 +34,7 @@
#include "cpu.h"
#include "arm-cpu-props.h"
#include "arm-cpu-models.h"
+#include "qobject/qlist.h"
static GICCapability *gic_cap_new(int version)
{
@@ -63,6 +64,49 @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
return head;
}
+CpuPropInfoList *qmp_query_arm_cpu_props_info(Error **errp)
+{
+ CpuPropInfoList *info = NULL;
+ CpuPropInfo *prop_info;
+ QList *sv;
+ int i;
+ const ArmCpuPropDesc *props = get_arm_cpu_props();
+
+ if (!kvm_enabled()) {
+ error_setg(errp, "query-arm-cpu-props-info requires KVM");
+ return NULL;
+ }
+
+ for (i = 0; props[i].name; i++) {
+ const ArmCpuPropDesc *pdesc = &props[i];
+ const ArmCpuPropDesc *composite_of = arm_prop_get_composite_of(pdesc);
+
+ prop_info = g_new0(CpuPropInfo, 1);
+ prop_info->name = g_strdup(pdesc->name);
+ prop_info->type = g_strdup(pdesc->type == ARM_PROP_STRING ? "string" :
+ pdesc->type == ARM_PROP_BOOLEAN ? "boolean" :
+ pdesc->type == ARM_PROP_NUMERIC ? "number" :
+ pdesc->type == ARM_PROP_FRACTIONAL ? "string" :
+ "unknown");
+
+ sv = qlist_new();
+ arm_prop_append_supported_values(pdesc,
+ kvm_arm_get_host_isar(),
+ sv);
+
+ prop_info->supported_values = QOBJECT(sv);
+ prop_info->composite = NULL;
+
+ if (composite_of) {
+ prop_info->composite = g_strdup(composite_of->name);
+ }
+
+ QAPI_LIST_PREPEND(info, prop_info);
+ }
+
+ return info;
+}
+
QEMU_BUILD_BUG_ON(ARM_MAX_VQ > 16);
/*
diff --git a/target/arm/cpu-idregs.c b/target/arm/cpu-idregs.c
index 91bb899571..7671925869 100644
--- a/target/arm/cpu-idregs.c
+++ b/target/arm/cpu-idregs.c
@@ -354,3 +354,74 @@ uint64_t arm_get_field_mask(ArmFieldIdx field)
}
return field_mask;
}
+
+void arm_field_foreach_supported_arch_val(ArmFieldIdx field,
+ const ARMISARegisters *host_isar,
+ ArmFieldValVisitor fn, void *opaque)
+{
+ const ArmIdRegField *f = arm_get_field_desc(field);
+ uint64_t host_val;
+
+ assert(!arm_field_is_idreg_any(field));
+
+ arm_idreg_field_read(host_isar, field, &host_val);
+
+ if (!arm_field_is_writable(field)) {
+ const char *name = arm_arch_val_name(field, host_val);
+ if (name) {
+ fn(name, host_val, opaque);
+ }
+ return;
+ }
+
+ for (uint32_t i = 0; i < f->arch_vals_count; i++) {
+ if (f->arch_vals[i].name &&
+ arm_field_check_val_safe(f->idx, f->arch_vals[i].value, host_isar)) {
+ fn(f->arch_vals[i].name, f->arch_vals[i].value, opaque);
+ }
+ }
+}
+
+char *arm_field_supported_numeric_range(ArmFieldIdx field,
+ const ARMISARegisters *host_isar)
+{
+ const ArmIdRegField *f = arm_get_field_desc(field);
+ uint64_t host_val;
+ uint64_t max;
+
+ if (f->length == 64) {
+ max = UINT64_MAX;
+ } else {
+ max = (1ULL << f->length) - 1;
+ }
+
+ arm_idreg_field_read(host_isar, field, &host_val);
+
+ if (!arm_field_is_writable(field)) {
+ return g_strdup_printf("%" PRIu64, host_val);
+ }
+
+ switch (f->safe_rule) {
+ case IDREG_SAFE_LOWER:
+ return g_strdup_printf("0-%" PRIu64, host_val);
+ case IDREG_SAFE_HIGHER:
+ return g_strdup_printf("%" PRIu64 "-%" PRIu64, host_val, max);
+ case IDREG_SAFE_HIGHER_OR_ZERO:
+ if (host_val <= 1) {
+ return g_strdup_printf("0-%" PRIu64, max);
+ }
+ return g_strdup_printf("0,%" PRIu64 "-%" PRIu64, host_val, max);
+ case IDREG_SAFE_SIGNED_LOWER:
+ g_assert_not_reached();
+ case IDREG_SAFE_EXACT:
+ if (f->default_val != host_val) {
+ return g_strdup_printf("%" PRIu64 ",%" PRIu64,
+ f->default_val, host_val);
+ }
+ return g_strdup_printf("%" PRIu64, host_val);
+ case IDREG_SAFE_ANY:
+ return g_strdup_printf("0-%" PRIu64, max);
+ default:
+ return g_strdup_printf("%" PRIu64, host_val);
+ }
+}
diff --git a/target/arm/cpu-idregs.h b/target/arm/cpu-idregs.h
index 51cc5ec341..171e03eece 100644
--- a/target/arm/cpu-idregs.h
+++ b/target/arm/cpu-idregs.h
@@ -104,4 +104,12 @@ bool arm_field_skip_writeback_if_not_writable(ArmFieldIdx field);
uint64_t arm_get_field_mask(ArmFieldIdx field);
+typedef void (*ArmFieldValVisitor)(const char *name, uint64_t value,
+ void *opaque);
+void arm_field_foreach_supported_arch_val(ArmFieldIdx field,
+ const ARMISARegisters *host_isar,
+ ArmFieldValVisitor fn, void *opaque);
+char *arm_field_supported_numeric_range(ArmFieldIdx field,
+ const ARMISARegisters *host_isar);
+
#endif /* CPU_IDREGS_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 24/29] target/arm: Report "off" for ID fields gated by vCPU init flags
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (22 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 23/29] target/arm/qmp: add query-arm-cpu-props-info Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 25/29] target/arm/qmp: hook blockers in query-cpu-definitions Khushit Shah
` (5 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
When QEMU queries supported CPU properties via KVM, it uses a scratch
vCPU initialized with all host-supported features (like SVE and PAuth).
KVM exposes the corresponding ID register fields (e.g.,
ID_AA64ISAR1_EL1.APA) as read-only, the supported values only shows the
enabled host value (e.g., "fpaccombine") and omits "off". This will lead
into falsely flagging a model as blocked as the features can be masked
by not passing those flags.
This commit introduces arm_field_supports_off_via_vcpu_flags() at the
ID regs level to identify such fields. For these fields, even if KVM
reports them as non-writable, we explicitly append "off" to the list of
supported values if the host value is non-zero.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/cpu-idregs.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/target/arm/cpu-idregs.c b/target/arm/cpu-idregs.c
index 7671925869..1ec1a38866 100644
--- a/target/arm/cpu-idregs.c
+++ b/target/arm/cpu-idregs.c
@@ -355,6 +355,29 @@ uint64_t arm_get_field_mask(ArmFieldIdx field)
return field_mask;
}
+/*
+ * Some fields which may not be writable but can be disabled or set
+ * to host by not passing appropiate vCPU init flags.
+ * These is needed because supported values are derived from scract-vCPU.
+ * Actual vCPU and scratch vCPU might have different init flags.
+ */
+static bool arm_field_supports_off_via_vcpu_flags(ArmFieldIdx field)
+{
+ /* sve and pauth can be disabled by not passing appropiate vCPU init flags */
+ switch (field) {
+ case ARM_FIELD_ID_AA64PFR0_SVE:
+ case ARM_FIELD_ID_AA64ISAR1_APA:
+ case ARM_FIELD_ID_AA64ISAR1_API:
+ case ARM_FIELD_ID_AA64ISAR2_APA3:
+ case ARM_FIELD_ID_AA64ISAR1_GPA:
+ case ARM_FIELD_ID_AA64ISAR2_GPA3:
+ case ARM_FIELD_ID_AA64ISAR1_GPI:
+ return true;
+ default:
+ return false;
+ }
+}
+
void arm_field_foreach_supported_arch_val(ArmFieldIdx field,
const ARMISARegisters *host_isar,
ArmFieldValVisitor fn, void *opaque)
@@ -371,6 +394,16 @@ void arm_field_foreach_supported_arch_val(ArmFieldIdx field,
if (name) {
fn(name, host_val, opaque);
}
+
+ /* not writable, but can be disabled. */
+ if (arm_field_supports_off_via_vcpu_flags(field) && host_val != 0) {
+ uint64_t off_val = 0;
+ const char *off_name = arm_arch_val_name(field, off_val);
+ if (off_name) {
+ fn(off_name, off_val, opaque);
+ }
+ }
+
return;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 25/29] target/arm/qmp: hook blockers in query-cpu-definitions
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (23 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 24/29] target/arm: Report "off" for ID fields gated by vCPU init flags Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 26/29] target/arm: Support exposing cache information for named cpu models Khushit Shah
` (4 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Now, report blocker for named cpu models in query-cpu-definitions.
Heavy handling is done by validating the realized ID registers values
against the host values. sveNNNN needs special handling as those
are not stored in any ID registers.
Introduces arm_cpu_class_check_missing_features() and
arm_idregs_get_blocker() to achieve this.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-models-stub.c | 5 ++++
target/arm/arm-cpu-models.c | 34 ++++++++++++++++++++++
target/arm/arm-cpu-models.h | 2 ++
target/arm/arm-qmp-cmds.c | 12 ++++++++
target/arm/cpu-idregs.c | 48 ++++++++++++++++++++++++++++++++
target/arm/cpu-idregs.h | 3 ++
6 files changed, 104 insertions(+)
diff --git a/target/arm/arm-cpu-models-stub.c b/target/arm/arm-cpu-models-stub.c
index 0481f0f946..dadd3b7647 100644
--- a/target/arm/arm-cpu-models-stub.c
+++ b/target/arm/arm-cpu-models-stub.c
@@ -11,3 +11,8 @@ const ArmNamedCpuModel *arm_find_model(const char *name)
{
return NULL;
}
+
+void arm_cpu_class_check_missing_features(ARMCPUClass *acc, strList **blockers)
+{
+ return;
+}
diff --git a/target/arm/arm-cpu-models.c b/target/arm/arm-cpu-models.c
index 8a725a0c26..3eafa0efc5 100644
--- a/target/arm/arm-cpu-models.c
+++ b/target/arm/arm-cpu-models.c
@@ -517,6 +517,40 @@ static void arm_named_cpu_initfn(Object *obj)
arm_realize_model_chain(obj, model, &error_abort);
}
+void arm_cpu_class_check_missing_features(ARMCPUClass *acc, strList **blockers)
+{
+ Error *err = NULL;
+ Object *obj = object_new_with_class(OBJECT_CLASS(acc));
+ ARMCPU *cpu = ARM_CPU(obj);
+
+ if (!kvm_enabled() || !arm_find_model(acc->info->name)) {
+ goto out;
+ }
+
+ if (cpu_isar_feature(aa64_sve, cpu)) {
+ arm_cpu_sve_finalize(cpu, &err);
+ if (err) {
+ error_free(err);
+ uint32_t host_vq_map = cpu->sve_vq.supported;
+ uint32_t model_vq_map = cpu->sve_vq.map;
+
+ if ((model_vq_map & host_vq_map) != model_vq_map) {
+ for (int vq = 1; vq <= ARM_MAX_VQ; vq++) {
+ uint32_t vq_bit = (1 << (vq - 1));
+ if ((model_vq_map & vq_bit) && !(host_vq_map & vq_bit)) {
+ QAPI_LIST_PREPEND(*blockers,
+ g_strdup_printf("sve%d", vq * 128));
+ }
+ }
+ }
+ }
+ }
+
+ arm_idregs_get_blockers(cpu, kvm_arm_get_host_isar(), blockers);
+out:
+ object_unref(obj);
+}
+
void arm_register_named_cpu_models(void)
{
size_t i;
diff --git a/target/arm/arm-cpu-models.h b/target/arm/arm-cpu-models.h
index 3d4d805da8..2c2038722e 100644
--- a/target/arm/arm-cpu-models.h
+++ b/target/arm/arm-cpu-models.h
@@ -42,6 +42,8 @@ void arm_register_named_cpu_models(void);
const ArmNamedCpuModel *arm_find_model(const char *name);
const ArmModelPropValue *arm_cpu_get_composite_subprop(ARMCPU *cpu, const char *comp);
+void arm_cpu_class_check_missing_features(ARMCPUClass *acc, strList **blockers);
+
void arm_apply_model_prop(Object *obj, const ArmModelPropValue *prop, Error **errp);
#endif /* ARM_CPU_MODELS_H */
diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
index 9bdf85885f..9b7eea7fea 100644
--- a/target/arm/arm-qmp-cmds.c
+++ b/target/arm/arm-qmp-cmds.c
@@ -326,6 +326,18 @@ static void arm_cpu_add_definition(gpointer data, gpointer user_data)
info->name = cpu_model_from_type(typename);
info->q_typename = g_strdup(typename);
+ /* calcualte blockers */
+ if (kvm_enabled()
+ && !g_str_equal(info->name, "host")
+ && !g_str_equal(info->name, "max")
+ && arm_find_model(info->name) != NULL) {
+ arm_cpu_class_check_missing_features(ARM_CPU_CLASS(oc),
+ &info->unavailable_features);
+ if (info->unavailable_features) {
+ info->has_unavailable_features = true;
+ }
+ }
+
QAPI_LIST_PREPEND(*cpu_list, info);
}
diff --git a/target/arm/cpu-idregs.c b/target/arm/cpu-idregs.c
index 1ec1a38866..3e69edf9cc 100644
--- a/target/arm/cpu-idregs.c
+++ b/target/arm/cpu-idregs.c
@@ -458,3 +458,51 @@ char *arm_field_supported_numeric_range(ArmFieldIdx field,
return g_strdup_printf("%" PRIu64, host_val);
}
}
+
+void arm_idregs_get_blockers(ARMCPU *cpu,
+ const ARMISARegisters *host_isar,
+ strList **blockers)
+{
+ for (int i = 0; i < NUM_ID_IDX; i++) {
+ const ArmIdReg *reg = &arm_idregs[i];
+ if (!reg->name) {
+ continue;
+ }
+
+ for (uint32_t j = 0; j < reg->fields_count; j++) {
+ const ArmIdRegField *f = ®->fields[j];
+ uint64_t model_val, host_val;
+
+ arm_idreg_field_read(&cpu->isar, f->idx, &model_val);
+ arm_idreg_field_read(host_isar, f->idx, &host_val);
+
+ if (!arm_field_is_writable(f->idx)
+ && !arm_field_skip_writeback_always(f->idx)
+ && !arm_field_skip_writeback_if_not_writable(f->idx)
+ && model_val != host_val
+ && !(arm_field_supports_off_via_vcpu_flags(f->idx)
+ && model_val == 0)) {
+ const ArmCpuPropDesc *prop = arm_prop_for_field(f->idx);
+ if (prop) {
+ QAPI_LIST_PREPEND(*blockers, g_strdup(prop->name));
+ } else {
+ QAPI_LIST_PREPEND(*blockers,
+ g_strdup_printf("idreg_%s_%s", reg->name, f->name));
+ }
+ continue;
+ }
+
+ if (arm_field_is_writable(f->idx)
+ && !arm_field_check_val_safe(f->idx, model_val, host_isar)
+ && !arm_field_skip_writeback_always(f->idx)) {
+ const ArmCpuPropDesc *prop = arm_prop_for_field(f->idx);
+ if (prop) {
+ QAPI_LIST_PREPEND(*blockers, g_strdup(prop->name));
+ } else {
+ QAPI_LIST_PREPEND(*blockers,
+ g_strdup_printf("idreg_%s_%s", reg->name, f->name));
+ }
+ }
+ }
+ }
+}
diff --git a/target/arm/cpu-idregs.h b/target/arm/cpu-idregs.h
index 171e03eece..c4f039f690 100644
--- a/target/arm/cpu-idregs.h
+++ b/target/arm/cpu-idregs.h
@@ -111,5 +111,8 @@ void arm_field_foreach_supported_arch_val(ArmFieldIdx field,
ArmFieldValVisitor fn, void *opaque);
char *arm_field_supported_numeric_range(ArmFieldIdx field,
const ARMISARegisters *host_isar);
+void arm_idregs_get_blockers(ARMCPU *cpu,
+ const ARMISARegisters *host_isar,
+ strList **blockers);
#endif /* CPU_IDREGS_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 26/29] target/arm: Support exposing cache information for named cpu models
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (24 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 25/29] target/arm/qmp: hook blockers in query-cpu-definitions Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 27/29] target/arm: Provide default cache hierarchy Khushit Shah
` (3 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Introduce "expose-cache" with newly introduced cache sub-props like
the per level (type, sets, linesize, associativity) and cache attributes
(louis, loc, louu, icb_type, ttypen). Back "expose-cache" by
ARMCPU::cache_exposed.
Add kvm_arm_writeback_ccsidr(), which writesback demux ccsidr values
into cpregs. Which is then written back to KVM.
Additionally, the same cache topology is exposed to the guest through
PPTT/DT cache nodes in virt.c, gated by the expose-cache boolean.
To support this on infra side:
- Introduce a new prop type ARM_PROP_CUSTOM which mandates custom
getter/setter and reset for a prop. Required for properties backed
by CCSIDR bank
- Add CLIDR_EL1 to cpu-idregs.h.inc. As it is not a part of kernel's
sysreg file, safe-rules are populated with ANY.
- Remove FIELD() entries for CLIDR_EL1.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
hw/arm/virt.c | 20 ++-
target/arm/arm-cpu-props.c | 272 +++++++++++++++++++++++++++++++++++-
target/arm/arm-cpu-props.h | 5 +-
target/arm/arm-qmp-cmds.c | 1 +
target/arm/cpu-features.h | 11 --
target/arm/cpu-idregs.h | 1 +
target/arm/cpu-idregs.h.inc | 91 ++++++++++++
target/arm/cpu.h | 3 +
target/arm/kvm.c | 54 +++++++
9 files changed, 440 insertions(+), 18 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 117033115d..eeb7a6faff 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -337,6 +337,16 @@ unsigned int virt_get_caches(const VirtMachineState *vms, CPUCoreCaches *caches)
ARMISARegisters *isar = &armcpu->isar;
uint32_t clidr = GET_IDREG(isar, CLIDR);
+ /*
+ * under KVM only expose caches when cache_exposed is true.
+ * Without cache_exposed, default view of KVM is in CLIDR_EL1:
+ * 1 line, 1 set, 1 way level 1 unified cache. skip setting up
+ * caches in this case.
+ */
+ if (kvm_enabled() && !armcpu->cache_exposed) {
+ return 0;
+ }
+
for (int cache_level = 1; cache_level <= CLIDR_CTYPE_MAX_CACHE_LEVEL;
cache_level++) {
uint8_t ctype =
@@ -654,9 +664,9 @@ static void fdt_add_cpu_nodes(VirtMachineState *vms)
bool cache_created = false;
bool cache_at_topo_level;
- num_cache = virt_get_caches(vms, caches);
+ num_cache = virt_get_caches(vms, caches); /* 0 if caches are not exposed */
- if (mc->smp_props.has_caches &&
+ if (num_cache > 0 && mc->smp_props.has_caches &&
partial_cache_description(ms, num_cache)) {
error_setg(&error_fatal, "Missing cache description");
return;
@@ -758,7 +768,7 @@ static void fdt_add_cpu_nodes(VirtMachineState *vms)
/* This assumes socket as the highest topological level. */
socket_offset = 0;
cluster_offset = 0;
- cache_at_topo_level =
+ cache_at_topo_level = (num_cache > 0) &&
machine_find_lowest_level_cache_at_topo_level(ms,
&bottom_node,
CPU_TOPOLOGY_LEVEL_SOCKET);
@@ -793,7 +803,7 @@ static void fdt_add_cpu_nodes(VirtMachineState *vms)
bottom_cluster = top_cluster;
cluster_offset = socket_offset;
core_offset = 0;
- cache_at_topo_level =
+ cache_at_topo_level = (num_cache > 0) &&
machine_find_lowest_level_cache_at_topo_level(ms,
&bottom_cluster,
CPU_TOPOLOGY_LEVEL_CLUSTER);
@@ -828,7 +838,7 @@ static void fdt_add_cpu_nodes(VirtMachineState *vms)
if (core_id != last_core) {
bottom_core = top_core;
core_offset = cluster_offset;
- cache_at_topo_level =
+ cache_at_topo_level = (num_cache > 0) &&
machine_find_lowest_level_cache_at_topo_level(ms,
&bottom_core,
CPU_TOPOLOGY_LEVEL_CORE);
diff --git a/target/arm/arm-cpu-props.c b/target/arm/arm-cpu-props.c
index dab7786622..44f21de1c5 100644
--- a/target/arm/arm-cpu-props.c
+++ b/target/arm/arm-cpu-props.c
@@ -12,6 +12,7 @@
#include "qemu/typedefs.h"
#include "qom/object.h"
#include "cpu.h"
+#include "cpu-features.h"
#include "arm-cpu-props.h"
#include "cpu-idregs.h"
#include "arm-cpu-models.h"
@@ -53,6 +54,13 @@
.get = _get, \
.set = _set }
+#define ARM_CUSTOM_PROP(prop_name, _custom_type, _get, _set, _reset) \
+ { .name = (prop_name), .type = ARM_PROP_CUSTOM, \
+ .u.custom_type = (_custom_type), \
+ .get = _get, \
+ .set = _set, \
+ .reset = _reset }
+
static void arm_composite_set_internal(ARMCPU *cpu,
const ArmCpuPropDesc *p,
bool val,
@@ -77,6 +85,139 @@ static void pauth_set(ARMCPU *cpu, Visitor *v, const char *name, Error **errp)
cpu->prop_pauth = val;
}
+/*
+ * Bank index in cpu->ccsidr[]: (level - 1) * 2 | InD.
+ */
+#define CACHE_BANK(level, is_icache) (((level) - 1) * 2 | !!(is_icache))
+
+/*
+ * CCSIDR_EL1 field accessors. The legacy and CCIDX encodings live at
+ * different bit positions; KVM forces legacy encodings, so use that.
+ */
+static void ccsidr_sets_get(ARMCPU *cpu, int level, bool is_icache,
+ Visitor *v, const char *name, Error **errp)
+{
+ uint64_t r = cpu->ccsidr[CACHE_BANK(level, is_icache)];
+ uint64_t val = FIELD_EX64(r, CCSIDR_EL1, NUMSETS) + 1;
+
+ if (val == 1) {
+ val = 0;
+ }
+
+ visit_type_uint64(v, name, &val, errp);
+}
+
+static void ccsidr_sets_set(ARMCPU *cpu, int level, bool is_icache,
+ Visitor *v, const char *name, Error **errp)
+{
+ uint64_t val;
+ uint64_t *r;
+
+ if (!visit_type_uint64(v, name, &val, errp)) {
+ return;
+ }
+ r = &cpu->ccsidr[CACHE_BANK(level, is_icache)];
+
+ assert(val > 0);
+
+ *r = FIELD_DP64(*r, CCSIDR_EL1, NUMSETS, val - 1);
+}
+
+static void ccsidr_associativity_get(ARMCPU *cpu, int level, bool is_icache,
+ Visitor *v, const char *name,
+ Error **errp)
+{
+ uint64_t r = cpu->ccsidr[CACHE_BANK(level, is_icache)];
+ uint64_t val = FIELD_EX64(r, CCSIDR_EL1, ASSOCIATIVITY) + 1;
+
+ visit_type_uint64(v, name, &val, errp);
+}
+
+static void ccsidr_associativity_set(ARMCPU *cpu, int level, bool is_icache,
+ Visitor *v, const char *name,
+ Error **errp)
+{
+ uint64_t val;
+ uint64_t *r;
+
+ if (!visit_type_uint64(v, name, &val, errp)) {
+ return;
+ }
+ r = &cpu->ccsidr[CACHE_BANK(level, is_icache)];
+
+ assert(val > 0);
+
+ *r = FIELD_DP64(*r, CCSIDR_EL1, ASSOCIATIVITY, val - 1);
+}
+
+static void ccsidr_linesize_get(ARMCPU *cpu, int level, bool is_icache,
+ Visitor *v, const char *name, Error **errp)
+{
+ uint64_t r = cpu->ccsidr[CACHE_BANK(level, is_icache)];
+ uint64_t enc = FIELD_EX64(r, CCSIDR_EL1, LINESIZE);
+ uint64_t val = 1ULL << (enc + 4);
+ visit_type_uint64(v, name, &val, errp);
+}
+
+static void ccsidr_linesize_set(ARMCPU *cpu, int level, bool is_icache,
+ Visitor *v, const char *name, Error **errp)
+{
+ uint64_t val;
+ uint64_t enc;
+ uint64_t *r;
+
+ if (!visit_type_uint64(v, name, &val, errp)) {
+ return;
+ }
+ /* Linesize is encoded as log2(bytes) - 4. */
+ enc = ctz64(val) - 4;
+ r = &cpu->ccsidr[CACHE_BANK(level, is_icache)];
+ *r = FIELD_DP64(*r, CCSIDR_EL1, LINESIZE, enc);
+}
+
+static void ccsidr_sets_reset(ARMCPU *cpu, int level, bool is_icache)
+{
+ uint64_t *r = &cpu->ccsidr[CACHE_BANK(level, is_icache)];
+ *r = FIELD_DP64(*r, CCSIDR_EL1, NUMSETS, 0);
+}
+
+static void ccsidr_associativity_reset(ARMCPU *cpu, int level, bool is_icache)
+{
+ uint64_t *r = &cpu->ccsidr[CACHE_BANK(level, is_icache)];
+ *r = FIELD_DP64(*r, CCSIDR_EL1, ASSOCIATIVITY, 0);
+}
+
+static void ccsidr_linesize_reset(ARMCPU *cpu, int level, bool is_icache)
+{
+ uint64_t *r = &cpu->ccsidr[CACHE_BANK(level, is_icache)];
+ *r = FIELD_DP64(*r, CCSIDR_EL1, LINESIZE, 0);
+}
+
+/*
+ * Generate the per-prop ccsidr_*_{get,set,reset}.
+ */
+#define CACHE_PROP_FNS(NAME, LVL, IC, FIELD) \
+ static void cache_##NAME##_##FIELD##_get(ARMCPU *cpu, Visitor *v, \
+ const char *name, Error **errp)\
+ { ccsidr_##FIELD##_get(cpu, (LVL), (IC), v, name, errp); } \
+ static void cache_##NAME##_##FIELD##_set(ARMCPU *cpu, Visitor *v, \
+ const char *name, Error **errp)\
+ { ccsidr_##FIELD##_set(cpu, (LVL), (IC), v, name, errp); } \
+ static void cache_##NAME##_##FIELD##_reset(ARMCPU *cpu, \
+ const char *name, \
+ Error **errp) \
+ { ccsidr_##FIELD##_reset(cpu, (LVL), (IC)); }
+
+#define CACHE_PROP_FNS_ALL(NAME, LVL, IC) \
+ CACHE_PROP_FNS(NAME, LVL, IC, sets) \
+ CACHE_PROP_FNS(NAME, LVL, IC, associativity) \
+ CACHE_PROP_FNS(NAME, LVL, IC, linesize)
+
+CACHE_PROP_FNS_ALL(lvl1_dcache, 1, false)
+CACHE_PROP_FNS_ALL(lvl1_icache, 1, true)
+CACHE_PROP_FNS_ALL(lvl2, 2, false)
+CACHE_PROP_FNS_ALL(lvl3, 3, false)
+
const ArmFracVal csv2_frac_vals[] = {
{ "0.0", 0, 0 },
{ "1.0", 1, 0 },
@@ -286,6 +427,66 @@ const ArmCpuPropDesc arm_cpu_props[] = {
ARM_SINGLE_FIELD_PROP("cpu_revidr", NUMERIC, REVIDR, VAL),
ARM_SINGLE_FIELD_PROP("cpu_aidr", NUMERIC, AIDR, VAL),
+ ARM_SINGLE_FIELD_PROP("cache_lvl1_type", STRING, CLIDR_EL1, CTYPE1),
+ ARM_SINGLE_FIELD_PROP("cache_lvl2_type", STRING, CLIDR_EL1, CTYPE2),
+ ARM_SINGLE_FIELD_PROP("cache_lvl3_type", STRING, CLIDR_EL1, CTYPE3),
+ ARM_SINGLE_FIELD_PROP("cache_louis", NUMERIC, CLIDR_EL1, LOUIS),
+ ARM_SINGLE_FIELD_PROP("cache_loc", NUMERIC, CLIDR_EL1, LOC),
+ ARM_SINGLE_FIELD_PROP("cache_louu", NUMERIC, CLIDR_EL1, LOUU),
+ ARM_SINGLE_FIELD_PROP("cache_icb_type", STRING, CLIDR_EL1, ICB),
+ ARM_SINGLE_FIELD_PROP("cache_ttypen", NUMERIC, CLIDR_EL1, TTYPEN),
+
+ ARM_CUSTOM_PROP("cache_lvl1_icache_sets", "number",
+ cache_lvl1_icache_sets_get,
+ cache_lvl1_icache_sets_set,
+ cache_lvl1_icache_sets_reset),
+ ARM_CUSTOM_PROP("cache_lvl1_dcache_sets", "number",
+ cache_lvl1_dcache_sets_get,
+ cache_lvl1_dcache_sets_set,
+ cache_lvl1_dcache_sets_reset),
+ ARM_CUSTOM_PROP("cache_lvl2_sets", "number",
+ cache_lvl2_sets_get,
+ cache_lvl2_sets_set,
+ cache_lvl2_sets_reset),
+ ARM_CUSTOM_PROP("cache_lvl3_sets", "number",
+ cache_lvl3_sets_get,
+ cache_lvl3_sets_set,
+ cache_lvl3_sets_reset),
+
+ ARM_CUSTOM_PROP("cache_lvl1_icache_associativity", "number",
+ cache_lvl1_icache_associativity_get,
+ cache_lvl1_icache_associativity_set,
+ cache_lvl1_icache_associativity_reset),
+ ARM_CUSTOM_PROP("cache_lvl1_dcache_associativity", "number",
+ cache_lvl1_dcache_associativity_get,
+ cache_lvl1_dcache_associativity_set,
+ cache_lvl1_dcache_associativity_reset),
+ ARM_CUSTOM_PROP("cache_lvl2_associativity", "number",
+ cache_lvl2_associativity_get,
+ cache_lvl2_associativity_set,
+ cache_lvl2_associativity_reset),
+ ARM_CUSTOM_PROP("cache_lvl3_associativity", "number",
+ cache_lvl3_associativity_get,
+ cache_lvl3_associativity_set,
+ cache_lvl3_associativity_reset),
+
+ ARM_CUSTOM_PROP("cache_lvl1_icache_linesize", "number",
+ cache_lvl1_icache_linesize_get,
+ cache_lvl1_icache_linesize_set,
+ cache_lvl1_icache_linesize_reset),
+ ARM_CUSTOM_PROP("cache_lvl1_dcache_linesize", "number",
+ cache_lvl1_dcache_linesize_get,
+ cache_lvl1_dcache_linesize_set,
+ cache_lvl1_dcache_linesize_reset),
+ ARM_CUSTOM_PROP("cache_lvl2_linesize", "number",
+ cache_lvl2_linesize_get,
+ cache_lvl2_linesize_set,
+ cache_lvl2_linesize_reset),
+ ARM_CUSTOM_PROP("cache_lvl3_linesize", "number",
+ cache_lvl3_linesize_get,
+ cache_lvl3_linesize_set,
+ cache_lvl3_linesize_reset),
+
/* Fractional properties */
ARM_FRAC_PROP("feat_CSV2", ID_AA64PFR0, CSV2, ID_AA64PFR1, CSV2_FRAC, csv2_frac_vals),
ARM_FRAC_PROP("feat_MPAM", ID_AA64PFR0, MPAM, ID_AA64PFR1, MPAM_FRAC, mpam_frac_vals),
@@ -314,6 +515,21 @@ static const char *sve_sub_props[] = {
NULL
};
+static const char *expose_cache_sub_props[] = {
+ "cache_lvl1_icache_sets", "cache_lvl1_dcache_sets",
+ "cache_lvl1_icache_associativity", "cache_lvl1_dcache_associativity",
+ "cache_lvl1_icache_linesize", "cache_lvl1_dcache_linesize",
+ "cache_lvl1_type",
+ "cache_lvl2_sets", "cache_lvl2_associativity",
+ "cache_lvl2_linesize", "cache_lvl2_type",
+ "cache_lvl3_sets", "cache_lvl3_associativity",
+ "cache_lvl3_linesize", "cache_lvl3_type",
+
+ "cache_icb_type", "cache_ttypen",
+ "cache_louis", "cache_loc", "cache_louu",
+ NULL
+};
+
static void pauth_get(ARMCPU *cpu, Visitor *v, const char *name, Error **errp)
{
uint64_t apa, api, apa3;
@@ -338,9 +554,35 @@ static void sve_get(ARMCPU *cpu, Visitor *v, const char *name, Error **errp)
visit_type_bool(v, name, &sve_enabled, errp);
}
+static void expose_cache_get(ARMCPU *cpu, Visitor *v, const char *name, Error **errp)
+{
+ visit_type_bool(v, name, &cpu->cache_exposed, errp);
+}
+
+static void expose_cache_set(ARMCPU *cpu, Visitor *v, const char *name,
+ Error **errp)
+{
+ bool val;
+
+ ERRP_GUARD();
+
+ if (!visit_type_bool(v, name, &val, errp)) {
+ return;
+ }
+
+ arm_composite_set_internal(cpu, arm_find_prop(name), val, name, errp);
+ if (*errp) {
+ error_prepend(errp, "Property '%s': ", name);
+ }
+
+ cpu->cache_exposed = val;
+}
+
const ArmCpuPropDesc arm_composite_props[] = {
ARM_COMPOSITE_PROP_GS("pauth", pauth_sub_props, pauth_get, pauth_set),
ARM_COMPOSITE_PROP("sve", sve_sub_props, sve_get),
+ ARM_COMPOSITE_PROP_GS("expose-cache", expose_cache_sub_props,
+ expose_cache_get, expose_cache_set),
{ .name = NULL }
};
@@ -448,6 +690,11 @@ static void arm_cpu_prop_get(Object *obj, Visitor *v, const char *name,
case ARM_PROP_COMPOSITE:
/* Composite features must have a custom getter */
g_assert_not_reached();
+ break;
+ case ARM_PROP_CUSTOM:
+ /* Custom getter should be passed. */
+ g_assert_not_reached();
+ break;
}
}
@@ -541,6 +788,11 @@ static void arm_prop_set_default(ARMCPU *cpu, const char *name, Error **errp)
return;
}
+ if (p->reset) {
+ p->reset(cpu, name, errp);
+ return;
+ }
+
switch (p->type) {
case ARM_PROP_STRING:
case ARM_PROP_BOOLEAN:
@@ -554,6 +806,10 @@ static void arm_prop_set_default(ARMCPU *cpu, const char *name, Error **errp)
case ARM_PROP_COMPOSITE:
object_property_set_bool(OBJECT(cpu), p->name, false, errp);
break;
+ case ARM_PROP_CUSTOM:
+ /* Custom default resetter should be implemetend. */
+ g_assert_not_reached();
+ break;
default:
g_assert_not_reached();
}
@@ -669,6 +925,10 @@ static void arm_cpu_prop_set(Object *obj, Visitor *v, const char *name,
case ARM_PROP_COMPOSITE:
arm_composite_set(cpu, p, v, name, errp);
break;
+ case ARM_PROP_CUSTOM:
+ /* Custom setter should be passed. */
+ g_assert_not_reached();
+ break;
}
}
@@ -689,6 +949,9 @@ void arm_add_cpu_props(Object *obj)
case ARM_PROP_NUMERIC:
type = "number";
break;
+ case ARM_PROP_CUSTOM:
+ type = p->u.custom_type;
+ break;
default:
g_assert_not_reached();
}
@@ -802,7 +1065,14 @@ void arm_prop_append_supported_values(const ArmCpuPropDesc *prop,
}
break;
}
-
+ case ARM_PROP_COMPOSITE: {
+ /* not supported for composites */
+ break;
+ }
+ case ARM_PROP_CUSTOM: {
+ /* not supported for custom props */
+ break;
+ }
default:
g_assert_not_reached();
}
diff --git a/target/arm/arm-cpu-props.h b/target/arm/arm-cpu-props.h
index 264a8a71de..55333de858 100644
--- a/target/arm/arm-cpu-props.h
+++ b/target/arm/arm-cpu-props.h
@@ -20,7 +20,8 @@ typedef enum ArmCpuPropType {
ARM_PROP_BOOLEAN,
ARM_PROP_NUMERIC,
ARM_PROP_FRACTIONAL,
- ARM_PROP_COMPOSITE
+ ARM_PROP_COMPOSITE,
+ ARM_PROP_CUSTOM
} ArmCpuPropType;
typedef struct ArmFracVal {
@@ -40,10 +41,12 @@ typedef struct ArmCpuPropDesc {
const ArmFracVal *vals;
} frac;
const char **comp_sub_props;
+ const char *custom_type;
} u;
void (*get)(ARMCPU *cpu, Visitor *v, const char *name, Error **errp);
void (*set)(ARMCPU *cpu, Visitor *v, const char *name, Error **errp);
+ void (*reset)(ARMCPU *cpu, const char *name, Error **errp);
} ArmCpuPropDesc;
const ArmCpuPropDesc *get_arm_cpu_props(void);
diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
index 9b7eea7fea..e13dfeb357 100644
--- a/target/arm/arm-qmp-cmds.c
+++ b/target/arm/arm-qmp-cmds.c
@@ -87,6 +87,7 @@ CpuPropInfoList *qmp_query_arm_cpu_props_info(Error **errp)
pdesc->type == ARM_PROP_BOOLEAN ? "boolean" :
pdesc->type == ARM_PROP_NUMERIC ? "number" :
pdesc->type == ARM_PROP_FRACTIONAL ? "string" :
+ pdesc->type == ARM_PROP_CUSTOM ? pdesc->u.custom_type :
"unknown");
sv = qlist_new();
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index e162bdff9b..c3aec21f5c 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -28,17 +28,6 @@
/*
* System register ID fields.
*/
-FIELD(CLIDR_EL1, CTYPE1, 0, 3)
-FIELD(CLIDR_EL1, CTYPE2, 3, 3)
-FIELD(CLIDR_EL1, CTYPE3, 6, 3)
-FIELD(CLIDR_EL1, CTYPE4, 9, 3)
-FIELD(CLIDR_EL1, CTYPE5, 12, 3)
-FIELD(CLIDR_EL1, CTYPE6, 15, 3)
-FIELD(CLIDR_EL1, CTYPE7, 18, 3)
-FIELD(CLIDR_EL1, LOUIS, 21, 3)
-FIELD(CLIDR_EL1, LOC, 24, 3)
-FIELD(CLIDR_EL1, LOUU, 27, 3)
-FIELD(CLIDR_EL1, ICB, 30, 3)
/* When FEAT_CCIDX is implemented */
FIELD(CCSIDR_EL1, CCIDX_LINESIZE, 0, 3)
diff --git a/target/arm/cpu-idregs.h b/target/arm/cpu-idregs.h
index c4f039f690..c1c334291a 100644
--- a/target/arm/cpu-idregs.h
+++ b/target/arm/cpu-idregs.h
@@ -18,6 +18,7 @@ typedef enum ArmIdRegSafeRule {
#define DCZID_EL0_EL1_IDX DCZID_EL0_IDX
#define CTR_EL0_EL1_IDX CTR_EL0_IDX
+#define CLIDR_EL1_EL1_IDX CLIDR_EL1_IDX
/* ArmFieldIdx: per-field enum generated from cpu-idregs.h.inc */
#define IDREG_START(reg)
diff --git a/target/arm/cpu-idregs.h.inc b/target/arm/cpu-idregs.h.inc
index 7e2bbf256d..05bf7fe96a 100644
--- a/target/arm/cpu-idregs.h.inc
+++ b/target/arm/cpu-idregs.h.inc
@@ -1547,6 +1547,97 @@ IDREG_FIELD_END(ID_AA64AFR1, VAL)
IDREG_END(ID_AA64AFR1_EL1)
+/* CLIDR_EL1 */
+IDREG_START(CLIDR_EL1)
+IDREG_FIELD_START(CLIDR_EL1, CTYPE1, 0, 3, ANY, 0)
+IDREG_FIELD_ARCH_VAL(0b000, "no-cache")
+IDREG_FIELD_ARCH_VAL(0b001, "i-cache-only")
+IDREG_FIELD_ARCH_VAL(0b010, "d-cache-only")
+IDREG_FIELD_ARCH_VAL(0b011, "separate-i-d-cache")
+IDREG_FIELD_ARCH_VAL(0b100, "unified-cache")
+IDREG_FIELD_END(CLIDR_EL1, CTYPE1)
+
+IDREG_FIELD_START(CLIDR_EL1, CTYPE2, 3, 3, ANY, 0)
+IDREG_FIELD_ARCH_VAL(0b000, "no-cache")
+IDREG_FIELD_ARCH_VAL(0b001, "i-cache-only")
+IDREG_FIELD_ARCH_VAL(0b010, "d-cache-only")
+IDREG_FIELD_ARCH_VAL(0b011, "separate-i-d-cache")
+IDREG_FIELD_ARCH_VAL(0b100, "unified-cache")
+IDREG_FIELD_END(CLIDR_EL1, CTYPE2)
+
+IDREG_FIELD_START(CLIDR_EL1, CTYPE3, 6, 3, ANY, 0)
+IDREG_FIELD_ARCH_VAL(0b000, "no-cache")
+IDREG_FIELD_ARCH_VAL(0b001, "i-cache-only")
+IDREG_FIELD_ARCH_VAL(0b010, "d-cache-only")
+IDREG_FIELD_ARCH_VAL(0b011, "separate-i-d-cache")
+IDREG_FIELD_ARCH_VAL(0b100, "unified-cache")
+IDREG_FIELD_END(CLIDR_EL1, CTYPE3)
+
+IDREG_FIELD_START(CLIDR_EL1, CTYPE4, 9, 3, ANY, 0)
+IDREG_FIELD_ARCH_VAL(0b000, "no-cache")
+IDREG_FIELD_ARCH_VAL(0b001, "i-cache-only")
+IDREG_FIELD_ARCH_VAL(0b010, "d-cache-only")
+IDREG_FIELD_ARCH_VAL(0b011, "separate-i-d-cache")
+IDREG_FIELD_ARCH_VAL(0b100, "unified-cache")
+IDREG_FIELD_END(CLIDR_EL1, CTYPE4)
+
+IDREG_FIELD_START(CLIDR_EL1, CTYPE5, 12, 3, ANY, 0)
+IDREG_FIELD_ARCH_VAL(0b000, "no-cache")
+IDREG_FIELD_ARCH_VAL(0b001, "i-cache-only")
+IDREG_FIELD_ARCH_VAL(0b010, "d-cache-only")
+IDREG_FIELD_ARCH_VAL(0b011, "separate-i-d-cache")
+IDREG_FIELD_ARCH_VAL(0b100, "unified-cache")
+IDREG_FIELD_END(CLIDR_EL1, CTYPE5)
+
+IDREG_FIELD_START(CLIDR_EL1, CTYPE6, 15, 3, ANY, 0)
+IDREG_FIELD_ARCH_VAL(0b000, "no-cache")
+IDREG_FIELD_ARCH_VAL(0b001, "i-cache-only")
+IDREG_FIELD_ARCH_VAL(0b010, "d-cache-only")
+IDREG_FIELD_ARCH_VAL(0b011, "separate-i-d-cache")
+IDREG_FIELD_ARCH_VAL(0b100, "unified-cache")
+IDREG_FIELD_END(CLIDR_EL1, CTYPE6)
+
+IDREG_FIELD_START(CLIDR_EL1, CTYPE7, 18, 3, ANY, 0)
+IDREG_FIELD_ARCH_VAL(0b000, "no-cache")
+IDREG_FIELD_ARCH_VAL(0b001, "i-cache-only")
+IDREG_FIELD_ARCH_VAL(0b010, "d-cache-only")
+IDREG_FIELD_ARCH_VAL(0b011, "separate-i-d-cache")
+IDREG_FIELD_ARCH_VAL(0b100, "unified-cache")
+IDREG_FIELD_END(CLIDR_EL1, CTYPE7)
+
+IDREG_FIELD_START(CLIDR_EL1, LOUIS, 21, 3, ANY, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(CLIDR_EL1, LOUIS)
+
+IDREG_FIELD_START(CLIDR_EL1, LOC, 24, 3, ANY, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(CLIDR_EL1, LOC)
+
+IDREG_FIELD_START(CLIDR_EL1, LOUU, 27, 3, ANY, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(CLIDR_EL1, LOUU)
+
+IDREG_FIELD_START(CLIDR_EL1, ICB, 30, 3, ANY, 0)
+IDREG_FIELD_ARCH_VAL(0b000, "unknown")
+IDREG_FIELD_ARCH_VAL(0b001, "l1")
+IDREG_FIELD_ARCH_VAL(0b010, "l2")
+IDREG_FIELD_ARCH_VAL(0b011, "l3")
+IDREG_FIELD_ARCH_VAL(0b100, "l4")
+IDREG_FIELD_ARCH_VAL(0b101, "l5")
+IDREG_FIELD_ARCH_VAL(0b110, "l6")
+IDREG_FIELD_ARCH_VAL(0b111, "l7")
+IDREG_FIELD_END(CLIDR_EL1, ICB)
+
+IDREG_FIELD_START(CLIDR_EL1, TTYPEN, 33, 14, ANY, 0)
+IDREG_FIELD_ARCH_VAL_ANY
+IDREG_FIELD_END(CLIDR_EL1, TTYPEN)
+
+IDREG_FIELD_START(CLIDR_EL1, RES0_47, 47, 17, EXACT, 0)
+IDREG_FIELD_ARCH_VAL(0, NULL)
+IDREG_FIELD_END(CLIDR_EL1, RES0_47)
+
+IDREG_END(CLIDR_EL1)
+
/* AArch32 ID registers */
/* ID_PFR0_EL1 */
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index a0a1d7fbe3..5dab74412f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1189,6 +1189,9 @@ struct ArchCPU {
/* Generic timer counter frequency, in Hz */
uint64_t gt_cntfrq_hz;
+
+ /* QOM property to indicate if the cache is exposed */
+ bool cache_exposed;
};
typedef struct ARMCPUInfo {
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index b4544f3514..984c7fd256 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -1197,6 +1197,48 @@ static uint64_t *kvm_arm_find_cpreg_ptr(ARMCPU *cpu, uint64_t regidx)
return &cpu->cpreg_values[res - cpu->cpreg_indexes];
}
+#define CSSELR_MAX 14
+
+/*
+ * Push the model-configured CCSIDR_EL1 values stored in cpu->ccsidr[] into
+ * the cpreg list, so the subsequent write_list_to_kvmstate() pass actually
+ * issues KVM_SET_ONE_REG for the matching KVM_REG_ARM_DEMUX_ID_CCSIDR
+ * registers.
+ */
+static void kvm_arm_writeback_ccsidr(ARMCPU *cpu)
+{
+ if (!cpu->cache_exposed) {
+ return;
+ }
+
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(cpu->ccsidr) < CSSELR_MAX);
+
+ for (uint32_t csselr = 0; csselr < CSSELR_MAX; csselr++) {
+ uint64_t regidx = KVM_REG_ARM64
+ | KVM_REG_SIZE_U32
+ | KVM_REG_ARM_DEMUX
+ | KVM_REG_ARM_DEMUX_ID_CCSIDR
+ | csselr;
+ uint64_t *cpreg = kvm_arm_find_cpreg_ptr(cpu, regidx);
+
+ if (cpu->ccsidr[csselr] == 0) {
+ continue;
+ }
+
+ if (!cpreg) {
+ /* This kernel doesn't expose this CSSELR slot; skip. */
+ error_report("KVM does not expose CSSELR slot %d", csselr);
+ continue;
+ }
+
+ /*
+ * cpu->ccsidr[] is u64. The DEMUX ABI only takes the low 32 bits,
+ * matching the legacy CCSIDR encoding, which KVM enforces.
+ */
+ *cpreg = (uint32_t)cpu->ccsidr[csselr];
+ }
+}
+
static void kvm_arm_writeback_idregs(ARMCPU *cpu)
{
for (int i = 0; i < NUM_ID_IDX; i++) {
@@ -1205,6 +1247,14 @@ static void kvm_arm_writeback_idregs(ARMCPU *cpu)
const char *name = arm_idregs[i].name;
uint64_t writable_mask, previous, desired, diff;
+ if (i == CLIDR_EL1_IDX && !cpu->cache_exposed) {
+ /*
+ * CLIDR is not exposed to KVM when cache_exposed is false.
+ * Continue with the whatever view KVM provides.
+ */
+ continue;
+ }
+
if (!cpreg) {
warn_report("KVM does not expose ID register slot %d "
"(kvm_reg=0x%" PRIx64 "), %s; skipping writeback",
@@ -1270,6 +1320,10 @@ static void kvm_arm_writeback_idregs(ARMCPU *cpu)
trace_kvm_arm_writeback_idreg(name, previous, *cpreg);
}
}
+
+ if (cpu->cache_exposed) {
+ kvm_arm_writeback_ccsidr(cpu);
+ }
}
bool kvm_arm_cpu_post_load(ARMCPU *cpu)
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 27/29] target/arm: Provide default cache hierarchy
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (25 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 26/29] target/arm: Support exposing cache information for named cpu models Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 28/29] target/arm: supported-values and blockers for CCSIDR cache properties Khushit Shah
` (2 subsequent siblings)
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
Default cache-hierarchy into kvm-base-v1, hence every model inherits
a cache topology.
Topology:
L1: separate-i-d, 4-way x 256 sets x 64B = 64 KiB each
L2: unified, 8-way x 2048 sets x 64B = 1 MiB
L3: unified, 12-way x 8192 sets x 64B = 6 MiB
CLIDR_EL1 fields are set to match the geometry:
LoC=3, LoUIS=LoUU=1, ICB=unknown, TTYPEN=0.
Whether to keep them on as default is another question to tackle some
another time.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-models.c | 46 +++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/target/arm/arm-cpu-models.c b/target/arm/arm-cpu-models.c
index 3eafa0efc5..5f59650c81 100644
--- a/target/arm/arm-cpu-models.c
+++ b/target/arm/arm-cpu-models.c
@@ -46,6 +46,50 @@
#define MODEL_PROP_END { .name = NULL }
+/*
+ * Expose a default three-level cache hierarchy.
+ * No justifications on the topology or the values.
+ *
+ * L1: separate-i-d-cache, 4-way, 64B, 256 sets: 64KiB
+ * L2: unified-cache, 8-way, 64B, 2048 sets: 1MiB
+ * L3: unified-cache, 12-way, 64B, 8192 sets: 6MiB
+ *
+ * Louis: 1
+ * Loc: 3
+ * Louu: 1
+ * Icb: unknown (not specified)
+ * Ttypen: 0
+ */
+static const ArmModelPropValue default_expose_cache_props[] = {
+ MODEL_PROP("cache_lvl1_type", STR, "separate-i-d-cache"),
+ MODEL_PROP("cache_lvl1_icache_linesize", NUM, 64),
+ MODEL_PROP("cache_lvl1_icache_associativity", NUM, 4),
+ MODEL_PROP("cache_lvl1_icache_sets", NUM, 256),
+
+ MODEL_PROP("cache_lvl1_dcache_linesize", NUM, 64),
+ MODEL_PROP("cache_lvl1_dcache_associativity", NUM, 4),
+ MODEL_PROP("cache_lvl1_dcache_sets", NUM, 256),
+
+ MODEL_PROP("cache_lvl2_type", STR, "unified-cache"),
+ MODEL_PROP("cache_lvl2_linesize", NUM, 64),
+ MODEL_PROP("cache_lvl2_associativity", NUM, 8),
+ MODEL_PROP("cache_lvl2_sets", NUM, 2048),
+
+ MODEL_PROP("cache_lvl3_type", STR, "unified-cache"),
+ MODEL_PROP("cache_lvl3_linesize", NUM, 64),
+ MODEL_PROP("cache_lvl3_associativity", NUM, 12),
+ MODEL_PROP("cache_lvl3_sets", NUM, 8192),
+
+ /* Only set/way based guest operations will care about this. */
+ MODEL_PROP("cache_louis", NUM, 1),
+ MODEL_PROP("cache_loc", NUM, 3), /* Can we safely set to 1 for performance? */
+ MODEL_PROP("cache_louu", NUM, 1),
+ MODEL_PROP("cache_icb_type", STR, "unknown"),
+ MODEL_PROP("cache_ttypen", NUM, 0),
+
+ MODEL_PROP_END,
+};
+
static const ArmModelPropValue kvm_base_v1_props[] = {
MODEL_PROP("el0_mode", STR, "aarch64"),
MODEL_PROP("el1_mode", STR, "aarch64"),
@@ -57,6 +101,8 @@ static const ArmModelPropValue kvm_base_v1_props[] = {
MODEL_PROP("feat_MTE_FRAC", STR, "async"),
MODEL_PROP("hw_prop_CCIDX", STR, "32"),
+ MODEL_PROP_COMP("expose-cache", true, default_expose_cache_props),
+
MODEL_PROP_END,
};
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 28/29] target/arm: supported-values and blockers for CCSIDR cache properties
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (26 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 27/29] target/arm: Provide default cache hierarchy Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 29/29] target/arm/kvm: fix host model writeback when kernel supports EL2 Khushit Shah
2026-06-12 14:50 ` [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Eric Auger
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
As CCSIDR banks are not backed by standard idregs[], add special
handling for them to hook up supported values and blockers for them.
KVM rejects CCSIDR[] linesize if it is < host CTR_EL0.*MinLineSize.
Report such case in qmp's cpu-definition blockers using
arm_ccsidr_get_blockers.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-models.c | 6 +-
target/arm/arm-cpu-props.c | 154 ++++++++++++++++++++++++++++++++----
target/arm/arm-cpu-props.h | 5 ++
3 files changed, 147 insertions(+), 18 deletions(-)
diff --git a/target/arm/arm-cpu-models.c b/target/arm/arm-cpu-models.c
index 5f59650c81..d38293cfb2 100644
--- a/target/arm/arm-cpu-models.c
+++ b/target/arm/arm-cpu-models.c
@@ -568,11 +568,14 @@ void arm_cpu_class_check_missing_features(ARMCPUClass *acc, strList **blockers)
Error *err = NULL;
Object *obj = object_new_with_class(OBJECT_CLASS(acc));
ARMCPU *cpu = ARM_CPU(obj);
+ const ARMISARegisters *host_isar;
if (!kvm_enabled() || !arm_find_model(acc->info->name)) {
goto out;
}
+ host_isar = kvm_arm_get_host_isar();
+
if (cpu_isar_feature(aa64_sve, cpu)) {
arm_cpu_sve_finalize(cpu, &err);
if (err) {
@@ -592,7 +595,8 @@ void arm_cpu_class_check_missing_features(ARMCPUClass *acc, strList **blockers)
}
}
- arm_idregs_get_blockers(cpu, kvm_arm_get_host_isar(), blockers);
+ arm_idregs_get_blockers(cpu, host_isar, blockers);
+ arm_ccsidr_get_blockers(cpu, host_isar, blockers);
out:
object_unref(obj);
}
diff --git a/target/arm/arm-cpu-props.c b/target/arm/arm-cpu-props.c
index 44f21de1c5..cb1c44ea1f 100644
--- a/target/arm/arm-cpu-props.c
+++ b/target/arm/arm-cpu-props.c
@@ -54,12 +54,13 @@
.get = _get, \
.set = _set }
-#define ARM_CUSTOM_PROP(prop_name, _custom_type, _get, _set, _reset) \
+#define ARM_CUSTOM_PROP(prop_name, _custom_type, _get, _set, _reset, _gsv) \
{ .name = (prop_name), .type = ARM_PROP_CUSTOM, \
.u.custom_type = (_custom_type), \
.get = _get, \
.set = _set, \
- .reset = _reset }
+ .reset = _reset, \
+ .get_supported_values = _gsv }
static void arm_composite_set_internal(ARMCPU *cpu,
const ArmCpuPropDesc *p,
@@ -123,6 +124,44 @@ static void ccsidr_sets_set(ARMCPU *cpu, int level, bool is_icache,
*r = FIELD_DP64(*r, CCSIDR_EL1, NUMSETS, val - 1);
}
+static uint64_t ccsidr_sets_get_max(const ARMISARegisters *host_isar)
+{
+ return 1ULL << R_CCSIDR_EL1_NUMSETS_LENGTH;
+}
+
+static uint64_t ccsidr_associativity_get_max(const ARMISARegisters *host_isar)
+{
+ return 1ULL << R_CCSIDR_EL1_ASSOCIATIVITY_LENGTH;
+}
+
+static uint64_t ccsidr_linesize_get_max(const ARMISARegisters *host_isar)
+{
+ return 1ULL << (((1U << R_CCSIDR_EL1_LINESIZE_LENGTH) - 1) + 4); /* 2048 bytes */
+}
+
+static uint64_t ccsidr_linesize_get_min(const ARMISARegisters *host_isar)
+{
+ uint64_t host_IMinLine;
+ uint64_t host_DMinLine;
+
+ arm_idreg_field_read(host_isar, ARM_FIELD_CTR_EL0_IMINLINE, &host_IMinLine);
+ arm_idreg_field_read(host_isar, ARM_FIELD_CTR_EL0_DMINLINE, &host_DMinLine);
+
+ /*
+ * ccsidr_linesize_{get,set} are in unit of bytes.
+ * CTR_EL0.{IminLine,DminLine} is represented as log2(bytes / 4)
+ */
+ return 1ULL << (MAX(host_IMinLine, host_DMinLine) + 2);
+}
+
+static void ccsidr_sets_get_supported_values(const ArmCpuPropDesc *prop,
+ const ARMISARegisters *host_isar,
+ QList *out)
+{
+ qlist_append_str(out, g_strdup_printf("0-%" PRIu64,
+ ccsidr_sets_get_max(host_isar)));
+}
+
static void ccsidr_associativity_get(ARMCPU *cpu, int level, bool is_icache,
Visitor *v, const char *name,
Error **errp)
@@ -150,6 +189,14 @@ static void ccsidr_associativity_set(ARMCPU *cpu, int level, bool is_icache,
*r = FIELD_DP64(*r, CCSIDR_EL1, ASSOCIATIVITY, val - 1);
}
+static void ccsidr_associativity_get_supported_values(const ArmCpuPropDesc *prop,
+ const ARMISARegisters *host_isar,
+ QList *out)
+{
+ qlist_append_str(out, g_strdup_printf("0-%" PRIu64,
+ ccsidr_associativity_get_max(host_isar)));
+}
+
static void ccsidr_linesize_get(ARMCPU *cpu, int level, bool is_icache,
Visitor *v, const char *name, Error **errp)
{
@@ -175,6 +222,15 @@ static void ccsidr_linesize_set(ARMCPU *cpu, int level, bool is_icache,
*r = FIELD_DP64(*r, CCSIDR_EL1, LINESIZE, enc);
}
+static void ccsidr_linesize_get_supported_values(const ArmCpuPropDesc *prop,
+ const ARMISARegisters *host_isar,
+ QList *out)
+{
+ qlist_append_str(out, g_strdup_printf("%" PRIu64 "-%" PRIu64,
+ ccsidr_linesize_get_min(host_isar),
+ ccsidr_linesize_get_max(host_isar)));
+}
+
static void ccsidr_sets_reset(ARMCPU *cpu, int level, bool is_icache)
{
uint64_t *r = &cpu->ccsidr[CACHE_BANK(level, is_icache)];
@@ -206,7 +262,14 @@ static void ccsidr_linesize_reset(ARMCPU *cpu, int level, bool is_icache)
static void cache_##NAME##_##FIELD##_reset(ARMCPU *cpu, \
const char *name, \
Error **errp) \
- { ccsidr_##FIELD##_reset(cpu, (LVL), (IC)); }
+ { ccsidr_##FIELD##_reset(cpu, (LVL), (IC)); } \
+ static void cache_##NAME##_##FIELD##_get_supported_values( \
+ const ArmCpuPropDesc *prop, \
+ const ARMISARegisters *host_isar, \
+ QList *out) \
+ { \
+ ccsidr_##FIELD##_get_supported_values(prop, host_isar, out); \
+ }
#define CACHE_PROP_FNS_ALL(NAME, LVL, IC) \
CACHE_PROP_FNS(NAME, LVL, IC, sets) \
@@ -439,53 +502,65 @@ const ArmCpuPropDesc arm_cpu_props[] = {
ARM_CUSTOM_PROP("cache_lvl1_icache_sets", "number",
cache_lvl1_icache_sets_get,
cache_lvl1_icache_sets_set,
- cache_lvl1_icache_sets_reset),
+ cache_lvl1_icache_sets_reset,
+ cache_lvl1_icache_sets_get_supported_values),
ARM_CUSTOM_PROP("cache_lvl1_dcache_sets", "number",
cache_lvl1_dcache_sets_get,
cache_lvl1_dcache_sets_set,
- cache_lvl1_dcache_sets_reset),
+ cache_lvl1_dcache_sets_reset,
+ cache_lvl1_dcache_sets_get_supported_values),
ARM_CUSTOM_PROP("cache_lvl2_sets", "number",
cache_lvl2_sets_get,
cache_lvl2_sets_set,
- cache_lvl2_sets_reset),
+ cache_lvl2_sets_reset,
+ cache_lvl2_sets_get_supported_values),
ARM_CUSTOM_PROP("cache_lvl3_sets", "number",
cache_lvl3_sets_get,
cache_lvl3_sets_set,
- cache_lvl3_sets_reset),
+ cache_lvl3_sets_reset,
+ cache_lvl3_sets_get_supported_values),
ARM_CUSTOM_PROP("cache_lvl1_icache_associativity", "number",
cache_lvl1_icache_associativity_get,
cache_lvl1_icache_associativity_set,
- cache_lvl1_icache_associativity_reset),
+ cache_lvl1_icache_associativity_reset,
+ cache_lvl1_icache_associativity_get_supported_values),
ARM_CUSTOM_PROP("cache_lvl1_dcache_associativity", "number",
cache_lvl1_dcache_associativity_get,
cache_lvl1_dcache_associativity_set,
- cache_lvl1_dcache_associativity_reset),
+ cache_lvl1_dcache_associativity_reset,
+ cache_lvl1_dcache_associativity_get_supported_values),
ARM_CUSTOM_PROP("cache_lvl2_associativity", "number",
cache_lvl2_associativity_get,
cache_lvl2_associativity_set,
- cache_lvl2_associativity_reset),
+ cache_lvl2_associativity_reset,
+ cache_lvl2_associativity_get_supported_values),
ARM_CUSTOM_PROP("cache_lvl3_associativity", "number",
cache_lvl3_associativity_get,
cache_lvl3_associativity_set,
- cache_lvl3_associativity_reset),
+ cache_lvl3_associativity_reset,
+ cache_lvl3_associativity_get_supported_values),
ARM_CUSTOM_PROP("cache_lvl1_icache_linesize", "number",
cache_lvl1_icache_linesize_get,
cache_lvl1_icache_linesize_set,
- cache_lvl1_icache_linesize_reset),
+ cache_lvl1_icache_linesize_reset,
+ cache_lvl1_icache_linesize_get_supported_values),
ARM_CUSTOM_PROP("cache_lvl1_dcache_linesize", "number",
cache_lvl1_dcache_linesize_get,
cache_lvl1_dcache_linesize_set,
- cache_lvl1_dcache_linesize_reset),
+ cache_lvl1_dcache_linesize_reset,
+ cache_lvl1_dcache_linesize_get_supported_values),
ARM_CUSTOM_PROP("cache_lvl2_linesize", "number",
cache_lvl2_linesize_get,
cache_lvl2_linesize_set,
- cache_lvl2_linesize_reset),
+ cache_lvl2_linesize_reset,
+ cache_lvl2_linesize_get_supported_values),
ARM_CUSTOM_PROP("cache_lvl3_linesize", "number",
cache_lvl3_linesize_get,
cache_lvl3_linesize_set,
- cache_lvl3_linesize_reset),
+ cache_lvl3_linesize_reset,
+ cache_lvl3_linesize_get_supported_values),
/* Fractional properties */
ARM_FRAC_PROP("feat_CSV2", ID_AA64PFR0, CSV2, ID_AA64PFR1, CSV2_FRAC, csv2_frac_vals),
@@ -1011,6 +1086,10 @@ void arm_prop_append_supported_values(const ArmCpuPropDesc *prop,
const ARMISARegisters *host_isar,
QList *out)
{
+ if (prop->get_supported_values) {
+ prop->get_supported_values(prop, host_isar, out);
+ return;
+ }
switch (prop->type) {
case ARM_PROP_STRING:
arm_field_foreach_supported_arch_val(prop->u.field, host_isar,
@@ -1066,11 +1145,11 @@ void arm_prop_append_supported_values(const ArmCpuPropDesc *prop,
break;
}
case ARM_PROP_COMPOSITE: {
- /* not supported for composites */
+ /* no defaults for composites */
break;
}
case ARM_PROP_CUSTOM: {
- /* not supported for custom props */
+ /* no defaults for custom props */
break;
}
default:
@@ -1090,3 +1169,44 @@ const ArmCpuPropDesc *arm_prop_get_composite_of(const ArmCpuPropDesc *prop)
return NULL;
}
+
+void arm_ccsidr_get_blockers(ARMCPU *cpu,
+ const ARMISARegisters *host_isar,
+ strList **blockers)
+{
+ uint64_t max_linesize = ccsidr_linesize_get_max(host_isar);
+ uint64_t min_linesize = ccsidr_linesize_get_min(host_isar);
+
+ if (!cpu->cache_exposed) {
+ return;
+ }
+
+ for (int level = 0; level < 3; level++) {
+ for (int is_icache = 0; is_icache < 2; is_icache++) {
+ uint64_t level_linesize;
+ char *linesize_props;
+ uint64_t ccsidr = cpu->ccsidr[CACHE_BANK(level, is_icache)];
+
+ if (ccsidr == 0) {
+ continue;
+ }
+
+ if (level == 0) {
+ linesize_props = g_strdup_printf("cache_lvl%d_%s_linesize",
+ level + 1, is_icache ? "icache" : "dcache");
+ } else {
+ linesize_props = g_strdup_printf("cache_lvl%d_linesize",
+ level + 1);
+ }
+
+ level_linesize = object_property_get_int(OBJECT(cpu),
+ linesize_props, NULL);
+
+ if (level_linesize > max_linesize || level_linesize < min_linesize) {
+ QAPI_LIST_PREPEND(*blockers, linesize_props);
+ } else {
+ g_free(linesize_props);
+ }
+ }
+ }
+}
diff --git a/target/arm/arm-cpu-props.h b/target/arm/arm-cpu-props.h
index 55333de858..b32973349c 100644
--- a/target/arm/arm-cpu-props.h
+++ b/target/arm/arm-cpu-props.h
@@ -47,6 +47,9 @@ typedef struct ArmCpuPropDesc {
void (*get)(ARMCPU *cpu, Visitor *v, const char *name, Error **errp);
void (*set)(ARMCPU *cpu, Visitor *v, const char *name, Error **errp);
void (*reset)(ARMCPU *cpu, const char *name, Error **errp);
+ void (*get_supported_values)(const struct ArmCpuPropDesc *prop,
+ const ARMISARegisters *host_isar,
+ QList *out);
} ArmCpuPropDesc;
const ArmCpuPropDesc *get_arm_cpu_props(void);
@@ -61,5 +64,7 @@ const ArmCpuPropDesc *arm_prop_for_field(ArmFieldIdx field);
void arm_prop_append_supported_values(const ArmCpuPropDesc *prop,
const ARMISARegisters *host_isar,
QList *out);
+void arm_ccsidr_get_blockers(ARMCPU *cpu, const ARMISARegisters *host_isar,
+ strList **blockers);
#endif
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [RFC PATCH v2 29/29] target/arm/kvm: fix host model writeback when kernel supports EL2
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (27 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 28/29] target/arm: supported-values and blockers for CCSIDR cache properties Khushit Shah
@ 2026-06-05 8:33 ` Khushit Shah
2026-06-12 14:50 ` [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Eric Auger
29 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-05 8:33 UTC (permalink / raw)
To: qemu-devel, qemu-arm, kvmarm, Eric Auger
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland, Khushit Shah
kvm_arm_get_host_cpu_features() probes the host by spinning up a
scratch vCPU and reading its ID registers. When the host kernel
advertises nested virtualization, the scratch is created with
KVM_ARM_VCPU_HAS_EL2, which makes the kernel run limit_nv_id_reg()
on that vCPU and force several fields (e.g. ID_AA64MMFR4_EL1.NV_frac,
parts of ID_AA64DFR0_EL1) to values that match KVM's nested-virt
capabilities rather than the raw host.
If the actual vCPU is later created without EL2 (e.g. -machine
virt,virtualization=off), the EL2-on values cached above no longer
match what the kernel exposes for the real vCPU and ID-register
writeback fails.
Fix this by caching two host views, one probed with EL2 and one
without, and selecting the appropriate view at every use site.
For -cpu host (and -cpu max) without EL2 we additionally rebase
cpu->isar.idregs[] from the EL2-on view it was initialized with
onto the EL2-off view via kvm_arm_rebase_host_idregs(), so each
field that the user has not explicitly touched picks up the value
that the real vCPU will actually see.
Corner case: the rebase compares the post-init field value against
the EL2-on host value to decide whether the user set it. If the
user directly or indirectly set field X=i and the EL2-on view also
reports feat_X=i but the EL2-off view reports feat_X=j, the rebase
cannot distinguish "user asked for i" from "inherited i from host" and
will overwrite with j. This only affects -cpu host/max without EL2
on NV enabled kernels where the user-requested value happens to match
the EL2-on host view, so we avoid the complexity of user set values
tracking and accept the loss here.
Named models are not affected with the issue as they already start
with default-zeroed view.
Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
---
target/arm/arm-cpu-models.c | 10 +++-
target/arm/arm-qmp-cmds.c | 2 +-
target/arm/cpu64.c | 2 +-
target/arm/kvm-stub.c | 4 +-
target/arm/kvm.c | 98 ++++++++++++++++++++++++++++++-------
target/arm/kvm_arm.h | 5 +-
6 files changed, 96 insertions(+), 25 deletions(-)
diff --git a/target/arm/arm-cpu-models.c b/target/arm/arm-cpu-models.c
index d38293cfb2..0fc30b72ed 100644
--- a/target/arm/arm-cpu-models.c
+++ b/target/arm/arm-cpu-models.c
@@ -548,7 +548,12 @@ static void arm_named_cpu_initfn(Object *obj)
return;
}
- kvm_arm_set_cpu_features_from_host(cpu);
+ /*
+ * Start with the host view without EL2.
+ * If nested virt is needed user must provide values for all the
+ * blockers.
+ */
+ kvm_arm_set_cpu_features_from_host(cpu, false);
if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
return;
}
@@ -574,7 +579,8 @@ void arm_cpu_class_check_missing_features(ARMCPUClass *acc, strList **blockers)
goto out;
}
- host_isar = kvm_arm_get_host_isar();
+ /* Use the host view without EL2 to calculate blockers. */
+ host_isar = kvm_arm_get_host_isar(false);
if (cpu_isar_feature(aa64_sve, cpu)) {
arm_cpu_sve_finalize(cpu, &err);
diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c
index e13dfeb357..844bc84720 100644
--- a/target/arm/arm-qmp-cmds.c
+++ b/target/arm/arm-qmp-cmds.c
@@ -92,7 +92,7 @@ CpuPropInfoList *qmp_query_arm_cpu_props_info(Error **errp)
sv = qlist_new();
arm_prop_append_supported_values(pdesc,
- kvm_arm_get_host_isar(),
+ kvm_arm_get_host_isar(false),
sv);
prop_info->supported_values = QOBJECT(sv);
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 2fa5b4d9da..bad0b1f9f9 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -889,7 +889,7 @@ static void aarch64_host_initfn(Object *obj)
#if defined(CONFIG_KVM)
kvm_arm_set_cpreg_mig_tolerances(cpu);
- kvm_arm_set_cpu_features_from_host(cpu);
+ kvm_arm_set_cpu_features_from_host(cpu, true);
aarch64_add_sve_properties(obj);
arm_add_cpu_props(obj);
#elif defined(CONFIG_HVF)
diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c
index dd683beaaf..98f41818ba 100644
--- a/target/arm/kvm-stub.c
+++ b/target/arm/kvm-stub.c
@@ -45,7 +45,7 @@ bool kvm_arm_el2_supported(void)
/*
* These functions should never actually be called without KVM support.
*/
-void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool with_el2)
{
g_assert_not_reached();
}
@@ -120,7 +120,7 @@ char *kvm_print_register_name(uint64_t regidx)
g_assert_not_reached();
}
-const ARMISARegisters *kvm_arm_get_host_isar(void)
+const ARMISARegisters *kvm_arm_get_host_isar(bool with_el2)
{
return NULL;
}
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 984c7fd256..3dbc2b5f1b 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -65,7 +65,7 @@ typedef struct ARMHostCPUFeatures {
const char *dtb_compatible;
} ARMHostCPUFeatures;
-static ARMHostCPUFeatures arm_host_cpu_features;
+static ARMHostCPUFeatures arm_host_cpu_features[2];
#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) [NAME##_IDX] = #NAME,
const char * const sysreg_names[NUM_ID_IDX] = {
@@ -349,7 +349,7 @@ static uint32_t kvm_arm_sve_get_vls(int fd)
return vls[0] & MAKE_64BIT_MASK(0, ARM_MAX_VQ);
}
-static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
+static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf, bool with_el2)
{
/* Identify the feature bits corresponding to the host CPU, and
* fill out the ARMHostCPUClass fields accordingly. To do this
@@ -389,7 +389,7 @@ static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
* Ask for EL2 if supported.
*/
el2_supported = kvm_arm_el2_supported();
- if (el2_supported) {
+ if (el2_supported && with_el2) {
init.features[0] |= 1 << KVM_ARM_VCPU_HAS_EL2;
}
@@ -528,7 +528,7 @@ static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
err |= get_host_cpu_reg(fd, ahcf, ID_AA64ZFR0_EL1_IDX);
/* Read the set of supported vector lengths. */
- arm_host_cpu_features.sve_vq_supported = kvm_arm_sve_get_vls(fd);
+ ahcf->sve_vq_supported = kvm_arm_sve_get_vls(fd);
}
}
/*
@@ -536,7 +536,6 @@ static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
* for all registers, hence ignore the errors.
*/
get_host_cpu_idregs_all(fd, ahcf);
-
{
int wret = get_writable_id_regs(fdarray[1]);
if (wret) {
@@ -572,15 +571,15 @@ static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
ahcf->features = features;
}
-void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool with_el2)
{
CPUARMState *env = &cpu->env;
- if (!arm_host_cpu_features.dtb_compatible) {
- kvm_arm_get_host_cpu_features(&arm_host_cpu_features);
+ if (!arm_host_cpu_features[with_el2].dtb_compatible) {
+ kvm_arm_get_host_cpu_features(&arm_host_cpu_features[with_el2], with_el2);
}
- cpu->kvm_target = arm_host_cpu_features.target;
+ cpu->kvm_target = arm_host_cpu_features[with_el2].target;
if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
/*
@@ -591,15 +590,18 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
return;
}
- cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible;
- cpu->isar = arm_host_cpu_features.isar;
- cpu->sve_vq.supported = arm_host_cpu_features.sve_vq_supported;
- env->features = arm_host_cpu_features.features;
+ cpu->dtb_compatible = arm_host_cpu_features[with_el2].dtb_compatible;
+ cpu->isar = arm_host_cpu_features[with_el2].isar;
+ cpu->sve_vq.supported = arm_host_cpu_features[with_el2].sve_vq_supported;
+ env->features = arm_host_cpu_features[with_el2].features;
}
-const ARMISARegisters *kvm_arm_get_host_isar(void)
+const ARMISARegisters *kvm_arm_get_host_isar(bool with_el2)
{
- return &arm_host_cpu_features.isar;
+ if (!arm_host_cpu_features[with_el2].dtb_compatible) {
+ kvm_arm_get_host_cpu_features(&arm_host_cpu_features[with_el2], with_el2);
+ }
+ return &arm_host_cpu_features[with_el2].isar;
}
static bool kvm_no_adjvtime_get(Object *obj, Error **errp)
@@ -2187,6 +2189,52 @@ bool kvm_arm_mte_supported(void)
return kvm_check_extension(kvm_state, KVM_CAP_ARM_MTE);
}
+/*
+ * Rebase cpu->isar.idregs[] on top of new_isar given the initial_isar.
+ *
+ * For fields in cpu->isar.idregs[] that are same as initial_isar, update
+ * the field with the new_isar values.
+ */
+static void kvm_arm_rebase_host_idregs(ARMCPU *cpu,
+ const ARMISARegisters *new_isar,
+ const ARMISARegisters *initial_isar)
+{
+ for (int i = 0; i < NUM_ID_IDX; i++) {
+ ArmIdReg *idreg = &arm_idregs[i];
+
+ for (int j = 0; j < idreg->fields_count; j++) {
+ ArmIdRegField *field = &idreg->fields[j];
+ uint64_t idreg_val;
+ uint64_t initial_val;
+ uint64_t new_val;
+
+ arm_idreg_field_read(&cpu->isar, field->idx,
+ &idreg_val);
+ arm_idreg_field_read(initial_isar, field->idx,
+ &initial_val);
+ arm_idreg_field_read(new_isar, field->idx,
+ &new_val);
+
+ if (idreg_val == initial_val && new_val != idreg_val) {
+ /* The cpu->isar.idregs[]'s field val is same as
+ * intial_isar.idregs[]'s field val, which was used to
+ * initialise it. Hence, override it with the new_isar[]
+ * value. User might have explicitly asked for some value
+ * which matched the host value without EL2 in this case,
+ * that value is lost. As rebase is needed in very specific
+ * case, we avoid that complication.
+ */
+ arm_idreg_field_write(cpu, field->idx, new_val,
+ &error_abort);
+
+ warn_report("KVM ID %s.%s value changed from 0x%016"
+ PRIx64 " to 0x%016" PRIx64,
+ idreg->name, field->name, idreg_val, new_val);
+ }
+ }
+ }
+}
+
QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
static int kvm_arm_sve_set_vls(ARMCPU *cpu)
@@ -2307,8 +2355,24 @@ int kvm_arch_init_vcpu(CPUState *cs)
return ret;
}
- /* validate the cpu->isar.idregs[] against the host's isar.idregs[]*/
- if (!arm_idregs_validate_safe_rule(cpu, &arm_host_cpu_features.isar, &err)) {
+ /* For -cpu host/max, rebase the idregs[] on top of cpregs[] */
+ if ((object_dynamic_cast(OBJECT(cpu), TYPE_ARM_HOST_CPU)
+ || object_dynamic_cast(OBJECT(cpu), TYPE_ARM_MAX_CPU))
+ && !cpu->has_el2
+ && kvm_arm_el2_supported()) {
+ /* scratch vCPU is created with EL2-enabled for -cpu host */
+ kvm_arm_rebase_host_idregs(cpu,
+ kvm_arm_get_host_isar(false),
+ kvm_arm_get_host_isar(true));
+ }
+
+ /*
+ * validate the cpu->isar.idregs[] against the ahcf->isar.idregs[],
+ * select ahcf based on the cpu->has_el2
+ */
+ if (!arm_idregs_validate_safe_rule(cpu,
+ kvm_arm_get_host_isar(cpu->has_el2),
+ &err)) {
error_report_err(err);
return -EINVAL;
}
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 750dbe1ef4..538f87e69e 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -129,11 +129,12 @@ void kvm_arm_destroy_scratch_host_vcpu(int *fdarray);
/**
* kvm_arm_set_cpu_features_from_host:
* @cpu: ARMCPU to set the features for
+ * @with_el2: probe the host with the EL2-enabled scratch vCPU view
*
* Set up the ARMCPU struct fields up to match the information probed
* from the host CPU.
*/
-void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
+void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool with_el2);
/**
* kvm_arm_add_vcpu_properties:
@@ -231,7 +232,7 @@ void kvm_arm_enable_mte(Object *cpuobj, Error **errp);
void arm_cpu_kvm_set_irq(void *arm_cpu, int irq, int level);
-const ARMISARegisters *kvm_arm_get_host_isar(void);
+const ARMISARegisters *kvm_arm_get_host_isar(bool with_el2);
void arm_gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3);
--
2.52.0
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [RFC PATCH v2 02/29] target/arm: Add ID Register field descriptions in cpu-idregs.h.inc
2026-06-05 8:33 ` [RFC PATCH v2 02/29] target/arm: Add ID Register field descriptions in cpu-idregs.h.inc Khushit Shah
@ 2026-06-12 9:35 ` Eric Auger
2026-06-12 11:01 ` Khushit Shah
2026-06-17 6:32 ` Eric Auger
1 sibling, 1 reply; 41+ messages in thread
From: Eric Auger @ 2026-06-12 9:35 UTC (permalink / raw)
To: Khushit Shah, qemu-devel, qemu-arm, kvmarm
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland
Hi Kushit,
On 6/5/26 10:33 AM, Khushit Shah wrote:
> From: Shaju Abraham <shaju.abraham@nutanix.com>
>
> Add a declarative description of every architecturally defined field in
> the Arm64 ID registers in cpu-idregs.h.inc file. This file will be
> included multiple times with different definitions to build:
> - per-field arch values,
> - per-register field descriptor arrays,
> - arm-idregs[] table etc.
>
> The architecturally defined values for each ID register field is
> extracted from 6.18 kernel's arch/arm64/tools/sysreg file.
>
> The safe-value tags and default values are derived from the kernel's
> ftr_bits array.
>
> Aarch32 ID registers are added with dummy field so they can be
> defaulted to 0 by later commits.
>
> X-macro structure:
> IDREG_START(REG)
> IDREG_FIELD_START(REG, FIELD, SHIFT, LENGTH, SAFE_RULE, DEFAULT_VAL)
> IDREG_FIELD_ARCH_VAL(VALUE, NAME)
> ...
> IDREG_FIELD_END(REG, FIELD)
> ...
> IDREG_END(REG)
>
> Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
> Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
> Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
> ---
> target/arm/cpu-idregs.h.inc | 1807 +++++++++++++++++++++++++++++++++++
> 1 file changed, 1807 insertions(+)
> create mode 100644 target/arm/cpu-idregs.h.inc
>
> diff --git a/target/arm/cpu-idregs.h.inc b/target/arm/cpu-idregs.h.inc
> new file mode 100644
> index 0000000000..7e2bbf256d
> --- /dev/null
> +++ b/target/arm/cpu-idregs.h.inc
> @@ -0,0 +1,1807 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +/* ID_AA64ISAR0_EL1 */
> +IDREG_START(ID_AA64ISAR0_EL1)
> +IDREG_FIELD_START(ID_AA64ISAR0, RES0_0, 0, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ISAR0, RES0_0)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, AES, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "aes")
> +IDREG_FIELD_ARCH_VAL(0b0010, "pmull")
> +IDREG_FIELD_END(ID_AA64ISAR0, AES)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, SHA1, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, SHA1)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, SHA2, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "sha256")
> +IDREG_FIELD_ARCH_VAL(0b0010, "sha512")
> +IDREG_FIELD_END(ID_AA64ISAR0, SHA2)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, CRC32, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, CRC32)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, ATOMIC, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0010, "on")
> +IDREG_FIELD_ARCH_VAL(0b0011, "LSE128")
> +IDREG_FIELD_END(ID_AA64ISAR0, ATOMIC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, RES0_24, 24, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ISAR0, RES0_24)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, RDM, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, RDM)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, SHA3, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, SHA3)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, SM3, 36, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, SM3)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, SM4, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, SM4)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, DP, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, DP)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, FHM, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, FHM)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, TS, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "flagm")
> +IDREG_FIELD_ARCH_VAL(0b0010, "flagm2")
> +IDREG_FIELD_END(ID_AA64ISAR0, TS)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, TLB, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "os")
> +IDREG_FIELD_ARCH_VAL(0b0010, "range")
> +IDREG_FIELD_END(ID_AA64ISAR0, TLB)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, RNDR, 60, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, RNDR)
> +
> +IDREG_END(ID_AA64ISAR0_EL1)
> +
> +/* ID_AA64ISAR1_EL1 */
> +IDREG_START(ID_AA64ISAR1_EL1)
> +IDREG_FIELD_START(ID_AA64ISAR1, DPB, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "dpb2")
> +IDREG_FIELD_END(ID_AA64ISAR1, DPB)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, APA, 4, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "pauth")
> +IDREG_FIELD_ARCH_VAL(0b0010, "epac")
> +IDREG_FIELD_ARCH_VAL(0b0011, "pauth2")
> +IDREG_FIELD_ARCH_VAL(0b0100, "fpac")
> +IDREG_FIELD_ARCH_VAL(0b0101, "fpaccombine")
> +IDREG_FIELD_ARCH_VAL(0b0110, "pauth_lr")
> +IDREG_FIELD_END(ID_AA64ISAR1, APA)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, API, 8, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "pauth")
> +IDREG_FIELD_ARCH_VAL(0b0010, "epac")
> +IDREG_FIELD_ARCH_VAL(0b0011, "pauth2")
> +IDREG_FIELD_ARCH_VAL(0b0100, "fpac")
> +IDREG_FIELD_ARCH_VAL(0b0101, "fpaccombine")
> +IDREG_FIELD_ARCH_VAL(0b0110, "pauth_lr")
> +IDREG_FIELD_END(ID_AA64ISAR1, API)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, JSCVT, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, JSCVT)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, FCMA, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, FCMA)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, LRCPC, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "lrcpc2")
> +IDREG_FIELD_ARCH_VAL(0b0011, "lrcpc3")
> +IDREG_FIELD_END(ID_AA64ISAR1, LRCPC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, GPA, 24, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, GPA)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, GPI, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, GPI)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, FRINTTS, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, FRINTTS)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, SB, 36, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, SB)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, SPECRES, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "cosp_rctx")
> +IDREG_FIELD_END(ID_AA64ISAR1, SPECRES)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, BF16, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ebf16")
> +IDREG_FIELD_END(ID_AA64ISAR1, BF16)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, DGH, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, DGH)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, I8MM, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, I8MM)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, XS, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, XS)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, LS64, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "ls64")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ls64_v")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ls64_accdata")
> +IDREG_FIELD_ARCH_VAL(0b0100, "ls64wb")
> +IDREG_FIELD_END(ID_AA64ISAR1, LS64)
After reworking the python script that extract sdata from Registers.json
I can generate
IDREG_START(ID_AA64ISAR1_EL1)
IDREG_FIELD(ID_AA64ISAR1_EL1, LS64, 60, 4)
IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, LS64, 0)
IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, LS64, 1)
IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, LS64, 2)
IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, LS64, 3)
IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, LS64, 4)
IDREG_FIELD(ID_AA64ISAR1_EL1, XS, 56, 4)
IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, XS, 0)
IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, XS, 1)
../..
Thanks
Eric
> +
> +IDREG_END(ID_AA64ISAR1_EL1)
> +
> +/* ID_AA64ISAR2_EL1 */
> +IDREG_START(ID_AA64ISAR2_EL1)
> +IDREG_FIELD_START(ID_AA64ISAR2, WFXT, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0010, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, WFXT)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, RPRES, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, RPRES)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, GPA3, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, GPA3)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, APA3, 12, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "pauth")
> +IDREG_FIELD_ARCH_VAL(0b0010, "epac")
> +IDREG_FIELD_ARCH_VAL(0b0011, "pauth2")
> +IDREG_FIELD_ARCH_VAL(0b0100, "fpac")
> +IDREG_FIELD_ARCH_VAL(0b0101, "fpaccombine")
> +IDREG_FIELD_ARCH_VAL(0b0110, "pauth_lr")
> +IDREG_FIELD_END(ID_AA64ISAR2, APA3)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, MOPS, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, MOPS)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, BC, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, BC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, PAC_FRAC, 24, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, PAC_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, CLRBHB, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, CLRBHB)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, SYSREG_128, 32, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, SYSREG_128)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, SYSINSTR_128, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, SYSINSTR_128)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, PRFMSLC, 40, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, PRFMSLC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, PCDPHINT, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, PCDPHINT)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, RPRFM, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, RPRFM)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, CSSC, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "cmpbr")
> +IDREG_FIELD_END(ID_AA64ISAR2, CSSC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, LUT, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, LUT)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, ATS1A, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, ATS1A)
> +
> +IDREG_END(ID_AA64ISAR2_EL1)
> +
> +/* ID_AA64PFR0_EL1 */
> +IDREG_START(ID_AA64PFR0_EL1)
> +IDREG_FIELD_START(ID_AA64PFR0, EL0, 0, 4, LOWER, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
> +IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
> +IDREG_FIELD_END(ID_AA64PFR0, EL0)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, EL1, 4, 4, LOWER, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
> +IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
> +IDREG_FIELD_END(ID_AA64PFR0, EL1)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, EL2, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
> +IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
> +IDREG_FIELD_END(ID_AA64PFR0, EL2)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, EL3, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
> +IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
> +IDREG_FIELD_END(ID_AA64PFR0, EL3)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, FP, 16, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b0001, "fp16")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64PFR0, FP)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, ADVSIMD, 20, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b0001, "fp16")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64PFR0, ADVSIMD)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, GIC, 24, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0011, "v4p1")
> +IDREG_FIELD_END(ID_AA64PFR0, GIC)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, RAS, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "v1p1")
> +IDREG_FIELD_ARCH_VAL(0b0011, "v2")
> +IDREG_FIELD_END(ID_AA64PFR0, RAS)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, SVE, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR0, SVE)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, SEL2, 36, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR0, SEL2)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, MPAM, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "0")
> +IDREG_FIELD_ARCH_VAL(0b0001, "1")
> +IDREG_FIELD_END(ID_AA64PFR0, MPAM)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, AMU, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "v1p1")
> +IDREG_FIELD_END(ID_AA64PFR0, AMU)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, DIT, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR0, DIT)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, RME, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR0, RME)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, CSV2, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "csv2_2")
> +IDREG_FIELD_ARCH_VAL(0b0011, "csv2_3")
> +IDREG_FIELD_END(ID_AA64PFR0, CSV2)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, CSV3, 60, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR0, CSV3)
> +
> +IDREG_END(ID_AA64PFR0_EL1)
> +
> +/* ID_AA64PFR1_EL1 */
> +IDREG_START(ID_AA64PFR1_EL1)
> +IDREG_FIELD_START(ID_AA64PFR1, BT, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, BT)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, SSBS, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ssbs2")
> +IDREG_FIELD_END(ID_AA64PFR1, SSBS)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, MTE, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "mte2")
> +IDREG_FIELD_ARCH_VAL(0b0011, "mte3")
> +IDREG_FIELD_END(ID_AA64PFR1, MTE)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, RAS_FRAC, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "rasv1p1")
> +IDREG_FIELD_END(ID_AA64PFR1, RAS_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, MPAM_FRAC, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "minor_0")
> +IDREG_FIELD_ARCH_VAL(0b0001, "minor_1")
> +IDREG_FIELD_END(ID_AA64PFR1, MPAM_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, RES0_20, 20, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64PFR1, RES0_20)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, SME, 24, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "sme2")
> +IDREG_FIELD_END(ID_AA64PFR1, SME)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, RNDR_TRAP, 28, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, RNDR_TRAP)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, CSV2_FRAC, 32, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "csv2_1p1")
> +IDREG_FIELD_ARCH_VAL(0b0010, "csv2_1p2")
> +IDREG_FIELD_END(ID_AA64PFR1, CSV2_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, NMI, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, NMI)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, MTE_FRAC, 40, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "async")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64PFR1, MTE_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, GCS, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, GCS)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, THE, 48, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, THE)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, MTEX, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "mte")
> +IDREG_FIELD_ARCH_VAL(0b0001, "mte4")
> +IDREG_FIELD_END(ID_AA64PFR1, MTEX)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, DF2, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, DF2)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, PFAR, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, PFAR)
> +
> +IDREG_END(ID_AA64PFR1_EL1)
> +
> +/* ID_AA64MMFR0_EL1 */
> +IDREG_START(ID_AA64MMFR0_EL1)
> +IDREG_FIELD_START(ID_AA64MMFR0, PARANGE, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "32")
> +IDREG_FIELD_ARCH_VAL(0b0001, "36")
> +IDREG_FIELD_ARCH_VAL(0b0010, "40")
> +IDREG_FIELD_ARCH_VAL(0b0011, "42")
> +IDREG_FIELD_ARCH_VAL(0b0100, "44")
> +IDREG_FIELD_ARCH_VAL(0b0101, "48")
> +IDREG_FIELD_ARCH_VAL(0b0110, "52")
> +IDREG_FIELD_ARCH_VAL(0b0111, "56")
> +IDREG_FIELD_END(ID_AA64MMFR0, PARANGE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, ASIDBITS, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "8")
> +IDREG_FIELD_ARCH_VAL(0b0010, "16")
> +IDREG_FIELD_END(ID_AA64MMFR0, ASIDBITS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, BIGEND, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR0, BIGEND)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, SNSMEM, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR0, SNSMEM)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, BIGENDEL0, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR0, BIGENDEL0)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN16, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "52_bit")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN16)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN64, 24, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN64)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN4, 28, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b0001, "52_bit")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN4)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN16_2, 32, 4, EXACT, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0000, "tgran16")
> +IDREG_FIELD_ARCH_VAL(0b0001, "off")
> +IDREG_FIELD_ARCH_VAL(0b0010, "on")
> +IDREG_FIELD_ARCH_VAL(0b0011, "52_bit")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN16_2)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN64_2, 36, 4, EXACT, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0000, "tgran64")
> +IDREG_FIELD_ARCH_VAL(0b0001, "off")
> +IDREG_FIELD_ARCH_VAL(0b0010, "on")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN64_2)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN4_2, 40, 4, EXACT, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0000, "tgran4")
> +IDREG_FIELD_ARCH_VAL(0b0001, "off")
> +IDREG_FIELD_ARCH_VAL(0b0010, "on")
> +IDREG_FIELD_ARCH_VAL(0b0011, "52_bit")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN4_2)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, EXS, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR0, EXS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, RES0_48, 48, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR0, RES0_48)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, FGT, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "fgt2")
> +IDREG_FIELD_END(ID_AA64MMFR0, FGT)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, ECV, 60, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "cntpoff")
> +IDREG_FIELD_END(ID_AA64MMFR0, ECV)
> +
> +IDREG_END(ID_AA64MMFR0_EL1)
> +
> +/* ID_AA64MMFR1_EL1 */
> +IDREG_START(ID_AA64MMFR1_EL1)
> +IDREG_FIELD_START(ID_AA64MMFR1, HAFDBS, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "af")
> +IDREG_FIELD_ARCH_VAL(0b0010, "dbm")
> +IDREG_FIELD_ARCH_VAL(0b0011, "haft")
> +IDREG_FIELD_ARCH_VAL(0b0100, "hdbss")
> +IDREG_FIELD_END(ID_AA64MMFR1, HAFDBS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, VMIDBITS, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "8")
> +IDREG_FIELD_ARCH_VAL(0b0010, "16")
> +IDREG_FIELD_END(ID_AA64MMFR1, VMIDBITS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, VH, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, VH)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, HPDS, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "hpds2")
> +IDREG_FIELD_END(ID_AA64MMFR1, HPDS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, LO, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, LO)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, PAN, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "pan2")
> +IDREG_FIELD_ARCH_VAL(0b0011, "pan3")
> +IDREG_FIELD_END(ID_AA64MMFR1, PAN)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, SPECSEI, 24, 4, HIGHER, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, SPECSEI)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, XNX, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, XNX)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, TWED, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, TWED)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, ETS, 36, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ets2")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ets3")
> +IDREG_FIELD_END(ID_AA64MMFR1, ETS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, HCX, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, HCX)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, AFP, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, AFP)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, NTLBPA, 48, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, NTLBPA)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, TIDCP1, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, TIDCP1)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, CMOW, 56, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, CMOW)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, ECBHB, 60, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, ECBHB)
> +
> +IDREG_END(ID_AA64MMFR1_EL1)
> +
> +/* ID_AA64MMFR2_EL1 */
> +IDREG_START(ID_AA64MMFR2_EL1)
> +IDREG_FIELD_START(ID_AA64MMFR2, CNP, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, CNP)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, UAO, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, UAO)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, LSM, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, LSM)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, IESB, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, IESB)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, VARANGE, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "48")
> +IDREG_FIELD_ARCH_VAL(0b0001, "52")
> +IDREG_FIELD_END(ID_AA64MMFR2, VARANGE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, CCIDX, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "32")
> +IDREG_FIELD_ARCH_VAL(0b0001, "64")
> +IDREG_FIELD_END(ID_AA64MMFR2, CCIDX)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, NV, 24, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "nv2")
> +IDREG_FIELD_END(ID_AA64MMFR2, NV)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, ST, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "39")
> +IDREG_FIELD_ARCH_VAL(0b0001, "48_47")
> +IDREG_FIELD_END(ID_AA64MMFR2, ST)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, AT, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, AT)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, IDS, 36, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "0x0")
> +IDREG_FIELD_ARCH_VAL(0b0001, "0x18")
> +IDREG_FIELD_END(ID_AA64MMFR2, IDS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, FWB, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, FWB)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, RES0_44, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR2, RES0_44)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, TTL, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, TTL)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, BBM, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "0")
> +IDREG_FIELD_ARCH_VAL(0b0001, "1")
> +IDREG_FIELD_ARCH_VAL(0b0010, "2")
> +IDREG_FIELD_END(ID_AA64MMFR2, BBM)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, EVT, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ttlbxs")
> +IDREG_FIELD_END(ID_AA64MMFR2, EVT)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, E0PD, 60, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, E0PD)
> +
> +IDREG_END(ID_AA64MMFR2_EL1)
> +
> +/* ID_AA64MMFR3_EL1 */
> +IDREG_START(ID_AA64MMFR3_EL1)
> +IDREG_FIELD_START(ID_AA64MMFR3, TCRX, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, TCRX)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, SCTLRX, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, SCTLRX)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, S1PIE, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, S1PIE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, S2PIE, 12, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, S2PIE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, S1POE, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, S1POE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, S2POE, 20, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, S2POE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, AIE, 24, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, AIE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, MEC, 28, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, MEC)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, D128, 32, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, D128)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, D128_2, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, D128_2)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, SNERR, 40, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "sync")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ANERR")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ANERR_IND")
> +IDREG_FIELD_END(ID_AA64MMFR3, SNERR)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, ANERR, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "async")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ANERR")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ANERR_IND")
> +IDREG_FIELD_END(ID_AA64MMFR3, ANERR)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, RES0_48, 48, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR3, RES0_48)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, SDERR, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "dev_sync")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ADERR")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ADERR_IND")
> +IDREG_FIELD_END(ID_AA64MMFR3, SDERR)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, ADERR, 56, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "dev_async")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ADERR")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ADERR_IND")
> +IDREG_FIELD_END(ID_AA64MMFR3, ADERR)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, SPEC_FPACC, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, SPEC_FPACC)
> +
> +IDREG_END(ID_AA64MMFR3_EL1)
> +
> +/* ID_AA64DFR0_EL1 */
> +IDREG_START(ID_AA64DFR0_EL1)
> +IDREG_FIELD_START(ID_AA64DFR0, DEBUGVER, 0, 4, LOWER, 0x6)
> +IDREG_FIELD_ARCH_VAL(0b0110, "on")
> +IDREG_FIELD_ARCH_VAL(0b0111, "vhe")
> +IDREG_FIELD_ARCH_VAL(0b1000, "v8p2")
> +IDREG_FIELD_ARCH_VAL(0b1001, "v8p4")
> +IDREG_FIELD_ARCH_VAL(0b1010, "v8p8")
> +IDREG_FIELD_ARCH_VAL(0b1011, "v8p9")
> +IDREG_FIELD_END(ID_AA64DFR0, DEBUGVER)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, TRACEVER, 4, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR0, TRACEVER)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, PMUVER, 8, 4, SIGNED_LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0100, "v3p1")
> +IDREG_FIELD_ARCH_VAL(0b0101, "v3p4")
> +IDREG_FIELD_ARCH_VAL(0b0110, "v3p5")
> +IDREG_FIELD_ARCH_VAL(0b0111, "v3p7")
> +IDREG_FIELD_ARCH_VAL(0b1000, "v3p8")
> +IDREG_FIELD_ARCH_VAL(0b1001, "v3p9")
> +IDREG_FIELD_ARCH_VAL(0b1111, "imp_def")
> +IDREG_FIELD_END(ID_AA64DFR0, PMUVER)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, BRPS, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR0, BRPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, PMSS, 16, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR0, PMSS)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, WRPS, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR0, WRPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, SEBEP, 24, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR0, SEBEP)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, CTX_CMPS, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR0, CTX_CMPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, PMSVER, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "v1p1")
> +IDREG_FIELD_ARCH_VAL(0b0011, "v1p2")
> +IDREG_FIELD_ARCH_VAL(0b0100, "v1p3")
> +IDREG_FIELD_ARCH_VAL(0b0101, "v1p4")
> +IDREG_FIELD_ARCH_VAL(0b0110, "v1p5")
> +IDREG_FIELD_END(ID_AA64DFR0, PMSVER)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, DOUBLELOCK, 36, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64DFR0, DOUBLELOCK)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, TRACEFILT, 40, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR0, TRACEFILT)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, TRACEBUFFER, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "trbe_v1p1")
> +IDREG_FIELD_END(ID_AA64DFR0, TRACEBUFFER)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, MTPMU, 48, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "ni_impdef")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64DFR0, MTPMU)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, BRBE, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "brbe_v1p1")
> +IDREG_FIELD_END(ID_AA64DFR0, BRBE)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, EXTTRCBUFF, 56, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR0, EXTTRCBUFF)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, HPMN0, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "unpredictable")
> +IDREG_FIELD_ARCH_VAL(0b0001, "def")
> +IDREG_FIELD_END(ID_AA64DFR0, HPMN0)
> +
> +IDREG_END(ID_AA64DFR0_EL1)
> +
> +/* ID_AA64ZFR0_EL1 */
> +IDREG_START(ID_AA64ZFR0_EL1)
> +IDREG_FIELD_START(ID_AA64ZFR0, SVEVER, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b0001, "sve2")
> +IDREG_FIELD_ARCH_VAL(0b0010, "sve2p1")
> +IDREG_FIELD_ARCH_VAL(0b0011, "sve2p2")
> +IDREG_FIELD_END(ID_AA64ZFR0, SVEVER)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, AES, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "pmull128")
> +IDREG_FIELD_ARCH_VAL(0b0011, "aes2")
> +IDREG_FIELD_END(ID_AA64ZFR0, AES)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, RES0_8, 8, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ZFR0, RES0_8)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, ELTPERM, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, ELTPERM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, BITPERM, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, BITPERM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, BFLOAT16, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ebf16")
> +IDREG_FIELD_END(ID_AA64ZFR0, BFLOAT16)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, B16B16, 24, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "bfscale")
> +IDREG_FIELD_END(ID_AA64ZFR0, B16B16)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, RES0_28, 28, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ZFR0, RES0_28)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, SHA3, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, SHA3)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, RES0_36, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ZFR0, RES0_36)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, SM4, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, SM4)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, I8MM, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, I8MM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, F16MM, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, F16MM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, F32MM, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, F32MM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, F64MM, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, F64MM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, RES0_60, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ZFR0, RES0_60)
> +
> +IDREG_END(ID_AA64ZFR0_EL1)
> +
> +/* ID_AA64SMFR0_EL1 */
> +IDREG_START(ID_AA64SMFR0_EL1)
> +IDREG_FIELD_START(ID_AA64SMFR0, SMOP4, 0, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SMOP4)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_1, 1, 15, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_1)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, STMOP, 16, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, STMOP)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_17, 17, 6, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_17)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SFEXPA, 23, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SFEXPA)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, AES, 24, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, AES)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SBITPERM, 25, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SBITPERM)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_26, 26, 2, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_26)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SF8DP2, 28, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SF8DP2)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SF8DP4, 29, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SF8DP4)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SF8FMA, 30, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SF8FMA)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_31, 31, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_31)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F32F32, 32, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F32F32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, BI32I32, 33, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, BI32I32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, B16F32, 34, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, B16F32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F16F32, 35, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F16F32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, I8I32, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b1111, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, I8I32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F8F32, 40, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F8F32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F8F16, 41, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F8F16)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F16F16, 42, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F16F16)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, B16B16, 43, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, B16B16)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, I16I32, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0101, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, I16I32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F64F64, 48, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F64F64)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_49, 49, 3, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_49)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, I16I64, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b1111, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, I16I64)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SMEVER, 56, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "sme")
> +IDREG_FIELD_ARCH_VAL(0b0001, "sme2")
> +IDREG_FIELD_ARCH_VAL(0b0010, "sme2p1")
> +IDREG_FIELD_ARCH_VAL(0b0011, "sme2p2")
> +IDREG_FIELD_END(ID_AA64SMFR0, SMEVER)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, LUTV2, 60, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, LUTV2)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_61, 61, 2, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_61)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, FA64, 63, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, FA64)
> +
> +IDREG_END(ID_AA64SMFR0_EL1)
> +
> +/* CTR_EL0 */
> +IDREG_START(CTR_EL0)
> +IDREG_FIELD_START(CTR_EL0, IMINLINE, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, IMINLINE)
> +
> +IDREG_FIELD_START(CTR_EL0, RES0_4, 4, 10, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(CTR_EL0, RES0_4)
> +
> +IDREG_FIELD_START(CTR_EL0, L1IP, 14, 2, EXACT, 0b10)
> +IDREG_FIELD_ARCH_VAL(0b00, "reserved_vpipt")
> +IDREG_FIELD_ARCH_VAL(0b01, "reserved_aivivt")
> +IDREG_FIELD_ARCH_VAL(0b10, "vipt")
> +IDREG_FIELD_ARCH_VAL(0b11, "pipt")
> +IDREG_FIELD_END(CTR_EL0, L1IP)
> +
> +IDREG_FIELD_START(CTR_EL0, DMINLINE, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, DMINLINE)
> +
> +IDREG_FIELD_START(CTR_EL0, ERG, 20, 4, HIGHER_OR_ZERO, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, ERG)
> +
> +IDREG_FIELD_START(CTR_EL0, CWG, 24, 4, HIGHER_OR_ZERO, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, CWG)
> +
> +IDREG_FIELD_START(CTR_EL0, IDC, 28, 1, LOWER, 0b1)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, IDC)
> +
> +IDREG_FIELD_START(CTR_EL0, DIC, 29, 1, LOWER, 0b1)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, DIC)
> +
> +IDREG_FIELD_START(CTR_EL0, RES0_30, 30, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(CTR_EL0, RES0_30)
> +
> +IDREG_FIELD_START(CTR_EL0, RES1_31, 31, 1, EXACT, 1)
> +IDREG_FIELD_ARCH_VAL(1, NULL)
> +IDREG_FIELD_END(CTR_EL0, RES1_31)
> +
> +IDREG_FIELD_START(CTR_EL0, TMINLINE, 32, 6, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, TMINLINE)
> +
> +IDREG_FIELD_START(CTR_EL0, RES0_38, 38, 26, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(CTR_EL0, RES0_38)
> +
> +IDREG_END(CTR_EL0)
> +
> +/* ID_AA64ISAR3_EL1 */
> +IDREG_START(ID_AA64ISAR3_EL1)
> +IDREG_FIELD_START(ID_AA64ISAR3, CPA, 0, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "cpa2")
> +IDREG_FIELD_END(ID_AA64ISAR3, CPA)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, FAMINMAX, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, FAMINMAX)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, TLBIW, 8, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, TLBIW)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, PACM, 12, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "trivial_imp")
> +IDREG_FIELD_ARCH_VAL(0b0010, "full_imp")
> +IDREG_FIELD_END(ID_AA64ISAR3, PACM)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, LSFE, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, LSFE)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, OCCMO, 20, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, OCCMO)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, LSUI, 24, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, LSUI)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, FPRCVT, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, FPRCVT)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, RES0_32, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ISAR3, RES0_32)
> +
> +IDREG_END(ID_AA64ISAR3_EL1)
> +
> +/* ID_AA64PFR2_EL1 */
> +IDREG_START(ID_AA64PFR2_EL1)
> +IDREG_FIELD_START(ID_AA64PFR2, MTEPERM, 0, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, MTEPERM)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, MTESTOREONLY, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, MTESTOREONLY)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, MTEFAR, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, MTEFAR)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, GCIE, 12, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, GCIE)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, UINJ, 16, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, UINJ)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, RES0_20, 20, 12, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64PFR2, RES0_20)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, FPMR, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, FPMR)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, RES0_36, 36, 28, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64PFR2, RES0_36)
> +
> +IDREG_END(ID_AA64PFR2_EL1)
> +
> +/* ID_AA64FPFR0_EL1 */
> +IDREG_START(ID_AA64FPFR0_EL1)
> +IDREG_FIELD_START(ID_AA64FPFR0, F8E5M2, 0, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8E5M2)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8E4M3, 1, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8E4M3)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, RES0_2, 2, 24, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64FPFR0, RES0_2)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8MM4, 26, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8MM4)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8MM8, 27, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8MM8)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8DP2, 28, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8DP2)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8DP4, 29, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8DP4)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8FMA, 30, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8FMA)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8CVT, 31, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8CVT)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, RES0_32, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64FPFR0, RES0_32)
> +
> +IDREG_END(ID_AA64FPFR0_EL1)
> +
> +
> +/* ID_AA64MMFR4_EL1 */
> +IDREG_START(ID_AA64MMFR4_EL1)
> +IDREG_FIELD_START(ID_AA64MMFR4, POPS, 0, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, POPS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, EIESB, 4, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "toel3")
> +IDREG_FIELD_ARCH_VAL(0b0010, "toelx")
> +IDREG_FIELD_ARCH_VAL(0b1111, "any")
> +IDREG_FIELD_END(ID_AA64MMFR4, EIESB)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, ASID2, 8, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, ASID2)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, HACDBS, 12, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, HACDBS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, FGWTE3, 16, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, FGWTE3)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, NV_FRAC, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "nv_nv2")
> +IDREG_FIELD_ARCH_VAL(0b0001, "nv2_only")
> +IDREG_FIELD_ARCH_VAL(0b0010, "nv2p1")
> +IDREG_FIELD_END(ID_AA64MMFR4, NV_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, E2H0, 24, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b1110, "ni_nv1")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64MMFR4, E2H0)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, RMEGDI, 28, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, RMEGDI)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, RES0_32, 32, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR4, RES0_32)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, E3DSE, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, E3DSE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, RES0_40, 40, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR4, RES0_40)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, SRMASK, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, SRMASK)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, RES0_48, 48, 16, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR4, RES0_48)
> +
> +IDREG_END(ID_AA64MMFR4_EL1)
> +
> +/* ID_AA64DFR1_EL1 */
> +IDREG_START(ID_AA64DFR1_EL1)
> +IDREG_FIELD_START(ID_AA64DFR1, SYSPMUID, 0, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR1, SYSPMUID)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, BRPS, 8, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR1, BRPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, WRPS, 16, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR1, WRPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, CTX_CMPS, 24, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR1, CTX_CMPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, SPMU, 32, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "imp_spmzr")
> +IDREG_FIELD_END(ID_AA64DFR1, SPMU)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, PMICNTR, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR1, PMICNTR)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, ABLE, 40, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR1, ABLE)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, ITE, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR1, ITE)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, EBEP, 48, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR1, EBEP)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, DPFZS, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "ignr")
> +IDREG_FIELD_ARCH_VAL(0b0001, "frzn")
> +IDREG_FIELD_END(ID_AA64DFR1, DPFZS)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, ABL_CMPS, 56, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR1, ABL_CMPS)
> +
> +IDREG_END(ID_AA64DFR1_EL1)
> +
> +/* MIDR_EL1 */
> +IDREG_START(MIDR_EL1)
> +IDREG_FIELD_START(MIDR, REVISION, 0, 4, ANY, 0)
> +IDREG_FIELD_END(MIDR, REVISION)
> +
> +IDREG_FIELD_START(MIDR, PARTNUM, 4, 12, ANY, 0)
> +IDREG_FIELD_END(MIDR, PARTNUM)
> +
> +IDREG_FIELD_START(MIDR, ARCHITECTURE, 16, 4, ANY, 0)
> +IDREG_FIELD_END(MIDR, ARCHITECTURE)
> +
> +IDREG_FIELD_START(MIDR, VARIANT, 20, 4, ANY, 0)
> +IDREG_FIELD_END(MIDR, VARIANT)
> +
> +IDREG_FIELD_START(MIDR, IMPLEMENTER, 24, 8, ANY, 0)
> +IDREG_FIELD_END(MIDR, IMPLEMENTER)
> +
> +IDREG_FIELD_START(MIDR, RES0_32, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(MIDR, RES0_32)
> +
> +IDREG_END(MIDR_EL1)
> +
> +/* REVIDR_EL1 */
> +IDREG_START(REVIDR_EL1)
> +IDREG_FIELD_START(REVIDR, VAL, 0, 64, ANY, 0)
> +IDREG_FIELD_END(REVIDR, VAL)
> +
> +IDREG_END(REVIDR_EL1)
> +
> +/* AIDR_EL1 */
> +IDREG_START(AIDR_EL1)
> +IDREG_FIELD_START(AIDR, VAL, 0, 64, ANY, 0)
> +IDREG_FIELD_END(AIDR, VAL)
> +
> +IDREG_END(AIDR_EL1)
> +
> +/* DCZID_EL0 */
> +IDREG_START(DCZID_EL0)
> +IDREG_FIELD_START(DCZID_EL0, BS, 0, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(DCZID_EL0, BS)
> +
> +IDREG_FIELD_START(DCZID_EL0, DZP, 4, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(DCZID_EL0, DZP)
> +
> +IDREG_FIELD_START(DCZID_EL0, RES0_5, 5, 59, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(DCZID_EL0, RES0_5)
> +
> +IDREG_END(DCZID_EL0)
> +
> +
> +/* ID_AA64AFR0_EL1 */
> +IDREG_START(ID_AA64AFR0_EL1)
> +IDREG_FIELD_START(ID_AA64AFR0, VAL, 0, 64, EXACT, 0)
> +IDREG_FIELD_END(ID_AA64AFR0, VAL)
> +
> +IDREG_END(ID_AA64AFR0_EL1)
> +
> +/* ID_AA64AFR1_EL1 */
> +IDREG_START(ID_AA64AFR1_EL1)
> +IDREG_FIELD_START(ID_AA64AFR1, VAL, 0, 64, EXACT, 0)
> +IDREG_FIELD_END(ID_AA64AFR1, VAL)
> +
> +IDREG_END(ID_AA64AFR1_EL1)
> +
> +/* AArch32 ID registers */
> +
> +/* ID_PFR0_EL1 */
> +IDREG_START(ID_PFR0_EL1)
> +IDREG_FIELD_START(ID_PFR0, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_PFR0, VAL)
> +
> +IDREG_FIELD_START(ID_PFR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_PFR0, RES0_HI)
> +
> +IDREG_END(ID_PFR0_EL1)
> +
> +/* ID_PFR1_EL1 */
> +IDREG_START(ID_PFR1_EL1)
> +IDREG_FIELD_START(ID_PFR1, VAL_LO, 0, 28, ANY, 0)
> +IDREG_FIELD_END(ID_PFR1, VAL_LO)
> +
> +IDREG_FIELD_START(ID_PFR1, GIC, 28, 4, ANY, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "gicv3")
> +IDREG_FIELD_ARCH_VAL(0b0011, "gicv4p1")
> +IDREG_FIELD_END(ID_PFR1, GIC)
> +
> +IDREG_FIELD_START(ID_PFR1, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_PFR1, RES0_HI)
> +
> +IDREG_END(ID_PFR1_EL1)
> +
> +/* ID_DFR0_EL1 */
> +IDREG_START(ID_DFR0_EL1)
> +IDREG_FIELD_START(ID_DFR0, COPDBG, 0, 4, ANY, 0)
> +IDREG_FIELD_END(ID_DFR0, COPDBG)
> +
> +IDREG_FIELD_START(ID_DFR0, VAL_LO, 4, 20, ANY, 0)
> +IDREG_FIELD_END(ID_DFR0, VAL_LO)
> +
> +IDREG_FIELD_START(ID_DFR0, PMU, 24, 4, ANY, 0)
> +IDREG_FIELD_END(ID_DFR0, PMU)
> +
> +IDREG_FIELD_START(ID_DFR0, VAL_HI, 28, 4, ANY, 0)
> +IDREG_FIELD_END(ID_DFR0, VAL_HI)
> +
> +IDREG_FIELD_START(ID_DFR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_DFR0, RES0_HI)
> +
> +IDREG_END(ID_DFR0_EL1)
> +
> +/* ID_AFR0_EL1 */
> +IDREG_START(ID_AFR0_EL1)
> +IDREG_FIELD_START(ID_AFR0, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_AFR0, VAL)
> +
> +IDREG_FIELD_START(ID_AFR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AFR0, RES0_HI)
> +
> +IDREG_END(ID_AFR0_EL1)
> +
> +/* ID_MMFR0_EL1 */
> +IDREG_START(ID_MMFR0_EL1)
> +IDREG_FIELD_START(ID_MMFR0, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR0, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR0, RES0_HI)
> +
> +IDREG_END(ID_MMFR0_EL1)
> +
> +/* ID_MMFR1_EL1 */
> +IDREG_START(ID_MMFR1_EL1)
> +IDREG_FIELD_START(ID_MMFR1, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR1, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR1, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR1, RES0_HI)
> +
> +IDREG_END(ID_MMFR1_EL1)
> +
> +/* ID_MMFR2_EL1 */
> +IDREG_START(ID_MMFR2_EL1)
> +IDREG_FIELD_START(ID_MMFR2, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR2, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR2, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR2, RES0_HI)
> +
> +IDREG_END(ID_MMFR2_EL1)
> +
> +/* ID_MMFR3_EL1 */
> +IDREG_START(ID_MMFR3_EL1)
> +IDREG_FIELD_START(ID_MMFR3, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR3, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR3, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR3, RES0_HI)
> +
> +IDREG_END(ID_MMFR3_EL1)
> +
> +/* ID_MMFR4_EL1 */
> +IDREG_START(ID_MMFR4_EL1)
> +IDREG_FIELD_START(ID_MMFR4, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR4, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR4, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR4, RES0_HI)
> +
> +IDREG_END(ID_MMFR4_EL1)
> +
> +/* ID_MMFR5_EL1 */
> +IDREG_START(ID_MMFR5_EL1)
> +IDREG_FIELD_START(ID_MMFR5, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR5, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR5, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR5, RES0_HI)
> +
> +IDREG_END(ID_MMFR5_EL1)
> +
> +/* ID_ISAR0_EL1 */
> +IDREG_START(ID_ISAR0_EL1)
> +IDREG_FIELD_START(ID_ISAR0, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR0, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR0, RES0_HI)
> +
> +IDREG_END(ID_ISAR0_EL1)
> +
> +/* ID_ISAR1_EL1 */
> +IDREG_START(ID_ISAR1_EL1)
> +IDREG_FIELD_START(ID_ISAR1, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR1, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR1, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR1, RES0_HI)
> +
> +IDREG_END(ID_ISAR1_EL1)
> +
> +/* ID_ISAR2_EL1 */
> +IDREG_START(ID_ISAR2_EL1)
> +IDREG_FIELD_START(ID_ISAR2, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR2, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR2, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR2, RES0_HI)
> +
> +IDREG_END(ID_ISAR2_EL1)
> +
> +/* ID_ISAR3_EL1 */
> +IDREG_START(ID_ISAR3_EL1)
> +IDREG_FIELD_START(ID_ISAR3, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR3, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR3, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR3, RES0_HI)
> +
> +IDREG_END(ID_ISAR3_EL1)
> +
> +/* ID_ISAR4_EL1 */
> +IDREG_START(ID_ISAR4_EL1)
> +IDREG_FIELD_START(ID_ISAR4, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR4, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR4, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR4, RES0_HI)
> +
> +IDREG_END(ID_ISAR4_EL1)
> +
> +/* ID_ISAR5_EL1 */
> +IDREG_START(ID_ISAR5_EL1)
> +IDREG_FIELD_START(ID_ISAR5, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR5, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR5, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR5, RES0_HI)
> +
> +IDREG_END(ID_ISAR5_EL1)
> +
> +/* ID_ISAR6_EL1 */
> +IDREG_START(ID_ISAR6_EL1)
> +IDREG_FIELD_START(ID_ISAR6, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR6, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR6, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR6, RES0_HI)
> +
> +IDREG_END(ID_ISAR6_EL1)
> +
> +/* ID_PFR2_EL1 */
> +IDREG_START(ID_PFR2_EL1)
> +IDREG_FIELD_START(ID_PFR2, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_PFR2, VAL)
> +
> +IDREG_FIELD_START(ID_PFR2, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_PFR2, RES0_HI)
> +
> +IDREG_END(ID_PFR2_EL1)
> +
> +/* ID_DFR1_EL1 */
> +IDREG_START(ID_DFR1_EL1)
> +IDREG_FIELD_START(ID_DFR1, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_DFR1, VAL)
> +
> +IDREG_FIELD_START(ID_DFR1, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_DFR1, RES0_HI)
> +
> +IDREG_END(ID_DFR1_EL1)
> +
> +/* MVFR0_EL1 */
> +IDREG_START(MVFR0_EL1)
> +IDREG_FIELD_START(MVFR0, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(MVFR0, VAL)
> +
> +IDREG_FIELD_START(MVFR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(MVFR0, RES0_HI)
> +
> +IDREG_END(MVFR0_EL1)
> +
> +/* MVFR1_EL1 */
> +IDREG_START(MVFR1_EL1)
> +IDREG_FIELD_START(MVFR1, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(MVFR1, VAL)
> +
> +IDREG_FIELD_START(MVFR1, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(MVFR1, RES0_HI)
> +
> +IDREG_END(MVFR1_EL1)
> +
> +/* MVFR2_EL1 */
> +IDREG_START(MVFR2_EL1)
> +IDREG_FIELD_START(MVFR2, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(MVFR2, VAL)
> +
> +IDREG_FIELD_START(MVFR2, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(MVFR2, RES0_HI)
> +
> +IDREG_END(MVFR2_EL1)
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [RFC PATCH v2 02/29] target/arm: Add ID Register field descriptions in cpu-idregs.h.inc
2026-06-12 9:35 ` Eric Auger
@ 2026-06-12 11:01 ` Khushit Shah
0 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-12 11:01 UTC (permalink / raw)
To: eric.auger@redhat.com
Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org,
kvmarm@lists.linux.dev, Cornelia Huck, Peter Maydell,
Richard Henderson, Marc Zyngier, Oliver Upton,
Daniel P . Berrangé, Andrea Bolognani, Jiri Denemark,
Gavin Shan, Shameer Kolothum, Sebastian Ott, Markus Armbruster,
Philippe Mathieu-Daudé, Jinqian Yang, Shaju Abraham,
Mark Cave-Ayland
> On 12 Jun 2026, at 3:05 PM, Eric Auger <eric.auger@redhat.com> wrote:
>
> After reworking the python script that extract sdata from Registers.json
> I can generate
>
> IDREG_START(ID_AA64ISAR1_EL1)
> IDREG_FIELD(ID_AA64ISAR1_EL1, LS64, 60, 4)
> IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, LS64, 0)
> IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, LS64, 1)
> IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, LS64, 2)
> IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, LS64, 3)
> IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, LS64, 4)
> IDREG_FIELD(ID_AA64ISAR1_EL1, XS, 56, 4)
> IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, XS, 0)
> IDREG_FIELD_ARCH_VAL(ID_AA64ISAR1_EL1, XS, 1)
>
> ../..
Amazing! That will be helpful.
Warm Regards,
Khushit
> Thanks
>
> Eric
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
` (28 preceding siblings ...)
2026-06-05 8:33 ` [RFC PATCH v2 29/29] target/arm/kvm: fix host model writeback when kernel supports EL2 Khushit Shah
@ 2026-06-12 14:50 ` Eric Auger
2026-06-15 5:45 ` Khushit Shah
29 siblings, 1 reply; 41+ messages in thread
From: Eric Auger @ 2026-06-12 14:50 UTC (permalink / raw)
To: Khushit Shah, qemu-devel, qemu-arm, kvmarm
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland
Hi Khushit,
On 6/5/26 10:33 AM, Khushit Shah wrote:
> Hi All,
>
> This is the v2 RFC of the Named CPU models support for Arm64 in QEMU.
> v2 implements all of Planned items that were mentioned in v1.
> v1 link: https://lore.kernel.org/qemu-arm/20260513163356.3033159-1-shaju.abraham@nutanix.com/
Please could you share a branch. This fails to apply on mainline due to
recent changes
Thanks
Eric
>
> Background:
> =============================================================
> Currently QEMU only support -cpu host/max for KVM on Arm64. This disables
> live migration of VMs between hosts that differ in CPU features.
>
> This RFC proposes hierarchical named models for Arm64 under KVM, this
> provides strict contract of CPU features that will be exposed to the guest
> for a given named model. Models can be customized further with feature
> properties (like feat_AES=off, pauth=on, sve=off, etc...).
>
> The design has three layers: an ARM ID-register field table (single
> source of truth for fields, safe-rules, defaults, arch-defined values); a
> property layer on top (single-field, fractional, and composite properties);
> and a hierarchical named-model layer that picks values for those properties
> with parent-chain inheritance.
>
> The series also implements QMP commands that lets the management layer query
> which models a host can run, what each model resolves to, and which feature
> values the host supports.
>
> Relationship with "customizable host model" series:
> ============================================================
> This RFC overlaps with customizable host model series [1]. The two series
> solve different parts of the same problem: [1] provides the lower layer
> (per-field SYSREG_<REG>_<FIELD> u64 properties on -cpu host,
> writable-mask probing, ID-register writeback).
>
> This series adds the layers above that, like:
> hierarchical named CPU models, default-from-zero baselines, fractional and
> composite properties for named models (sve, pauth, expose-cache),
> property/value names, and QMP introspection (blockers via safe-rule
> validation, supported values, new query-arm-cpu-props-info). This series
> also fixes the host-supports-Nested-Virtualziation-while-qemu-booted-without-it
> writeback case [2] that surfaces once [1]'s writeback lands.
>
> Long term plan is to rebase this series on top of [1]. Few difficulties
> in that will be augmenting the ID regs fields table with safe rules and
> default values, which Eric correctly mentioned in [1] that it cannot
> be inferred from Registers.json.
>
> For property names and values we have no strong preference,
> <SYSREG>_<REG>_<FIELD> with uint64 values or "feat_*" properties with
> string values (SYSREG_ID_AA64ISAR0_AES=2/feat_AES="pmull").
>
> [1]: https://lore.kernel.org/qemu-arm/20260519132905.145643-1-eric.auger@redhat.com/
> [2]: See patch 29 of this series.
>
> TL;DR examples:
> # Boot with Grace
> qemu-system-aarch64 -cpu grace-v1 -machine virt,accel=kvm ...
>
> # Grace with a feature disabled
> qemu-system-aarch64 -cpu grace-v1,feat_SHA1=off ...
>
> # Host passthrough with individual feature control
> qemu-system-aarch64 -cpu host,feat_AES=aes ...
>
> # named CPU model with composite properties
> qemu-system-aarch64 -cpu grace-v1,pauth=off,sve=on ...
>
> # QMP -cpu host query-cpu-model-expansion:
> "model": {
> "name": "host",
> "props": {
> "cpu_partnum": 3407,
> "feat_SM4": "on",
> "feat_SM3": "on",
> ....
> }
> }
>
> # QMP -cpu graviton3-v1 query-cpu-model-expansion:
> "model": {
> "name": "graviton3-v1",
> "props": {
> "cpu_partnum": 3392,
> "feat_SM4": "on",
> "feat_SM3": "on",
> "feat_RNDR": "on",
> ....
> }
> }
>
> # QMP query-cpu-definitions (on Grace host) (blockers for graviton3-v1):
> {
> "name": "grace-v1",
> "typename": "grace-v1-arm-cpu",
> "static": false,
> "deprecated": false
> },
> {
> "name": "graviton3-v1",
> "typename": "graviton3-v1-arm-cpu",
> "unavailable-features": [
> "hw_prop_TGRAN4_2",
> "hw_prop_TGRAN64_2",
> "hw_prop_TGRAN16_2",
> "hw_prop_APA",
> "feat_RNDR"
> ],
> "static": false,
> "deprecated": false
> },
> ....
>
> # new QMP query-arm-cpu-props-info (on Grace host):
> {
> "name": "feat_SHA1",
> "type": "boolean",
> "supported-values": [
> "on",
> "off"
> ]
> },
> {
> "name": "feat_AES",
> "type": "string",
> "supported-values": [
> "off",
> "aes",
> "pmull"
> ]
> },
> ....
>
> Changes since v1:
> - Added `query-cpu-definitions` and `query-cpu-model-expansion` QMP
> support for named models and accompanying properties.
> - Introduced `query-arm-cpu-props-info` QMP command that returns
> list of all newly supported properties for -cpu host, and its supported
> values.
> - Add composite properties for named models which acts as master "on"/"off"
> switches for features that compose of broader range of ID registers
> fields like pauth and sve.
> - Added `expose-cache` composite with other cache related properties to
> allow named models to expose cache information to the guest.
> - Cache the host isar view with and without EL2 support, and make
> -cpu host with writeback work on host kernel that supports
> virtualization.
> - Validate the cpu->isar.idregs before writing back to KVM to catch early
> errors.
> - Properties and models are now defined in file rather than using .h.inc
> files.
>
> Tested on NVIDIA Grace and AWS Graviton3 hosts (6.18); booted grace-v1,
> graviton3-v1, neoverse-v2-v1, neoverse-v1-v1, and -cpu host with per-feature
> overrides.
>
> Plans for v3:
> - Some documentation and unit tests.
> - More properties based on what more the latest kernel supports.
> - pmu composite property.
> - Trying to rebase on top of [1].
> - Splitting this huge series into 3-4 sub series.
>
> Warm Regards,
> Khushit, Shaju
>
> Khushit Shah (20):
> target/arm: Introduce data-structures for the ARM property layer
> target/arm: Add all ARM64 properties to host model
> target/arm: Add Nvidia Grace named model
> target/arm/kvm: enable writable implementation ID registers
> target/aarm: Validate cpu->isar.idregs[] before writeback
> target/arm/kvm: handle DCZID_EL0 specially
> target/arm: skip GIC, COPDBG and PMU fields during KVM writeback
> target/arm: Add composite property type to model definitions
> target/arm: define pauth composite property
> target/arm: define sve composite property
> target/arm: Introduce stub files required for qmp support
> target/arm/qmp: add named models and properties to cpu-model-expansion
> target/arm/kvm: introduce kvm_arm_get_host_isar helper
> target/arm/qmp: add query-arm-cpu-props-info
> target/arm: Report "off" for ID fields gated by vCPU init flags
> target/arm/qmp: hook blockers in query-cpu-definitions
> target/arm: Support exposing cache information for named cpu models
> target/arm: Provide default cache hierarchy
> target/arm: supported-values and blockers for CCSIDR cache properties
> target/arm/kvm: fix host model writeback when kernel supports EL2
>
> Shaju Abraham (9):
> target/arm: named_cpu_model: define containers for ID registers and
> fields
> target/arm: Add ID Register field descriptions in cpu-idregs.h.inc
> target/arm: Add MIDR, REVIDR, AIDR and extra ID regs to cpu-sysregs
> target/arm: Generate ARM64 ID registers and field tables
> target/arm: Replace FIELD() macros with IDREG_FIELD expansion
> target/arm: Define ARM properties
> target/arm: Add ID register field helper functions
> target/arm: Add named cpu model infra + graviton3 named model
> target/arm/kvm: Writeback modified ID registers to KVM
>
> hw/arm/virt.c | 28 +-
> qapi/misc-arm.json | 41 +
> stubs/qmp-arm-gic.c | 6 +
> target/arm/arm-cpu-models-stub.c | 18 +
> target/arm/arm-cpu-models.c | 620 ++++++++++
> target/arm/arm-cpu-models.h | 49 +
> target/arm/arm-cpu-props-stub.c | 36 +
> target/arm/arm-cpu-props.c | 1212 +++++++++++++++++++
> target/arm/arm-cpu-props.h | 70 ++
> target/arm/arm-qmp-cmds.c | 128 +-
> target/arm/cpu-features.h | 246 +---
> target/arm/cpu-idregs.c | 508 ++++++++
> target/arm/cpu-idregs.h | 119 ++
> target/arm/cpu-idregs.h.inc | 1898 ++++++++++++++++++++++++++++++
> target/arm/cpu-sysregs.h.inc | 5 +
> target/arm/cpu.h | 3 +
> target/arm/cpu64.c | 31 +-
> target/arm/kvm-stub.c | 7 +-
> target/arm/kvm.c | 356 +++++-
> target/arm/kvm_arm.h | 7 +-
> target/arm/meson.build | 11 +-
> target/arm/trace-events | 1 +
> 22 files changed, 5148 insertions(+), 252 deletions(-)
> create mode 100644 target/arm/arm-cpu-models-stub.c
> create mode 100644 target/arm/arm-cpu-models.c
> create mode 100644 target/arm/arm-cpu-models.h
> create mode 100644 target/arm/arm-cpu-props-stub.c
> create mode 100644 target/arm/arm-cpu-props.c
> create mode 100644 target/arm/arm-cpu-props.h
> create mode 100644 target/arm/cpu-idregs.c
> create mode 100644 target/arm/cpu-idregs.h
> create mode 100644 target/arm/cpu-idregs.h.inc
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM
2026-06-12 14:50 ` [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Eric Auger
@ 2026-06-15 5:45 ` Khushit Shah
2026-06-15 16:15 ` Eric Auger
0 siblings, 1 reply; 41+ messages in thread
From: Khushit Shah @ 2026-06-15 5:45 UTC (permalink / raw)
To: eric.auger@redhat.com
Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org,
kvmarm@lists.linux.dev, Cornelia Huck, Peter Maydell,
Richard Henderson, Marc Zyngier, Oliver Upton,
Daniel P . Berrangé, Andrea Bolognani, Jiri Denemark,
Gavin Shan, Shameer Kolothum, Sebastian Ott, Markus Armbruster,
Philippe Mathieu-Daudé, Jinqian Yang, Shaju Abraham,
Mark Cave-Ayland
> On 12 Jun 2026, at 8:20 PM, Eric Auger <eric.auger@redhat.com> wrote:
>
> Please could you share a branch. This fails to apply on mainline due to
> recent changes
Here is the v2 branch:
https://github.com/khushit-shah-nx/qemu/tree/upstream-checkout-2
Please do let me know if you also want v1 branch.
Warm Regards,
Khushit
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM
2026-06-15 5:45 ` Khushit Shah
@ 2026-06-15 16:15 ` Eric Auger
0 siblings, 0 replies; 41+ messages in thread
From: Eric Auger @ 2026-06-15 16:15 UTC (permalink / raw)
To: Khushit Shah
Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org,
kvmarm@lists.linux.dev, Cornelia Huck, Peter Maydell,
Richard Henderson, Marc Zyngier, Oliver Upton,
Daniel P . Berrangé, Andrea Bolognani, Jiri Denemark,
Gavin Shan, Shameer Kolothum, Sebastian Ott, Markus Armbruster,
Philippe Mathieu-Daudé, Jinqian Yang, Shaju Abraham,
Mark Cave-Ayland
Hi Khushit,
On 6/15/26 7:45 AM, Khushit Shah wrote:
>
>> On 12 Jun 2026, at 8:20 PM, Eric Auger <eric.auger@redhat.com> wrote:
>>
>> Please could you share a branch. This fails to apply on mainline due to
>> recent changes
>
> Here is the v2 branch:
> https://github.com/khushit-shah-nx/qemu/tree/upstream-checkout-2
thank you very much.
I should be able to send my v6 on Tuesday or Wed.
Eric
>
> Please do let me know if you also want v1 branch.
>
> Warm Regards,
> Khushit
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [RFC PATCH v2 02/29] target/arm: Add ID Register field descriptions in cpu-idregs.h.inc
2026-06-05 8:33 ` [RFC PATCH v2 02/29] target/arm: Add ID Register field descriptions in cpu-idregs.h.inc Khushit Shah
2026-06-12 9:35 ` Eric Auger
@ 2026-06-17 6:32 ` Eric Auger
1 sibling, 0 replies; 41+ messages in thread
From: Eric Auger @ 2026-06-17 6:32 UTC (permalink / raw)
To: Khushit Shah, qemu-devel, qemu-arm, kvmarm
Cc: Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Daniel P . Berrangé, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland
Hi Khushit,
On 6/5/26 10:33 AM, Khushit Shah wrote:
> From: Shaju Abraham <shaju.abraham@nutanix.com>
>
> Add a declarative description of every architecturally defined field in
> the Arm64 ID registers in cpu-idregs.h.inc file. This file will be
> included multiple times with different definitions to build:
> - per-field arch values,
> - per-register field descriptor arrays,
> - arm-idregs[] table etc.
>
> The architecturally defined values for each ID register field is
> extracted from 6.18 kernel's arch/arm64/tools/sysreg file.
>
> The safe-value tags and default values are derived from the kernel's
> ftr_bits array.
>
> Aarch32 ID registers are added with dummy field so they can be
> defaulted to 0 by later commits.
>
> X-macro structure:
> IDREG_START(REG)
> IDREG_FIELD_START(REG, FIELD, SHIFT, LENGTH, SAFE_RULE, DEFAULT_VAL)
> IDREG_FIELD_ARCH_VAL(VALUE, NAME)
for fields which do not feature any ENUM values, you can simplify the
macros and do not use IDREG_FIELD_START/END but just IDREG_FIELD. This
improves the visibility. Also I think along that
line IDREG_FIELD_ARCH_VAL_ANY can be removed. I attempted to do that in
my v6.
Thanks
Eric
> ...
> IDREG_FIELD_END(REG, FIELD)
> ...
> IDREG_END(REG)
>
> Co-authored-by: Khushit Shah <khushit.shah@nutanix.com>
> Signed-off-by: Shaju Abraham <shaju.abraham@nutanix.com>
> Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
> ---
> target/arm/cpu-idregs.h.inc | 1807 +++++++++++++++++++++++++++++++++++
> 1 file changed, 1807 insertions(+)
> create mode 100644 target/arm/cpu-idregs.h.inc
>
> diff --git a/target/arm/cpu-idregs.h.inc b/target/arm/cpu-idregs.h.inc
> new file mode 100644
> index 0000000000..7e2bbf256d
> --- /dev/null
> +++ b/target/arm/cpu-idregs.h.inc
> @@ -0,0 +1,1807 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +/* ID_AA64ISAR0_EL1 */
> +IDREG_START(ID_AA64ISAR0_EL1)
> +IDREG_FIELD_START(ID_AA64ISAR0, RES0_0, 0, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ISAR0, RES0_0)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, AES, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "aes")
> +IDREG_FIELD_ARCH_VAL(0b0010, "pmull")
> +IDREG_FIELD_END(ID_AA64ISAR0, AES)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, SHA1, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, SHA1)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, SHA2, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "sha256")
> +IDREG_FIELD_ARCH_VAL(0b0010, "sha512")
> +IDREG_FIELD_END(ID_AA64ISAR0, SHA2)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, CRC32, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, CRC32)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, ATOMIC, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0010, "on")
> +IDREG_FIELD_ARCH_VAL(0b0011, "LSE128")
> +IDREG_FIELD_END(ID_AA64ISAR0, ATOMIC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, RES0_24, 24, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ISAR0, RES0_24)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, RDM, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, RDM)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, SHA3, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, SHA3)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, SM3, 36, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, SM3)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, SM4, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, SM4)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, DP, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, DP)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, FHM, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, FHM)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, TS, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "flagm")
> +IDREG_FIELD_ARCH_VAL(0b0010, "flagm2")
> +IDREG_FIELD_END(ID_AA64ISAR0, TS)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, TLB, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "os")
> +IDREG_FIELD_ARCH_VAL(0b0010, "range")
> +IDREG_FIELD_END(ID_AA64ISAR0, TLB)
> +
> +IDREG_FIELD_START(ID_AA64ISAR0, RNDR, 60, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR0, RNDR)
> +
> +IDREG_END(ID_AA64ISAR0_EL1)
> +
> +/* ID_AA64ISAR1_EL1 */
> +IDREG_START(ID_AA64ISAR1_EL1)
> +IDREG_FIELD_START(ID_AA64ISAR1, DPB, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "dpb2")
> +IDREG_FIELD_END(ID_AA64ISAR1, DPB)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, APA, 4, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "pauth")
> +IDREG_FIELD_ARCH_VAL(0b0010, "epac")
> +IDREG_FIELD_ARCH_VAL(0b0011, "pauth2")
> +IDREG_FIELD_ARCH_VAL(0b0100, "fpac")
> +IDREG_FIELD_ARCH_VAL(0b0101, "fpaccombine")
> +IDREG_FIELD_ARCH_VAL(0b0110, "pauth_lr")
> +IDREG_FIELD_END(ID_AA64ISAR1, APA)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, API, 8, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "pauth")
> +IDREG_FIELD_ARCH_VAL(0b0010, "epac")
> +IDREG_FIELD_ARCH_VAL(0b0011, "pauth2")
> +IDREG_FIELD_ARCH_VAL(0b0100, "fpac")
> +IDREG_FIELD_ARCH_VAL(0b0101, "fpaccombine")
> +IDREG_FIELD_ARCH_VAL(0b0110, "pauth_lr")
> +IDREG_FIELD_END(ID_AA64ISAR1, API)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, JSCVT, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, JSCVT)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, FCMA, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, FCMA)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, LRCPC, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "lrcpc2")
> +IDREG_FIELD_ARCH_VAL(0b0011, "lrcpc3")
> +IDREG_FIELD_END(ID_AA64ISAR1, LRCPC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, GPA, 24, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, GPA)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, GPI, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, GPI)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, FRINTTS, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, FRINTTS)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, SB, 36, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, SB)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, SPECRES, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "cosp_rctx")
> +IDREG_FIELD_END(ID_AA64ISAR1, SPECRES)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, BF16, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ebf16")
> +IDREG_FIELD_END(ID_AA64ISAR1, BF16)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, DGH, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, DGH)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, I8MM, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, I8MM)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, XS, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR1, XS)
> +
> +IDREG_FIELD_START(ID_AA64ISAR1, LS64, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "ls64")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ls64_v")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ls64_accdata")
> +IDREG_FIELD_ARCH_VAL(0b0100, "ls64wb")
> +IDREG_FIELD_END(ID_AA64ISAR1, LS64)
> +
> +IDREG_END(ID_AA64ISAR1_EL1)
> +
> +/* ID_AA64ISAR2_EL1 */
> +IDREG_START(ID_AA64ISAR2_EL1)
> +IDREG_FIELD_START(ID_AA64ISAR2, WFXT, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0010, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, WFXT)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, RPRES, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, RPRES)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, GPA3, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, GPA3)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, APA3, 12, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "pauth")
> +IDREG_FIELD_ARCH_VAL(0b0010, "epac")
> +IDREG_FIELD_ARCH_VAL(0b0011, "pauth2")
> +IDREG_FIELD_ARCH_VAL(0b0100, "fpac")
> +IDREG_FIELD_ARCH_VAL(0b0101, "fpaccombine")
> +IDREG_FIELD_ARCH_VAL(0b0110, "pauth_lr")
> +IDREG_FIELD_END(ID_AA64ISAR2, APA3)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, MOPS, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, MOPS)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, BC, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, BC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, PAC_FRAC, 24, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, PAC_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, CLRBHB, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, CLRBHB)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, SYSREG_128, 32, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, SYSREG_128)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, SYSINSTR_128, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, SYSINSTR_128)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, PRFMSLC, 40, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, PRFMSLC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, PCDPHINT, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, PCDPHINT)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, RPRFM, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, RPRFM)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, CSSC, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "cmpbr")
> +IDREG_FIELD_END(ID_AA64ISAR2, CSSC)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, LUT, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, LUT)
> +
> +IDREG_FIELD_START(ID_AA64ISAR2, ATS1A, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR2, ATS1A)
> +
> +IDREG_END(ID_AA64ISAR2_EL1)
> +
> +/* ID_AA64PFR0_EL1 */
> +IDREG_START(ID_AA64PFR0_EL1)
> +IDREG_FIELD_START(ID_AA64PFR0, EL0, 0, 4, LOWER, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
> +IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
> +IDREG_FIELD_END(ID_AA64PFR0, EL0)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, EL1, 4, 4, LOWER, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
> +IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
> +IDREG_FIELD_END(ID_AA64PFR0, EL1)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, EL2, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
> +IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
> +IDREG_FIELD_END(ID_AA64PFR0, EL2)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, EL3, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "aarch64")
> +IDREG_FIELD_ARCH_VAL(0b0010, "aarch32")
> +IDREG_FIELD_END(ID_AA64PFR0, EL3)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, FP, 16, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b0001, "fp16")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64PFR0, FP)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, ADVSIMD, 20, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b0001, "fp16")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64PFR0, ADVSIMD)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, GIC, 24, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0011, "v4p1")
> +IDREG_FIELD_END(ID_AA64PFR0, GIC)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, RAS, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "v1p1")
> +IDREG_FIELD_ARCH_VAL(0b0011, "v2")
> +IDREG_FIELD_END(ID_AA64PFR0, RAS)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, SVE, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR0, SVE)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, SEL2, 36, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR0, SEL2)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, MPAM, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "0")
> +IDREG_FIELD_ARCH_VAL(0b0001, "1")
> +IDREG_FIELD_END(ID_AA64PFR0, MPAM)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, AMU, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "v1p1")
> +IDREG_FIELD_END(ID_AA64PFR0, AMU)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, DIT, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR0, DIT)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, RME, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR0, RME)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, CSV2, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "csv2_2")
> +IDREG_FIELD_ARCH_VAL(0b0011, "csv2_3")
> +IDREG_FIELD_END(ID_AA64PFR0, CSV2)
> +
> +IDREG_FIELD_START(ID_AA64PFR0, CSV3, 60, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR0, CSV3)
> +
> +IDREG_END(ID_AA64PFR0_EL1)
> +
> +/* ID_AA64PFR1_EL1 */
> +IDREG_START(ID_AA64PFR1_EL1)
> +IDREG_FIELD_START(ID_AA64PFR1, BT, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, BT)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, SSBS, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ssbs2")
> +IDREG_FIELD_END(ID_AA64PFR1, SSBS)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, MTE, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "mte2")
> +IDREG_FIELD_ARCH_VAL(0b0011, "mte3")
> +IDREG_FIELD_END(ID_AA64PFR1, MTE)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, RAS_FRAC, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "rasv1p1")
> +IDREG_FIELD_END(ID_AA64PFR1, RAS_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, MPAM_FRAC, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "minor_0")
> +IDREG_FIELD_ARCH_VAL(0b0001, "minor_1")
> +IDREG_FIELD_END(ID_AA64PFR1, MPAM_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, RES0_20, 20, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64PFR1, RES0_20)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, SME, 24, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "sme2")
> +IDREG_FIELD_END(ID_AA64PFR1, SME)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, RNDR_TRAP, 28, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, RNDR_TRAP)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, CSV2_FRAC, 32, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "csv2_1p1")
> +IDREG_FIELD_ARCH_VAL(0b0010, "csv2_1p2")
> +IDREG_FIELD_END(ID_AA64PFR1, CSV2_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, NMI, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, NMI)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, MTE_FRAC, 40, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "async")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64PFR1, MTE_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, GCS, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, GCS)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, THE, 48, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, THE)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, MTEX, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "mte")
> +IDREG_FIELD_ARCH_VAL(0b0001, "mte4")
> +IDREG_FIELD_END(ID_AA64PFR1, MTEX)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, DF2, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, DF2)
> +
> +IDREG_FIELD_START(ID_AA64PFR1, PFAR, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR1, PFAR)
> +
> +IDREG_END(ID_AA64PFR1_EL1)
> +
> +/* ID_AA64MMFR0_EL1 */
> +IDREG_START(ID_AA64MMFR0_EL1)
> +IDREG_FIELD_START(ID_AA64MMFR0, PARANGE, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "32")
> +IDREG_FIELD_ARCH_VAL(0b0001, "36")
> +IDREG_FIELD_ARCH_VAL(0b0010, "40")
> +IDREG_FIELD_ARCH_VAL(0b0011, "42")
> +IDREG_FIELD_ARCH_VAL(0b0100, "44")
> +IDREG_FIELD_ARCH_VAL(0b0101, "48")
> +IDREG_FIELD_ARCH_VAL(0b0110, "52")
> +IDREG_FIELD_ARCH_VAL(0b0111, "56")
> +IDREG_FIELD_END(ID_AA64MMFR0, PARANGE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, ASIDBITS, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "8")
> +IDREG_FIELD_ARCH_VAL(0b0010, "16")
> +IDREG_FIELD_END(ID_AA64MMFR0, ASIDBITS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, BIGEND, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR0, BIGEND)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, SNSMEM, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR0, SNSMEM)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, BIGENDEL0, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR0, BIGENDEL0)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN16, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "52_bit")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN16)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN64, 24, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN64)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN4, 28, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b0001, "52_bit")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN4)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN16_2, 32, 4, EXACT, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0000, "tgran16")
> +IDREG_FIELD_ARCH_VAL(0b0001, "off")
> +IDREG_FIELD_ARCH_VAL(0b0010, "on")
> +IDREG_FIELD_ARCH_VAL(0b0011, "52_bit")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN16_2)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN64_2, 36, 4, EXACT, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0000, "tgran64")
> +IDREG_FIELD_ARCH_VAL(0b0001, "off")
> +IDREG_FIELD_ARCH_VAL(0b0010, "on")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN64_2)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, TGRAN4_2, 40, 4, EXACT, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0000, "tgran4")
> +IDREG_FIELD_ARCH_VAL(0b0001, "off")
> +IDREG_FIELD_ARCH_VAL(0b0010, "on")
> +IDREG_FIELD_ARCH_VAL(0b0011, "52_bit")
> +IDREG_FIELD_END(ID_AA64MMFR0, TGRAN4_2)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, EXS, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR0, EXS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, RES0_48, 48, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR0, RES0_48)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, FGT, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "fgt2")
> +IDREG_FIELD_END(ID_AA64MMFR0, FGT)
> +
> +IDREG_FIELD_START(ID_AA64MMFR0, ECV, 60, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "cntpoff")
> +IDREG_FIELD_END(ID_AA64MMFR0, ECV)
> +
> +IDREG_END(ID_AA64MMFR0_EL1)
> +
> +/* ID_AA64MMFR1_EL1 */
> +IDREG_START(ID_AA64MMFR1_EL1)
> +IDREG_FIELD_START(ID_AA64MMFR1, HAFDBS, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "af")
> +IDREG_FIELD_ARCH_VAL(0b0010, "dbm")
> +IDREG_FIELD_ARCH_VAL(0b0011, "haft")
> +IDREG_FIELD_ARCH_VAL(0b0100, "hdbss")
> +IDREG_FIELD_END(ID_AA64MMFR1, HAFDBS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, VMIDBITS, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "8")
> +IDREG_FIELD_ARCH_VAL(0b0010, "16")
> +IDREG_FIELD_END(ID_AA64MMFR1, VMIDBITS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, VH, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, VH)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, HPDS, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "hpds2")
> +IDREG_FIELD_END(ID_AA64MMFR1, HPDS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, LO, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, LO)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, PAN, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "pan2")
> +IDREG_FIELD_ARCH_VAL(0b0011, "pan3")
> +IDREG_FIELD_END(ID_AA64MMFR1, PAN)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, SPECSEI, 24, 4, HIGHER, 0b0001)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, SPECSEI)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, XNX, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, XNX)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, TWED, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, TWED)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, ETS, 36, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ets2")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ets3")
> +IDREG_FIELD_END(ID_AA64MMFR1, ETS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, HCX, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, HCX)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, AFP, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, AFP)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, NTLBPA, 48, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, NTLBPA)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, TIDCP1, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, TIDCP1)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, CMOW, 56, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, CMOW)
> +
> +IDREG_FIELD_START(ID_AA64MMFR1, ECBHB, 60, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR1, ECBHB)
> +
> +IDREG_END(ID_AA64MMFR1_EL1)
> +
> +/* ID_AA64MMFR2_EL1 */
> +IDREG_START(ID_AA64MMFR2_EL1)
> +IDREG_FIELD_START(ID_AA64MMFR2, CNP, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, CNP)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, UAO, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, UAO)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, LSM, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, LSM)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, IESB, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, IESB)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, VARANGE, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "48")
> +IDREG_FIELD_ARCH_VAL(0b0001, "52")
> +IDREG_FIELD_END(ID_AA64MMFR2, VARANGE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, CCIDX, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "32")
> +IDREG_FIELD_ARCH_VAL(0b0001, "64")
> +IDREG_FIELD_END(ID_AA64MMFR2, CCIDX)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, NV, 24, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "nv2")
> +IDREG_FIELD_END(ID_AA64MMFR2, NV)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, ST, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "39")
> +IDREG_FIELD_ARCH_VAL(0b0001, "48_47")
> +IDREG_FIELD_END(ID_AA64MMFR2, ST)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, AT, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, AT)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, IDS, 36, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "0x0")
> +IDREG_FIELD_ARCH_VAL(0b0001, "0x18")
> +IDREG_FIELD_END(ID_AA64MMFR2, IDS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, FWB, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, FWB)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, RES0_44, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR2, RES0_44)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, TTL, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, TTL)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, BBM, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "0")
> +IDREG_FIELD_ARCH_VAL(0b0001, "1")
> +IDREG_FIELD_ARCH_VAL(0b0010, "2")
> +IDREG_FIELD_END(ID_AA64MMFR2, BBM)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, EVT, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ttlbxs")
> +IDREG_FIELD_END(ID_AA64MMFR2, EVT)
> +
> +IDREG_FIELD_START(ID_AA64MMFR2, E0PD, 60, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR2, E0PD)
> +
> +IDREG_END(ID_AA64MMFR2_EL1)
> +
> +/* ID_AA64MMFR3_EL1 */
> +IDREG_START(ID_AA64MMFR3_EL1)
> +IDREG_FIELD_START(ID_AA64MMFR3, TCRX, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, TCRX)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, SCTLRX, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, SCTLRX)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, S1PIE, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, S1PIE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, S2PIE, 12, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, S2PIE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, S1POE, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, S1POE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, S2POE, 20, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, S2POE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, AIE, 24, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, AIE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, MEC, 28, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, MEC)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, D128, 32, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, D128)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, D128_2, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, D128_2)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, SNERR, 40, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "sync")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ANERR")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ANERR_IND")
> +IDREG_FIELD_END(ID_AA64MMFR3, SNERR)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, ANERR, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "async")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ANERR")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ANERR_IND")
> +IDREG_FIELD_END(ID_AA64MMFR3, ANERR)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, RES0_48, 48, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR3, RES0_48)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, SDERR, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "dev_sync")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ADERR")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ADERR_IND")
> +IDREG_FIELD_END(ID_AA64MMFR3, SDERR)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, ADERR, 56, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "dev_async")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ADERR")
> +IDREG_FIELD_ARCH_VAL(0b0011, "ADERR_IND")
> +IDREG_FIELD_END(ID_AA64MMFR3, ADERR)
> +
> +IDREG_FIELD_START(ID_AA64MMFR3, SPEC_FPACC, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR3, SPEC_FPACC)
> +
> +IDREG_END(ID_AA64MMFR3_EL1)
> +
> +/* ID_AA64DFR0_EL1 */
> +IDREG_START(ID_AA64DFR0_EL1)
> +IDREG_FIELD_START(ID_AA64DFR0, DEBUGVER, 0, 4, LOWER, 0x6)
> +IDREG_FIELD_ARCH_VAL(0b0110, "on")
> +IDREG_FIELD_ARCH_VAL(0b0111, "vhe")
> +IDREG_FIELD_ARCH_VAL(0b1000, "v8p2")
> +IDREG_FIELD_ARCH_VAL(0b1001, "v8p4")
> +IDREG_FIELD_ARCH_VAL(0b1010, "v8p8")
> +IDREG_FIELD_ARCH_VAL(0b1011, "v8p9")
> +IDREG_FIELD_END(ID_AA64DFR0, DEBUGVER)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, TRACEVER, 4, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR0, TRACEVER)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, PMUVER, 8, 4, SIGNED_LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0100, "v3p1")
> +IDREG_FIELD_ARCH_VAL(0b0101, "v3p4")
> +IDREG_FIELD_ARCH_VAL(0b0110, "v3p5")
> +IDREG_FIELD_ARCH_VAL(0b0111, "v3p7")
> +IDREG_FIELD_ARCH_VAL(0b1000, "v3p8")
> +IDREG_FIELD_ARCH_VAL(0b1001, "v3p9")
> +IDREG_FIELD_ARCH_VAL(0b1111, "imp_def")
> +IDREG_FIELD_END(ID_AA64DFR0, PMUVER)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, BRPS, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR0, BRPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, PMSS, 16, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR0, PMSS)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, WRPS, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR0, WRPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, SEBEP, 24, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR0, SEBEP)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, CTX_CMPS, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR0, CTX_CMPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, PMSVER, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "v1p1")
> +IDREG_FIELD_ARCH_VAL(0b0011, "v1p2")
> +IDREG_FIELD_ARCH_VAL(0b0100, "v1p3")
> +IDREG_FIELD_ARCH_VAL(0b0101, "v1p4")
> +IDREG_FIELD_ARCH_VAL(0b0110, "v1p5")
> +IDREG_FIELD_END(ID_AA64DFR0, PMSVER)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, DOUBLELOCK, 36, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64DFR0, DOUBLELOCK)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, TRACEFILT, 40, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR0, TRACEFILT)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, TRACEBUFFER, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "trbe_v1p1")
> +IDREG_FIELD_END(ID_AA64DFR0, TRACEBUFFER)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, MTPMU, 48, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "ni_impdef")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64DFR0, MTPMU)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, BRBE, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "brbe_v1p1")
> +IDREG_FIELD_END(ID_AA64DFR0, BRBE)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, EXTTRCBUFF, 56, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR0, EXTTRCBUFF)
> +
> +IDREG_FIELD_START(ID_AA64DFR0, HPMN0, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "unpredictable")
> +IDREG_FIELD_ARCH_VAL(0b0001, "def")
> +IDREG_FIELD_END(ID_AA64DFR0, HPMN0)
> +
> +IDREG_END(ID_AA64DFR0_EL1)
> +
> +/* ID_AA64ZFR0_EL1 */
> +IDREG_START(ID_AA64ZFR0_EL1)
> +IDREG_FIELD_START(ID_AA64ZFR0, SVEVER, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b0001, "sve2")
> +IDREG_FIELD_ARCH_VAL(0b0010, "sve2p1")
> +IDREG_FIELD_ARCH_VAL(0b0011, "sve2p2")
> +IDREG_FIELD_END(ID_AA64ZFR0, SVEVER)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, AES, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "pmull128")
> +IDREG_FIELD_ARCH_VAL(0b0011, "aes2")
> +IDREG_FIELD_END(ID_AA64ZFR0, AES)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, RES0_8, 8, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ZFR0, RES0_8)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, ELTPERM, 12, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, ELTPERM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, BITPERM, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, BITPERM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, BFLOAT16, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "ebf16")
> +IDREG_FIELD_END(ID_AA64ZFR0, BFLOAT16)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, B16B16, 24, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "bfscale")
> +IDREG_FIELD_END(ID_AA64ZFR0, B16B16)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, RES0_28, 28, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ZFR0, RES0_28)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, SHA3, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, SHA3)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, RES0_36, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ZFR0, RES0_36)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, SM4, 40, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, SM4)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, I8MM, 44, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, I8MM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, F16MM, 48, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, F16MM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, F32MM, 52, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, F32MM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, F64MM, 56, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ZFR0, F64MM)
> +
> +IDREG_FIELD_START(ID_AA64ZFR0, RES0_60, 60, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ZFR0, RES0_60)
> +
> +IDREG_END(ID_AA64ZFR0_EL1)
> +
> +/* ID_AA64SMFR0_EL1 */
> +IDREG_START(ID_AA64SMFR0_EL1)
> +IDREG_FIELD_START(ID_AA64SMFR0, SMOP4, 0, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SMOP4)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_1, 1, 15, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_1)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, STMOP, 16, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, STMOP)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_17, 17, 6, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_17)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SFEXPA, 23, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SFEXPA)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, AES, 24, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, AES)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SBITPERM, 25, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SBITPERM)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_26, 26, 2, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_26)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SF8DP2, 28, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SF8DP2)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SF8DP4, 29, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SF8DP4)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SF8FMA, 30, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, SF8FMA)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_31, 31, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_31)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F32F32, 32, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F32F32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, BI32I32, 33, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, BI32I32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, B16F32, 34, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, B16F32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F16F32, 35, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F16F32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, I8I32, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b1111, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, I8I32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F8F32, 40, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F8F32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F8F16, 41, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F8F16)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F16F16, 42, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F16F16)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, B16B16, 43, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, B16B16)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, I16I32, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0101, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, I16I32)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, F64F64, 48, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, F64F64)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_49, 49, 3, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_49)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, I16I64, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b1111, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, I16I64)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, SMEVER, 56, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "sme")
> +IDREG_FIELD_ARCH_VAL(0b0001, "sme2")
> +IDREG_FIELD_ARCH_VAL(0b0010, "sme2p1")
> +IDREG_FIELD_ARCH_VAL(0b0011, "sme2p2")
> +IDREG_FIELD_END(ID_AA64SMFR0, SMEVER)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, LUTV2, 60, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, LUTV2)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, RES0_61, 61, 2, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64SMFR0, RES0_61)
> +
> +IDREG_FIELD_START(ID_AA64SMFR0, FA64, 63, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64SMFR0, FA64)
> +
> +IDREG_END(ID_AA64SMFR0_EL1)
> +
> +/* CTR_EL0 */
> +IDREG_START(CTR_EL0)
> +IDREG_FIELD_START(CTR_EL0, IMINLINE, 0, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, IMINLINE)
> +
> +IDREG_FIELD_START(CTR_EL0, RES0_4, 4, 10, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(CTR_EL0, RES0_4)
> +
> +IDREG_FIELD_START(CTR_EL0, L1IP, 14, 2, EXACT, 0b10)
> +IDREG_FIELD_ARCH_VAL(0b00, "reserved_vpipt")
> +IDREG_FIELD_ARCH_VAL(0b01, "reserved_aivivt")
> +IDREG_FIELD_ARCH_VAL(0b10, "vipt")
> +IDREG_FIELD_ARCH_VAL(0b11, "pipt")
> +IDREG_FIELD_END(CTR_EL0, L1IP)
> +
> +IDREG_FIELD_START(CTR_EL0, DMINLINE, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, DMINLINE)
> +
> +IDREG_FIELD_START(CTR_EL0, ERG, 20, 4, HIGHER_OR_ZERO, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, ERG)
> +
> +IDREG_FIELD_START(CTR_EL0, CWG, 24, 4, HIGHER_OR_ZERO, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, CWG)
> +
> +IDREG_FIELD_START(CTR_EL0, IDC, 28, 1, LOWER, 0b1)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, IDC)
> +
> +IDREG_FIELD_START(CTR_EL0, DIC, 29, 1, LOWER, 0b1)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, DIC)
> +
> +IDREG_FIELD_START(CTR_EL0, RES0_30, 30, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(CTR_EL0, RES0_30)
> +
> +IDREG_FIELD_START(CTR_EL0, RES1_31, 31, 1, EXACT, 1)
> +IDREG_FIELD_ARCH_VAL(1, NULL)
> +IDREG_FIELD_END(CTR_EL0, RES1_31)
> +
> +IDREG_FIELD_START(CTR_EL0, TMINLINE, 32, 6, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(CTR_EL0, TMINLINE)
> +
> +IDREG_FIELD_START(CTR_EL0, RES0_38, 38, 26, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(CTR_EL0, RES0_38)
> +
> +IDREG_END(CTR_EL0)
> +
> +/* ID_AA64ISAR3_EL1 */
> +IDREG_START(ID_AA64ISAR3_EL1)
> +IDREG_FIELD_START(ID_AA64ISAR3, CPA, 0, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "cpa2")
> +IDREG_FIELD_END(ID_AA64ISAR3, CPA)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, FAMINMAX, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, FAMINMAX)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, TLBIW, 8, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, TLBIW)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, PACM, 12, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "trivial_imp")
> +IDREG_FIELD_ARCH_VAL(0b0010, "full_imp")
> +IDREG_FIELD_END(ID_AA64ISAR3, PACM)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, LSFE, 16, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, LSFE)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, OCCMO, 20, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, OCCMO)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, LSUI, 24, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, LSUI)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, FPRCVT, 28, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64ISAR3, FPRCVT)
> +
> +IDREG_FIELD_START(ID_AA64ISAR3, RES0_32, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64ISAR3, RES0_32)
> +
> +IDREG_END(ID_AA64ISAR3_EL1)
> +
> +/* ID_AA64PFR2_EL1 */
> +IDREG_START(ID_AA64PFR2_EL1)
> +IDREG_FIELD_START(ID_AA64PFR2, MTEPERM, 0, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, MTEPERM)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, MTESTOREONLY, 4, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, MTESTOREONLY)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, MTEFAR, 8, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, MTEFAR)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, GCIE, 12, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, GCIE)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, UINJ, 16, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, UINJ)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, RES0_20, 20, 12, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64PFR2, RES0_20)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, FPMR, 32, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64PFR2, FPMR)
> +
> +IDREG_FIELD_START(ID_AA64PFR2, RES0_36, 36, 28, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64PFR2, RES0_36)
> +
> +IDREG_END(ID_AA64PFR2_EL1)
> +
> +/* ID_AA64FPFR0_EL1 */
> +IDREG_START(ID_AA64FPFR0_EL1)
> +IDREG_FIELD_START(ID_AA64FPFR0, F8E5M2, 0, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8E5M2)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8E4M3, 1, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8E4M3)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, RES0_2, 2, 24, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64FPFR0, RES0_2)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8MM4, 26, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8MM4)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8MM8, 27, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8MM8)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8DP2, 28, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8DP2)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8DP4, 29, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8DP4)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8FMA, 30, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8FMA)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, F8CVT, 31, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0, "off")
> +IDREG_FIELD_ARCH_VAL(0b1, "on")
> +IDREG_FIELD_END(ID_AA64FPFR0, F8CVT)
> +
> +IDREG_FIELD_START(ID_AA64FPFR0, RES0_32, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64FPFR0, RES0_32)
> +
> +IDREG_END(ID_AA64FPFR0_EL1)
> +
> +
> +/* ID_AA64MMFR4_EL1 */
> +IDREG_START(ID_AA64MMFR4_EL1)
> +IDREG_FIELD_START(ID_AA64MMFR4, POPS, 0, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, POPS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, EIESB, 4, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "toel3")
> +IDREG_FIELD_ARCH_VAL(0b0010, "toelx")
> +IDREG_FIELD_ARCH_VAL(0b1111, "any")
> +IDREG_FIELD_END(ID_AA64MMFR4, EIESB)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, ASID2, 8, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, ASID2)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, HACDBS, 12, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, HACDBS)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, FGWTE3, 16, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, FGWTE3)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, NV_FRAC, 20, 4, LOWER, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "nv_nv2")
> +IDREG_FIELD_ARCH_VAL(0b0001, "nv2_only")
> +IDREG_FIELD_ARCH_VAL(0b0010, "nv2p1")
> +IDREG_FIELD_END(ID_AA64MMFR4, NV_FRAC)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, E2H0, 24, 4, SIGNED_LOWER, 0b1111)
> +IDREG_FIELD_ARCH_VAL(0b0000, "on")
> +IDREG_FIELD_ARCH_VAL(0b1110, "ni_nv1")
> +IDREG_FIELD_ARCH_VAL(0b1111, "off")
> +IDREG_FIELD_END(ID_AA64MMFR4, E2H0)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, RMEGDI, 28, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, RMEGDI)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, RES0_32, 32, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR4, RES0_32)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, E3DSE, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, E3DSE)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, RES0_40, 40, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR4, RES0_40)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, SRMASK, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64MMFR4, SRMASK)
> +
> +IDREG_FIELD_START(ID_AA64MMFR4, RES0_48, 48, 16, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AA64MMFR4, RES0_48)
> +
> +IDREG_END(ID_AA64MMFR4_EL1)
> +
> +/* ID_AA64DFR1_EL1 */
> +IDREG_START(ID_AA64DFR1_EL1)
> +IDREG_FIELD_START(ID_AA64DFR1, SYSPMUID, 0, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR1, SYSPMUID)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, BRPS, 8, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR1, BRPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, WRPS, 16, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR1, WRPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, CTX_CMPS, 24, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR1, CTX_CMPS)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, SPMU, 32, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_ARCH_VAL(0b0010, "imp_spmzr")
> +IDREG_FIELD_END(ID_AA64DFR1, SPMU)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, PMICNTR, 36, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR1, PMICNTR)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, ABLE, 40, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR1, ABLE)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, ITE, 44, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR1, ITE)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, EBEP, 48, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "on")
> +IDREG_FIELD_END(ID_AA64DFR1, EBEP)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, DPFZS, 52, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "ignr")
> +IDREG_FIELD_ARCH_VAL(0b0001, "frzn")
> +IDREG_FIELD_END(ID_AA64DFR1, DPFZS)
> +
> +IDREG_FIELD_START(ID_AA64DFR1, ABL_CMPS, 56, 8, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(ID_AA64DFR1, ABL_CMPS)
> +
> +IDREG_END(ID_AA64DFR1_EL1)
> +
> +/* MIDR_EL1 */
> +IDREG_START(MIDR_EL1)
> +IDREG_FIELD_START(MIDR, REVISION, 0, 4, ANY, 0)
> +IDREG_FIELD_END(MIDR, REVISION)
> +
> +IDREG_FIELD_START(MIDR, PARTNUM, 4, 12, ANY, 0)
> +IDREG_FIELD_END(MIDR, PARTNUM)
> +
> +IDREG_FIELD_START(MIDR, ARCHITECTURE, 16, 4, ANY, 0)
> +IDREG_FIELD_END(MIDR, ARCHITECTURE)
> +
> +IDREG_FIELD_START(MIDR, VARIANT, 20, 4, ANY, 0)
> +IDREG_FIELD_END(MIDR, VARIANT)
> +
> +IDREG_FIELD_START(MIDR, IMPLEMENTER, 24, 8, ANY, 0)
> +IDREG_FIELD_END(MIDR, IMPLEMENTER)
> +
> +IDREG_FIELD_START(MIDR, RES0_32, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(MIDR, RES0_32)
> +
> +IDREG_END(MIDR_EL1)
> +
> +/* REVIDR_EL1 */
> +IDREG_START(REVIDR_EL1)
> +IDREG_FIELD_START(REVIDR, VAL, 0, 64, ANY, 0)
> +IDREG_FIELD_END(REVIDR, VAL)
> +
> +IDREG_END(REVIDR_EL1)
> +
> +/* AIDR_EL1 */
> +IDREG_START(AIDR_EL1)
> +IDREG_FIELD_START(AIDR, VAL, 0, 64, ANY, 0)
> +IDREG_FIELD_END(AIDR, VAL)
> +
> +IDREG_END(AIDR_EL1)
> +
> +/* DCZID_EL0 */
> +IDREG_START(DCZID_EL0)
> +IDREG_FIELD_START(DCZID_EL0, BS, 0, 4, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(DCZID_EL0, BS)
> +
> +IDREG_FIELD_START(DCZID_EL0, DZP, 4, 1, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL_ANY
> +IDREG_FIELD_END(DCZID_EL0, DZP)
> +
> +IDREG_FIELD_START(DCZID_EL0, RES0_5, 5, 59, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(DCZID_EL0, RES0_5)
> +
> +IDREG_END(DCZID_EL0)
> +
> +
> +/* ID_AA64AFR0_EL1 */
> +IDREG_START(ID_AA64AFR0_EL1)
> +IDREG_FIELD_START(ID_AA64AFR0, VAL, 0, 64, EXACT, 0)
> +IDREG_FIELD_END(ID_AA64AFR0, VAL)
> +
> +IDREG_END(ID_AA64AFR0_EL1)
> +
> +/* ID_AA64AFR1_EL1 */
> +IDREG_START(ID_AA64AFR1_EL1)
> +IDREG_FIELD_START(ID_AA64AFR1, VAL, 0, 64, EXACT, 0)
> +IDREG_FIELD_END(ID_AA64AFR1, VAL)
> +
> +IDREG_END(ID_AA64AFR1_EL1)
> +
> +/* AArch32 ID registers */
> +
> +/* ID_PFR0_EL1 */
> +IDREG_START(ID_PFR0_EL1)
> +IDREG_FIELD_START(ID_PFR0, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_PFR0, VAL)
> +
> +IDREG_FIELD_START(ID_PFR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_PFR0, RES0_HI)
> +
> +IDREG_END(ID_PFR0_EL1)
> +
> +/* ID_PFR1_EL1 */
> +IDREG_START(ID_PFR1_EL1)
> +IDREG_FIELD_START(ID_PFR1, VAL_LO, 0, 28, ANY, 0)
> +IDREG_FIELD_END(ID_PFR1, VAL_LO)
> +
> +IDREG_FIELD_START(ID_PFR1, GIC, 28, 4, ANY, 0)
> +IDREG_FIELD_ARCH_VAL(0b0000, "off")
> +IDREG_FIELD_ARCH_VAL(0b0001, "gicv3")
> +IDREG_FIELD_ARCH_VAL(0b0011, "gicv4p1")
> +IDREG_FIELD_END(ID_PFR1, GIC)
> +
> +IDREG_FIELD_START(ID_PFR1, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_PFR1, RES0_HI)
> +
> +IDREG_END(ID_PFR1_EL1)
> +
> +/* ID_DFR0_EL1 */
> +IDREG_START(ID_DFR0_EL1)
> +IDREG_FIELD_START(ID_DFR0, COPDBG, 0, 4, ANY, 0)
> +IDREG_FIELD_END(ID_DFR0, COPDBG)
> +
> +IDREG_FIELD_START(ID_DFR0, VAL_LO, 4, 20, ANY, 0)
> +IDREG_FIELD_END(ID_DFR0, VAL_LO)
> +
> +IDREG_FIELD_START(ID_DFR0, PMU, 24, 4, ANY, 0)
> +IDREG_FIELD_END(ID_DFR0, PMU)
> +
> +IDREG_FIELD_START(ID_DFR0, VAL_HI, 28, 4, ANY, 0)
> +IDREG_FIELD_END(ID_DFR0, VAL_HI)
> +
> +IDREG_FIELD_START(ID_DFR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_DFR0, RES0_HI)
> +
> +IDREG_END(ID_DFR0_EL1)
> +
> +/* ID_AFR0_EL1 */
> +IDREG_START(ID_AFR0_EL1)
> +IDREG_FIELD_START(ID_AFR0, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_AFR0, VAL)
> +
> +IDREG_FIELD_START(ID_AFR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_AFR0, RES0_HI)
> +
> +IDREG_END(ID_AFR0_EL1)
> +
> +/* ID_MMFR0_EL1 */
> +IDREG_START(ID_MMFR0_EL1)
> +IDREG_FIELD_START(ID_MMFR0, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR0, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR0, RES0_HI)
> +
> +IDREG_END(ID_MMFR0_EL1)
> +
> +/* ID_MMFR1_EL1 */
> +IDREG_START(ID_MMFR1_EL1)
> +IDREG_FIELD_START(ID_MMFR1, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR1, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR1, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR1, RES0_HI)
> +
> +IDREG_END(ID_MMFR1_EL1)
> +
> +/* ID_MMFR2_EL1 */
> +IDREG_START(ID_MMFR2_EL1)
> +IDREG_FIELD_START(ID_MMFR2, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR2, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR2, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR2, RES0_HI)
> +
> +IDREG_END(ID_MMFR2_EL1)
> +
> +/* ID_MMFR3_EL1 */
> +IDREG_START(ID_MMFR3_EL1)
> +IDREG_FIELD_START(ID_MMFR3, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR3, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR3, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR3, RES0_HI)
> +
> +IDREG_END(ID_MMFR3_EL1)
> +
> +/* ID_MMFR4_EL1 */
> +IDREG_START(ID_MMFR4_EL1)
> +IDREG_FIELD_START(ID_MMFR4, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR4, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR4, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR4, RES0_HI)
> +
> +IDREG_END(ID_MMFR4_EL1)
> +
> +/* ID_MMFR5_EL1 */
> +IDREG_START(ID_MMFR5_EL1)
> +IDREG_FIELD_START(ID_MMFR5, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_MMFR5, VAL)
> +
> +IDREG_FIELD_START(ID_MMFR5, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_MMFR5, RES0_HI)
> +
> +IDREG_END(ID_MMFR5_EL1)
> +
> +/* ID_ISAR0_EL1 */
> +IDREG_START(ID_ISAR0_EL1)
> +IDREG_FIELD_START(ID_ISAR0, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR0, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR0, RES0_HI)
> +
> +IDREG_END(ID_ISAR0_EL1)
> +
> +/* ID_ISAR1_EL1 */
> +IDREG_START(ID_ISAR1_EL1)
> +IDREG_FIELD_START(ID_ISAR1, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR1, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR1, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR1, RES0_HI)
> +
> +IDREG_END(ID_ISAR1_EL1)
> +
> +/* ID_ISAR2_EL1 */
> +IDREG_START(ID_ISAR2_EL1)
> +IDREG_FIELD_START(ID_ISAR2, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR2, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR2, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR2, RES0_HI)
> +
> +IDREG_END(ID_ISAR2_EL1)
> +
> +/* ID_ISAR3_EL1 */
> +IDREG_START(ID_ISAR3_EL1)
> +IDREG_FIELD_START(ID_ISAR3, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR3, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR3, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR3, RES0_HI)
> +
> +IDREG_END(ID_ISAR3_EL1)
> +
> +/* ID_ISAR4_EL1 */
> +IDREG_START(ID_ISAR4_EL1)
> +IDREG_FIELD_START(ID_ISAR4, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR4, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR4, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR4, RES0_HI)
> +
> +IDREG_END(ID_ISAR4_EL1)
> +
> +/* ID_ISAR5_EL1 */
> +IDREG_START(ID_ISAR5_EL1)
> +IDREG_FIELD_START(ID_ISAR5, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR5, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR5, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR5, RES0_HI)
> +
> +IDREG_END(ID_ISAR5_EL1)
> +
> +/* ID_ISAR6_EL1 */
> +IDREG_START(ID_ISAR6_EL1)
> +IDREG_FIELD_START(ID_ISAR6, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_ISAR6, VAL)
> +
> +IDREG_FIELD_START(ID_ISAR6, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_ISAR6, RES0_HI)
> +
> +IDREG_END(ID_ISAR6_EL1)
> +
> +/* ID_PFR2_EL1 */
> +IDREG_START(ID_PFR2_EL1)
> +IDREG_FIELD_START(ID_PFR2, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_PFR2, VAL)
> +
> +IDREG_FIELD_START(ID_PFR2, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_PFR2, RES0_HI)
> +
> +IDREG_END(ID_PFR2_EL1)
> +
> +/* ID_DFR1_EL1 */
> +IDREG_START(ID_DFR1_EL1)
> +IDREG_FIELD_START(ID_DFR1, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(ID_DFR1, VAL)
> +
> +IDREG_FIELD_START(ID_DFR1, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(ID_DFR1, RES0_HI)
> +
> +IDREG_END(ID_DFR1_EL1)
> +
> +/* MVFR0_EL1 */
> +IDREG_START(MVFR0_EL1)
> +IDREG_FIELD_START(MVFR0, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(MVFR0, VAL)
> +
> +IDREG_FIELD_START(MVFR0, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(MVFR0, RES0_HI)
> +
> +IDREG_END(MVFR0_EL1)
> +
> +/* MVFR1_EL1 */
> +IDREG_START(MVFR1_EL1)
> +IDREG_FIELD_START(MVFR1, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(MVFR1, VAL)
> +
> +IDREG_FIELD_START(MVFR1, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(MVFR1, RES0_HI)
> +
> +IDREG_END(MVFR1_EL1)
> +
> +/* MVFR2_EL1 */
> +IDREG_START(MVFR2_EL1)
> +IDREG_FIELD_START(MVFR2, VAL, 0, 32, ANY, 0)
> +IDREG_FIELD_END(MVFR2, VAL)
> +
> +IDREG_FIELD_START(MVFR2, RES0_HI, 32, 32, EXACT, 0)
> +IDREG_FIELD_ARCH_VAL(0, NULL)
> +IDREG_FIELD_END(MVFR2, RES0_HI)
> +
> +IDREG_END(MVFR2_EL1)
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [RFC PATCH v2 23/29] target/arm/qmp: add query-arm-cpu-props-info
2026-06-05 8:33 ` [RFC PATCH v2 23/29] target/arm/qmp: add query-arm-cpu-props-info Khushit Shah
@ 2026-06-19 9:25 ` Markus Armbruster
2026-06-19 11:54 ` Khushit Shah
2026-06-19 9:51 ` Daniel P. Berrangé
1 sibling, 1 reply; 41+ messages in thread
From: Markus Armbruster @ 2026-06-19 9:25 UTC (permalink / raw)
To: Khushit Shah
Cc: qemu-devel, qemu-arm, kvmarm, Eric Auger, Cornelia Huck,
Peter Maydell, Richard Henderson, Marc Zyngier, Oliver Upton,
Daniel P . Berrangé, Andrea Bolognani, Jiri Denemark,
Gavin Shan, Shameer Kolothum, Sebastian Ott,
Philippe Mathieu-Daudé, Jinqian Yang, Shaju Abraham,
Mark Cave-Ayland
Khushit Shah <khushit.shah@nutanix.com> writes:
> Introduce 'query-arm-cpu-props-info' QMP command. This command returns
> information about ARM CPU model properties, including their name, type,
> supported values on the given host, and composite parent if any.
>
> This provides management layer necessary information to determine
> migration compatibility off a VM on different host.
>
> Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
> ---
> qapi/misc-arm.json | 41 ++++++++++++++++
> stubs/qmp-arm-gic.c | 6 +++
> target/arm/arm-cpu-props-stub.c | 13 +++++
> target/arm/arm-cpu-props.c | 85 +++++++++++++++++++++++++++++++++
> target/arm/arm-cpu-props.h | 5 ++
> target/arm/arm-qmp-cmds.c | 44 +++++++++++++++++
> target/arm/cpu-idregs.c | 71 +++++++++++++++++++++++++++
> target/arm/cpu-idregs.h | 8 ++++
> 8 files changed, 273 insertions(+)
>
> diff --git a/qapi/misc-arm.json b/qapi/misc-arm.json
> index 4dc66d00e5..1a3fb140c4 100644
> --- a/qapi/misc-arm.json
> +++ b/qapi/misc-arm.json
> @@ -46,6 +46,47 @@
> ##
> { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] }
>
> +##
> +# @CpuPropInfo:
CpuPropertyInfo for consistency with type names such as ObjectPropertyInfo.
> +#
> +# Information about a specific ARM CPU model property.
> +#
> +# @name: the name of the property
> +#
> +# @type: the type of the property, any of ('string', 'boolean',
> +# 'number').
> +#
> +# @supported-values: the set of values the host hardware supports
> +# for the property, a list of strings.
I figure the set of values depends on the host, i.e. it isn't known at
compile time. Correct?
Are the possible property names known at compile time?
List of strings is fine when the values are strings. When they're not,
the interface requires its users to parse strings, which is something we
try hard to avoid in QAPI/QMP.
> +#
> +# @composite: name of the encapsulating composite property if any.
> +#
> +# Since: 11.1
> +##
> +{ 'struct': 'CpuPropInfo',
> + 'data': { 'name': 'str',
> + 'type': 'str',
> + 'supported-values': 'any',
Description above claims "list of strings". If that's accurate, it
should be ['str'] here. Else, the description needs fixing.
> + '*composite': 'str' } }
> +
> +##
> +# @query-arm-cpu-props-info:
> +#
> +# Returns information about most of ARM CPU named model properties.
Imperative mood, please: Return information ...
> +# This does not include composite properties or properties already
> +# defined by QEMU like (sveNNNN, pmu, etc), This only returns all
> +# the newly defined properties like ('feat_*', 'hw_prop_*', etc).
"newly defined" compared to what?
> +#
> +# With this upper management layers can find out what property values
Comma after this, I think.
> +# are supported on the given host.
> +#
> +# Requires KVM to be enabled.
What happens when it isn't?
> +#
> +# Since: 11.1
> +##
> +{ 'command': 'query-arm-cpu-props-info',
> + 'returns': ['CpuPropInfo'] }
> +
> ##
> # @SsidSizeMode:
> #
[...]
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [RFC PATCH v2 23/29] target/arm/qmp: add query-arm-cpu-props-info
2026-06-05 8:33 ` [RFC PATCH v2 23/29] target/arm/qmp: add query-arm-cpu-props-info Khushit Shah
2026-06-19 9:25 ` Markus Armbruster
@ 2026-06-19 9:51 ` Daniel P. Berrangé
2026-06-19 11:06 ` Andrea Bolognani
2026-06-19 12:04 ` Khushit Shah
1 sibling, 2 replies; 41+ messages in thread
From: Daniel P. Berrangé @ 2026-06-19 9:51 UTC (permalink / raw)
To: Khushit Shah
Cc: qemu-devel, qemu-arm, kvmarm, Eric Auger, Cornelia Huck,
Peter Maydell, Richard Henderson, Marc Zyngier, Oliver Upton,
Andrea Bolognani, Jiri Denemark, Gavin Shan, Shameer Kolothum,
Sebastian Ott, Markus Armbruster, Philippe Mathieu-Daudé,
Jinqian Yang, Shaju Abraham, Mark Cave-Ayland
On Fri, Jun 05, 2026 at 08:33:52AM +0000, Khushit Shah wrote:
> Introduce 'query-arm-cpu-props-info' QMP command. This command returns
> information about ARM CPU model properties, including their name, type,
> supported values on the given host, and composite parent if any.
Do we have to make this ARM only ?
x86 has named CPU properties too. They are all basically
booleans so this API offers a superset of functionality
needed for x86, and thus I'd expect x86 to be folded into
this new API too.
> This provides management layer necessary information to determine
> migration compatibility off a VM on different host.
>
> Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
> ---
> qapi/misc-arm.json | 41 ++++++++++++++++
> stubs/qmp-arm-gic.c | 6 +++
> target/arm/arm-cpu-props-stub.c | 13 +++++
> target/arm/arm-cpu-props.c | 85 +++++++++++++++++++++++++++++++++
> target/arm/arm-cpu-props.h | 5 ++
> target/arm/arm-qmp-cmds.c | 44 +++++++++++++++++
> target/arm/cpu-idregs.c | 71 +++++++++++++++++++++++++++
> target/arm/cpu-idregs.h | 8 ++++
> 8 files changed, 273 insertions(+)
>
> diff --git a/qapi/misc-arm.json b/qapi/misc-arm.json
> index 4dc66d00e5..1a3fb140c4 100644
> --- a/qapi/misc-arm.json
> +++ b/qapi/misc-arm.json
> @@ -46,6 +46,47 @@
> ##
> { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] }
>
> +##
> +# @CpuPropInfo:
> +#
> +# Information about a specific ARM CPU model property.
> +#
> +# @name: the name of the property
> +#
> +# @type: the type of the property, any of ('string', 'boolean',
> +# 'number').
> +#
> +# @supported-values: the set of values the host hardware supports
> +# for the property, a list of strings.
> +#
> +# @composite: name of the encapsulating composite property if any.
> +#
> +# Since: 11.1
> +##
> +{ 'struct': 'CpuPropInfo',
> + 'data': { 'name': 'str',
> + 'type': 'str',
This should be an enumerated type, not a string.
> + 'supported-values': 'any',
If these values vary based on @type, then this should
be a discriminated union.
> + '*composite': 'str' } }
> +
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [RFC PATCH v2 23/29] target/arm/qmp: add query-arm-cpu-props-info
2026-06-19 9:51 ` Daniel P. Berrangé
@ 2026-06-19 11:06 ` Andrea Bolognani
2026-06-19 12:04 ` Khushit Shah
1 sibling, 0 replies; 41+ messages in thread
From: Andrea Bolognani @ 2026-06-19 11:06 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: Khushit Shah, qemu-devel, qemu-arm, kvmarm, Eric Auger,
Cornelia Huck, Peter Maydell, Richard Henderson, Marc Zyngier,
Oliver Upton, Jiri Denemark, Gavin Shan, Shameer Kolothum,
Sebastian Ott, Markus Armbruster, Philippe Mathieu-Daudé,
Jinqian Yang, Shaju Abraham, Mark Cave-Ayland
On Fri, Jun 19, 2026 at 10:51:04AM +0100, Daniel P. Berrangé wrote:
> On Fri, Jun 05, 2026 at 08:33:52AM +0000, Khushit Shah wrote:
> > Introduce 'query-arm-cpu-props-info' QMP command. This command returns
> > information about ARM CPU model properties, including their name, type,
> > supported values on the given host, and composite parent if any.
>
> Do we have to make this ARM only ?
>
> x86 has named CPU properties too. They are all basically
> booleans so this API offers a superset of functionality
> needed for x86, and thus I'd expect x86 to be folded into
> this new API too.
riscv64 will certainly need something like this too in due time.
So +1 to making it architecture-agnostic.
--
Andrea Bolognani / Red Hat / Virtualization
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [RFC PATCH v2 23/29] target/arm/qmp: add query-arm-cpu-props-info
2026-06-19 9:25 ` Markus Armbruster
@ 2026-06-19 11:54 ` Khushit Shah
0 siblings, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-19 11:54 UTC (permalink / raw)
To: Markus Armbruster
Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org,
kvmarm@lists.linux.dev, Eric Auger, Cornelia Huck, Peter Maydell,
Richard Henderson, Marc Zyngier, Oliver Upton,
Daniel P . Berrangé, Andrea Bolognani, Jiri Denemark,
Gavin Shan, Shameer Kolothum, Sebastian Ott,
Philippe Mathieu-Daudé, Jinqian Yang, Shaju Abraham,
Mark Cave-Ayland, Sandesh Patel
> On 19 Jun 2026, at 2:55 PM, Markus Armbruster <armbru@redhat.com> wrote:
>
> !-------------------------------------------------------------------|
> CAUTION: External Email
>
> |-------------------------------------------------------------------!
>
> Khushit Shah <khushit.shah@nutanix.com> writes:
>
>> Introduce 'query-arm-cpu-props-info' QMP command. This command returns
>> information about ARM CPU model properties, including their name, type,
>> supported values on the given host, and composite parent if any.
>>
>> This provides management layer necessary information to determine
>> migration compatibility off a VM on different host.
Note: s/off/of.
>>
>> Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
>> ---
>> qapi/misc-arm.json | 41 ++++++++++++++++
>> stubs/qmp-arm-gic.c | 6 +++
>> target/arm/arm-cpu-props-stub.c | 13 +++++
>> target/arm/arm-cpu-props.c | 85 +++++++++++++++++++++++++++++++++
>> target/arm/arm-cpu-props.h | 5 ++
>> target/arm/arm-qmp-cmds.c | 44 +++++++++++++++++
>> target/arm/cpu-idregs.c | 71 +++++++++++++++++++++++++++
>> target/arm/cpu-idregs.h | 8 ++++
>> 8 files changed, 273 insertions(+)
>>
>> diff --git a/qapi/misc-arm.json b/qapi/misc-arm.json
>> index 4dc66d00e5..1a3fb140c4 100644
>> --- a/qapi/misc-arm.json
>> +++ b/qapi/misc-arm.json
>> @@ -46,6 +46,47 @@
>> ##
>> { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] }
>>
>> +##
>> +# @CpuPropInfo:
>
> CpuPropertyInfo for consistency with type names such as ObjectPropertyInfo.
Acked.
>> +#
>> +# Information about a specific ARM CPU model property.
>> +#
>> +# @name: the name of the property
>> +#
>> +# @type: the type of the property, any of ('string', 'boolean',
>> +# 'number').
>> +#
>> +# @supported-values: the set of values the host hardware supports
>> +# for the property, a list of strings.
>
> I figure the set of values depends on the host, i.e. it isn't known at
> compile time. Correct?
>
Yes, correct.
> Are the possible property names known at compile time?
Yes, property names are known at compile time.
> List of strings is fine when the values are strings. When they're not,
> the interface requires its users to parse strings, which is something we
> try hard to avoid in QAPI/QMP.
Okay, then I think we can do this with flat union discriminated with
“type” (changing it to enum) :
boolean: [‘bool’]
string: [’str’]
number: ['NumRange’] where NumRange: {‘min’: uint64, ‘max’: uint64}
Range form to handle numeric properties with no restrictions.
Does this look reasonable to you?
>> +#
>> +# @composite: name of the encapsulating composite property if any.
>> +#
>> +# Since: 11.1
>> +##
>> +{ 'struct': 'CpuPropInfo',
>> + 'data': { 'name': 'str',
>> + 'type': 'str',
>> + 'supported-values': 'any',
>
> Description above claims "list of strings". If that's accurate, it
> should be ['str'] here. Else, the description needs fixing.
>
Acked, will fix as mentioned above.
>> + '*composite': 'str' } }
>> +
>> +##
>> +# @query-arm-cpu-props-info:
>> +#
>> +# Returns information about most of ARM CPU named model properties.
>
> Imperative mood, please: Return information ...
Acked, will fix this.
>
>> +# This does not include composite properties or properties already
>> +# defined by QEMU like (sveNNNN, pmu, etc), This only returns all
>> +# the newly defined properties like ('feat_*', 'hw_prop_*', etc).
>
> "newly defined" compared to what?
Okay, I see the issue. Will reword this.
>
>> +#
>> +# With this upper management layers can find out what property values
>
> Comma after this, I think.
Acked.
>
>> +# are supported on the given host.
>> +#
>> +# Requires KVM to be enabled.
>
> What happens when it isn't?
Right now it throws an error. We cannot calculate supported-values
until we read host values using KVM. Will explicitly mention this
in the doc.
Warm Regards,
Khushit
>
>> +#
>> +# Since: 11.1
>> +##
>> +{ 'command': 'query-arm-cpu-props-info',
>> + 'returns': ['CpuPropInfo'] }
>> +
>> ##
>> # @SsidSizeMode:
>> #
>
> [...]
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [RFC PATCH v2 23/29] target/arm/qmp: add query-arm-cpu-props-info
2026-06-19 9:51 ` Daniel P. Berrangé
2026-06-19 11:06 ` Andrea Bolognani
@ 2026-06-19 12:04 ` Khushit Shah
1 sibling, 0 replies; 41+ messages in thread
From: Khushit Shah @ 2026-06-19 12:04 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org,
kvmarm@lists.linux.dev, Eric Auger, Cornelia Huck, Peter Maydell,
Richard Henderson, Marc Zyngier, Oliver Upton, Andrea Bolognani,
Jiri Denemark, Gavin Shan, Shameer Kolothum, Sebastian Ott,
Markus Armbruster, Philippe Mathieu-Daudé, Jinqian Yang,
Shaju Abraham, Mark Cave-Ayland
> On 19 Jun 2026, at 3:21 PM, Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> !-------------------------------------------------------------------|
> CAUTION: External Email
>
> |-------------------------------------------------------------------!
>
> On Fri, Jun 05, 2026 at 08:33:52AM +0000, Khushit Shah wrote:
>> Introduce 'query-arm-cpu-props-info' QMP command. This command returns
>> information about ARM CPU model properties, including their name, type,
>> supported values on the given host, and composite parent if any.
>
> Do we have to make this ARM only ?
Nope. Nothing in schema specific to ARM, maybe other archs
does have a concept of composites.
> x86 has named CPU properties too. They are all basically
> booleans so this API offers a superset of functionality
> needed for x86, and thus I'd expect x86 to be folded into
> this new API too.
Certainly, Will rename it to query-cpu-props-info and move
the declaration to machine.json.
>> This provides management layer necessary information to determine
>> migration compatibility off a VM on different host.
>>
>> Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
>> ---
>> qapi/misc-arm.json | 41 ++++++++++++++++
>> stubs/qmp-arm-gic.c | 6 +++
>> target/arm/arm-cpu-props-stub.c | 13 +++++
>> target/arm/arm-cpu-props.c | 85 +++++++++++++++++++++++++++++++++
>> target/arm/arm-cpu-props.h | 5 ++
>> target/arm/arm-qmp-cmds.c | 44 +++++++++++++++++
>> target/arm/cpu-idregs.c | 71 +++++++++++++++++++++++++++
>> target/arm/cpu-idregs.h | 8 ++++
>> 8 files changed, 273 insertions(+)
>>
>> diff --git a/qapi/misc-arm.json b/qapi/misc-arm.json
>> index 4dc66d00e5..1a3fb140c4 100644
>> --- a/qapi/misc-arm.json
>> +++ b/qapi/misc-arm.json
>> @@ -46,6 +46,47 @@
>> ##
>> { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] }
>>
>> +##
>> +# @CpuPropInfo:
>> +#
>> +# Information about a specific ARM CPU model property.
>> +#
>> +# @name: the name of the property
>> +#
>> +# @type: the type of the property, any of ('string', 'boolean',
>> +# 'number').
>> +#
>> +# @supported-values: the set of values the host hardware supports
>> +# for the property, a list of strings.
>> +#
>> +# @composite: name of the encapsulating composite property if any.
>> +#
>> +# Since: 11.1
>> +##
>> +{ 'struct': 'CpuPropInfo',
>> + 'data': { 'name': 'str',
>> + 'type': 'str',
>
> This should be an enumerated type, not a string.
>
>> + 'supported-values': 'any',
>
> If these values vary based on @type, then this should
> be a discriminated union.
>
>> + '*composite': 'str' } }
>> +
>
Ack to all!
Warm Regards,
Khushit
> With regards,
> Daniel
> --
> |: https://urldefense.proofpoint.com/v2/url?u=https-3A__berrange.com&d=DwIBaQ&c=s883GpUCOChKOHiocYtGcg&r=PGWMyignA0NiDmTlyP7vOTHozBws_VN86yrVmSMkBp0&m=FXhC3p0qW8N3cIYBZFdG9pF8QfQzl21CQecJzd3LmNz1KrPCn2pckuUE4BEf9mAL&s=OLpF_UYVkL1bH71PWInEs9jqCkoSFHUvkAda6zleyvw&e= ~~ https://urldefense.proofpoint.com/v2/url?u=https-3A__hachyderm.io_-40berrange&d=DwIBaQ&c=s883GpUCOChKOHiocYtGcg&r=PGWMyignA0NiDmTlyP7vOTHozBws_VN86yrVmSMkBp0&m=FXhC3p0qW8N3cIYBZFdG9pF8QfQzl21CQecJzd3LmNz1KrPCn2pckuUE4BEf9mAL&s=0ktOw-l2jkXZzRBSc5_ZEHqt8R3osEs_JAqa_IqvlQw&e= :|
> |: https://urldefense.proofpoint.com/v2/url?u=https-3A__libvirt.org&d=DwIBaQ&c=s883GpUCOChKOHiocYtGcg&r=PGWMyignA0NiDmTlyP7vOTHozBws_VN86yrVmSMkBp0&m=FXhC3p0qW8N3cIYBZFdG9pF8QfQzl21CQecJzd3LmNz1KrPCn2pckuUE4BEf9mAL&s=WJ4ntSda_NIAI-hZQ9e3g5NwkVlJ2zwmQSbAAmL9RGE&e= ~~ https://urldefense.proofpoint.com/v2/url?u=https-3A__entangle-2Dphoto.org&d=DwIBaQ&c=s883GpUCOChKOHiocYtGcg&r=PGWMyignA0NiDmTlyP7vOTHozBws_VN86yrVmSMkBp0&m=FXhC3p0qW8N3cIYBZFdG9pF8QfQzl21CQecJzd3LmNz1KrPCn2pckuUE4BEf9mAL&s=ZC_GjXOo8WNgqhFo9Sm6VnjegEjzClMrnYMQLb2dEmM&e= :|
> |: https://urldefense.proofpoint.com/v2/url?u=https-3A__pixelfed.art_berrange&d=DwIBaQ&c=s883GpUCOChKOHiocYtGcg&r=PGWMyignA0NiDmTlyP7vOTHozBws_VN86yrVmSMkBp0&m=FXhC3p0qW8N3cIYBZFdG9pF8QfQzl21CQecJzd3LmNz1KrPCn2pckuUE4BEf9mAL&s=UIbdFieTADHsmAtLYuyPuFQQHXy1pQR6fj2-YE7pgUY&e= ~~ https://urldefense.proofpoint.com/v2/url?u=https-3A__fstop138.berrange.com&d=DwIBaQ&c=s883GpUCOChKOHiocYtGcg&r=PGWMyignA0NiDmTlyP7vOTHozBws_VN86yrVmSMkBp0&m=FXhC3p0qW8N3cIYBZFdG9pF8QfQzl21CQecJzd3LmNz1KrPCn2pckuUE4BEf9mAL&s=hPqy2OF9hYRvQil8blS1xHkELTl-8xvgquNPYaopa4o&e= :|
^ permalink raw reply [flat|nested] 41+ messages in thread
end of thread, other threads:[~2026-06-19 12:04 UTC | newest]
Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-05 8:33 [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 01/29] target/arm: named_cpu_model: define containers for ID registers and fields Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 02/29] target/arm: Add ID Register field descriptions in cpu-idregs.h.inc Khushit Shah
2026-06-12 9:35 ` Eric Auger
2026-06-12 11:01 ` Khushit Shah
2026-06-17 6:32 ` Eric Auger
2026-06-05 8:33 ` [RFC PATCH v2 03/29] target/arm: Add MIDR, REVIDR, AIDR and extra ID regs to cpu-sysregs Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 04/29] target/arm: Generate ARM64 ID registers and field tables Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 05/29] target/arm: Replace FIELD() macros with IDREG_FIELD expansion Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 06/29] target/arm: Introduce data-structures for the ARM property layer Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 07/29] target/arm: Define ARM properties Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 08/29] target/arm: Add ID register field helper functions Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 09/29] target/arm: Add all ARM64 properties to host model Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 10/29] target/arm: Add named cpu model infra + graviton3 named model Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 11/29] target/arm: Add Nvidia Grace " Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 12/29] target/arm/kvm: Writeback modified ID registers to KVM Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 13/29] target/arm/kvm: enable writable implementation ID registers Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 14/29] target/arm: Validate cpu->isar.idregs[] before writeback Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 15/29] target/arm/kvm: handle DCZID_EL0 specially Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 16/29] target/arm: skip GIC, COPDBG and PMU fields during KVM writeback Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 17/29] target/arm: Add composite property type to model definitions Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 18/29] target/arm: define pauth composite property Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 19/29] target/arm: define sve " Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 20/29] target/arm: Introduce stub files required for qmp support Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 21/29] target/arm/qmp: add named models and properties to cpu-model-expansion Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 22/29] target/arm/kvm: introduce kvm_arm_get_host_isar helper Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 23/29] target/arm/qmp: add query-arm-cpu-props-info Khushit Shah
2026-06-19 9:25 ` Markus Armbruster
2026-06-19 11:54 ` Khushit Shah
2026-06-19 9:51 ` Daniel P. Berrangé
2026-06-19 11:06 ` Andrea Bolognani
2026-06-19 12:04 ` Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 24/29] target/arm: Report "off" for ID fields gated by vCPU init flags Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 25/29] target/arm/qmp: hook blockers in query-cpu-definitions Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 26/29] target/arm: Support exposing cache information for named cpu models Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 27/29] target/arm: Provide default cache hierarchy Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 28/29] target/arm: supported-values and blockers for CCSIDR cache properties Khushit Shah
2026-06-05 8:33 ` [RFC PATCH v2 29/29] target/arm/kvm: fix host model writeback when kernel supports EL2 Khushit Shah
2026-06-12 14:50 ` [RFC PATCH v2 00/29] target/arm: Named CPU models for Arm64 on KVM Eric Auger
2026-06-15 5:45 ` Khushit Shah
2026-06-15 16:15 ` Eric Auger
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.