diff --git a/Fix-the-compilation-of-target-arm-softmmu.patch b/Fix-the-compilation-of-target-arm-softmmu.patch new file mode 100644 index 0000000000000000000000000000000000000000..070233c6c9b6542169146821e78755c7a9cbadcc --- /dev/null +++ b/Fix-the-compilation-of-target-arm-softmmu.patch @@ -0,0 +1,28 @@ +From 54926203be817a82c7062cc5b277d488e6836758 Mon Sep 17 00:00:00 2001 +From: Jian Cai +Date: Thu, 30 Oct 2025 15:49:31 +0800 +Subject: [PATCH] Fix the compilation of target arm-softmmu + +Fix the compilation of target arm-softmmu. + +Signed-off-by: Jian Cai +--- + target/arm/kvm_arm.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index 8c69957fbf..13509b7836 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -534,7 +534,7 @@ static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap) + return -ENOSYS; + } + +-void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu) ++static inline void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu) + { + g_assert_not_reached(); + } +-- +2.33.0 + diff --git a/Revert-hw-arm-virt-Introduce-a-IPIV-machine-option.patch b/Revert-hw-arm-virt-Introduce-a-IPIV-machine-option.patch new file mode 100644 index 0000000000000000000000000000000000000000..beb14a583e651630d773abda90ac68399dd0c928 --- /dev/null +++ b/Revert-hw-arm-virt-Introduce-a-IPIV-machine-option.patch @@ -0,0 +1,108 @@ +From cf868536745ed2db3c0e148e34039a829dbbf4b7 Mon Sep 17 00:00:00 2001 +From: Jinqian Yang +Date: Mon, 20 Oct 2025 16:06:49 +0800 +Subject: [PATCH] Revert "hw/arm/virt: Introduce a IPIV machine option" + +This reverts commit 9db5487d84eef5ba38adefb70138644d1012f05f. +This patch will cause virsh to fail to start because libvirt first +starts a QEMU process with `-machine none` for initialization, and +then starts one with `-machine virt`. When using `-machine none`, +the VIRT_MACHINE conversion will result in an error. + +Signed-off-by: Jinqian Yang +--- + hw/arm/virt.c | 19 ------------------- + include/hw/arm/virt.h | 1 - + target/arm/kvm.c | 10 ++-------- + 3 files changed, 2 insertions(+), 28 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index db1b9715e0..f7a9ba9a58 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -3044,20 +3044,6 @@ static void virt_set_its(Object *obj, bool value, Error **errp) + vms->its = value; + } + +-static bool virt_get_ipiv(Object *obj, Error **errp) +-{ +- VirtMachineState *vms = VIRT_MACHINE(obj); +- +- return vms->ipiv; +-} +- +-static void virt_set_ipiv(Object *obj, bool value, Error **errp) +-{ +- VirtMachineState *vms = VIRT_MACHINE(obj); +- +- vms->ipiv = value; +-} +- + static void virt_get_dtb_randomness(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) + { +@@ -4100,11 +4086,6 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + "in ACPI table header." + "The string may be up to 8 bytes in size"); + +- object_class_property_add_bool(oc, "ipiv", +- virt_get_ipiv, +- virt_set_ipiv); +- object_class_property_set_description(oc, "ipiv", +- "Set on/off to enable/disable IPIV"); + } + + static char *virt_get_kvm_type(Object *obj, Error **errp G_GNUC_UNUSED) +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index a54b0057fb..fee7c27e0c 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -225,7 +225,6 @@ struct VirtMachineState { + bool cpu_hotplug_enabled; + bool ras; + bool mte; +- bool ipiv; + OnOffAuto dtb_randomness; + bool pmu; + int smmu_accel_count; +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 7d443a967d..f45783a9da 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -34,7 +34,6 @@ + #include "hw/irq.h" + #include "qapi/visitor.h" + #include "qemu/log.h" +-#include "hw/arm/virt.h" + + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO +@@ -260,15 +259,10 @@ int kvm_arch_get_default_type(MachineState *ms) + return fixed_ipa ? 0 : size; + } + +-static void kvm_update_ipiv_cap(MachineState *ms, KVMState *s) ++static void kvm_update_ipiv_cap(KVMState *s) + { +- VirtMachineState *vms = VIRT_MACHINE(ms); + int ret; + +- if (!vms->ipiv) { +- return; +- } +- + if (!kvm_check_extension(s, KVM_CAP_ARM_HISI_IPIV)) { + return; + } +@@ -355,7 +349,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + } + + kvm_arm_init_debug(s); +- kvm_update_ipiv_cap(ms, s); ++ kvm_update_ipiv_cap(s); + + ret = kvm_arm_rme_init(ms); + if (ret) { +-- +2.33.0 + diff --git a/arm-cpu-Add-generated-sysreg-properties.patch b/arm-cpu-Add-generated-sysreg-properties.patch new file mode 100644 index 0000000000000000000000000000000000000000..7b849f742c51d9f85dcf514e92f1d536a1ce4666 --- /dev/null +++ b/arm-cpu-Add-generated-sysreg-properties.patch @@ -0,0 +1,783 @@ +From 3581592ca359fbeca14d1ee29b1335d97d346d29 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 17/26] arm/cpu: Add generated sysreg properties + +Generated against Linux 6.14-rc4. + +Signed-off-by: Cornelia Huck +--- + target/arm/cpu-sysreg-properties.c | 748 ++++++++++++++++++++++++++++- + 1 file changed, 726 insertions(+), 22 deletions(-) + +diff --git a/target/arm/cpu-sysreg-properties.c b/target/arm/cpu-sysreg-properties.c +index 8b7ef5badf..94cc496438 100644 +--- a/target/arm/cpu-sysreg-properties.c ++++ b/target/arm/cpu-sysreg-properties.c +@@ -1,24 +1,3 @@ +-/* +- * QEMU ARM CPU SYSREG PROPERTIES +- * to be generated from linux sysreg +- * +- * Copyright (c) Red Hat, Inc. 2024 +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, see +- * +- */ +- + #include "cpu-custom.h" + + ARM64SysReg arm64_id_regs[NUM_ID_IDX]; +@@ -26,6 +5,657 @@ ARM64SysReg arm64_id_regs[NUM_ID_IDX]; + void initialize_cpu_sysreg_properties(void) + { + memset(arm64_id_regs, 0, sizeof(ARM64SysReg) * NUM_ID_IDX); ++ ++/* For SPMACCESSR_EL12 fields see SPMACCESSR_EL1 */ ++ ++ /* ID_PFR0_EL1 */ ++ ARM64SysReg *ID_PFR0_EL1 = arm64_sysreg_get(ID_PFR0_EL1_IDX); ++ ID_PFR0_EL1->name = "ID_PFR0_EL1"; ++ arm64_sysreg_add_field(ID_PFR0_EL1, "RAS", 28, 31); ++ arm64_sysreg_add_field(ID_PFR0_EL1, "DIT", 24, 27); ++ arm64_sysreg_add_field(ID_PFR0_EL1, "AMU", 20, 23); ++ arm64_sysreg_add_field(ID_PFR0_EL1, "CSV2", 16, 19); ++ arm64_sysreg_add_field(ID_PFR0_EL1, "State3", 12, 15); ++ arm64_sysreg_add_field(ID_PFR0_EL1, "State2", 8, 11); ++ arm64_sysreg_add_field(ID_PFR0_EL1, "State1", 4, 7); ++ arm64_sysreg_add_field(ID_PFR0_EL1, "State0", 0, 3); ++ ++ /* ID_PFR1_EL1 */ ++ ARM64SysReg *ID_PFR1_EL1 = arm64_sysreg_get(ID_PFR1_EL1_IDX); ++ ID_PFR1_EL1->name = "ID_PFR1_EL1"; ++ arm64_sysreg_add_field(ID_PFR1_EL1, "GIC", 28, 31); ++ arm64_sysreg_add_field(ID_PFR1_EL1, "Virt_frac", 24, 27); ++ arm64_sysreg_add_field(ID_PFR1_EL1, "Sec_frac", 20, 23); ++ arm64_sysreg_add_field(ID_PFR1_EL1, "GenTimer", 16, 19); ++ arm64_sysreg_add_field(ID_PFR1_EL1, "Virtualization", 12, 15); ++ arm64_sysreg_add_field(ID_PFR1_EL1, "MProgMod", 8, 11); ++ arm64_sysreg_add_field(ID_PFR1_EL1, "Security", 4, 7); ++ arm64_sysreg_add_field(ID_PFR1_EL1, "ProgMod", 0, 3); ++ ++ /* ID_DFR0_EL1 */ ++ ARM64SysReg *ID_DFR0_EL1 = arm64_sysreg_get(ID_DFR0_EL1_IDX); ++ ID_DFR0_EL1->name = "ID_DFR0_EL1"; ++ arm64_sysreg_add_field(ID_DFR0_EL1, "TraceFilt", 28, 31); ++ arm64_sysreg_add_field(ID_DFR0_EL1, "PerfMon", 24, 27); ++ arm64_sysreg_add_field(ID_DFR0_EL1, "MProfDbg", 20, 23); ++ arm64_sysreg_add_field(ID_DFR0_EL1, "MMapTrc", 16, 19); ++ arm64_sysreg_add_field(ID_DFR0_EL1, "CopTrc", 12, 15); ++ arm64_sysreg_add_field(ID_DFR0_EL1, "MMapDbg", 8, 11); ++ arm64_sysreg_add_field(ID_DFR0_EL1, "CopSDbg", 4, 7); ++ arm64_sysreg_add_field(ID_DFR0_EL1, "CopDbg", 0, 3); ++ ++ /* ID_AFR0_EL1 */ ++ ARM64SysReg *ID_AFR0_EL1 = arm64_sysreg_get(ID_AFR0_EL1_IDX); ++ ID_AFR0_EL1->name = "ID_AFR0_EL1"; ++ arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF3", 12, 15); ++ arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF2", 8, 11); ++ arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF1", 4, 7); ++ arm64_sysreg_add_field(ID_AFR0_EL1, "IMPDEF0", 0, 3); ++ ++ /* ID_MMFR0_EL1 */ ++ ARM64SysReg *ID_MMFR0_EL1 = arm64_sysreg_get(ID_MMFR0_EL1_IDX); ++ ID_MMFR0_EL1->name = "ID_MMFR0_EL1"; ++ arm64_sysreg_add_field(ID_MMFR0_EL1, "InnerShr", 28, 31); ++ arm64_sysreg_add_field(ID_MMFR0_EL1, "FCSE", 24, 27); ++ arm64_sysreg_add_field(ID_MMFR0_EL1, "AuxReg", 20, 23); ++ arm64_sysreg_add_field(ID_MMFR0_EL1, "TCM", 16, 19); ++ arm64_sysreg_add_field(ID_MMFR0_EL1, "ShareLvl", 12, 15); ++ arm64_sysreg_add_field(ID_MMFR0_EL1, "OuterShr", 8, 11); ++ arm64_sysreg_add_field(ID_MMFR0_EL1, "PMSA", 4, 7); ++ arm64_sysreg_add_field(ID_MMFR0_EL1, "VMSA", 0, 3); ++ ++ /* ID_MMFR1_EL1 */ ++ ARM64SysReg *ID_MMFR1_EL1 = arm64_sysreg_get(ID_MMFR1_EL1_IDX); ++ ID_MMFR1_EL1->name = "ID_MMFR1_EL1"; ++ arm64_sysreg_add_field(ID_MMFR1_EL1, "BPred", 28, 31); ++ arm64_sysreg_add_field(ID_MMFR1_EL1, "L1TstCln", 24, 27); ++ arm64_sysreg_add_field(ID_MMFR1_EL1, "L1Uni", 20, 23); ++ arm64_sysreg_add_field(ID_MMFR1_EL1, "L1Hvd", 16, 19); ++ arm64_sysreg_add_field(ID_MMFR1_EL1, "L1UniSW", 12, 15); ++ arm64_sysreg_add_field(ID_MMFR1_EL1, "L1HvdSW", 8, 11); ++ arm64_sysreg_add_field(ID_MMFR1_EL1, "L1UniVA", 4, 7); ++ arm64_sysreg_add_field(ID_MMFR1_EL1, "L1HvdVA", 0, 3); ++ ++ /* ID_MMFR2_EL1 */ ++ ARM64SysReg *ID_MMFR2_EL1 = arm64_sysreg_get(ID_MMFR2_EL1_IDX); ++ ID_MMFR2_EL1->name = "ID_MMFR2_EL1"; ++ arm64_sysreg_add_field(ID_MMFR2_EL1, "HWAccFlg", 28, 31); ++ arm64_sysreg_add_field(ID_MMFR2_EL1, "WFIStall", 24, 27); ++ arm64_sysreg_add_field(ID_MMFR2_EL1, "MemBarr", 20, 23); ++ arm64_sysreg_add_field(ID_MMFR2_EL1, "UniTLB", 16, 19); ++ arm64_sysreg_add_field(ID_MMFR2_EL1, "HvdTLB", 12, 15); ++ arm64_sysreg_add_field(ID_MMFR2_EL1, "L1HvdRng", 8, 11); ++ arm64_sysreg_add_field(ID_MMFR2_EL1, "L1HvdBG", 4, 7); ++ arm64_sysreg_add_field(ID_MMFR2_EL1, "L1HvdFG", 0, 3); ++ ++ /* ID_MMFR3_EL1 */ ++ ARM64SysReg *ID_MMFR3_EL1 = arm64_sysreg_get(ID_MMFR3_EL1_IDX); ++ ID_MMFR3_EL1->name = "ID_MMFR3_EL1"; ++ arm64_sysreg_add_field(ID_MMFR3_EL1, "Supersec", 28, 31); ++ arm64_sysreg_add_field(ID_MMFR3_EL1, "CMemSz", 24, 27); ++ arm64_sysreg_add_field(ID_MMFR3_EL1, "CohWalk", 20, 23); ++ arm64_sysreg_add_field(ID_MMFR3_EL1, "PAN", 16, 19); ++ arm64_sysreg_add_field(ID_MMFR3_EL1, "MaintBcst", 12, 15); ++ arm64_sysreg_add_field(ID_MMFR3_EL1, "BPMaint", 8, 11); ++ arm64_sysreg_add_field(ID_MMFR3_EL1, "CMaintSW", 4, 7); ++ arm64_sysreg_add_field(ID_MMFR3_EL1, "CMaintVA", 0, 3); ++ ++ /* ID_ISAR0_EL1 */ ++ ARM64SysReg *ID_ISAR0_EL1 = arm64_sysreg_get(ID_ISAR0_EL1_IDX); ++ ID_ISAR0_EL1->name = "ID_ISAR0_EL1"; ++ arm64_sysreg_add_field(ID_ISAR0_EL1, "Divide", 24, 27); ++ arm64_sysreg_add_field(ID_ISAR0_EL1, "Debug", 20, 23); ++ arm64_sysreg_add_field(ID_ISAR0_EL1, "Coproc", 16, 19); ++ arm64_sysreg_add_field(ID_ISAR0_EL1, "CmpBranch", 12, 15); ++ arm64_sysreg_add_field(ID_ISAR0_EL1, "BitField", 8, 11); ++ arm64_sysreg_add_field(ID_ISAR0_EL1, "BitCount", 4, 7); ++ arm64_sysreg_add_field(ID_ISAR0_EL1, "Swap", 0, 3); ++ ++ /* ID_ISAR1_EL1 */ ++ ARM64SysReg *ID_ISAR1_EL1 = arm64_sysreg_get(ID_ISAR1_EL1_IDX); ++ ID_ISAR1_EL1->name = "ID_ISAR1_EL1"; ++ arm64_sysreg_add_field(ID_ISAR1_EL1, "Jazelle", 28, 31); ++ arm64_sysreg_add_field(ID_ISAR1_EL1, "Interwork", 24, 27); ++ arm64_sysreg_add_field(ID_ISAR1_EL1, "Immediate", 20, 23); ++ arm64_sysreg_add_field(ID_ISAR1_EL1, "IfThen", 16, 19); ++ arm64_sysreg_add_field(ID_ISAR1_EL1, "Extend", 12, 15); ++ arm64_sysreg_add_field(ID_ISAR1_EL1, "Except_AR", 8, 11); ++ arm64_sysreg_add_field(ID_ISAR1_EL1, "Except", 4, 7); ++ arm64_sysreg_add_field(ID_ISAR1_EL1, "Endian", 0, 3); ++ ++ /* ID_ISAR2_EL1 */ ++ ARM64SysReg *ID_ISAR2_EL1 = arm64_sysreg_get(ID_ISAR2_EL1_IDX); ++ ID_ISAR2_EL1->name = "ID_ISAR2_EL1"; ++ arm64_sysreg_add_field(ID_ISAR2_EL1, "Reversal", 28, 31); ++ arm64_sysreg_add_field(ID_ISAR2_EL1, "PSR_AR", 24, 27); ++ arm64_sysreg_add_field(ID_ISAR2_EL1, "MultU", 20, 23); ++ arm64_sysreg_add_field(ID_ISAR2_EL1, "MultS", 16, 19); ++ arm64_sysreg_add_field(ID_ISAR2_EL1, "Mult", 12, 15); ++ arm64_sysreg_add_field(ID_ISAR2_EL1, "MultiAccessInt", 8, 11); ++ arm64_sysreg_add_field(ID_ISAR2_EL1, "MemHint", 4, 7); ++ arm64_sysreg_add_field(ID_ISAR2_EL1, "LoadStore", 0, 3); ++ ++ /* ID_ISAR3_EL1 */ ++ ARM64SysReg *ID_ISAR3_EL1 = arm64_sysreg_get(ID_ISAR3_EL1_IDX); ++ ID_ISAR3_EL1->name = "ID_ISAR3_EL1"; ++ arm64_sysreg_add_field(ID_ISAR3_EL1, "T32EE", 28, 31); ++ arm64_sysreg_add_field(ID_ISAR3_EL1, "TrueNOP", 24, 27); ++ arm64_sysreg_add_field(ID_ISAR3_EL1, "T32Copy", 20, 23); ++ arm64_sysreg_add_field(ID_ISAR3_EL1, "TabBranch", 16, 19); ++ arm64_sysreg_add_field(ID_ISAR3_EL1, "SynchPrim", 12, 15); ++ arm64_sysreg_add_field(ID_ISAR3_EL1, "SVC", 8, 11); ++ arm64_sysreg_add_field(ID_ISAR3_EL1, "SIMD", 4, 7); ++ arm64_sysreg_add_field(ID_ISAR3_EL1, "Saturate", 0, 3); ++ ++ /* ID_ISAR4_EL1 */ ++ ARM64SysReg *ID_ISAR4_EL1 = arm64_sysreg_get(ID_ISAR4_EL1_IDX); ++ ID_ISAR4_EL1->name = "ID_ISAR4_EL1"; ++ arm64_sysreg_add_field(ID_ISAR4_EL1, "SWP_frac", 28, 31); ++ arm64_sysreg_add_field(ID_ISAR4_EL1, "PSR_M", 24, 27); ++ arm64_sysreg_add_field(ID_ISAR4_EL1, "SynchPrim_frac", 20, 23); ++ arm64_sysreg_add_field(ID_ISAR4_EL1, "Barrier", 16, 19); ++ arm64_sysreg_add_field(ID_ISAR4_EL1, "SMC", 12, 15); ++ arm64_sysreg_add_field(ID_ISAR4_EL1, "Writeback", 8, 11); ++ arm64_sysreg_add_field(ID_ISAR4_EL1, "WithShifts", 4, 7); ++ arm64_sysreg_add_field(ID_ISAR4_EL1, "Unpriv", 0, 3); ++ ++ /* ID_ISAR5_EL1 */ ++ ARM64SysReg *ID_ISAR5_EL1 = arm64_sysreg_get(ID_ISAR5_EL1_IDX); ++ ID_ISAR5_EL1->name = "ID_ISAR5_EL1"; ++ arm64_sysreg_add_field(ID_ISAR5_EL1, "VCMA", 28, 31); ++ arm64_sysreg_add_field(ID_ISAR5_EL1, "RDM", 24, 27); ++ arm64_sysreg_add_field(ID_ISAR5_EL1, "CRC32", 16, 19); ++ arm64_sysreg_add_field(ID_ISAR5_EL1, "SHA2", 12, 15); ++ arm64_sysreg_add_field(ID_ISAR5_EL1, "SHA1", 8, 11); ++ arm64_sysreg_add_field(ID_ISAR5_EL1, "AES", 4, 7); ++ arm64_sysreg_add_field(ID_ISAR5_EL1, "SEVL", 0, 3); ++ ++ /* ID_ISAR6_EL1 */ ++ ARM64SysReg *ID_ISAR6_EL1 = arm64_sysreg_get(ID_ISAR6_EL1_IDX); ++ ID_ISAR6_EL1->name = "ID_ISAR6_EL1"; ++ arm64_sysreg_add_field(ID_ISAR6_EL1, "I8MM", 24, 27); ++ arm64_sysreg_add_field(ID_ISAR6_EL1, "BF16", 20, 23); ++ arm64_sysreg_add_field(ID_ISAR6_EL1, "SPECRES", 16, 19); ++ arm64_sysreg_add_field(ID_ISAR6_EL1, "SB", 12, 15); ++ arm64_sysreg_add_field(ID_ISAR6_EL1, "FHM", 8, 11); ++ arm64_sysreg_add_field(ID_ISAR6_EL1, "DP", 4, 7); ++ arm64_sysreg_add_field(ID_ISAR6_EL1, "JSCVT", 0, 3); ++ ++ /* ID_MMFR4_EL1 */ ++ ARM64SysReg *ID_MMFR4_EL1 = arm64_sysreg_get(ID_MMFR4_EL1_IDX); ++ ID_MMFR4_EL1->name = "ID_MMFR4_EL1"; ++ arm64_sysreg_add_field(ID_MMFR4_EL1, "EVT", 28, 31); ++ arm64_sysreg_add_field(ID_MMFR4_EL1, "CCIDX", 24, 27); ++ arm64_sysreg_add_field(ID_MMFR4_EL1, "LSM", 20, 23); ++ arm64_sysreg_add_field(ID_MMFR4_EL1, "HPDS", 16, 19); ++ arm64_sysreg_add_field(ID_MMFR4_EL1, "CnP", 12, 15); ++ arm64_sysreg_add_field(ID_MMFR4_EL1, "XNX", 8, 11); ++ arm64_sysreg_add_field(ID_MMFR4_EL1, "AC2", 4, 7); ++ arm64_sysreg_add_field(ID_MMFR4_EL1, "SpecSEI", 0, 3); ++ ++ /* MVFR0_EL1 */ ++ ARM64SysReg *MVFR0_EL1 = arm64_sysreg_get(MVFR0_EL1_IDX); ++ MVFR0_EL1->name = "MVFR0_EL1"; ++ arm64_sysreg_add_field(MVFR0_EL1, "FPRound", 28, 31); ++ arm64_sysreg_add_field(MVFR0_EL1, "FPShVec", 24, 27); ++ arm64_sysreg_add_field(MVFR0_EL1, "FPSqrt", 20, 23); ++ arm64_sysreg_add_field(MVFR0_EL1, "FPDivide", 16, 19); ++ arm64_sysreg_add_field(MVFR0_EL1, "FPTrap", 12, 15); ++ arm64_sysreg_add_field(MVFR0_EL1, "FPDP", 8, 11); ++ arm64_sysreg_add_field(MVFR0_EL1, "FPSP", 4, 7); ++ arm64_sysreg_add_field(MVFR0_EL1, "SIMDReg", 0, 3); ++ ++ /* MVFR1_EL1 */ ++ ARM64SysReg *MVFR1_EL1 = arm64_sysreg_get(MVFR1_EL1_IDX); ++ MVFR1_EL1->name = "MVFR1_EL1"; ++ arm64_sysreg_add_field(MVFR1_EL1, "SIMDFMAC", 28, 31); ++ arm64_sysreg_add_field(MVFR1_EL1, "FPHP", 24, 27); ++ arm64_sysreg_add_field(MVFR1_EL1, "SIMDHP", 20, 23); ++ arm64_sysreg_add_field(MVFR1_EL1, "SIMDSP", 16, 19); ++ arm64_sysreg_add_field(MVFR1_EL1, "SIMDInt", 12, 15); ++ arm64_sysreg_add_field(MVFR1_EL1, "SIMDLS", 8, 11); ++ arm64_sysreg_add_field(MVFR1_EL1, "FPDNaN", 4, 7); ++ arm64_sysreg_add_field(MVFR1_EL1, "FPFtZ", 0, 3); ++ ++ /* MVFR2_EL1 */ ++ ARM64SysReg *MVFR2_EL1 = arm64_sysreg_get(MVFR2_EL1_IDX); ++ MVFR2_EL1->name = "MVFR2_EL1"; ++ arm64_sysreg_add_field(MVFR2_EL1, "FPMisc", 4, 7); ++ arm64_sysreg_add_field(MVFR2_EL1, "SIMDMisc", 0, 3); ++ ++ /* ID_PFR2_EL1 */ ++ ARM64SysReg *ID_PFR2_EL1 = arm64_sysreg_get(ID_PFR2_EL1_IDX); ++ ID_PFR2_EL1->name = "ID_PFR2_EL1"; ++ arm64_sysreg_add_field(ID_PFR2_EL1, "RAS_frac", 8, 11); ++ arm64_sysreg_add_field(ID_PFR2_EL1, "SSBS", 4, 7); ++ arm64_sysreg_add_field(ID_PFR2_EL1, "CSV3", 0, 3); ++ ++ /* ID_DFR1_EL1 */ ++ ARM64SysReg *ID_DFR1_EL1 = arm64_sysreg_get(ID_DFR1_EL1_IDX); ++ ID_DFR1_EL1->name = "ID_DFR1_EL1"; ++ arm64_sysreg_add_field(ID_DFR1_EL1, "HPMN0", 4, 7); ++ arm64_sysreg_add_field(ID_DFR1_EL1, "MTPMU", 0, 3); ++ ++ /* ID_MMFR5_EL1 */ ++ ARM64SysReg *ID_MMFR5_EL1 = arm64_sysreg_get(ID_MMFR5_EL1_IDX); ++ ID_MMFR5_EL1->name = "ID_MMFR5_EL1"; ++ arm64_sysreg_add_field(ID_MMFR5_EL1, "nTLBPA", 4, 7); ++ arm64_sysreg_add_field(ID_MMFR5_EL1, "ETS", 0, 3); ++ ++ /* ID_AA64PFR0_EL1 */ ++ ARM64SysReg *ID_AA64PFR0_EL1 = arm64_sysreg_get(ID_AA64PFR0_EL1_IDX); ++ ID_AA64PFR0_EL1->name = "ID_AA64PFR0_EL1"; ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "CSV3", 60, 63); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "CSV2", 56, 59); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "RME", 52, 55); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "DIT", 48, 51); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "AMU", 44, 47); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "MPAM", 40, 43); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "SEL2", 36, 39); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "SVE", 32, 35); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "RAS", 28, 31); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "GIC", 24, 27); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "AdvSIMD", 20, 23); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "AdvSIMD", 20, 23); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "FP", 16, 19); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "FP", 16, 19); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL3", 12, 15); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL2", 8, 11); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL1", 4, 7); ++ arm64_sysreg_add_field(ID_AA64PFR0_EL1, "EL0", 0, 3); ++ ++ /* ID_AA64PFR1_EL1 */ ++ ARM64SysReg *ID_AA64PFR1_EL1 = arm64_sysreg_get(ID_AA64PFR1_EL1_IDX); ++ ID_AA64PFR1_EL1->name = "ID_AA64PFR1_EL1"; ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "PFAR", 60, 63); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "DF2", 56, 59); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MTEX", 52, 55); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "THE", 48, 51); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "GCS", 44, 47); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MTE_frac", 40, 43); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "NMI", 36, 39); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "CSV2_frac", 32, 35); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "RNDR_trap", 28, 31); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "SME", 24, 27); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MPAM_frac", 16, 19); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "RAS_frac", 12, 15); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "MTE", 8, 11); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "SSBS", 4, 7); ++ arm64_sysreg_add_field(ID_AA64PFR1_EL1, "BT", 0, 3); ++ ++ /* ID_AA64PFR2_EL1 */ ++ ARM64SysReg *ID_AA64PFR2_EL1 = arm64_sysreg_get(ID_AA64PFR2_EL1_IDX); ++ ID_AA64PFR2_EL1->name = "ID_AA64PFR2_EL1"; ++ arm64_sysreg_add_field(ID_AA64PFR2_EL1, "FPMR", 32, 35); ++ arm64_sysreg_add_field(ID_AA64PFR2_EL1, "UINJ", 16, 19); ++ arm64_sysreg_add_field(ID_AA64PFR2_EL1, "MTEFAR", 8, 11); ++ arm64_sysreg_add_field(ID_AA64PFR2_EL1, "MTESTOREONLY", 4, 7); ++ arm64_sysreg_add_field(ID_AA64PFR2_EL1, "MTEPERM", 0, 3); ++ ++ /* ID_AA64ZFR0_EL1 */ ++ ARM64SysReg *ID_AA64ZFR0_EL1 = arm64_sysreg_get(ID_AA64ZFR0_EL1_IDX); ++ ID_AA64ZFR0_EL1->name = "ID_AA64ZFR0_EL1"; ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "F64MM", 56, 59); ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "F32MM", 52, 55); ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "F16MM", 48, 51); ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "I8MM", 44, 47); ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "SM4", 40, 43); ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "SHA3", 32, 35); ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "B16B16", 24, 27); ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "BF16", 20, 23); ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "BitPerm", 16, 19); ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "EltPerm", 12, 15); ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "AES", 4, 7); ++ arm64_sysreg_add_field(ID_AA64ZFR0_EL1, "SVEver", 0, 3); ++ ++ /* ID_AA64SMFR0_EL1 */ ++ ARM64SysReg *ID_AA64SMFR0_EL1 = arm64_sysreg_get(ID_AA64SMFR0_EL1_IDX); ++ ID_AA64SMFR0_EL1->name = "ID_AA64SMFR0_EL1"; ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "FA64", 63, 63); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "LUTv2", 60, 60); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SMEver", 56, 59); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "I16I64", 52, 55); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F64F64", 48, 48); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "I16I32", 44, 47); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "B16B16", 43, 43); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F16F16", 42, 42); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F8F16", 41, 41); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F8F32", 40, 40); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "I8I32", 36, 39); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F16F32", 35, 35); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "B16F32", 34, 34); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "BI32I32", 33, 33); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "F32F32", 32, 32); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SF8FMA", 30, 30); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SF8DP4", 29, 29); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SF8DP2", 28, 28); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SBitPerm", 25, 25); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "AES", 24, 24); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SFEXPA", 23, 23); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "STMOP", 16, 16); ++ arm64_sysreg_add_field(ID_AA64SMFR0_EL1, "SMOP4", 0, 0); ++ ++ /* ID_AA64FPFR0_EL1 */ ++ ARM64SysReg *ID_AA64FPFR0_EL1 = arm64_sysreg_get(ID_AA64FPFR0_EL1_IDX); ++ ID_AA64FPFR0_EL1->name = "ID_AA64FPFR0_EL1"; ++ arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8CVT", 31, 31); ++ arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8FMA", 30, 30); ++ arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8DP4", 29, 29); ++ arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8DP2", 28, 28); ++ arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8MM8", 27, 27); ++ arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8MM4", 26, 26); ++ arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8E4M3", 1, 1); ++ arm64_sysreg_add_field(ID_AA64FPFR0_EL1, "F8E5M2", 0, 0); ++ ++ /* ID_AA64DFR0_EL1 */ ++ ARM64SysReg *ID_AA64DFR0_EL1 = arm64_sysreg_get(ID_AA64DFR0_EL1_IDX); ++ ID_AA64DFR0_EL1->name = "ID_AA64DFR0_EL1"; ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "HPMN0", 60, 63); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "ExtTrcBuff", 56, 59); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "BRBE", 52, 55); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "MTPMU", 48, 51); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "MTPMU", 48, 51); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "TraceBuffer", 44, 47); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "TraceFilt", 40, 43); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "DoubleLock", 36, 39); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "PMSVer", 32, 35); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "CTX_CMPs", 28, 31); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "SEBEP", 24, 27); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "WRPs", 20, 23); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "PMSS", 16, 19); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "BRPs", 12, 15); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "PMUVer", 8, 11); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "TraceVer", 4, 7); ++ arm64_sysreg_add_field(ID_AA64DFR0_EL1, "DebugVer", 0, 3); ++ ++ /* ID_AA64DFR1_EL1 */ ++ ARM64SysReg *ID_AA64DFR1_EL1 = arm64_sysreg_get(ID_AA64DFR1_EL1_IDX); ++ ID_AA64DFR1_EL1->name = "ID_AA64DFR1_EL1"; ++ arm64_sysreg_add_field(ID_AA64DFR1_EL1, "ABL_CMPs", 56, 63); ++ arm64_sysreg_add_field(ID_AA64DFR1_EL1, "DPFZS", 52, 55); ++ arm64_sysreg_add_field(ID_AA64DFR1_EL1, "EBEP", 48, 51); ++ arm64_sysreg_add_field(ID_AA64DFR1_EL1, "ITE", 44, 47); ++ arm64_sysreg_add_field(ID_AA64DFR1_EL1, "ABLE", 40, 43); ++ arm64_sysreg_add_field(ID_AA64DFR1_EL1, "PMICNTR", 36, 39); ++ arm64_sysreg_add_field(ID_AA64DFR1_EL1, "SPMU", 32, 35); ++ arm64_sysreg_add_field(ID_AA64DFR1_EL1, "CTX_CMPs", 24, 31); ++ arm64_sysreg_add_field(ID_AA64DFR1_EL1, "WRPs", 16, 23); ++ arm64_sysreg_add_field(ID_AA64DFR1_EL1, "BRPs", 8, 15); ++ arm64_sysreg_add_field(ID_AA64DFR1_EL1, "SYSPMUID", 0, 7); ++ ++ /* ID_AA64DFR2_EL1 */ ++ ARM64SysReg *ID_AA64DFR2_EL1 = arm64_sysreg_get(ID_AA64DFR2_EL1_IDX); ++ ID_AA64DFR2_EL1->name = "ID_AA64DFR2_EL1"; ++ arm64_sysreg_add_field(ID_AA64DFR2_EL1, "TRBE_EXC", 24, 27); ++ arm64_sysreg_add_field(ID_AA64DFR2_EL1, "SPE_nVM", 20, 23); ++ arm64_sysreg_add_field(ID_AA64DFR2_EL1, "SPE_EXC", 16, 19); ++ arm64_sysreg_add_field(ID_AA64DFR2_EL1, "BWE", 4, 7); ++ arm64_sysreg_add_field(ID_AA64DFR2_EL1, "STEP", 0, 3); ++ ++ /* ID_AA64AFR0_EL1 */ ++ ARM64SysReg *ID_AA64AFR0_EL1 = arm64_sysreg_get(ID_AA64AFR0_EL1_IDX); ++ ID_AA64AFR0_EL1->name = "ID_AA64AFR0_EL1"; ++ arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF7", 28, 31); ++ arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF6", 24, 27); ++ arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF5", 20, 23); ++ arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF4", 16, 19); ++ arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF3", 12, 15); ++ arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF2", 8, 11); ++ arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF1", 4, 7); ++ arm64_sysreg_add_field(ID_AA64AFR0_EL1, "IMPDEF0", 0, 3); ++ ++ /* ID_AA64AFR1_EL1 */ ++ ARM64SysReg *ID_AA64AFR1_EL1 = arm64_sysreg_get(ID_AA64AFR1_EL1_IDX); ++ ID_AA64AFR1_EL1->name = "ID_AA64AFR1_EL1"; ++ ++ /* ID_AA64ISAR0_EL1 */ ++ ARM64SysReg *ID_AA64ISAR0_EL1 = arm64_sysreg_get(ID_AA64ISAR0_EL1_IDX); ++ ID_AA64ISAR0_EL1->name = "ID_AA64ISAR0_EL1"; ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "RNDR", 60, 63); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "TLB", 56, 59); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "TS", 52, 55); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "FHM", 48, 51); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "DP", 44, 47); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SM4", 40, 43); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SM3", 36, 39); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SHA3", 32, 35); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "RDM", 28, 31); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "TME", 24, 27); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "ATOMIC", 20, 23); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "CRC32", 16, 19); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SHA2", 12, 15); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "SHA1", 8, 11); ++ arm64_sysreg_add_field(ID_AA64ISAR0_EL1, "AES", 4, 7); ++ ++ /* ID_AA64ISAR1_EL1 */ ++ ARM64SysReg *ID_AA64ISAR1_EL1 = arm64_sysreg_get(ID_AA64ISAR1_EL1_IDX); ++ ID_AA64ISAR1_EL1->name = "ID_AA64ISAR1_EL1"; ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "LS64", 60, 63); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "XS", 56, 59); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "I8MM", 52, 55); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "DGH", 48, 51); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "BF16", 44, 47); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "SPECRES", 40, 43); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "SB", 36, 39); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "FRINTTS", 32, 35); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "GPI", 28, 31); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "GPA", 24, 27); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "LRCPC", 20, 23); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "FCMA", 16, 19); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "JSCVT", 12, 15); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "API", 8, 11); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "APA", 4, 7); ++ arm64_sysreg_add_field(ID_AA64ISAR1_EL1, "DPB", 0, 3); ++ ++ /* ID_AA64ISAR2_EL1 */ ++ ARM64SysReg *ID_AA64ISAR2_EL1 = arm64_sysreg_get(ID_AA64ISAR2_EL1_IDX); ++ ID_AA64ISAR2_EL1->name = "ID_AA64ISAR2_EL1"; ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "ATS1A", 60, 63); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "LUT", 56, 59); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "CSSC", 52, 55); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "RPRFM", 48, 51); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "PCDPHINT", 44, 47); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "PRFMSLC", 40, 43); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "SYSINSTR_128", 36, 39); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "SYSREG_128", 32, 35); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "CLRBHB", 28, 31); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "PAC_frac", 24, 27); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "BC", 20, 23); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "MOPS", 16, 19); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "APA3", 12, 15); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "GPA3", 8, 11); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "RPRES", 4, 7); ++ arm64_sysreg_add_field(ID_AA64ISAR2_EL1, "WFxT", 0, 3); ++ ++ /* ID_AA64ISAR3_EL1 */ ++ ARM64SysReg *ID_AA64ISAR3_EL1 = arm64_sysreg_get(ID_AA64ISAR3_EL1_IDX); ++ ID_AA64ISAR3_EL1->name = "ID_AA64ISAR3_EL1"; ++ arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "FPRCVT", 28, 31); ++ arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "LSUI", 24, 27); ++ arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "OCCMO", 20, 23); ++ arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "LSFE", 16, 19); ++ arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "PACM", 12, 15); ++ arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "TLBIW", 8, 11); ++ arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "FAMINMAX", 4, 7); ++ arm64_sysreg_add_field(ID_AA64ISAR3_EL1, "CPA", 0, 3); ++ ++ /* ID_AA64MMFR0_EL1 */ ++ ARM64SysReg *ID_AA64MMFR0_EL1 = arm64_sysreg_get(ID_AA64MMFR0_EL1_IDX); ++ ID_AA64MMFR0_EL1->name = "ID_AA64MMFR0_EL1"; ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "ECV", 60, 63); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "FGT", 56, 59); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "EXS", 44, 47); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN4_2", 40, 43); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN64_2", 36, 39); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN16_2", 32, 35); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN4", 28, 31); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN4", 28, 31); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN64", 24, 27); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN64", 24, 27); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "TGRAN16", 20, 23); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "BIGENDEL0", 16, 19); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "SNSMEM", 12, 15); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "BIGEND", 8, 11); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "ASIDBITS", 4, 7); ++ arm64_sysreg_add_field(ID_AA64MMFR0_EL1, "PARANGE", 0, 3); ++ ++ /* ID_AA64MMFR1_EL1 */ ++ ARM64SysReg *ID_AA64MMFR1_EL1 = arm64_sysreg_get(ID_AA64MMFR1_EL1_IDX); ++ ID_AA64MMFR1_EL1->name = "ID_AA64MMFR1_EL1"; ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "ECBHB", 60, 63); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "CMOW", 56, 59); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "TIDCP1", 52, 55); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "nTLBPA", 48, 51); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "AFP", 44, 47); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "HCX", 40, 43); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "ETS", 36, 39); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "TWED", 32, 35); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "XNX", 28, 31); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "SpecSEI", 24, 27); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "PAN", 20, 23); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "LO", 16, 19); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "HPDS", 12, 15); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "VH", 8, 11); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "VMIDBits", 4, 7); ++ arm64_sysreg_add_field(ID_AA64MMFR1_EL1, "HAFDBS", 0, 3); ++ ++ /* ID_AA64MMFR2_EL1 */ ++ ARM64SysReg *ID_AA64MMFR2_EL1 = arm64_sysreg_get(ID_AA64MMFR2_EL1_IDX); ++ ID_AA64MMFR2_EL1->name = "ID_AA64MMFR2_EL1"; ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "E0PD", 60, 63); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "EVT", 56, 59); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "BBM", 52, 55); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "TTL", 48, 51); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "FWB", 40, 43); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "IDS", 36, 39); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "AT", 32, 35); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "ST", 28, 31); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "NV", 24, 27); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "CCIDX", 20, 23); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "VARange", 16, 19); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "IESB", 12, 15); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "LSM", 8, 11); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "UAO", 4, 7); ++ arm64_sysreg_add_field(ID_AA64MMFR2_EL1, "CnP", 0, 3); ++ ++ /* ID_AA64MMFR3_EL1 */ ++ ARM64SysReg *ID_AA64MMFR3_EL1 = arm64_sysreg_get(ID_AA64MMFR3_EL1_IDX); ++ ID_AA64MMFR3_EL1->name = "ID_AA64MMFR3_EL1"; ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "Spec_FPACC", 60, 63); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "ADERR", 56, 59); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "SDERR", 52, 55); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "ANERR", 44, 47); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "SNERR", 40, 43); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "D128_2", 36, 39); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "D128", 32, 35); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "MEC", 28, 31); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "AIE", 24, 27); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S2POE", 20, 23); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S1POE", 16, 19); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S2PIE", 12, 15); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "S1PIE", 8, 11); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "SCTLRX", 4, 7); ++ arm64_sysreg_add_field(ID_AA64MMFR3_EL1, "TCRX", 0, 3); ++ ++ /* ID_AA64MMFR4_EL1 */ ++ ARM64SysReg *ID_AA64MMFR4_EL1 = arm64_sysreg_get(ID_AA64MMFR4_EL1_IDX); ++ ID_AA64MMFR4_EL1->name = "ID_AA64MMFR4_EL1"; ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "SRMASK", 44, 47); ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "E3DSE", 36, 39); ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "RMEGDI", 28, 31); ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "E2H0", 24, 27); ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "E2H0", 24, 27); ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "NV_frac", 20, 23); ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "FGWTE3", 16, 19); ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "HACDBS", 12, 15); ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "ASID2", 8, 11); ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "EIESB", 4, 7); ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "EIESB", 4, 7); ++ arm64_sysreg_add_field(ID_AA64MMFR4_EL1, "PoPS", 0, 3); ++ ++/* For SCTLR_EL12 fields see SCTLR_EL1 */ ++ ++/* For SCTLRALIAS_EL1 fields see SCTLR_EL1 */ ++ ++/* For ACTLR_EL12 fields see ACTLR_EL1 */ ++ ++/* For ACTLRALIAS_EL1 fields see ACTLR_EL1 */ ++ ++/* For CPACR_EL12 fields see CPACR_EL1 */ ++ ++/* For CPACRALIAS_EL1 fields see CPACR_EL1 */ ++ ++/* For ACTLRMASK_EL12 fields see ACTLRMASK_EL1 */ ++ ++/* For CPACRMASK_EL12 fields see CPACRMASK_EL1 */ ++ ++/* For PFAR_EL12 fields see PFAR_EL1 */ ++ ++/* For SCTLR2_EL12 fields see SCTLR2_EL1 */ ++ ++/* For SCTLR2ALIAS_EL1 fields see SCTLR2_EL1 */ ++ ++/* For SCTLR2MASK_EL12 fields see SCTLR2MASK_EL1 */ ++ ++/* For SCTLRMASK_EL12 fields see SCTLRMASK_EL1 */ ++ ++/* For TCR2MASK_EL12 fields see TCR2MASK_EL1 */ ++ ++/* For TCRMASK_EL12 fields see TCRMASK_EL1 */ ++ ++/* For TRCITECR_EL12 fields see TRCITECR_EL1 */ ++ ++/* For ZCR_EL1 fields see ZCR_ELx */ ++ ++/* For SMCR_EL1 fields see SMCR_ELx */ ++ ++/* For GCSCR_EL1 fields see GCSCR_ELx */ ++ ++/* For GCSPR_EL1 fields see GCSPR_ELx */ ++ ++/* For CONTEXTIDR_EL1 fields see CONTEXTIDR_ELx */ ++ ++ /* CCSIDR_EL1 */ ++ ARM64SysReg *CCSIDR_EL1 = arm64_sysreg_get(CCSIDR_EL1_IDX); ++ CCSIDR_EL1->name = "CCSIDR_EL1"; ++ arm64_sysreg_add_field(CCSIDR_EL1, "NumSets", 13, 27); ++ arm64_sysreg_add_field(CCSIDR_EL1, "Associativity", 3, 12); ++ arm64_sysreg_add_field(CCSIDR_EL1, "LineSize", 0, 2); ++ ++ /* CLIDR_EL1 */ ++ ARM64SysReg *CLIDR_EL1 = arm64_sysreg_get(CLIDR_EL1_IDX); ++ CLIDR_EL1->name = "CLIDR_EL1"; ++ arm64_sysreg_add_field(CLIDR_EL1, "Ttypen", 33, 46); ++ arm64_sysreg_add_field(CLIDR_EL1, "ICB", 30, 32); ++ arm64_sysreg_add_field(CLIDR_EL1, "LoUU", 27, 29); ++ arm64_sysreg_add_field(CLIDR_EL1, "LoC", 24, 26); ++ arm64_sysreg_add_field(CLIDR_EL1, "LoUIS", 21, 23); ++ arm64_sysreg_add_field(CLIDR_EL1, "Ctype7", 18, 20); ++ arm64_sysreg_add_field(CLIDR_EL1, "Ctype6", 15, 17); ++ arm64_sysreg_add_field(CLIDR_EL1, "Ctype5", 12, 14); ++ arm64_sysreg_add_field(CLIDR_EL1, "Ctype4", 9, 11); ++ arm64_sysreg_add_field(CLIDR_EL1, "Ctype3", 6, 8); ++ arm64_sysreg_add_field(CLIDR_EL1, "Ctype2", 3, 5); ++ arm64_sysreg_add_field(CLIDR_EL1, "Ctype1", 0, 2); ++ ++ /* CCSIDR2_EL1 */ ++ ARM64SysReg *CCSIDR2_EL1 = arm64_sysreg_get(CCSIDR2_EL1_IDX); ++ CCSIDR2_EL1->name = "CCSIDR2_EL1"; ++ arm64_sysreg_add_field(CCSIDR2_EL1, "NumSets", 0, 23); ++ ++ /* GMID_EL1 */ ++ ARM64SysReg *GMID_EL1 = arm64_sysreg_get(GMID_EL1_IDX); ++ GMID_EL1->name = "GMID_EL1"; ++ arm64_sysreg_add_field(GMID_EL1, "BS", 0, 3); ++ ++ /* SMIDR_EL1 */ ++ ARM64SysReg *SMIDR_EL1 = arm64_sysreg_get(SMIDR_EL1_IDX); ++ SMIDR_EL1->name = "SMIDR_EL1"; ++ arm64_sysreg_add_field(SMIDR_EL1, "IMPLEMENTER", 24, 31); ++ arm64_sysreg_add_field(SMIDR_EL1, "REVISION", 16, 23); ++ arm64_sysreg_add_field(SMIDR_EL1, "SMPS", 15, 15); ++ arm64_sysreg_add_field(SMIDR_EL1, "AFFINITY", 0, 11); ++ + /* CTR_EL0 */ + ARM64SysReg *CTR_EL0 = arm64_sysreg_get(CTR_EL0_IDX); + CTR_EL0->name = "CTR_EL0"; +@@ -37,5 +667,79 @@ void initialize_cpu_sysreg_properties(void) + arm64_sysreg_add_field(CTR_EL0, "DminLine", 16, 19); + arm64_sysreg_add_field(CTR_EL0, "L1Ip", 14, 15); + arm64_sysreg_add_field(CTR_EL0, "IminLine", 0, 3); +-} + ++ /* DCZID_EL0 */ ++ ARM64SysReg *DCZID_EL0 = arm64_sysreg_get(DCZID_EL0_IDX); ++ DCZID_EL0->name = "DCZID_EL0"; ++ arm64_sysreg_add_field(DCZID_EL0, "DZP", 4, 4); ++ arm64_sysreg_add_field(DCZID_EL0, "BS", 0, 3); ++ ++/* For GCSPR_EL0 fields see GCSPR_ELx */ ++ ++/* For ZCR_EL2 fields see ZCR_ELx */ ++ ++/* For SMCR_EL2 fields see SMCR_ELx */ ++ ++/* For GCSCR_EL2 fields see GCSCR_ELx */ ++ ++/* For GCSPR_EL2 fields see GCSPR_ELx */ ++ ++/* For CONTEXTIDR_EL2 fields see CONTEXTIDR_ELx */ ++ ++/* For CPACR_EL12 fields see CPACR_EL1 */ ++ ++/* For ZCR_EL12 fields see ZCR_EL1 */ ++ ++/* For TRFCR_EL12 fields see TRFCR_EL1 */ ++ ++/* For SMCR_EL12 fields see SMCR_EL1 */ ++ ++/* For GCSCR_EL12 fields see GCSCR_EL1 */ ++ ++/* For GCSPR_EL12 fields see GCSPR_EL1 */ ++ ++/* For MPAM1_EL12 fields see MPAM1_ELx */ ++ ++/* For CONTEXTIDR_EL12 fields see CONTEXTIDR_EL1 */ ++ ++/* For TTBR0_EL1 fields see TTBRx_EL1 */ ++ ++/* For TTBR1_EL1 fields see TTBRx_EL1 */ ++ ++/* For TCR_EL12 fields see TCR_EL1 */ ++ ++/* For TCRALIAS_EL1 fields see TCR_EL1 */ ++ ++/* For TCR2_EL12 fields see TCR2_EL1 */ ++ ++/* For TCR2ALIAS_EL1 fields see TCR2_EL1 */ ++ ++/* For MAIR2_EL1 fields see MAIR2_ELx */ ++ ++/* For MAIR2_EL2 fields see MAIR2_ELx */ ++ ++/* For PIRE0_EL1 fields see PIRx_ELx */ ++ ++/* For PIRE0_EL12 fields see PIRE0_EL1 */ ++ ++/* For PIRE0_EL2 fields see PIRx_ELx */ ++ ++/* For PIR_EL1 fields see PIRx_ELx */ ++ ++/* For PIR_EL12 fields see PIR_EL1 */ ++ ++/* For PIR_EL2 fields see PIRx_ELx */ ++ ++/* For POR_EL0 fields see PIRx_ELx */ ++ ++/* For POR_EL1 fields see PIRx_ELx */ ++ ++/* For POR_EL2 fields see PIRx_ELx */ ++ ++/* For POR_EL12 fields see POR_EL1 */ ++ ++/* For S2POR_EL1 fields see PIRx_ELx */ ++ ++/* For S2PIR_EL2 fields see PIRx_ELx */ ++ ++} +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Add-infra-to-handle-generated-ID-register-de.patch b/arm-cpu-Add-infra-to-handle-generated-ID-register-de.patch new file mode 100644 index 0000000000000000000000000000000000000000..98daf697c2ba6fc142a8162a8957ddfe4c2276d4 --- /dev/null +++ b/arm-cpu-Add-infra-to-handle-generated-ID-register-de.patch @@ -0,0 +1,175 @@ +From 39eea84e3923cca8d0bb9fba1c87b2965d14eed2 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 15/26] arm/cpu: Add infra to handle generated ID register + definitions + +The known ID regs are described in a new initialization function +dubbed initialize_cpu_sysreg_properties(). That code will be +automatically generated from linux arch/arm64/tools/sysreg. For the +time being let's just describe a single id reg, CTR_EL0. In this +description we only care about non RES/RAZ fields, ie. named fields. + +The registers are populated in an array indexed by ARMIDRegisterIdx +and their fields are added in a sorted list. + +[CH: adapted to reworked register storage] +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu-custom.h | 60 ++++++++++++++++++++++++++++++ + target/arm/cpu-sysreg-properties.c | 41 ++++++++++++++++++++ + target/arm/cpu64.c | 2 + + target/arm/meson.build | 1 + + 4 files changed, 104 insertions(+) + create mode 100644 target/arm/cpu-custom.h + create mode 100644 target/arm/cpu-sysreg-properties.c + +diff --git a/target/arm/cpu-custom.h b/target/arm/cpu-custom.h +new file mode 100644 +index 0000000000..615347376e +--- /dev/null ++++ b/target/arm/cpu-custom.h +@@ -0,0 +1,60 @@ ++/* ++ * handle ID registers and their fields ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++#ifndef ARM_CPU_CUSTOM_H ++#define ARM_CPU_CUSTOM_H ++ ++#include "qemu/osdep.h" ++#include "qemu/error-report.h" ++#include "cpu.h" ++#include "cpu-sysregs.h" ++ ++typedef struct ARM64SysRegField { ++ const char *name; /* name of the field, for instance CTR_EL0_IDC */ ++ int index; ++ int lower; ++ int upper; ++} ARM64SysRegField; ++ ++typedef struct ARM64SysReg { ++ const char *name; /* name of the sysreg, for instance CTR_EL0 */ ++ ARMSysRegs sysreg; ++ int index; ++ GList *fields; /* list of named fields, excluding RES* */ ++} ARM64SysReg; ++ ++void initialize_cpu_sysreg_properties(void); ++ ++/* ++ * List of exposed ID regs (automatically populated from linux ++ * arch/arm64/tools/sysreg) ++ */ ++extern ARM64SysReg arm64_id_regs[NUM_ID_IDX]; ++ ++/* Allocate a new field and insert it at the head of the @reg list */ ++static inline GList *arm64_sysreg_add_field(ARM64SysReg *reg, const char *name, ++ uint8_t min, uint8_t max) { ++ ++ ARM64SysRegField *field = g_new0(ARM64SysRegField, 1); ++ ++ field->name = name; ++ field->lower = min; ++ field->upper = max; ++ field->index = reg->index; ++ ++ reg->fields = g_list_append(reg->fields, field); ++ return reg->fields; ++} ++ ++static inline ARM64SysReg *arm64_sysreg_get(ARMIDRegisterIdx index) ++{ ++ ARM64SysReg *reg = &arm64_id_regs[index]; ++ ++ reg->index = index; ++ reg->sysreg = id_register_sysreg[index]; ++ return reg; ++} ++ ++#endif +diff --git a/target/arm/cpu-sysreg-properties.c b/target/arm/cpu-sysreg-properties.c +new file mode 100644 +index 0000000000..8b7ef5badf +--- /dev/null ++++ b/target/arm/cpu-sysreg-properties.c +@@ -0,0 +1,41 @@ ++/* ++ * QEMU ARM CPU SYSREG PROPERTIES ++ * to be generated from linux sysreg ++ * ++ * Copyright (c) Red Hat, Inc. 2024 ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see ++ * ++ */ ++ ++#include "cpu-custom.h" ++ ++ARM64SysReg arm64_id_regs[NUM_ID_IDX]; ++ ++void initialize_cpu_sysreg_properties(void) ++{ ++ memset(arm64_id_regs, 0, sizeof(ARM64SysReg) * NUM_ID_IDX); ++ /* CTR_EL0 */ ++ ARM64SysReg *CTR_EL0 = arm64_sysreg_get(CTR_EL0_IDX); ++ CTR_EL0->name = "CTR_EL0"; ++ arm64_sysreg_add_field(CTR_EL0, "TminLine", 32, 37); ++ arm64_sysreg_add_field(CTR_EL0, "DIC", 29, 29); ++ arm64_sysreg_add_field(CTR_EL0, "IDC", 28, 28); ++ arm64_sysreg_add_field(CTR_EL0, "CWG", 24, 27); ++ arm64_sysreg_add_field(CTR_EL0, "ERG", 20, 23); ++ arm64_sysreg_add_field(CTR_EL0, "DminLine", 16, 19); ++ arm64_sysreg_add_field(CTR_EL0, "L1Ip", 14, 15); ++ arm64_sysreg_add_field(CTR_EL0, "IminLine", 0, 3); ++} ++ +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 0942bb7a60..5ad6f77417 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -34,6 +34,7 @@ + #include "internals.h" + #include "cpu-features.h" + #include "cpregs.h" ++#include "cpu-custom.h" + + /* convert between _IDX and SYS_ */ + #define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \ +@@ -1071,6 +1072,7 @@ static void aarch64_cpu_register_types(void) + { + size_t i; + ++ initialize_cpu_sysreg_properties(); + type_register_static(&aarch64_cpu_type_info); + + for (i = 0; i < ARRAY_SIZE(aarch64_cpus); ++i) { +diff --git a/target/arm/meson.build b/target/arm/meson.build +index 7973b35cca..963ad9592b 100644 +--- a/target/arm/meson.build ++++ b/target/arm/meson.build +@@ -15,6 +15,7 @@ arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c', 'kvm-tmm.c'), + arm_ss.add(when: 'TARGET_AARCH64', if_true: files( + 'cpu64.c', + 'gdbstub64.c', ++ 'cpu-sysreg-properties.c', + )) + + arm_system_ss = ss.source_set() +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Add-sysreg-definitions-in-cpu-sysregs.h.patch b/arm-cpu-Add-sysreg-definitions-in-cpu-sysregs.h.patch new file mode 100644 index 0000000000000000000000000000000000000000..97fd74bcb23078a53b9573b83d97fbee4d426e93 --- /dev/null +++ b/arm-cpu-Add-sysreg-definitions-in-cpu-sysregs.h.patch @@ -0,0 +1,229 @@ +From 9f21bf95b285da235b3bba67a3d96f180068eaeb Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:47 +0800 +Subject: [PATCH 01/26] arm/cpu: Add sysreg definitions in cpu-sysregs.h + +This new header contains macros that define aarch64 registers. +In a subsequent patch, this will be replaced by a more exhaustive +version that will be generated from linux arch/arm64/tools/sysreg +file. Those macros are sufficient to migrate the storage of those +ID regs from named fields in isar struct to an array cell. + +[CH: reworked to use different structures] +[CH: moved accessors from the patches first using them to here, + dropped interaction with writable registers, which will happen + later] +[CH: use DEF magic suggested by rth] +Reviewed-by: Richard Henderson +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu-sysregs.h | 42 +++++++++++++++++++++++++++++++ + target/arm/cpu-sysregs.h.inc | 36 ++++++++++++++++++++++++++ + target/arm/cpu.h | 49 ++++++++++++++++++++++++++++++++++++ + target/arm/cpu64.c | 22 ++++++++++++++++ + 4 files changed, 149 insertions(+) + create mode 100644 target/arm/cpu-sysregs.h + create mode 100644 target/arm/cpu-sysregs.h.inc + +diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h +new file mode 100644 +index 0000000000..7877a3b06a +--- /dev/null ++++ b/target/arm/cpu-sysregs.h +@@ -0,0 +1,42 @@ ++/* ++ * Definitions for Arm ID system registers ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++#ifndef ARM_CPU_SYSREGS_H ++#define ARM_CPU_SYSREGS_H ++ ++/* ++ * Following is similar to the coprocessor regs encodings, but with an argument ++ * ordering that matches the ARM ARM. We also reuse the various CP_REG_ defines ++ * that actually are the same as the equivalent KVM_REG_ values. ++ */ ++#define ENCODE_ID_REG(op0, op1, crn, crm, op2) \ ++ (((op0) << CP_REG_ARM64_SYSREG_OP0_SHIFT) | \ ++ ((op1) << CP_REG_ARM64_SYSREG_OP1_SHIFT) | \ ++ ((crn) << CP_REG_ARM64_SYSREG_CRN_SHIFT) | \ ++ ((crm) << CP_REG_ARM64_SYSREG_CRM_SHIFT) | \ ++ ((op2) << CP_REG_ARM64_SYSREG_OP2_SHIFT)) ++ ++#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) NAME##_IDX, ++ ++typedef enum ARMIDRegisterIdx { ++#include "cpu-sysregs.h.inc" ++ NUM_ID_IDX, ++} ARMIDRegisterIdx; ++ ++#undef DEF ++#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \ ++ SYS_##NAME = ENCODE_ID_REG(OP0, OP1, CRN, CRM, OP2), ++ ++typedef enum ARMSysRegs { ++#include "cpu-sysregs.h.inc" ++} ARMSysRegs; ++ ++#undef DEF ++ ++extern const uint32_t id_register_sysreg[NUM_ID_IDX]; ++ ++int get_sysreg_idx(ARMSysRegs sysreg); ++ ++#endif /* ARM_CPU_SYSREGS_H */ +diff --git a/target/arm/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc +new file mode 100644 +index 0000000000..cb99286f70 +--- /dev/null ++++ b/target/arm/cpu-sysregs.h.inc +@@ -0,0 +1,36 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++DEF(ID_AA64PFR0_EL1, 3, 0, 0, 4, 0) ++DEF(ID_AA64PFR1_EL1, 3, 0, 0, 4, 1) ++DEF(ID_AA64SMFR0_EL1, 3, 0, 0, 4, 5) ++DEF(ID_AA64DFR0_EL1, 3, 0, 0, 5, 0) ++DEF(ID_AA64DFR1_EL1, 3, 0, 0, 5, 1) ++DEF(ID_AA64ISAR0_EL1, 3, 0, 0, 6, 0) ++DEF(ID_AA64ISAR1_EL1, 3, 0, 0, 6, 1) ++DEF(ID_AA64ISAR2_EL1, 3, 0, 0, 6, 2) ++DEF(ID_AA64MMFR0_EL1, 3, 0, 0, 7, 0) ++DEF(ID_AA64MMFR1_EL1, 3, 0, 0, 7, 1) ++DEF(ID_AA64MMFR2_EL1, 3, 0, 0, 7, 2) ++DEF(ID_AA64MMFR3_EL1, 3, 0, 0, 7, 3) ++DEF(ID_PFR0_EL1, 3, 0, 0, 1, 0) ++DEF(ID_PFR1_EL1, 3, 0, 0, 1, 1) ++DEF(ID_DFR0_EL1, 3, 0, 0, 1, 2) ++DEF(ID_MMFR0_EL1, 3, 0, 0, 1, 4) ++DEF(ID_MMFR1_EL1, 3, 0, 0, 1, 5) ++DEF(ID_MMFR2_EL1, 3, 0, 0, 1, 6) ++DEF(ID_MMFR3_EL1, 3, 0, 0, 1, 7) ++DEF(ID_ISAR0_EL1, 3, 0, 0, 2, 0) ++DEF(ID_ISAR1_EL1, 3, 0, 0, 2, 1) ++DEF(ID_ISAR2_EL1, 3, 0, 0, 2, 2) ++DEF(ID_ISAR3_EL1, 3, 0, 0, 2, 3) ++DEF(ID_ISAR4_EL1, 3, 0, 0, 2, 4) ++DEF(ID_ISAR5_EL1, 3, 0, 0, 2, 5) ++DEF(ID_MMFR4_EL1, 3, 0, 0, 2, 6) ++DEF(ID_ISAR6_EL1, 3, 0, 0, 2, 7) ++DEF(MVFR0_EL1, 3, 0, 0, 3, 0) ++DEF(MVFR1_EL1, 3, 0, 0, 3, 1) ++DEF(MVFR2_EL1, 3, 0, 0, 3, 2) ++DEF(ID_PFR2_EL1, 3, 0, 0, 3, 4) ++DEF(ID_DFR1_EL1, 3, 0, 0, 3, 5) ++DEF(ID_MMFR5_EL1, 3, 0, 0, 3, 6) ++DEF(ID_AA64ZFR0_EL1, 3, 0, 0, 4, 4) ++DEF(CTR_EL0, 3, 3, 0, 0, 1) +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index cb546a93e2..6933b1a73f 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -26,6 +26,7 @@ + #include "cpu-qom.h" + #include "exec/cpu-defs.h" + #include "qapi/qapi-types-common.h" ++#include "target/arm/cpu-sysregs.h" + + /* ARM processors have a weak memory model */ + #define TCG_GUEST_DEFAULT_MO (0) +@@ -845,6 +846,53 @@ typedef struct { + uint32_t map, init, supported; + } ARMVQMap; + ++/* REG is ID_XXX */ ++#define FIELD_DP64_IDREG(ISAR, REG, FIELD, VALUE) \ ++ ({ \ ++ ARMISARegisters *i_ = (ISAR); \ ++ uint64_t regval = i_->idregs[REG ## _EL1_IDX]; \ ++ regval = FIELD_DP64(regval, REG, FIELD, VALUE); \ ++ i_->idregs[REG ## _EL1_IDX] = regval; \ ++ }) ++ ++#define FIELD_DP32_IDREG(ISAR, REG, FIELD, VALUE) \ ++ ({ \ ++ ARMISARegisters *i_ = (ISAR); \ ++ uint64_t regval = i_->idregs[REG ## _EL1_IDX]; \ ++ regval = FIELD_DP32(regval, REG, FIELD, VALUE); \ ++ i_->idregs[REG ## _EL1_IDX] = regval; \ ++ }) ++ ++#define FIELD_EX64_IDREG(ISAR, REG, FIELD) \ ++ ({ \ ++ const ARMISARegisters *i_ = (ISAR); \ ++ FIELD_EX64(i_->idregs[REG ## _EL1_IDX], REG, FIELD); \ ++ }) ++ ++#define FIELD_EX32_IDREG(ISAR, REG, FIELD) \ ++ ({ \ ++ const ARMISARegisters *i_ = (ISAR); \ ++ FIELD_EX32(i_->idregs[REG ## _EL1_IDX], REG, FIELD); \ ++ }) ++ ++#define FIELD_SEX64_IDREG(ISAR, REG, FIELD) \ ++ ({ \ ++ const ARMISARegisters *i_ = (ISAR); \ ++ FIELD_SEX64(i_->idregs[REG ## _EL1_IDX], REG, FIELD); \ ++ }) ++ ++#define SET_IDREG(ISAR, REG, VALUE) \ ++ ({ \ ++ ARMISARegisters *i_ = (ISAR); \ ++ i_->idregs[REG ## _EL1_IDX] = VALUE; \ ++ }) ++ ++#define GET_IDREG(ISAR, REG) \ ++ ({ \ ++ const ARMISARegisters *i_ = (ISAR); \ ++ i_->idregs[REG ## _EL1_IDX]; \ ++ }) ++ + /** + * ARMCPU: + * @env: #CPUARMState +@@ -1047,6 +1095,7 @@ struct ArchCPU { + uint64_t id_aa64zfr0; + uint64_t id_aa64smfr0; + uint64_t reset_pmcr_el0; ++ uint64_t idregs[NUM_ID_IDX]; + } isar; + uint64_t midr; + uint32_t revidr; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 4cf8446b6e..20e49aa72a 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -35,6 +35,28 @@ + #include "cpu-features.h" + #include "cpregs.h" + ++/* convert between _IDX and SYS_ */ ++#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \ ++ [NAME##_IDX] = SYS_##NAME, ++ ++const uint32_t id_register_sysreg[NUM_ID_IDX] = { ++#include "cpu-sysregs.h.inc" ++}; ++ ++#undef DEF ++#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \ ++ case SYS_##NAME: return NAME##_IDX; ++ ++int get_sysreg_idx(ARMSysRegs sysreg) ++{ ++ switch (sysreg) { ++#include "cpu-sysregs.h.inc" ++ } ++ g_assert_not_reached(); ++} ++ ++#undef DEF ++ + void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) + { + /* +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Add-sysreg-generation-scripts.patch b/arm-cpu-Add-sysreg-generation-scripts.patch new file mode 100644 index 0000000000000000000000000000000000000000..1c317cea04e10aad55b18d9f87713ee20f0acd53 --- /dev/null +++ b/arm-cpu-Add-sysreg-generation-scripts.patch @@ -0,0 +1,123 @@ +From ce63c58400412a3f206e3bfb085c0a4f9322436f Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 12/26] arm/cpu: Add sysreg generation scripts + +Introduce scripts that automate the generation of system register +definitions from a given linux source tree arch/arm64/tools/sysreg. + +Invocation of +./update-aarch64-sysreg-code.sh $PATH_TO_LINUX_SOURCE_TREE +in scripts directory generates target/arm/cpu-sysregs.h.inc +containing defines for all system registers. + +[CH: update to handle current kernel sysregs structure, and to emit + the re-worked register structures; cpu properties will be added + later] +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + MAINTAINERS | 1 + + scripts/arm-gen-cpu-sysregs-header.awk | 37 ++++++++++++++++++++++++++ + scripts/update-aarch64-sysreg-code.sh | 32 ++++++++++++++++++++++ + 3 files changed, 70 insertions(+) + create mode 100755 scripts/arm-gen-cpu-sysregs-header.awk + create mode 100755 scripts/update-aarch64-sysreg-code.sh + +diff --git a/MAINTAINERS b/MAINTAINERS +index ada87bfa9e..73ae0ba448 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -459,6 +459,7 @@ M: Peter Maydell + L: qemu-arm@nongnu.org + S: Maintained + F: target/arm/kvm.c ++F: scripts/*-sysreg* + + MIPS KVM CPUs + M: Huacai Chen +diff --git a/scripts/arm-gen-cpu-sysregs-header.awk b/scripts/arm-gen-cpu-sysregs-header.awk +new file mode 100755 +index 0000000000..f92bbbafa7 +--- /dev/null ++++ b/scripts/arm-gen-cpu-sysregs-header.awk +@@ -0,0 +1,37 @@ ++#!/bin/awk -f ++# SPDX-License-Identifier: GPL-2.0-or-later ++# arm-gen-cpu-sysregs-header.awk: arm64 sysreg header include generator ++# ++# Usage: awk -f arm-gen-cpu-sysregs-header.awk $LINUX_PATH/arch/arm64/tools/sysreg ++ ++BEGIN { ++ print "/* SPDX-License-Identifier: GPL-2.0-or-later */" ++ print "/* GENERATED FILE, DO NOT EDIT */" ++ print "/* use arm-gen-cpu-sysregs-header.awk to regenerate */" ++} END { ++ print "" ++} ++ ++# skip blank lines and comment lines ++/^$/ { next } ++/^[\t ]*#/ { next } ++ ++/^Sysreg\t/ || /^Sysreg /{ ++ ++ reg = $2 ++ op0 = $3 ++ op1 = $4 ++ crn = $5 ++ crm = $6 ++ op2 = $7 ++ ++ if (op0 == 3 && (op1==0 || op1==1 || op1==3) && crn==0 && (crm>=0 && crm<=7) && (op2>=0 && op2<=7)) { ++ print "DEF("reg", "op0", "op1", "crn", "crm", "op2")" ++ } ++ next ++} ++ ++{ ++ /* skip all other lines */ ++ next ++} +diff --git a/scripts/update-aarch64-sysreg-code.sh b/scripts/update-aarch64-sysreg-code.sh +new file mode 100755 +index 0000000000..7bba0bcd6f +--- /dev/null ++++ b/scripts/update-aarch64-sysreg-code.sh +@@ -0,0 +1,32 @@ ++#!/bin/sh -e ++# ++# SPDX-License-Identifier: GPL-2.0-or-later ++# Update target/arm/cpu-sysregs.h ++# from a linux source tree (arch/arm64/tools/sysreg) ++# ++# Copyright Red Hat, Inc. 2024 ++# ++# Authors: ++# Eric Auger ++# ++ ++scripts="$(dirname "$0")" ++linux="$1" ++output="$2" ++ ++if [ -z "$linux" ] || ! [ -d "$linux" ]; then ++ cat << EOF ++usage: update-aarch64-sysreg-code.sh LINUX_PATH [OUTPUT_PATH] ++ ++LINUX_PATH Linux kernel directory to obtain the register definitions from ++OUTPUT_PATH output directory, usually the qemu source tree (default: $PWD) ++EOF ++ exit 1 ++fi ++ ++if [ -z "$output" ]; then ++ output="$PWD" ++fi ++ ++awk -f $scripts/arm-gen-cpu-sysregs-header.awk \ ++ $linux/arch/arm64/tools/sysreg > $output/target/arm/cpu-sysregs.h.inc +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Add-sysreg-properties-generation.patch b/arm-cpu-Add-sysreg-properties-generation.patch new file mode 100644 index 0000000000000000000000000000000000000000..96895351b54edee24b9aee806becb7866f842f2c --- /dev/null +++ b/arm-cpu-Add-sysreg-properties-generation.patch @@ -0,0 +1,385 @@ +From 6c5df2e2647b9178b35fa5d39a83d3f44cc41534 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 16/26] arm/cpu: Add sysreg properties generation + +Introduce a script that automates the generation of system register +properties definitions from a given linux source tree +arch/arm64/tools/sysreg. + +Invocation of +./update-aarch64-sysreg-code.sh $PATH_TO_LINUX_SOURCE_TREE +in scripts directory additionally generates +target/arm/cpu-sysreg-properties.c containing definitions for +feature ID registers. + +update-aarch64-sysreg-code.sh additionally calls +gen-cpu-sysreg-properties.awk which is inherited from kernel +arch/arm64/tools/gen-sysreg.awk. All credits to Mark Rutland +the original author of this script. + +[CH: split off from original patch adding both sysreg definitions + and properties] +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + scripts/gen-cpu-sysreg-properties.awk | 325 ++++++++++++++++++++++++++ + scripts/update-aarch64-sysreg-code.sh | 5 +- + 2 files changed, 329 insertions(+), 1 deletion(-) + create mode 100755 scripts/gen-cpu-sysreg-properties.awk + +diff --git a/scripts/gen-cpu-sysreg-properties.awk b/scripts/gen-cpu-sysreg-properties.awk +new file mode 100755 +index 0000000000..da00d377ff +--- /dev/null ++++ b/scripts/gen-cpu-sysreg-properties.awk +@@ -0,0 +1,325 @@ ++#!/bin/awk -f ++# SPDX-License-Identifier: GPL-2.0 ++# gen-cpu-sysreg-properties.awk: arm64 sysreg header generator ++# ++# Usage: awk -f gen-cpu-sysreg-properties.awk $LINUX_PATH/arch/arm64/tools/sysreg ++ ++function block_current() { ++ return __current_block[__current_block_depth]; ++} ++ ++# Log an error and terminate ++function fatal(msg) { ++ print "Error at " NR ": " msg > "/dev/stderr" ++ ++ printf "Current block nesting:" ++ ++ for (i = 0; i <= __current_block_depth; i++) { ++ printf " " __current_block[i] ++ } ++ printf "\n" ++ ++ exit 1 ++} ++ ++# Enter a new block, setting the active block to @block ++function block_push(block) { ++ __current_block[++__current_block_depth] = block ++} ++ ++# Exit a block, setting the active block to the parent block ++function block_pop() { ++ if (__current_block_depth == 0) ++ fatal("error: block_pop() in root block") ++ ++ __current_block_depth--; ++} ++ ++# Sanity check the number of records for a field makes sense. If not, produce ++# an error and terminate. ++function expect_fields(nf) { ++ if (NF != nf) ++ fatal(NF " fields found where " nf " expected") ++} ++ ++# Print a CPP macro definition, padded with spaces so that the macro bodies ++# line up in a column ++function define(name, val) { ++ printf "%-56s%s\n", "#define " name, val ++} ++ ++# Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field ++function define_field(reg, field, msb, lsb, idreg) { ++ if (idreg) ++ print " arm64_sysreg_add_field("reg", \""field"\", "lsb", "msb");" ++} ++ ++# Print a field _SIGNED definition for a field ++function define_field_sign(reg, field, sign, idreg) { ++ if (idreg) ++ print " arm64_sysreg_add_field("reg", \""field"\", "lsb", "msb");" ++} ++ ++# Parse a "[:]" string into the global variables @msb and @lsb ++function parse_bitdef(reg, field, bitdef, _bits) ++{ ++ if (bitdef ~ /^[0-9]+$/) { ++ msb = bitdef ++ lsb = bitdef ++ } else if (split(bitdef, _bits, ":") == 2) { ++ msb = _bits[1] ++ lsb = _bits[2] ++ } else { ++ fatal("invalid bit-range definition '" bitdef "'") ++ } ++ ++ ++ if (msb != next_bit) ++ fatal(reg "." field " starts at " msb " not " next_bit) ++ if (63 < msb || msb < 0) ++ fatal(reg "." field " invalid high bit in '" bitdef "'") ++ if (63 < lsb || lsb < 0) ++ fatal(reg "." field " invalid low bit in '" bitdef "'") ++ if (msb < lsb) ++ fatal(reg "." field " invalid bit-range '" bitdef "'") ++ if (low > high) ++ fatal(reg "." field " has invalid range " high "-" low) ++ ++ next_bit = lsb - 1 ++} ++ ++BEGIN { ++ print "#include \"cpu-custom.h\"" ++ print "" ++ print "ARM64SysReg arm64_id_regs[NUM_ID_IDX];" ++ print "" ++ print "void initialize_cpu_sysreg_properties(void)" ++ print "{" ++ print " memset(arm64_id_regs, 0, sizeof(ARM64SysReg) * NUM_ID_IDX);" ++ print "" ++ ++ __current_block_depth = 0 ++ __current_block[__current_block_depth] = "Root" ++} ++ ++END { ++ if (__current_block_depth != 0) ++ fatal("Missing terminator for " block_current() " block") ++ ++ print "}" ++} ++ ++# skip blank lines and comment lines ++/^$/ { next } ++/^[\t ]*#/ { next } ++ ++/^SysregFields/ && block_current() == "Root" { ++ block_push("SysregFields") ++ ++ expect_fields(2) ++ ++ reg = $2 ++ ++ res0 = "UL(0)" ++ res1 = "UL(0)" ++ unkn = "UL(0)" ++ ++ next_bit = 63 ++ ++ next ++} ++ ++/^EndSysregFields/ && block_current() == "SysregFields" { ++ if (next_bit > 0) ++ fatal("Unspecified bits in " reg) ++ ++ reg = null ++ res0 = null ++ res1 = null ++ unkn = null ++ ++ block_pop() ++ next ++} ++ ++/^Sysreg/ && block_current() == "Root" { ++ block_push("Sysreg") ++ ++ expect_fields(7) ++ ++ reg = $2 ++ op0 = $3 ++ op1 = $4 ++ crn = $5 ++ crm = $6 ++ op2 = $7 ++ ++ res0 = "UL(0)" ++ res1 = "UL(0)" ++ unkn = "UL(0)" ++ ++ if (op0 == 3 && (op1<2 || op1==3) && crn==0 && (crm>=0 && crm<=7) && (op2>=0 && op2<=7)) { ++ idreg = 1 ++ } else { ++ idreg = 0 ++ } ++ ++ if (idreg == 1) { ++ print " /* "reg" */" ++ print " ARM64SysReg *"reg" = arm64_sysreg_get("reg"_IDX);" ++ print " "reg"->name = \""reg"\";" ++ } ++ ++ next_bit = 63 ++ ++ next ++} ++ ++/^EndSysreg/ && block_current() == "Sysreg" { ++ if (next_bit > 0) ++ fatal("Unspecified bits in " reg) ++ ++ reg = null ++ op0 = null ++ op1 = null ++ crn = null ++ crm = null ++ op2 = null ++ res0 = null ++ res1 = null ++ unkn = null ++ ++ if (idreg==1) ++ print "" ++ block_pop() ++ next ++} ++ ++# Currently this is effectivey a comment, in future we may want to emit ++# defines for the fields. ++(/^Fields/ || /^Mapping/) && block_current() == "Sysreg" { ++ expect_fields(2) ++ ++ if (next_bit != 63) ++ fatal("Some fields already defined for " reg) ++ ++ print "/* For " reg " fields see " $2 " */" ++ print "" ++ ++ next_bit = 0 ++ res0 = null ++ res1 = null ++ unkn = null ++ ++ next ++} ++ ++ ++/^Res0/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { ++ expect_fields(2) ++ parse_bitdef(reg, "RES0", $2) ++ field = "RES0_" msb "_" lsb ++ ++ res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")" ++ ++ next ++} ++ ++/^Res1/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { ++ expect_fields(2) ++ parse_bitdef(reg, "RES1", $2) ++ field = "RES1_" msb "_" lsb ++ ++ res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")" ++ ++ next ++} ++ ++/^Unkn/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { ++ expect_fields(2) ++ parse_bitdef(reg, "UNKN", $2) ++ field = "UNKN_" msb "_" lsb ++ ++ unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")" ++ ++ next ++} ++ ++/^Field/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { ++ expect_fields(3) ++ field = $3 ++ parse_bitdef(reg, field, $2) ++ ++ ++ define_field(reg, field, msb, lsb, idreg) ++ ++ next ++} ++ ++/^Raz/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { ++ expect_fields(2) ++ parse_bitdef(reg, field, $2) ++ ++ next ++} ++ ++/^SignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { ++ block_push("Enum") ++ ++ expect_fields(3) ++ field = $3 ++ parse_bitdef(reg, field, $2) ++ ++ define_field(reg, field, msb, lsb, idreg) ++ define_field_sign(reg, field, "true", idreg) ++ ++ next ++} ++ ++/^UnsignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { ++ block_push("Enum") ++ ++ expect_fields(3) ++ field = $3 ++ parse_bitdef(reg, field, $2) ++ ++ define_field(reg, field, msb, lsb, idreg) ++ #define_field_sign(reg, field, "false", idreg) ++ ++ next ++} ++ ++/^Enum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { ++ block_push("Enum") ++ ++ expect_fields(3) ++ field = $3 ++ parse_bitdef(reg, field, $2) ++ ++ define_field(reg, field, msb, lsb, idreg) ++ ++ next ++} ++ ++/^EndEnum/ && block_current() == "Enum" { ++ ++ field = null ++ msb = null ++ lsb = null ++ ++ block_pop() ++ next ++} ++ ++/0b[01]+/ && block_current() == "Enum" { ++ expect_fields(2) ++ val = $1 ++ name = $2 ++ ++ next ++} ++ ++# Any lines not handled by previous rules are unexpected ++{ ++ fatal("unhandled statement") ++} +diff --git a/scripts/update-aarch64-sysreg-code.sh b/scripts/update-aarch64-sysreg-code.sh +index 7bba0bcd6f..764c63a9cc 100755 +--- a/scripts/update-aarch64-sysreg-code.sh ++++ b/scripts/update-aarch64-sysreg-code.sh +@@ -1,7 +1,7 @@ + #!/bin/sh -e + # + # SPDX-License-Identifier: GPL-2.0-or-later +-# Update target/arm/cpu-sysregs.h ++# Update target/arm/cpu-sysreg-properties.c and target/arm/cpu-sysregs.h + # from a linux source tree (arch/arm64/tools/sysreg) + # + # Copyright Red Hat, Inc. 2024 +@@ -30,3 +30,6 @@ fi + + awk -f $scripts/arm-gen-cpu-sysregs-header.awk \ + $linux/arch/arm64/tools/sysreg > $output/target/arm/cpu-sysregs.h.inc ++ ++awk -f $scripts/gen-cpu-sysreg-properties.awk \ ++ $linux/arch/arm64/tools/sysreg > $output/target/arm/cpu-sysreg-properties.c +\ No newline at end of file +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Store-aa64dfr0-1-into-the-idregs-array.patch b/arm-cpu-Store-aa64dfr0-1-into-the-idregs-array.patch new file mode 100644 index 0000000000000000000000000000000000000000..ec66b59987eaf1e744a2b2f82c6de8ca39ca0192 --- /dev/null +++ b/arm-cpu-Store-aa64dfr0-1-into-the-idregs-array.patch @@ -0,0 +1,430 @@ +From da581f393d2d7379cc0850ed7a9f2a7fa48c8186 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:47 +0800 +Subject: [PATCH 06/26] arm/cpu: Store aa64dfr0/1 into the idregs array + +Reviewed-by: Richard Henderson +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu-features.h | 16 ++++++++-------- + target/arm/cpu.c | 15 +++++---------- + target/arm/cpu.h | 2 -- + target/arm/cpu64.c | 16 ++++++++-------- + target/arm/helper.c | 4 ++-- + target/arm/hvf/hvf.c | 4 ++-- + target/arm/internals.h | 6 +++--- + target/arm/kvm-rme.c | 5 +++-- + target/arm/kvm.c | 2 +- + target/arm/kvm64.c | 12 +++++------- + target/arm/tcg/cpu64.c | 32 ++++++++++++++++---------------- + 11 files changed, 53 insertions(+), 61 deletions(-) + +diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h +index aefde4b057..eea88ea681 100644 +--- a/target/arm/cpu-features.h ++++ b/target/arm/cpu-features.h +@@ -842,30 +842,30 @@ static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id) + + static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 && +- FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; ++ return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 4 && ++ FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf; + } + + static inline bool isar_feature_aa64_pmuv3p4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 && +- FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; ++ return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 5 && ++ FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf; + } + + static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 6 && +- FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; ++ return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 6 && ++ FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf; + } + + static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8; ++ return FIELD_EX64_IDREG(id, ID_AA64DFR0, DEBUGVER) >= 8; + } + + static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id) + { +- return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0; ++ return FIELD_SEX64_IDREG(id, ID_AA64DFR0, DOUBLELOCK) >= 0; + } + + static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id) +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 7ac964b550..22c3335522 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2180,8 +2180,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + cpu); + #endif + } else { +- cpu->isar.id_aa64dfr0 = +- FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMUVER, 0); ++ FIELD_DP64_IDREG(isar, ID_AA64DFR0, PMUVER, 0); + cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0); + cpu->pmceid0 = 0; + cpu->pmceid1 = 0; +@@ -2226,19 +2225,15 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + * try to access the non-existent system registers for them. + */ + /* FEAT_SPE (Statistical Profiling Extension) */ +- cpu->isar.id_aa64dfr0 = +- FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMSVER, 0); ++ FIELD_DP64_IDREG(isar, ID_AA64DFR0, PMSVER, 0); + /* FEAT_TRBE (Trace Buffer Extension) */ +- cpu->isar.id_aa64dfr0 = +- FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEBUFFER, 0); ++ FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEBUFFER, 0); + /* FEAT_TRF (Self-hosted Trace Extension) */ +- cpu->isar.id_aa64dfr0 = +- FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEFILT, 0); ++ FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEFILT, 0); + cpu->isar.id_dfr0 = + FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, TRACEFILT, 0); + /* Trace Macrocell system register access */ +- cpu->isar.id_aa64dfr0 = +- FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEVER, 0); ++ FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEVER, 0); + cpu->isar.id_dfr0 = + FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPTRC, 0); + /* Memory mapped trace */ +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 3ef3a6f958..be5587411f 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1082,8 +1082,6 @@ struct ArchCPU { + uint32_t dbgdidr; + uint32_t dbgdevid; + uint32_t dbgdevid1; +- uint64_t id_aa64dfr0; +- uint64_t id_aa64dfr1; + uint64_t id_aa64smfr0; + uint64_t reset_pmcr_el0; + uint64_t idregs[NUM_ID_IDX]; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index f980f1efd2..3a7a8861cf 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -602,7 +602,7 @@ static void arm_cpu_get_num_wps(Object *obj, Visitor *v, const char *name, + + val = cpu->num_wps; + if (val == 0) { +- val = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1; ++ val = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, WRPS) + 1; + } + + visit_type_uint8(v, name, &val, errp); +@@ -613,7 +613,7 @@ static void arm_cpu_set_num_wps(Object *obj, Visitor *v, const char *name, + { + uint8_t val; + ARMCPU *cpu = ARM_CPU(obj); +- uint8_t max_wps = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1; ++ uint8_t max_wps = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, WRPS) + 1; + + if (!visit_type_uint8(v, name, &val, errp)) { + return; +@@ -635,7 +635,7 @@ static void arm_cpu_get_num_bps(Object *obj, Visitor *v, const char *name, + + val = cpu->num_bps; + if (val == 0) { +- val = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1; ++ val = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, BRPS) + 1; + } + + visit_type_uint8(v, name, &val, errp); +@@ -646,7 +646,7 @@ static void arm_cpu_set_num_bps(Object *obj, Visitor *v, const char *name, + { + uint8_t val; + ARMCPU *cpu = ARM_CPU(obj); +- uint8_t max_bps = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1; ++ uint8_t max_bps = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, BRPS) + 1; + + if (!visit_type_uint8(v, name, &val, errp)) { + return; +@@ -769,7 +769,7 @@ static void aarch64_a57_initfn(Object *obj) + cpu->isar.id_isar5 = 0x00011121; + cpu->isar.id_isar6 = 0; + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); +- cpu->isar.id_aa64dfr0 = 0x10305106; ++ SET_IDREG(isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + SET_IDREG(isar, ID_AA64MMFR0, 0x00001124); + cpu->isar.dbgdidr = 0x3516d000; +@@ -827,7 +827,7 @@ static void aarch64_a53_initfn(Object *obj) + cpu->isar.id_isar5 = 0x00011121; + cpu->isar.id_isar6 = 0; + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); +- cpu->isar.id_aa64dfr0 = 0x10305106; ++ SET_IDREG(isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + SET_IDREG(isar, ID_AA64MMFR0, 0x00001122); /* 40 bit physical addr */ + cpu->isar.dbgdidr = 0x3516d000; +@@ -883,7 +883,7 @@ static void aarch64_a72_initfn(Object *obj) + cpu->isar.id_isar4 = 0x00011142; + cpu->isar.id_isar5 = 0x00011121; + SET_IDREG(&cpu->isar, ID_AA64PFR0, 0x00002222); +- cpu->isar.id_aa64dfr0 = 0x10305106; ++ SET_IDREG(&cpu->isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0x00011120); + SET_IDREG(&cpu->isar, ID_AA64MMFR0, 0x00001124); + cpu->isar.dbgdidr = 0x3516d000; +@@ -912,7 +912,7 @@ static void aarch64_kunpeng_920_initfn(Object *obj) + cpu->midr = 0x480fd010; + cpu->ctr = 0x84448004; + SET_IDREG(&cpu->isar, ID_AA64PFR0, 0x11001111); +- cpu->isar.id_aa64dfr0 = 0x110305408; ++ SET_IDREG(&cpu->isar, ID_AA64DFR0, 0x110305408); + SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0x10211120); + SET_IDREG(&cpu->isar, ID_AA64MMFR0, 0x101125); + } +diff --git a/target/arm/helper.c b/target/arm/helper.c +index a44c13b2b0..46f0b4089b 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -8415,12 +8415,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64dfr0 }, ++ .resetvalue = GET_IDREG(isar, ID_AA64DFR0) }, + { .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64dfr1 }, ++ .resetvalue = GET_IDREG(isar, ID_AA64DFR1) }, + { .name = "ID_AA64DFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, +diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c +index 7bf5276484..13d72b0bd6 100644 +--- a/target/arm/hvf/hvf.c ++++ b/target/arm/hvf/hvf.c +@@ -844,8 +844,8 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + } regs[] = { + { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.idregs[ID_AA64PFR0_EL1_IDX] }, + { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.idregs[ID_AA64PFR1_EL1_IDX] }, +- { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 }, +- { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 }, ++ { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.idregs[ID_AA64DFR0_EL1_IDX] }, ++ { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.idregs[ID_AA64DFR1_EL1_IDX] }, + { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.idregs[ID_AA64ISAR0_EL1_IDX] }, + { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.idregs[ID_AA64ISAR1_EL1_IDX] }, + /* Add ID_AA64ISAR2_EL1 here when HVF supports it */ +diff --git a/target/arm/internals.h b/target/arm/internals.h +index efc58c7146..dc0c5d9051 100644 +--- a/target/arm/internals.h ++++ b/target/arm/internals.h +@@ -831,7 +831,7 @@ static inline bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx) + static inline int arm_num_brps(ARMCPU *cpu) + { + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { +- return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1; ++ return FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, BRPS) + 1; + } else { + return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, BRPS) + 1; + } +@@ -845,7 +845,7 @@ static inline int arm_num_brps(ARMCPU *cpu) + static inline int arm_num_wrps(ARMCPU *cpu) + { + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { +- return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1; ++ return FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, WRPS) + 1; + } else { + return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, WRPS) + 1; + } +@@ -859,7 +859,7 @@ static inline int arm_num_wrps(ARMCPU *cpu) + static inline int arm_num_ctx_cmps(ARMCPU *cpu) + { + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { +- return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1; ++ return FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, CTX_CMPS) + 1; + } else { + return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, CTX_CMPS) + 1; + } +diff --git a/target/arm/kvm-rme.c b/target/arm/kvm-rme.c +index 26dda39df6..43ff825425 100644 +--- a/target/arm/kvm-rme.c ++++ b/target/arm/kvm-rme.c +@@ -267,8 +267,9 @@ static int rme_log_realm_create(Error **errp) + params.flags |= REALM_PARAMS_FLAG_SVE; + params.sve_vl = cpu->sve_max_vq - 1; + } +- params.num_bps = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS); +- params.num_wps = FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS); ++ ++ params.num_bps = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, BRPS); ++ params.num_wps = FIELD_EX64_IDREG(&cpu->isar, ID_AA64DFR0, WRPS); + + switch (rme_guest->measurement_algo) { + case RME_GUEST_MEASUREMENT_ALGORITHM_SHA256: +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 13679c7c18..c6c92c120f 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -696,7 +696,7 @@ static void kvm_arm_configure_aa64dfr0(ARMCPU *cpu) + return; + } + +- newval = cpu->isar.id_aa64dfr0; ++ newval = GET_IDREG(&cpu->isar, ID_AA64DFR0); + if (cpu->num_bps) { + uint64_t ctx_cmps = FIELD_EX64(newval, ID_AA64DFR0, CTX_CMPS); + +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 1d0dc2e2b3..e46afd00bb 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -358,10 +358,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + err |= get_host_cpu_reg(fd, ahcf, ID_AA64PFR1_EL1_IDX); + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64smfr0, + ARM64_SYS_REG(3, 0, 0, 4, 5)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0, +- KVM_REG_ARM_ID_AA64DFR0_EL1); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1, +- ARM64_SYS_REG(3, 0, 0, 5, 1)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_AA64DFR0_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_AA64DFR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR2_EL1_IDX); +@@ -431,10 +429,10 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * We only do this if the CPU supports AArch32 at EL1. + */ + if (FIELD_EX32_IDREG(&ahcf->isar, ID_AA64PFR0, EL1) >= 2) { +- int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS); +- int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS); ++ int wrps = FIELD_EX64_IDREG(&ahcf->isar, ID_AA64DFR0, WRPS); ++ int brps = FIELD_EX64_IDREG(&ahcf->isar, ID_AA64DFR0, BRPS); + int ctx_cmps = +- FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS); ++ FIELD_EX64_IDREG(&ahcf->isar, ID_AA64DFR0, CTX_CMPS); + int version = 6; /* ARMv8 debug architecture */ + bool has_el3 = + !!FIELD_EX32_IDREG(&ahcf->isar, ID_AA64PFR0, EL3); +diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c +index 4805af8409..b0a020c14e 100644 +--- a/target/arm/tcg/cpu64.c ++++ b/target/arm/tcg/cpu64.c +@@ -90,8 +90,8 @@ static void aarch64_a35_initfn(Object *obj) + cpu->isar.id_isar5 = 0x00011121; + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + SET_IDREG(isar, ID_AA64PFR1, 0); +- cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64dfr1 = 0; ++ SET_IDREG(isar, ID_AA64DFR0, 0x10305106); ++ SET_IDREG(isar, ID_AA64DFR1, 0); + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + SET_IDREG(isar, ID_AA64ISAR1, 0); + SET_IDREG(isar, ID_AA64MMFR0, 0x00101122); +@@ -240,7 +240,7 @@ static void aarch64_a55_initfn(Object *obj) + cpu->clidr = 0x82000023; + cpu->ctr = 0x84448004; /* L1Ip = VIPT */ + cpu->dcz_blocksize = 4; /* 64 bytes */ +- cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; ++ SET_IDREG(isar, ID_AA64DFR0, 0x0000000010305408ull); + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); + SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000101122ull); +@@ -327,7 +327,7 @@ static void aarch64_a72_initfn(Object *obj) + cpu->isar.id_isar4 = 0x00011142; + cpu->isar.id_isar5 = 0x00011121; + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); +- cpu->isar.id_aa64dfr0 = 0x10305106; ++ SET_IDREG(isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + SET_IDREG(isar, ID_AA64MMFR0, 0x00001124); + cpu->isar.dbgdidr = 0x3516d000; +@@ -365,7 +365,7 @@ static void aarch64_a76_initfn(Object *obj) + cpu->clidr = 0x82000023; + cpu->ctr = 0x8444C004; + cpu->dcz_blocksize = 4; +- cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; ++ SET_IDREG(isar, ID_AA64DFR0, 0x0000000010305408ull), + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); + SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000101122ull); +@@ -435,8 +435,8 @@ static void aarch64_a64fx_initfn(Object *obj) + cpu->reset_sctlr = 0x30000180; + SET_IDREG(isar, ID_AA64PFR0, 0x0000000101111111); /* No RAS Extensions */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000000); +- cpu->isar.id_aa64dfr0 = 0x0000000010305408; +- cpu->isar.id_aa64dfr1 = 0x0000000000000000; ++ SET_IDREG(isar, ID_AA64DFR0, 0x0000000010305408), ++ SET_IDREG(isar, ID_AA64DFR1, 0x0000000000000000), + cpu->id_aa64afr0 = 0x0000000000000000; + cpu->id_aa64afr1 = 0x0000000000000000; + SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000001122); +@@ -605,7 +605,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj) + cpu->clidr = 0x82000023; + cpu->ctr = 0x8444c004; + cpu->dcz_blocksize = 4; +- cpu->isar.id_aa64dfr0 = 0x0000000110305408ull; ++ SET_IDREG(isar, ID_AA64DFR0, 0x0000000110305408ull); + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); + SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000101125ull); +@@ -679,8 +679,8 @@ static void aarch64_neoverse_v1_initfn(Object *obj) + cpu->dcz_blocksize = 4; + cpu->id_aa64afr0 = 0x00000000; + cpu->id_aa64afr1 = 0x00000000; +- cpu->isar.id_aa64dfr0 = 0x000001f210305519ull; +- cpu->isar.id_aa64dfr1 = 0x00000000; ++ SET_IDREG(isar, ID_AA64DFR0, 0x000001f210305519ull), ++ SET_IDREG(isar, ID_AA64DFR1, 0x00000000), + SET_IDREG(isar, ID_AA64ISAR0, 0x1011111110212120ull); /* with FEAT_RNG */ + SET_IDREG(&cpu->isar, ID_AA64ISAR1, 0x0111000001211032ull); + SET_IDREG(&cpu->isar, ID_AA64MMFR0, 0x0000000000101125ull); +@@ -922,8 +922,8 @@ static void aarch64_a710_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000221ull); + SET_IDREG(isar, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */ +- cpu->isar.id_aa64dfr0 = 0x000011f010305619ull; +- cpu->isar.id_aa64dfr1 = 0; ++ SET_IDREG(isar, ID_AA64DFR0, 0x000011f010305619ull); ++ SET_IDREG(isar, ID_AA64DFR1, 0); + cpu->id_aa64afr0 = 0; + cpu->id_aa64afr1 = 0; + SET_IDREG(isar, ID_AA64ISAR0, 0x0221111110212120ull); /* with Crypto */ +@@ -1020,8 +1020,8 @@ static void aarch64_neoverse_n2_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000221ull); + SET_IDREG(isar, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */ +- cpu->isar.id_aa64dfr0 = 0x000011f210305619ull; +- cpu->isar.id_aa64dfr1 = 0; ++ SET_IDREG(isar, ID_AA64DFR0, 0x000011f210305619ull); ++ SET_IDREG(isar, ID_AA64DFR1, 0); + cpu->id_aa64afr0 = 0; + cpu->id_aa64afr1 = 0; + SET_IDREG(isar, ID_AA64ISAR0, 0x1221111110212120ull); /* with Crypto and FEAT_RNG */ +@@ -1223,11 +1223,11 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1); /* FEAT_F64MM */ + SET_IDREG(isar, ID_AA64ZFR0, t); + +- t = cpu->isar.id_aa64dfr0; ++ t = GET_IDREG(isar, ID_AA64DFR0); + t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 9); /* FEAT_Debugv8p4 */ + t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 6); /* FEAT_PMUv3p5 */ + t = FIELD_DP64(t, ID_AA64DFR0, HPMN0, 1); /* FEAT_HPMN0 */ +- cpu->isar.id_aa64dfr0 = t; ++ SET_IDREG(isar, ID_AA64DFR0, t); + + t = cpu->isar.id_aa64smfr0; + t = FIELD_DP64(t, ID_AA64SMFR0, F32F32, 1); /* FEAT_SME */ +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Store-aa64isar0-aa64zfr0-into-the-idregs-arr.patch b/arm-cpu-Store-aa64isar0-aa64zfr0-into-the-idregs-arr.patch new file mode 100644 index 0000000000000000000000000000000000000000..19f5a4902422742eb3c897045941c883de4e3962 --- /dev/null +++ b/arm-cpu-Store-aa64isar0-aa64zfr0-into-the-idregs-arr.patch @@ -0,0 +1,710 @@ +From ed6851b867dd3184eb2f978e83273d41f89784d0 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:47 +0800 +Subject: [PATCH 02/26] arm/cpu: Store aa64isar0/aa64zfr0 into the idregs + arrays + +Also add kvm accessors for storing host features into idregs. + +Reviewed-by: Richard Henderson +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu-features.h | 57 ++++++++++++++++++++------------------- + target/arm/cpu-sysregs.h | 4 +++ + target/arm/cpu.c | 9 +++---- + target/arm/cpu.h | 2 -- + target/arm/cpu64.c | 12 +++++---- + target/arm/helper.c | 6 +++-- + target/arm/hvf/hvf.c | 3 ++- + target/arm/kvm.c | 1 + + target/arm/kvm64.c | 29 +++++++++++++++++--- + target/arm/tcg/cpu64.c | 44 ++++++++++++++++++------------ + 10 files changed, 103 insertions(+), 64 deletions(-) + +diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h +index 165a497f7b..b9ece5f03a 100644 +--- a/target/arm/cpu-features.h ++++ b/target/arm/cpu-features.h +@@ -20,6 +20,7 @@ + #ifndef TARGET_ARM_FEATURES_H + #define TARGET_ARM_FEATURES_H + ++#include "cpu-sysregs.h" + /* + * Naming convention for isar_feature functions: + * Functions which test 32-bit ID registers should have _aa32_ in +@@ -373,92 +374,92 @@ static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id) + */ + static inline bool isar_feature_aa64_aes(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, AES) != 0; + } + + static inline bool isar_feature_aa64_pmull(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) > 1; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, AES) > 1; + } + + static inline bool isar_feature_aa64_sha1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA1) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA1) != 0; + } + + static inline bool isar_feature_aa64_sha256(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA2) != 0; + } + + static inline bool isar_feature_aa64_sha512(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) > 1; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA2) > 1; + } + + static inline bool isar_feature_aa64_crc32(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, CRC32) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, CRC32) != 0; + } + + static inline bool isar_feature_aa64_atomics(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, ATOMIC) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, ATOMIC) != 0; + } + + static inline bool isar_feature_aa64_rdm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RDM) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, RDM) != 0; + } + + static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA3) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA3) != 0; + } + + static inline bool isar_feature_aa64_sm3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM3) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SM3) != 0; + } + + static inline bool isar_feature_aa64_sm4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM4) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SM4) != 0; + } + + static inline bool isar_feature_aa64_dp(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, DP) != 0; + } + + static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, FHM) != 0; + } + + static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TS) != 0; + } + + static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TS) >= 2; + } + + static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RNDR) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, RNDR) != 0; + } + + static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TLB) == 2; + } + + static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TLB) != 0; + } + + static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) +@@ -869,52 +870,52 @@ static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id) + + static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SVEVER) != 0; + } + + static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ZFR0, AES) != 0; + } + + static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64ZFR0, AES) >= 2; + } + + static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BITPERM) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ZFR0, BITPERM) != 0; + } + + static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BFLOAT16) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ZFR0, BFLOAT16) != 0; + } + + static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SHA3) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SHA3) != 0; + } + + static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SM4) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SM4) != 0; + } + + static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, I8MM) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ZFR0, I8MM) != 0; + } + + static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F32MM) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ZFR0, F32MM) != 0; + } + + static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F64MM) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ZFR0, F64MM) != 0; + } + + static inline bool isar_feature_aa64_sme_f64f64(const ARMISARegisters *id) +diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h +index 7877a3b06a..e89a110590 100644 +--- a/target/arm/cpu-sysregs.h ++++ b/target/arm/cpu-sysregs.h +@@ -39,4 +39,8 @@ extern const uint32_t id_register_sysreg[NUM_ID_IDX]; + + int get_sysreg_idx(ARMSysRegs sysreg); + ++#ifdef CONFIG_KVM ++uint64_t idregs_sysreg_to_kvm_reg(ARMSysRegs sysreg); ++#endif ++ + #endif /* ARM_CPU_SYSREGS_H */ +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 3de2e1a3c3..262c5017d2 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1815,6 +1815,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + { + CPUState *cs = CPU(dev); + ARMCPU *cpu = ARM_CPU(dev); ++ ARMISARegisters *isar = &cpu->isar; + ARMCPUClass *acc = ARM_CPU_GET_CLASS(dev); + CPUARMState *env = &cpu->env; + int pagebits; +@@ -2008,7 +2009,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + + unset_feature(env, ARM_FEATURE_NEON); + +- t = cpu->isar.id_aa64isar0; ++ t = GET_IDREG(isar, ID_AA64ISAR0); + t = FIELD_DP64(t, ID_AA64ISAR0, AES, 0); + t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 0); + t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 0); +@@ -2016,7 +2017,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 0); + t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 0); + t = FIELD_DP64(t, ID_AA64ISAR0, DP, 0); +- cpu->isar.id_aa64isar0 = t; ++ SET_IDREG(isar, ID_AA64ISAR0, t); + + t = cpu->isar.id_aa64isar1; + t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0); +@@ -2061,9 +2062,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + uint64_t t; + uint32_t u; + +- t = cpu->isar.id_aa64isar0; +- t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 0); +- cpu->isar.id_aa64isar0 = t; ++ FIELD_DP64_IDREG(isar, ID_AA64ISAR0, FHM, 0); + + t = cpu->isar.id_aa64isar1; + t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 0); +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 6933b1a73f..b6e988e570 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1082,7 +1082,6 @@ struct ArchCPU { + uint32_t dbgdidr; + uint32_t dbgdevid; + uint32_t dbgdevid1; +- uint64_t id_aa64isar0; + uint64_t id_aa64isar1; + uint64_t id_aa64isar2; + uint64_t id_aa64pfr0; +@@ -1092,7 +1091,6 @@ struct ArchCPU { + uint64_t id_aa64mmfr2; + uint64_t id_aa64dfr0; + uint64_t id_aa64dfr1; +- uint64_t id_aa64zfr0; + uint64_t id_aa64smfr0; + uint64_t reset_pmcr_el0; + uint64_t idregs[NUM_ID_IDX]; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 20e49aa72a..4d31d34591 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -136,7 +136,7 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) + * SVE is disabled and so are all vector lengths. Good. + * Disable all SVE extensions as well. + */ +- cpu->isar.id_aa64zfr0 = 0; ++ SET_IDREG(&cpu->isar, ID_AA64ZFR0, 0); + return; + } + +@@ -738,6 +738,7 @@ void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp) + static void aarch64_a57_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,cortex-a57"; + set_feature(&cpu->env, ARM_FEATURE_V8); +@@ -774,7 +775,7 @@ static void aarch64_a57_initfn(Object *obj) + cpu->isar.id_isar6 = 0; + cpu->isar.id_aa64pfr0 = 0x00002222; + cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; ++ SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + cpu->isar.id_aa64mmfr0 = 0x00001124; + cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.dbgdevid = 0x01110f13; +@@ -795,6 +796,7 @@ static void aarch64_a57_initfn(Object *obj) + static void aarch64_a53_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,cortex-a53"; + set_feature(&cpu->env, ARM_FEATURE_V8); +@@ -831,7 +833,7 @@ static void aarch64_a53_initfn(Object *obj) + cpu->isar.id_isar6 = 0; + cpu->isar.id_aa64pfr0 = 0x00002222; + cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; ++ SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ + cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.dbgdevid = 0x00110f13; +@@ -887,7 +889,7 @@ static void aarch64_a72_initfn(Object *obj) + cpu->isar.id_isar5 = 0x00011121; + cpu->isar.id_aa64pfr0 = 0x00002222; + cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; ++ SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0x00011120); + cpu->isar.id_aa64mmfr0 = 0x00001124; + cpu->isar.dbgdidr = 0x3516d000; + cpu->clidr = 0x0a200023; +@@ -916,7 +918,7 @@ static void aarch64_kunpeng_920_initfn(Object *obj) + cpu->ctr = 0x84448004; + cpu->isar.id_aa64pfr0 = 0x11001111; + cpu->isar.id_aa64dfr0 = 0x110305408; +- cpu->isar.id_aa64isar0 = 0x10211120; ++ SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0x10211120); + cpu->isar.id_aa64mmfr0 = 0x101125; + } + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 0370a739e3..02c0033712 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -8202,6 +8202,8 @@ void register_cp_regs_for_features(ARMCPU *cpu) + { + /* Register all the coprocessor registers based on feature bits */ + CPUARMState *env = &cpu->env; ++ ARMISARegisters *isar = &cpu->isar; ++ + if (arm_feature(env, ARM_FEATURE_M)) { + /* M profile has no coprocessor registers */ + return; +@@ -8393,7 +8395,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 4, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64zfr0 }, ++ .resetvalue = GET_IDREG(isar, ID_AA64ZFR0)}, + { .name = "ID_AA64SMFR0_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -8453,7 +8455,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64isar0 }, ++ .resetvalue = GET_IDREG(isar, ID_AA64ISAR0)}, + { .name = "ID_AA64ISAR1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, +diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c +index d7cc00a084..3953e6257d 100644 +--- a/target/arm/hvf/hvf.c ++++ b/target/arm/hvf/hvf.c +@@ -18,6 +18,7 @@ + #include "sysemu/hw_accel.h" + #include "hvf_arm.h" + #include "cpregs.h" ++#include "cpu-sysregs.h" + + #include + +@@ -845,7 +846,7 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.id_aa64pfr1 }, + { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 }, + { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 }, +- { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.id_aa64isar0 }, ++ { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.idregs[ID_AA64ISAR0_EL1_IDX] }, + { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 }, + /* Add ID_AA64ISAR2_EL1 here when HVF supports it */ + { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 }, +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 599c2c2462..13679c7c18 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -23,6 +23,7 @@ + #include "sysemu/kvm_int.h" + #include "kvm_arm.h" + #include "cpu.h" ++#include "cpu-sysregs.h" + #include "trace.h" + #include "internals.h" + #include "hw/pci/pci.h" +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 6a8aad0f06..f47a5be3ac 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -17,6 +17,7 @@ + #include + + #include "qapi/error.h" ++#include "qapi/visitor.h" + #include "cpu.h" + #include "qemu/timer.h" + #include "qemu/error-report.h" +@@ -251,6 +252,27 @@ static bool kvm_arm_pauth_supported(void) + kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_GENERIC)); + } + ++uint64_t idregs_sysreg_to_kvm_reg(ARMSysRegs sysreg) ++{ ++ return ARM64_SYS_REG((sysreg & CP_REG_ARM64_SYSREG_OP0_MASK) >> CP_REG_ARM64_SYSREG_OP0_SHIFT, ++ (sysreg & CP_REG_ARM64_SYSREG_OP1_MASK) >> CP_REG_ARM64_SYSREG_OP1_SHIFT, ++ (sysreg & CP_REG_ARM64_SYSREG_CRN_MASK) >> CP_REG_ARM64_SYSREG_CRN_SHIFT, ++ (sysreg & CP_REG_ARM64_SYSREG_CRM_MASK) >> CP_REG_ARM64_SYSREG_CRM_SHIFT, ++ (sysreg & CP_REG_ARM64_SYSREG_OP2_MASK) >> CP_REG_ARM64_SYSREG_OP2_SHIFT); ++} ++ ++/* read a sysreg value and store it in the idregs */ ++static int get_host_cpu_reg(int fd, ARMHostCPUFeatures *ahcf, ARMIDRegisterIdx index) ++{ ++ uint64_t *reg; ++ int ret; ++ ++ reg = &ahcf->isar.idregs[index]; ++ ret = read_sys_reg64(fd, reg, ++ idregs_sysreg_to_kvm_reg(id_register_sysreg[index])); ++ return ret; ++} ++ + bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + { + /* Identify the feature bits corresponding to the host CPU, and +@@ -310,6 +332,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + + ahcf->target = init.target; + ahcf->dtb_compatible = "arm,arm-v8"; ++ int fd = fdarray[2]; + + err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0, + ARM64_SYS_REG(3, 0, 0, 4, 0)); +@@ -341,8 +364,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + KVM_REG_ARM_ID_AA64DFR0_EL1); + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1, + ARM64_SYS_REG(3, 0, 0, 5, 1)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0, +- ARM64_SYS_REG(3, 0, 0, 6, 0)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR0_EL1_IDX); + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1, + ARM64_SYS_REG(3, 0, 0, 6, 1)); + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar2, +@@ -449,8 +471,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * enabled SVE support, which resulted in an error rather than RAZ. + * So only read the register if we set KVM_ARM_VCPU_SVE above. + */ +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0, +- ARM64_SYS_REG(3, 0, 0, 4, 4)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_AA64ZFR0_EL1_IDX); + } + } + +diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c +index fcda99e158..2515026ce5 100644 +--- a/target/arm/tcg/cpu64.c ++++ b/target/arm/tcg/cpu64.c +@@ -58,6 +58,7 @@ static uint64_t make_ccsidr64(unsigned assoc, unsigned linesize, + static void aarch64_a35_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,cortex-a35"; + set_feature(&cpu->env, ARM_FEATURE_V8); +@@ -91,7 +92,7 @@ static void aarch64_a35_initfn(Object *obj) + cpu->isar.id_aa64pfr1 = 0; + cpu->isar.id_aa64dfr0 = 0x10305106; + cpu->isar.id_aa64dfr1 = 0; +- cpu->isar.id_aa64isar0 = 0x00011120; ++ SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + cpu->isar.id_aa64isar1 = 0; + cpu->isar.id_aa64mmfr0 = 0x00101122; + cpu->isar.id_aa64mmfr1 = 0; +@@ -226,6 +227,7 @@ static Property arm_cpu_lpa2_property = + static void aarch64_a55_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,cortex-a55"; + set_feature(&cpu->env, ARM_FEATURE_V8); +@@ -242,7 +244,7 @@ static void aarch64_a55_initfn(Object *obj) + cpu->ctr = 0x84448004; /* L1Ip = VIPT */ + cpu->dcz_blocksize = 4; /* 64 bytes */ + cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; +- cpu->isar.id_aa64isar0 = 0x0000100010211120ull; ++ SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + cpu->isar.id_aa64isar1 = 0x0000000000100001ull; + cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +@@ -294,6 +296,7 @@ static void aarch64_a55_initfn(Object *obj) + static void aarch64_a72_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,cortex-a72"; + set_feature(&cpu->env, ARM_FEATURE_V8); +@@ -328,7 +331,7 @@ static void aarch64_a72_initfn(Object *obj) + cpu->isar.id_isar5 = 0x00011121; + cpu->isar.id_aa64pfr0 = 0x00002222; + cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; ++ SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + cpu->isar.id_aa64mmfr0 = 0x00001124; + cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.dbgdevid = 0x01110f13; +@@ -349,6 +352,7 @@ static void aarch64_a72_initfn(Object *obj) + static void aarch64_a76_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,cortex-a76"; + set_feature(&cpu->env, ARM_FEATURE_V8); +@@ -365,7 +369,7 @@ static void aarch64_a76_initfn(Object *obj) + cpu->ctr = 0x8444C004; + cpu->dcz_blocksize = 4; + cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; +- cpu->isar.id_aa64isar0 = 0x0000100010211120ull; ++ SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + cpu->isar.id_aa64isar1 = 0x0000000000100001ull; + cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +@@ -418,6 +422,7 @@ static void aarch64_a76_initfn(Object *obj) + static void aarch64_a64fx_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,a64fx"; + set_feature(&cpu->env, ARM_FEATURE_V8); +@@ -440,9 +445,9 @@ static void aarch64_a64fx_initfn(Object *obj) + cpu->isar.id_aa64mmfr0 = 0x0000000000001122; + cpu->isar.id_aa64mmfr1 = 0x0000000011212100; + cpu->isar.id_aa64mmfr2 = 0x0000000000001011; +- cpu->isar.id_aa64isar0 = 0x0000000010211120; ++ SET_IDREG(isar, ID_AA64ISAR0, 0x0000000010211120); + cpu->isar.id_aa64isar1 = 0x0000000000010001; +- cpu->isar.id_aa64zfr0 = 0x0000000000000000; ++ SET_IDREG(isar, ID_AA64ZFR0, 0x0000000000000000); + cpu->clidr = 0x0000000080000023; + cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */ + cpu->ccsidr[1] = 0x2007e01c; /* 64KB L1 icache */ +@@ -587,6 +592,7 @@ static void define_neoverse_v1_cp_reginfo(ARMCPU *cpu) + static void aarch64_neoverse_n1_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,neoverse-n1"; + set_feature(&cpu->env, ARM_FEATURE_V8); +@@ -603,7 +609,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj) + cpu->ctr = 0x8444c004; + cpu->dcz_blocksize = 4; + cpu->isar.id_aa64dfr0 = 0x0000000110305408ull; +- cpu->isar.id_aa64isar0 = 0x0000100010211120ull; ++ SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + cpu->isar.id_aa64isar1 = 0x0000000000100001ull; + cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +@@ -658,6 +664,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj) + static void aarch64_neoverse_v1_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,neoverse-v1"; + set_feature(&cpu->env, ARM_FEATURE_V8); +@@ -677,7 +684,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj) + cpu->id_aa64afr1 = 0x00000000; + cpu->isar.id_aa64dfr0 = 0x000001f210305519ull; + cpu->isar.id_aa64dfr1 = 0x00000000; +- cpu->isar.id_aa64isar0 = 0x1011111110212120ull; /* with FEAT_RNG */ ++ SET_IDREG(isar, ID_AA64ISAR0, 0x1011111110212120ull); /* with FEAT_RNG */ + cpu->isar.id_aa64isar1 = 0x0111000001211032ull; + cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +@@ -733,7 +740,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj) + cpu->isar.mvfr2 = 0x00000043; + + /* From 3.7.5 ID_AA64ZFR0_EL1 */ +- cpu->isar.id_aa64zfr0 = 0x0000100000100000; ++ SET_IDREG(isar, ID_AA64ZFR0, 0x0000100000100000); + cpu->sve_vq.supported = (1 << 0) /* 128bit */ + | (1 << 1); /* 256bit */ + +@@ -880,6 +887,7 @@ static const ARMCPRegInfo cortex_a710_cp_reginfo[] = { + static void aarch64_a710_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,cortex-a710"; + set_feature(&cpu->env, ARM_FEATURE_V8); +@@ -916,12 +924,12 @@ static void aarch64_a710_initfn(Object *obj) + cpu->isar.id_pfr2 = 0x00000011; + cpu->isar.id_aa64pfr0 = 0x1201111120111112ull; /* GIC filled in later */ + cpu->isar.id_aa64pfr1 = 0x0000000000000221ull; +- cpu->isar.id_aa64zfr0 = 0x0000110100110021ull; /* with Crypto */ ++ SET_IDREG(isar, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */ + cpu->isar.id_aa64dfr0 = 0x000011f010305619ull; + cpu->isar.id_aa64dfr1 = 0; + cpu->id_aa64afr0 = 0; + cpu->id_aa64afr1 = 0; +- cpu->isar.id_aa64isar0 = 0x0221111110212120ull; /* with Crypto */ ++ SET_IDREG(isar, ID_AA64ISAR0, 0x0221111110212120ull); /* with Crypto */ + cpu->isar.id_aa64isar1 = 0x0010111101211052ull; + cpu->isar.id_aa64mmfr0 = 0x0000022200101122ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +@@ -977,6 +985,7 @@ static const ARMCPRegInfo neoverse_n2_cp_reginfo[] = { + static void aarch64_neoverse_n2_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,neoverse-n2"; + set_feature(&cpu->env, ARM_FEATURE_V8); +@@ -1013,12 +1022,12 @@ static void aarch64_neoverse_n2_initfn(Object *obj) + cpu->isar.id_pfr2 = 0x00000011; + cpu->isar.id_aa64pfr0 = 0x1201111120111112ull; /* GIC filled in later */ + cpu->isar.id_aa64pfr1 = 0x0000000000000221ull; +- cpu->isar.id_aa64zfr0 = 0x0000110100110021ull; /* with Crypto */ ++ SET_IDREG(isar, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */ + cpu->isar.id_aa64dfr0 = 0x000011f210305619ull; + cpu->isar.id_aa64dfr1 = 0; + cpu->id_aa64afr0 = 0; + cpu->id_aa64afr1 = 0; +- cpu->isar.id_aa64isar0 = 0x1221111110212120ull; /* with Crypto and FEAT_RNG */ ++ SET_IDREG(isar, ID_AA64ISAR0, 0x1221111110212120ull); /* with Crypto and FEAT_RNG */ + cpu->isar.id_aa64isar1 = 0x0011111101211052ull; + cpu->isar.id_aa64mmfr0 = 0x0000022200101125ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +@@ -1074,6 +1083,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj) + void aarch64_max_tcg_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + uint64_t t; + uint32_t u; + +@@ -1105,7 +1115,7 @@ void aarch64_max_tcg_initfn(Object *obj) + u = FIELD_DP32(u, CLIDR_EL1, LOUU, 0); + cpu->clidr = u; + +- t = cpu->isar.id_aa64isar0; ++ t = GET_IDREG(isar, ID_AA64ISAR0); + t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* FEAT_PMULL */ + t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); /* FEAT_SHA1 */ + t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* FEAT_SHA512 */ +@@ -1120,7 +1130,7 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* FEAT_FlagM2 */ + t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2); /* FEAT_TLBIRANGE */ + t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1); /* FEAT_RNG */ +- cpu->isar.id_aa64isar0 = t; ++ SET_IDREG(isar, ID_AA64ISAR0, t); + + t = cpu->isar.id_aa64isar1; + t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */ +@@ -1204,7 +1214,7 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */ + cpu->isar.id_aa64mmfr2 = t; + +- t = cpu->isar.id_aa64zfr0; ++ t = GET_IDREG(isar, ID_AA64ZFR0); + t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1); + t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* FEAT_SVE_PMULL128 */ + t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1); /* FEAT_SVE_BitPerm */ +@@ -1214,7 +1224,7 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1); /* FEAT_I8MM */ + t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1); /* FEAT_F32MM */ + t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1); /* FEAT_F64MM */ +- cpu->isar.id_aa64zfr0 = t; ++ SET_IDREG(isar, ID_AA64ZFR0, t); + + t = cpu->isar.id_aa64dfr0; + t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 9); /* FEAT_Debugv8p4 */ +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Store-aa64isar1-2-into-the-idregs-array.patch b/arm-cpu-Store-aa64isar1-2-into-the-idregs-array.patch new file mode 100644 index 0000000000000000000000000000000000000000..4a8cb23c1f7e28f02a7469ccd2882f1abd63e1cc --- /dev/null +++ b/arm-cpu-Store-aa64isar1-2-into-the-idregs-array.patch @@ -0,0 +1,386 @@ +From 5847c51bd1ace4a48a489ae278807c4b7e3dd7eb Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:47 +0800 +Subject: [PATCH 03/26] arm/cpu: Store aa64isar1/2 into the idregs array + +Reviewed-by: Richard Henderson +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu-features.h | 36 ++++++++++++++++++------------------ + target/arm/cpu.c | 13 ++++--------- + target/arm/cpu.h | 2 -- + target/arm/cpu64.c | 9 +++++---- + target/arm/helper.c | 4 ++-- + target/arm/hvf/hvf.c | 2 +- + target/arm/kvm64.c | 6 ++---- + target/arm/tcg/cpu64.c | 24 ++++++++++++------------ + 8 files changed, 44 insertions(+), 52 deletions(-) + +diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h +index b9ece5f03a..06f3666d07 100644 +--- a/target/arm/cpu-features.h ++++ b/target/arm/cpu-features.h +@@ -464,12 +464,12 @@ static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id) + + static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, JSCVT) != 0; + } + + static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, FCMA) != 0; + } + + /* +@@ -493,9 +493,9 @@ isar_feature_pauth_feature(const ARMISARegisters *id) + * Architecturally, only one of {APA,API,APA3} may be active (non-zero) + * and the other two must be zero. Thus we may avoid conditionals. + */ +- return (FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) | +- FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, API) | +- FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3)); ++ return (FIELD_EX64_IDREG(id, ID_AA64ISAR1, APA) | ++ FIELD_EX64_IDREG(id, ID_AA64ISAR1, API) | ++ FIELD_EX64_IDREG(id, ID_AA64ISAR2, APA3)); + } + + static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) +@@ -513,7 +513,7 @@ static inline bool isar_feature_aa64_pauth_qarma5(const ARMISARegisters *id) + * Return true if pauth is enabled with the architected QARMA5 algorithm. + * QEMU will always enable or disable both APA and GPA. + */ +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, APA) != 0; + } + + static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id) +@@ -522,62 +522,62 @@ static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id) + * Return true if pauth is enabled with the architected QARMA3 algorithm. + * QEMU will always enable or disable both APA3 and GPA3. + */ +- return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR2, APA3) != 0; + } + + static inline bool isar_feature_aa64_sb(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, SB) != 0; + } + + static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, SPECRES) != 0; + } + + static inline bool isar_feature_aa64_frint(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, FRINTTS) != 0; + } + + static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, DPB) != 0; + } + + static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, DPB) >= 2; + } + + static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, BF16) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, BF16) != 0; + } + + static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, LRCPC) != 0; + } + + static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, LRCPC) >= 2; + } + + static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR1, I8MM) != 0; + } + + static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR2, BC) != 0; + } + + static inline bool isar_feature_aa64_mops(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS); ++ return FIELD_EX64_IDREG(id, ID_AA64ISAR2, MOPS); + } + + static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id) +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 262c5017d2..a61f081ec5 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1964,9 +1964,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + uint64_t t; + uint32_t u; + +- t = cpu->isar.id_aa64isar1; +- t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 0); +- cpu->isar.id_aa64isar1 = t; ++ FIELD_DP64_IDREG(isar, ID_AA64ISAR1, JSCVT, 0); + + t = cpu->isar.id_aa64pfr0; + t = FIELD_DP64(t, ID_AA64PFR0, FP, 0xf); +@@ -2019,11 +2017,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + t = FIELD_DP64(t, ID_AA64ISAR0, DP, 0); + SET_IDREG(isar, ID_AA64ISAR0, t); + +- t = cpu->isar.id_aa64isar1; ++ t = GET_IDREG(isar, ID_AA64ISAR1); + t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0); + t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 0); + t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 0); +- cpu->isar.id_aa64isar1 = t; ++ SET_IDREG(isar, ID_AA64ISAR1, t); + + t = cpu->isar.id_aa64pfr0; + t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 0xf); +@@ -2059,14 +2057,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + } + + if (!cpu->has_neon && !cpu->has_vfp) { +- uint64_t t; + uint32_t u; + + FIELD_DP64_IDREG(isar, ID_AA64ISAR0, FHM, 0); + +- t = cpu->isar.id_aa64isar1; +- t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 0); +- cpu->isar.id_aa64isar1 = t; ++ FIELD_DP64_IDREG(isar, ID_AA64ISAR1, FRINTTS, 0); + + u = cpu->isar.mvfr0; + u = FIELD_DP32(u, MVFR0, SIMDREG, 0); +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index b6e988e570..fa5a916c92 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1082,8 +1082,6 @@ struct ArchCPU { + uint32_t dbgdidr; + uint32_t dbgdevid; + uint32_t dbgdevid1; +- uint64_t id_aa64isar1; +- uint64_t id_aa64isar2; + uint64_t id_aa64pfr0; + uint64_t id_aa64pfr1; + uint64_t id_aa64mmfr0; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 4d31d34591..b646c7bdeb 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -502,6 +502,7 @@ void aarch64_add_sme_properties(Object *obj) + void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) + { + ARMPauthFeature features = cpu_isar_feature(pauth_feature, cpu); ++ ARMISARegisters *isar = &cpu->isar; + uint64_t isar1, isar2; + + /* +@@ -512,13 +513,13 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) + * + * Begin by disabling all fields. + */ +- isar1 = cpu->isar.id_aa64isar1; ++ isar1 = GET_IDREG(isar, ID_AA64ISAR1); + isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, 0); + isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 0); + isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, 0); + isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 0); + +- isar2 = cpu->isar.id_aa64isar2; ++ isar2 = GET_IDREG(isar, ID_AA64ISAR2); + isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, 0); + isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 0); + +@@ -565,8 +566,8 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) + } + } + +- cpu->isar.id_aa64isar1 = isar1; +- cpu->isar.id_aa64isar2 = isar2; ++ SET_IDREG(isar, ID_AA64ISAR1, isar1); ++ SET_IDREG(isar, ID_AA64ISAR2, isar2); + } + + static Property arm_cpu_pauth_property = +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 02c0033712..6758e82440 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -8460,12 +8460,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64isar1 }, ++ .resetvalue = GET_IDREG(isar, ID_AA64ISAR1)}, + { .name = "ID_AA64ISAR2_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64isar2 }, ++ .resetvalue = GET_IDREG(isar, ID_AA64ISAR2)}, + { .name = "ID_AA64ISAR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 3, + .access = PL1_R, .type = ARM_CP_CONST, +diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c +index 3953e6257d..80c1e36d10 100644 +--- a/target/arm/hvf/hvf.c ++++ b/target/arm/hvf/hvf.c +@@ -847,7 +847,7 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 }, + { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 }, + { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.idregs[ID_AA64ISAR0_EL1_IDX] }, +- { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 }, ++ { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.idregs[ID_AA64ISAR1_EL1_IDX] }, + /* Add ID_AA64ISAR2_EL1 here when HVF supports it */ + { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 }, + { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 }, +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index f47a5be3ac..5ff37ab24d 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -365,10 +365,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1, + ARM64_SYS_REG(3, 0, 0, 5, 1)); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR0_EL1_IDX); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1, +- ARM64_SYS_REG(3, 0, 0, 6, 1)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar2, +- ARM64_SYS_REG(3, 0, 0, 6, 2)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR1_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR2_EL1_IDX); + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0, + ARM64_SYS_REG(3, 0, 0, 7, 0)); + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1, +diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c +index 2515026ce5..a62d735029 100644 +--- a/target/arm/tcg/cpu64.c ++++ b/target/arm/tcg/cpu64.c +@@ -93,7 +93,7 @@ static void aarch64_a35_initfn(Object *obj) + cpu->isar.id_aa64dfr0 = 0x10305106; + cpu->isar.id_aa64dfr1 = 0; + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); +- cpu->isar.id_aa64isar1 = 0; ++ SET_IDREG(isar, ID_AA64ISAR1, 0); + cpu->isar.id_aa64mmfr0 = 0x00101122; + cpu->isar.id_aa64mmfr1 = 0; + cpu->clidr = 0x0a200023; +@@ -245,7 +245,7 @@ static void aarch64_a55_initfn(Object *obj) + cpu->dcz_blocksize = 4; /* 64 bytes */ + cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); +- cpu->isar.id_aa64isar1 = 0x0000000000100001ull; ++ SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); + cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; +@@ -370,7 +370,7 @@ static void aarch64_a76_initfn(Object *obj) + cpu->dcz_blocksize = 4; + cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); +- cpu->isar.id_aa64isar1 = 0x0000000000100001ull; ++ SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); + cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; +@@ -446,7 +446,7 @@ static void aarch64_a64fx_initfn(Object *obj) + cpu->isar.id_aa64mmfr1 = 0x0000000011212100; + cpu->isar.id_aa64mmfr2 = 0x0000000000001011; + SET_IDREG(isar, ID_AA64ISAR0, 0x0000000010211120); +- cpu->isar.id_aa64isar1 = 0x0000000000010001; ++ SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000010001); + SET_IDREG(isar, ID_AA64ZFR0, 0x0000000000000000); + cpu->clidr = 0x0000000080000023; + cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */ +@@ -610,7 +610,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj) + cpu->dcz_blocksize = 4; + cpu->isar.id_aa64dfr0 = 0x0000000110305408ull; + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); +- cpu->isar.id_aa64isar1 = 0x0000000000100001ull; ++ SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); + cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; +@@ -685,7 +685,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj) + cpu->isar.id_aa64dfr0 = 0x000001f210305519ull; + cpu->isar.id_aa64dfr1 = 0x00000000; + SET_IDREG(isar, ID_AA64ISAR0, 0x1011111110212120ull); /* with FEAT_RNG */ +- cpu->isar.id_aa64isar1 = 0x0111000001211032ull; ++ SET_IDREG(&cpu->isar, ID_AA64ISAR1, 0x0111000001211032ull); + cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x0220011102101011ull; +@@ -930,7 +930,7 @@ static void aarch64_a710_initfn(Object *obj) + cpu->id_aa64afr0 = 0; + cpu->id_aa64afr1 = 0; + SET_IDREG(isar, ID_AA64ISAR0, 0x0221111110212120ull); /* with Crypto */ +- cpu->isar.id_aa64isar1 = 0x0010111101211052ull; ++ SET_IDREG(isar, ID_AA64ISAR1, 0x0010111101211052ull); + cpu->isar.id_aa64mmfr0 = 0x0000022200101122ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x1221011110101011ull; +@@ -1028,7 +1028,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj) + cpu->id_aa64afr0 = 0; + cpu->id_aa64afr1 = 0; + SET_IDREG(isar, ID_AA64ISAR0, 0x1221111110212120ull); /* with Crypto and FEAT_RNG */ +- cpu->isar.id_aa64isar1 = 0x0011111101211052ull; ++ SET_IDREG(isar, ID_AA64ISAR1, 0x0011111101211052ull); + cpu->isar.id_aa64mmfr0 = 0x0000022200101125ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x1221011112101011ull; +@@ -1132,7 +1132,7 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1); /* FEAT_RNG */ + SET_IDREG(isar, ID_AA64ISAR0, t); + +- t = cpu->isar.id_aa64isar1; ++ t = GET_IDREG(isar, ID_AA64ISAR1); + t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */ + t = FIELD_DP64(t, ID_AA64ISAR1, APA, PauthFeat_FPACCOMBINED); + t = FIELD_DP64(t, ID_AA64ISAR1, API, 1); +@@ -1145,12 +1145,12 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 1); /* FEAT_BF16 */ + t = FIELD_DP64(t, ID_AA64ISAR1, DGH, 1); /* FEAT_DGH */ + t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1); /* FEAT_I8MM */ +- cpu->isar.id_aa64isar1 = t; ++ SET_IDREG(&cpu->isar, ID_AA64ISAR1, t); + +- t = cpu->isar.id_aa64isar2; ++ t = GET_IDREG(isar, ID_AA64ISAR2); + t = FIELD_DP64(t, ID_AA64ISAR2, MOPS, 1); /* FEAT_MOPS */ + t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1); /* FEAT_HBC */ +- cpu->isar.id_aa64isar2 = t; ++ SET_IDREG(&cpu->isar, ID_AA64ISAR2, t); + + t = cpu->isar.id_aa64pfr0; + t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); /* FEAT_FP16 */ +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Store-aa64mmfr0-2-into-the-idregs-array.patch b/arm-cpu-Store-aa64mmfr0-2-into-the-idregs-array.patch new file mode 100644 index 0000000000000000000000000000000000000000..19a2ca9f1d3c618ea898bd1ae0e91963eee60d2d --- /dev/null +++ b/arm-cpu-Store-aa64mmfr0-2-into-the-idregs-array.patch @@ -0,0 +1,563 @@ +From a5a09e88e80abbe211001aa0f0d0c35f56c09fb2 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:47 +0800 +Subject: [PATCH 05/26] arm/cpu: Store aa64mmfr0-2 into the idregs array + +Reviewed-by: Richard Henderson +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu-features.h | 62 +++++++++++++++++++-------------------- + target/arm/cpu.c | 3 +- + target/arm/cpu.h | 3 -- + target/arm/cpu64.c | 12 ++++---- + target/arm/helper.c | 6 ++-- + target/arm/hvf/hvf.c | 8 ++--- + target/arm/kvm64.c | 9 ++---- + target/arm/ptw.c | 6 ++-- + target/arm/tcg/cpu64.c | 60 ++++++++++++++++++------------------- + 9 files changed, 81 insertions(+), 88 deletions(-) + +diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h +index d3935981d1..aefde4b057 100644 +--- a/target/arm/cpu-features.h ++++ b/target/arm/cpu-features.h +@@ -682,162 +682,162 @@ static inline bool isar_feature_aa64_sme(const ARMISARegisters *id) + + static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) + { +- return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1; ++ return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 1; + } + + static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id) + { +- unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); ++ unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN4_2); + return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id)); + } + + static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16) >= 2; + } + + static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id) + { +- unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); ++ unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16_2); + return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id)); + } + + static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id) + { +- return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0; ++ return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 0; + } + + static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16) >= 1; + } + + static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id) + { +- return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0; ++ return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN64) >= 0; + } + + static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id) + { +- unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); ++ unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN4_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id)); + } + + static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id) + { +- unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); ++ unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id)); + } + + static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id) + { +- unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2); ++ unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN64_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id)); + } + + static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR0, FGT) != 0; + } + + static inline bool isar_feature_aa64_vh(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR1, VH) != 0; + } + + static inline bool isar_feature_aa64_lor(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR1, LO) != 0; + } + + static inline bool isar_feature_aa64_pan(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) != 0; + } + + static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) >= 2; + } + + static inline bool isar_feature_aa64_pan3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 3; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) >= 3; + } + + static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HCX) != 0; + } + + static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, TIDCP1) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR1, TIDCP1) != 0; + } + + static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HAFDBS) != 0; + } + + static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HAFDBS) >= 2; + } + + static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR1, XNX) != 0; + } + + static inline bool isar_feature_aa64_uao(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR2, UAO) != 0; + } + + static inline bool isar_feature_aa64_st(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR2, ST) != 0; + } + + static inline bool isar_feature_aa64_lse2(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, AT) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR2, AT) != 0; + } + + static inline bool isar_feature_aa64_fwb(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, FWB) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR2, FWB) != 0; + } + + static inline bool isar_feature_aa64_ids(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, IDS) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR2, IDS) != 0; + } + + static inline bool isar_feature_aa64_half_evt(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 1; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR2, EVT) >= 1; + } + + static inline bool isar_feature_aa64_evt(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR2, EVT) >= 2; + } + + static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR2, CCIDX) != 0; + } + + static inline bool isar_feature_aa64_lva(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR2, VARANGE) != 0; + } + + static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64MMFR2, E0PD) != 0; + } + + static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id) +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index f708782d00..7ac964b550 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2251,8 +2251,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + /* FEAT_MPAM (Memory Partitioning and Monitoring Extension) */ + FIELD_DP64_IDREG(isar, ID_AA64PFR0, MPAM, 0); + /* FEAT_NV (Nested Virtualization) */ +- cpu->isar.id_aa64mmfr2 = +- FIELD_DP64(cpu->isar.id_aa64mmfr2, ID_AA64MMFR2, NV, 0); ++ FIELD_DP64_IDREG(isar, ID_AA64MMFR2, NV, 0); + } + + /* MPU can be configured out of a PMSA CPU either by setting has-mpu +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 057d669075..3ef3a6f958 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1082,9 +1082,6 @@ struct ArchCPU { + uint32_t dbgdidr; + uint32_t dbgdevid; + uint32_t dbgdevid1; +- uint64_t id_aa64mmfr0; +- uint64_t id_aa64mmfr1; +- uint64_t id_aa64mmfr2; + uint64_t id_aa64dfr0; + uint64_t id_aa64dfr1; + uint64_t id_aa64smfr0; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 2c03735a93..f980f1efd2 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -722,12 +722,12 @@ void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp) + return; + } + +- t = cpu->isar.id_aa64mmfr0; ++ t = GET_IDREG(&cpu->isar, ID_AA64MMFR0); + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 2); /* 16k pages w/ LPA2 */ + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4, 1); /* 4k pages w/ LPA2 */ + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 3); /* 16k stage2 w/ LPA2 */ + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 3); /* 4k stage2 w/ LPA2 */ +- cpu->isar.id_aa64mmfr0 = t; ++ SET_IDREG(&cpu->isar, ID_AA64MMFR0, t); + } + + static void aarch64_a57_initfn(Object *obj) +@@ -771,7 +771,7 @@ static void aarch64_a57_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + cpu->isar.id_aa64dfr0 = 0x10305106; + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); +- cpu->isar.id_aa64mmfr0 = 0x00001124; ++ SET_IDREG(isar, ID_AA64MMFR0, 0x00001124); + cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.dbgdevid = 0x01110f13; + cpu->isar.dbgdevid1 = 0x2; +@@ -829,7 +829,7 @@ static void aarch64_a53_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + cpu->isar.id_aa64dfr0 = 0x10305106; + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); +- cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ ++ SET_IDREG(isar, ID_AA64MMFR0, 0x00001122); /* 40 bit physical addr */ + cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.dbgdevid = 0x00110f13; + cpu->isar.dbgdevid1 = 0x1; +@@ -885,7 +885,7 @@ static void aarch64_a72_initfn(Object *obj) + SET_IDREG(&cpu->isar, ID_AA64PFR0, 0x00002222); + cpu->isar.id_aa64dfr0 = 0x10305106; + SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0x00011120); +- cpu->isar.id_aa64mmfr0 = 0x00001124; ++ SET_IDREG(&cpu->isar, ID_AA64MMFR0, 0x00001124); + cpu->isar.dbgdidr = 0x3516d000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ +@@ -914,7 +914,7 @@ static void aarch64_kunpeng_920_initfn(Object *obj) + SET_IDREG(&cpu->isar, ID_AA64PFR0, 0x11001111); + cpu->isar.id_aa64dfr0 = 0x110305408; + SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0x10211120); +- cpu->isar.id_aa64mmfr0 = 0x101125; ++ SET_IDREG(&cpu->isar, ID_AA64MMFR0, 0x101125); + } + + static void aarch64_host_initfn(Object *obj) +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 970cc890c0..a44c13b2b0 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -8495,17 +8495,17 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64mmfr0 }, ++ .resetvalue = GET_IDREG(isar, ID_AA64MMFR0)}, + { .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64mmfr1 }, ++ .resetvalue = GET_IDREG(isar, ID_AA64MMFR1) }, + { .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64mmfr2 }, ++ .resetvalue = GET_IDREG(isar, ID_AA64MMFR2) }, + { .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3, + .access = PL1_R, .type = ARM_CP_CONST, +diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c +index 9484d057a2..7bf5276484 100644 +--- a/target/arm/hvf/hvf.c ++++ b/target/arm/hvf/hvf.c +@@ -849,9 +849,9 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.idregs[ID_AA64ISAR0_EL1_IDX] }, + { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.idregs[ID_AA64ISAR1_EL1_IDX] }, + /* Add ID_AA64ISAR2_EL1 here when HVF supports it */ +- { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 }, +- { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 }, +- { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 }, ++ { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.idregs[ID_AA64MMFR0_EL1_IDX] }, ++ { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.idregs[ID_AA64MMFR1_EL1_IDX] }, ++ { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.idregs[ID_AA64MMFR2_EL1_IDX] }, + }; + hv_vcpu_t fd; + hv_return_t r = HV_SUCCESS; +@@ -987,7 +987,7 @@ int hvf_arch_init_vcpu(CPUState *cpu) + + /* We're limited to underlying hardware caps, override internal versions */ + ret = hv_vcpu_get_sys_reg(cpu->accel->fd, HV_SYS_REG_ID_AA64MMFR0_EL1, +- &arm_cpu->isar.id_aa64mmfr0); ++ &arm_cpu->isar.idregs[ID_AA64MMFR0_EL1_IDX]); + assert_hvf_ok(ret); + + return 0; +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index cf61c18bfc..1d0dc2e2b3 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -365,12 +365,9 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR2_EL1_IDX); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0, +- ARM64_SYS_REG(3, 0, 0, 7, 0)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1, +- ARM64_SYS_REG(3, 0, 0, 7, 1)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2, +- ARM64_SYS_REG(3, 0, 0, 7, 2)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_AA64MMFR0_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_AA64MMFR1_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_AA64MMFR2_EL1_IDX); + + /* + * Note that if AArch32 support is not present in the host, +diff --git a/target/arm/ptw.c b/target/arm/ptw.c +index 1762b058ae..0fe20ddea6 100644 +--- a/target/arm/ptw.c ++++ b/target/arm/ptw.c +@@ -100,7 +100,7 @@ unsigned int arm_pamax(ARMCPU *cpu) + { + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + unsigned int parange = +- FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE); ++ FIELD_EX64_IDREG(&cpu->isar, ID_AA64MMFR0, PARANGE); + + /* + * id_aa64mmfr0 is a read-only register so values outside of the +@@ -313,7 +313,7 @@ static bool granule_protection_check(CPUARMState *env, uint64_t paddress, + * physical address size is invalid. + */ + pps = FIELD_EX64(gpccr, GPCCR, PPS); +- if (pps > FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE)) { ++ if (pps > FIELD_EX64_IDREG(&cpu->isar, ID_AA64MMFR0, PARANGE)) { + goto fault_walk; + } + pps = pamax_map[pps]; +@@ -1651,7 +1651,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw, + * ID_AA64MMFR0 is a read-only register so values outside of the + * supported mappings can be considered an implementation error. + */ +- ps = FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE); ++ ps = FIELD_EX64_IDREG(&cpu->isar, ID_AA64MMFR0, PARANGE); + ps = MIN(ps, param.ps); + assert(ps < ARRAY_SIZE(pamax_map)); + outputsize = pamax_map[ps]; +diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c +index 39e319e62a..4805af8409 100644 +--- a/target/arm/tcg/cpu64.c ++++ b/target/arm/tcg/cpu64.c +@@ -94,8 +94,8 @@ static void aarch64_a35_initfn(Object *obj) + cpu->isar.id_aa64dfr1 = 0; + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + SET_IDREG(isar, ID_AA64ISAR1, 0); +- cpu->isar.id_aa64mmfr0 = 0x00101122; +- cpu->isar.id_aa64mmfr1 = 0; ++ SET_IDREG(isar, ID_AA64MMFR0, 0x00101122); ++ SET_IDREG(isar, ID_AA64MMFR1, 0); + cpu->clidr = 0x0a200023; + cpu->dcz_blocksize = 4; + +@@ -243,9 +243,9 @@ static void aarch64_a55_initfn(Object *obj) + cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); +- cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; +- cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +- cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; ++ SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000101122ull); ++ SET_IDREG(isar, ID_AA64MMFR1, 0x0000000010212122ull); ++ SET_IDREG(isar, ID_AA64MMFR2, 0x0000000000001011ull); + SET_IDREG(isar, ID_AA64PFR0, 0x0000000010112222ull); + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000010ull); + cpu->id_afr0 = 0x00000000; +@@ -329,7 +329,7 @@ static void aarch64_a72_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + cpu->isar.id_aa64dfr0 = 0x10305106; + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); +- cpu->isar.id_aa64mmfr0 = 0x00001124; ++ SET_IDREG(isar, ID_AA64MMFR0, 0x00001124); + cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.dbgdevid = 0x01110f13; + cpu->isar.dbgdevid1 = 0x2; +@@ -368,9 +368,9 @@ static void aarch64_a76_initfn(Object *obj) + cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); +- cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; +- cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +- cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; ++ SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000101122ull); ++ SET_IDREG(isar, ID_AA64MMFR1, 0x0000000010212122ull); ++ SET_IDREG(isar, ID_AA64MMFR2, 0x0000000000001011ull); + SET_IDREG(isar, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000010ull); + cpu->id_afr0 = 0x00000000; +@@ -439,9 +439,9 @@ static void aarch64_a64fx_initfn(Object *obj) + cpu->isar.id_aa64dfr1 = 0x0000000000000000; + cpu->id_aa64afr0 = 0x0000000000000000; + cpu->id_aa64afr1 = 0x0000000000000000; +- cpu->isar.id_aa64mmfr0 = 0x0000000000001122; +- cpu->isar.id_aa64mmfr1 = 0x0000000011212100; +- cpu->isar.id_aa64mmfr2 = 0x0000000000001011; ++ SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000001122); ++ SET_IDREG(isar, ID_AA64MMFR1, 0x0000000011212100); ++ SET_IDREG(isar, ID_AA64MMFR2, 0x0000000000001011); + SET_IDREG(isar, ID_AA64ISAR0, 0x0000000010211120); + SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000010001); + SET_IDREG(isar, ID_AA64ZFR0, 0x0000000000000000); +@@ -608,9 +608,9 @@ static void aarch64_neoverse_n1_initfn(Object *obj) + cpu->isar.id_aa64dfr0 = 0x0000000110305408ull; + SET_IDREG(isar, ID_AA64ISAR0, 0x0000100010211120ull); + SET_IDREG(isar, ID_AA64ISAR1, 0x0000000000100001ull); +- cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; +- cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +- cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; ++ SET_IDREG(isar, ID_AA64MMFR0, 0x0000000000101125ull); ++ SET_IDREG(isar, ID_AA64MMFR1, 0x0000000010212122ull); ++ SET_IDREG(isar, ID_AA64MMFR2, 0x0000000000001011ull); + SET_IDREG(isar, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000020ull); + cpu->id_afr0 = 0x00000000; +@@ -683,9 +683,9 @@ static void aarch64_neoverse_v1_initfn(Object *obj) + cpu->isar.id_aa64dfr1 = 0x00000000; + SET_IDREG(isar, ID_AA64ISAR0, 0x1011111110212120ull); /* with FEAT_RNG */ + SET_IDREG(&cpu->isar, ID_AA64ISAR1, 0x0111000001211032ull); +- cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; +- cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +- cpu->isar.id_aa64mmfr2 = 0x0220011102101011ull; ++ SET_IDREG(&cpu->isar, ID_AA64MMFR0, 0x0000000000101125ull); ++ SET_IDREG(&cpu->isar, ID_AA64MMFR1, 0x0000000010212122ull); ++ SET_IDREG(&cpu->isar, ID_AA64MMFR2, 0x0220011102101011ull); + SET_IDREG(isar, ID_AA64PFR0, 0x1101110120111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000020ull); + cpu->id_afr0 = 0x00000000; +@@ -928,9 +928,9 @@ static void aarch64_a710_initfn(Object *obj) + cpu->id_aa64afr1 = 0; + SET_IDREG(isar, ID_AA64ISAR0, 0x0221111110212120ull); /* with Crypto */ + SET_IDREG(isar, ID_AA64ISAR1, 0x0010111101211052ull); +- cpu->isar.id_aa64mmfr0 = 0x0000022200101122ull; +- cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +- cpu->isar.id_aa64mmfr2 = 0x1221011110101011ull; ++ SET_IDREG(isar, ID_AA64MMFR0, 0x0000022200101122ull); ++ SET_IDREG(isar, ID_AA64MMFR1, 0x0000000010212122ull); ++ SET_IDREG(isar, ID_AA64MMFR2, 0x1221011110101011ull); + cpu->clidr = 0x0000001482000023ull; + cpu->gm_blocksize = 4; + cpu->ctr = 0x000000049444c004ull; +@@ -1026,9 +1026,9 @@ static void aarch64_neoverse_n2_initfn(Object *obj) + cpu->id_aa64afr1 = 0; + SET_IDREG(isar, ID_AA64ISAR0, 0x1221111110212120ull); /* with Crypto and FEAT_RNG */ + SET_IDREG(isar, ID_AA64ISAR1, 0x0011111101211052ull); +- cpu->isar.id_aa64mmfr0 = 0x0000022200101125ull; +- cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; +- cpu->isar.id_aa64mmfr2 = 0x1221011112101011ull; ++ SET_IDREG(isar, ID_AA64MMFR0, 0x0000022200101125ull); ++ SET_IDREG(isar, ID_AA64MMFR1, 0x0000000010212122ull); ++ SET_IDREG(isar, ID_AA64MMFR2, 0x1221011112101011ull); + cpu->clidr = 0x0000001482000023ull; + cpu->gm_blocksize = 4; + cpu->ctr = 0x00000004b444c004ull; +@@ -1174,16 +1174,16 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */ + SET_IDREG(isar, ID_AA64PFR1, t); + +- t = cpu->isar.id_aa64mmfr0; ++ t = GET_IDREG(isar, ID_AA64MMFR0); + t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */ + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 1); /* 16k pages supported */ + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 2); /* 16k stage2 supported */ + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */ + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */ + t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */ +- cpu->isar.id_aa64mmfr0 = t; ++ SET_IDREG(isar, ID_AA64MMFR0, t); + +- t = cpu->isar.id_aa64mmfr1; ++ t = GET_IDREG(isar, ID_AA64MMFR1); + t = FIELD_DP64(t, ID_AA64MMFR1, HAFDBS, 2); /* FEAT_HAFDBS */ + t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* FEAT_VMID16 */ + t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */ +@@ -1194,9 +1194,9 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 1); /* FEAT_ETS */ + t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */ + t = FIELD_DP64(t, ID_AA64MMFR1, TIDCP1, 1); /* FEAT_TIDCP1 */ +- cpu->isar.id_aa64mmfr1 = t; ++ SET_IDREG(isar, ID_AA64MMFR1, t); + +- t = cpu->isar.id_aa64mmfr2; ++ t = GET_IDREG(isar, ID_AA64MMFR2); + t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* FEAT_TTCNP */ + t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1); /* FEAT_UAO */ + t = FIELD_DP64(t, ID_AA64MMFR2, IESB, 1); /* FEAT_IESB */ +@@ -1209,7 +1209,7 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64MMFR2, BBM, 2); /* FEAT_BBM at level 2 */ + t = FIELD_DP64(t, ID_AA64MMFR2, EVT, 2); /* FEAT_EVT */ + t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */ +- cpu->isar.id_aa64mmfr2 = t; ++ SET_IDREG(isar, ID_AA64MMFR2, t); + + t = GET_IDREG(isar, ID_AA64ZFR0); + t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1); +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Store-aa64pfr0-1-into-the-idregs-array.patch b/arm-cpu-Store-aa64pfr0-1-into-the-idregs-array.patch new file mode 100644 index 0000000000000000000000000000000000000000..d7bb6374e236f5b98524e21b11f6c990a951de7e --- /dev/null +++ b/arm-cpu-Store-aa64pfr0-1-into-the-idregs-array.patch @@ -0,0 +1,558 @@ +From c88ddc78ac6d5b986d9fe4d58d60fa40a8f4f5a3 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:47 +0800 +Subject: [PATCH 04/26] arm/cpu: Store aa64pfr0/1 into the idregs array + +Reviewed-by: Richard Henderson +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu-features.h | 38 +++++++++++++++---------------- + target/arm/cpu.c | 27 +++++++--------------- + target/arm/cpu.h | 2 -- + target/arm/cpu64.c | 18 +++++---------- + target/arm/helper.c | 6 ++--- + target/arm/hvf/hvf.c | 6 ++--- + target/arm/kvm64.c | 12 +++++----- + target/arm/tcg/cpu64.c | 47 ++++++++++++++++++--------------------- + 8 files changed, 66 insertions(+), 90 deletions(-) + +diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h +index 06f3666d07..d3935981d1 100644 +--- a/target/arm/cpu-features.h ++++ b/target/arm/cpu-features.h +@@ -583,68 +583,68 @@ static inline bool isar_feature_aa64_mops(const ARMISARegisters *id) + static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id) + { + /* We always set the AdvSIMD and FP fields identically. */ +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) != 0xf; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR0, FP) != 0xf; + } + + static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id) + { + /* We always set the AdvSIMD and FP fields identically wrt FP16. */ +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR0, FP) == 1; + } + + static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL0) >= 2; + } + + static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL1) >= 2; + } + + static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL2) >= 2; + } + + static inline bool isar_feature_aa64_ras(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR0, RAS) != 0; + } + + static inline bool isar_feature_aa64_doublefault(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR0, RAS) >= 2; + } + + static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR0, SVE) != 0; + } + + static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR0, SEL2) != 0; + } + + static inline bool isar_feature_aa64_rme(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RME) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR0, RME) != 0; + } + + static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR0, DIT) != 0; + } + + static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id) + { +- int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2); ++ int key = FIELD_EX64_IDREG(id, ID_AA64PFR0, CSV2); + if (key >= 2) { + return true; /* FEAT_CSV2_2 */ + } + if (key == 1) { +- key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC); ++ key = FIELD_EX64_IDREG(id, ID_AA64PFR1, CSV2_FRAC); + return key >= 2; /* FEAT_CSV2_1p2 */ + } + return false; +@@ -652,32 +652,32 @@ static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id) + + static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR1, SSBS) != 0; + } + + static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR1, BT) != 0; + } + + static inline bool isar_feature_aa64_mte_insn_reg(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) != 0; + } + + static inline bool isar_feature_aa64_mte(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) >= 2; + } + + static inline bool isar_feature_aa64_mte3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 3; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) >= 3; + } + + static inline bool isar_feature_aa64_sme(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0; ++ return FIELD_EX64_IDREG(id, ID_AA64PFR1, SME) != 0; + } + + static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index a61f081ec5..f708782d00 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1961,14 +1961,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + } + + if (!cpu->has_vfp) { +- uint64_t t; + uint32_t u; + + FIELD_DP64_IDREG(isar, ID_AA64ISAR1, JSCVT, 0); + +- t = cpu->isar.id_aa64pfr0; +- t = FIELD_DP64(t, ID_AA64PFR0, FP, 0xf); +- cpu->isar.id_aa64pfr0 = t; ++ FIELD_DP64_IDREG(isar, ID_AA64PFR0, FP, 0xf); + + u = cpu->isar.id_isar6; + u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0); +@@ -2023,9 +2020,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 0); + SET_IDREG(isar, ID_AA64ISAR1, t); + +- t = cpu->isar.id_aa64pfr0; +- t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 0xf); +- cpu->isar.id_aa64pfr0 = t; ++ FIELD_DP64_IDREG(isar, ID_AA64PFR0, ADVSIMD, 0xf); + + u = cpu->isar.id_isar5; + u = FIELD_DP32(u, ID_ISAR5, AES, 0); +@@ -2159,12 +2154,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + */ + cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1, ID_PFR1, SECURITY, 0); + cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPSDBG, 0); +- cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0, +- ID_AA64PFR0, EL3, 0); ++ FIELD_DP64_IDREG(isar, ID_AA64PFR0, EL3, 0); + + /* Disable the realm management extension, which requires EL3. */ +- cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0, +- ID_AA64PFR0, RME, 0); ++ FIELD_DP64_IDREG(isar, ID_AA64PFR0, RME, 0); + } + + if (!cpu->has_el2) { +@@ -2199,8 +2192,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + * Disable the hypervisor feature bits in the processor feature + * registers if we don't have EL2. + */ +- cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0, +- ID_AA64PFR0, EL2, 0); ++ FIELD_DP64_IDREG(isar, ID_AA64PFR0, EL2, 0); + cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1, + ID_PFR1, VIRTUALIZATION, 0); + } +@@ -2221,8 +2213,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + * This matches Cortex-A710 BROADCASTMTE input being LOW. + */ + if (cpu->tag_memory == NULL) { +- cpu->isar.id_aa64pfr1 = +- FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 1); ++ FIELD_DP64_IDREG(isar, ID_AA64PFR1, MTE, 1); + } + #endif + } +@@ -2254,13 +2245,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + cpu->isar.id_dfr0 = + FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, MMAPTRC, 0); + /* FEAT_AMU (Activity Monitors Extension) */ +- cpu->isar.id_aa64pfr0 = +- FIELD_DP64(cpu->isar.id_aa64pfr0, ID_AA64PFR0, AMU, 0); ++ FIELD_DP64_IDREG(isar, ID_AA64PFR0, AMU, 0); + cpu->isar.id_pfr0 = + FIELD_DP32(cpu->isar.id_pfr0, ID_PFR0, AMU, 0); + /* FEAT_MPAM (Memory Partitioning and Monitoring Extension) */ +- cpu->isar.id_aa64pfr0 = +- FIELD_DP64(cpu->isar.id_aa64pfr0, ID_AA64PFR0, MPAM, 0); ++ FIELD_DP64_IDREG(isar, ID_AA64PFR0, MPAM, 0); + /* FEAT_NV (Nested Virtualization) */ + cpu->isar.id_aa64mmfr2 = + FIELD_DP64(cpu->isar.id_aa64mmfr2, ID_AA64MMFR2, NV, 0); +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index fa5a916c92..057d669075 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1082,8 +1082,6 @@ struct ArchCPU { + uint32_t dbgdidr; + uint32_t dbgdevid; + uint32_t dbgdevid1; +- uint64_t id_aa64pfr0; +- uint64_t id_aa64pfr1; + uint64_t id_aa64mmfr0; + uint64_t id_aa64mmfr1; + uint64_t id_aa64mmfr2; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index b646c7bdeb..2c03735a93 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -310,16 +310,13 @@ static bool cpu_arm_get_sve(Object *obj, Error **errp) + static void cpu_arm_set_sve(Object *obj, bool value, Error **errp) + { + ARMCPU *cpu = ARM_CPU(obj); +- uint64_t t; + + if (value && kvm_enabled() && !kvm_arm_sve_supported()) { + error_setg(errp, "'sve' feature not supported by KVM on this host"); + return; + } + +- t = cpu->isar.id_aa64pfr0; +- t = FIELD_DP64(t, ID_AA64PFR0, SVE, value); +- cpu->isar.id_aa64pfr0 = t; ++ FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR0, SVE, value); + } + + void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp) +@@ -370,11 +367,8 @@ static bool cpu_arm_get_sme(Object *obj, Error **errp) + static void cpu_arm_set_sme(Object *obj, bool value, Error **errp) + { + ARMCPU *cpu = ARM_CPU(obj); +- uint64_t t; + +- t = cpu->isar.id_aa64pfr1; +- t = FIELD_DP64(t, ID_AA64PFR1, SME, value); +- cpu->isar.id_aa64pfr1 = t; ++ FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR1, SME, value); + } + + static bool cpu_arm_get_sme_fa64(Object *obj, Error **errp) +@@ -774,7 +768,7 @@ static void aarch64_a57_initfn(Object *obj) + cpu->isar.id_isar4 = 0x00011142; + cpu->isar.id_isar5 = 0x00011121; + cpu->isar.id_isar6 = 0; +- cpu->isar.id_aa64pfr0 = 0x00002222; ++ SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + cpu->isar.id_aa64dfr0 = 0x10305106; + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + cpu->isar.id_aa64mmfr0 = 0x00001124; +@@ -832,7 +826,7 @@ static void aarch64_a53_initfn(Object *obj) + cpu->isar.id_isar4 = 0x00011142; + cpu->isar.id_isar5 = 0x00011121; + cpu->isar.id_isar6 = 0; +- cpu->isar.id_aa64pfr0 = 0x00002222; ++ SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + cpu->isar.id_aa64dfr0 = 0x10305106; + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ +@@ -888,7 +882,7 @@ static void aarch64_a72_initfn(Object *obj) + cpu->isar.id_isar3 = 0x01112131; + cpu->isar.id_isar4 = 0x00011142; + cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_aa64pfr0 = 0x00002222; ++ SET_IDREG(&cpu->isar, ID_AA64PFR0, 0x00002222); + cpu->isar.id_aa64dfr0 = 0x10305106; + SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0x00011120); + cpu->isar.id_aa64mmfr0 = 0x00001124; +@@ -917,7 +911,7 @@ static void aarch64_kunpeng_920_initfn(Object *obj) + + cpu->midr = 0x480fd010; + cpu->ctr = 0x84448004; +- cpu->isar.id_aa64pfr0 = 0x11001111; ++ SET_IDREG(&cpu->isar, ID_AA64PFR0, 0x11001111); + cpu->isar.id_aa64dfr0 = 0x110305408; + SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0x10211120); + cpu->isar.id_aa64mmfr0 = 0x101125; +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 6758e82440..970cc890c0 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -7279,7 +7279,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) + static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri) + { + ARMCPU *cpu = env_archcpu(env); +- uint64_t pfr0 = cpu->isar.id_aa64pfr0; ++ uint64_t pfr0 = GET_IDREG(&cpu->isar, ID_AA64PFR0); + + if (env->gicv3state) { + pfr0 |= 1 << 24; +@@ -8368,7 +8368,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .access = PL1_R, + #ifdef CONFIG_USER_ONLY + .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_aa64pfr0 ++ .resetvalue = GET_IDREG(isar, ID_AA64PFR0) + #else + .type = ARM_CP_NO_RAW, + .accessfn = access_aa64_tid3, +@@ -8380,7 +8380,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64pfr1}, ++ .resetvalue = GET_IDREG(isar, ID_AA64PFR1)}, + { .name = "ID_AA64PFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, +diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c +index 80c1e36d10..9484d057a2 100644 +--- a/target/arm/hvf/hvf.c ++++ b/target/arm/hvf/hvf.c +@@ -842,8 +842,8 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + int reg; + uint64_t *val; + } regs[] = { +- { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.id_aa64pfr0 }, +- { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.id_aa64pfr1 }, ++ { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.idregs[ID_AA64PFR0_EL1_IDX] }, ++ { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.idregs[ID_AA64PFR1_EL1_IDX] }, + { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 }, + { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 }, + { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.idregs[ID_AA64ISAR0_EL1_IDX] }, +@@ -892,7 +892,7 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + ahcf->reset_sctlr |= 0x00800000; + + /* Make sure we don't advertise AArch32 support for EL0/EL1 */ +- if ((host_isar.id_aa64pfr0 & 0xff) != 0x11) { ++ if ((GET_IDREG(&host_isar, ID_AA64PFR0) & 0xff) != 0x11) { + return false; + } + +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 5ff37ab24d..cf61c18bfc 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -334,8 +334,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + ahcf->dtb_compatible = "arm,arm-v8"; + int fd = fdarray[2]; + +- err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0, +- ARM64_SYS_REG(3, 0, 0, 4, 0)); ++ err = get_host_cpu_reg(fd, ahcf, ID_AA64PFR0_EL1_IDX); + if (unlikely(err < 0)) { + /* + * Before v4.15, the kernel only exposed a limited number of system +@@ -353,11 +352,10 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * ??? Either of these sounds like too much effort just + * to work around running a modern host kernel. + */ +- ahcf->isar.id_aa64pfr0 = 0x00000011; /* EL1&0, AArch64 only */ ++ SET_IDREG(&ahcf->isar, ID_AA64PFR0, 0x00000011); /* EL1&0, AArch64 only */ + err = 0; + } else { +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1, +- ARM64_SYS_REG(3, 0, 0, 4, 1)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_AA64PFR1_EL1_IDX); + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64smfr0, + ARM64_SYS_REG(3, 0, 0, 4, 5)); + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0, +@@ -435,14 +433,14 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * arch/arm64/kvm/sys_regs.c:trap_dbgidr() does. + * We only do this if the CPU supports AArch32 at EL1. + */ +- if (FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL1) >= 2) { ++ if (FIELD_EX32_IDREG(&ahcf->isar, ID_AA64PFR0, EL1) >= 2) { + int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS); + int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS); + int ctx_cmps = + FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS); + int version = 6; /* ARMv8 debug architecture */ + bool has_el3 = +- !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3); ++ !!FIELD_EX32_IDREG(&ahcf->isar, ID_AA64PFR0, EL3); + uint32_t dbgdidr = 0; + + dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps); +diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c +index a62d735029..39e319e62a 100644 +--- a/target/arm/tcg/cpu64.c ++++ b/target/arm/tcg/cpu64.c +@@ -88,8 +88,8 @@ static void aarch64_a35_initfn(Object *obj) + cpu->isar.id_isar3 = 0x01112131; + cpu->isar.id_isar4 = 0x00011142; + cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_aa64pfr0 = 0x00002222; +- cpu->isar.id_aa64pfr1 = 0; ++ SET_IDREG(isar, ID_AA64PFR0, 0x00002222); ++ SET_IDREG(isar, ID_AA64PFR1, 0); + cpu->isar.id_aa64dfr0 = 0x10305106; + cpu->isar.id_aa64dfr1 = 0; + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); +@@ -180,11 +180,8 @@ static bool cpu_arm_get_rme(Object *obj, Error **errp) + static void cpu_arm_set_rme(Object *obj, bool value, Error **errp) + { + ARMCPU *cpu = ARM_CPU(obj); +- uint64_t t; + +- t = cpu->isar.id_aa64pfr0; +- t = FIELD_DP64(t, ID_AA64PFR0, RME, value); +- cpu->isar.id_aa64pfr0 = t; ++ FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR0, RME, value); + } + + static void cpu_max_set_l0gptsz(Object *obj, Visitor *v, const char *name, +@@ -249,8 +246,8 @@ static void aarch64_a55_initfn(Object *obj) + cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; +- cpu->isar.id_aa64pfr0 = 0x0000000010112222ull; +- cpu->isar.id_aa64pfr1 = 0x0000000000000010ull; ++ SET_IDREG(isar, ID_AA64PFR0, 0x0000000010112222ull); ++ SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000010ull); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_dfr0 = 0x04010088; + cpu->isar.id_isar0 = 0x02101110; +@@ -329,7 +326,7 @@ static void aarch64_a72_initfn(Object *obj) + cpu->isar.id_isar3 = 0x01112131; + cpu->isar.id_isar4 = 0x00011142; + cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_aa64pfr0 = 0x00002222; ++ SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + cpu->isar.id_aa64dfr0 = 0x10305106; + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); + cpu->isar.id_aa64mmfr0 = 0x00001124; +@@ -374,8 +371,8 @@ static void aarch64_a76_initfn(Object *obj) + cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; +- cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */ +- cpu->isar.id_aa64pfr1 = 0x0000000000000010ull; ++ SET_IDREG(isar, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */ ++ SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000010ull); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_dfr0 = 0x04010088; + cpu->isar.id_isar0 = 0x02101110; +@@ -436,8 +433,8 @@ static void aarch64_a64fx_initfn(Object *obj) + cpu->revidr = 0x00000000; + cpu->ctr = 0x86668006; + cpu->reset_sctlr = 0x30000180; +- cpu->isar.id_aa64pfr0 = 0x0000000101111111; /* No RAS Extensions */ +- cpu->isar.id_aa64pfr1 = 0x0000000000000000; ++ SET_IDREG(isar, ID_AA64PFR0, 0x0000000101111111); /* No RAS Extensions */ ++ SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000000); + cpu->isar.id_aa64dfr0 = 0x0000000010305408; + cpu->isar.id_aa64dfr1 = 0x0000000000000000; + cpu->id_aa64afr0 = 0x0000000000000000; +@@ -614,8 +611,8 @@ static void aarch64_neoverse_n1_initfn(Object *obj) + cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; +- cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */ +- cpu->isar.id_aa64pfr1 = 0x0000000000000020ull; ++ SET_IDREG(isar, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */ ++ SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000020ull); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_dfr0 = 0x04010088; + cpu->isar.id_isar0 = 0x02101110; +@@ -689,8 +686,8 @@ static void aarch64_neoverse_v1_initfn(Object *obj) + cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x0220011102101011ull; +- cpu->isar.id_aa64pfr0 = 0x1101110120111112ull; /* GIC filled in later */ +- cpu->isar.id_aa64pfr1 = 0x0000000000000020ull; ++ SET_IDREG(isar, ID_AA64PFR0, 0x1101110120111112ull); /* GIC filled in later */ ++ SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000020ull); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_dfr0 = 0x15011099; + cpu->isar.id_isar0 = 0x02101110; +@@ -922,8 +919,8 @@ static void aarch64_a710_initfn(Object *obj) + cpu->isar.mvfr1 = 0x13211111; + cpu->isar.mvfr2 = 0x00000043; + cpu->isar.id_pfr2 = 0x00000011; +- cpu->isar.id_aa64pfr0 = 0x1201111120111112ull; /* GIC filled in later */ +- cpu->isar.id_aa64pfr1 = 0x0000000000000221ull; ++ SET_IDREG(isar, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */ ++ SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000221ull); + SET_IDREG(isar, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */ + cpu->isar.id_aa64dfr0 = 0x000011f010305619ull; + cpu->isar.id_aa64dfr1 = 0; +@@ -1020,8 +1017,8 @@ static void aarch64_neoverse_n2_initfn(Object *obj) + cpu->isar.mvfr1 = 0x13211111; + cpu->isar.mvfr2 = 0x00000043; + cpu->isar.id_pfr2 = 0x00000011; +- cpu->isar.id_aa64pfr0 = 0x1201111120111112ull; /* GIC filled in later */ +- cpu->isar.id_aa64pfr1 = 0x0000000000000221ull; ++ SET_IDREG(isar, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */ ++ SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000221ull); + SET_IDREG(isar, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */ + cpu->isar.id_aa64dfr0 = 0x000011f210305619ull; + cpu->isar.id_aa64dfr1 = 0; +@@ -1152,7 +1149,7 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1); /* FEAT_HBC */ + SET_IDREG(&cpu->isar, ID_AA64ISAR2, t); + +- t = cpu->isar.id_aa64pfr0; ++ t = GET_IDREG(isar, ID_AA64PFR0); + t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); /* FEAT_FP16 */ + t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); /* FEAT_FP16 */ + t = FIELD_DP64(t, ID_AA64PFR0, RAS, 2); /* FEAT_RASv1p1 + FEAT_DoubleFault */ +@@ -1161,9 +1158,9 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */ + t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 2); /* FEAT_CSV2_2 */ + t = FIELD_DP64(t, ID_AA64PFR0, CSV3, 1); /* FEAT_CSV3 */ +- cpu->isar.id_aa64pfr0 = t; ++ SET_IDREG(isar, ID_AA64PFR0, t); + +- t = cpu->isar.id_aa64pfr1; ++ t = GET_IDREG(isar, ID_AA64PFR1); + t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); /* FEAT_BTI */ + t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2); /* FEAT_SSBS2 */ + /* +@@ -1175,7 +1172,7 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* FEAT_RASv1p1 + FEAT_DoubleFault */ + t = FIELD_DP64(t, ID_AA64PFR1, SME, 1); /* FEAT_SME */ + t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */ +- cpu->isar.id_aa64pfr1 = t; ++ SET_IDREG(isar, ID_AA64PFR1, t); + + t = cpu->isar.id_aa64mmfr0; + t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 6); /* FEAT_LPA: 52 bits */ +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Store-aa64smfr0-into-the-idregs-array.patch b/arm-cpu-Store-aa64smfr0-into-the-idregs-array.patch new file mode 100644 index 0000000000000000000000000000000000000000..379d3def5aa33f674fbd942acca2f985db7fb660 --- /dev/null +++ b/arm-cpu-Store-aa64smfr0-into-the-idregs-array.patch @@ -0,0 +1,133 @@ +From f5ffb70a17959ae7581dd5f28be0992cad029f4c Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 07/26] arm/cpu: Store aa64smfr0 into the idregs array + +Reviewed-by: Richard Henderson +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu-features.h | 6 +++--- + target/arm/cpu.h | 1 - + target/arm/cpu64.c | 7 ++----- + target/arm/helper.c | 2 +- + target/arm/kvm64.c | 3 +-- + target/arm/tcg/cpu64.c | 4 ++-- + 6 files changed, 9 insertions(+), 14 deletions(-) + +diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h +index eea88ea681..9e73c90cae 100644 +--- a/target/arm/cpu-features.h ++++ b/target/arm/cpu-features.h +@@ -920,17 +920,17 @@ static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id) + + static inline bool isar_feature_aa64_sme_f64f64(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, F64F64); ++ return FIELD_EX64_IDREG(id, ID_AA64SMFR0, F64F64); + } + + static inline bool isar_feature_aa64_sme_i16i64(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, I16I64) == 0xf; ++ return FIELD_EX64_IDREG(id, ID_AA64SMFR0, I16I64) == 0xf; + } + + static inline bool isar_feature_aa64_sme_fa64(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, FA64); ++ return FIELD_EX64_IDREG(id, ID_AA64SMFR0, FA64); + } + + /* +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index be5587411f..429b36a248 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1082,7 +1082,6 @@ struct ArchCPU { + uint32_t dbgdidr; + uint32_t dbgdevid; + uint32_t dbgdevid1; +- uint64_t id_aa64smfr0; + uint64_t reset_pmcr_el0; + uint64_t idregs[NUM_ID_IDX]; + } isar; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 3a7a8861cf..df8fc52af5 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -328,7 +328,7 @@ void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp) + + if (vq_map == 0) { + if (!cpu_isar_feature(aa64_sme, cpu)) { +- cpu->isar.id_aa64smfr0 = 0; ++ SET_IDREG(&cpu->isar, ID_AA64SMFR0, 0); + return; + } + +@@ -381,11 +381,8 @@ static bool cpu_arm_get_sme_fa64(Object *obj, Error **errp) + static void cpu_arm_set_sme_fa64(Object *obj, bool value, Error **errp) + { + ARMCPU *cpu = ARM_CPU(obj); +- uint64_t t; + +- t = cpu->isar.id_aa64smfr0; +- t = FIELD_DP64(t, ID_AA64SMFR0, FA64, value); +- cpu->isar.id_aa64smfr0 = t; ++ FIELD_DP64_IDREG(&cpu->isar, ID_AA64SMFR0, FA64, value); + } + + #ifdef CONFIG_USER_ONLY +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 46f0b4089b..0ed6c4a37e 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -8400,7 +8400,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64smfr0 }, ++ .resetvalue = GET_IDREG(isar, ID_AA64SMFR0)}, + { .name = "ID_AA64PFR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 6, + .access = PL1_R, .type = ARM_CP_CONST, +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index e46afd00bb..b50af4acd9 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -356,8 +356,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + err = 0; + } else { + err |= get_host_cpu_reg(fd, ahcf, ID_AA64PFR1_EL1_IDX); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64smfr0, +- ARM64_SYS_REG(3, 0, 0, 4, 5)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_AA64SMFR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64DFR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64DFR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_AA64ISAR0_EL1_IDX); +diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c +index b0a020c14e..04deff475e 100644 +--- a/target/arm/tcg/cpu64.c ++++ b/target/arm/tcg/cpu64.c +@@ -1229,7 +1229,7 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64DFR0, HPMN0, 1); /* FEAT_HPMN0 */ + SET_IDREG(isar, ID_AA64DFR0, t); + +- t = cpu->isar.id_aa64smfr0; ++ t = GET_IDREG(isar, ID_AA64SMFR0); + t = FIELD_DP64(t, ID_AA64SMFR0, F32F32, 1); /* FEAT_SME */ + t = FIELD_DP64(t, ID_AA64SMFR0, B16F32, 1); /* FEAT_SME */ + t = FIELD_DP64(t, ID_AA64SMFR0, F16F32, 1); /* FEAT_SME */ +@@ -1237,7 +1237,7 @@ void aarch64_max_tcg_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64SMFR0, F64F64, 1); /* FEAT_SME_F64F64 */ + t = FIELD_DP64(t, ID_AA64SMFR0, I16I64, 0xf); /* FEAT_SME_I16I64 */ + t = FIELD_DP64(t, ID_AA64SMFR0, FA64, 1); /* FEAT_SME_FA64 */ +- cpu->isar.id_aa64smfr0 = t; ++ SET_IDREG(isar, ID_AA64SMFR0, t); + + /* Replicate the same data to the 32-bit id registers. */ + aa32_max_features(cpu); +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Store-id_dfr0-1-into-the-idregs-array.patch b/arm-cpu-Store-id_dfr0-1-into-the-idregs-array.patch new file mode 100644 index 0000000000000000000000000000000000000000..85be67b83deb210d194806e04b193a3d42ac26c3 --- /dev/null +++ b/arm-cpu-Store-id_dfr0-1-into-the-idregs-array.patch @@ -0,0 +1,468 @@ +From b8c35cd5e70009f38da4b33386ebd52a20be4d70 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 10/26] arm/cpu: Store id_dfr0/1 into the idregs array + +Reviewed-by: Richard Henderson +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + hw/intc/armv7m_nvic.c | 2 +- + target/arm/cpu-features.h | 16 +++++++-------- + target/arm/cpu.c | 13 +++++------- + target/arm/cpu.h | 2 -- + target/arm/cpu64.c | 6 +++--- + target/arm/helper.c | 4 ++-- + target/arm/kvm64.c | 6 ++---- + target/arm/tcg/cpu32.c | 42 +++++++++++++++++++-------------------- + target/arm/tcg/cpu64.c | 16 +++++++-------- + 9 files changed, 49 insertions(+), 58 deletions(-) + +diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c +index b613b2cafe..d0415d9acd 100644 +--- a/hw/intc/armv7m_nvic.c ++++ b/hw/intc/armv7m_nvic.c +@@ -1274,7 +1274,7 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_dfr0; ++ return GET_IDREG(isar, ID_DFR0); + case 0xd4c: /* AFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; +diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h +index fe73988141..2af4b258de 100644 +--- a/target/arm/cpu-features.h ++++ b/target/arm/cpu-features.h +@@ -296,22 +296,22 @@ static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id) + static inline bool isar_feature_aa32_pmuv3p1(const ARMISARegisters *id) + { + /* 0xf means "non-standard IMPDEF PMU" */ +- return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 4 && +- FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; ++ return FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) >= 4 && ++ FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) != 0xf; + } + + static inline bool isar_feature_aa32_pmuv3p4(const ARMISARegisters *id) + { + /* 0xf means "non-standard IMPDEF PMU" */ +- return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 && +- FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; ++ return FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) >= 5 && ++ FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) != 0xf; + } + + static inline bool isar_feature_aa32_pmuv3p5(const ARMISARegisters *id) + { + /* 0xf means "non-standard IMPDEF PMU" */ +- return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 6 && +- FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; ++ return FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) >= 6 && ++ FIELD_EX32_IDREG(id, ID_DFR0, PERFMON) != 0xf; + } + + static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id) +@@ -356,12 +356,12 @@ static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id) + + static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 5; ++ return FIELD_EX32_IDREG(id, ID_DFR0, COPDBG) >= 5; + } + + static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8; ++ return FIELD_EX32_IDREG(id, ID_DFR0, COPDBG) >= 8; + } + + static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id) +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 60654e8630..08d83c4e1a 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2151,7 +2151,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + * feature registers as well. + */ + FIELD_DP32_IDREG(isar, ID_PFR1, SECURITY, 0); +- cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPSDBG, 0); ++ FIELD_DP32_IDREG(isar, ID_DFR0, COPSDBG, 0); + FIELD_DP64_IDREG(isar, ID_AA64PFR0, EL3, 0); + + /* Disable the realm management extension, which requires EL3. */ +@@ -2179,7 +2179,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + #endif + } else { + FIELD_DP64_IDREG(isar, ID_AA64DFR0, PMUVER, 0); +- cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0); ++ FIELD_DP32_IDREG(isar, ID_DFR0, PERFMON, 0); + cpu->pmceid0 = 0; + cpu->pmceid1 = 0; + } +@@ -2227,15 +2227,12 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEBUFFER, 0); + /* FEAT_TRF (Self-hosted Trace Extension) */ + FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEFILT, 0); +- cpu->isar.id_dfr0 = +- FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, TRACEFILT, 0); ++ FIELD_DP32_IDREG(isar, ID_DFR0, TRACEFILT, 0); + /* Trace Macrocell system register access */ + FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEVER, 0); +- cpu->isar.id_dfr0 = +- FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPTRC, 0); ++ FIELD_DP32_IDREG(isar, ID_DFR0, COPTRC, 0); + /* Memory mapped trace */ +- cpu->isar.id_dfr0 = +- FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, MMAPTRC, 0); ++ FIELD_DP32_IDREG(isar, ID_DFR0, MMAPTRC, 0); + /* FEAT_AMU (Activity Monitors Extension) */ + FIELD_DP64_IDREG(isar, ID_AA64PFR0, AMU, 0); + FIELD_DP32_IDREG(isar, ID_PFR0, AMU, 0); +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index e9ef2fd484..7b9d2bfda4 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1067,8 +1067,6 @@ struct ArchCPU { + uint32_t mvfr0; + uint32_t mvfr1; + uint32_t mvfr2; +- uint32_t id_dfr0; +- uint32_t id_dfr1; + uint32_t dbgdidr; + uint32_t dbgdevid; + uint32_t dbgdevid1; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 9d8c617aca..7cabc3c646 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -752,7 +752,7 @@ static void aarch64_a57_initfn(Object *obj) + cpu->reset_sctlr = 0x00c50838; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x00011011); +- cpu->isar.id_dfr0 = 0x03010066; ++ SET_IDREG(isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10101105; + cpu->isar.id_mmfr1 = 0x40000000; +@@ -810,7 +810,7 @@ static void aarch64_a53_initfn(Object *obj) + cpu->reset_sctlr = 0x00c50838; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x00011011); +- cpu->isar.id_dfr0 = 0x03010066; ++ SET_IDREG(isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10101105; + cpu->isar.id_mmfr1 = 0x40000000; +@@ -867,7 +867,7 @@ static void aarch64_a72_initfn(Object *obj) + cpu->reset_sctlr = 0x00c50838; + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000131); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00011011); +- cpu->isar.id_dfr0 = 0x03010066; ++ SET_IDREG(&cpu->isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 9895e8e74f..7e4a222d13 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -8248,7 +8248,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_dfr0 }, ++ .resetvalue = GET_IDREG(isar, ID_DFR0)}, + { .name = "ID_AFR0", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 3, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -8587,7 +8587,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_dfr1 }, ++ .resetvalue = GET_IDREG(isar, ID_DFR1)}, + { .name = "ID_MMFR5", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 6, + .access = PL1_R, .type = ARM_CP_CONST, +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 74eba5ce47..56d5aa70a4 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -375,8 +375,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + */ + err |= get_host_cpu_reg(fd, ahcf, ID_PFR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_PFR1_EL1_IDX); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, +- ARM64_SYS_REG(3, 0, 0, 1, 2)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_DFR0_EL1_IDX); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, + ARM64_SYS_REG(3, 0, 0, 1, 4)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, +@@ -402,8 +401,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, + ARM64_SYS_REG(3, 0, 0, 3, 2)); + err |= get_host_cpu_reg(fd, ahcf, ID_PFR2_EL1_IDX); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr1, +- ARM64_SYS_REG(3, 0, 0, 3, 5)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_DFR1_EL1_IDX); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr5, + ARM64_SYS_REG(3, 0, 0, 3, 6)); + +diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c +index 7830189672..e1a7ad654a 100644 +--- a/target/arm/tcg/cpu32.c ++++ b/target/arm/tcg/cpu32.c +@@ -85,15 +85,13 @@ void aa32_max_features(ARMCPU *cpu) + t = FIELD_DP32(t, ID_PFR2, SSBS, 1); /* FEAT_SSBS */ + SET_IDREG(isar, ID_PFR2, t); + +- t = cpu->isar.id_dfr0; ++ t = GET_IDREG(isar, ID_DFR0); + t = FIELD_DP32(t, ID_DFR0, COPDBG, 9); /* FEAT_Debugv8p4 */ + t = FIELD_DP32(t, ID_DFR0, COPSDBG, 9); /* FEAT_Debugv8p4 */ + t = FIELD_DP32(t, ID_DFR0, PERFMON, 6); /* FEAT_PMUv3p5 */ +- cpu->isar.id_dfr0 = t; ++ SET_IDREG(isar, ID_DFR0, t); + +- t = cpu->isar.id_dfr1; +- t = FIELD_DP32(t, ID_DFR1, HPMN0, 1); /* FEAT_HPMN0 */ +- cpu->isar.id_dfr1 = t; ++ FIELD_DP32_IDREG(isar, ID_DFR1, HPMN0, 1); /* FEAT_HPMN0 */ + } + + /* CPU models. These are not needed for the AArch64 linux-user build. */ +@@ -231,7 +229,7 @@ static void arm1136_r2_initfn(Object *obj) + cpu->reset_sctlr = 0x00050078; + SET_IDREG(isar, ID_PFR0, 0x111); + SET_IDREG(isar, ID_PFR1, 0x1); +- cpu->isar.id_dfr0 = 0x2; ++ SET_IDREG(isar, ID_DFR0, 0x2); + cpu->id_afr0 = 0x3; + cpu->isar.id_mmfr0 = 0x01130003; + cpu->isar.id_mmfr1 = 0x10030302; +@@ -263,7 +261,7 @@ static void arm1136_initfn(Object *obj) + cpu->reset_sctlr = 0x00050078; + SET_IDREG(isar, ID_PFR0, 0x111); + SET_IDREG(isar, ID_PFR1, 0x1); +- cpu->isar.id_dfr0 = 0x2; ++ SET_IDREG(isar, ID_DFR0, 0x2); + cpu->id_afr0 = 0x3; + cpu->isar.id_mmfr0 = 0x01130003; + cpu->isar.id_mmfr1 = 0x10030302; +@@ -296,7 +294,7 @@ static void arm1176_initfn(Object *obj) + cpu->reset_sctlr = 0x00050078; + SET_IDREG(isar, ID_PFR0, 0x111); + SET_IDREG(isar, ID_PFR1, 0x11); +- cpu->isar.id_dfr0 = 0x33; ++ SET_IDREG(isar, ID_DFR0, 0x33); + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x01130003; + cpu->isar.id_mmfr1 = 0x10030302; +@@ -326,7 +324,7 @@ static void arm11mpcore_initfn(Object *obj) + cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ + SET_IDREG(isar, ID_PFR0, 0x111); + SET_IDREG(isar, ID_PFR1, 0x1); +- cpu->isar.id_dfr0 = 0; ++ SET_IDREG(isar, ID_DFR0, 0); + cpu->id_afr0 = 0x2; + cpu->isar.id_mmfr0 = 0x01100103; + cpu->isar.id_mmfr1 = 0x10020302; +@@ -366,7 +364,7 @@ static void cortex_a8_initfn(Object *obj) + cpu->reset_sctlr = 0x00c50078; + SET_IDREG(isar, ID_PFR0, 0x1031); + SET_IDREG(isar, ID_PFR1, 0x11); +- cpu->isar.id_dfr0 = 0x400; ++ SET_IDREG(isar, ID_DFR0, 0x400); + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x31100003; + cpu->isar.id_mmfr1 = 0x20000000; +@@ -442,7 +440,7 @@ static void cortex_a9_initfn(Object *obj) + cpu->reset_sctlr = 0x00c50078; + SET_IDREG(isar, ID_PFR0, 0x1031); + SET_IDREG(isar, ID_PFR1, 0x11); +- cpu->isar.id_dfr0 = 0x000; ++ SET_IDREG(isar, ID_DFR0, 0x000); + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x00100103; + cpu->isar.id_mmfr1 = 0x20000000; +@@ -507,7 +505,7 @@ static void cortex_a7_initfn(Object *obj) + cpu->reset_sctlr = 0x00c50078; + SET_IDREG(isar, ID_PFR0, 0x00001131); + SET_IDREG(isar, ID_PFR1, 0x00011011); +- cpu->isar.id_dfr0 = 0x02010555; ++ SET_IDREG(isar, ID_DFR0, 0x02010555); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10101105; + cpu->isar.id_mmfr1 = 0x40000000; +@@ -558,7 +556,7 @@ static void cortex_a15_initfn(Object *obj) + cpu->reset_sctlr = 0x00c50078; + SET_IDREG(isar, ID_PFR0, 0x00001131); + SET_IDREG(isar, ID_PFR1, 0x00011011); +- cpu->isar.id_dfr0 = 0x02010555; ++ SET_IDREG(isar, ID_DFR0, 0x02010555); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x20000000; +@@ -600,7 +598,7 @@ static void cortex_m0_initfn(Object *obj) + */ + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); +- cpu->isar.id_dfr0 = 0x00100000; ++ SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00000030; + cpu->isar.id_mmfr1 = 0x00000000; +@@ -627,7 +625,7 @@ static void cortex_m3_initfn(Object *obj) + cpu->pmsav7_dregion = 8; + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); +- cpu->isar.id_dfr0 = 0x00100000; ++ SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00000030; + cpu->isar.id_mmfr1 = 0x00000000; +@@ -658,7 +656,7 @@ static void cortex_m4_initfn(Object *obj) + cpu->isar.mvfr2 = 0x00000000; + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); +- cpu->isar.id_dfr0 = 0x00100000; ++ SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00000030; + cpu->isar.id_mmfr1 = 0x00000000; +@@ -689,7 +687,7 @@ static void cortex_m7_initfn(Object *obj) + cpu->isar.mvfr2 = 0x00000040; + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); +- cpu->isar.id_dfr0 = 0x00100000; ++ SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00100030; + cpu->isar.id_mmfr1 = 0x00000000; +@@ -722,7 +720,7 @@ static void cortex_m33_initfn(Object *obj) + cpu->isar.mvfr2 = 0x00000040; + SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000210); +- cpu->isar.id_dfr0 = 0x00200000; ++ SET_IDREG(&cpu->isar, ID_DFR0, 0x00200000); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00101F40; + cpu->isar.id_mmfr1 = 0x00000000; +@@ -760,7 +758,7 @@ static void cortex_m55_initfn(Object *obj) + cpu->isar.mvfr2 = 0x00000040; + SET_IDREG(&cpu->isar, ID_PFR0, 0x20000030); + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000230); +- cpu->isar.id_dfr0 = 0x10200000; ++ SET_IDREG(&cpu->isar, ID_DFR0, 0x10200000); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00111040; + cpu->isar.id_mmfr1 = 0x00000000; +@@ -799,7 +797,7 @@ static void cortex_r5_initfn(Object *obj) + cpu->midr = 0x411fc153; /* r1p3 */ + SET_IDREG(isar, ID_PFR0, 0x0131); + SET_IDREG(isar, ID_PFR1, 0x001); +- cpu->isar.id_dfr0 = 0x010400; ++ SET_IDREG(isar, ID_DFR0, 0x010400); + cpu->id_afr0 = 0x0; + cpu->isar.id_mmfr0 = 0x0210030; + cpu->isar.id_mmfr1 = 0x00000000; +@@ -838,7 +836,7 @@ static void cortex_r52_initfn(Object *obj) + cpu->reset_sctlr = 0x30c50838; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x10111001); +- cpu->isar.id_dfr0 = 0x03010006; ++ SET_IDREG(isar, ID_DFR0, 0x03010006); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00211040; + cpu->isar.id_mmfr1 = 0x40000000; +@@ -1098,7 +1096,7 @@ static void arm_max_initfn(Object *obj) + cpu->reset_sctlr = 0x00c50838; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x00011011); +- cpu->isar.id_dfr0 = 0x03010066; ++ SET_IDREG(isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10101105; + cpu->isar.id_mmfr1 = 0x40000000; +diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c +index dbfeeb92a0..6646f265ee 100644 +--- a/target/arm/tcg/cpu64.c ++++ b/target/arm/tcg/cpu64.c +@@ -76,7 +76,7 @@ static void aarch64_a35_initfn(Object *obj) + cpu->ctr = 0x84448004; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x00011011); +- cpu->isar.id_dfr0 = 0x03010066; ++ SET_IDREG(isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; +@@ -249,7 +249,7 @@ static void aarch64_a55_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR0, 0x0000000010112222ull); + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000010ull); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_dfr0 = 0x04010088; ++ SET_IDREG(isar, ID_DFR0, 0x04010088); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); +@@ -314,7 +314,7 @@ static void aarch64_a72_initfn(Object *obj) + cpu->reset_sctlr = 0x00c50838; + SET_IDREG(isar, ID_PFR0, 0x00000131); + SET_IDREG(isar, ID_PFR1, 0x00011011); +- cpu->isar.id_dfr0 = 0x03010066; ++ SET_IDREG(isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; +@@ -374,7 +374,7 @@ static void aarch64_a76_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000010ull); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_dfr0 = 0x04010088; ++ SET_IDREG(isar, ID_DFR0, 0x04010088); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); +@@ -614,7 +614,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR0, 0x1100000010111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000020ull); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_dfr0 = 0x04010088; ++ SET_IDREG(isar, ID_DFR0, 0x04010088); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); +@@ -689,7 +689,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR0, 0x1101110120111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000020ull); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_dfr0 = 0x15011099; ++ SET_IDREG(isar, ID_DFR0, 0x15011099); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); +@@ -901,7 +901,7 @@ static void aarch64_a710_initfn(Object *obj) + cpu->revidr = 0; + SET_IDREG(isar, ID_PFR0, 0x21110131); + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ +- cpu->isar.id_dfr0 = 0x16011099; ++ SET_IDREG(isar, ID_DFR0, 0x16011099); + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; +@@ -999,7 +999,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj) + cpu->revidr = 0; + SET_IDREG(isar, ID_PFR0, 0x21110131); + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ +- cpu->isar.id_dfr0 = 0x16011099; ++ SET_IDREG(isar, ID_DFR0, 0x16011099); + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Store-id_isar0-7-into-the-idregs-array.patch b/arm-cpu-Store-id_isar0-7-into-the-idregs-array.patch new file mode 100644 index 0000000000000000000000000000000000000000..ff8d8468ad4c225d207dd626d49e11ce1a629ae1 --- /dev/null +++ b/arm-cpu-Store-id_isar0-7-into-the-idregs-array.patch @@ -0,0 +1,1093 @@ +From 72b11b40f42ed3d919f355d52b1a77c6b530c7d1 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 08/26] arm/cpu: Store id_isar0-7 into the idregs array + +Reviewed-by: Richard Henderson +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + hw/intc/armv7m_nvic.c | 12 +- + target/arm/cpu-features.h | 36 +++--- + target/arm/cpu.c | 24 ++-- + target/arm/cpu.h | 7 -- + target/arm/cpu64.c | 40 +++---- + target/arm/helper.c | 14 +-- + target/arm/kvm64.c | 21 ++-- + target/arm/tcg/cpu32.c | 236 +++++++++++++++++++++----------------- + target/arm/tcg/cpu64.c | 108 ++++++++--------- + 9 files changed, 251 insertions(+), 247 deletions(-) + +diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c +index 942be7bd11..5f68b0e711 100644 +--- a/hw/intc/armv7m_nvic.c ++++ b/hw/intc/armv7m_nvic.c +@@ -1303,32 +1303,32 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar0; ++ return GET_IDREG(&cpu->isar, ID_ISAR0); + case 0xd64: /* ISAR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar1; ++ return GET_IDREG(&cpu->isar, ID_ISAR1); + case 0xd68: /* ISAR2. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar2; ++ return GET_IDREG(&cpu->isar, ID_ISAR2); + case 0xd6c: /* ISAR3. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar3; ++ return GET_IDREG(&cpu->isar, ID_ISAR3); + case 0xd70: /* ISAR4. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar4; ++ return GET_IDREG(&cpu->isar, ID_ISAR4); + case 0xd74: /* ISAR5. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_isar5; ++ return GET_IDREG(&cpu->isar, ID_ISAR5); + case 0xd78: /* CLIDR */ + return cpu->clidr; + case 0xd7c: /* CTR */ +diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h +index 9e73c90cae..25180e4b77 100644 +--- a/target/arm/cpu-features.h ++++ b/target/arm/cpu-features.h +@@ -42,93 +42,93 @@ + */ + static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR0, DIVIDE) != 0; + } + + static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1; ++ return FIELD_EX32_IDREG(id, ID_ISAR0, DIVIDE) > 1; + } + + static inline bool isar_feature_aa32_lob(const ARMISARegisters *id) + { + /* (M-profile) low-overhead loops and branch future */ +- return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3; ++ return FIELD_EX32_IDREG(id, ID_ISAR0, CMPBRANCH) >= 3; + } + + static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR1, JAZELLE) != 0; + } + + static inline bool isar_feature_aa32_aes(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR5, AES) != 0; + } + + static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) > 1; ++ return FIELD_EX32_IDREG(id, ID_ISAR5, AES) > 1; + } + + static inline bool isar_feature_aa32_sha1(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA1) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR5, SHA1) != 0; + } + + static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA2) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR5, SHA2) != 0; + } + + static inline bool isar_feature_aa32_crc32(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, CRC32) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR5, CRC32) != 0; + } + + static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, RDM) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR5, RDM) != 0; + } + + static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR5, VCMA) != 0; + } + + static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR6, JSCVT) != 0; + } + + static inline bool isar_feature_aa32_dp(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR6, DP) != 0; + } + + static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR6, FHM) != 0; + } + + static inline bool isar_feature_aa32_sb(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR6, SB) != 0; + } + + static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR6, SPECRES) != 0; + } + + static inline bool isar_feature_aa32_bf16(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, BF16) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR6, BF16) != 0; + } + + static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, I8MM) != 0; ++ return FIELD_EX32_IDREG(id, ID_ISAR6, I8MM) != 0; + } + + static inline bool isar_feature_aa32_ras(const ARMISARegisters *id) +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 22c3335522..7667530e9d 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1967,10 +1967,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + + FIELD_DP64_IDREG(isar, ID_AA64PFR0, FP, 0xf); + +- u = cpu->isar.id_isar6; ++ u = GET_IDREG(isar, ID_ISAR6); + u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0); + u = FIELD_DP32(u, ID_ISAR6, BF16, 0); +- cpu->isar.id_isar6 = u; ++ SET_IDREG(isar, ID_ISAR6, u); + + u = cpu->isar.mvfr0; + u = FIELD_DP32(u, MVFR0, FPSP, 0); +@@ -2022,20 +2022,20 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + + FIELD_DP64_IDREG(isar, ID_AA64PFR0, ADVSIMD, 0xf); + +- u = cpu->isar.id_isar5; ++ u = GET_IDREG(isar, ID_ISAR5); + u = FIELD_DP32(u, ID_ISAR5, AES, 0); + u = FIELD_DP32(u, ID_ISAR5, SHA1, 0); + u = FIELD_DP32(u, ID_ISAR5, SHA2, 0); + u = FIELD_DP32(u, ID_ISAR5, RDM, 0); + u = FIELD_DP32(u, ID_ISAR5, VCMA, 0); +- cpu->isar.id_isar5 = u; ++ SET_IDREG(isar, ID_ISAR5, u); + +- u = cpu->isar.id_isar6; ++ u = GET_IDREG(isar, ID_ISAR6); + u = FIELD_DP32(u, ID_ISAR6, DP, 0); + u = FIELD_DP32(u, ID_ISAR6, FHM, 0); + u = FIELD_DP32(u, ID_ISAR6, BF16, 0); + u = FIELD_DP32(u, ID_ISAR6, I8MM, 0); +- cpu->isar.id_isar6 = u; ++ SET_IDREG(isar, ID_ISAR6, u); + + if (!arm_feature(env, ARM_FEATURE_M)) { + u = cpu->isar.mvfr1; +@@ -2073,19 +2073,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + + unset_feature(env, ARM_FEATURE_THUMB_DSP); + +- u = cpu->isar.id_isar1; +- u = FIELD_DP32(u, ID_ISAR1, EXTEND, 1); +- cpu->isar.id_isar1 = u; ++ FIELD_DP32_IDREG(isar, ID_ISAR1, EXTEND, 1); + +- u = cpu->isar.id_isar2; ++ u = GET_IDREG(isar, ID_ISAR2); + u = FIELD_DP32(u, ID_ISAR2, MULTU, 1); + u = FIELD_DP32(u, ID_ISAR2, MULTS, 1); +- cpu->isar.id_isar2 = u; ++ SET_IDREG(isar, ID_ISAR2, u); + +- u = cpu->isar.id_isar3; ++ u = GET_IDREG(isar, ID_ISAR3); + u = FIELD_DP32(u, ID_ISAR3, SIMD, 1); + u = FIELD_DP32(u, ID_ISAR3, SATURATE, 0); +- cpu->isar.id_isar3 = u; ++ SET_IDREG(isar, ID_ISAR3, u); + } + + +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 429b36a248..4c29657ec7 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1058,13 +1058,6 @@ struct ArchCPU { + * field by reading the value from the KVM vCPU. + */ + struct ARMISARegisters { +- uint32_t id_isar0; +- uint32_t id_isar1; +- uint32_t id_isar2; +- uint32_t id_isar3; +- uint32_t id_isar4; +- uint32_t id_isar5; +- uint32_t id_isar6; + uint32_t id_mmfr0; + uint32_t id_mmfr1; + uint32_t id_mmfr2; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index df8fc52af5..9495bc418e 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -758,13 +758,13 @@ static void aarch64_a57_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_isar6 = 0; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00011142); ++ SET_IDREG(isar, ID_ISAR5, 0x00011121); ++ SET_IDREG(isar, ID_ISAR6, 0); + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + SET_IDREG(isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); +@@ -816,13 +816,13 @@ static void aarch64_a53_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_isar6 = 0; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00011142); ++ SET_IDREG(isar, ID_ISAR5, 0x00011121); ++ SET_IDREG(isar, ID_ISAR6, 0); + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + SET_IDREG(isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); +@@ -873,12 +873,12 @@ static void aarch64_a72_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; ++ SET_IDREG(&cpu->isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(&cpu->isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(&cpu->isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(&cpu->isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(&cpu->isar, ID_ISAR4, 0x00011142); ++ SET_IDREG(&cpu->isar, ID_ISAR5, 0x00011121); + SET_IDREG(&cpu->isar, ID_AA64PFR0, 0x00002222); + SET_IDREG(&cpu->isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(&cpu->isar, ID_AA64ISAR0, 0x00011120); +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 0ed6c4a37e..d2d9de8b0b 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -8278,32 +8278,32 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar0 }, ++ .resetvalue = GET_IDREG(isar, ID_ISAR0)}, + { .name = "ID_ISAR1", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar1 }, ++ .resetvalue = GET_IDREG(isar, ID_ISAR1)}, + { .name = "ID_ISAR2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar2 }, ++ .resetvalue = GET_IDREG(isar, ID_ISAR2)}, + { .name = "ID_ISAR3", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 3, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar3 }, ++ .resetvalue = GET_IDREG(isar, ID_ISAR3) }, + { .name = "ID_ISAR4", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 4, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar4 }, ++ .resetvalue = GET_IDREG(isar, ID_ISAR4) }, + { .name = "ID_ISAR5", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar5 }, ++ .resetvalue = GET_IDREG(isar, ID_ISAR5) }, + { .name = "ID_MMFR4", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -8313,7 +8313,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_isar6 }, ++ .resetvalue = GET_IDREG(isar, ID_ISAR6) }, + }; + define_arm_cp_regs(cpu, v6_idregs); + define_arm_cp_regs(cpu, v6_cp_reginfo); +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index b50af4acd9..2e57ba4224 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -387,22 +387,15 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + ARM64_SYS_REG(3, 0, 0, 1, 6)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3, + ARM64_SYS_REG(3, 0, 0, 1, 7)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0, +- ARM64_SYS_REG(3, 0, 0, 2, 0)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1, +- ARM64_SYS_REG(3, 0, 0, 2, 1)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2, +- ARM64_SYS_REG(3, 0, 0, 2, 2)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3, +- ARM64_SYS_REG(3, 0, 0, 2, 3)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4, +- ARM64_SYS_REG(3, 0, 0, 2, 4)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5, +- ARM64_SYS_REG(3, 0, 0, 2, 5)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_ISAR0_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_ISAR1_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_ISAR2_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_ISAR3_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_ISAR4_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_ISAR5_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_ISAR6_EL1_IDX); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4, + ARM64_SYS_REG(3, 0, 0, 2, 6)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6, +- ARM64_SYS_REG(3, 0, 0, 2, 7)); + + err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, + ARM64_SYS_REG(3, 0, 0, 3, 0)); +diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c +index d9e0e2a4dd..dbf2070a81 100644 +--- a/target/arm/tcg/cpu32.c ++++ b/target/arm/tcg/cpu32.c +@@ -26,18 +26,19 @@ + void aa32_max_features(ARMCPU *cpu) + { + uint32_t t; ++ ARMISARegisters *isar = &cpu->isar; + + /* Add additional features supported by QEMU */ +- t = cpu->isar.id_isar5; ++ t = GET_IDREG(isar, ID_ISAR5); + t = FIELD_DP32(t, ID_ISAR5, AES, 2); /* FEAT_PMULL */ + t = FIELD_DP32(t, ID_ISAR5, SHA1, 1); /* FEAT_SHA1 */ + t = FIELD_DP32(t, ID_ISAR5, SHA2, 1); /* FEAT_SHA256 */ + t = FIELD_DP32(t, ID_ISAR5, CRC32, 1); + t = FIELD_DP32(t, ID_ISAR5, RDM, 1); /* FEAT_RDM */ + t = FIELD_DP32(t, ID_ISAR5, VCMA, 1); /* FEAT_FCMA */ +- cpu->isar.id_isar5 = t; ++ SET_IDREG(isar, ID_ISAR5, t); + +- t = cpu->isar.id_isar6; ++ t = GET_IDREG(isar, ID_ISAR6); + t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1); /* FEAT_JSCVT */ + t = FIELD_DP32(t, ID_ISAR6, DP, 1); /* Feat_DotProd */ + t = FIELD_DP32(t, ID_ISAR6, FHM, 1); /* FEAT_FHM */ +@@ -45,7 +46,7 @@ void aa32_max_features(ARMCPU *cpu) + t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); /* FEAT_SPECRES */ + t = FIELD_DP32(t, ID_ISAR6, BF16, 1); /* FEAT_AA32BF16 */ + t = FIELD_DP32(t, ID_ISAR6, I8MM, 1); /* FEAT_AA32I8MM */ +- cpu->isar.id_isar6 = t; ++ SET_IDREG(isar, ID_ISAR6, t); + + t = cpu->isar.mvfr1; + t = FIELD_DP32(t, MVFR1, FPHP, 3); /* FEAT_FP16 */ +@@ -141,7 +142,7 @@ static void arm926_initfn(Object *obj) + * ARMv5 does not have the ID_ISAR registers, but we can still + * set the field to indicate Jazelle support within QEMU. + */ +- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); ++ FIELD_DP32_IDREG(&cpu->isar, ID_ISAR1, JAZELLE, 1); + /* + * Similarly, we need to set MVFR0 fields to enable vfp and short vector + * support even though ARMv5 doesn't have this register. +@@ -183,7 +184,7 @@ static void arm1026_initfn(Object *obj) + * ARMv5 does not have the ID_ISAR registers, but we can still + * set the field to indicate Jazelle support within QEMU. + */ +- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); ++ FIELD_DP32_IDREG(&cpu->isar, ID_ISAR1, JAZELLE, 1); + /* + * Similarly, we need to set MVFR0 fields to enable vfp and short vector + * support even though ARMv5 doesn't have this register. +@@ -207,6 +208,7 @@ static void arm1026_initfn(Object *obj) + static void arm1136_r2_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + /* + * What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an + * older core than plain "arm1136". In particular this does not +@@ -234,17 +236,18 @@ static void arm1136_r2_initfn(Object *obj) + cpu->isar.id_mmfr0 = 0x01130003; + cpu->isar.id_mmfr1 = 0x10030302; + cpu->isar.id_mmfr2 = 0x01222110; +- cpu->isar.id_isar0 = 0x00140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231111; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ SET_IDREG(isar, ID_ISAR0, 0x00140011); ++ SET_IDREG(isar, ID_ISAR1, 0x12002111); ++ SET_IDREG(isar, ID_ISAR2, 0x11231111); ++ SET_IDREG(isar, ID_ISAR3, 0x01102131); ++ SET_IDREG(isar, ID_ISAR4, 0x141); + cpu->reset_auxcr = 7; + } + + static void arm1136_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,arm1136"; + set_feature(&cpu->env, ARM_FEATURE_V6K); +@@ -265,17 +268,18 @@ static void arm1136_initfn(Object *obj) + cpu->isar.id_mmfr0 = 0x01130003; + cpu->isar.id_mmfr1 = 0x10030302; + cpu->isar.id_mmfr2 = 0x01222110; +- cpu->isar.id_isar0 = 0x00140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231111; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ SET_IDREG(isar, ID_ISAR0, 0x00140011); ++ SET_IDREG(isar, ID_ISAR1, 0x12002111); ++ SET_IDREG(isar, ID_ISAR2, 0x11231111); ++ SET_IDREG(isar, ID_ISAR3, 0x01102131); ++ SET_IDREG(isar, ID_ISAR4, 0x141); + cpu->reset_auxcr = 7; + } + + static void arm1176_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,arm1176"; + set_feature(&cpu->env, ARM_FEATURE_V6K); +@@ -297,17 +301,18 @@ static void arm1176_initfn(Object *obj) + cpu->isar.id_mmfr0 = 0x01130003; + cpu->isar.id_mmfr1 = 0x10030302; + cpu->isar.id_mmfr2 = 0x01222100; +- cpu->isar.id_isar0 = 0x0140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231121; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x01141; ++ SET_IDREG(isar, ID_ISAR0, 0x0140011); ++ SET_IDREG(isar, ID_ISAR1, 0x12002111); ++ SET_IDREG(isar, ID_ISAR2, 0x11231121); ++ SET_IDREG(isar, ID_ISAR3, 0x01102131); ++ SET_IDREG(isar, ID_ISAR4, 0x01141); + cpu->reset_auxcr = 7; + } + + static void arm11mpcore_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,arm11mpcore"; + set_feature(&cpu->env, ARM_FEATURE_V6K); +@@ -326,11 +331,11 @@ static void arm11mpcore_initfn(Object *obj) + cpu->isar.id_mmfr0 = 0x01100103; + cpu->isar.id_mmfr1 = 0x10020302; + cpu->isar.id_mmfr2 = 0x01222000; +- cpu->isar.id_isar0 = 0x00100011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11221011; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ SET_IDREG(isar, ID_ISAR0, 0x00100011); ++ SET_IDREG(isar, ID_ISAR1, 0x12002111); ++ SET_IDREG(isar, ID_ISAR2, 0x11221011); ++ SET_IDREG(isar, ID_ISAR3, 0x01102131); ++ SET_IDREG(isar, ID_ISAR4, 0x141); + cpu->reset_auxcr = 1; + } + +@@ -344,6 +349,7 @@ static const ARMCPRegInfo cortexa8_cp_reginfo[] = { + static void cortex_a8_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,cortex-a8"; + set_feature(&cpu->env, ARM_FEATURE_V7); +@@ -366,11 +372,11 @@ static void cortex_a8_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x20000000; + cpu->isar.id_mmfr2 = 0x01202000; + cpu->isar.id_mmfr3 = 0x11; +- cpu->isar.id_isar0 = 0x00101111; +- cpu->isar.id_isar1 = 0x12112111; +- cpu->isar.id_isar2 = 0x21232031; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x00111142; ++ SET_IDREG(isar, ID_ISAR0, 0x00101111); ++ SET_IDREG(isar, ID_ISAR1, 0x12112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232031); ++ SET_IDREG(isar, ID_ISAR3, 0x11112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00111142); + cpu->isar.dbgdidr = 0x15141000; + cpu->clidr = (1 << 27) | (2 << 24) | 3; + cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */ +@@ -413,6 +419,7 @@ static const ARMCPRegInfo cortexa9_cp_reginfo[] = { + static void cortex_a9_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,cortex-a9"; + set_feature(&cpu->env, ARM_FEATURE_V7); +@@ -441,11 +448,11 @@ static void cortex_a9_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x20000000; + cpu->isar.id_mmfr2 = 0x01230000; + cpu->isar.id_mmfr3 = 0x00002111; +- cpu->isar.id_isar0 = 0x00101111; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232041; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x00111142; ++ SET_IDREG(isar, ID_ISAR0, 0x00101111); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232041); ++ SET_IDREG(isar, ID_ISAR3, 0x11112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00111142); + cpu->isar.dbgdidr = 0x35141000; + cpu->clidr = (1 << 27) | (1 << 24) | 3; + cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */ +@@ -480,6 +487,7 @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = { + static void cortex_a7_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,cortex-a7"; + set_feature(&cpu->env, ARM_FEATURE_V7VE); +@@ -509,11 +517,11 @@ static void cortex_a7_initfn(Object *obj) + * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but + * table 4-41 gives 0x02101110, which includes the arm div insns. + */ +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232041; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x10011142; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232041); ++ SET_IDREG(isar, ID_ISAR3, 0x11112131); ++ SET_IDREG(isar, ID_ISAR4, 0x10011142); + cpu->isar.dbgdidr = 0x3515f005; + cpu->isar.dbgdevid = 0x01110f13; + cpu->isar.dbgdevid1 = 0x1; +@@ -528,6 +536,7 @@ static void cortex_a7_initfn(Object *obj) + static void cortex_a15_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + cpu->dtb_compatible = "arm,cortex-a15"; + set_feature(&cpu->env, ARM_FEATURE_V7VE); +@@ -555,11 +564,11 @@ static void cortex_a15_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x20000000; + cpu->isar.id_mmfr2 = 0x01240000; + cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232041; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x10011142; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232041); ++ SET_IDREG(isar, ID_ISAR3, 0x11112131); ++ SET_IDREG(isar, ID_ISAR4, 0x10011142); + cpu->isar.dbgdidr = 0x3515f021; + cpu->isar.dbgdevid = 0x01110f13; + cpu->isar.dbgdevid1 = 0x0; +@@ -574,6 +583,8 @@ static void cortex_a15_initfn(Object *obj) + static void cortex_m0_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; ++ + set_feature(&cpu->env, ARM_FEATURE_V6); + set_feature(&cpu->env, ARM_FEATURE_M); + +@@ -595,18 +606,20 @@ static void cortex_m0_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x00000000; + cpu->isar.id_mmfr2 = 0x00000000; + cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01141110; +- cpu->isar.id_isar1 = 0x02111000; +- cpu->isar.id_isar2 = 0x21112231; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ SET_IDREG(isar, ID_ISAR0, 0x01141110); ++ SET_IDREG(isar, ID_ISAR1, 0x02111000); ++ SET_IDREG(isar, ID_ISAR2, 0x21112231); ++ SET_IDREG(isar, ID_ISAR3, 0x01111110); ++ SET_IDREG(isar, ID_ISAR4, 0x01310102); ++ SET_IDREG(isar, ID_ISAR5, 0); ++ SET_IDREG(isar, ID_ISAR6, 0); + } + + static void cortex_m3_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; ++ + set_feature(&cpu->env, ARM_FEATURE_V7); + set_feature(&cpu->env, ARM_FEATURE_M); + set_feature(&cpu->env, ARM_FEATURE_M_MAIN); +@@ -620,18 +633,19 @@ static void cortex_m3_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x00000000; + cpu->isar.id_mmfr2 = 0x00000000; + cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01141110; +- cpu->isar.id_isar1 = 0x02111000; +- cpu->isar.id_isar2 = 0x21112231; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ SET_IDREG(isar, ID_ISAR0, 0x01141110); ++ SET_IDREG(isar, ID_ISAR1, 0x02111000); ++ SET_IDREG(isar, ID_ISAR2, 0x21112231); ++ SET_IDREG(isar, ID_ISAR3, 0x01111110); ++ SET_IDREG(isar, ID_ISAR4, 0x01310102); ++ SET_IDREG(isar, ID_ISAR5, 0); ++ SET_IDREG(isar, ID_ISAR6, 0); + } + + static void cortex_m4_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + set_feature(&cpu->env, ARM_FEATURE_V7); + set_feature(&cpu->env, ARM_FEATURE_M); +@@ -650,18 +664,19 @@ static void cortex_m4_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x00000000; + cpu->isar.id_mmfr2 = 0x00000000; + cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01141110; +- cpu->isar.id_isar1 = 0x02111000; +- cpu->isar.id_isar2 = 0x21112231; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ SET_IDREG(isar, ID_ISAR0, 0x01141110); ++ SET_IDREG(isar, ID_ISAR1, 0x02111000); ++ SET_IDREG(isar, ID_ISAR2, 0x21112231); ++ SET_IDREG(isar, ID_ISAR3, 0x01111110); ++ SET_IDREG(isar, ID_ISAR4, 0x01310102); ++ SET_IDREG(isar, ID_ISAR5, 0); ++ SET_IDREG(isar, ID_ISAR6, 0); + } + + static void cortex_m7_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + set_feature(&cpu->env, ARM_FEATURE_V7); + set_feature(&cpu->env, ARM_FEATURE_M); +@@ -680,18 +695,19 @@ static void cortex_m7_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x00000000; + cpu->isar.id_mmfr2 = 0x01000000; + cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01101110; +- cpu->isar.id_isar1 = 0x02112000; +- cpu->isar.id_isar2 = 0x20232231; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ SET_IDREG(isar, ID_ISAR0, 0x01101110); ++ SET_IDREG(isar, ID_ISAR1, 0x02112000); ++ SET_IDREG(isar, ID_ISAR2, 0x20232231); ++ SET_IDREG(isar, ID_ISAR3, 0x01111131); ++ SET_IDREG(isar, ID_ISAR4, 0x01310132); ++ SET_IDREG(isar, ID_ISAR5, 0); ++ SET_IDREG(isar, ID_ISAR6, 0); + } + + static void cortex_m33_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_M); +@@ -712,13 +728,13 @@ static void cortex_m33_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x00000000; + cpu->isar.id_mmfr2 = 0x01000000; + cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01101110; +- cpu->isar.id_isar1 = 0x02212000; +- cpu->isar.id_isar2 = 0x20232232; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ SET_IDREG(isar, ID_ISAR0, 0x01101110); ++ SET_IDREG(isar, ID_ISAR1, 0x02212000); ++ SET_IDREG(isar, ID_ISAR2, 0x20232232); ++ SET_IDREG(isar, ID_ISAR3, 0x01111131); ++ SET_IDREG(isar, ID_ISAR4, 0x01310132); ++ SET_IDREG(isar, ID_ISAR5, 0); ++ SET_IDREG(isar, ID_ISAR6, 0); + cpu->clidr = 0x00000000; + cpu->ctr = 0x8000c000; + } +@@ -726,6 +742,7 @@ static void cortex_m33_initfn(Object *obj) + static void cortex_m55_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_V8_1M); +@@ -749,13 +766,13 @@ static void cortex_m55_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x00000000; + cpu->isar.id_mmfr2 = 0x01000000; + cpu->isar.id_mmfr3 = 0x00000011; +- cpu->isar.id_isar0 = 0x01103110; +- cpu->isar.id_isar1 = 0x02212000; +- cpu->isar.id_isar2 = 0x20232232; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ SET_IDREG(isar, ID_ISAR0, 0x01103110); ++ SET_IDREG(isar, ID_ISAR1, 0x02212000); ++ SET_IDREG(isar, ID_ISAR2, 0x20232232); ++ SET_IDREG(isar, ID_ISAR3, 0x01111131); ++ SET_IDREG(isar, ID_ISAR4, 0x01310132); ++ SET_IDREG(isar, ID_ISAR5, 0); ++ SET_IDREG(isar, ID_ISAR6, 0); + cpu->clidr = 0x00000000; /* caches not implemented */ + cpu->ctr = 0x8303c003; + } +@@ -773,6 +790,7 @@ static const ARMCPRegInfo cortexr5_cp_reginfo[] = { + static void cortex_r5_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + set_feature(&cpu->env, ARM_FEATURE_V7); + set_feature(&cpu->env, ARM_FEATURE_V7MP); +@@ -787,13 +805,13 @@ static void cortex_r5_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x00000000; + cpu->isar.id_mmfr2 = 0x01200000; + cpu->isar.id_mmfr3 = 0x0211; +- cpu->isar.id_isar0 = 0x02101111; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232141; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x0010142; +- cpu->isar.id_isar5 = 0x0; +- cpu->isar.id_isar6 = 0x0; ++ SET_IDREG(isar, ID_ISAR0, 0x02101111); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232141); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x0010142); ++ SET_IDREG(isar, ID_ISAR5, 0x0); ++ SET_IDREG(isar, ID_ISAR6, 0x0); + cpu->mp_is_up = true; + cpu->pmsav7_dregion = 16; + cpu->isar.reset_pmcr_el0 = 0x41151800; +@@ -803,6 +821,7 @@ static void cortex_r5_initfn(Object *obj) + static void cortex_r52_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_EL2); +@@ -826,12 +845,12 @@ static void cortex_r52_initfn(Object *obj) + cpu->isar.id_mmfr2 = 0x01200000; + cpu->isar.id_mmfr3 = 0xf0102211; + cpu->isar.id_mmfr4 = 0x00000010; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232142; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00010142; +- cpu->isar.id_isar5 = 0x00010001; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232142); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00010142); ++ SET_IDREG(isar, ID_ISAR5, 0x00010001); + cpu->isar.dbgdidr = 0x77168000; + cpu->clidr = (1 << 27) | (1 << 24) | 0x3; + cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ +@@ -1058,6 +1077,7 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data) + static void arm_max_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); ++ ARMISARegisters *isar = &cpu->isar; + + /* aarch64_a57_initfn, advertising none of the aarch64 features */ + cpu->dtb_compatible = "arm,cortex-a57"; +@@ -1084,13 +1104,13 @@ static void arm_max_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_isar6 = 0; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00011142); ++ SET_IDREG(isar, ID_ISAR5, 0x00011121); ++ SET_IDREG(isar, ID_ISAR6, 0); + cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.dbgdevid = 0x00110f13; + cpu->isar.dbgdevid1 = 0x2; +diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c +index 04deff475e..6be05f87f6 100644 +--- a/target/arm/tcg/cpu64.c ++++ b/target/arm/tcg/cpu64.c +@@ -82,12 +82,12 @@ static void aarch64_a35_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00011142); ++ SET_IDREG(isar, ID_ISAR5, 0x00011121); + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + SET_IDREG(isar, ID_AA64PFR1, 0); + SET_IDREG(isar, ID_AA64DFR0, 0x10305106); +@@ -250,13 +250,13 @@ static void aarch64_a55_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000010ull); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_dfr0 = 0x04010088; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x01011121; +- cpu->isar.id_isar6 = 0x00000010; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00011142); ++ SET_IDREG(isar, ID_ISAR5, 0x01011121); ++ SET_IDREG(isar, ID_ISAR6, 0x00000010); + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; +@@ -320,12 +320,12 @@ static void aarch64_a72_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00011142); ++ SET_IDREG(isar, ID_ISAR5, 0x00011121); + SET_IDREG(isar, ID_AA64PFR0, 0x00002222); + SET_IDREG(isar, ID_AA64DFR0, 0x10305106); + SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); +@@ -375,13 +375,13 @@ static void aarch64_a76_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000010ull); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_dfr0 = 0x04010088; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00010142; +- cpu->isar.id_isar5 = 0x01011121; +- cpu->isar.id_isar6 = 0x00000010; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00010142); ++ SET_IDREG(isar, ID_ISAR5, 0x01011121); ++ SET_IDREG(isar, ID_ISAR6, 0x00000010); + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; +@@ -615,13 +615,13 @@ static void aarch64_neoverse_n1_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000020ull); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_dfr0 = 0x04010088; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00010142; +- cpu->isar.id_isar5 = 0x01011121; +- cpu->isar.id_isar6 = 0x00000010; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00010142); ++ SET_IDREG(isar, ID_ISAR5, 0x01011121); ++ SET_IDREG(isar, ID_ISAR6, 0x00000010); + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; +@@ -690,13 +690,13 @@ static void aarch64_neoverse_v1_initfn(Object *obj) + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000020ull); + cpu->id_afr0 = 0x00000000; + cpu->isar.id_dfr0 = 0x15011099; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00010142; +- cpu->isar.id_isar5 = 0x11011121; +- cpu->isar.id_isar6 = 0x01100111; ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00010142); ++ SET_IDREG(isar, ID_ISAR5, 0x11011121); ++ SET_IDREG(isar, ID_ISAR6, 0x01100111); + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; +@@ -907,14 +907,14 @@ static void aarch64_a710_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02122211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00010142; +- cpu->isar.id_isar5 = 0x11011121; /* with Crypto */ ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00010142); ++ SET_IDREG(isar, ID_ISAR5, 0x11011121); /* with Crypto */ + cpu->isar.id_mmfr4 = 0x21021110; +- cpu->isar.id_isar6 = 0x01111111; ++ SET_IDREG(isar, ID_ISAR6, 0x01111111); + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x13211111; + cpu->isar.mvfr2 = 0x00000043; +@@ -1005,14 +1005,14 @@ static void aarch64_neoverse_n2_initfn(Object *obj) + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02122211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00010142; +- cpu->isar.id_isar5 = 0x11011121; /* with Crypto */ ++ SET_IDREG(isar, ID_ISAR0, 0x02101110); ++ SET_IDREG(isar, ID_ISAR1, 0x13112111); ++ SET_IDREG(isar, ID_ISAR2, 0x21232042); ++ SET_IDREG(isar, ID_ISAR3, 0x01112131); ++ SET_IDREG(isar, ID_ISAR4, 0x00010142); ++ SET_IDREG(isar, ID_ISAR5, 0x11011121); /* with Crypto */ + cpu->isar.id_mmfr4 = 0x01021110; +- cpu->isar.id_isar6 = 0x01111111; ++ SET_IDREG(isar, ID_ISAR6, 0x01111111); + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x13211111; + cpu->isar.mvfr2 = 0x00000043; +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Store-id_mmfr0-5-into-the-idregs-array.patch b/arm-cpu-Store-id_mmfr0-5-into-the-idregs-array.patch new file mode 100644 index 0000000000000000000000000000000000000000..980da3a3cddb8347d6885294feb7ce86bd091b98 --- /dev/null +++ b/arm-cpu-Store-id_mmfr0-5-into-the-idregs-array.patch @@ -0,0 +1,703 @@ +From 34b052184fc29389babae9bd30208133a73a51a6 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 11/26] arm/cpu: Store id_mmfr0-5 into the idregs array + +Reviewed-by: Richard Henderson +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + hw/intc/armv7m_nvic.c | 8 +-- + target/arm/cpu-features.h | 18 ++--- + target/arm/cpu.h | 6 -- + target/arm/cpu64.c | 24 +++---- + target/arm/helper.c | 12 ++-- + target/arm/kvm64.c | 18 ++--- + target/arm/tcg/cpu32.c | 142 ++++++++++++++++++-------------------- + target/arm/tcg/cpu64.c | 76 ++++++++++---------- + 8 files changed, 144 insertions(+), 160 deletions(-) + +diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c +index d0415d9acd..e34ca591f0 100644 +--- a/hw/intc/armv7m_nvic.c ++++ b/hw/intc/armv7m_nvic.c +@@ -1284,22 +1284,22 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_mmfr0; ++ return GET_IDREG(isar, ID_MMFR0); + case 0xd54: /* MMFR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_mmfr1; ++ return GET_IDREG(isar, ID_MMFR1); + case 0xd58: /* MMFR2. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_mmfr2; ++ return GET_IDREG(isar, ID_MMFR2); + case 0xd5c: /* MMFR3. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_mmfr3; ++ return GET_IDREG(isar, ID_MMFR3); + case 0xd60: /* ISAR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; +diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h +index 2af4b258de..46a1016302 100644 +--- a/target/arm/cpu-features.h ++++ b/target/arm/cpu-features.h +@@ -280,17 +280,17 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) + + static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4; ++ return FIELD_EX32_IDREG(id, ID_MMFR0, VMSA) >= 4; + } + + static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0; ++ return FIELD_EX32_IDREG(id, ID_MMFR3, PAN) != 0; + } + + static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) >= 2; ++ return FIELD_EX32_IDREG(id, ID_MMFR3, PAN) >= 2; + } + + static inline bool isar_feature_aa32_pmuv3p1(const ARMISARegisters *id) +@@ -316,32 +316,32 @@ static inline bool isar_feature_aa32_pmuv3p5(const ARMISARegisters *id) + + static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0; ++ return FIELD_EX32_IDREG(id, ID_MMFR4, HPDS) != 0; + } + + static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0; ++ return FIELD_EX32_IDREG(id, ID_MMFR4, AC2) != 0; + } + + static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0; ++ return FIELD_EX32_IDREG(id, ID_MMFR4, CCIDX) != 0; + } + + static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0; ++ return FIELD_EX32_IDREG(id, ID_MMFR4, XNX) != 0; + } + + static inline bool isar_feature_aa32_half_evt(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 1; ++ return FIELD_EX32_IDREG(id, ID_MMFR4, EVT) >= 1; + } + + static inline bool isar_feature_aa32_evt(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 2; ++ return FIELD_EX32_IDREG(id, ID_MMFR4, EVT) >= 2; + } + + static inline bool isar_feature_aa32_dit(const ARMISARegisters *id) +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 7b9d2bfda4..2c8f2ffd45 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1058,12 +1058,6 @@ struct ArchCPU { + * field by reading the value from the KVM vCPU. + */ + struct ARMISARegisters { +- uint32_t id_mmfr0; +- uint32_t id_mmfr1; +- uint32_t id_mmfr2; +- uint32_t id_mmfr3; +- uint32_t id_mmfr4; +- uint32_t id_mmfr5; + uint32_t mvfr0; + uint32_t mvfr1; + uint32_t mvfr2; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 7cabc3c646..0942bb7a60 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -754,10 +754,10 @@ static void aarch64_a57_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; ++ SET_IDREG(isar, ID_MMFR0, 0x10101105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); +@@ -812,10 +812,10 @@ static void aarch64_a53_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; ++ SET_IDREG(isar, ID_MMFR0, 0x10101105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); +@@ -869,10 +869,10 @@ static void aarch64_a72_initfn(Object *obj) + SET_IDREG(&cpu->isar, ID_PFR1, 0x00011011); + SET_IDREG(&cpu->isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; ++ SET_IDREG(&cpu->isar, ID_MMFR0, 0x10201105); ++ SET_IDREG(&cpu->isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(&cpu->isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(&cpu->isar, ID_MMFR3, 0x02102211); + SET_IDREG(&cpu->isar, ID_ISAR0, 0x02101110); + SET_IDREG(&cpu->isar, ID_ISAR1, 0x13112111); + SET_IDREG(&cpu->isar, ID_ISAR2, 0x21232042); +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 7e4a222d13..f50baa0f7b 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -8258,22 +8258,22 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_mmfr0 }, ++ .resetvalue = GET_IDREG(isar, ID_MMFR0)}, + { .name = "ID_MMFR1", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_mmfr1 }, ++ .resetvalue = GET_IDREG(isar, ID_MMFR1)}, + { .name = "ID_MMFR2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 6, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_mmfr2 }, ++ .resetvalue = GET_IDREG(isar, ID_MMFR2)}, + { .name = "ID_MMFR3", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 7, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_mmfr3 }, ++ .resetvalue = GET_IDREG(isar, ID_MMFR3)}, + { .name = "ID_ISAR0", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -8308,7 +8308,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_mmfr4 }, ++ .resetvalue = GET_IDREG(isar, ID_MMFR4)}, + { .name = "ID_ISAR6", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -8592,7 +8592,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 6, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_mmfr5 }, ++ .resetvalue = GET_IDREG(isar, ID_MMFR5)}, + { .name = "RES_0_C0_C3_7", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 7, + .access = PL1_R, .type = ARM_CP_CONST, +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 56d5aa70a4..4e184fe1d5 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -376,14 +376,10 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + err |= get_host_cpu_reg(fd, ahcf, ID_PFR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_PFR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_DFR0_EL1_IDX); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, +- ARM64_SYS_REG(3, 0, 0, 1, 4)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, +- ARM64_SYS_REG(3, 0, 0, 1, 5)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2, +- ARM64_SYS_REG(3, 0, 0, 1, 6)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3, +- ARM64_SYS_REG(3, 0, 0, 1, 7)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_MMFR0_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_MMFR1_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_MMFR2_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_MMFR3_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR0_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR2_EL1_IDX); +@@ -391,8 +387,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR4_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR5_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR6_EL1_IDX); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4, +- ARM64_SYS_REG(3, 0, 0, 2, 6)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_MMFR4_EL1_IDX); + + err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, + ARM64_SYS_REG(3, 0, 0, 3, 0)); +@@ -402,8 +397,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + ARM64_SYS_REG(3, 0, 0, 3, 2)); + err |= get_host_cpu_reg(fd, ahcf, ID_PFR2_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_DFR1_EL1_IDX); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr5, +- ARM64_SYS_REG(3, 0, 0, 3, 6)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_MMFR5_EL1_IDX); + + /* + * DBGDIDR is a bit complicated because the kernel doesn't +diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c +index e1a7ad654a..38e516a236 100644 +--- a/target/arm/tcg/cpu32.c ++++ b/target/arm/tcg/cpu32.c +@@ -58,21 +58,17 @@ void aa32_max_features(ARMCPU *cpu) + t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ + cpu->isar.mvfr2 = t; + +- t = cpu->isar.id_mmfr3; +- t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* FEAT_PAN2 */ +- cpu->isar.id_mmfr3 = t; ++ FIELD_DP32_IDREG(isar, ID_MMFR3, PAN, 2); /* FEAT_PAN2 */ + +- t = cpu->isar.id_mmfr4; ++ t = GET_IDREG(isar, ID_MMFR4); + t = FIELD_DP32(t, ID_MMFR4, HPDS, 2); /* FEAT_HPDS2 */ + t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ + t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* FEAT_TTCNP */ + t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* FEAT_XNX */ + t = FIELD_DP32(t, ID_MMFR4, EVT, 2); /* FEAT_EVT */ +- cpu->isar.id_mmfr4 = t; ++ SET_IDREG(isar, ID_MMFR4, t); + +- t = cpu->isar.id_mmfr5; +- t = FIELD_DP32(t, ID_MMFR5, ETS, 1); /* FEAT_ETS */ +- cpu->isar.id_mmfr5 = t; ++ FIELD_DP32_IDREG(isar, ID_MMFR5, ETS, 1); /* FEAT_ETS */ + + t = GET_IDREG(isar, ID_PFR0); + t = FIELD_DP32(t, ID_PFR0, CSV2, 2); /* FEAT_CVS2 */ +@@ -231,9 +227,9 @@ static void arm1136_r2_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x1); + SET_IDREG(isar, ID_DFR0, 0x2); + cpu->id_afr0 = 0x3; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222110; ++ SET_IDREG(isar, ID_MMFR0, 0x01130003); ++ SET_IDREG(isar, ID_MMFR1, 0x10030302); ++ SET_IDREG(isar, ID_MMFR2, 0x01222110); + SET_IDREG(isar, ID_ISAR0, 0x00140011); + SET_IDREG(isar, ID_ISAR1, 0x12002111); + SET_IDREG(isar, ID_ISAR2, 0x11231111); +@@ -263,9 +259,9 @@ static void arm1136_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x1); + SET_IDREG(isar, ID_DFR0, 0x2); + cpu->id_afr0 = 0x3; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222110; ++ SET_IDREG(isar, ID_MMFR0, 0x01130003); ++ SET_IDREG(isar, ID_MMFR1, 0x10030302); ++ SET_IDREG(isar, ID_MMFR2, 0x01222110); + SET_IDREG(isar, ID_ISAR0, 0x00140011); + SET_IDREG(isar, ID_ISAR1, 0x12002111); + SET_IDREG(isar, ID_ISAR2, 0x11231111); +@@ -296,9 +292,9 @@ static void arm1176_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x11); + SET_IDREG(isar, ID_DFR0, 0x33); + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222100; ++ SET_IDREG(isar, ID_MMFR0, 0x01130003); ++ SET_IDREG(isar, ID_MMFR1, 0x10030302); ++ SET_IDREG(isar, ID_MMFR2, 0x01222100); + SET_IDREG(isar, ID_ISAR0, 0x0140011); + SET_IDREG(isar, ID_ISAR1, 0x12002111); + SET_IDREG(isar, ID_ISAR2, 0x11231121); +@@ -326,9 +322,9 @@ static void arm11mpcore_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x1); + SET_IDREG(isar, ID_DFR0, 0); + cpu->id_afr0 = 0x2; +- cpu->isar.id_mmfr0 = 0x01100103; +- cpu->isar.id_mmfr1 = 0x10020302; +- cpu->isar.id_mmfr2 = 0x01222000; ++ SET_IDREG(isar, ID_MMFR0, 0x01100103); ++ SET_IDREG(isar, ID_MMFR1, 0x10020302); ++ SET_IDREG(isar, ID_MMFR2, 0x01222000); + SET_IDREG(isar, ID_ISAR0, 0x00100011); + SET_IDREG(isar, ID_ISAR1, 0x12002111); + SET_IDREG(isar, ID_ISAR2, 0x11221011); +@@ -366,10 +362,10 @@ static void cortex_a8_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x11); + SET_IDREG(isar, ID_DFR0, 0x400); + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x31100003; +- cpu->isar.id_mmfr1 = 0x20000000; +- cpu->isar.id_mmfr2 = 0x01202000; +- cpu->isar.id_mmfr3 = 0x11; ++ SET_IDREG(isar, ID_MMFR0, 0x31100003); ++ SET_IDREG(isar, ID_MMFR1, 0x20000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01202000); ++ SET_IDREG(isar, ID_MMFR3, 0x11); + SET_IDREG(isar, ID_ISAR0, 0x00101111); + SET_IDREG(isar, ID_ISAR1, 0x12112111); + SET_IDREG(isar, ID_ISAR2, 0x21232031); +@@ -442,10 +438,10 @@ static void cortex_a9_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x11); + SET_IDREG(isar, ID_DFR0, 0x000); + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x00100103; +- cpu->isar.id_mmfr1 = 0x20000000; +- cpu->isar.id_mmfr2 = 0x01230000; +- cpu->isar.id_mmfr3 = 0x00002111; ++ SET_IDREG(isar, ID_MMFR0, 0x00100103); ++ SET_IDREG(isar, ID_MMFR1, 0x20000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01230000); ++ SET_IDREG(isar, ID_MMFR3, 0x00002111); + SET_IDREG(isar, ID_ISAR0, 0x00101111); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232041); +@@ -507,10 +503,10 @@ static void cortex_a7_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x02010555); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01240000; +- cpu->isar.id_mmfr3 = 0x02102211; ++ SET_IDREG(isar, ID_MMFR0, 0x10101105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01240000); ++ SET_IDREG(isar, ID_MMFR3, 0x02102211); + /* + * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but + * table 4-41 gives 0x02101110, which includes the arm div insns. +@@ -558,10 +554,10 @@ static void cortex_a15_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x02010555); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x20000000; +- cpu->isar.id_mmfr2 = 0x01240000; +- cpu->isar.id_mmfr3 = 0x02102211; ++ SET_IDREG(isar, ID_MMFR0, 0x10201105); ++ SET_IDREG(isar, ID_MMFR1, 0x20000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01240000); ++ SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232041); +@@ -600,10 +596,10 @@ static void cortex_m0_initfn(Object *obj) + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00000030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x00000000; +- cpu->isar.id_mmfr3 = 0x00000000; ++ SET_IDREG(&cpu->isar, ID_MMFR0, 0x00000030); ++ SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); ++ SET_IDREG(&cpu->isar, ID_MMFR2, 0x00000000); ++ SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000000); + SET_IDREG(isar, ID_ISAR0, 0x01141110); + SET_IDREG(isar, ID_ISAR1, 0x02111000); + SET_IDREG(isar, ID_ISAR2, 0x21112231); +@@ -627,10 +623,10 @@ static void cortex_m3_initfn(Object *obj) + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00000030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x00000000; +- cpu->isar.id_mmfr3 = 0x00000000; ++ SET_IDREG(&cpu->isar, ID_MMFR0, 0x00000030); ++ SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); ++ SET_IDREG(&cpu->isar, ID_MMFR2, 0x00000000); ++ SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000000); + SET_IDREG(isar, ID_ISAR0, 0x01141110); + SET_IDREG(isar, ID_ISAR1, 0x02111000); + SET_IDREG(isar, ID_ISAR2, 0x21112231); +@@ -658,10 +654,10 @@ static void cortex_m4_initfn(Object *obj) + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00000030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x00000000; +- cpu->isar.id_mmfr3 = 0x00000000; ++ SET_IDREG(&cpu->isar, ID_MMFR0, 0x00000030); ++ SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); ++ SET_IDREG(&cpu->isar, ID_MMFR2, 0x00000000); ++ SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000000); + SET_IDREG(isar, ID_ISAR0, 0x01141110); + SET_IDREG(isar, ID_ISAR1, 0x02111000); + SET_IDREG(isar, ID_ISAR2, 0x21112231); +@@ -689,10 +685,10 @@ static void cortex_m7_initfn(Object *obj) + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + SET_IDREG(&cpu->isar, ID_DFR0, 0x00100000); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00100030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01000000; +- cpu->isar.id_mmfr3 = 0x00000000; ++ SET_IDREG(&cpu->isar, ID_MMFR0, 0x00100030); ++ SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); ++ SET_IDREG(&cpu->isar, ID_MMFR2, 0x01000000); ++ SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000000); + SET_IDREG(isar, ID_ISAR0, 0x01101110); + SET_IDREG(isar, ID_ISAR1, 0x02112000); + SET_IDREG(isar, ID_ISAR2, 0x20232231); +@@ -722,10 +718,10 @@ static void cortex_m33_initfn(Object *obj) + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000210); + SET_IDREG(&cpu->isar, ID_DFR0, 0x00200000); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00101F40; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01000000; +- cpu->isar.id_mmfr3 = 0x00000000; ++ SET_IDREG(&cpu->isar, ID_MMFR0, 0x00101F40); ++ SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); ++ SET_IDREG(&cpu->isar, ID_MMFR2, 0x01000000); ++ SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000000); + SET_IDREG(isar, ID_ISAR0, 0x01101110); + SET_IDREG(isar, ID_ISAR1, 0x02212000); + SET_IDREG(isar, ID_ISAR2, 0x20232232); +@@ -760,10 +756,10 @@ static void cortex_m55_initfn(Object *obj) + SET_IDREG(&cpu->isar, ID_PFR1, 0x00000230); + SET_IDREG(&cpu->isar, ID_DFR0, 0x10200000); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00111040; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01000000; +- cpu->isar.id_mmfr3 = 0x00000011; ++ SET_IDREG(&cpu->isar, ID_MMFR0, 0x00111040); ++ SET_IDREG(&cpu->isar, ID_MMFR1, 0x00000000); ++ SET_IDREG(&cpu->isar, ID_MMFR2, 0x01000000); ++ SET_IDREG(&cpu->isar, ID_MMFR3, 0x00000011); + SET_IDREG(isar, ID_ISAR0, 0x01103110); + SET_IDREG(isar, ID_ISAR1, 0x02212000); + SET_IDREG(isar, ID_ISAR2, 0x20232232); +@@ -799,10 +795,10 @@ static void cortex_r5_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x001); + SET_IDREG(isar, ID_DFR0, 0x010400); + cpu->id_afr0 = 0x0; +- cpu->isar.id_mmfr0 = 0x0210030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01200000; +- cpu->isar.id_mmfr3 = 0x0211; ++ SET_IDREG(isar, ID_MMFR0, 0x0210030); ++ SET_IDREG(isar, ID_MMFR1, 0x00000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01200000); ++ SET_IDREG(isar, ID_MMFR3, 0x0211); + SET_IDREG(isar, ID_ISAR0, 0x02101111); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232141); +@@ -838,11 +834,11 @@ static void cortex_r52_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x10111001); + SET_IDREG(isar, ID_DFR0, 0x03010006); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00211040; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01200000; +- cpu->isar.id_mmfr3 = 0xf0102211; +- cpu->isar.id_mmfr4 = 0x00000010; ++ SET_IDREG(isar, ID_MMFR0, 0x00211040); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01200000); ++ SET_IDREG(isar, ID_MMFR3, 0xf0102211); ++ SET_IDREG(isar, ID_MMFR4, 0x00000010); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232142); +@@ -1098,10 +1094,10 @@ static void arm_max_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; ++ SET_IDREG(isar, ID_MMFR0, 0x10101105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); +diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c +index 6646f265ee..31a5a6b9c5 100644 +--- a/target/arm/tcg/cpu64.c ++++ b/target/arm/tcg/cpu64.c +@@ -78,10 +78,10 @@ static void aarch64_a35_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; ++ SET_IDREG(isar, ID_MMFR0, 0x10201105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); +@@ -257,11 +257,11 @@ static void aarch64_a55_initfn(Object *obj) + SET_IDREG(isar, ID_ISAR4, 0x00011142); + SET_IDREG(isar, ID_ISAR5, 0x01011121); + SET_IDREG(isar, ID_ISAR6, 0x00000010); +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02122211; +- cpu->isar.id_mmfr4 = 0x00021110; ++ SET_IDREG(isar, ID_MMFR0, 0x10201105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(isar, ID_MMFR3, 0x02122211); ++ SET_IDREG(isar, ID_MMFR4, 0x00021110); + SET_IDREG(isar, ID_PFR0, 0x10010131); + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_PFR2, 0x00000011); +@@ -316,10 +316,10 @@ static void aarch64_a72_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x00011011); + SET_IDREG(isar, ID_DFR0, 0x03010066); + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; ++ SET_IDREG(isar, ID_MMFR0, 0x10201105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(isar, ID_MMFR3, 0x02102211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); +@@ -382,11 +382,11 @@ static void aarch64_a76_initfn(Object *obj) + SET_IDREG(isar, ID_ISAR4, 0x00010142); + SET_IDREG(isar, ID_ISAR5, 0x01011121); + SET_IDREG(isar, ID_ISAR6, 0x00000010); +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02122211; +- cpu->isar.id_mmfr4 = 0x00021110; ++ SET_IDREG(isar, ID_MMFR0, 0x10201105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(isar, ID_MMFR3, 0x02122211); ++ SET_IDREG(isar, ID_MMFR4, 0x00021110); + SET_IDREG(isar, ID_PFR0, 0x10010131); + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + SET_IDREG(isar, ID_PFR2, 0x00000011); +@@ -622,11 +622,11 @@ static void aarch64_neoverse_n1_initfn(Object *obj) + SET_IDREG(isar, ID_ISAR4, 0x00010142); + SET_IDREG(isar, ID_ISAR5, 0x01011121); + SET_IDREG(isar, ID_ISAR6, 0x00000010); +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02122211; +- cpu->isar.id_mmfr4 = 0x00021110; ++ SET_IDREG(isar, ID_MMFR0, 0x10201105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(isar, ID_MMFR3, 0x02122211); ++ SET_IDREG(isar, ID_MMFR4, 0x00021110); + SET_IDREG(isar, ID_PFR0, 0x10010131); + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + SET_IDREG(isar, ID_PFR2, 0x00000011); +@@ -697,11 +697,11 @@ static void aarch64_neoverse_v1_initfn(Object *obj) + SET_IDREG(isar, ID_ISAR4, 0x00010142); + SET_IDREG(isar, ID_ISAR5, 0x11011121); + SET_IDREG(isar, ID_ISAR6, 0x01100111); +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02122211; +- cpu->isar.id_mmfr4 = 0x01021110; ++ SET_IDREG(isar, ID_MMFR0, 0x10201105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(isar, ID_MMFR3, 0x02122211); ++ SET_IDREG(isar, ID_MMFR4, 0x01021110); + SET_IDREG(isar, ID_PFR0, 0x21110131); + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + SET_IDREG(isar, ID_PFR2, 0x00000011); +@@ -903,17 +903,17 @@ static void aarch64_a710_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + SET_IDREG(isar, ID_DFR0, 0x16011099); + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02122211; ++ SET_IDREG(isar, ID_MMFR0, 0x10201105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(isar, ID_MMFR3, 0x02122211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00010142); + SET_IDREG(isar, ID_ISAR5, 0x11011121); /* with Crypto */ +- cpu->isar.id_mmfr4 = 0x21021110; ++ SET_IDREG(isar, ID_MMFR4, 0x21021110); + SET_IDREG(isar, ID_ISAR6, 0x01111111); + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x13211111; +@@ -1001,17 +1001,17 @@ static void aarch64_neoverse_n2_initfn(Object *obj) + SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + SET_IDREG(isar, ID_DFR0, 0x16011099); + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02122211; ++ SET_IDREG(isar, ID_MMFR0, 0x10201105); ++ SET_IDREG(isar, ID_MMFR1, 0x40000000); ++ SET_IDREG(isar, ID_MMFR2, 0x01260000); ++ SET_IDREG(isar, ID_MMFR3, 0x02122211); + SET_IDREG(isar, ID_ISAR0, 0x02101110); + SET_IDREG(isar, ID_ISAR1, 0x13112111); + SET_IDREG(isar, ID_ISAR2, 0x21232042); + SET_IDREG(isar, ID_ISAR3, 0x01112131); + SET_IDREG(isar, ID_ISAR4, 0x00010142); + SET_IDREG(isar, ID_ISAR5, 0x11011121); /* with Crypto */ +- cpu->isar.id_mmfr4 = 0x01021110; ++ SET_IDREG(isar, ID_MMFR4, 0x01021110); + SET_IDREG(isar, ID_ISAR6, 0x01111111); + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x13211111; +-- +2.51.0.windows.1 + diff --git a/arm-cpu-Store-id_pfr0-1-2-into-the-idregs-array.patch b/arm-cpu-Store-id_pfr0-1-2-into-the-idregs-array.patch new file mode 100644 index 0000000000000000000000000000000000000000..d058de5d7811ed525b6c50926f6819704c97944d --- /dev/null +++ b/arm-cpu-Store-id_pfr0-1-2-into-the-idregs-array.patch @@ -0,0 +1,575 @@ +From 9ce1df8b42d48a6d733ecff04f029e0198c25646 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 09/26] arm/cpu: Store id_pfr0/1/2 into the idregs array + +Reviewed-by: Richard Henderson +Reviewed-by: Sebastian Ott +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + hw/intc/armv7m_nvic.c | 5 +-- + target/arm/cpu-features.h | 10 +++--- + target/arm/cpu.c | 8 ++--- + target/arm/cpu.h | 3 -- + target/arm/cpu64.c | 12 +++---- + target/arm/helper.c | 8 ++--- + target/arm/kvm64.c | 9 ++--- + target/arm/tcg/cpu32.c | 76 +++++++++++++++++++-------------------- + target/arm/tcg/cpu64.c | 44 +++++++++++------------ + 9 files changed, 84 insertions(+), 91 deletions(-) + +diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c +index 5f68b0e711..b613b2cafe 100644 +--- a/hw/intc/armv7m_nvic.c ++++ b/hw/intc/armv7m_nvic.c +@@ -988,6 +988,7 @@ static void nvic_nmi_trigger(void *opaque, int n, int level) + static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + { + ARMCPU *cpu = s->cpu; ++ ARMISARegisters *isar = &cpu->isar; + uint32_t val; + + switch (offset) { +@@ -1263,12 +1264,12 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_pfr0; ++ return GET_IDREG(isar, ID_PFR0); + case 0xd44: /* PFR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_pfr1; ++ return GET_IDREG(isar, ID_PFR1); + case 0xd48: /* DFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; +diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h +index 25180e4b77..fe73988141 100644 +--- a/target/arm/cpu-features.h ++++ b/target/arm/cpu-features.h +@@ -133,12 +133,12 @@ static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id) + + static inline bool isar_feature_aa32_ras(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0; ++ return FIELD_EX32_IDREG(id, ID_PFR0, RAS) != 0; + } + + static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0; ++ return FIELD_EX32_IDREG(id, ID_PFR1, MPROGMOD) != 0; + } + + static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) +@@ -147,7 +147,7 @@ static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) + * Return true if M-profile state handling insns + * (VSCCLRM, CLRM, FPCTX access insns) are implemented + */ +- return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3; ++ return FIELD_EX32_IDREG(id, ID_PFR1, SECURITY) >= 3; + } + + static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) +@@ -346,12 +346,12 @@ static inline bool isar_feature_aa32_evt(const ARMISARegisters *id) + + static inline bool isar_feature_aa32_dit(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0; ++ return FIELD_EX32_IDREG(id, ID_PFR0, DIT) != 0; + } + + static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0; ++ return FIELD_EX32_IDREG(id, ID_PFR2, SSBS) != 0; + } + + static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id) +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 7667530e9d..60654e8630 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2150,7 +2150,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + * Disable the security extension feature bits in the processor + * feature registers as well. + */ +- cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1, ID_PFR1, SECURITY, 0); ++ FIELD_DP32_IDREG(isar, ID_PFR1, SECURITY, 0); + cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPSDBG, 0); + FIELD_DP64_IDREG(isar, ID_AA64PFR0, EL3, 0); + +@@ -2190,8 +2190,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + * registers if we don't have EL2. + */ + FIELD_DP64_IDREG(isar, ID_AA64PFR0, EL2, 0); +- cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1, +- ID_PFR1, VIRTUALIZATION, 0); ++ FIELD_DP32_IDREG(isar, ID_PFR1, VIRTUALIZATION, 0); + } + + if (cpu_isar_feature(aa64_mte, cpu)) { +@@ -2239,8 +2238,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, MMAPTRC, 0); + /* FEAT_AMU (Activity Monitors Extension) */ + FIELD_DP64_IDREG(isar, ID_AA64PFR0, AMU, 0); +- cpu->isar.id_pfr0 = +- FIELD_DP32(cpu->isar.id_pfr0, ID_PFR0, AMU, 0); ++ FIELD_DP32_IDREG(isar, ID_PFR0, AMU, 0); + /* FEAT_MPAM (Memory Partitioning and Monitoring Extension) */ + FIELD_DP64_IDREG(isar, ID_AA64PFR0, MPAM, 0); + /* FEAT_NV (Nested Virtualization) */ +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 4c29657ec7..e9ef2fd484 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1064,9 +1064,6 @@ struct ArchCPU { + uint32_t id_mmfr3; + uint32_t id_mmfr4; + uint32_t id_mmfr5; +- uint32_t id_pfr0; +- uint32_t id_pfr1; +- uint32_t id_pfr2; + uint32_t mvfr0; + uint32_t mvfr1; + uint32_t mvfr2; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 9495bc418e..9d8c617aca 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -750,8 +750,8 @@ static void aarch64_a57_initfn(Object *obj) + cpu->isar.mvfr2 = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; ++ SET_IDREG(isar, ID_PFR0, 0x00000131); ++ SET_IDREG(isar, ID_PFR1, 0x00011011); + cpu->isar.id_dfr0 = 0x03010066; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10101105; +@@ -808,8 +808,8 @@ static void aarch64_a53_initfn(Object *obj) + cpu->isar.mvfr2 = 0x00000043; + cpu->ctr = 0x84448004; /* L1Ip = VIPT */ + cpu->reset_sctlr = 0x00c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; ++ SET_IDREG(isar, ID_PFR0, 0x00000131); ++ SET_IDREG(isar, ID_PFR1, 0x00011011); + cpu->isar.id_dfr0 = 0x03010066; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10101105; +@@ -865,8 +865,8 @@ static void aarch64_a72_initfn(Object *obj) + cpu->isar.mvfr2 = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; ++ SET_IDREG(&cpu->isar, ID_PFR0, 0x00000131); ++ SET_IDREG(&cpu->isar, ID_PFR1, 0x00011011); + cpu->isar.id_dfr0 = 0x03010066; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10201105; +diff --git a/target/arm/helper.c b/target/arm/helper.c +index d2d9de8b0b..9895e8e74f 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -7268,7 +7268,7 @@ static void define_pmu_regs(ARMCPU *cpu) + static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) + { + ARMCPU *cpu = env_archcpu(env); +- uint64_t pfr1 = cpu->isar.id_pfr1; ++ uint64_t pfr1 = GET_IDREG(&cpu->isar, ID_PFR1); + + if (env->gicv3state) { + pfr1 |= 1 << 28; +@@ -8225,7 +8225,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_pfr0 }, ++ .resetvalue = GET_IDREG(isar, ID_PFR0)}, + /* + * ID_PFR1 is not a plain ARM_CP_CONST because we don't know + * the value of the GIC field until after we define these regs. +@@ -8236,7 +8236,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .accessfn = access_aa32_tid3, + #ifdef CONFIG_USER_ONLY + .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_pfr1, ++ .resetvalue = GET_IDREG(isar, ID_PFR1), + #else + .type = ARM_CP_NO_RAW, + .accessfn = access_aa32_tid3, +@@ -8582,7 +8582,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_pfr2 }, ++ .resetvalue = GET_IDREG(isar, ID_PFR2)}, + { .name = "ID_DFR1", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 2e57ba4224..74eba5ce47 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -373,10 +373,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * than skipping the reads and leaving 0, as we must avoid + * considering the values in every case. + */ +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr0, +- ARM64_SYS_REG(3, 0, 0, 1, 0)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1, +- ARM64_SYS_REG(3, 0, 0, 1, 1)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_PFR0_EL1_IDX); ++ err |= get_host_cpu_reg(fd, ahcf, ID_PFR1_EL1_IDX); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, + ARM64_SYS_REG(3, 0, 0, 1, 2)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, +@@ -403,8 +401,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + ARM64_SYS_REG(3, 0, 0, 3, 1)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, + ARM64_SYS_REG(3, 0, 0, 3, 2)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2, +- ARM64_SYS_REG(3, 0, 0, 3, 4)); ++ err |= get_host_cpu_reg(fd, ahcf, ID_PFR2_EL1_IDX); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr1, + ARM64_SYS_REG(3, 0, 0, 3, 5)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr5, +diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c +index dbf2070a81..7830189672 100644 +--- a/target/arm/tcg/cpu32.c ++++ b/target/arm/tcg/cpu32.c +@@ -74,16 +74,16 @@ void aa32_max_features(ARMCPU *cpu) + t = FIELD_DP32(t, ID_MMFR5, ETS, 1); /* FEAT_ETS */ + cpu->isar.id_mmfr5 = t; + +- t = cpu->isar.id_pfr0; ++ t = GET_IDREG(isar, ID_PFR0); + t = FIELD_DP32(t, ID_PFR0, CSV2, 2); /* FEAT_CVS2 */ + t = FIELD_DP32(t, ID_PFR0, DIT, 1); /* FEAT_DIT */ + t = FIELD_DP32(t, ID_PFR0, RAS, 1); /* FEAT_RAS */ +- cpu->isar.id_pfr0 = t; ++ SET_IDREG(isar, ID_PFR0, t); + +- t = cpu->isar.id_pfr2; ++ t = GET_IDREG(isar, ID_PFR2); + t = FIELD_DP32(t, ID_PFR2, CSV3, 1); /* FEAT_CSV3 */ + t = FIELD_DP32(t, ID_PFR2, SSBS, 1); /* FEAT_SSBS */ +- cpu->isar.id_pfr2 = t; ++ SET_IDREG(isar, ID_PFR2, t); + + t = cpu->isar.id_dfr0; + t = FIELD_DP32(t, ID_DFR0, COPDBG, 9); /* FEAT_Debugv8p4 */ +@@ -229,8 +229,8 @@ static void arm1136_r2_initfn(Object *obj) + cpu->isar.mvfr1 = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x1; ++ SET_IDREG(isar, ID_PFR0, 0x111); ++ SET_IDREG(isar, ID_PFR1, 0x1); + cpu->isar.id_dfr0 = 0x2; + cpu->id_afr0 = 0x3; + cpu->isar.id_mmfr0 = 0x01130003; +@@ -261,8 +261,8 @@ static void arm1136_initfn(Object *obj) + cpu->isar.mvfr1 = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x1; ++ SET_IDREG(isar, ID_PFR0, 0x111); ++ SET_IDREG(isar, ID_PFR1, 0x1); + cpu->isar.id_dfr0 = 0x2; + cpu->id_afr0 = 0x3; + cpu->isar.id_mmfr0 = 0x01130003; +@@ -294,8 +294,8 @@ static void arm1176_initfn(Object *obj) + cpu->isar.mvfr1 = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x11; ++ SET_IDREG(isar, ID_PFR0, 0x111); ++ SET_IDREG(isar, ID_PFR1, 0x11); + cpu->isar.id_dfr0 = 0x33; + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x01130003; +@@ -324,8 +324,8 @@ static void arm11mpcore_initfn(Object *obj) + cpu->isar.mvfr0 = 0x11111111; + cpu->isar.mvfr1 = 0x00000000; + cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x1; ++ SET_IDREG(isar, ID_PFR0, 0x111); ++ SET_IDREG(isar, ID_PFR1, 0x1); + cpu->isar.id_dfr0 = 0; + cpu->id_afr0 = 0x2; + cpu->isar.id_mmfr0 = 0x01100103; +@@ -364,8 +364,8 @@ static void cortex_a8_initfn(Object *obj) + cpu->isar.mvfr1 = 0x00011111; + cpu->ctr = 0x82048004; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x1031; +- cpu->isar.id_pfr1 = 0x11; ++ SET_IDREG(isar, ID_PFR0, 0x1031); ++ SET_IDREG(isar, ID_PFR1, 0x11); + cpu->isar.id_dfr0 = 0x400; + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x31100003; +@@ -440,8 +440,8 @@ static void cortex_a9_initfn(Object *obj) + cpu->isar.mvfr1 = 0x01111111; + cpu->ctr = 0x80038003; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x1031; +- cpu->isar.id_pfr1 = 0x11; ++ SET_IDREG(isar, ID_PFR0, 0x1031); ++ SET_IDREG(isar, ID_PFR1, 0x11); + cpu->isar.id_dfr0 = 0x000; + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x00100103; +@@ -505,8 +505,8 @@ static void cortex_a7_initfn(Object *obj) + cpu->isar.mvfr1 = 0x11111111; + cpu->ctr = 0x84448003; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x00001131; +- cpu->isar.id_pfr1 = 0x00011011; ++ SET_IDREG(isar, ID_PFR0, 0x00001131); ++ SET_IDREG(isar, ID_PFR1, 0x00011011); + cpu->isar.id_dfr0 = 0x02010555; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10101105; +@@ -556,8 +556,8 @@ static void cortex_a15_initfn(Object *obj) + cpu->isar.mvfr1 = 0x11111111; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x00001131; +- cpu->isar.id_pfr1 = 0x00011011; ++ SET_IDREG(isar, ID_PFR0, 0x00001131); ++ SET_IDREG(isar, ID_PFR1, 0x00011011); + cpu->isar.id_dfr0 = 0x02010555; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10201105; +@@ -598,8 +598,8 @@ static void cortex_m0_initfn(Object *obj) + * by looking at ID register fields. We use the same values as + * for the M3. + */ +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; ++ SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); ++ SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + cpu->isar.id_dfr0 = 0x00100000; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00000030; +@@ -625,8 +625,8 @@ static void cortex_m3_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_M_MAIN); + cpu->midr = 0x410fc231; + cpu->pmsav7_dregion = 8; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; ++ SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); ++ SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + cpu->isar.id_dfr0 = 0x00100000; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00000030; +@@ -656,8 +656,8 @@ static void cortex_m4_initfn(Object *obj) + cpu->isar.mvfr0 = 0x10110021; + cpu->isar.mvfr1 = 0x11000011; + cpu->isar.mvfr2 = 0x00000000; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; ++ SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); ++ SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + cpu->isar.id_dfr0 = 0x00100000; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00000030; +@@ -687,8 +687,8 @@ static void cortex_m7_initfn(Object *obj) + cpu->isar.mvfr0 = 0x10110221; + cpu->isar.mvfr1 = 0x12000011; + cpu->isar.mvfr2 = 0x00000040; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; ++ SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); ++ SET_IDREG(&cpu->isar, ID_PFR1, 0x00000200); + cpu->isar.id_dfr0 = 0x00100000; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00100030; +@@ -720,8 +720,8 @@ static void cortex_m33_initfn(Object *obj) + cpu->isar.mvfr0 = 0x10110021; + cpu->isar.mvfr1 = 0x11000011; + cpu->isar.mvfr2 = 0x00000040; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000210; ++ SET_IDREG(&cpu->isar, ID_PFR0, 0x00000030); ++ SET_IDREG(&cpu->isar, ID_PFR1, 0x00000210); + cpu->isar.id_dfr0 = 0x00200000; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00101F40; +@@ -758,8 +758,8 @@ static void cortex_m55_initfn(Object *obj) + cpu->isar.mvfr0 = 0x10110221; + cpu->isar.mvfr1 = 0x12100211; + cpu->isar.mvfr2 = 0x00000040; +- cpu->isar.id_pfr0 = 0x20000030; +- cpu->isar.id_pfr1 = 0x00000230; ++ SET_IDREG(&cpu->isar, ID_PFR0, 0x20000030); ++ SET_IDREG(&cpu->isar, ID_PFR1, 0x00000230); + cpu->isar.id_dfr0 = 0x10200000; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00111040; +@@ -797,8 +797,8 @@ static void cortex_r5_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_PMSA); + set_feature(&cpu->env, ARM_FEATURE_PMU); + cpu->midr = 0x411fc153; /* r1p3 */ +- cpu->isar.id_pfr0 = 0x0131; +- cpu->isar.id_pfr1 = 0x001; ++ SET_IDREG(isar, ID_PFR0, 0x0131); ++ SET_IDREG(isar, ID_PFR1, 0x001); + cpu->isar.id_dfr0 = 0x010400; + cpu->id_afr0 = 0x0; + cpu->isar.id_mmfr0 = 0x0210030; +@@ -836,8 +836,8 @@ static void cortex_r52_initfn(Object *obj) + cpu->isar.mvfr2 = 0x00000043; + cpu->ctr = 0x8144c004; + cpu->reset_sctlr = 0x30c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x10111001; ++ SET_IDREG(isar, ID_PFR0, 0x00000131); ++ SET_IDREG(isar, ID_PFR1, 0x10111001); + cpu->isar.id_dfr0 = 0x03010006; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x00211040; +@@ -1096,8 +1096,8 @@ static void arm_max_initfn(Object *obj) + cpu->isar.mvfr2 = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; ++ SET_IDREG(isar, ID_PFR0, 0x00000131); ++ SET_IDREG(isar, ID_PFR1, 0x00011011); + cpu->isar.id_dfr0 = 0x03010066; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10101105; +diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c +index 6be05f87f6..dbfeeb92a0 100644 +--- a/target/arm/tcg/cpu64.c ++++ b/target/arm/tcg/cpu64.c +@@ -74,8 +74,8 @@ static void aarch64_a35_initfn(Object *obj) + cpu->midr = 0x411fd040; + cpu->revidr = 0; + cpu->ctr = 0x84448004; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; ++ SET_IDREG(isar, ID_PFR0, 0x00000131); ++ SET_IDREG(isar, ID_PFR1, 0x00011011); + cpu->isar.id_dfr0 = 0x03010066; + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x10201105; +@@ -262,9 +262,9 @@ static void aarch64_a55_initfn(Object *obj) + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02122211; + cpu->isar.id_mmfr4 = 0x00021110; +- cpu->isar.id_pfr0 = 0x10010131; +- cpu->isar.id_pfr1 = 0x00011011; +- cpu->isar.id_pfr2 = 0x00000011; ++ SET_IDREG(isar, ID_PFR0, 0x10010131); ++ SET_IDREG(isar, ID_PFR1, 0x00011011); ++ SET_IDREG(isar, ID_PFR2, 0x00000011); + cpu->midr = 0x412FD050; /* r2p0 */ + cpu->revidr = 0; + +@@ -312,8 +312,8 @@ static void aarch64_a72_initfn(Object *obj) + cpu->isar.mvfr2 = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; ++ SET_IDREG(isar, ID_PFR0, 0x00000131); ++ SET_IDREG(isar, ID_PFR1, 0x00011011); + cpu->isar.id_dfr0 = 0x03010066; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10201105; +@@ -387,9 +387,9 @@ static void aarch64_a76_initfn(Object *obj) + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02122211; + cpu->isar.id_mmfr4 = 0x00021110; +- cpu->isar.id_pfr0 = 0x10010131; +- cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ +- cpu->isar.id_pfr2 = 0x00000011; ++ SET_IDREG(isar, ID_PFR0, 0x10010131); ++ SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ ++ SET_IDREG(isar, ID_PFR2, 0x00000011); + cpu->midr = 0x414fd0b1; /* r4p1 */ + cpu->revidr = 0; + +@@ -627,9 +627,9 @@ static void aarch64_neoverse_n1_initfn(Object *obj) + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02122211; + cpu->isar.id_mmfr4 = 0x00021110; +- cpu->isar.id_pfr0 = 0x10010131; +- cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ +- cpu->isar.id_pfr2 = 0x00000011; ++ SET_IDREG(isar, ID_PFR0, 0x10010131); ++ SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ ++ SET_IDREG(isar, ID_PFR2, 0x00000011); + cpu->midr = 0x414fd0c1; /* r4p1 */ + cpu->revidr = 0; + +@@ -702,9 +702,9 @@ static void aarch64_neoverse_v1_initfn(Object *obj) + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02122211; + cpu->isar.id_mmfr4 = 0x01021110; +- cpu->isar.id_pfr0 = 0x21110131; +- cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ +- cpu->isar.id_pfr2 = 0x00000011; ++ SET_IDREG(isar, ID_PFR0, 0x21110131); ++ SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ ++ SET_IDREG(isar, ID_PFR2, 0x00000011); + cpu->midr = 0x411FD402; /* r1p2 */ + cpu->revidr = 0; + +@@ -899,8 +899,8 @@ static void aarch64_a710_initfn(Object *obj) + /* Ordered by Section B.4: AArch64 registers */ + cpu->midr = 0x412FD471; /* r2p1 */ + cpu->revidr = 0; +- cpu->isar.id_pfr0 = 0x21110131; +- cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ ++ SET_IDREG(isar, ID_PFR0, 0x21110131); ++ SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + cpu->isar.id_dfr0 = 0x16011099; + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x10201105; +@@ -918,7 +918,7 @@ static void aarch64_a710_initfn(Object *obj) + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x13211111; + cpu->isar.mvfr2 = 0x00000043; +- cpu->isar.id_pfr2 = 0x00000011; ++ SET_IDREG(isar, ID_PFR2, 0x00000011); + SET_IDREG(isar, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000221ull); + SET_IDREG(isar, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */ +@@ -997,8 +997,8 @@ static void aarch64_neoverse_n2_initfn(Object *obj) + /* Ordered by Section B.5: AArch64 ID registers */ + cpu->midr = 0x410FD493; /* r0p3 */ + cpu->revidr = 0; +- cpu->isar.id_pfr0 = 0x21110131; +- cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ ++ SET_IDREG(isar, ID_PFR0, 0x21110131); ++ SET_IDREG(isar, ID_PFR1, 0x00010000); /* GIC filled in later */ + cpu->isar.id_dfr0 = 0x16011099; + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x10201105; +@@ -1016,7 +1016,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj) + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x13211111; + cpu->isar.mvfr2 = 0x00000043; +- cpu->isar.id_pfr2 = 0x00000011; ++ SET_IDREG(isar, ID_PFR2, 0x00000011); + SET_IDREG(isar, ID_AA64PFR0, 0x1201111120111112ull); /* GIC filled in later */ + SET_IDREG(isar, ID_AA64PFR1, 0x0000000000000221ull); + SET_IDREG(isar, ID_AA64ZFR0, 0x0000110100110021ull); /* with Crypto */ +-- +2.51.0.windows.1 + diff --git a/arm-cpu-accessors-for-writable-id-registers.patch b/arm-cpu-accessors-for-writable-id-registers.patch new file mode 100644 index 0000000000000000000000000000000000000000..55b79ced61747ef939705018dd5cf9228759b121 --- /dev/null +++ b/arm-cpu-accessors-for-writable-id-registers.patch @@ -0,0 +1,51 @@ +From 36a23693d442edbcd4a610daf36265a3a113e11e Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 19/26] arm/cpu: accessors for writable id registers + +Also add conversion between the different indices. + +Signed-off-by: Cornelia Huck +--- + target/arm/cpu.h | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 3f57363baf..a75f057430 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -866,6 +866,13 @@ typedef struct IdRegMap { + uint64_t regs[NR_ID_REGS]; + } IdRegMap; + ++#define ARM_FEATURE_ID_RANGE_IDX(op0, op1, crn, crm, op2) \ ++ ({ \ ++ __u64 __op1 = (op1) & 3; \ ++ __op1 -= (__op1 == 3); \ ++ (__op1 << 6 | ((crm) & 7) << 3 | (op2)); \ ++ }) ++ + /* REG is ID_XXX */ + #define FIELD_DP64_IDREG(ISAR, REG, FIELD, VALUE) \ + ({ \ +@@ -913,6 +920,17 @@ typedef struct IdRegMap { + i_->idregs[REG ## _EL1_IDX]; \ + }) + ++#define GET_IDREG_WRITABLE(MAP, REG) \ ++ ({ \ ++ const IdRegMap *m_ = (MAP); \ ++ int index = ARM_FEATURE_ID_RANGE_IDX((sysreg >> 14) & 0x0000c000, \ ++ (sysreg >> 11) & 0x00003800, \ ++ (sysreg >> 7) & 0x00000780, \ ++ (sysreg >> 3) & 0x00000078, \ ++ sysreg & 0x00000007); \ ++ m_->regs[index]; \ ++ }) ++ + /** + * ARMCPU: + * @env: #CPUARMState +-- +2.51.0.windows.1 + diff --git a/arm-cpu-enable-MIDR-writable.patch b/arm-cpu-enable-MIDR-writable.patch new file mode 100644 index 0000000000000000000000000000000000000000..c5db976bacb2d571fbbf1d467143b60e4126c781 --- /dev/null +++ b/arm-cpu-enable-MIDR-writable.patch @@ -0,0 +1,34 @@ +From e9f40ad8e41fa8ac2653ea4cc11f6f2ea66e6ca3 Mon Sep 17 00:00:00 2001 +From: Qingtong Jia +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 26/26] arm/cpu: enable MIDR writable + +For now we support writable imp id feature. Let's check and enable +KVM_CAP_ARM_WRITABLE_IMP_ID_REGS if kvm supports it. + +Signed-off-by: Qingtong Jia +--- + accel/kvm/kvm-all.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 6e3a3f14a1..a321bf514c 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -2680,6 +2680,13 @@ static int kvm_init(MachineState *ms) + query_stats_schemas_cb); + } + ++ if (kvm_check_extension(kvm_state, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS)) { ++ ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS, 0); ++ if (ret) { ++ fprintf(stderr, "Could not enable KVM_CAP_ARM_WRITABLE_IMP_ID_REGS: %d\n", ret); ++ } ++ } ++ + return 0; + + err: +-- +2.51.0.windows.1 + diff --git a/arm-cpu-features-document-ID-reg-properties.patch b/arm-cpu-features-document-ID-reg-properties.patch new file mode 100644 index 0000000000000000000000000000000000000000..eaa616a67ea1b1e8006599a954c3df57649008e4 --- /dev/null +++ b/arm-cpu-features-document-ID-reg-properties.patch @@ -0,0 +1,159 @@ +From 974c2e6edd683c96054343541d388ed48ad754af Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 24/26] arm/cpu-features: document ID reg properties + +Add some documentation for how individual ID registers can be +configured with the host cpu model. + +[CH: adapt to removal of the 'custom' model, added some more + explanations about using the ID register props] +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + docs/system/arm/cpu-features.rst | 104 ++++++++++++++++++++++++++++--- + 1 file changed, 96 insertions(+), 8 deletions(-) + +diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst +index a5fb929243..8b497134ab 100644 +--- a/docs/system/arm/cpu-features.rst ++++ b/docs/system/arm/cpu-features.rst +@@ -2,7 +2,10 @@ Arm CPU Features + ================ + + CPU features are optional features that a CPU of supporting type may +-choose to implement or not. In QEMU, optional CPU features have ++choose to implement or not. QEMU provides two different mechanisms ++to configure those features: ++ ++1. For most CPU models, optional CPU features may have + corresponding boolean CPU proprieties that, when enabled, indicate + that the feature is implemented, and, conversely, when disabled, + indicate that it is not implemented. An example of an Arm CPU feature +@@ -29,6 +32,16 @@ supports the feature. While ``aarch64`` currently only works with KVM, + it could work with TCG. CPU features that are specific to KVM are + prefixed with "kvm-" and are described in "KVM VCPU Features". + ++2. Additionally, the ``host`` CPU model on KVM allows to configure optional ++CPU features via the corresponding ID registers. The host kernel allows ++to write a subset of ID register fields. The host model exposes ++properties for each writable ID register field. Those options are named ++SYSREG__. IDREG and FIELD names are those used in the ++ARM ARM Reference Manual. They can also be found in the Linux ++arch/arm64/tool/sysreg file which is used to automatically generate the ++description for those registers and fields. This currently only has been ++implemented for KVM. ++ + CPU Feature Probing + =================== + +@@ -124,13 +137,20 @@ A note about CPU models and KVM + + Named CPU models generally do not work with KVM. There are a few cases + that do work, e.g. using the named CPU model ``cortex-a57`` with KVM on a +-seattle host, but mostly if KVM is enabled the ``host`` CPU type must be +-used. This means the guest is provided all the same CPU features as the +-host CPU type has. And, for this reason, the ``host`` CPU type should +-enable all CPU features that the host has by default. Indeed it's even +-a bit strange to allow disabling CPU features that the host has when using +-the ``host`` CPU type, but in the absence of CPU models it's the best we can +-do if we want to launch guests without all the host's CPU features enabled. ++seattle host, but mostly if KVM is enabled, the ``host`` CPU model must be ++used. ++ ++Using the ``host`` type means the guest is provided all the same CPU ++features as the host CPU type has. And, for this reason, the ``host`` ++CPU type should enable all CPU features that the host has by default. ++ ++In case some features need to be hidden to the guest, and the host kernel ++supports it, the ``host`` model can be instructed to disable individual ++ID register values. This is especially useful for migration purposes. ++However, this interface will not allow configuring an arbitrary set of ++features; the ID registers must describe a subset of the host's features, ++and all differences to the host's configuration must actually be supported ++by the kernel to be deconfigured. + + Enabling KVM also affects the ``query-cpu-model-expansion`` QMP command. The + affect is not only limited to specific features, as pointed out in example +@@ -167,6 +187,13 @@ disabling many SVE vector lengths would be quite verbose, the ``sve`` CPU + properties have special semantics (see "SVE CPU Property Parsing + Semantics"). + ++Additionally, if supported by KVM on the host kernel, the ``host`` CPU model ++may be configured via individual ID register field properties, for example:: ++ ++ $ qemu-system-aarch64 -M virt -cpu host,SYSREG_ID_AA64ISAR0_EL1_DP=0x0 ++ ++This forces ID_AA64ISAR0_EL1 DP field to 0. ++ + KVM VCPU Features + ================= + +@@ -463,3 +490,64 @@ Legal values for ``S`` are 30, 34, 36, and 39; the default is 30. + + As with ``x-rme``, the ``x-l0gptsz`` property may be renamed or + removed in some future QEMU release. ++ ++Configuring CPU features via ID register fields ++=============================================== ++ ++Note that this is currently only supported under KVM, and with the ++``host`` CPU model. ++ ++Querying available ID register fields ++------------------------------------- ++ ++QEMU will create properties for all ID register fields that are ++reported as being writable by the kernel, and that are known to the ++QEMU instance. Therefore, the same QEMU binary may expose different ++properties when run under a different kernel. ++ ++To find out all available writable ID register fields, use the ++``query-cpu-model-expansion`` QMP command:: ++ ++ (QEMU) query-cpu-model-expansion type=full model={"name":"host"} ++ {"return": { ++ "model": {"name": "host", "props": { ++ "SYSREG_ID_AA64PFR0_EL1_EL3": 1, "SYSREG_ID_AA64ISAR2_EL1_CLRBHB": 0, ++ "SYSREG_CTR_EL0_L1Ip": 3, "SYSREG_CTR_EL0_DminLine": 4, ++ "SYSREG_ID_AA64MMFR0_EL1_BIGEND": 1, "SYSREG_ID_AA64MMFR1_EL1_ECBHB": 0, ++ "SYSREG_ID_AA64MMFR2_EL1_CnP": 1, "SYSREG_ID_DFR0_EL1_PerfMon": 4, ++ "SYSREG_ID_AA64PFR0_EL1_DIT": 0, "SYSREG_ID_AA64MMFR1_EL1_HAFDBS": 2, ++ "SYSREG_ID_AA64ISAR0_EL1_FHM": 0, "SYSREG_ID_AA64ISAR2_EL1_CSSC": 0, ++ "SYSREG_ID_AA64ISAR0_EL1_DP": 1, (...) ++ }}}} ++ ++If a certain field in an ID register does not show up in this list, it ++is not writable with the specific host kernel. ++ ++A note on compatibility ++----------------------- ++ ++A common use case for providing a defined set of ID register values is ++to be able to present a fixed set of features to a guest, often referred ++to as "stable guest ABI". This may take the form of ironing out differences ++between two similar CPUs with the intention of being able to migrate ++between machines with those CPUs, or providing the same CPU across Linux ++kernel updates on the host. ++ ++Over the course of time, the Linux kernel is changing the set of ID register ++fields that are writable by userspace. Newly introduced writable ID ++registers should be initialized to 0 to ensure compatibility. However, ID ++registers that have already been introduced that undergo a change as to ++which fields are writable may introduce incompatibities that need to be ++addressed on a case-by-case basis for the systems that you wish to migrate ++inbetween. ++ ++A note on Arm CPU features (FEAT_xxx) ++------------------------------------- ++ ++Configuring CPUs is done on a feature level on other architectures, and this ++would imply configuring FEAT_xxx values on Arm. However, differences between ++CPUs may not map to FEAT_xxx, but to differences in other registers in the ++ID register range; for example, differences in the cache architecture exposed ++via ``CTR_EL0``. We therefore cannot rely on configuration via FEAT_xxx. A ++feature-based interface more similar to other architectures may be implemented ++on top of the ID register interface in the future. +-- +2.51.0.windows.1 + diff --git a/arm-cpu-manually-make-MIDR-REVIDR-AIDR-writable.patch b/arm-cpu-manually-make-MIDR-REVIDR-AIDR-writable.patch new file mode 100644 index 0000000000000000000000000000000000000000..a7375d210c603ff7afd032d8dfacfe6dc57ea5fa --- /dev/null +++ b/arm-cpu-manually-make-MIDR-REVIDR-AIDR-writable.patch @@ -0,0 +1,122 @@ +From 8c3706bcbb07816384ffa5e26c97c6a570d0e24b Mon Sep 17 00:00:00 2001 +From: Qingtong Jia +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 25/26] arm/cpu: manually make MIDR/REVIDR/AIDR writable + +Currently MIDR/REVIDR/AIDR didn't create from sysreg generation scripts, +we manually add MIDR/REVIDR/AIDR for now. + +Signed-off-by: Qingtong Jia +--- + scripts/arm-gen-cpu-sysregs-header.awk | 5 ++++- + scripts/gen-cpu-sysreg-properties.awk | 21 +++++++++++++++++++++ + target/arm/cpu-sysreg-properties.c | 19 +++++++++++++++++++ + target/arm/cpu-sysregs.h.inc | 4 +++- + target/arm/cpu64.c | 2 +- + 5 files changed, 48 insertions(+), 3 deletions(-) + +diff --git a/scripts/arm-gen-cpu-sysregs-header.awk b/scripts/arm-gen-cpu-sysregs-header.awk +index f92bbbafa7..9f16e420f8 100755 +--- a/scripts/arm-gen-cpu-sysregs-header.awk ++++ b/scripts/arm-gen-cpu-sysregs-header.awk +@@ -9,7 +9,10 @@ BEGIN { + print "/* GENERATED FILE, DO NOT EDIT */" + print "/* use arm-gen-cpu-sysregs-header.awk to regenerate */" + } END { +- print "" ++ /* add MIDR, REVIDR, and AIDR */ ++ print "DEF(MIDR_EL1, 3, 0, 0, 0, 0)" ++ print "DEF(REVIDR_EL1, 3, 0, 0, 0, 6)" ++ print "DEF(AIDR_EL1, 3, 1, 0, 0, 7)" + } + + # skip blank lines and comment lines +diff --git a/scripts/gen-cpu-sysreg-properties.awk b/scripts/gen-cpu-sysreg-properties.awk +index da00d377ff..56d9d8f002 100755 +--- a/scripts/gen-cpu-sysreg-properties.awk ++++ b/scripts/gen-cpu-sysreg-properties.awk +@@ -106,6 +106,27 @@ END { + if (__current_block_depth != 0) + fatal("Missing terminator for " block_current() " block") + ++ # Manually add MIDR/REVIDR/AIDR ++ print "" ++ print " /* MIDR_EL1 */" ++ print " ARM64SysReg *MIDR_EL1 = arm64_sysreg_get(MIDR_EL1_IDX);" ++ print " MIDR_EL1->name = \"MIDR_EL1\";" ++ print " arm64_sysreg_add_field(MIDR_EL1, \"Implementer\", 24, 31);" ++ print " arm64_sysreg_add_field(MIDR_EL1, \"Variant\", 20, 23);" ++ print " arm64_sysreg_add_field(MIDR_EL1, \"Architecture\", 16, 19);" ++ print " arm64_sysreg_add_field(MIDR_EL1, \"PartNum\", 4, 15);" ++ print " arm64_sysreg_add_field(MIDR_EL1, \"Revision\", 0, 3);" ++ print "" ++ print " /* REVIDR_EL1 */" ++ print " ARM64SysReg *REVIDR_EL1 = arm64_sysreg_get(REVIDR_EL1_IDX);" ++ print " REVIDR_EL1->name = \"REVIDR_EL1\";" ++ print " arm64_sysreg_add_field(REVIDR_EL1, \"IMPDEF\", 0, 63);" ++ print "" ++ print " /* AIDR_EL1 */" ++ print " ARM64SysReg *AIDR_EL1 = arm64_sysreg_get(AIDR_EL1_IDX);" ++ print " AIDR_EL1->name = \"AIDR_EL1\";" ++ print " arm64_sysreg_add_field(AIDR_EL1, \"IMPDEF\", 0, 63);" ++ print "" + print "}" + } + +diff --git a/target/arm/cpu-sysreg-properties.c b/target/arm/cpu-sysreg-properties.c +index 94cc496438..c8a43c9eb4 100644 +--- a/target/arm/cpu-sysreg-properties.c ++++ b/target/arm/cpu-sysreg-properties.c +@@ -742,4 +742,23 @@ void initialize_cpu_sysreg_properties(void) + + /* For S2PIR_EL2 fields see PIRx_ELx */ + ++ /* MIDR_EL1 */ ++ ARM64SysReg *MIDR_EL1 = arm64_sysreg_get(MIDR_EL1_IDX); ++ MIDR_EL1->name = "MIDR_EL1"; ++ arm64_sysreg_add_field(MIDR_EL1, "Implementer", 24, 31); ++ arm64_sysreg_add_field(MIDR_EL1, "Variant", 20, 23); ++ arm64_sysreg_add_field(MIDR_EL1, "Architecture", 16, 19); ++ arm64_sysreg_add_field(MIDR_EL1, "PartNum", 4, 15); ++ arm64_sysreg_add_field(MIDR_EL1, "Revision", 0, 3); ++ ++ /* REVIDR_EL1 */ ++ ARM64SysReg *REVIDR_EL1 = arm64_sysreg_get(REVIDR_EL1_IDX); ++ REVIDR_EL1->name = "REVIDR_EL1"; ++ arm64_sysreg_add_field(REVIDR_EL1, "IMPDEF", 0, 63); ++ ++ /* AIDR_EL1 */ ++ ARM64SysReg *AIDR_EL1 = arm64_sysreg_get(AIDR_EL1_IDX); ++ AIDR_EL1->name = "AIDR_EL1"; ++ arm64_sysreg_add_field(AIDR_EL1, "IMPDEF", 0, 63); ++ + } +diff --git a/target/arm/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc +index 1dddd3d357..e3e81e11ee 100644 +--- a/target/arm/cpu-sysregs.h.inc ++++ b/target/arm/cpu-sysregs.h.inc +@@ -50,4 +50,6 @@ DEF(GMID_EL1, 3, 1, 0, 0, 4) + DEF(SMIDR_EL1, 3, 1, 0, 0, 6) + 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) +\ No newline at end of file +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 02e5a54b76..edfc19a6ed 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -53,7 +53,7 @@ int get_sysreg_idx(ARMSysRegs sysreg) + switch (sysreg) { + #include "cpu-sysregs.h.inc" + } +- g_assert_not_reached(); ++ return -1; + } + + #undef DEF +-- +2.51.0.windows.1 + diff --git a/arm-cpu-more-customization-for-the-kvm-host-cpu-mode.patch b/arm-cpu-more-customization-for-the-kvm-host-cpu-mode.patch new file mode 100644 index 0000000000000000000000000000000000000000..07fed877a022cf7c58641bf431cef19cc1cb1a54 --- /dev/null +++ b/arm-cpu-more-customization-for-the-kvm-host-cpu-mode.patch @@ -0,0 +1,277 @@ +From 9593509d0f8e80963ece8dbb271144249585fff0 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 22/26] arm/cpu: more customization for the kvm host cpu model + +If the interface for writable ID registers is available, expose uint64 +SYSREG properties for writable ID reg fields exposed by the host +kernel. Properties are named SYSREG__ with REG and FIELD +being those used in linux arch/arm64/tools/sysreg. This done by +matching the writable fields retrieved from the host kernel against the +generated description of sysregs. + +An example of invocation is: +-cpu host,SYSREG_ID_AA64ISAR0_EL1_DP=0x0 +which sets DP field of ID_AA64ISAR0_EL1 to 0. + +[CH: add properties to the host model instead of introducing a new +"custom" model] +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu.c | 12 ++++ + target/arm/cpu64.c | 22 ++++++- + target/arm/kvm64.c | 138 ++++++++++++++++++++++++++++++++++++++++ + target/arm/kvm_arm.h | 10 +++ + target/arm/trace-events | 4 ++ + 5 files changed, 185 insertions(+), 1 deletion(-) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 08d83c4e1a..1f91fb6cf2 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1839,6 +1839,18 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + return; + } + ++ /* ++ * If we failed to retrieve the set of writable ID registers for the "host" ++ * CPU model, report it here. No error if the interface for discovering ++ * writable ID registers is not available. ++ * In case we did get the set of writable ID registers, set the features to ++ * the configured values here and perform some sanity checks. ++ */ ++ if (cpu->writable_id_regs == WRITABLE_ID_REGS_FAILED) { ++ error_setg(errp, "Failed to discover writable id registers"); ++ return; ++ } ++ + #ifndef CONFIG_USER_ONLY + /* The NVIC and M-profile CPU are two halves of a single piece of + * hardware; trying to use one without the other is a command line +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 1a64bdf86e..02e5a54b76 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -919,12 +919,32 @@ static void aarch64_host_initfn(Object *obj) + { + #if defined(CONFIG_KVM) + ARMCPU *cpu = ARM_CPU(obj); +- kvm_arm_set_cpu_features_from_host(cpu, false); ++ bool expose_id_regs = true; ++ int ret; ++ ++ cpu->writable_map = g_malloc(sizeof(IdRegMap)); ++ ++ /* discover via KVM_ARM_GET_REG_WRITABLE_MASKS */ ++ ret = kvm_arm_get_writable_id_regs(cpu, cpu->writable_map); ++ if (ret == -ENOSYS) { ++ /* legacy: continue without writable id regs */ ++ expose_id_regs = false; ++ } else if (ret) { ++ /* function will have marked an error */ ++ return; ++ } ++ ++ kvm_arm_set_cpu_features_from_host(cpu, expose_id_regs); + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + aarch64_add_sve_properties(obj); + aarch64_add_pauth_properties(obj); + aarch64_add_kvm_writable_properties(obj); + } ++ if (expose_id_regs) { ++ /* generate SYSREG properties according to writable masks */ ++ kvm_arm_expose_idreg_properties(cpu, arm64_id_regs); ++ } ++ + #elif defined(CONFIG_HVF) + ARMCPU *cpu = ARM_CPU(obj); + hvf_arm_set_cpu_features_from_host(cpu); +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index be9233f936..7e0ca919b2 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -339,6 +339,144 @@ static int get_host_cpu_idregs(ARMCPU *cpu, int fd, ARMHostCPUFeatures *ahcf) + return err; + } + ++ ++static ARM64SysRegField *get_field(int i, ARM64SysReg *reg) ++{ ++ GList *l; ++ ++ for (l = reg->fields; l; l = l->next) { ++ ARM64SysRegField *field = (ARM64SysRegField *)l->data; ++ ++ if (i >= field->lower && i <= field->upper) { ++ return field; ++ } ++ } ++ return NULL; ++} ++ ++static void set_sysreg_prop(Object *obj, Visitor *v, ++ const char *name, void *opaque, ++ Error **errp) ++{ ++ ARM64SysRegField *field = (ARM64SysRegField *)opaque; ++ ARMCPU *cpu = ARM_CPU(obj); ++ uint64_t *idregs = cpu->isar.idregs; ++ uint64_t old, value, mask; ++ int lower = field->lower; ++ int upper = field->upper; ++ int length = upper - lower + 1; ++ int index = field->index; ++ ++ if (!visit_type_uint64(v, name, &value, errp)) { ++ return; ++ } ++ ++ if (length < 64 && value > ((1 << length) - 1)) { ++ error_setg(errp, ++ "idreg %s set value (0x%lx) exceeds length of field (%d)!", ++ name, value, length); ++ return; ++ } ++ ++ mask = MAKE_64BIT_MASK(lower, length); ++ value = value << lower; ++ old = idregs[index]; ++ idregs[index] = old & ~mask; ++ idregs[index] |= value; ++ trace_set_sysreg_prop(name, old, mask, value, idregs[index]); ++} ++ ++static void get_sysreg_prop(Object *obj, Visitor *v, ++ const char *name, void *opaque, ++ Error **errp) ++{ ++ ARM64SysRegField *field = (ARM64SysRegField *)opaque; ++ ARMCPU *cpu = ARM_CPU(obj); ++ uint64_t *idregs = cpu->isar.idregs; ++ uint64_t value, mask; ++ int lower = field->lower; ++ int upper = field->upper; ++ int length = upper - lower + 1; ++ int index = field->index; ++ ++ mask = MAKE_64BIT_MASK(lower, length); ++ value = (idregs[index] & mask) >> lower; ++ visit_type_uint64(v, name, &value, errp); ++ trace_get_sysreg_prop(name, value); ++} ++ ++/* ++ * decode_idreg_writemap: Generate props for writable fields ++ * ++ * @obj: CPU object ++ * @index: index of the sysreg ++ * @map: writable map for the sysreg ++ * @reg: description of the sysreg ++ */ ++static int ++decode_idreg_writemap(Object *obj, int index, uint64_t map, ARM64SysReg *reg) ++{ ++ int i = ctz64(map); ++ int nb_sysreg_props = 0; ++ ++ while (map) { ++ ++ ARM64SysRegField *field = get_field(i, reg); ++ int lower, upper; ++ uint64_t mask; ++ char *prop_name; ++ ++ if (!field) { ++ /* the field cannot be matched to any know id named field */ ++ warn_report("%s bit %d of %s is writable but cannot be matched", ++ __func__, i, reg->name); ++ warn_report("%s is cpu-sysreg-properties.c up to date?", __func__); ++ map = map & ~BIT_ULL(i); ++ i = ctz64(map); ++ continue; ++ } ++ lower = field->lower; ++ upper = field->upper; ++ prop_name = g_strdup_printf("SYSREG_%s_%s", reg->name, field->name); ++ trace_decode_idreg_writemap(field->name, lower, upper, prop_name); ++ object_property_add(obj, prop_name, "uint64", ++ get_sysreg_prop, set_sysreg_prop, NULL, field); ++ nb_sysreg_props++; ++ ++ mask = MAKE_64BIT_MASK(lower, upper - lower + 1); ++ map = map & ~mask; ++ i = ctz64(map); ++ ++ g_free(prop_name); ++ } ++ trace_nb_sysreg_props(reg->name, nb_sysreg_props); ++ return 0; ++} ++ ++/* analyze the writable mask and generate properties for writable fields */ ++void kvm_arm_expose_idreg_properties(ARMCPU *cpu, ARM64SysReg *regs) ++{ ++ int i, idx; ++ IdRegMap *map = cpu->writable_map; ++ Object *obj = OBJECT(cpu); ++ ++ for (i = 0; i < NR_ID_REGS; i++) { ++ uint64_t mask = map->regs[i]; ++ ++ if (mask) { ++ /* reg @i has some writable fields, decode them */ ++ idx = kvm_idx_to_idregs_idx(i); ++ if (idx < 0) { ++ /* no matching reg? */ ++ warn_report("%s: reg %d writable, but not in list of idregs?", ++ __func__, i); ++ } else { ++ decode_idreg_writemap(obj, i, mask, ®s[idx]); ++ } ++ } ++ } ++} ++ + bool kvm_arm_get_host_cpu_features(ARMCPU *cpu, ARMHostCPUFeatures *ahcf, + bool exhaustive) + { +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index e7126d1844..df8258ef34 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -282,6 +282,16 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool exhaustive); + */ + void kvm_arm_add_vcpu_properties(Object *obj); + ++typedef struct ARM64SysReg ARM64SysReg; ++/** ++ * kvm_arm_expose_idreg_properties: ++ * @cpu: The CPU object to generate the properties for ++ * @reg: registers from the host ++ * ++ * analyze the writable mask and generate properties for writable fields ++ */ ++void kvm_arm_expose_idreg_properties(ARMCPU *cpu, ARM64SysReg *regs); ++ + /** + * @cs: CPUState + * @feature: a KVM_ARM_VCPU_* feature +diff --git a/target/arm/trace-events b/target/arm/trace-events +index fe8721d66a..a5f08547a7 100644 +--- a/target/arm/trace-events ++++ b/target/arm/trace-events +@@ -12,6 +12,10 @@ arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d" + + # kvm64.c + get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu host value for %s is 0x%"PRIx64 ++decode_idreg_writemap(const char* name, int lower, int upper, char *prop_name) "%s [%d:%d] is writable (prop %s)" ++get_sysreg_prop(const char *name, uint64_t value) "%s 0x%"PRIx64 ++set_sysreg_prop(const char *name, uint64_t old, uint64_t mask, uint64_t field_value, uint64_t new) "%s old reg value=0x%"PRIx64" mask=0x%"PRIx64" new field value=0x%"PRIx64" new reg value=0x%"PRIx64 ++nb_sysreg_props(const char *name, int count) "%s: %d SYSREG properties" + + # kvm.c + kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64 +-- +2.51.0.windows.1 + diff --git a/arm-cpu-switch-to-a-generated-cpu-sysregs.h.inc.patch b/arm-cpu-switch-to-a-generated-cpu-sysregs.h.inc.patch new file mode 100644 index 0000000000000000000000000000000000000000..bda24b070b975d16a0fb4fb941214de00ffe90d0 --- /dev/null +++ b/arm-cpu-switch-to-a-generated-cpu-sysregs.h.inc.patch @@ -0,0 +1,85 @@ +From c4e3c2bb56b3e72b6b70b050fec6374c8dceac11 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 13/26] arm/cpu: switch to a generated cpu-sysregs.h.inc + +Generated against Linux 6.15. + +Reviewed-by: Sebastian Ott +Reviewed-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu-sysregs.h.inc | 43 +++++++++++++++++++++++++----------- + 1 file changed, 30 insertions(+), 13 deletions(-) + +diff --git a/target/arm/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc +index cb99286f70..1dddd3d357 100644 +--- a/target/arm/cpu-sysregs.h.inc ++++ b/target/arm/cpu-sysregs.h.inc +@@ -1,19 +1,10 @@ + /* SPDX-License-Identifier: GPL-2.0-or-later */ +-DEF(ID_AA64PFR0_EL1, 3, 0, 0, 4, 0) +-DEF(ID_AA64PFR1_EL1, 3, 0, 0, 4, 1) +-DEF(ID_AA64SMFR0_EL1, 3, 0, 0, 4, 5) +-DEF(ID_AA64DFR0_EL1, 3, 0, 0, 5, 0) +-DEF(ID_AA64DFR1_EL1, 3, 0, 0, 5, 1) +-DEF(ID_AA64ISAR0_EL1, 3, 0, 0, 6, 0) +-DEF(ID_AA64ISAR1_EL1, 3, 0, 0, 6, 1) +-DEF(ID_AA64ISAR2_EL1, 3, 0, 0, 6, 2) +-DEF(ID_AA64MMFR0_EL1, 3, 0, 0, 7, 0) +-DEF(ID_AA64MMFR1_EL1, 3, 0, 0, 7, 1) +-DEF(ID_AA64MMFR2_EL1, 3, 0, 0, 7, 2) +-DEF(ID_AA64MMFR3_EL1, 3, 0, 0, 7, 3) ++/* GENERATED FILE, DO NOT EDIT */ ++/* use arm-gen-cpu-sysregs-header.awk to regenerate */ + DEF(ID_PFR0_EL1, 3, 0, 0, 1, 0) + DEF(ID_PFR1_EL1, 3, 0, 0, 1, 1) + DEF(ID_DFR0_EL1, 3, 0, 0, 1, 2) ++DEF(ID_AFR0_EL1, 3, 0, 0, 1, 3) + DEF(ID_MMFR0_EL1, 3, 0, 0, 1, 4) + DEF(ID_MMFR1_EL1, 3, 0, 0, 1, 5) + DEF(ID_MMFR2_EL1, 3, 0, 0, 1, 6) +@@ -24,13 +15,39 @@ DEF(ID_ISAR2_EL1, 3, 0, 0, 2, 2) + DEF(ID_ISAR3_EL1, 3, 0, 0, 2, 3) + DEF(ID_ISAR4_EL1, 3, 0, 0, 2, 4) + DEF(ID_ISAR5_EL1, 3, 0, 0, 2, 5) +-DEF(ID_MMFR4_EL1, 3, 0, 0, 2, 6) + DEF(ID_ISAR6_EL1, 3, 0, 0, 2, 7) ++DEF(ID_MMFR4_EL1, 3, 0, 0, 2, 6) + DEF(MVFR0_EL1, 3, 0, 0, 3, 0) + DEF(MVFR1_EL1, 3, 0, 0, 3, 1) + DEF(MVFR2_EL1, 3, 0, 0, 3, 2) + DEF(ID_PFR2_EL1, 3, 0, 0, 3, 4) + DEF(ID_DFR1_EL1, 3, 0, 0, 3, 5) + DEF(ID_MMFR5_EL1, 3, 0, 0, 3, 6) ++DEF(ID_AA64PFR0_EL1, 3, 0, 0, 4, 0) ++DEF(ID_AA64PFR1_EL1, 3, 0, 0, 4, 1) ++DEF(ID_AA64PFR2_EL1, 3, 0, 0, 4, 2) + DEF(ID_AA64ZFR0_EL1, 3, 0, 0, 4, 4) ++DEF(ID_AA64SMFR0_EL1, 3, 0, 0, 4, 5) ++DEF(ID_AA64FPFR0_EL1, 3, 0, 0, 4, 7) ++DEF(ID_AA64DFR0_EL1, 3, 0, 0, 5, 0) ++DEF(ID_AA64DFR1_EL1, 3, 0, 0, 5, 1) ++DEF(ID_AA64DFR2_EL1, 3, 0, 0, 5, 2) ++DEF(ID_AA64AFR0_EL1, 3, 0, 0, 5, 4) ++DEF(ID_AA64AFR1_EL1, 3, 0, 0, 5, 5) ++DEF(ID_AA64ISAR0_EL1, 3, 0, 0, 6, 0) ++DEF(ID_AA64ISAR1_EL1, 3, 0, 0, 6, 1) ++DEF(ID_AA64ISAR2_EL1, 3, 0, 0, 6, 2) ++DEF(ID_AA64ISAR3_EL1, 3, 0, 0, 6, 3) ++DEF(ID_AA64MMFR0_EL1, 3, 0, 0, 7, 0) ++DEF(ID_AA64MMFR1_EL1, 3, 0, 0, 7, 1) ++DEF(ID_AA64MMFR2_EL1, 3, 0, 0, 7, 2) ++DEF(ID_AA64MMFR3_EL1, 3, 0, 0, 7, 3) ++DEF(ID_AA64MMFR4_EL1, 3, 0, 0, 7, 4) ++DEF(CCSIDR_EL1, 3, 1, 0, 0, 0) ++DEF(CLIDR_EL1, 3, 1, 0, 0, 1) ++DEF(CCSIDR2_EL1, 3, 1, 0, 0, 2) ++DEF(GMID_EL1, 3, 1, 0, 0, 4) ++DEF(SMIDR_EL1, 3, 1, 0, 0, 6) + DEF(CTR_EL0, 3, 3, 0, 0, 1) ++DEF(DCZID_EL0, 3, 3, 0, 0, 7) ++ +-- +2.51.0.windows.1 + diff --git a/arm-kvm-Allow-reading-all-the-writable-ID-registers.patch b/arm-kvm-Allow-reading-all-the-writable-ID-registers.patch new file mode 100644 index 0000000000000000000000000000000000000000..ce670df6bade4244132b62b8f6edc06adddbc225 --- /dev/null +++ b/arm-kvm-Allow-reading-all-the-writable-ID-registers.patch @@ -0,0 +1,262 @@ +From d7565b841e558598fdd94444593b5e9c735d1fc4 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 20/26] arm/kvm: Allow reading all the writable ID registers + +At the moment kvm_arm_get_host_cpu_features() reads a subset of the +ID regs. As we want to introduce properties for all writable ID reg +fields, we want more genericity and read more default host register +values. + +Introduce a new get_host_cpu_idregs() helper and add a new exhaustive +boolean parameter to kvm_arm_get_host_cpu_features() and +kvm_arm_set_cpu_features_from_host() to select the right behavior. +The host cpu model will keep the legacy behavior unless the writable +id register interface is available. + +A writable_map IdRegMap is introduced in the CPU object. A subsequent +patch will populate it. + +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu-sysregs.h | 2 ++ + target/arm/cpu.h | 5 ++- + target/arm/cpu64.c | 2 +- + target/arm/kvm.c | 4 +-- + target/arm/kvm64.c | 74 +++++++++++++++++++++++++++++++++++++++- + target/arm/kvm_arm.h | 17 ++++++--- + target/arm/trace-events | 3 ++ + 7 files changed, 98 insertions(+), 9 deletions(-) + +diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h +index e89a110590..367fab51f1 100644 +--- a/target/arm/cpu-sysregs.h ++++ b/target/arm/cpu-sysregs.h +@@ -41,6 +41,8 @@ int get_sysreg_idx(ARMSysRegs sysreg); + + #ifdef CONFIG_KVM + uint64_t idregs_sysreg_to_kvm_reg(ARMSysRegs sysreg); ++int kvm_idx_to_idregs_idx(int kidx); ++int idregs_idx_to_kvm_idx(ARMIDRegisterIdx idx); + #endif + + #endif /* ARM_CPU_SYSREGS_H */ +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index a75f057430..7f174ca319 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1078,7 +1078,10 @@ struct ArchCPU { + * on KVM custom vcpu model realize + */ + ARMIdRegsState writable_id_regs; +- ++ ++ /* ID reg writable bitmask (KVM only) */ ++ IdRegMap *writable_map; ++ + /* Specify the number of cores in this CPU cluster. Used for the L2CTLR + * register. + */ +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 5ad6f77417..1a64bdf86e 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -919,7 +919,7 @@ static void aarch64_host_initfn(Object *obj) + { + #if defined(CONFIG_KVM) + ARMCPU *cpu = ARM_CPU(obj); +- kvm_arm_set_cpu_features_from_host(cpu); ++ kvm_arm_set_cpu_features_from_host(cpu, false); + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + aarch64_add_sve_properties(obj); + aarch64_add_pauth_properties(obj); +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 50b7ccf759..895f44df18 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -173,13 +173,13 @@ void kvm_arm_destroy_scratch_host_vcpu(int *fdarray) + } + } + +-void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) ++void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool exhaustive) + { + CPUARMState *env = &cpu->env; + + if (!arm_host_cpu_features.dtb_compatible) { + if (!kvm_enabled() || +- !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) { ++ !kvm_arm_get_host_cpu_features(cpu, &arm_host_cpu_features, exhaustive)) { + /* We can't report this error yet, so flag that we need to + * in arm_cpu_realizefn(). + */ +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index bdac9ef549..da9352b14d 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -27,11 +27,13 @@ + #include "sysemu/runstate.h" + #include "sysemu/kvm.h" + #include "sysemu/kvm_int.h" ++#include "trace.h" + #include "kvm_arm.h" + #include "internals.h" + #include "cpu-features.h" + #include "hw/acpi/acpi.h" + #include "hw/acpi/ghes.h" ++#include "cpu-custom.h" + + static bool have_guest_debug; + +@@ -273,7 +275,72 @@ static int get_host_cpu_reg(int fd, ARMHostCPUFeatures *ahcf, ARMIDRegisterIdx i + return ret; + } + +-bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) ++int kvm_idx_to_idregs_idx(int kidx) ++{ ++ int op1, crm, op2; ++ ARMSysRegs sysreg; ++ ++ op1 = kidx / 64; ++ if (op1 == 2) { ++ op1 = 3; ++ } ++ crm = (kidx % 64) / 8; ++ op2 = kidx % 8; ++ sysreg = ENCODE_ID_REG(3, op1, 0, crm, op2); ++ return get_sysreg_idx(sysreg); ++} ++ ++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_MASK) >> CP_REG_ARM64_SYSREG_OP0_SHIFT, ++ (sysreg & CP_REG_ARM64_SYSREG_OP1_MASK) >> CP_REG_ARM64_SYSREG_OP1_SHIFT, ++ (sysreg & CP_REG_ARM64_SYSREG_CRN_MASK) >> CP_REG_ARM64_SYSREG_CRN_SHIFT, ++ (sysreg & CP_REG_ARM64_SYSREG_CRM_MASK) >> CP_REG_ARM64_SYSREG_CRM_SHIFT, ++ (sysreg & CP_REG_ARM64_SYSREG_OP2_MASK) >> CP_REG_ARM64_SYSREG_OP2_SHIFT); ++} ++ ++ ++/* ++ * get_host_cpu_idregs: Read all the writable ID reg host values ++ * ++ * Need to be called once the writable mask has been populated ++ * Note we may want to read all the known id regs but some of them are not ++ * writable and return an error, hence the choice of reading only those which ++ * are writable. Those are also readable! ++ */ ++static int get_host_cpu_idregs(ARMCPU *cpu, int fd, ARMHostCPUFeatures *ahcf) ++{ ++ int err = 0; ++ int i; ++ ++ for (i = 0; i < NUM_ID_IDX; i++) { ++ ARM64SysReg *sysregdesc = &arm64_id_regs[i]; ++ ARMSysRegs sysreg = sysregdesc->sysreg; ++ uint64_t writable_mask = cpu->writable_map->regs[idregs_idx_to_kvm_idx(i)]; ++ uint64_t *reg; ++ int ret; ++ ++ if (!writable_mask) { ++ continue; ++ } ++ ++ reg = &ahcf->isar.idregs[i]; ++ ret = read_sys_reg64(fd, reg, idregs_sysreg_to_kvm_reg(sysreg)); ++ trace_get_host_cpu_idregs(sysregdesc->name, *reg); ++ if (ret) { ++ error_report("%s error reading value of host %s register (%m)", ++ __func__, sysregdesc->name); ++ ++ err = ret; ++ } ++ } ++ return err; ++} ++ ++bool kvm_arm_get_host_cpu_features(ARMCPU *cpu, ARMHostCPUFeatures *ahcf, ++ bool exhaustive) + { + /* Identify the feature bits corresponding to the host CPU, and + * fill out the ARMHostCPUClass fields accordingly. To do this +@@ -399,6 +466,11 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + err |= get_host_cpu_reg(fd, ahcf, ID_DFR1_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_MMFR5_EL1_IDX); + ++ /* Make sure writable ID reg values are read */ ++ if (exhaustive) { ++ err |= get_host_cpu_idregs(cpu, fd, ahcf); ++ } ++ + /* + * DBGDIDR is a bit complicated because the kernel doesn't + * provide an accessor for it in 64-bit mode, which is what this +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index 50ae2be9c5..b82e04e25b 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -237,14 +237,18 @@ typedef struct ARMHostCPUFeatures { + + /** + * kvm_arm_get_host_cpu_features: ++ * @cpu: cpu object + * @ahcf: ARMHostCPUClass to fill in +- * ++ * @exhaustive: if true, all the feature ID regs are queried instead of ++ * a subset ++ + * Probe the capabilities of the host kernel's preferred CPU and fill + * in the ARMHostCPUClass struct accordingly. + * + * Returns true on success and false otherwise. + */ +-bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf); ++bool kvm_arm_get_host_cpu_features(ARMCPU *cpu, ARMHostCPUFeatures *ahcf, ++ bool exhaustive); + + /** + * kvm_arm_sve_get_vls: +@@ -262,8 +266,12 @@ uint32_t kvm_arm_sve_get_vls(CPUState *cs); + * + * Set up the ARMCPU struct fields up to match the information probed + * from the host CPU. ++ * ++ * @cpu: cpu object ++ * @exhaustive: if true, all the feature ID regs are queried instead of ++ * a subset + */ +-void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); ++void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, bool exhaustive); + + /** + * kvm_arm_add_vcpu_properties: +@@ -511,7 +519,8 @@ static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap) + /* + * These functions should never actually be called without KVM support. + */ +-static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) ++static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu, ++ bool exhaustive) + { + g_assert_not_reached(); + } +diff --git a/target/arm/trace-events b/target/arm/trace-events +index 48cc0512db..49162b87b2 100644 +--- a/target/arm/trace-events ++++ b/target/arm/trace-events +@@ -10,5 +10,8 @@ arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle" + arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64 + arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d" + ++# kvm64.c ++get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu host value for %s is 0x%"PRIx64 ++ + # kvm.c + kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64 +-- +2.51.0.windows.1 + diff --git a/arm-kvm-use-fd-instead-of-fdarray-2.patch b/arm-kvm-use-fd-instead-of-fdarray-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..400b5f5d262510208f6cdcf4fe4b9c948dc9fe96 --- /dev/null +++ b/arm-kvm-use-fd-instead-of-fdarray-2.patch @@ -0,0 +1,45 @@ +From e682560920b662fd73c00bea4fd3ca47fe8433df Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 14/26] arm/kvm: use fd instead of fdarray[2] + +We have fd, so might as well neaten things up. + +Suggested-by: Eric Auger +Reviewed-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/kvm64.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 4e184fe1d5..bdac9ef549 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -389,11 +389,11 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + err |= get_host_cpu_reg(fd, ahcf, ID_ISAR6_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_MMFR4_EL1_IDX); + +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, ++ err |= read_sys_reg32(fd, &ahcf->isar.mvfr0, + ARM64_SYS_REG(3, 0, 0, 3, 0)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1, ++ err |= read_sys_reg32(fd, &ahcf->isar.mvfr1, + ARM64_SYS_REG(3, 0, 0, 3, 1)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, ++ err |= read_sys_reg32(fd, &ahcf->isar.mvfr2, + ARM64_SYS_REG(3, 0, 0, 3, 2)); + err |= get_host_cpu_reg(fd, ahcf, ID_PFR2_EL1_IDX); + err |= get_host_cpu_reg(fd, ahcf, ID_DFR1_EL1_IDX); +@@ -431,7 +431,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + + if (pmu_supported) { + /* PMCR_EL0 is only accessible if the vCPU has feature PMU_V3 */ +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.reset_pmcr_el0, ++ err |= read_sys_reg64(fd, &ahcf->isar.reset_pmcr_el0, + KVM_REG_ARM_PMCR_EL0); + } + +-- +2.51.0.windows.1 + diff --git a/arm-kvm-write-back-modified-ID-regs-to-KVM.patch b/arm-kvm-write-back-modified-ID-regs-to-KVM.patch new file mode 100644 index 0000000000000000000000000000000000000000..bdabbadc93b4448b2fbccfbd7e4dab320aa4a4d0 --- /dev/null +++ b/arm-kvm-write-back-modified-ID-regs-to-KVM.patch @@ -0,0 +1,142 @@ +From 05c35d0d6e7b778563e1aa4f624f8472c814e285 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 21/26] arm/kvm: write back modified ID regs to KVM + +We want to give a chance to override the value of host ID regs. +In a previous patch we made sure all their values could be fetched +through kvm_get_one_reg() calls before their modification. After +their potential modification we need to make sure we write back +the values through kvm_set_one_reg() calls. + +Make sure the cpreg_list is modified with updated values and +transfer those values back to kvm. + +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/kvm.c | 34 ++++++++++++++++++++++++++++++++++ + target/arm/kvm64.c | 13 +++++++++++-- + target/arm/kvm_arm.h | 6 ++++++ + target/arm/trace-events | 1 + + 4 files changed, 52 insertions(+), 2 deletions(-) + +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 895f44df18..1b5bd85e77 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -23,6 +23,7 @@ + #include "sysemu/kvm_int.h" + #include "kvm_arm.h" + #include "cpu.h" ++#include "cpu-custom.h" + #include "cpu-sysregs.h" + #include "trace.h" + #include "internals.h" +@@ -798,6 +799,39 @@ static void kvm_arm_configure_vcpu_regs(ARMCPU *cpu) + kvm_arm_configure_pmcr(cpu); + } + ++void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu) ++{ ++ if (!cpu->writable_map) { ++ return; ++ } ++ for (int i = 0; i < NR_ID_REGS; i++) { ++ uint64_t writable_mask = cpu->writable_map->regs[i]; ++ uint64_t *cpreg; ++ ++ if (writable_mask) { ++ uint64_t previous, new; ++ int idx = kvm_idx_to_idregs_idx(i); ++ ARM64SysReg *sysregdesc; ++ uint32_t sysreg; ++ ++ if (idx == -1) { ++ /* sysreg writable, but we don't know it */ ++ continue; ++ } ++ sysregdesc = &arm64_id_regs[idx]; ++ sysreg = sysregdesc->sysreg; ++ cpreg = kvm_arm_get_cpreg_ptr(cpu, idregs_sysreg_to_kvm_reg(sysreg)); ++ previous = *cpreg; ++ new = cpu->isar.idregs[idx]; ++ if (previous != new) { ++ *cpreg = new; ++ trace_kvm_arm_writable_idregs_to_cpreg_list(sysregdesc->name, ++ previous, new); ++ } ++ } ++ } ++} ++ + void kvm_arm_reset_vcpu(ARMCPU *cpu) + { + int ret; +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index da9352b14d..be9233f936 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -470,7 +470,7 @@ bool kvm_arm_get_host_cpu_features(ARMCPU *cpu, ARMHostCPUFeatures *ahcf, + if (exhaustive) { + err |= get_host_cpu_idregs(cpu, fd, ahcf); + } +- ++ + /* + * DBGDIDR is a bit complicated because the kernel doesn't + * provide an accessor for it in 64-bit mode, which is what this +@@ -757,7 +757,16 @@ int kvm_arch_init_vcpu(CPUState *cs) + /* Check whether user space can specify guest syndrome value */ + kvm_arm_init_serror_injection(cs); + +- return kvm_arm_init_cpreg_list(cpu); ++ ret = kvm_arm_init_cpreg_list(cpu); ++ if (ret) { ++ return ret; ++ } ++ /* overwrite writable ID regs with their updated property values */ ++ kvm_arm_writable_idregs_to_cpreg_list(cpu); ++ ++ write_list_to_kvmstate(cpu, 3); ++ ++ return 0; + } + + int kvm_arch_destroy_vcpu(CPUState *cs) +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index b82e04e25b..e7126d1844 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -471,6 +471,8 @@ Object *kvm_arm_rme_get_measurement_log(void); + + int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap); + ++void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu); ++ + #else + + /* +@@ -516,6 +518,10 @@ static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap) + return -ENOSYS; + } + ++void kvm_arm_writable_idregs_to_cpreg_list(ARMCPU *cpu) ++{ ++ g_assert_not_reached(); ++} + /* + * These functions should never actually be called without KVM support. + */ +diff --git a/target/arm/trace-events b/target/arm/trace-events +index 49162b87b2..fe8721d66a 100644 +--- a/target/arm/trace-events ++++ b/target/arm/trace-events +@@ -15,3 +15,4 @@ get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu host value f + + # kvm.c + kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64 ++kvm_arm_writable_idregs_to_cpreg_list(const char *name, uint64_t previous, uint64_t new) "%s overwrite default 0x%"PRIx64" with 0x%"PRIx64 +-- +2.51.0.windows.1 + diff --git a/arm-qmp-cmds-introspection-for-ID-register-props.patch b/arm-qmp-cmds-introspection-for-ID-register-props.patch new file mode 100644 index 0000000000000000000000000000000000000000..be603b713cf66c3ad0aa41e7c76ec53bea7fb053 --- /dev/null +++ b/arm-qmp-cmds-introspection-for-ID-register-props.patch @@ -0,0 +1,66 @@ +From 0e3658b3adef452d8b21c08bbe0944b837549eeb Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 23/26] arm-qmp-cmds: introspection for ID register props + +Implement the capability to query available ID register values by +adding SYSREG_* options and values to the cpu model expansion for the +host model, if available. + +Excerpt: +(QEMU) query-cpu-model-expansion type=full model={"name":"host"} +{"return": {"model": {"name": "host", "props": +{"SYSREG_ID_AA64PFR0_EL1_EL3": 1224979098931106066, +"SYSREG_ID_AA64ISAR2_EL1_CLRBHB": 0, +../.. + +So this allows the upper stack to detect available writable ID +regs and the "host passthrough model" values. + +[CH: moved SYSREG_* values to host model] +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/arm-qmp-cmds.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/target/arm/arm-qmp-cmds.c b/target/arm/arm-qmp-cmds.c +index d201d319bd..5109aeb873 100644 +--- a/target/arm/arm-qmp-cmds.c ++++ b/target/arm/arm-qmp-cmds.c +@@ -21,6 +21,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/error-report.h" + #include "hw/boards.h" + #include "kvm_arm.h" + #include "qapi/error.h" +@@ -218,6 +219,24 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, + } + } + ++ /* If writable ID regs are supported, add them as well */ ++ if (ARM_CPU(obj)->writable_id_regs == WRITABLE_ID_REGS_AVAIL) { ++ ObjectProperty *prop; ++ ObjectPropertyIterator iter; ++ ++ object_property_iter_init(&iter, obj); ++ ++ while ((prop = object_property_iter_next(&iter))) { ++ QObject *value; ++ ++ if (!g_str_has_prefix(prop->name, "SYSREG_")) { ++ continue; ++ } ++ value = object_property_get_qobject(obj, prop->name, &error_abort); ++ qdict_put_obj(qdict_out, prop->name, value); ++ } ++ } ++ + if (!qdict_size(qdict_out)) { + qobject_unref(qdict_out); + } else { +-- +2.51.0.windows.1 + diff --git a/hw-arm-virt-Initial-support-to-set-target_impl-CPUs.patch b/hw-arm-virt-Initial-support-to-set-target_impl-CPUs.patch new file mode 100644 index 0000000000000000000000000000000000000000..5c60c0558e0bdc1d2c79557ee67d23fc3afb849b --- /dev/null +++ b/hw-arm-virt-Initial-support-to-set-target_impl-CPUs.patch @@ -0,0 +1,256 @@ +From 5f8bb127fc2f7c693cf8e75da68338402cbfbe63 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 2/4] hw/arm/virt: Initial support to set target_impl CPUs + +This is a hacked interface to test the kernel. + +Usage Eg: +-machine virt,.., x-target-impl-cpus=0xMIDR1:0xREVIDR1-0xMIDR2:REVIDR2 + +The HVC/SMC hypercall exit handling part is loosly based on this patch, +https://lore.kernel.org/qemu-devel/20240614001510.202991-1-salil.mehta@huawe... + +Signed-off-by: Shameer Kolothum +--- + hw/arm/virt.c | 65 ++++++++++++++++++++++++++++++++++++++- + include/hw/boards.h | 3 ++ + target/arm/kvm.c | 72 +++++++++++++++++++++++++++++++++++++++++--- + target/arm/kvm_arm.h | 6 ++++ + 4 files changed, 140 insertions(+), 6 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index f7a9ba9a58..e046fff5dd 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -29,6 +29,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/cutils.h" + #include "qemu/datadir.h" + #include "qemu/units.h" + #include "qemu/option.h" +@@ -3103,6 +3104,62 @@ static void virt_set_oem_table_id(Object *obj, const char *value, + strncpy(vms->oem_table_id, value, 8); + } + ++static TargetImplCpu target_impl_cpus[MAX_TARGET_IMPL_CPUS]; ++ ++static void virt_set_target_impl_cpus(Object *obj, const char *value, ++ Error **errp) ++{ ++ MachineState *ms = MACHINE(obj); ++ g_autofree char *target_dup = g_strdup(value); ++ char *target_impl = strtok(target_dup, "-"); ++ int cnt = 0; ++ ++ while (target_impl) { ++ char num[16]; ++ long val; ++ const char *num_start = target_impl; ++ const char *num_end = strchr(num_start, ':'); ++ ++ if (!num_end) { ++ error_setg(errp, ++ "Wrong format, Please use 0xmidr:0xrevid-0xmidr:0xrevid"); ++ return; ++ } ++ ++ strncpy(num, num_start, num_end - num_start); ++ num[num_end - num_start] = '\0'; ++ if (qemu_strtol(num, NULL, 16, &val)) { ++ error_setg(errp, ++ "Wrong format, Please use 0xmidr:0xrevid-0xmidr:0xrevid"); ++ return; ++ } ++ target_impl_cpus[cnt].midr = val; ++ num_start = num_end + 1; ++ if (!(*num_start)) { ++ error_setg(errp, ++ "Wrong format, Please use 0xmidr:0xrevid-0xmidr:0xrevid"); ++ return; ++ } ++ ++ strncpy(num, num_start, sizeof(num) - 1); ++ num[sizeof(num) - 1] = '\0'; ++ if (qemu_strtol(num, NULL, 16, &val)) { ++ error_setg(errp, ++ "Wrong format, Please use 0xmidr:0xrevid-0xmidr:0xrevid"); ++ return; ++ } ++ target_impl_cpus[cnt].revidr = val; ++ cnt++; ++ if (cnt >= MAX_TARGET_IMPL_CPUS) { ++ error_setg(errp, ++ "Wrong format, Max %d targets can be set for now!", MAX_TARGET_IMPL_CPUS); ++ return; ++ } ++ target_impl = strtok(NULL, "-"); ++ } ++ ms->target_ipml_cpu_num = cnt; ++ ms->target_ipml_cpu = target_impl_cpus; ++} + + bool virt_is_acpi_enabled(VirtMachineState *vms) + { +@@ -4085,7 +4142,13 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + "Override the default value of field OEM Table ID " + "in ACPI table header." + "The string may be up to 8 bytes in size"); +- ++ ++ object_class_property_add_str(oc, "x-target-impl-cpus", ++ NULL, ++ virt_set_target_impl_cpus); ++ object_class_property_set_description(oc, "x-target-impl-cpus", ++ "Describe target cpu impl in the format midr1:revidr1-midr2:revidr2" ++ "Maximum 4 midr:revidr pair is supported"); + } + + static char *virt_get_kvm_type(Object *obj, Error **errp G_GNUC_UNUSED) +diff --git a/include/hw/boards.h b/include/hw/boards.h +index 8ac8cad2a2..192dc7dc09 100644 +--- a/include/hw/boards.h ++++ b/include/hw/boards.h +@@ -402,6 +402,9 @@ struct MachineState { + CpuTopology smp; + struct NVDIMMState *nvdimms_state; + struct NumaState *numa_state; ++ ++ uint32_t target_ipml_cpu_num; ++ void *target_ipml_cpu; + }; + + #define DEFINE_MACHINE(namestr, machine_initfn) \ +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 52fb1b0919..3ecb1f339a 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -59,7 +59,7 @@ + #define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER 64 + #define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS 65 + +-#define ARM_SMCCC_KVM_DISCOVER_IMPL_VER_1_0 0x10000 ++#define ARM_SMCCC_KVM_DISCOVER_IMPL_VER_1_0 0x100000000 + + #define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \ + (((type) << ARM_SMCCC_TYPE_SHIFT) | \ +@@ -440,6 +440,16 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + if (ret) { + error_report("Failed to enable RME: %s", strerror(-ret)); + } ++ ++ if (kvm_arm_set_smccc_filter(ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID, ++ KVM_SMCCC_FILTER_FWD_TO_USER)) { ++ error_report("ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER fwd filter install failed"); ++ } ++ ++ if (kvm_arm_set_smccc_filter(ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID, ++ KVM_SMCCC_FILTER_FWD_TO_USER)) { ++ error_report("ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS fwd filter install failed"); ++ } + + return ret; + } +@@ -1178,6 +1188,55 @@ void kvm_arm_vm_state_change(void *opaque, bool running, RunState state) + } + } + ++static bool arm_handle_smcc_kvm_vendor_hypercall(ARMCPU *cpu) ++{ ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ CPUARMState *env = &cpu->env; ++ uint64_t param[4]; ++ int idx; ++ int i; ++ ++ for (i = 0; i < 4; i++) { ++ /* ++ * All PSCI functions take explicit 32-bit or native int sized ++ * arguments so we can simply zero-extend all arguments regardless ++ * of which exact function we are about to call. ++ */ ++ param[i] = is_a64(env) ? env->xregs[i] : env->regs[i]; ++ } ++ ++ if (is_a64(env)) { ++ TargetImplCpu *target = ms->target_ipml_cpu; ++ ++ switch (param[0]) { ++ case ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID: ++ if (!ms->target_ipml_cpu_num) { ++ env->xregs[0] = SMCCC_RET_NOT_SUPPORTED; ++ break; ++ } ++ env->xregs[0] = SMCCC_RET_SUCCESS; ++ env->xregs[1] = ARM_SMCCC_KVM_DISCOVER_IMPL_VER_1_0; ++ env->xregs[2] = ms->target_ipml_cpu_num; ++ break; ++ case ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID: ++ idx = param[1]; ++ if (idx >= ms->target_ipml_cpu_num) { ++ env->xregs[0] = SMCCC_RET_INVALID_PARAMETER; ++ break; ++ } ++ env->xregs[0] = SMCCC_RET_SUCCESS; ++ env->xregs[1] = target[idx].midr; ++ env->xregs[2] = target[idx].revidr; ++ break; ++ default: ++ return false; ++ } ++ } else { ++ return false; ++ } ++ return true; ++} ++ + /** + * kvm_arm_handle_dabt_nisv: + * @cs: CPUState +@@ -1240,9 +1299,12 @@ static int kvm_arm_handle_hypercall(CPUState *cs, struct kvm_run *run) + env->exception.syndrome = syn_aa64_hvc(0); + } + env->exception.target_el = 1; +- qemu_mutex_lock_iothread(); +- arm_cpu_do_interrupt(cs); +- qemu_mutex_unlock_iothread(); ++ ++ if (!arm_handle_smcc_kvm_vendor_hypercall(cpu)) { ++ qemu_mutex_lock_iothread(); ++ arm_cpu_do_interrupt(cs); ++ qemu_mutex_unlock_iothread(); ++ } + + /* + * For PSCI, exit the kvm_run loop and process the work. Especially +@@ -1267,7 +1329,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) + run->arm_nisv.fault_ipa); + break; + case KVM_EXIT_HYPERCALL: +- ret = kvm_arm_handle_hypercall(cs, run); ++ ret = kvm_arm_handle_hypercall(cs, run); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index df8258ef34..8c69957fbf 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -21,6 +21,12 @@ + #define KVM_REG_ARM_ID_AA64DFR0_EL1 ARM64_SYS_REG(3, 0, 0, 5, 0) + #define KVM_REG_ARM_PMCR_EL0 ARM64_SYS_REG(3, 3, 9, 12, 0) + ++#define MAX_TARGET_IMPL_CPUS 8 ++typedef struct TargetImplCpu { ++ uint32_t midr; ++ uint32_t revidr; ++} TargetImplCpu; ++ + /** + * kvm_arm_init_debug() - initialize guest debug capabilities + * @s: KVMState +-- +2.51.0.windows.1 + diff --git a/kvm-kvm_get_writable_id_regs.patch b/kvm-kvm_get_writable_id_regs.patch new file mode 100644 index 0000000000000000000000000000000000000000..669a4f79de17440d541e132470fcb3b923c3cf8b --- /dev/null +++ b/kvm-kvm_get_writable_id_regs.patch @@ -0,0 +1,139 @@ +From 39c606cce1f67508c36985ada072b3a4688794da Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 18/26] kvm: kvm_get_writable_id_regs + +Add an helper to retrieve the writable id reg bitmask. The +status of the query is stored in the CPU struct so that an +an error, if any, can be reported on vcpu realize(). + +Signed-off-by: Eric Auger +Signed-off-by: Cornelia Huck +--- + target/arm/cpu.h | 26 ++++++++++++++++++++++++++ + target/arm/kvm.c | 32 ++++++++++++++++++++++++++++++++ + target/arm/kvm_arm.h | 7 +++++++ + 3 files changed, 65 insertions(+) + +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 2c8f2ffd45..3f57363baf 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -846,6 +846,26 @@ typedef struct { + uint32_t map, init, supported; + } ARMVQMap; + ++typedef enum ARMIdRegsState { ++ WRITABLE_ID_REGS_UNKNOWN, ++ WRITABLE_ID_REGS_NOT_DISCOVERABLE, ++ WRITABLE_ID_REGS_FAILED, ++ WRITABLE_ID_REGS_AVAIL, ++} ARMIdRegsState; ++ ++/* ++ * The following structures are for the purpose of mapping the output of ++ * KVM_ARM_GET_REG_WRITABLE_MASKS that also may cover id registers we do ++ * not support in QEMU ++ * ID registers in op0==3, op1=={0,1,3}, crn=0, crm=={0-7}, op2=={0-7}, ++ * as used by the KVM_ARM_GET_REG_WRITABLE_MASKS ioctl call. ++ */ ++#define NR_ID_REGS (3 * 8 * 8) ++ ++typedef struct IdRegMap { ++ uint64_t regs[NR_ID_REGS]; ++} IdRegMap; ++ + /* REG is ID_XXX */ + #define FIELD_DP64_IDREG(ISAR, REG, FIELD, VALUE) \ + ({ \ +@@ -1035,6 +1055,12 @@ struct ArchCPU { + */ + bool host_cpu_probe_failed; + ++ /* ++ * state of writable id regs query used to report an error, if any, ++ * on KVM custom vcpu model realize ++ */ ++ ARMIdRegsState writable_id_regs; ++ + /* Specify the number of cores in this CPU cluster. Used for the L2CTLR + * register. + */ +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index c6c92c120f..50b7ccf759 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -43,6 +43,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + static bool cap_has_mp_state; + static bool cap_has_inject_serror_esr; + static bool cap_has_inject_ext_dabt; ++static int cap_writable_id_regs; + + static ARMHostCPUFeatures arm_host_cpu_features; + +@@ -194,6 +195,37 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) + env->features = arm_host_cpu_features.features; + } + ++int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap) ++{ ++ struct reg_mask_range range = { ++ .range = 0, /* up to now only a single range is supported */ ++ .addr = (uint64_t)idregmap, ++ }; ++ int ret; ++ ++ if (!kvm_enabled()) { ++ cpu->writable_id_regs = WRITABLE_ID_REGS_NOT_DISCOVERABLE; ++ return -ENOSYS; ++ } ++ ++ cap_writable_id_regs = ++ kvm_check_extension(kvm_state, KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES); ++ ++ if (!cap_writable_id_regs || ++ !(cap_writable_id_regs & (1 << KVM_ARM_FEATURE_ID_RANGE))) { ++ cpu->writable_id_regs = WRITABLE_ID_REGS_NOT_DISCOVERABLE; ++ return -ENOSYS; ++ } ++ ++ ret = kvm_vm_ioctl(kvm_state, KVM_ARM_GET_REG_WRITABLE_MASKS, &range); ++ if (ret) { ++ cpu->writable_id_regs = WRITABLE_ID_REGS_FAILED; ++ return ret; ++ } ++ cpu->writable_id_regs = WRITABLE_ID_REGS_AVAIL; ++ return ret; ++} ++ + static bool kvm_no_adjvtime_get(Object *obj, Error **errp) + { + return !ARM_CPU(obj)->kvm_adjvtime; +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index 8e9b2039c4..50ae2be9c5 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -461,6 +461,8 @@ void kvm_arm_rme_init_gpa_space(hwaddr highest_gpa, PCIBus *pci_bus); + */ + Object *kvm_arm_rme_get_measurement_log(void); + ++int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap); ++ + #else + + /* +@@ -501,6 +503,11 @@ static inline Object *kvm_arm_rme_get_measurement_log(void) + return NULL; + } + ++static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap) ++{ ++ return -ENOSYS; ++} ++ + /* + * These functions should never actually be called without KVM support. + */ +-- +2.51.0.windows.1 + diff --git a/qemu.spec b/qemu.spec index 893b4097e33af3f0f0d14eb2533da2f23c25e420..441ac2bbd5f2c710a6f6ec2b97b64a102c14c812 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 8.2.0 -Release: 49 +Release: 50 Epoch: 11 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -1101,6 +1101,39 @@ Patch1084: hw-usb-hcd-xhci-Unmap-canceled-packet.patch Patch1085: meson-Use-has_header_symbol-to-check-getcpu.patch Patch1086: hw-intc-arm_gicv3_cpuif-Don-t-downgrade-monitor-trap.patch Patch1087: migration-fix-SEEK_CUR-offset-calculation-in-qio_cha.patch +Patch1088: Revert-hw-arm-virt-Introduce-a-IPIV-machine-option.patch +Patch1089: target-arm-add-ipiv-on-off-option.patch +Patch1090: arm-cpu-Add-sysreg-definitions-in-cpu-sysregs.h.patch +Patch1091: arm-cpu-Store-aa64isar0-aa64zfr0-into-the-idregs-arr.patch +Patch1092: arm-cpu-Store-aa64isar1-2-into-the-idregs-array.patch +Patch1093: arm-cpu-Store-aa64pfr0-1-into-the-idregs-array.patch +Patch1094: arm-cpu-Store-aa64mmfr0-2-into-the-idregs-array.patch +Patch1095: arm-cpu-Store-aa64dfr0-1-into-the-idregs-array.patch +Patch1096: arm-cpu-Store-aa64smfr0-into-the-idregs-array.patch +Patch1097: arm-cpu-Store-id_isar0-7-into-the-idregs-array.patch +Patch1098: arm-cpu-Store-id_pfr0-1-2-into-the-idregs-array.patch +Patch1099: arm-cpu-Store-id_dfr0-1-into-the-idregs-array.patch +Patch1100: arm-cpu-Store-id_mmfr0-5-into-the-idregs-array.patch +Patch1101: arm-cpu-Add-sysreg-generation-scripts.patch +Patch1102: arm-cpu-switch-to-a-generated-cpu-sysregs.h.inc.patch +Patch1103: arm-kvm-use-fd-instead-of-fdarray-2.patch +Patch1104: arm-cpu-Add-infra-to-handle-generated-ID-register-de.patch +Patch1105: arm-cpu-Add-sysreg-properties-generation.patch +Patch1106: arm-cpu-Add-generated-sysreg-properties.patch +Patch1107: kvm-kvm_get_writable_id_regs.patch +Patch1108: arm-cpu-accessors-for-writable-id-registers.patch +Patch1109: arm-kvm-Allow-reading-all-the-writable-ID-registers.patch +Patch1110: arm-kvm-write-back-modified-ID-regs-to-KVM.patch +Patch1111: arm-cpu-more-customization-for-the-kvm-host-cpu-mode.patch +Patch1112: arm-qmp-cmds-introspection-for-ID-register-props.patch +Patch1113: arm-cpu-features-document-ID-reg-properties.patch +Patch1114: arm-cpu-manually-make-MIDR-REVIDR-AIDR-writable.patch +Patch1115: arm-cpu-enable-MIDR-writable.patch +Patch1116: target-arm-kvm-Add-SMMC-hypercall-definitions.patch +Patch1117: hw-arm-virt-Initial-support-to-set-target_impl-CPUs.patch +Patch1118: target-arm-kvm-Use-PSCI_VERSIOn-for-version-info.patch +Patch1119: target-arm-kvm-Set-DISCOVER_IMPL_-hypercalls.patch +Patch1120: Fix-the-compilation-of-target-arm-softmmu.patch BuildRequires: flex BuildRequires: gcc @@ -1703,6 +1736,46 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Thu Oct 30 2025 Pengrui Zhang - 11:8.2.0-50 +- Revert "hw/arm/virt: Introduce a IPIV machine option" +- target/arm: add ipiv=on/off option +- arm/cpu: Add sysreg definitions in cpu-sysregs.h +- arm/cpu: Store aa64isar0/aa64zfr0 into the idregs arrays +- arm/cpu: Store aa64isar1/2 into the idregs array +- arm/cpu: Store aa64pfr0/1 into the idregs array +- arm/cpu: Store aa64mmfr0-2 into the idregs array +- arm/cpu: Store aa64dfr0/1 into the idregs array +- arm/cpu: Store aa64smfr0 into the idregs array +- arm/cpu: Store id_isar0-7 into the idregs array +- arm/cpu: Store id_pfr0/1/2 into the idregs array +- arm/cpu: Store id_dfr0/1 into the idregs array +- arm/cpu: Store id_mmfr0-5 into the idregs array +- arm/cpu: Add generated sysreg properties +- arm/cpu: Add sysreg properties generation +- arm/cpu: Add infra to handle generated ID register definitions +- kvm: kvm_get_writable_id_regs +- arm/kvm: use fd instead of fdarray[2] +- arm/cpu: switch to a generated cpu-sysregs.h.inc +- arm/cpu: Add sysreg generation scripts +- arm/cpu: Store aa64dfr0/1 into the idregs array +- arm/cpu: Store aa64mmfr0-2 into the idregs array +- arm/cpu: Store aa64pfr0/1 into the idregs array +- arm/cpu: Store aa64isar1/2 into the idregs array +- arm/cpu: Store aa64isar0/aa64zfr0 into the idregs arrays +- arm/cpu: Add sysreg definitions in cpu-sysregs.h +- arm/cpu: more customization for the kvm host cpu model +- arm/kvm: write back modified ID regs to KVM +- arm/kvm: Allow reading all the writable ID registers +- arm/cpu-features: document ID reg properties +- arm/qmp-cmds: introspection for ID register props +- arm/cpu: manually make MIDR/REVIDR/AIDR writable +- arm/cpu: enable MIDR writable +- target/arm/kvm: Add SMMC hypercall definitions +- hw/arm/virt: Initial support to set target_impl CPUs +- target/arm/kvm: Use PSCI_VERSION for version info +- target/arm/kvm: Set DISCOVER_IMPL_* hypercalls +- Fix the compilation of target arm-softmmu + * Fri Oct 24 2025 Pengrui Zhang - 11:8.2.0-49 - common-user/host/riscv: use tail pseudoinstruction for calling tail - meson: Remove CONFIG_STATX and CONFIG_STATX_MNT_ID diff --git a/target-arm-add-ipiv-on-off-option.patch b/target-arm-add-ipiv-on-off-option.patch new file mode 100644 index 0000000000000000000000000000000000000000..d69e4a3c3fc3879a0b0ae01f64197a9d355ad334 --- /dev/null +++ b/target-arm-add-ipiv-on-off-option.patch @@ -0,0 +1,78 @@ +From 4168f996acf21b0ecfe34d42756bed3be49e9853 Mon Sep 17 00:00:00 2001 +From: Jinqian Yang +Date: Mon, 20 Oct 2025 16:06:52 +0800 +Subject: [PATCH] target/arm: add ipiv=on/off option + +If IPIV is required to be enabled on the virtual machine, must add +`-accel kvm,ipiv=on`. Adding the IPIV switch in QEMU ensures that +the guest's IPIV can be flexibly disabled in certain scenarios, +such as cross-generation live migration. + +Signed-off-by: Jinqian Yang +--- + include/sysemu/kvm_int.h | 1 + + target/arm/kvm.c | 24 ++++++++++++++++++++++++ + 2 files changed, 25 insertions(+) + +diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h +index 9a7bc1a4b8..7b90117a86 100644 +--- a/include/sysemu/kvm_int.h ++++ b/include/sysemu/kvm_int.h +@@ -122,6 +122,7 @@ struct KVMState + uint32_t xen_caps; + uint16_t xen_gnttab_max_frames; + uint16_t xen_evtchn_max_pirq; ++ bool ipiv; + }; + + void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml, +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index f45783a9da..599c2c2462 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -263,6 +263,10 @@ static void kvm_update_ipiv_cap(KVMState *s) + { + int ret; + ++ if (!s->ipiv) { ++ return; ++ } ++ + if (!kvm_check_extension(s, KVM_CAP_ARM_HISI_IPIV)) { + return; + } +@@ -1364,6 +1368,20 @@ static void kvm_arch_set_eager_split_size(Object *obj, Visitor *v, + s->kvm_eager_split_size = value; + } + ++static bool virt_get_ipiv(Object *obj, Error **errp) ++{ ++ KVMState *s = KVM_STATE(obj); ++ ++ return s->ipiv; ++} ++ ++static void virt_set_ipiv(Object *obj, bool value, Error **errp) ++{ ++ KVMState *s = KVM_STATE(obj); ++ ++ s->ipiv = value; ++} ++ + void kvm_arch_accel_class_init(ObjectClass *oc) + { + object_class_property_add(oc, "eager-split-size", "size", +@@ -1372,4 +1390,10 @@ void kvm_arch_accel_class_init(ObjectClass *oc) + + object_class_property_set_description(oc, "eager-split-size", + "Eager Page Split chunk size for hugepages. (default: 0, disabled)"); ++ ++ object_class_property_add_bool(oc, "ipiv", ++ virt_get_ipiv, ++ virt_set_ipiv); ++ object_class_property_set_description(oc, "ipiv", ++ "Set on/off to enable/disable IPIV"); + } +-- +2.33.0 + diff --git a/target-arm-kvm-Add-SMMC-hypercall-definitions.patch b/target-arm-kvm-Add-SMMC-hypercall-definitions.patch new file mode 100644 index 0000000000000000000000000000000000000000..521a54af3292f1d991a5ced9a255ca5bbc949c95 --- /dev/null +++ b/target-arm-kvm-Add-SMMC-hypercall-definitions.patch @@ -0,0 +1,73 @@ +From f61060d0f0b00ac94da535b72f4f62cfc5808fb6 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 1/4] target/arm/kvm: Add SMMC hypercall definitions + +ToDo: Do it properly using update-linux-headers.sh + +Signed-off-by: Shameer Kolothum +--- + target/arm/kvm.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) + +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 1b5bd85e77..52fb1b0919 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -37,6 +37,53 @@ + #include "qapi/visitor.h" + #include "qemu/log.h" + ++/* ++ * SMMCC KVM Vendor hypercall definitions. ++ * ToDo: Include using update-linux-headers.sh ++ */ ++#define ARM_SMCCC_FAST_CALL _AC(1,U) ++#define ARM_SMCCC_TYPE_SHIFT 31 ++ ++#define ARM_SMCCC_SMC_32 0 ++#define ARM_SMCCC_SMC_64 1 ++#define ARM_SMCCC_CALL_CONV_SHIFT 30 ++ ++#define ARM_SMCCC_OWNER_MASK 0x3F ++#define ARM_SMCCC_OWNER_SHIFT 24 ++ ++#define ARM_SMCCC_FUNC_MASK 0xFFFF ++ ++#define ARM_SMCCC_OWNER_VENDOR_HYP 6 ++ ++ ++#define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER 64 ++#define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS 65 ++ ++#define ARM_SMCCC_KVM_DISCOVER_IMPL_VER_1_0 0x10000 ++ ++#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \ ++ (((type) << ARM_SMCCC_TYPE_SHIFT) | \ ++ ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \ ++ (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \ ++ ((func_num) & ARM_SMCCC_FUNC_MASK)) ++ ++#define ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ++ ARM_SMCCC_SMC_64, \ ++ ARM_SMCCC_OWNER_VENDOR_HYP, \ ++ ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER) ++ ++#define ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ++ ARM_SMCCC_SMC_64, \ ++ ARM_SMCCC_OWNER_VENDOR_HYP, \ ++ ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS) ++ ++#define SMCCC_RET_SUCCESS 0 ++#define SMCCC_RET_NOT_SUPPORTED -1 ++#define SMCCC_RET_NOT_REQUIRED -2 ++#define SMCCC_RET_INVALID_PARAMETER -3 ++ + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO + }; +-- +2.51.0.windows.1 + diff --git a/target-arm-kvm-Set-DISCOVER_IMPL_-hypercalls.patch b/target-arm-kvm-Set-DISCOVER_IMPL_-hypercalls.patch new file mode 100644 index 0000000000000000000000000000000000000000..2959f373b94af420e5d061fb52fd873ff24eb691 --- /dev/null +++ b/target-arm-kvm-Set-DISCOVER_IMPL_-hypercalls.patch @@ -0,0 +1,40 @@ +From 6daafff5667ac443411ad948343cc83fe15b3741 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 4/4] target/arm/kvm: Set DISCOVER_IMPL_* hypercalls + +Signed-off-by: Shameer Kolothum +--- + target/arm/kvm64.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 7e0ca919b2..7614194998 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -795,6 +795,14 @@ static int kvm_arm_sve_set_vls(CPUState *cs) + return kvm_set_one_reg(cs, KVM_REG_ARM64_SVE_VLS, &vls[0]); + } + ++static int kvm_arm_set_vend_hyp_bmap_2(ARMCPU *cpu) ++{ ++ /* Set DISCOVER_IMPL_* hypercalls */ ++ uint64_t bmap_2 = MAKE_64BIT_MASK(0, 2); ++ ++ return kvm_set_one_reg(CPU(cpu), KVM_REG_ARM_VENDOR_HYP_BMAP_2, &bmap_2); ++} ++ + #define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5 + + int kvm_arch_init_vcpu(CPUState *cs) +@@ -871,6 +879,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + } + } + ++ kvm_arm_set_vend_hyp_bmap_2(cpu); + /* + * KVM reports the exact PSCI version it is implementing via a + * special sysreg. If it is present, use its contents to determine +-- +2.51.0.windows.1 + diff --git a/target-arm-kvm-Use-PSCI_VERSIOn-for-version-info.patch b/target-arm-kvm-Use-PSCI_VERSIOn-for-version-info.patch new file mode 100644 index 0000000000000000000000000000000000000000..fd8d7d6d36ffbf4327c598b62465d3ff041357d5 --- /dev/null +++ b/target-arm-kvm-Use-PSCI_VERSIOn-for-version-info.patch @@ -0,0 +1,35 @@ +From b79e70a8a53b13ba9eeb049cedd55ff0a8eeacce Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Thu, 4 Sep 2025 16:28:48 +0800 +Subject: [PATCH 3/4] target/arm/kvm: Use PSCI_VERSIOn for version info + +Signed-off-by: Shameer Kolothum +--- + target/arm/kvm.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 3ecb1f339a..50f22717ec 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -59,8 +59,6 @@ + #define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER 64 + #define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS 65 + +-#define ARM_SMCCC_KVM_DISCOVER_IMPL_VER_1_0 0x100000000 +- + #define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \ + (((type) << ARM_SMCCC_TYPE_SHIFT) | \ + ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \ +@@ -1215,7 +1213,7 @@ static bool arm_handle_smcc_kvm_vendor_hypercall(ARMCPU *cpu) + break; + } + env->xregs[0] = SMCCC_RET_SUCCESS; +- env->xregs[1] = ARM_SMCCC_KVM_DISCOVER_IMPL_VER_1_0; ++ env->xregs[1] = PSCI_VERSION(1, 0); + env->xregs[2] = ms->target_ipml_cpu_num; + break; + case ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID: +-- +2.51.0.windows.1 +