All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/9] Support disable/enable CPU features for AArch64
@ 2020-08-13 10:26 Peng Liang
  2020-08-13 10:26 ` [RFC 1/9] target/arm: convert isar regs to array Peng Liang
                   ` (12 more replies)
  0 siblings, 13 replies; 28+ messages in thread
From: Peng Liang @ 2020-08-13 10:26 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, Peng Liang, pbonzini

QEMU does not support disable/enable CPU features in AArch64 for now.
This patch series add support for CPU features in AArch64.

Firstly, we change the isar struct in ARMCPU to an array for
convenience.  Secondly, we add support to configure CPU feautres in
AArch64 and make sure that the ID registers can be synchronized to KVM
so that guest can read the value we configure.  Thirdly, we add a
mechanism to solve the dependency relationship of some CPU features.
Last, we add a KVM_CAP_ARM_CPU_FEATURE to check whether KVM supports to
set CPU features in AArch64.

Also export CPU features to the result of qmp query-cpu-model-expansion
so that libvirt can get the supported CPU features.

Update the ID fields to ARMv8.6 and add some CPU features according to
the new ID fields.

With related KVM patch set[1], we can disable/enable CPU features in
AArch64.

[1] https://patchwork.kernel.org/cover/11711693/

Peng Liang (9):
  target/arm: convert isar regs to array
  target/arm: parse cpu feature related options
  target/arm: register CPU features for property
  target/arm: Allow ID registers to synchronize to KVM
  target/arm: introduce CPU feature dependency mechanism
  target/arm: introduce KVM_CAP_ARM_CPU_FEATURE
  target/arm: Add CPU features to query-cpu-model-expansion
  target/arm: Update ID fields
  target/arm: Add more CPU features

 hw/intc/armv7m_nvic.c     |  48 +--
 linux-headers/linux/kvm.h |   1 +
 target/arm/cpu.c          | 753 ++++++++++++++++++++++++++++++++------
 target/arm/cpu.h          | 245 +++++++------
 target/arm/cpu64.c        | 271 +++++++++-----
 target/arm/cpu_tcg.c      | 250 ++++++-------
 target/arm/helper.c       |  85 +++--
 target/arm/internals.h    |  15 +-
 target/arm/kvm.c          |  38 ++
 target/arm/kvm64.c        |  86 +++--
 target/arm/kvm_arm.h      |  10 +
 target/arm/monitor.c      |   2 +
 12 files changed, 1267 insertions(+), 537 deletions(-)

-- 
2.18.4



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

* [RFC 1/9] target/arm: convert isar regs to array
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
@ 2020-08-13 10:26 ` Peng Liang
  2020-08-13 10:42   ` Philippe Mathieu-Daudé
  2020-08-13 10:26 ` [RFC 2/9] target/arm: parse cpu feature related options Peng Liang
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Peng Liang @ 2020-08-13 10:26 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, Peng Liang, pbonzini

The isar in ARMCPU is a struct, each field of which represents an ID
register.  It's not convenient for us to support CPU feature in AArch64.
So let's change it to an array first and add an enum as the index of the
array for convenience.  Since we will never access high 32-bits of ID
registers in AArch32, it's harmless to change the ID registers in
AArch32 to 64-bits.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 hw/intc/armv7m_nvic.c  |  48 ++++----
 target/arm/cpu.c       | 232 +++++++++++++++++++-------------------
 target/arm/cpu.h       | 226 +++++++++++++++++++------------------
 target/arm/cpu64.c     | 170 ++++++++++++++--------------
 target/arm/cpu_tcg.c   | 250 +++++++++++++++++++++--------------------
 target/arm/helper.c    |  54 ++++-----
 target/arm/internals.h |  15 +--
 target/arm/kvm64.c     |  72 ++++++------
 8 files changed, 541 insertions(+), 526 deletions(-)

diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 277a98b87b..ca81a3cbef 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -1242,29 +1242,29 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
     case 0xd44: /* PFR1.  */
         return cpu->id_pfr1;
     case 0xd48: /* DFR0.  */
-        return cpu->isar.id_dfr0;
+        return cpu->isar.regs[ID_DFR0];
     case 0xd4c: /* AFR0.  */
         return cpu->id_afr0;
-    case 0xd50: /* MMFR0.  */
-        return cpu->isar.id_mmfr0;
-    case 0xd54: /* MMFR1.  */
-        return cpu->isar.id_mmfr1;
-    case 0xd58: /* MMFR2.  */
-        return cpu->isar.id_mmfr2;
-    case 0xd5c: /* MMFR3.  */
-        return cpu->isar.id_mmfr3;
-    case 0xd60: /* ISAR0.  */
-        return cpu->isar.id_isar0;
-    case 0xd64: /* ISAR1.  */
-        return cpu->isar.id_isar1;
-    case 0xd68: /* ISAR2.  */
-        return cpu->isar.id_isar2;
-    case 0xd6c: /* ISAR3.  */
-        return cpu->isar.id_isar3;
-    case 0xd70: /* ISAR4.  */
-        return cpu->isar.id_isar4;
-    case 0xd74: /* ISAR5.  */
-        return cpu->isar.id_isar5;
+    case 0xd50: /* MMFR0. */
+        return cpu->isar.regs[ID_MMFR0];
+    case 0xd54: /* MMFR1. */
+        return cpu->isar.regs[ID_MMFR1];
+    case 0xd58: /* MMFR2. */
+        return cpu->isar.regs[ID_MMFR2];
+    case 0xd5c: /* MMFR3. */
+        return cpu->isar.regs[ID_MMFR3];
+    case 0xd60: /* ISAR0. */
+        return cpu->isar.regs[ID_ISAR0];
+    case 0xd64: /* ISAR1. */
+        return cpu->isar.regs[ID_ISAR1];
+    case 0xd68: /* ISAR2. */
+        return cpu->isar.regs[ID_ISAR2];
+    case 0xd6c: /* ISAR3. */
+        return cpu->isar.regs[ID_ISAR3];
+    case 0xd70: /* ISAR4. */
+        return cpu->isar.regs[ID_ISAR4];
+    case 0xd74: /* ISAR5. */
+        return cpu->isar.regs[ID_ISAR5];
     case 0xd78: /* CLIDR */
         return cpu->clidr;
     case 0xd7c: /* CTR */
@@ -1469,11 +1469,11 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
         }
         return cpu->env.v7m.fpdscr[attrs.secure];
     case 0xf40: /* MVFR0 */
-        return cpu->isar.mvfr0;
+        return cpu->isar.regs[MVFR0];
     case 0xf44: /* MVFR1 */
-        return cpu->isar.mvfr1;
+        return cpu->isar.regs[MVFR1];
     case 0xf48: /* MVFR2 */
-        return cpu->isar.mvfr2;
+        return cpu->isar.regs[MVFR2];
     default:
     bad_offset:
         qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 111579554f..79d7a6b45c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -170,9 +170,9 @@ static void arm_cpu_reset(DeviceState *dev)
     g_hash_table_foreach(cpu->cp_regs, cp_reg_check_reset, cpu);
 
     env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
-    env->vfp.xregs[ARM_VFP_MVFR0] = cpu->isar.mvfr0;
-    env->vfp.xregs[ARM_VFP_MVFR1] = cpu->isar.mvfr1;
-    env->vfp.xregs[ARM_VFP_MVFR2] = cpu->isar.mvfr2;
+    env->vfp.xregs[ARM_VFP_MVFR0] = cpu->isar.regs[MVFR0];
+    env->vfp.xregs[ARM_VFP_MVFR1] = cpu->isar.regs[MVFR1];
+    env->vfp.xregs[ARM_VFP_MVFR2] = cpu->isar.regs[MVFR2];
 
     cpu->power_state = cpu->start_powered_off ? PSCI_OFF : PSCI_ON;
     s->halted = cpu->start_powered_off;
@@ -1404,19 +1404,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         uint64_t t;
         uint32_t u;
 
-        t = cpu->isar.id_aa64isar1;
+        t = cpu->isar.regs[ID_AA64ISAR1];
         t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 0);
-        cpu->isar.id_aa64isar1 = t;
+        cpu->isar.regs[ID_AA64ISAR1] = t;
 
-        t = cpu->isar.id_aa64pfr0;
+        t = cpu->isar.regs[ID_AA64PFR0];
         t = FIELD_DP64(t, ID_AA64PFR0, FP, 0xf);
-        cpu->isar.id_aa64pfr0 = t;
+        cpu->isar.regs[ID_AA64PFR0] = t;
 
-        u = cpu->isar.id_isar6;
+        u = cpu->isar.regs[ID_ISAR6];
         u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0);
-        cpu->isar.id_isar6 = u;
+        cpu->isar.regs[ID_ISAR6] = u;
 
-        u = cpu->isar.mvfr0;
+        u = cpu->isar.regs[MVFR0];
         u = FIELD_DP32(u, MVFR0, FPSP, 0);
         u = FIELD_DP32(u, MVFR0, FPDP, 0);
         u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
@@ -1424,17 +1424,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         u = FIELD_DP32(u, MVFR0, FPSQRT, 0);
         u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
         u = FIELD_DP32(u, MVFR0, FPROUND, 0);
-        cpu->isar.mvfr0 = u;
+        cpu->isar.regs[MVFR0] = u;
 
-        u = cpu->isar.mvfr1;
+        u = cpu->isar.regs[MVFR1];
         u = FIELD_DP32(u, MVFR1, FPFTZ, 0);
         u = FIELD_DP32(u, MVFR1, FPDNAN, 0);
         u = FIELD_DP32(u, MVFR1, FPHP, 0);
-        cpu->isar.mvfr1 = u;
+        cpu->isar.regs[MVFR1] = u;
 
-        u = cpu->isar.mvfr2;
+        u = cpu->isar.regs[MVFR2];
         u = FIELD_DP32(u, MVFR2, FPMISC, 0);
-        cpu->isar.mvfr2 = u;
+        cpu->isar.regs[MVFR2] = u;
     }
 
     if (!cpu->has_neon) {
@@ -1443,60 +1443,60 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
 
         unset_feature(env, ARM_FEATURE_NEON);
 
-        t = cpu->isar.id_aa64isar0;
+        t = cpu->isar.regs[ID_AA64ISAR0];
         t = FIELD_DP64(t, ID_AA64ISAR0, DP, 0);
-        cpu->isar.id_aa64isar0 = t;
+        cpu->isar.regs[ID_AA64ISAR0] = t;
 
-        t = cpu->isar.id_aa64isar1;
+        t = cpu->isar.regs[ID_AA64ISAR1];
         t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0);
-        cpu->isar.id_aa64isar1 = t;
+        cpu->isar.regs[ID_AA64ISAR1] = t;
 
-        t = cpu->isar.id_aa64pfr0;
+        t = cpu->isar.regs[ID_AA64PFR0];
         t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 0xf);
-        cpu->isar.id_aa64pfr0 = t;
+        cpu->isar.regs[ID_AA64PFR0] = t;
 
-        u = cpu->isar.id_isar5;
+        u = cpu->isar.regs[ID_ISAR5];
         u = FIELD_DP32(u, ID_ISAR5, RDM, 0);
         u = FIELD_DP32(u, ID_ISAR5, VCMA, 0);
-        cpu->isar.id_isar5 = u;
+        cpu->isar.regs[ID_ISAR5] = u;
 
-        u = cpu->isar.id_isar6;
+        u = cpu->isar.regs[ID_ISAR6];
         u = FIELD_DP32(u, ID_ISAR6, DP, 0);
         u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
-        cpu->isar.id_isar6 = u;
+        cpu->isar.regs[ID_ISAR6] = u;
 
-        u = cpu->isar.mvfr1;
+        u = cpu->isar.regs[MVFR1];
         u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
         u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
         u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
         u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
-        cpu->isar.mvfr1 = u;
+        cpu->isar.regs[MVFR1] = u;
 
-        u = cpu->isar.mvfr2;
+        u = cpu->isar.regs[MVFR2];
         u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
-        cpu->isar.mvfr2 = u;
+        cpu->isar.regs[MVFR2] = u;
     }
 
     if (!cpu->has_neon && !cpu->has_vfp) {
         uint64_t t;
         uint32_t u;
 
-        t = cpu->isar.id_aa64isar0;
+        t = cpu->isar.regs[ID_AA64ISAR0];
         t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 0);
-        cpu->isar.id_aa64isar0 = t;
+        cpu->isar.regs[ID_AA64ISAR0] = t;
 
-        t = cpu->isar.id_aa64isar1;
+        t = cpu->isar.regs[ID_AA64ISAR1];
         t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 0);
-        cpu->isar.id_aa64isar1 = t;
+        cpu->isar.regs[ID_AA64ISAR1] = t;
 
-        u = cpu->isar.mvfr0;
+        u = cpu->isar.regs[MVFR0];
         u = FIELD_DP32(u, MVFR0, SIMDREG, 0);
-        cpu->isar.mvfr0 = u;
+        cpu->isar.regs[MVFR0] = u;
 
         /* Despite the name, this field covers both VFP and Neon */
-        u = cpu->isar.mvfr1;
+        u = cpu->isar.regs[MVFR1];
         u = FIELD_DP32(u, MVFR1, SIMDFMAC, 0);
-        cpu->isar.mvfr1 = u;
+        cpu->isar.regs[MVFR1] = u;
     }
 
     if (arm_feature(env, ARM_FEATURE_M) && !cpu->has_dsp) {
@@ -1504,19 +1504,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
 
         unset_feature(env, ARM_FEATURE_THUMB_DSP);
 
-        u = cpu->isar.id_isar1;
+        u = cpu->isar.regs[ID_ISAR1];
         u = FIELD_DP32(u, ID_ISAR1, EXTEND, 1);
-        cpu->isar.id_isar1 = u;
+        cpu->isar.regs[ID_ISAR1] = u;
 
-        u = cpu->isar.id_isar2;
+        u = cpu->isar.regs[ID_ISAR2];
         u = FIELD_DP32(u, ID_ISAR2, MULTU, 1);
         u = FIELD_DP32(u, ID_ISAR2, MULTS, 1);
-        cpu->isar.id_isar2 = u;
+        cpu->isar.regs[ID_ISAR2] = u;
 
-        u = cpu->isar.id_isar3;
+        u = cpu->isar.regs[ID_ISAR3];
         u = FIELD_DP32(u, ID_ISAR3, SIMD, 1);
         u = FIELD_DP32(u, ID_ISAR3, SATURATE, 0);
-        cpu->isar.id_isar3 = u;
+        cpu->isar.regs[ID_ISAR3] = u;
     }
 
     /* Some features automatically imply others: */
@@ -1659,7 +1659,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
          * registers as well. These are id_pfr1[7:4] and id_aa64pfr0[15:12].
          */
         cpu->id_pfr1 &= ~0xf0;
-        cpu->isar.id_aa64pfr0 &= ~0xf000;
+        cpu->isar.regs[ID_AA64PFR0] &= ~0xf000;
     }
 
     if (!cpu->has_el2) {
@@ -1682,9 +1682,10 @@ 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);
-        cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0);
+        cpu->isar.regs[ID_AA64DFR0] =
+            FIELD_DP64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER, 0);
+        cpu->isar.regs[ID_DFR0] = FIELD_DP32(cpu->isar.regs[ID_DFR0], ID_DFR0,
+                                             PERFMON, 0);
         cpu->pmceid0 = 0;
         cpu->pmceid1 = 0;
     }
@@ -1694,7 +1695,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
          * registers if we don't have EL2. These are id_pfr1[15:12] and
          * id_aa64pfr0_el1[11:8].
          */
-        cpu->isar.id_aa64pfr0 &= ~0xf00;
+        cpu->isar.regs[ID_AA64PFR0] &= ~0xf00;
         cpu->id_pfr1 &= ~0xf000;
     }
 
@@ -1704,8 +1705,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
          * Disable the MTE feature bits if we do not have tag-memory
          * provided by the machine.
          */
-        cpu->isar.id_aa64pfr1 =
-            FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0);
+        cpu->isar.regs[ID_AA64PFR1] =
+            FIELD_DP64(cpu->isar.regs[ID_AA64PFR1], ID_AA64PFR1, MTE, 0);
     }
 #endif
 
@@ -1889,24 +1890,24 @@ static void cortex_a8_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_EL3);
     cpu->midr = 0x410fc080;
     cpu->reset_fpsid = 0x410330c0;
-    cpu->isar.mvfr0 = 0x11110222;
-    cpu->isar.mvfr1 = 0x00011111;
+    cpu->isar.regs[MVFR0] = 0x11110222;
+    cpu->isar.regs[MVFR1] = 0x00011111;
     cpu->ctr = 0x82048004;
     cpu->reset_sctlr = 0x00c50078;
     cpu->id_pfr0 = 0x1031;
     cpu->id_pfr1 = 0x11;
-    cpu->isar.id_dfr0 = 0x400;
+    cpu->isar.regs[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;
-    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;
-    cpu->isar.dbgdidr = 0x15141000;
+    cpu->isar.regs[ID_MMFR0] = 0x31100003;
+    cpu->isar.regs[ID_MMFR1] = 0x20000000;
+    cpu->isar.regs[ID_MMFR2] = 0x01202000;
+    cpu->isar.regs[ID_MMFR3] = 0x11;
+    cpu->isar.regs[ID_ISAR0] = 0x00101111;
+    cpu->isar.regs[ID_ISAR1] = 0x12112111;
+    cpu->isar.regs[ID_ISAR2] = 0x21232031;
+    cpu->isar.regs[ID_ISAR3] = 0x11112131;
+    cpu->isar.regs[ID_ISAR4] = 0x00111142;
+    cpu->isar.regs[DBGDIDR] = 0x15141000;
     cpu->clidr = (1 << 27) | (2 << 24) | 3;
     cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
     cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
@@ -1961,24 +1962,24 @@ static void cortex_a9_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_CBAR);
     cpu->midr = 0x410fc090;
     cpu->reset_fpsid = 0x41033090;
-    cpu->isar.mvfr0 = 0x11110222;
-    cpu->isar.mvfr1 = 0x01111111;
+    cpu->isar.regs[MVFR0] = 0x11110222;
+    cpu->isar.regs[MVFR1] = 0x01111111;
     cpu->ctr = 0x80038003;
     cpu->reset_sctlr = 0x00c50078;
     cpu->id_pfr0 = 0x1031;
     cpu->id_pfr1 = 0x11;
-    cpu->isar.id_dfr0 = 0x000;
+    cpu->isar.regs[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;
-    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;
-    cpu->isar.dbgdidr = 0x35141000;
+    cpu->isar.regs[ID_MMFR0] = 0x00100103;
+    cpu->isar.regs[ID_MMFR1] = 0x20000000;
+    cpu->isar.regs[ID_MMFR2] = 0x01230000;
+    cpu->isar.regs[ID_MMFR3] = 0x00002111;
+    cpu->isar.regs[ID_ISAR0] = 0x00101111;
+    cpu->isar.regs[ID_ISAR1] = 0x13112111;
+    cpu->isar.regs[ID_ISAR2] = 0x21232041;
+    cpu->isar.regs[ID_ISAR3] = 0x11112131;
+    cpu->isar.regs[ID_ISAR4] = 0x00111142;
+    cpu->isar.regs[DBGDIDR] = 0x35141000;
     cpu->clidr = (1 << 27) | (1 << 24) | 3;
     cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
     cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
@@ -2025,27 +2026,27 @@ static void cortex_a7_initfn(Object *obj)
     cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
     cpu->midr = 0x410fc075;
     cpu->reset_fpsid = 0x41023075;
-    cpu->isar.mvfr0 = 0x10110222;
-    cpu->isar.mvfr1 = 0x11111111;
+    cpu->isar.regs[MVFR0] = 0x10110222;
+    cpu->isar.regs[MVFR1] = 0x11111111;
     cpu->ctr = 0x84448003;
     cpu->reset_sctlr = 0x00c50078;
     cpu->id_pfr0 = 0x00001131;
     cpu->id_pfr1 = 0x00011011;
-    cpu->isar.id_dfr0 = 0x02010555;
+    cpu->isar.regs[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;
+    cpu->isar.regs[ID_MMFR0] = 0x10101105;
+    cpu->isar.regs[ID_MMFR1] = 0x40000000;
+    cpu->isar.regs[ID_MMFR2] = 0x01240000;
+    cpu->isar.regs[ID_MMFR3] = 0x02102211;
     /* 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;
-    cpu->isar.dbgdidr = 0x3515f005;
+    cpu->isar.regs[ID_ISAR0] = 0x02101110;
+    cpu->isar.regs[ID_ISAR1] = 0x13112111;
+    cpu->isar.regs[ID_ISAR2] = 0x21232041;
+    cpu->isar.regs[ID_ISAR3] = 0x11112131;
+    cpu->isar.regs[ID_ISAR4] = 0x10011142;
+    cpu->isar.regs[DBGDIDR] = 0x3515f005;
     cpu->clidr = 0x0a200023;
     cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
     cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
@@ -2070,24 +2071,24 @@ static void cortex_a15_initfn(Object *obj)
     cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
     cpu->midr = 0x412fc0f1;
     cpu->reset_fpsid = 0x410430f0;
-    cpu->isar.mvfr0 = 0x10110222;
-    cpu->isar.mvfr1 = 0x11111111;
+    cpu->isar.regs[MVFR0] = 0x10110222;
+    cpu->isar.regs[MVFR1] = 0x11111111;
     cpu->ctr = 0x8444c004;
     cpu->reset_sctlr = 0x00c50078;
     cpu->id_pfr0 = 0x00001131;
     cpu->id_pfr1 = 0x00011011;
-    cpu->isar.id_dfr0 = 0x02010555;
+    cpu->isar.regs[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;
-    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;
-    cpu->isar.dbgdidr = 0x3515f021;
+    cpu->isar.regs[ID_MMFR0] = 0x10201105;
+    cpu->isar.regs[ID_MMFR1] = 0x20000000;
+    cpu->isar.regs[ID_MMFR2] = 0x01240000;
+    cpu->isar.regs[ID_MMFR3] = 0x02102211;
+    cpu->isar.regs[ID_ISAR0] = 0x02101110;
+    cpu->isar.regs[ID_ISAR1] = 0x13112111;
+    cpu->isar.regs[ID_ISAR2] = 0x21232041;
+    cpu->isar.regs[ID_ISAR3] = 0x11112131;
+    cpu->isar.regs[ID_ISAR4] = 0x10011142;
+    cpu->isar.regs[DBGDIDR] = 0x3515f021;
     cpu->clidr = 0x0a200023;
     cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
     cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
@@ -2111,7 +2112,8 @@ static void arm_max_initfn(Object *obj)
         cortex_a15_initfn(obj);
 
         /* old-style VFP short-vector support */
-        cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
+        cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0,
+                                           FPSHVEC, 1);
 
 #ifdef CONFIG_USER_ONLY
         /* We don't set these in system emulation mode for the moment,
@@ -2122,42 +2124,42 @@ static void arm_max_initfn(Object *obj)
         {
             uint32_t t;
 
-            t = cpu->isar.id_isar5;
+            t = cpu->isar.regs[ID_ISAR5];
             t = FIELD_DP32(t, ID_ISAR5, AES, 2);
             t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
             t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
             t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
             t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
             t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
-            cpu->isar.id_isar5 = t;
+            cpu->isar.regs[ID_ISAR5] = t;
 
-            t = cpu->isar.id_isar6;
+            t = cpu->isar.regs[ID_ISAR6];
             t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
             t = FIELD_DP32(t, ID_ISAR6, DP, 1);
             t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
             t = FIELD_DP32(t, ID_ISAR6, SB, 1);
             t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
-            cpu->isar.id_isar6 = t;
+            cpu->isar.regs[ID_ISAR6] = t;
 
-            t = cpu->isar.mvfr1;
+            t = cpu->isar.regs[MVFR1];
             t = FIELD_DP32(t, MVFR1, FPHP, 2);     /* v8.0 FP support */
-            cpu->isar.mvfr1 = t;
+            cpu->isar.regs[MVFR1] = t;
 
-            t = cpu->isar.mvfr2;
+            t = cpu->isar.regs[MVFR2];
             t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
             t = FIELD_DP32(t, MVFR2, FPMISC, 4);   /* FP MaxNum */
-            cpu->isar.mvfr2 = t;
+            cpu->isar.regs[MVFR2] = t;
 
-            t = cpu->isar.id_mmfr3;
+            t = cpu->isar.regs[ID_MMFR3];
             t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
-            cpu->isar.id_mmfr3 = t;
+            cpu->isar.regs[ID_MMFR3] = t;
 
-            t = cpu->isar.id_mmfr4;
+            t = cpu->isar.regs[ID_MMFR4];
             t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
             t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
             t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
             t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
-            cpu->isar.id_mmfr4 = t;
+            cpu->isar.regs[ID_MMFR4] = t;
         }
 #endif
     }
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 9e8ed423ea..5d8074d03b 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -67,6 +67,37 @@
 #define ARMV7M_EXCP_PENDSV  14
 #define ARMV7M_EXCP_SYSTICK 15
 
+typedef enum CPUIDReg {
+    MIDR_EL1,
+    ID_ISAR0,
+    ID_ISAR1,
+    ID_ISAR2,
+    ID_ISAR3,
+    ID_ISAR4,
+    ID_ISAR5,
+    ID_ISAR6,
+    ID_MMFR0,
+    ID_MMFR1,
+    ID_MMFR2,
+    ID_MMFR3,
+    ID_MMFR4,
+    ID_AA64ISAR0,
+    ID_AA64ISAR1,
+    ID_AA64PFR0,
+    ID_AA64PFR1,
+    ID_AA64MMFR0,
+    ID_AA64MMFR1,
+    ID_AA64MMFR2,
+    ID_AA64DFR0,
+    ID_AA64DFR1,
+    ID_DFR0,
+    MVFR0,
+    MVFR1,
+    MVFR2,
+    DBGDIDR,
+    ID_MAX,
+} CPUIDReg;
+
 /* For M profile, some registers are banked secure vs non-secure;
  * these are represented as a 2-element array where the first element
  * is the non-secure copy and the second is the secure copy.
@@ -890,32 +921,7 @@ struct ARMCPU {
      * 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;
-        uint32_t id_mmfr3;
-        uint32_t id_mmfr4;
-        uint32_t mvfr0;
-        uint32_t mvfr1;
-        uint32_t mvfr2;
-        uint32_t id_dfr0;
-        uint32_t dbgdidr;
-        uint64_t id_aa64isar0;
-        uint64_t id_aa64isar1;
-        uint64_t id_aa64pfr0;
-        uint64_t id_aa64pfr1;
-        uint64_t id_aa64mmfr0;
-        uint64_t id_aa64mmfr1;
-        uint64_t id_aa64mmfr2;
-        uint64_t id_aa64dfr0;
-        uint64_t id_aa64dfr1;
+        uint64_t regs[ID_MAX];
     } isar;
     uint64_t midr;
     uint32_t revidr;
@@ -3438,77 +3444,77 @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
  */
 static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0;
+    return FIELD_EX32(id->regs[ID_ISAR0], 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(id->regs[ID_ISAR0], ID_ISAR0, DIVIDE) > 1;
 }
 
 static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0;
+    return FIELD_EX32(id->regs[ID_ISAR1], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR5], 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(id->regs[ID_ISAR6], 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(id->regs[ID_ISAR6], 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(id->regs[ID_ISAR6], 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(id->regs[ID_ISAR6], 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(id->regs[ID_ISAR6], ID_ISAR6, SPECRES) != 0;
 }
 
 static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
@@ -3518,7 +3524,7 @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
      * the ARMv8.2-FP16 extension is implemented for aa32 mode.
      * At which point we can properly set and check MVFR1.FPHP.
      */
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
+    return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, FP) == 1;
 }
 
 static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id)
@@ -3527,42 +3533,42 @@ static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id)
      * Return true if either VFP or SIMD is implemented.
      * In this case, a minimum of VFP w/ D0-D15.
      */
-    return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0;
+    return FIELD_EX32(id->regs[MVFR0], MVFR0, SIMDREG) > 0;
 }
 
 static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id)
 {
     /* Return true if D16-D31 are implemented */
-    return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) >= 2;
+    return FIELD_EX32(id->regs[MVFR0], MVFR0, SIMDREG) >= 2;
 }
 
 static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0;
+    return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSHVEC) > 0;
 }
 
 static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id)
 {
     /* Return true if CPU supports single precision floating point, VFPv2 */
-    return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0;
+    return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSP) > 0;
 }
 
 static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id)
 {
     /* Return true if CPU supports single precision floating point, VFPv3 */
-    return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2;
+    return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSP) >= 2;
 }
 
 static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id)
 {
     /* Return true if CPU supports double precision floating point, VFPv2 */
-    return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0;
+    return FIELD_EX32(id->regs[MVFR0], MVFR0, FPDP) > 0;
 }
 
 static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id)
 {
     /* Return true if CPU supports double precision floating point, VFPv3 */
-    return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2;
+    return FIELD_EX32(id->regs[MVFR0], MVFR0, FPDP) >= 2;
 }
 
 static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id)
@@ -3577,12 +3583,12 @@ static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id)
  */
 static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 0;
+    return FIELD_EX32(id->regs[MVFR1], MVFR1, FPHP) > 0;
 }
 
 static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1;
+    return FIELD_EX32(id->regs[MVFR1], MVFR1, FPHP) > 1;
 }
 
 /*
@@ -3594,71 +3600,71 @@ static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id)
  */
 static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0;
+    return FIELD_EX32(id->regs[MVFR1], MVFR1, SIMDFMAC) != 0;
 }
 
 static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1;
+    return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 1;
 }
 
 static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 2;
+    return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 2;
 }
 
 static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 3;
+    return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 3;
 }
 
 static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4;
+    return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 4;
 }
 
 static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0;
+    return FIELD_EX32(id->regs[ID_MMFR3], 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(id->regs[ID_MMFR3], ID_MMFR3, PAN) >= 2;
 }
 
 static inline bool isar_feature_aa32_pmu_8_1(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(id->regs[ID_DFR0], ID_DFR0, PERFMON) >= 4 &&
+        FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) != 0xf;
 }
 
 static inline bool isar_feature_aa32_pmu_8_4(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(id->regs[ID_DFR0], ID_DFR0, PERFMON) >= 5 &&
+        FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) != 0xf;
 }
 
 static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id)
 {
-    return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0;
+    return FIELD_EX32(id->regs[ID_MMFR4], 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(id->regs[ID_MMFR4], 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(id->regs[ID_MMFR4], 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(id->regs[ID_MMFR4], ID_MMFR4, XNX) != 0;
 }
 
 /*
@@ -3666,92 +3672,92 @@ static inline bool isar_feature_aa32_tts2uxn(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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], 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(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, RNDR) != 0;
 }
 
 static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
+    return FIELD_EX64(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, FCMA) != 0;
 }
 
 static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id)
@@ -3762,7 +3768,7 @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id)
      * defined algorithms, and thus API+GPI, and this predicate controls
      * migration of the 128-bit keys.
      */
-    return (id->id_aa64isar1 &
+    return (id->regs[ID_AA64ISAR1] &
             (FIELD_DP64(0, ID_AA64ISAR1, APA, 0xf) |
              FIELD_DP64(0, ID_AA64ISAR1, API, 0xf) |
              FIELD_DP64(0, ID_AA64ISAR1, GPA, 0xf) |
@@ -3771,121 +3777,121 @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id)
 
 static inline bool isar_feature_aa64_sb(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0;
+    return FIELD_EX64(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, DPB) >= 2;
 }
 
 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(id->regs[ID_AA64PFR0], 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(id->regs[ID_AA64PFR0], 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(id->regs[ID_AA64PFR0], ID_AA64PFR0, EL0) >= 2;
 }
 
 static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
+    return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, SVE) != 0;
 }
 
 static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
+    return FIELD_EX64(id->regs[ID_AA64MMFR1], 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(id->regs[ID_AA64MMFR1], 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(id->regs[ID_AA64MMFR1], 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(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, PAN) >= 2;
 }
 
 static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
+    return FIELD_EX64(id->regs[ID_AA64MMFR2], ID_AA64MMFR2, UAO) != 0;
 }
 
 static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
+    return FIELD_EX64(id->regs[ID_AA64PFR1], 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(id->regs[ID_AA64PFR1], 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(id->regs[ID_AA64PFR1], ID_AA64PFR1, MTE) >= 2;
 }
 
 static inline bool isar_feature_aa64_pmu_8_1(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(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) >= 4 &&
+        FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) != 0xf;
 }
 
 static inline bool isar_feature_aa64_pmu_8_4(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(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) >= 5 &&
+        FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) != 0xf;
 }
 
 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(id->regs[ID_AA64ISAR1], 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(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, LRCPC) >= 2;
 }
 
 static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
+    return FIELD_EX64(id->regs[ID_AA64MMFR2], ID_AA64MMFR2, CCIDX) != 0;
 }
 
 static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
 {
-    return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0;
+    return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, XNX) != 0;
 }
 
 /*
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index dd696183df..4b52505b6e 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -103,31 +103,31 @@ static void aarch64_a57_initfn(Object *obj)
     cpu->midr = 0x411fd070;
     cpu->revidr = 0x00000000;
     cpu->reset_fpsid = 0x41034070;
-    cpu->isar.mvfr0 = 0x10110222;
-    cpu->isar.mvfr1 = 0x12111111;
-    cpu->isar.mvfr2 = 0x00000043;
+    cpu->isar.regs[MVFR0] = 0x10110222;
+    cpu->isar.regs[MVFR1] = 0x12111111;
+    cpu->isar.regs[MVFR2] = 0x00000043;
     cpu->ctr = 0x8444c004;
     cpu->reset_sctlr = 0x00c50838;
     cpu->id_pfr0 = 0x00000131;
     cpu->id_pfr1 = 0x00011011;
-    cpu->isar.id_dfr0 = 0x03010066;
+    cpu->isar.regs[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;
-    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;
-    cpu->isar.id_aa64pfr0 = 0x00002222;
-    cpu->isar.id_aa64dfr0 = 0x10305106;
-    cpu->isar.id_aa64isar0 = 0x00011120;
-    cpu->isar.id_aa64mmfr0 = 0x00001124;
-    cpu->isar.dbgdidr = 0x3516d000;
+    cpu->isar.regs[ID_MMFR0] = 0x10101105;
+    cpu->isar.regs[ID_MMFR1] = 0x40000000;
+    cpu->isar.regs[ID_MMFR2] = 0x01260000;
+    cpu->isar.regs[ID_MMFR3] = 0x02102211;
+    cpu->isar.regs[ID_ISAR0] = 0x02101110;
+    cpu->isar.regs[ID_ISAR1] = 0x13112111;
+    cpu->isar.regs[ID_ISAR2] = 0x21232042;
+    cpu->isar.regs[ID_ISAR3] = 0x01112131;
+    cpu->isar.regs[ID_ISAR4] = 0x00011142;
+    cpu->isar.regs[ID_ISAR5] = 0x00011121;
+    cpu->isar.regs[ID_ISAR6] = 0;
+    cpu->isar.regs[ID_AA64PFR0] = 0x00002222;
+    cpu->isar.regs[ID_AA64DFR0] = 0x10305106;
+    cpu->isar.regs[ID_AA64ISAR0] = 0x00011120;
+    cpu->isar.regs[ID_AA64MMFR0] = 0x00001124;
+    cpu->isar.regs[DBGDIDR] = 0x3516d000;
     cpu->clidr = 0x0a200023;
     cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
     cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
@@ -156,31 +156,31 @@ static void aarch64_a53_initfn(Object *obj)
     cpu->midr = 0x410fd034;
     cpu->revidr = 0x00000000;
     cpu->reset_fpsid = 0x41034070;
-    cpu->isar.mvfr0 = 0x10110222;
-    cpu->isar.mvfr1 = 0x12111111;
-    cpu->isar.mvfr2 = 0x00000043;
+    cpu->isar.regs[MVFR0] = 0x10110222;
+    cpu->isar.regs[MVFR1] = 0x12111111;
+    cpu->isar.regs[MVFR2] = 0x00000043;
     cpu->ctr = 0x84448004; /* L1Ip = VIPT */
     cpu->reset_sctlr = 0x00c50838;
     cpu->id_pfr0 = 0x00000131;
     cpu->id_pfr1 = 0x00011011;
-    cpu->isar.id_dfr0 = 0x03010066;
+    cpu->isar.regs[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;
-    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;
-    cpu->isar.id_aa64pfr0 = 0x00002222;
-    cpu->isar.id_aa64dfr0 = 0x10305106;
-    cpu->isar.id_aa64isar0 = 0x00011120;
-    cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
-    cpu->isar.dbgdidr = 0x3516d000;
+    cpu->isar.regs[ID_MMFR0] = 0x10101105;
+    cpu->isar.regs[ID_MMFR1] = 0x40000000;
+    cpu->isar.regs[ID_MMFR2] = 0x01260000;
+    cpu->isar.regs[ID_MMFR3] = 0x02102211;
+    cpu->isar.regs[ID_ISAR0] = 0x02101110;
+    cpu->isar.regs[ID_ISAR1] = 0x13112111;
+    cpu->isar.regs[ID_ISAR2] = 0x21232042;
+    cpu->isar.regs[ID_ISAR3] = 0x01112131;
+    cpu->isar.regs[ID_ISAR4] = 0x00011142;
+    cpu->isar.regs[ID_ISAR5] = 0x00011121;
+    cpu->isar.regs[ID_ISAR6] = 0;
+    cpu->isar.regs[ID_AA64PFR0] = 0x00002222;
+    cpu->isar.regs[ID_AA64DFR0] = 0x10305106;
+    cpu->isar.regs[ID_AA64ISAR0] = 0x00011120;
+    cpu->isar.regs[ID_AA64MMFR0] = 0x00001122; /* 40 bit physical addr */
+    cpu->isar.regs[DBGDIDR] = 0x3516d000;
     cpu->clidr = 0x0a200023;
     cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */
     cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */
@@ -208,30 +208,30 @@ static void aarch64_a72_initfn(Object *obj)
     cpu->midr = 0x410fd083;
     cpu->revidr = 0x00000000;
     cpu->reset_fpsid = 0x41034080;
-    cpu->isar.mvfr0 = 0x10110222;
-    cpu->isar.mvfr1 = 0x12111111;
-    cpu->isar.mvfr2 = 0x00000043;
+    cpu->isar.regs[MVFR0] = 0x10110222;
+    cpu->isar.regs[MVFR1] = 0x12111111;
+    cpu->isar.regs[MVFR2] = 0x00000043;
     cpu->ctr = 0x8444c004;
     cpu->reset_sctlr = 0x00c50838;
     cpu->id_pfr0 = 0x00000131;
     cpu->id_pfr1 = 0x00011011;
-    cpu->isar.id_dfr0 = 0x03010066;
+    cpu->isar.regs[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;
-    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_aa64pfr0 = 0x00002222;
-    cpu->isar.id_aa64dfr0 = 0x10305106;
-    cpu->isar.id_aa64isar0 = 0x00011120;
-    cpu->isar.id_aa64mmfr0 = 0x00001124;
-    cpu->isar.dbgdidr = 0x3516d000;
+    cpu->isar.regs[ID_MMFR0] = 0x10201105;
+    cpu->isar.regs[ID_MMFR1] = 0x40000000;
+    cpu->isar.regs[ID_MMFR2] = 0x01260000;
+    cpu->isar.regs[ID_MMFR3] = 0x02102211;
+    cpu->isar.regs[ID_ISAR0] = 0x02101110;
+    cpu->isar.regs[ID_ISAR1] = 0x13112111;
+    cpu->isar.regs[ID_ISAR2] = 0x21232042;
+    cpu->isar.regs[ID_ISAR3] = 0x01112131;
+    cpu->isar.regs[ID_ISAR4] = 0x00011142;
+    cpu->isar.regs[ID_ISAR5] = 0x00011121;
+    cpu->isar.regs[ID_AA64PFR0] = 0x00002222;
+    cpu->isar.regs[ID_AA64DFR0] = 0x10305106;
+    cpu->isar.regs[ID_AA64ISAR0] = 0x00011120;
+    cpu->isar.regs[ID_AA64MMFR0] = 0x00001124;
+    cpu->isar.regs[DBGDIDR] = 0x3516d000;
     cpu->clidr = 0x0a200023;
     cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
     cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
@@ -552,9 +552,9 @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
         return;
     }
 
-    t = cpu->isar.id_aa64pfr0;
+    t = cpu->isar.regs[ID_AA64PFR0];
     t = FIELD_DP64(t, ID_AA64PFR0, SVE, value);
-    cpu->isar.id_aa64pfr0 = t;
+    cpu->isar.regs[ID_AA64PFR0] = t;
 }
 
 void aarch64_add_sve_properties(Object *obj)
@@ -607,7 +607,7 @@ static void aarch64_max_initfn(Object *obj)
         t = FIELD_DP64(t, MIDR_EL1, REVISION, 0);
         cpu->midr = t;
 
-        t = cpu->isar.id_aa64isar0;
+        t = cpu->isar.regs[ID_AA64ISAR0];
         t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* AES + PMULL */
         t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1);
         t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* SHA512 */
@@ -621,9 +621,9 @@ static void aarch64_max_initfn(Object *obj)
         t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
         t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */
         t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1);
-        cpu->isar.id_aa64isar0 = t;
+        cpu->isar.regs[ID_AA64ISAR0] = t;
 
-        t = cpu->isar.id_aa64isar1;
+        t = cpu->isar.regs[ID_AA64ISAR1];
         t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2);
         t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
         t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
@@ -635,15 +635,15 @@ static void aarch64_max_initfn(Object *obj)
         t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
         t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
         t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* ARMv8.4-RCPC */
-        cpu->isar.id_aa64isar1 = t;
+        cpu->isar.regs[ID_AA64ISAR1] = t;
 
-        t = cpu->isar.id_aa64pfr0;
+        t = cpu->isar.regs[ID_AA64PFR0];
         t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
         t = FIELD_DP64(t, ID_AA64PFR0, FP, 1);
         t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1);
-        cpu->isar.id_aa64pfr0 = t;
+        cpu->isar.regs[ID_AA64PFR0] = t;
 
-        t = cpu->isar.id_aa64pfr1;
+        t = cpu->isar.regs[ID_AA64PFR1];
         t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
         /*
          * Begin with full support for MTE. This will be downgraded to MTE=0
@@ -651,58 +651,58 @@ static void aarch64_max_initfn(Object *obj)
          * we do for EL2 with the virtualization=on property.
          */
         t = FIELD_DP64(t, ID_AA64PFR1, MTE, 2);
-        cpu->isar.id_aa64pfr1 = t;
+        cpu->isar.regs[ID_AA64PFR1] = t;
 
-        t = cpu->isar.id_aa64mmfr1;
+        t = cpu->isar.regs[ID_AA64MMFR1];
         t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
         t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
         t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);
         t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */
         t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* VMID16 */
         t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* TTS2UXN */
-        cpu->isar.id_aa64mmfr1 = t;
+        cpu->isar.regs[ID_AA64MMFR1] = t;
 
-        t = cpu->isar.id_aa64mmfr2;
+        t = cpu->isar.regs[ID_AA64MMFR2];
         t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
         t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
-        cpu->isar.id_aa64mmfr2 = t;
+        cpu->isar.regs[ID_AA64MMFR2] = t;
 
         /* Replicate the same data to the 32-bit id registers.  */
-        u = cpu->isar.id_isar5;
+        u = cpu->isar.regs[ID_ISAR5];
         u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */
         u = FIELD_DP32(u, ID_ISAR5, SHA1, 1);
         u = FIELD_DP32(u, ID_ISAR5, SHA2, 1);
         u = FIELD_DP32(u, ID_ISAR5, CRC32, 1);
         u = FIELD_DP32(u, ID_ISAR5, RDM, 1);
         u = FIELD_DP32(u, ID_ISAR5, VCMA, 1);
-        cpu->isar.id_isar5 = u;
+        cpu->isar.regs[ID_ISAR5] = u;
 
-        u = cpu->isar.id_isar6;
+        u = cpu->isar.regs[ID_ISAR6];
         u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1);
         u = FIELD_DP32(u, ID_ISAR6, DP, 1);
         u = FIELD_DP32(u, ID_ISAR6, FHM, 1);
         u = FIELD_DP32(u, ID_ISAR6, SB, 1);
         u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
-        cpu->isar.id_isar6 = u;
+        cpu->isar.regs[ID_ISAR6] = u;
 
-        u = cpu->isar.id_mmfr3;
+        u = cpu->isar.regs[ID_MMFR3];
         u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
-        cpu->isar.id_mmfr3 = u;
+        cpu->isar.regs[ID_MMFR3] = u;
 
-        u = cpu->isar.id_mmfr4;
+        u = cpu->isar.regs[ID_MMFR4];
         u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */
         u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
         u = FIELD_DP32(u, ID_MMFR4, CNP, 1); /* TTCNP */
         u = FIELD_DP32(u, ID_MMFR4, XNX, 1); /* TTS2UXN */
-        cpu->isar.id_mmfr4 = u;
+        cpu->isar.regs[ID_MMFR4] = u;
 
-        t = cpu->isar.id_aa64dfr0;
+        t = cpu->isar.regs[ID_AA64DFR0];
         t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */
-        cpu->isar.id_aa64dfr0 = t;
+        cpu->isar.regs[ID_AA64DFR0] = t;
 
-        u = cpu->isar.id_dfr0;
+        u = cpu->isar.regs[ID_DFR0];
         u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */
-        cpu->isar.id_dfr0 = u;
+        cpu->isar.regs[ID_DFR0] = u;
 
         /*
          * FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet,
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
index 00b0e08f33..715f831faf 100644
--- a/target/arm/cpu_tcg.c
+++ b/target/arm/cpu_tcg.c
@@ -56,14 +56,16 @@ 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);
+    cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], 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.
      */
-    cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
-    cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1);
-    cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1);
+    cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0,
+                                       FPSHVEC, 1);
+    cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSP, 1);
+    cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1);
 }
 
 static void arm946_initfn(Object *obj)
@@ -98,14 +100,16 @@ 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);
+    cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], 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.
      */
-    cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
-    cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1);
-    cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1);
+    cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0,
+                                       FPSHVEC, 1);
+    cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSP, 1);
+    cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1);
 
     {
         /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */
@@ -138,22 +142,22 @@ static void arm1136_r2_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
     cpu->midr = 0x4107b362;
     cpu->reset_fpsid = 0x410120b4;
-    cpu->isar.mvfr0 = 0x11111111;
-    cpu->isar.mvfr1 = 0x00000000;
+    cpu->isar.regs[MVFR0] = 0x11111111;
+    cpu->isar.regs[MVFR1] = 0x00000000;
     cpu->ctr = 0x1dd20d2;
     cpu->reset_sctlr = 0x00050078;
     cpu->id_pfr0 = 0x111;
     cpu->id_pfr1 = 0x1;
-    cpu->isar.id_dfr0 = 0x2;
+    cpu->isar.regs[ID_DFR0] = 0x2;
     cpu->id_afr0 = 0x3;
-    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;
+    cpu->isar.regs[ID_MMFR0] = 0x01130003;
+    cpu->isar.regs[ID_MMFR1] = 0x10030302;
+    cpu->isar.regs[ID_MMFR2] = 0x01222110;
+    cpu->isar.regs[ID_ISAR0] = 0x00140011;
+    cpu->isar.regs[ID_ISAR1] = 0x12002111;
+    cpu->isar.regs[ID_ISAR2] = 0x11231111;
+    cpu->isar.regs[ID_ISAR3] = 0x01102131;
+    cpu->isar.regs[ID_ISAR4] = 0x141;
     cpu->reset_auxcr = 7;
 }
 
@@ -169,22 +173,22 @@ static void arm1136_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
     cpu->midr = 0x4117b363;
     cpu->reset_fpsid = 0x410120b4;
-    cpu->isar.mvfr0 = 0x11111111;
-    cpu->isar.mvfr1 = 0x00000000;
+    cpu->isar.regs[MVFR0] = 0x11111111;
+    cpu->isar.regs[MVFR1] = 0x00000000;
     cpu->ctr = 0x1dd20d2;
     cpu->reset_sctlr = 0x00050078;
     cpu->id_pfr0 = 0x111;
     cpu->id_pfr1 = 0x1;
-    cpu->isar.id_dfr0 = 0x2;
+    cpu->isar.regs[ID_DFR0] = 0x2;
     cpu->id_afr0 = 0x3;
-    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;
+    cpu->isar.regs[ID_MMFR0] = 0x01130003;
+    cpu->isar.regs[ID_MMFR1] = 0x10030302;
+    cpu->isar.regs[ID_MMFR2] = 0x01222110;
+    cpu->isar.regs[ID_ISAR0] = 0x00140011;
+    cpu->isar.regs[ID_ISAR1] = 0x12002111;
+    cpu->isar.regs[ID_ISAR2] = 0x11231111;
+    cpu->isar.regs[ID_ISAR3] = 0x01102131;
+    cpu->isar.regs[ID_ISAR4] = 0x141;
     cpu->reset_auxcr = 7;
 }
 
@@ -201,22 +205,22 @@ static void arm1176_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_EL3);
     cpu->midr = 0x410fb767;
     cpu->reset_fpsid = 0x410120b5;
-    cpu->isar.mvfr0 = 0x11111111;
-    cpu->isar.mvfr1 = 0x00000000;
+    cpu->isar.regs[MVFR0] = 0x11111111;
+    cpu->isar.regs[MVFR1] = 0x00000000;
     cpu->ctr = 0x1dd20d2;
     cpu->reset_sctlr = 0x00050078;
     cpu->id_pfr0 = 0x111;
     cpu->id_pfr1 = 0x11;
-    cpu->isar.id_dfr0 = 0x33;
+    cpu->isar.regs[ID_DFR0] = 0x33;
     cpu->id_afr0 = 0;
-    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;
+    cpu->isar.regs[ID_MMFR0] = 0x01130003;
+    cpu->isar.regs[ID_MMFR1] = 0x10030302;
+    cpu->isar.regs[ID_MMFR2] = 0x01222100;
+    cpu->isar.regs[ID_ISAR0] = 0x0140011;
+    cpu->isar.regs[ID_ISAR1] = 0x12002111;
+    cpu->isar.regs[ID_ISAR2] = 0x11231121;
+    cpu->isar.regs[ID_ISAR3] = 0x01102131;
+    cpu->isar.regs[ID_ISAR4] = 0x01141;
     cpu->reset_auxcr = 7;
 }
 
@@ -231,21 +235,21 @@ static void arm11mpcore_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
     cpu->midr = 0x410fb022;
     cpu->reset_fpsid = 0x410120b4;
-    cpu->isar.mvfr0 = 0x11111111;
-    cpu->isar.mvfr1 = 0x00000000;
+    cpu->isar.regs[MVFR0] = 0x11111111;
+    cpu->isar.regs[MVFR1] = 0x00000000;
     cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */
     cpu->id_pfr0 = 0x111;
     cpu->id_pfr1 = 0x1;
-    cpu->isar.id_dfr0 = 0;
+    cpu->isar.regs[ID_DFR0] = 0;
     cpu->id_afr0 = 0x2;
-    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;
+    cpu->isar.regs[ID_MMFR0] = 0x01100103;
+    cpu->isar.regs[ID_MMFR1] = 0x10020302;
+    cpu->isar.regs[ID_MMFR2] = 0x01222000;
+    cpu->isar.regs[ID_ISAR0] = 0x00100011;
+    cpu->isar.regs[ID_ISAR1] = 0x12002111;
+    cpu->isar.regs[ID_ISAR2] = 0x11221011;
+    cpu->isar.regs[ID_ISAR3] = 0x01102131;
+    cpu->isar.regs[ID_ISAR4] = 0x141;
     cpu->reset_auxcr = 1;
 }
 
@@ -268,19 +272,19 @@ static void cortex_m3_initfn(Object *obj)
     cpu->pmsav7_dregion = 8;
     cpu->id_pfr0 = 0x00000030;
     cpu->id_pfr1 = 0x00000200;
-    cpu->isar.id_dfr0 = 0x00100000;
+    cpu->isar.regs[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;
-    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;
+    cpu->isar.regs[ID_MMFR0] = 0x00000030;
+    cpu->isar.regs[ID_MMFR1] = 0x00000000;
+    cpu->isar.regs[ID_MMFR2] = 0x00000000;
+    cpu->isar.regs[ID_MMFR3] = 0x00000000;
+    cpu->isar.regs[ID_ISAR0] = 0x01141110;
+    cpu->isar.regs[ID_ISAR1] = 0x02111000;
+    cpu->isar.regs[ID_ISAR2] = 0x21112231;
+    cpu->isar.regs[ID_ISAR3] = 0x01111110;
+    cpu->isar.regs[ID_ISAR4] = 0x01310102;
+    cpu->isar.regs[ID_ISAR5] = 0x00000000;
+    cpu->isar.regs[ID_ISAR6] = 0x00000000;
 }
 
 static void cortex_m4_initfn(Object *obj)
@@ -293,24 +297,24 @@ static void cortex_m4_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
     cpu->midr = 0x410fc240; /* r0p0 */
     cpu->pmsav7_dregion = 8;
-    cpu->isar.mvfr0 = 0x10110021;
-    cpu->isar.mvfr1 = 0x11000011;
-    cpu->isar.mvfr2 = 0x00000000;
+    cpu->isar.regs[MVFR0] = 0x10110021;
+    cpu->isar.regs[MVFR1] = 0x11000011;
+    cpu->isar.regs[MVFR2] = 0x00000000;
     cpu->id_pfr0 = 0x00000030;
     cpu->id_pfr1 = 0x00000200;
-    cpu->isar.id_dfr0 = 0x00100000;
+    cpu->isar.regs[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;
-    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;
+    cpu->isar.regs[ID_MMFR0] = 0x00000030;
+    cpu->isar.regs[ID_MMFR1] = 0x00000000;
+    cpu->isar.regs[ID_MMFR2] = 0x00000000;
+    cpu->isar.regs[ID_MMFR3] = 0x00000000;
+    cpu->isar.regs[ID_ISAR0] = 0x01141110;
+    cpu->isar.regs[ID_ISAR1] = 0x02111000;
+    cpu->isar.regs[ID_ISAR2] = 0x21112231;
+    cpu->isar.regs[ID_ISAR3] = 0x01111110;
+    cpu->isar.regs[ID_ISAR4] = 0x01310102;
+    cpu->isar.regs[ID_ISAR5] = 0x00000000;
+    cpu->isar.regs[ID_ISAR6] = 0x00000000;
 }
 
 static void cortex_m7_initfn(Object *obj)
@@ -323,24 +327,24 @@ static void cortex_m7_initfn(Object *obj)
     set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
     cpu->midr = 0x411fc272; /* r1p2 */
     cpu->pmsav7_dregion = 8;
-    cpu->isar.mvfr0 = 0x10110221;
-    cpu->isar.mvfr1 = 0x12000011;
-    cpu->isar.mvfr2 = 0x00000040;
+    cpu->isar.regs[MVFR0] = 0x10110221;
+    cpu->isar.regs[MVFR1] = 0x12000011;
+    cpu->isar.regs[MVFR2] = 0x00000040;
     cpu->id_pfr0 = 0x00000030;
     cpu->id_pfr1 = 0x00000200;
-    cpu->isar.id_dfr0 = 0x00100000;
+    cpu->isar.regs[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;
-    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;
+    cpu->isar.regs[ID_MMFR0] = 0x00100030;
+    cpu->isar.regs[ID_MMFR1] = 0x00000000;
+    cpu->isar.regs[ID_MMFR2] = 0x01000000;
+    cpu->isar.regs[ID_MMFR3] = 0x00000000;
+    cpu->isar.regs[ID_ISAR0] = 0x01101110;
+    cpu->isar.regs[ID_ISAR1] = 0x02112000;
+    cpu->isar.regs[ID_ISAR2] = 0x20232231;
+    cpu->isar.regs[ID_ISAR3] = 0x01111131;
+    cpu->isar.regs[ID_ISAR4] = 0x01310132;
+    cpu->isar.regs[ID_ISAR5] = 0x00000000;
+    cpu->isar.regs[ID_ISAR6] = 0x00000000;
 }
 
 static void cortex_m33_initfn(Object *obj)
@@ -355,24 +359,24 @@ static void cortex_m33_initfn(Object *obj)
     cpu->midr = 0x410fd213; /* r0p3 */
     cpu->pmsav7_dregion = 16;
     cpu->sau_sregion = 8;
-    cpu->isar.mvfr0 = 0x10110021;
-    cpu->isar.mvfr1 = 0x11000011;
-    cpu->isar.mvfr2 = 0x00000040;
+    cpu->isar.regs[MVFR0] = 0x10110021;
+    cpu->isar.regs[MVFR1] = 0x11000011;
+    cpu->isar.regs[MVFR2] = 0x00000040;
     cpu->id_pfr0 = 0x00000030;
     cpu->id_pfr1 = 0x00000210;
-    cpu->isar.id_dfr0 = 0x00200000;
+    cpu->isar.regs[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;
-    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;
+    cpu->isar.regs[ID_MMFR0] = 0x00101F40;
+    cpu->isar.regs[ID_MMFR1] = 0x00000000;
+    cpu->isar.regs[ID_MMFR2] = 0x01000000;
+    cpu->isar.regs[ID_MMFR3] = 0x00000000;
+    cpu->isar.regs[ID_ISAR0] = 0x01101110;
+    cpu->isar.regs[ID_ISAR1] = 0x02212000;
+    cpu->isar.regs[ID_ISAR2] = 0x20232232;
+    cpu->isar.regs[ID_ISAR3] = 0x01111131;
+    cpu->isar.regs[ID_ISAR4] = 0x01310132;
+    cpu->isar.regs[ID_ISAR5] = 0x00000000;
+    cpu->isar.regs[ID_ISAR6] = 0x00000000;
     cpu->clidr = 0x00000000;
     cpu->ctr = 0x8000c000;
 }
@@ -399,19 +403,19 @@ static void cortex_r5_initfn(Object *obj)
     cpu->midr = 0x411fc153; /* r1p3 */
     cpu->id_pfr0 = 0x0131;
     cpu->id_pfr1 = 0x001;
-    cpu->isar.id_dfr0 = 0x010400;
+    cpu->isar.regs[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;
-    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;
+    cpu->isar.regs[ID_MMFR0] = 0x0210030;
+    cpu->isar.regs[ID_MMFR1] = 0x00000000;
+    cpu->isar.regs[ID_MMFR2] = 0x01200000;
+    cpu->isar.regs[ID_MMFR3] = 0x0211;
+    cpu->isar.regs[ID_ISAR0] = 0x02101111;
+    cpu->isar.regs[ID_ISAR1] = 0x13112111;
+    cpu->isar.regs[ID_ISAR2] = 0x21232141;
+    cpu->isar.regs[ID_ISAR3] = 0x01112131;
+    cpu->isar.regs[ID_ISAR4] = 0x0010142;
+    cpu->isar.regs[ID_ISAR5] = 0x0;
+    cpu->isar.regs[ID_ISAR6] = 0x0;
     cpu->mp_is_up = true;
     cpu->pmsav7_dregion = 16;
     define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
@@ -422,8 +426,8 @@ static void cortex_r5f_initfn(Object *obj)
     ARMCPU *cpu = ARM_CPU(obj);
 
     cortex_r5_initfn(obj);
-    cpu->isar.mvfr0 = 0x10110221;
-    cpu->isar.mvfr1 = 0x00000011;
+    cpu->isar.regs[MVFR0] = 0x10110221;
+    cpu->isar.regs[MVFR1] = 0x00000011;
 }
 
 static void ti925t_initfn(Object *obj)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 455c92b891..9208ec046c 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6472,7 +6472,7 @@ static void define_debug_regs(ARMCPU *cpu)
     ARMCPRegInfo dbgdidr = {
         .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
         .access = PL0_R, .accessfn = access_tda,
-        .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
+        .type = ARM_CP_CONST, .resetvalue = cpu->isar.regs[DBGDIDR],
     };
 
     /* Note that all these register fields hold "number of Xs minus 1". */
@@ -6638,7 +6638,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 = cpu->isar.regs[ID_AA64PFR0];
 
     if (env->gicv3state) {
         pfr0 |= 1 << 24;
@@ -7273,7 +7273,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 = cpu->isar.regs[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,
@@ -7283,62 +7283,62 @@ 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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_isar0 },
+              .resetvalue = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_mmfr4 },
+              .resetvalue = cpu->isar.regs[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,
               .accessfn = access_aa32_tid3,
-              .resetvalue = cpu->isar.id_isar6 },
+              .resetvalue = cpu->isar.regs[ID_ISAR6] },
             REGINFO_SENTINEL
         };
         define_arm_cp_regs(cpu, v6_idregs);
@@ -7388,7 +7388,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 = cpu->isar.regs[ID_AA64PFR0]
 #else
               .type = ARM_CP_NO_RAW,
               .accessfn = access_aa64_tid3,
@@ -7400,7 +7400,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 = cpu->isar.regs[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,
@@ -7436,12 +7436,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 = cpu->isar.regs[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 = cpu->isar.regs[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,
@@ -7476,12 +7476,12 @@ 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 = cpu->isar.regs[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,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.id_aa64isar1 },
+              .resetvalue = cpu->isar.regs[ID_AA64ISAR1] },
             { .name = "ID_AA64ISAR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2,
               .access = PL1_R, .type = ARM_CP_CONST,
@@ -7516,17 +7516,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 = cpu->isar.regs[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 = cpu->isar.regs[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 = cpu->isar.regs[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,
@@ -7556,17 +7556,17 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 0,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.mvfr0 },
+              .resetvalue = cpu->isar.regs[MVFR0] },
             { .name = "MVFR1_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 1,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.mvfr1 },
+              .resetvalue = cpu->isar.regs[MVFR1] },
             { .name = "MVFR2_EL1", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
               .access = PL1_R, .type = ARM_CP_CONST,
               .accessfn = access_aa64_tid3,
-              .resetvalue = cpu->isar.mvfr2 },
+              .resetvalue = cpu->isar.regs[MVFR2] },
             { .name = "MVFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
               .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 3,
               .access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/internals.h b/target/arm/internals.h
index ae99725d2b..bcb9ba9954 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -237,7 +237,7 @@ static inline unsigned int arm_pamax(ARMCPU *cpu)
         [5] = 48,
     };
     unsigned int parange =
-        FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE);
+        FIELD_EX64(cpu->isar.regs[ID_AA64MMFR0], ID_AA64MMFR0, PARANGE);
 
     /* id_aa64mmfr0 is a read-only register so values outside of the
      * supported mappings can be considered an implementation error.  */
@@ -991,9 +991,9 @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
 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(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, BRPS) + 1;
     } else {
-        return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, BRPS) + 1;
+        return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, BRPS) + 1;
     }
 }
 
@@ -1005,9 +1005,9 @@ 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(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, WRPS) + 1;
     } else {
-        return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, WRPS) + 1;
+        return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, WRPS) + 1;
     }
 }
 
@@ -1019,9 +1019,10 @@ 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(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0,
+                          CTX_CMPS) + 1;
     } else {
-        return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, CTX_CMPS) + 1;
+        return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, CTX_CMPS) + 1;
     }
 }
 
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 1169237905..be2d0cda0d 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -450,7 +450,7 @@ void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
     }
 }
 
-static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id)
+static int read_sys_reg32(int fd, uint64_t *pret, uint64_t id)
 {
     uint64_t ret;
     struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)&ret };
@@ -510,7 +510,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
     ahcf->target = init.target;
     ahcf->dtb_compatible = "arm,arm-v8";
 
-    err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0,
+    err = read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64PFR0],
                          ARM64_SYS_REG(3, 0, 0, 4, 0));
     if (unlikely(err < 0)) {
         /*
@@ -529,24 +529,24 @@ 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 */
+        ahcf->isar.regs[ID_AA64PFR0] = 0x00000011; /* EL1&0, AArch64 only */
         err = 0;
     } else {
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1,
+        err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64PFR1],
                               ARM64_SYS_REG(3, 0, 0, 4, 1));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0,
+        err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64DFR0],
                               ARM64_SYS_REG(3, 0, 0, 5, 0));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1,
+        err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64DFR1],
                               ARM64_SYS_REG(3, 0, 0, 5, 1));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0,
+        err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64ISAR0],
                               ARM64_SYS_REG(3, 0, 0, 6, 0));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1,
+        err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64ISAR1],
                               ARM64_SYS_REG(3, 0, 0, 6, 1));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0,
+        err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR0],
                               ARM64_SYS_REG(3, 0, 0, 7, 0));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1,
+        err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR1],
                               ARM64_SYS_REG(3, 0, 0, 7, 1));
-        err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2,
+        err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR2],
                               ARM64_SYS_REG(3, 0, 0, 7, 2));
 
         /*
@@ -556,38 +556,38 @@ 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_dfr0,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_DFR0],
                               ARM64_SYS_REG(3, 0, 0, 1, 2));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR0],
                               ARM64_SYS_REG(3, 0, 0, 1, 4));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR1],
                               ARM64_SYS_REG(3, 0, 0, 1, 5));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR2],
                               ARM64_SYS_REG(3, 0, 0, 1, 6));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR3],
                               ARM64_SYS_REG(3, 0, 0, 1, 7));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR0],
                               ARM64_SYS_REG(3, 0, 0, 2, 0));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR1],
                               ARM64_SYS_REG(3, 0, 0, 2, 1));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR2],
                               ARM64_SYS_REG(3, 0, 0, 2, 2));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR3],
                               ARM64_SYS_REG(3, 0, 0, 2, 3));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR4],
                               ARM64_SYS_REG(3, 0, 0, 2, 4));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR5],
                               ARM64_SYS_REG(3, 0, 0, 2, 5));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR4],
                               ARM64_SYS_REG(3, 0, 0, 2, 6));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR6],
                               ARM64_SYS_REG(3, 0, 0, 2, 7));
 
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR0],
                               ARM64_SYS_REG(3, 0, 0, 3, 0));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR1],
                               ARM64_SYS_REG(3, 0, 0, 3, 1));
-        err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2,
+        err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR2],
                               ARM64_SYS_REG(3, 0, 0, 3, 2));
 
         /*
@@ -600,14 +600,16 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
          * arch/arm64/kvm/sys_regs.c:trap_dbgidr() does.
          * We only do this if the CPU supports AArch32 at EL1.
          */
-        if (FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL1) >= 2) {
-            int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS);
-            int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS);
+        if (FIELD_EX32(ahcf->isar.regs[ID_AA64PFR0], ID_AA64PFR0, EL1) >= 2) {
+            int wrps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0],
+                                  ID_AA64DFR0, WRPS);
+            int brps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0],
+                                  ID_AA64DFR0, BRPS);
             int ctx_cmps =
-                FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS);
+                FIELD_EX64(ahcf->isar.regs[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(ahcf->isar.regs[ID_AA64PFR0], ID_AA64PFR0, EL3);
             uint32_t dbgdidr = 0;
 
             dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps);
@@ -617,7 +619,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
             dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, NSUHD_IMP, has_el3);
             dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, SE_IMP, has_el3);
             dbgdidr |= (1 << 15); /* RES1 bit */
-            ahcf->isar.dbgdidr = dbgdidr;
+            ahcf->isar.regs[DBGDIDR] = dbgdidr;
         }
     }
 
@@ -631,9 +633,9 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
 
     /* Add feature bits that can't appear until after VCPU init. */
     if (sve_supported) {
-        t = ahcf->isar.id_aa64pfr0;
+        t = ahcf->isar.regs[ID_AA64PFR0];
         t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
-        ahcf->isar.id_aa64pfr0 = t;
+        ahcf->isar.regs[ID_AA64PFR0] = t;
     }
 
     /*
-- 
2.18.4



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

* [RFC 2/9] target/arm: parse cpu feature related options
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
  2020-08-13 10:26 ` [RFC 1/9] target/arm: convert isar regs to array Peng Liang
@ 2020-08-13 10:26 ` Peng Liang
  2020-08-13 12:21   ` Andrew Jones
  2020-08-13 10:26 ` [RFC 3/9] target/arm: register CPU features for property Peng Liang
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Peng Liang @ 2020-08-13 10:26 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, Peng Liang, pbonzini

The implementation of CPUClass::parse_features only supports CPU
features in "feature=value" format.  However, libvirt maybe send us a
CPU feature string in "+feature/-feature" format.  Hence, we need to
override CPUClass::parse_features to support CPU feature string in both
"feature=value" and "+feature/-feature" format.

The logic of AArch64CPUClass::parse_features is similar to that of
X86CPUClass::parse_features.  The diference is that feature name is
transformed to upper before it's added as a property because the name
of CPU features is upper for convenience.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 target/arm/cpu64.c | 101 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 101 insertions(+)

diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 4b52505b6e..981011b3da 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -28,6 +28,7 @@
 #include "sysemu/kvm.h"
 #include "kvm_arm.h"
 #include "qapi/visitor.h"
+#include "hw/qdev-properties.h"
 
 #ifndef CONFIG_USER_ONLY
 static uint64_t a57_a53_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
@@ -778,6 +779,105 @@ static gchar *aarch64_gdb_arch_name(CPUState *cs)
     return g_strdup("aarch64");
 }
 
+static void
+cpu_add_feat_as_prop(const char *typename, const char *name, const char *val)
+{
+    GlobalProperty *prop = g_new0(typeof(*prop), 1);
+    prop->driver = typename;
+    prop->property = g_strdup(name);
+    prop->value = g_strdup(val);
+    qdev_prop_register_global(prop);
+}
+
+static gint compare_string(gconstpointer a, gconstpointer b)
+{
+    return g_strcmp0(a, b);
+}
+
+static GList *plus_features, *minus_features;
+
+static char *strtoupr(char *str)
+{
+    char *orign = str;
+
+    for (; *str != '\0'; str++) {
+        *str = toupper(*str);
+    }
+
+    return orign;
+}
+
+static void aarch64_cpu_parse_features(const char *typename, char *features,
+                                     Error **errp)
+{
+    GList *l;
+    char *featurestr; /* Single 'key=value" string being parsed */
+    static bool cpu_globals_initialized;
+
+    if (cpu_globals_initialized) {
+        return;
+    }
+    cpu_globals_initialized = true;
+
+    if (!features) {
+        return;
+    }
+    for (featurestr = strtok(features, ",");
+        featurestr;
+        featurestr = strtok(NULL, ",")) {
+        const char *name;
+        char *tmp;
+        const char *val = NULL;
+        char *eq = NULL;
+
+        /* Compatibility syntax: */
+        if (featurestr[0] == '+') {
+            plus_features = g_list_append(plus_features,
+                                          g_strdup(featurestr + 1));
+            continue;
+        } else if (featurestr[0] == '-') {
+            minus_features = g_list_append(minus_features,
+                                           g_strdup(featurestr + 1));
+            continue;
+        }
+
+        eq = strchr(featurestr, '=');
+        name = featurestr;
+        if (eq) {
+            *eq++ = 0;
+            val = eq;
+        } else {
+            error_setg(errp, "Unsupported property format: %s", name);
+            return;
+        }
+
+        if (g_list_find_custom(plus_features, name, compare_string)) {
+            warn_report("Ambiguous CPU model string. "
+                        "Don't mix both \"+%s\" and \"%s=%s\"",
+                        name, name, val);
+        }
+        if (g_list_find_custom(minus_features, name, compare_string)) {
+            warn_report("Ambiguous CPU model string. "
+                        "Don't mix both \"-%s\" and \"%s=%s\"",
+                        name, name, val);
+        }
+        tmp = g_strdup(name);
+        tmp = strtoupr(tmp);
+        cpu_add_feat_as_prop(typename, tmp, val);
+        g_free(tmp);
+    }
+
+    for (l = plus_features; l; l = l->next) {
+        const char *name = strtoupr(l->data); /* convert to upper string */
+        cpu_add_feat_as_prop(typename, name, "on");
+    }
+
+    for (l = minus_features; l; l = l->next) {
+        const char *name = strtoupr(l->data);
+        cpu_add_feat_as_prop(typename, name, "off");
+    }
+}
+
 static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
 {
     CPUClass *cc = CPU_CLASS(oc);
@@ -788,6 +888,7 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
     cc->gdb_num_core_regs = 34;
     cc->gdb_core_xml_file = "aarch64-core.xml";
     cc->gdb_arch_name = aarch64_gdb_arch_name;
+    cc->parse_features = aarch64_cpu_parse_features;
 }
 
 static void aarch64_cpu_instance_init(Object *obj)
-- 
2.18.4



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

* [RFC 3/9] target/arm: register CPU features for property
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
  2020-08-13 10:26 ` [RFC 1/9] target/arm: convert isar regs to array Peng Liang
  2020-08-13 10:26 ` [RFC 2/9] target/arm: parse cpu feature related options Peng Liang
@ 2020-08-13 10:26 ` Peng Liang
  2020-08-13 12:34   ` Andrew Jones
  2020-08-13 10:26 ` [RFC 4/9] target/arm: Allow ID registers to synchronize to KVM Peng Liang
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Peng Liang @ 2020-08-13 10:26 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, Peng Liang, pbonzini

The Arm architecture specifies a number of ID registers that are
characterized as comprising a set of 4-bit ID fields. Each ID field
identifies the presence, and possibly the level of support for, a
particular feature in an implementation of the architecture. [1]

For most of the ID fields, there is a minimum presence value, equal to
or higher than which means the corresponding CPU feature is implemented.
Hence, we can use the minimum presence value to determine whether a CPU
feature is enabled and enable a CPU feature.

To disable a CPU feature, setting the corresponding ID field to 0x0/0xf
(for unsigned/signed field) seems as a good idea.  However, it maybe
lead to some problems.  For example,  ID_AA64PFR0_EL1.FP is a signed ID
field. ID_AA64PFR0_EL1.FP == 0x0 represents the implementation of FP
(floating-point) and ID_AA64PFR0_EL1.FP == 0x1 represents the
implementation of FPHP (half-precision floating-point).  If
ID_AA64PFR0_EL1.FP is set to 0xf when FPHP is disabled (which is also
disable FP), guest kernel maybe stuck.  Hence, we add a ni_value (means
not-implemented value) to disable a CPU feature safely.

[1] D13.1.3 Principles of the ID scheme for fields in ID registers in
    DDI.0487

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 target/arm/cpu.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 343 insertions(+)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 79d7a6b45c..113cf4a9e7 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1146,6 +1146,348 @@ unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
       NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1;
 }
 
+/**
+ * CPUFeatureInfo:
+ * @reg: The ID register where the ID field is in.
+ * @name: The name of the CPU feature.
+ * @length: The bit length of the ID field.
+ * @shift: The bit shift of the ID field in the ID register.
+ * @min_value: The minimum value equal to or larger than which means the CPU
+ *   feature is implemented.
+ * @ni_value: Not-implemented value. It will be set to the ID field when
+ *   disabling the CPU feature.  Usually, it's min_value - 1.
+ * @sign: Whether the ID field is signed.
+ * @is_32bit: Whether the CPU feature is for 32-bit.
+ *
+ * In ARM, a CPU feature is described by an ID field, which is a 4-bit field in
+ * an ID register.
+ */
+typedef struct CPUFeatureInfo {
+    CPUIDReg reg;
+    const char *name;
+    int length;
+    int shift;
+    int min_value;
+    int ni_value;
+    bool sign;
+    bool is_32bit;
+} CPUFeatureInfo;
+
+#define FIELD_INFO(id_reg, field, s, min_val, ni_val, is32bit) { \
+    .reg = id_reg, \
+    .length = R_ ## id_reg ## _ ## field ## _LENGTH, \
+    .shift = R_ ## id_reg ## _ ## field ## _SHIFT, \
+    .sign = s, \
+    .min_value = min_val, \
+    .ni_value = ni_val, \
+    .name = #field, \
+    .is_32bit = is32bit, \
+}
+
+static struct CPUFeatureInfo cpu_features[] = {
+    FIELD_INFO(ID_ISAR0, SWAP, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR0, BITCOUNT, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR0, BITFIELD, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR0, CMPBRANCH, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR0, COPROC, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR0, DEBUG, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR0, DIVIDE, false, 1, 0, true),
+
+    FIELD_INFO(ID_ISAR1, ENDIAN, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR1, EXCEPT, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR1, EXCEPT_AR, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR1, EXTEND, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR1, IFTHEN, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR1, IMMEDIATE, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR1, INTERWORK, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR1, JAZELLE, false, 1, 0, true),
+
+    FIELD_INFO(ID_ISAR2, LOADSTORE, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR2, MEMHINT, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR2, MULTIACCESSINT, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR2, MULT, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR2, MULTS, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR2, MULTU, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR2, PSR_AR, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR2, REVERSAL, false, 1, 0, true),
+
+    FIELD_INFO(ID_ISAR3, SATURATE, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR3, SIMD, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR3, SVC, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR3, SYNCHPRIM, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR3, TABBRANCH, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR3, T32COPY, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR3, TRUENOP, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR3, T32EE, false, 1, 0, true),
+
+    FIELD_INFO(ID_ISAR4, UNPRIV, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR4, WITHSHIFTS, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR4, WRITEBACK, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR4, SMC, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR4, BARRIER, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR4, SYNCHPRIM_FRAC, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR4, PSR_M, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR4, SWP_FRAC, false, 1, 0, true),
+
+    FIELD_INFO(ID_ISAR5, SEVL, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR5, AES, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR5, SHA1, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR5, SHA2, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR5, CRC32, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR5, RDM, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR5, VCMA, false, 1, 0, true),
+
+    FIELD_INFO(ID_ISAR6, JSCVT, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR6, DP, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR6, FHM, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR6, SB, false, 1, 0, true),
+    FIELD_INFO(ID_ISAR6, SPECRES, false, 1, 0, true),
+
+    FIELD_INFO(ID_MMFR3, CMAINTVA, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR3, CMAINTSW, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR3, BPMAINT, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR3, MAINTBCST, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR3, PAN, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR3, COHWALK, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR3, CMEMSZ, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR3, SUPERSEC, false, 1, 0, true),
+
+    FIELD_INFO(ID_MMFR4, SPECSEI, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR4, AC2, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR4, XNX, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR4, CNP, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR4, HPDS, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR4, LSM, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR4, CCIDX, false, 1, 0, true),
+    FIELD_INFO(ID_MMFR4, EVT, false, 1, 0, true),
+
+    FIELD_INFO(MVFR0, SIMDREG, false, 1, 0, true),
+    FIELD_INFO(MVFR0, FPSP, false, 1, 0, true),
+    FIELD_INFO(MVFR0, FPDP, false, 1, 0, true),
+    FIELD_INFO(MVFR0, FPTRAP, false, 1, 0, true),
+    FIELD_INFO(MVFR0, FPDIVIDE, false, 1, 0, true),
+    FIELD_INFO(MVFR0, FPSQRT, false, 1, 0, true),
+    FIELD_INFO(MVFR0, FPSHVEC, false, 1, 0, true),
+    FIELD_INFO(MVFR0, FPROUND, false, 1, 0, true),
+
+    FIELD_INFO(MVFR1, FPFTZ, false, 1, 0, true),
+    FIELD_INFO(MVFR1, FPDNAN, false, 1, 0, true),
+    FIELD_INFO(MVFR1, SIMDLS, false, 1, 0, true),
+    FIELD_INFO(MVFR1, SIMDINT, false, 1, 0, true),
+    FIELD_INFO(MVFR1, SIMDSP, false, 1, 0, true),
+    FIELD_INFO(MVFR1, SIMDHP, false, 1, 0, true),
+    FIELD_INFO(MVFR1, FPHP, false, 1, 0, true),
+    FIELD_INFO(MVFR1, SIMDFMAC, false, 1, 0, true),
+
+    FIELD_INFO(MVFR2, SIMDMISC, false, 1, 0, true),
+    FIELD_INFO(MVFR2, FPMISC, false, 1, 0, true),
+
+    FIELD_INFO(ID_DFR0, COPDBG, false, 1, 0, true),
+    FIELD_INFO(ID_DFR0, COPSDBG, false, 1, 0, true),
+    FIELD_INFO(ID_DFR0, MMAPDBG, false, 1, 0, true),
+    FIELD_INFO(ID_DFR0, COPTRC, false, 1, 0, true),
+    FIELD_INFO(ID_DFR0, MMAPTRC, false, 1, 0, true),
+    FIELD_INFO(ID_DFR0, MPROFDBG, false, 1, 0, true),
+    FIELD_INFO(ID_DFR0, PERFMON, false, 1, 0, true),
+    FIELD_INFO(ID_DFR0, TRACEFILT, false, 1, 0, true),
+
+    FIELD_INFO(ID_AA64ISAR0, AES, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, SHA1, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, SHA2, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, CRC32, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, ATOMIC, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, RDM, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, SHA3, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, SM3, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, SM4, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, DP, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, FHM, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, TS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, TLB, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR0, RNDR, false, 1, 0, false),
+
+    FIELD_INFO(ID_AA64ISAR1, DPB, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, APA, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, API, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, JSCVT, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, FCMA, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, LRCPC, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, GPA, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, GPI, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, FRINTTS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, SB, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, SPECRES, false, 1, 0, false),
+
+    FIELD_INFO(ID_AA64PFR0, EL0, false, 1, 0, false),
+    FIELD_INFO(ID_AA64PFR0, EL1, false, 1, 0, false),
+    FIELD_INFO(ID_AA64PFR0, EL2, false, 1, 0, false),
+    FIELD_INFO(ID_AA64PFR0, EL3, false, 1, 0, false),
+    FIELD_INFO(ID_AA64PFR0, FP, true, 0, 0xf, false),
+    FIELD_INFO(ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false),
+    FIELD_INFO(ID_AA64PFR0, GIC, false, 1, 0, false),
+    FIELD_INFO(ID_AA64PFR0, RAS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64PFR0, SVE, false, 1, 0, false),
+
+    FIELD_INFO(ID_AA64PFR1, BT, false, 1, 0, false),
+    FIELD_INFO(ID_AA64PFR1, SBSS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64PFR1, MTE, false, 1, 0, false),
+    FIELD_INFO(ID_AA64PFR1, RAS_FRAC, false, 1, 0, false),
+
+    FIELD_INFO(ID_AA64MMFR0, PARANGE, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR0, ASIDBITS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR0, BIGEND, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR0, SNSMEM, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR0, BIGENDEL0, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR0, TGRAN16, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR0, TGRAN64, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR0, TGRAN4, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR0, TGRAN16_2, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR0, TGRAN64_2, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR0, TGRAN4_2, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR0, EXS, false, 1, 0, false),
+
+    FIELD_INFO(ID_AA64MMFR1, HAFDBS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR1, VMIDBITS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR1, VH, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR1, HPDS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR1, LO, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR1, PAN, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR1, SPECSEI, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR1, XNX, false, 1, 0, false),
+
+    FIELD_INFO(ID_AA64MMFR2, CNP, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, UAO, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, LSM, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, IESB, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, VARANGE, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, CCIDX, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, NV, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, ST, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, AT, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, IDS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, FWB, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, TTL, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, BBM, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, EVT, false, 1, 0, false),
+    FIELD_INFO(ID_AA64MMFR2, E0PD, false, 1, 0, false),
+
+    FIELD_INFO(ID_AA64DFR0, DEBUGVER, false, 1, 0, false),
+    FIELD_INFO(ID_AA64DFR0, TRACEVER, false, 1, 0, false),
+    FIELD_INFO(ID_AA64DFR0, PMUVER, false, 1, 0, false),
+    FIELD_INFO(ID_AA64DFR0, BRPS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64DFR0, WRPS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64DFR0, CTX_CMPS, false, 1, 0, false),
+    FIELD_INFO(ID_AA64DFR0, PMSVER, false, 1, 0, false),
+    FIELD_INFO(ID_AA64DFR0, DOUBLELOCK, false, 1, 0, false),
+    FIELD_INFO(ID_AA64DFR0, TRACEFILT, false, 1, 0, false),
+
+    {
+        .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH,
+        .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1,
+        .ni_value = 0, .name = "FPHP", .is_32bit = false,
+    },
+    {
+        .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH,
+        .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1,
+        .ni_value = 0, .name = "ADVSIMDHP", .is_32bit = false,
+    },
+    {
+        .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_AES_LENGTH,
+        .shift = R_ID_AA64ISAR0_AES_SHIFT, .sign = false, .min_value = 2,
+        .ni_value = 1, .name = "PMULL", .is_32bit = false,
+    },
+    {
+        .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH,
+        .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2,
+        .ni_value = 1, .name = "SHA512", .is_32bit = false,
+    },
+    {
+        .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_TS_LENGTH,
+        .shift = R_ID_AA64ISAR0_TS_SHIFT, .sign = false, .min_value = 2,
+        .ni_value = 1, .name = "FLAGM2", .is_32bit = false,
+    },
+    {
+        .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_DPB_LENGTH,
+        .shift = R_ID_AA64ISAR1_DPB_SHIFT, .sign = false, .min_value = 2,
+        .ni_value = 1, .name = "DCPODP", .is_32bit = false,
+    },
+    {
+        .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_LRCPC_LENGTH,
+        .shift = R_ID_AA64ISAR1_LRCPC_SHIFT, .sign = false, .min_value = 2,
+        .ni_value = 1, .name = "ILRCPC", .is_32bit = false,
+    },
+};
+
+static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
+                                 void *opaque, Error **errp)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    CPUFeatureInfo *feat = opaque;
+    int field_value = feat->sign ? sextract64(cpu->isar.regs[feat->reg],
+                                              feat->shift, feat->length) :
+                                   extract64(cpu->isar.regs[feat->reg],
+                                             feat->shift, feat->length);
+    bool value = field_value >= feat->min_value;
+
+    visit_type_bool(v, name, &value, errp);
+}
+
+static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name,
+                                 void *opaque, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    ARMCPU *cpu = ARM_CPU(obj);
+    ARMISARegisters *isar = &cpu->isar;
+    CPUFeatureInfo *feat = opaque;
+    Error *local_err = NULL;
+    bool value;
+
+    if (dev->realized) {
+        qdev_prop_set_after_realize(dev, name, errp);
+        return;
+    }
+
+    visit_type_bool(v, name, &value, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (value) {
+        isar->regs[feat->reg] = deposit64(isar->regs[feat->reg],
+                                          feat->shift, feat->length,
+                                          feat->min_value);
+    } else {
+        isar->regs[feat->reg] = deposit64(isar->regs[feat->reg],
+                                          feat->shift, feat->length,
+                                          feat->ni_value);
+    }
+}
+
+static void arm_cpu_register_feature_props(ARMCPU *cpu)
+{
+    int i;
+    int num = sizeof(cpu_features) / sizeof(cpu_features[i]);
+    ObjectProperty *op;
+    CPUARMState *env = &cpu->env;
+
+    for (i = 0; i < num; i++) {
+        if ((arm_feature(env, ARM_FEATURE_AARCH64) && cpu_features[i].is_32bit)
+            || (!arm_feature(env, ARM_FEATURE_AARCH64) &&
+                cpu_features[i].is_32bit)) {
+            continue;
+        }
+        op = object_property_find(OBJECT(cpu), cpu_features[i].name, NULL);
+        if (!op) {
+            error_report("register name %s", cpu_features[i].name);
+            object_property_add(OBJECT(cpu), cpu_features[i].name, "bool",
+                    arm_cpu_get_bit_prop,
+                    arm_cpu_set_bit_prop,
+                    NULL, &cpu_features[i]);
+        }
+    }
+}
+
 void arm_cpu_post_init(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
@@ -1271,6 +1613,7 @@ void arm_cpu_post_init(Object *obj)
         }
     }
 #endif
+    arm_cpu_register_feature_props(cpu);
 }
 
 static void arm_cpu_finalizefn(Object *obj)
-- 
2.18.4



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

* [RFC 4/9] target/arm: Allow ID registers to synchronize to KVM
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
                   ` (2 preceding siblings ...)
  2020-08-13 10:26 ` [RFC 3/9] target/arm: register CPU features for property Peng Liang
@ 2020-08-13 10:26 ` Peng Liang
  2020-08-13 10:26 ` [RFC 5/9] target/arm: introduce CPU feature dependency mechanism Peng Liang
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Peng Liang @ 2020-08-13 10:26 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, Peng Liang, pbonzini

There are 2 steps to synchronize the values of system registers from
CPU state to KVM:
1. write to the values of system registers from CPU state to
   (index,value) list by write_cpustate_to_list;
2. write the values in (index,value) list to KVM by
   write_list_to_kvmstate;

In step 1, the values of constant system registers are not allowed to
write to (index,value) list.  However, a constant system register is
CONSTANT for guest but not for QEMU, which means, QEMU can set/modify
the value of constant system registers that is different from phsical
registers when startup.  But if KVM is enabled, guest can not read the
values of the system registers which QEMU set unless they can be written
to (index,value) list.  And why not try to write to KVM if kvm_sync is
true?

At the moment we call write_cpustate_to_list, all ID registers are
contant, including ID_PFR1_EL1 and ID_AA64PFR0_EL1 because GIC has been
initialized.  Hence, let's give all ID registers a chance to write to
KVM.  If the write is successful, then write to (index,value) list.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 target/arm/helper.c  | 31 ++++++++++++++++++++-----------
 target/arm/kvm.c     | 38 ++++++++++++++++++++++++++++++++++++++
 target/arm/kvm_arm.h |  3 +++
 3 files changed, 61 insertions(+), 11 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 9208ec046c..1cac269ef1 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -34,6 +34,7 @@
 #include "arm_ldst.h"
 #include "exec/cpu_ldst.h"
 #endif
+#include "kvm_arm.h"
 
 #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
 
@@ -369,30 +370,38 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
             ok = false;
             continue;
         }
-        if (ri->type & ARM_CP_NO_RAW) {
+        /*
+         * (Op0, Op1, CRn, CRm, Op2) of ID registers is (3, 0, 0, crm, op2),
+         * where 1<=crm<8, 0<=op2<8.  Let's give ID registers a chance to
+         * synchronize to kvm.
+         */
+        if ((ri->type & ARM_CP_NO_RAW) && !(kvm_sync &&
+            ri->opc0 == 3 && ri->opc1 == 0 && ri->crn == 0 && ri->crm > 0)) {
             continue;
         }
 
         newval = read_raw_cp_reg(&cpu->env, ri);
         if (kvm_sync) {
-            /*
-             * Only sync if the previous list->cpustate sync succeeded.
-             * Rather than tracking the success/failure state for every
-             * item in the list, we just recheck "does the raw write we must
-             * have made in write_list_to_cpustate() read back OK" here.
-             */
-            uint64_t oldval = cpu->cpreg_values[i];
+            /* Only sync if we can sync to KVM successfully. */
+            uint64_t oldval;
+            uint64_t kvmval;
 
+            if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &oldval)) {
+                continue;
+            }
             if (oldval == newval) {
                 continue;
             }
 
-            write_raw_cp_reg(&cpu->env, ri, oldval);
-            if (read_raw_cp_reg(&cpu->env, ri) != oldval) {
+            if (kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &newval)) {
+                continue;
+            }
+            if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &kvmval) ||
+                kvmval != newval) {
                 continue;
             }
 
-            write_raw_cp_reg(&cpu->env, ri, newval);
+            kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &oldval);
         }
         cpu->cpreg_values[i] = newval;
     }
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 8bb7318378..6a40e7da61 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -490,6 +490,44 @@ out:
     return ret;
 }
 
+int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target)
+{
+    uint32_t v32;
+    int ret;
+
+    switch (regidx & KVM_REG_SIZE_MASK) {
+    case KVM_REG_SIZE_U32:
+        ret = kvm_get_one_reg(CPU(cpu), regidx, &v32);
+        if (ret == 0) {
+            *target = v32;
+        }
+        return ret;
+    case KVM_REG_SIZE_U64:
+        return kvm_get_one_reg(CPU(cpu), regidx, target);
+    default:
+        return -1;
+    }
+}
+
+int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source)
+{
+    uint32_t v32;
+
+    switch (regidx & KVM_REG_SIZE_MASK) {
+    case KVM_REG_SIZE_U32:
+        v32 = *source;
+        if (v32 != *source) {
+            error_report("the value of source is too large");
+            return -1;
+        }
+        return kvm_set_one_reg(CPU(cpu), regidx, &v32);
+    case KVM_REG_SIZE_U64:
+        return kvm_set_one_reg(CPU(cpu), regidx, source);
+    default:
+        return -1;
+    }
+}
+
 bool write_kvmstate_to_list(ARMCPU *cpu)
 {
     CPUState *cs = CPU(cpu);
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index adb38514bf..99035494ae 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -478,4 +478,7 @@ static inline const char *its_class_name(void)
     }
 }
 
+int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target);
+int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source);
+
 #endif
-- 
2.18.4



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

* [RFC 5/9] target/arm: introduce CPU feature dependency mechanism
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
                   ` (3 preceding siblings ...)
  2020-08-13 10:26 ` [RFC 4/9] target/arm: Allow ID registers to synchronize to KVM Peng Liang
@ 2020-08-13 10:26 ` Peng Liang
  2020-08-13 12:48   ` Andrew Jones
  2020-08-13 10:26 ` [RFC 6/9] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE Peng Liang
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Peng Liang @ 2020-08-13 10:26 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, Peng Liang, pbonzini

Some CPU features are dependent on other CPU features.  For example,
ID_AA64PFR0_EL1.FP field and ID_AA64PFR0_EL1.AdvSIMD must have the same
value, which means FP and ADVSIMD are dependent on each other, FPHP and
ADVSIMDHP are dependent on each other.

This commit introduces a mechanism for CPU feature dependency in
AArch64.  We build a directed graph from the CPU feature dependency
relationship, each edge from->to means the `to` CPU feature is dependent
on the `from` CPU feature.  And we will automatically enable/disable CPU
feature according to the directed graph.

For example, a, b, and c CPU features are in relationship a->b->c, which
means c is dependent on b and b is dependent on a.  If c is enabled by
user, then a and b is enabled automatically.  And if a is disabled by
user, then b and c is disabled automatically.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 target/arm/cpu.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 129 insertions(+)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 113cf4a9e7..4e67b8f22c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1418,6 +1418,103 @@ static struct CPUFeatureInfo cpu_features[] = {
     },
 };
 
+typedef struct CPUFeatureDep {
+    CPUFeatureInfo from, to;
+} CPUFeatureDep;
+
+static const CPUFeatureDep feature_dependencies[] = {
+    {
+        .from = FIELD_INFO(ID_AA64PFR0, FP, true, 0, 0xf, false),
+        .to = FIELD_INFO(ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false),
+    },
+    {
+        .from = FIELD_INFO(ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false),
+        .to = FIELD_INFO(ID_AA64PFR0, FP, true, 0, 0xf, false),
+    },
+    {
+        .from = {
+            .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH,
+            .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1,
+            .ni_value = 0, .name = "FPHP", .is_32bit = false,
+        },
+        .to = {
+            .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH,
+            .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1,
+            .ni_value = 0, .name = "ADVSIMDHP", .is_32bit = false,
+        },
+    },
+    {
+        .from = {
+            .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH,
+            .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1,
+            .ni_value = 0, .name = "ADVSIMDHP", .is_32bit = false,
+        },
+        .to = {
+            .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH,
+            .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1,
+            .ni_value = 0, .name = "FPHP", .is_32bit = false,
+        },
+    },
+    {
+
+        .from = FIELD_INFO(ID_AA64ISAR0, AES, false, 1, 0, false),
+        .to = {
+            .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_AES_LENGTH,
+            .shift = R_ID_AA64ISAR0_AES_SHIFT, .sign = false, .min_value = 2,
+            .ni_value = 1, .name = "PMULL", .is_32bit = false,
+        },
+    },
+    {
+
+        .from = FIELD_INFO(ID_AA64ISAR0, SHA2, false, 1, 0, false),
+        .to = {
+            .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH,
+            .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2,
+            .ni_value = 1, .name = "SHA512", .is_32bit = false,
+        },
+    },
+    {
+        .from = FIELD_INFO(ID_AA64ISAR1, LRCPC, false, 1, 0, false),
+        .to = {
+            .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_LRCPC_LENGTH,
+            .shift = R_ID_AA64ISAR1_LRCPC_SHIFT, .sign = false, .min_value = 2,
+            .ni_value = 1, .name = "ILRCPC", .is_32bit = false,
+        },
+    },
+    {
+        .from = FIELD_INFO(ID_AA64ISAR0, SM3, false, 1, 0, false),
+        .to = FIELD_INFO(ID_AA64ISAR0, SM4, false, 1, 0, false),
+    },
+    {
+        .from = FIELD_INFO(ID_AA64ISAR0, SM4, false, 1, 0, false),
+        .to = FIELD_INFO(ID_AA64ISAR0, SM3, false, 1, 0, false),
+    },
+    {
+        .from = FIELD_INFO(ID_AA64ISAR0, SHA1, false, 1, 0, false),
+        .to = FIELD_INFO(ID_AA64ISAR0, SHA2, false, 1, 0, false),
+    },
+    {
+        .from = FIELD_INFO(ID_AA64ISAR0, SHA1, false, 1, 0, false),
+        .to = FIELD_INFO(ID_AA64ISAR0, SHA3, false, 1, 0, false),
+    },
+    {
+        .from = FIELD_INFO(ID_AA64ISAR0, SHA3, false, 1, 0, false),
+        .to = {
+            .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH,
+            .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2,
+            .ni_value = 1, .name = "SHA512", .is_32bit = false,
+        },
+    },
+    {
+        .from = {
+            .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH,
+            .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2,
+            .ni_value = 1, .name = "SHA512", .is_32bit = false,
+        },
+        .to = FIELD_INFO(ID_AA64ISAR0, SHA3, false, 1, 0, false),
+    },
+};
+
 static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
                                  void *opaque, Error **errp)
 {
@@ -1454,13 +1551,45 @@ static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name,
     }
 
     if (value) {
+        if (object_property_get_bool(obj, feat->name, NULL)) {
+            return;
+        }
         isar->regs[feat->reg] = deposit64(isar->regs[feat->reg],
                                           feat->shift, feat->length,
                                           feat->min_value);
+        /* Auto enable the features which current feature is dependent on. */
+        for (int i = 0; i < ARRAY_SIZE(feature_dependencies); ++i) {
+            const CPUFeatureDep *d = &feature_dependencies[i];
+            if (strcmp(d->to.name, feat->name) != 0) {
+                continue;
+            }
+
+            object_property_set_bool(obj, d->from.name, true, &local_err);
+            if (local_err) {
+                error_propagate(errp, local_err);
+                return;
+            }
+        }
     } else {
+        if (!object_property_get_bool(obj, feat->name, NULL)) {
+            return;
+        }
         isar->regs[feat->reg] = deposit64(isar->regs[feat->reg],
                                           feat->shift, feat->length,
                                           feat->ni_value);
+        /* Auto disable the features which are dependent on current feature. */
+        for (int i = 0; i < ARRAY_SIZE(feature_dependencies); ++i) {
+            const CPUFeatureDep *d = &feature_dependencies[i];
+            if (strcmp(d->from.name, feat->name) != 0) {
+                continue;
+            }
+
+            object_property_set_bool(obj, d->to.name, false, &local_err);
+            if (local_err) {
+                error_propagate(errp, local_err);
+                return;
+            }
+        }
     }
 }
 
-- 
2.18.4



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

* [RFC 6/9] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
                   ` (4 preceding siblings ...)
  2020-08-13 10:26 ` [RFC 5/9] target/arm: introduce CPU feature dependency mechanism Peng Liang
@ 2020-08-13 10:26 ` Peng Liang
  2020-08-13 11:00   ` Cornelia Huck
  2020-08-13 10:26 ` [RFC 7/9] target/arm: Add CPU features to query-cpu-model-expansion Peng Liang
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Peng Liang @ 2020-08-13 10:26 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, Peng Liang, pbonzini

Introduce KVM_CAP_ARM_CPU_FEATURE to check whether KVM supports to set
CPU features in ARM.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 linux-headers/linux/kvm.h |  1 +
 target/arm/cpu.c          |  5 +++++
 target/arm/kvm64.c        | 14 ++++++++++++++
 target/arm/kvm_arm.h      |  7 +++++++
 4 files changed, 27 insertions(+)

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index a28c366737..0b83d2b4bb 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -1031,6 +1031,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_PPC_SECURE_GUEST 181
 #define KVM_CAP_HALT_POLL 182
 #define KVM_CAP_ASYNC_PF_INT 183
+#define KVM_CAP_ARM_CPU_FEATURE 187
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 4e67b8f22c..3fc54cb3a4 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1539,6 +1539,11 @@ static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name,
     Error *local_err = NULL;
     bool value;
 
+    if (!kvm_arm_cpu_feature_supported()) {
+        warn_report("KVM doesn't support to set CPU feature in arm.  "
+                    "Setting to `%s` is ignored.", name);
+        return;
+    }
     if (dev->realized) {
         qdev_prop_set_after_realize(dev, name, errp);
         return;
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index be2d0cda0d..e7470477d5 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -664,6 +664,20 @@ bool kvm_arm_sve_supported(void)
     return kvm_check_extension(kvm_state, KVM_CAP_ARM_SVE);
 }
 
+bool kvm_arm_cpu_feature_supported(void)
+{
+    static bool cpu_feature_initialized;
+    static bool cpu_feature_supported;
+
+    if (!cpu_feature_initialized) {
+        cpu_feature_supported = kvm_check_extension(kvm_state,
+                                                    KVM_CAP_ARM_CPU_FEATURE);
+        cpu_feature_initialized = true;
+    }
+
+    return cpu_feature_supported;
+}
+
 QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
 
 void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map)
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 99035494ae..c2481ce464 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -290,6 +290,13 @@ bool kvm_arm_pmu_supported(void);
  */
 bool kvm_arm_sve_supported(void);
 
+/**
+ * kvm_arm_cpu_feature_supported:
+ *
+ * Returns true if KVM can set CPU features and false otherwise.
+ */
+bool kvm_arm_cpu_feature_supported(void);
+
 /**
  * kvm_arm_get_max_vm_ipa_size:
  * @ms: Machine state handle
-- 
2.18.4



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

* [RFC 7/9] target/arm: Add CPU features to query-cpu-model-expansion
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
                   ` (5 preceding siblings ...)
  2020-08-13 10:26 ` [RFC 6/9] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE Peng Liang
@ 2020-08-13 10:26 ` Peng Liang
  2020-08-13 12:56   ` Andrew Jones
  2020-08-13 10:26 ` [RFC 8/9] target/arm: Update ID fields Peng Liang
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Peng Liang @ 2020-08-13 10:26 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, Peng Liang, pbonzini

Add CPU features to the result of query-cpu-model-expansion so that
other applications (such as libvirt) can know the supported CPU
features.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 target/arm/cpu.c     | 41 +++++++++++++++++++++++++++++++++++++++++
 target/arm/cpu.h     |  2 ++
 target/arm/monitor.c |  2 ++
 3 files changed, 45 insertions(+)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 3fc54cb3a4..0f620e8afe 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -25,6 +25,8 @@
 #include "qemu/module.h"
 #include "qapi/error.h"
 #include "qapi/visitor.h"
+#include "qapi/qmp/qdict.h"
+#include "qom/qom-qobject.h"
 #include "cpu.h"
 #include "internals.h"
 #include "exec/exec-all.h"
@@ -1515,6 +1517,45 @@ static const CPUFeatureDep feature_dependencies[] = {
     },
 };
 
+static char *strtolower(char *src)
+{
+    char *start = src;
+
+    for (; *src; ++src) {
+        *src = tolower(*src);
+    }
+
+    return start;
+}
+
+void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features)
+{
+    Object *obj = OBJECT(cpu);
+    const char *name;
+    ObjectProperty *prop;
+    bool is_32bit = !arm_feature(&cpu->env, ARM_FEATURE_AARCH64);
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(cpu_features); ++i) {
+        if (is_32bit != cpu_features[i].is_32bit) {
+            continue;
+        }
+
+        name = cpu_features[i].name;
+        prop = object_property_find(obj, name, NULL);
+        if (prop) {
+            QObject *value;
+            g_autofree char *tmp;
+
+            assert(prop->get);
+            value = object_property_get_qobject(obj, name, &error_abort);
+            tmp = strtolower(g_strdup(name));
+
+            qdict_put_obj(features, tmp, value);
+        }
+    }
+}
+
 static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
                                  void *opaque, Error **errp)
 {
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 5d8074d03b..da68b7f8f4 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3933,4 +3933,6 @@ static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
 #define cpu_isar_feature(name, cpu) \
     ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); })
 
+void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features);
+
 #endif
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index ba6e01abd0..f8eb29efec 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -225,6 +225,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
         }
     }
 
+    arm_cpu_features_to_dict(ARM_CPU(obj), qdict_out);
+
     if (!qdict_size(qdict_out)) {
         qobject_unref(qdict_out);
     } else {
-- 
2.18.4



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

* [RFC 8/9] target/arm: Update ID fields
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
                   ` (6 preceding siblings ...)
  2020-08-13 10:26 ` [RFC 7/9] target/arm: Add CPU features to query-cpu-model-expansion Peng Liang
@ 2020-08-13 10:26 ` Peng Liang
  2020-08-13 10:26 ` [RFC 9/9] target/arm: Add more CPU features Peng Liang
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Peng Liang @ 2020-08-13 10:26 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, Peng Liang, pbonzini

Update definitions for ID fields, up to ARMv8.6.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 target/arm/cpu.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index da68b7f8f4..7a46d223bc 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1773,6 +1773,8 @@ FIELD(ID_ISAR6, DP, 4, 4)
 FIELD(ID_ISAR6, FHM, 8, 4)
 FIELD(ID_ISAR6, SB, 12, 4)
 FIELD(ID_ISAR6, SPECRES, 16, 4)
+FIELD(ID_ISAR6, BF16, 20, 4)
+FIELD(ID_ISAR6, I8MM, 24, 4)
 
 FIELD(ID_MMFR3, CMAINTVA, 0, 4)
 FIELD(ID_MMFR3, CMAINTSW, 4, 4)
@@ -1818,6 +1820,9 @@ FIELD(ID_AA64ISAR1, GPI, 28, 4)
 FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
 FIELD(ID_AA64ISAR1, SB, 36, 4)
 FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
+FIELD(ID_AA64ISAR1, BF16, 44, 4)
+FIELD(ID_AA64ISAR1, DGH, 48, 4)
+FIELD(ID_AA64ISAR1, I8MM, 52, 4)
 
 FIELD(ID_AA64PFR0, EL0, 0, 4)
 FIELD(ID_AA64PFR0, EL1, 4, 4)
@@ -1828,11 +1833,18 @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
 FIELD(ID_AA64PFR0, GIC, 24, 4)
 FIELD(ID_AA64PFR0, RAS, 28, 4)
 FIELD(ID_AA64PFR0, SVE, 32, 4)
+FIELD(ID_AA64PFR0, SEL2, 36, 4)
+FIELD(ID_AA64PFR0, MPAM, 40, 4)
+FIELD(ID_AA64PFR0, AMU, 44, 4)
+FIELD(ID_AA64PFR0, DIT, 44, 4)
+FIELD(ID_AA64PFR0, CSV2, 56, 4)
+FIELD(ID_AA64PFR0, CSV3, 60, 4)
 
 FIELD(ID_AA64PFR1, BT, 0, 4)
 FIELD(ID_AA64PFR1, SBSS, 4, 4)
 FIELD(ID_AA64PFR1, MTE, 8, 4)
 FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
 
 FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
 FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
@@ -1846,6 +1858,8 @@ FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
 FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
 FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
 FIELD(ID_AA64MMFR0, EXS, 44, 4)
+FIELD(ID_AA64MMFR0, FGT, 56, 4)
+FIELD(ID_AA64MMFR0, ECV, 60, 4)
 
 FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
 FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
@@ -1855,6 +1869,8 @@ FIELD(ID_AA64MMFR1, LO, 16, 4)
 FIELD(ID_AA64MMFR1, PAN, 20, 4)
 FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
 FIELD(ID_AA64MMFR1, XNX, 28, 4)
+FIELD(ID_AA64MMFR1, TWED, 32, 4)
+FIELD(ID_AA64MMFR1, ETS, 36, 4)
 
 FIELD(ID_AA64MMFR2, CNP, 0, 4)
 FIELD(ID_AA64MMFR2, UAO, 4, 4)
@@ -1881,6 +1897,7 @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
 FIELD(ID_AA64DFR0, PMSVER, 32, 4)
 FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
 FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
+FIELD(ID_AA64DFR0, MUPMU, 48, 4)
 
 FIELD(ID_DFR0, COPDBG, 0, 4)
 FIELD(ID_DFR0, COPSDBG, 4, 4)
-- 
2.18.4



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

* [RFC 9/9] target/arm: Add more CPU features
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
                   ` (7 preceding siblings ...)
  2020-08-13 10:26 ` [RFC 8/9] target/arm: Update ID fields Peng Liang
@ 2020-08-13 10:26 ` Peng Liang
  2020-08-13 14:10 ` [RFC 0/9] Support disable/enable CPU features for AArch64 Andrew Jones
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Peng Liang @ 2020-08-13 10:26 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, Peng Liang, pbonzini

Add i8mm, bf16, and dgh CPU features for AArch64.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 target/arm/cpu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 0f620e8afe..9e2ddbc3ed 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1319,6 +1319,9 @@ static struct CPUFeatureInfo cpu_features[] = {
     FIELD_INFO(ID_AA64ISAR1, FRINTTS, false, 1, 0, false),
     FIELD_INFO(ID_AA64ISAR1, SB, false, 1, 0, false),
     FIELD_INFO(ID_AA64ISAR1, SPECRES, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, I8MM, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, BF16, false, 1, 0, false),
+    FIELD_INFO(ID_AA64ISAR1, DGH, false, 1, 0, false),
 
     FIELD_INFO(ID_AA64PFR0, EL0, false, 1, 0, false),
     FIELD_INFO(ID_AA64PFR0, EL1, false, 1, 0, false),
-- 
2.18.4



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

* Re: [RFC 1/9] target/arm: convert isar regs to array
  2020-08-13 10:26 ` [RFC 1/9] target/arm: convert isar regs to array Peng Liang
@ 2020-08-13 10:42   ` Philippe Mathieu-Daudé
  2020-08-13 16:11     ` Richard Henderson
  0 siblings, 1 reply; 28+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-08-13 10:42 UTC (permalink / raw)
  To: Peng Liang, qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, pbonzini

On 8/13/20 12:26 PM, Peng Liang wrote:
> The isar in ARMCPU is a struct, each field of which represents an ID
> register.  It's not convenient for us to support CPU feature in AArch64.
> So let's change it to an array first and add an enum as the index of the
> array for convenience.  Since we will never access high 32-bits of ID
> registers in AArch32, it's harmless to change the ID registers in
> AArch32 to 64-bits.
> 
> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> Signed-off-by: Peng Liang <liangpeng10@huawei.com>
> ---
>  hw/intc/armv7m_nvic.c  |  48 ++++----
>  target/arm/cpu.c       | 232 +++++++++++++++++++-------------------
>  target/arm/cpu.h       | 226 +++++++++++++++++++------------------
>  target/arm/cpu64.c     | 170 ++++++++++++++--------------
>  target/arm/cpu_tcg.c   | 250 +++++++++++++++++++++--------------------
>  target/arm/helper.c    |  54 ++++-----
>  target/arm/internals.h |  15 +--
>  target/arm/kvm64.c     |  72 ++++++------
>  8 files changed, 541 insertions(+), 526 deletions(-)

Please consider using scripts/git.orderfile.

[...]
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 9e8ed423ea..5d8074d03b 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -67,6 +67,37 @@
>  #define ARMV7M_EXCP_PENDSV  14
>  #define ARMV7M_EXCP_SYSTICK 15
>  
> +typedef enum CPUIDReg {
> +    MIDR_EL1,
> +    ID_ISAR0,
> +    ID_ISAR1,
> +    ID_ISAR2,
> +    ID_ISAR3,
> +    ID_ISAR4,
> +    ID_ISAR5,
> +    ID_ISAR6,
> +    ID_MMFR0,
> +    ID_MMFR1,
> +    ID_MMFR2,
> +    ID_MMFR3,
> +    ID_MMFR4,
> +    ID_AA64ISAR0,
> +    ID_AA64ISAR1,
> +    ID_AA64PFR0,
> +    ID_AA64PFR1,
> +    ID_AA64MMFR0,
> +    ID_AA64MMFR1,
> +    ID_AA64MMFR2,
> +    ID_AA64DFR0,
> +    ID_AA64DFR1,
> +    ID_DFR0,
> +    MVFR0,
> +    MVFR1,
> +    MVFR2,
> +    DBGDIDR,
> +    ID_MAX,

(nitpicking, drop the last comma).

> +} CPUIDReg;
> +
>  /* For M profile, some registers are banked secure vs non-secure;
>   * these are represented as a 2-element array where the first element
>   * is the non-secure copy and the second is the secure copy.
> @@ -890,32 +921,7 @@ struct ARMCPU {
>       * 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;
> -        uint32_t id_mmfr3;
> -        uint32_t id_mmfr4;
> -        uint32_t mvfr0;
> -        uint32_t mvfr1;
> -        uint32_t mvfr2;
> -        uint32_t id_dfr0;
> -        uint32_t dbgdidr;
> -        uint64_t id_aa64isar0;
> -        uint64_t id_aa64isar1;
> -        uint64_t id_aa64pfr0;
> -        uint64_t id_aa64pfr1;
> -        uint64_t id_aa64mmfr0;
> -        uint64_t id_aa64mmfr1;
> -        uint64_t id_aa64mmfr2;
> -        uint64_t id_aa64dfr0;
> -        uint64_t id_aa64dfr1;
> +        uint64_t regs[ID_MAX];
>      } isar;

Why not simply this?

       uint64_t isar[ID_MAX];

>      uint64_t midr;
>      uint32_t revidr;
[...]



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

* Re: [RFC 6/9] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE
  2020-08-13 10:26 ` [RFC 6/9] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE Peng Liang
@ 2020-08-13 11:00   ` Cornelia Huck
  2020-08-15  2:19     ` Peng Liang
  0 siblings, 1 reply; 28+ messages in thread
From: Cornelia Huck @ 2020-08-13 11:00 UTC (permalink / raw)
  To: Peng Liang
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, qemu-devel,
	xiexiangyou, qemu-arm, pbonzini

On Thu, 13 Aug 2020 18:26:54 +0800
Peng Liang <liangpeng10@huawei.com> wrote:

> Introduce KVM_CAP_ARM_CPU_FEATURE to check whether KVM supports to set
> CPU features in ARM.
> 
> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> Signed-off-by: Peng Liang <liangpeng10@huawei.com>
> ---
>  linux-headers/linux/kvm.h |  1 +
>  target/arm/cpu.c          |  5 +++++
>  target/arm/kvm64.c        | 14 ++++++++++++++
>  target/arm/kvm_arm.h      |  7 +++++++
>  4 files changed, 27 insertions(+)
> 
> diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
> index a28c366737..0b83d2b4bb 100644
> --- a/linux-headers/linux/kvm.h
> +++ b/linux-headers/linux/kvm.h
> @@ -1031,6 +1031,7 @@ struct kvm_ppc_resize_hpt {
>  #define KVM_CAP_PPC_SECURE_GUEST 181
>  #define KVM_CAP_HALT_POLL 182
>  #define KVM_CAP_ASYNC_PF_INT 183
> +#define KVM_CAP_ARM_CPU_FEATURE 187
>  
>  #ifdef KVM_CAP_IRQ_ROUTING

Please split out this header update into a separate patch so that it
can be replaced by a proper headers update once the kernel code has been
included.



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

* Re: [RFC 2/9] target/arm: parse cpu feature related options
  2020-08-13 10:26 ` [RFC 2/9] target/arm: parse cpu feature related options Peng Liang
@ 2020-08-13 12:21   ` Andrew Jones
  2020-08-15  2:19     ` Peng Liang
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Jones @ 2020-08-13 12:21 UTC (permalink / raw)
  To: Peng Liang
  Cc: peter.maydell, zhang.zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou, qemu-arm, pbonzini

On Thu, Aug 13, 2020 at 06:26:50PM +0800, Peng Liang wrote:
> The implementation of CPUClass::parse_features only supports CPU
> features in "feature=value" format.  However, libvirt maybe send us a
> CPU feature string in "+feature/-feature" format. 

Why would libvirt do that? If we have a boolean feature, then I'd think
libvirt should be capable of sending feature=on/off just as easily as a
+/-feature. Indeed libvirt seems to do the right thing with all the
CPU features we already have: pmu, sve*, ...

Thanks,
drew



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

* Re: [RFC 3/9] target/arm: register CPU features for property
  2020-08-13 10:26 ` [RFC 3/9] target/arm: register CPU features for property Peng Liang
@ 2020-08-13 12:34   ` Andrew Jones
  0 siblings, 0 replies; 28+ messages in thread
From: Andrew Jones @ 2020-08-13 12:34 UTC (permalink / raw)
  To: Peng Liang
  Cc: peter.maydell, zhang.zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou, qemu-arm, pbonzini

On Thu, Aug 13, 2020 at 06:26:51PM +0800, Peng Liang wrote:
> The Arm architecture specifies a number of ID registers that are
> characterized as comprising a set of 4-bit ID fields. Each ID field
> identifies the presence, and possibly the level of support for, a
> particular feature in an implementation of the architecture. [1]
> 
> For most of the ID fields, there is a minimum presence value, equal to
> or higher than which means the corresponding CPU feature is implemented.
> Hence, we can use the minimum presence value to determine whether a CPU
> feature is enabled and enable a CPU feature.
> 
> To disable a CPU feature, setting the corresponding ID field to 0x0/0xf
> (for unsigned/signed field) seems as a good idea.  However, it maybe
> lead to some problems.  For example,  ID_AA64PFR0_EL1.FP is a signed ID
> field. ID_AA64PFR0_EL1.FP == 0x0 represents the implementation of FP
> (floating-point) and ID_AA64PFR0_EL1.FP == 0x1 represents the
> implementation of FPHP (half-precision floating-point).  If
> ID_AA64PFR0_EL1.FP is set to 0xf when FPHP is disabled (which is also
> disable FP), guest kernel maybe stuck.  Hence, we add a ni_value (means
> not-implemented value) to disable a CPU feature safely.
> 
> [1] D13.1.3 Principles of the ID scheme for fields in ID registers in
>     DDI.0487
> 
> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> Signed-off-by: Peng Liang <liangpeng10@huawei.com>
> ---
>  target/arm/cpu.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 343 insertions(+)
> 
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index 79d7a6b45c..113cf4a9e7 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -1146,6 +1146,348 @@ unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
>        NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1;
>  }
>  
> +/**
> + * CPUFeatureInfo:
> + * @reg: The ID register where the ID field is in.
> + * @name: The name of the CPU feature.
> + * @length: The bit length of the ID field.
> + * @shift: The bit shift of the ID field in the ID register.
> + * @min_value: The minimum value equal to or larger than which means the CPU
> + *   feature is implemented.
> + * @ni_value: Not-implemented value. It will be set to the ID field when
> + *   disabling the CPU feature.  Usually, it's min_value - 1.
> + * @sign: Whether the ID field is signed.
> + * @is_32bit: Whether the CPU feature is for 32-bit.
> + *
> + * In ARM, a CPU feature is described by an ID field, which is a 4-bit field in
> + * an ID register.
> + */
> +typedef struct CPUFeatureInfo {
> +    CPUIDReg reg;
> +    const char *name;
> +    int length;
> +    int shift;
> +    int min_value;
> +    int ni_value;
> +    bool sign;
> +    bool is_32bit;
> +} CPUFeatureInfo;
> +
> +#define FIELD_INFO(id_reg, field, s, min_val, ni_val, is32bit) { \
> +    .reg = id_reg, \
> +    .length = R_ ## id_reg ## _ ## field ## _LENGTH, \
> +    .shift = R_ ## id_reg ## _ ## field ## _SHIFT, \
> +    .sign = s, \
> +    .min_value = min_val, \
> +    .ni_value = ni_val, \
> +    .name = #field, \
> +    .is_32bit = is32bit, \
> +}
> +
> +static struct CPUFeatureInfo cpu_features[] = {
> +    FIELD_INFO(ID_ISAR0, SWAP, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR0, BITCOUNT, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR0, BITFIELD, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR0, CMPBRANCH, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR0, COPROC, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR0, DEBUG, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR0, DIVIDE, false, 1, 0, true),
> +
> +    FIELD_INFO(ID_ISAR1, ENDIAN, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR1, EXCEPT, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR1, EXCEPT_AR, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR1, EXTEND, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR1, IFTHEN, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR1, IMMEDIATE, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR1, INTERWORK, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR1, JAZELLE, false, 1, 0, true),
> +
> +    FIELD_INFO(ID_ISAR2, LOADSTORE, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR2, MEMHINT, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR2, MULTIACCESSINT, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR2, MULT, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR2, MULTS, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR2, MULTU, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR2, PSR_AR, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR2, REVERSAL, false, 1, 0, true),
> +
> +    FIELD_INFO(ID_ISAR3, SATURATE, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR3, SIMD, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR3, SVC, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR3, SYNCHPRIM, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR3, TABBRANCH, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR3, T32COPY, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR3, TRUENOP, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR3, T32EE, false, 1, 0, true),
> +
> +    FIELD_INFO(ID_ISAR4, UNPRIV, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR4, WITHSHIFTS, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR4, WRITEBACK, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR4, SMC, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR4, BARRIER, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR4, SYNCHPRIM_FRAC, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR4, PSR_M, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR4, SWP_FRAC, false, 1, 0, true),
> +
> +    FIELD_INFO(ID_ISAR5, SEVL, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR5, AES, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR5, SHA1, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR5, SHA2, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR5, CRC32, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR5, RDM, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR5, VCMA, false, 1, 0, true),
> +
> +    FIELD_INFO(ID_ISAR6, JSCVT, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR6, DP, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR6, FHM, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR6, SB, false, 1, 0, true),
> +    FIELD_INFO(ID_ISAR6, SPECRES, false, 1, 0, true),
> +
> +    FIELD_INFO(ID_MMFR3, CMAINTVA, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR3, CMAINTSW, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR3, BPMAINT, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR3, MAINTBCST, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR3, PAN, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR3, COHWALK, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR3, CMEMSZ, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR3, SUPERSEC, false, 1, 0, true),
> +
> +    FIELD_INFO(ID_MMFR4, SPECSEI, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR4, AC2, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR4, XNX, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR4, CNP, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR4, HPDS, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR4, LSM, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR4, CCIDX, false, 1, 0, true),
> +    FIELD_INFO(ID_MMFR4, EVT, false, 1, 0, true),
> +
> +    FIELD_INFO(MVFR0, SIMDREG, false, 1, 0, true),
> +    FIELD_INFO(MVFR0, FPSP, false, 1, 0, true),
> +    FIELD_INFO(MVFR0, FPDP, false, 1, 0, true),
> +    FIELD_INFO(MVFR0, FPTRAP, false, 1, 0, true),
> +    FIELD_INFO(MVFR0, FPDIVIDE, false, 1, 0, true),
> +    FIELD_INFO(MVFR0, FPSQRT, false, 1, 0, true),
> +    FIELD_INFO(MVFR0, FPSHVEC, false, 1, 0, true),
> +    FIELD_INFO(MVFR0, FPROUND, false, 1, 0, true),
> +
> +    FIELD_INFO(MVFR1, FPFTZ, false, 1, 0, true),
> +    FIELD_INFO(MVFR1, FPDNAN, false, 1, 0, true),
> +    FIELD_INFO(MVFR1, SIMDLS, false, 1, 0, true),
> +    FIELD_INFO(MVFR1, SIMDINT, false, 1, 0, true),
> +    FIELD_INFO(MVFR1, SIMDSP, false, 1, 0, true),
> +    FIELD_INFO(MVFR1, SIMDHP, false, 1, 0, true),
> +    FIELD_INFO(MVFR1, FPHP, false, 1, 0, true),
> +    FIELD_INFO(MVFR1, SIMDFMAC, false, 1, 0, true),
> +
> +    FIELD_INFO(MVFR2, SIMDMISC, false, 1, 0, true),
> +    FIELD_INFO(MVFR2, FPMISC, false, 1, 0, true),
> +
> +    FIELD_INFO(ID_DFR0, COPDBG, false, 1, 0, true),
> +    FIELD_INFO(ID_DFR0, COPSDBG, false, 1, 0, true),
> +    FIELD_INFO(ID_DFR0, MMAPDBG, false, 1, 0, true),
> +    FIELD_INFO(ID_DFR0, COPTRC, false, 1, 0, true),
> +    FIELD_INFO(ID_DFR0, MMAPTRC, false, 1, 0, true),
> +    FIELD_INFO(ID_DFR0, MPROFDBG, false, 1, 0, true),
> +    FIELD_INFO(ID_DFR0, PERFMON, false, 1, 0, true),
> +    FIELD_INFO(ID_DFR0, TRACEFILT, false, 1, 0, true),
> +
> +    FIELD_INFO(ID_AA64ISAR0, AES, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, SHA1, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, SHA2, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, CRC32, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, ATOMIC, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, RDM, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, SHA3, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, SM3, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, SM4, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, DP, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, FHM, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, TS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, TLB, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR0, RNDR, false, 1, 0, false),
> +
> +    FIELD_INFO(ID_AA64ISAR1, DPB, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR1, APA, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR1, API, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR1, JSCVT, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR1, FCMA, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR1, LRCPC, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR1, GPA, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR1, GPI, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR1, FRINTTS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR1, SB, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64ISAR1, SPECRES, false, 1, 0, false),
> +
> +    FIELD_INFO(ID_AA64PFR0, EL0, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64PFR0, EL1, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64PFR0, EL2, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64PFR0, EL3, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64PFR0, FP, true, 0, 0xf, false),
> +    FIELD_INFO(ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false),
> +    FIELD_INFO(ID_AA64PFR0, GIC, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64PFR0, RAS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64PFR0, SVE, false, 1, 0, false),
> +
> +    FIELD_INFO(ID_AA64PFR1, BT, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64PFR1, SBSS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64PFR1, MTE, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64PFR1, RAS_FRAC, false, 1, 0, false),
> +
> +    FIELD_INFO(ID_AA64MMFR0, PARANGE, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR0, ASIDBITS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR0, BIGEND, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR0, SNSMEM, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR0, BIGENDEL0, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR0, TGRAN16, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR0, TGRAN64, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR0, TGRAN4, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR0, TGRAN16_2, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR0, TGRAN64_2, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR0, TGRAN4_2, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR0, EXS, false, 1, 0, false),
> +
> +    FIELD_INFO(ID_AA64MMFR1, HAFDBS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR1, VMIDBITS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR1, VH, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR1, HPDS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR1, LO, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR1, PAN, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR1, SPECSEI, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR1, XNX, false, 1, 0, false),
> +
> +    FIELD_INFO(ID_AA64MMFR2, CNP, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, UAO, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, LSM, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, IESB, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, VARANGE, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, CCIDX, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, NV, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, ST, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, AT, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, IDS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, FWB, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, TTL, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, BBM, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, EVT, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64MMFR2, E0PD, false, 1, 0, false),
> +
> +    FIELD_INFO(ID_AA64DFR0, DEBUGVER, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64DFR0, TRACEVER, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64DFR0, PMUVER, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64DFR0, BRPS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64DFR0, WRPS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64DFR0, CTX_CMPS, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64DFR0, PMSVER, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64DFR0, DOUBLELOCK, false, 1, 0, false),
> +    FIELD_INFO(ID_AA64DFR0, TRACEFILT, false, 1, 0, false),
> +
> +    {
> +        .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH,
> +        .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1,
> +        .ni_value = 0, .name = "FPHP", .is_32bit = false,
> +    },
> +    {
> +        .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH,
> +        .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1,
> +        .ni_value = 0, .name = "ADVSIMDHP", .is_32bit = false,
> +    },
> +    {
> +        .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_AES_LENGTH,
> +        .shift = R_ID_AA64ISAR0_AES_SHIFT, .sign = false, .min_value = 2,
> +        .ni_value = 1, .name = "PMULL", .is_32bit = false,
> +    },
> +    {
> +        .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH,
> +        .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2,
> +        .ni_value = 1, .name = "SHA512", .is_32bit = false,
> +    },
> +    {
> +        .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_TS_LENGTH,
> +        .shift = R_ID_AA64ISAR0_TS_SHIFT, .sign = false, .min_value = 2,
> +        .ni_value = 1, .name = "FLAGM2", .is_32bit = false,
> +    },
> +    {
> +        .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_DPB_LENGTH,
> +        .shift = R_ID_AA64ISAR1_DPB_SHIFT, .sign = false, .min_value = 2,
> +        .ni_value = 1, .name = "DCPODP", .is_32bit = false,
> +    },
> +    {
> +        .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_LRCPC_LENGTH,
> +        .shift = R_ID_AA64ISAR1_LRCPC_SHIFT, .sign = false, .min_value = 2,
> +        .ni_value = 1, .name = "ILRCPC", .is_32bit = false,
> +    },
> +};
> +
> +static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
> +                                 void *opaque, Error **errp)
> +{
> +    ARMCPU *cpu = ARM_CPU(obj);
> +    CPUFeatureInfo *feat = opaque;
> +    int field_value = feat->sign ? sextract64(cpu->isar.regs[feat->reg],
> +                                              feat->shift, feat->length) :
> +                                   extract64(cpu->isar.regs[feat->reg],
> +                                             feat->shift, feat->length);
> +    bool value = field_value >= feat->min_value;
> +
> +    visit_type_bool(v, name, &value, errp);
> +}
> +
> +static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name,
> +                                 void *opaque, Error **errp)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +    ARMCPU *cpu = ARM_CPU(obj);
> +    ARMISARegisters *isar = &cpu->isar;
> +    CPUFeatureInfo *feat = opaque;
> +    Error *local_err = NULL;
> +    bool value;
> +
> +    if (dev->realized) {
> +        qdev_prop_set_after_realize(dev, name, errp);
> +        return;
> +    }
> +
> +    visit_type_bool(v, name, &value, &local_err);
> +    if (local_err) {
> +        error_propagate(errp, local_err);
> +        return;
> +    }
> +
> +    if (value) {
> +        isar->regs[feat->reg] = deposit64(isar->regs[feat->reg],
> +                                          feat->shift, feat->length,
> +                                          feat->min_value);
> +    } else {
> +        isar->regs[feat->reg] = deposit64(isar->regs[feat->reg],
> +                                          feat->shift, feat->length,
> +                                          feat->ni_value);
> +    }
> +}
> +
> +static void arm_cpu_register_feature_props(ARMCPU *cpu)
> +{
> +    int i;
> +    int num = sizeof(cpu_features) / sizeof(cpu_features[i]);
> +    ObjectProperty *op;
> +    CPUARMState *env = &cpu->env;
> +
> +    for (i = 0; i < num; i++) {
> +        if ((arm_feature(env, ARM_FEATURE_AARCH64) && cpu_features[i].is_32bit)
> +            || (!arm_feature(env, ARM_FEATURE_AARCH64) &&
> +                cpu_features[i].is_32bit)) {
> +            continue;
> +        }
> +        op = object_property_find(OBJECT(cpu), cpu_features[i].name, NULL);
> +        if (!op) {
> +            error_report("register name %s", cpu_features[i].name);
> +            object_property_add(OBJECT(cpu), cpu_features[i].name, "bool",
> +                    arm_cpu_get_bit_prop,
> +                    arm_cpu_set_bit_prop,
> +                    NULL, &cpu_features[i]);

So we're adding properties for every CPU feature? How many of these make
sense for the user to change? What happens when a user selects an invalid
combination?

Thanks,
drew

> +        }
> +    }
> +}
> +
>  void arm_cpu_post_init(Object *obj)
>  {
>      ARMCPU *cpu = ARM_CPU(obj);
> @@ -1271,6 +1613,7 @@ void arm_cpu_post_init(Object *obj)
>          }
>      }
>  #endif
> +    arm_cpu_register_feature_props(cpu);
>  }
>  
>  static void arm_cpu_finalizefn(Object *obj)
> -- 
> 2.18.4
> 



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

* Re: [RFC 5/9] target/arm: introduce CPU feature dependency mechanism
  2020-08-13 10:26 ` [RFC 5/9] target/arm: introduce CPU feature dependency mechanism Peng Liang
@ 2020-08-13 12:48   ` Andrew Jones
  2020-08-15  2:19     ` Peng Liang
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Jones @ 2020-08-13 12:48 UTC (permalink / raw)
  To: Peng Liang
  Cc: peter.maydell, zhang.zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou, qemu-arm, pbonzini

On Thu, Aug 13, 2020 at 06:26:53PM +0800, Peng Liang wrote:
> Some CPU features are dependent on other CPU features.  For example,
> ID_AA64PFR0_EL1.FP field and ID_AA64PFR0_EL1.AdvSIMD must have the same
> value, which means FP and ADVSIMD are dependent on each other, FPHP and
> ADVSIMDHP are dependent on each other.
> 
> This commit introduces a mechanism for CPU feature dependency in
> AArch64.  We build a directed graph from the CPU feature dependency
> relationship, each edge from->to means the `to` CPU feature is dependent
> on the `from` CPU feature.  And we will automatically enable/disable CPU
> feature according to the directed graph.
> 
> For example, a, b, and c CPU features are in relationship a->b->c, which
> means c is dependent on b and b is dependent on a.  If c is enabled by
> user, then a and b is enabled automatically.  And if a is disabled by
> user, then b and c is disabled automatically.

And what if a is mutually exclusive with b? I.e. a and b can both be
disabled, but only a or b may be enabled.

Thanks,
drew



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

* Re: [RFC 7/9] target/arm: Add CPU features to query-cpu-model-expansion
  2020-08-13 10:26 ` [RFC 7/9] target/arm: Add CPU features to query-cpu-model-expansion Peng Liang
@ 2020-08-13 12:56   ` Andrew Jones
  2020-08-15  2:19     ` Peng Liang
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Jones @ 2020-08-13 12:56 UTC (permalink / raw)
  To: Peng Liang
  Cc: peter.maydell, zhang.zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou, qemu-arm, pbonzini

On Thu, Aug 13, 2020 at 06:26:55PM +0800, Peng Liang wrote:
> Add CPU features to the result of query-cpu-model-expansion so that
> other applications (such as libvirt) can know the supported CPU
> features.
> 
> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> Signed-off-by: Peng Liang <liangpeng10@huawei.com>
> ---
>  target/arm/cpu.c     | 41 +++++++++++++++++++++++++++++++++++++++++
>  target/arm/cpu.h     |  2 ++
>  target/arm/monitor.c |  2 ++
>  3 files changed, 45 insertions(+)
> 
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index 3fc54cb3a4..0f620e8afe 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -25,6 +25,8 @@
>  #include "qemu/module.h"
>  #include "qapi/error.h"
>  #include "qapi/visitor.h"
> +#include "qapi/qmp/qdict.h"
> +#include "qom/qom-qobject.h"
>  #include "cpu.h"
>  #include "internals.h"
>  #include "exec/exec-all.h"
> @@ -1515,6 +1517,45 @@ static const CPUFeatureDep feature_dependencies[] = {
>      },
>  };
>  
> +static char *strtolower(char *src)
> +{
> +    char *start = src;
> +
> +    for (; *src; ++src) {
> +        *src = tolower(*src);
> +    }
> +
> +    return start;
> +}

Shouldn't need this. The CPU property names should already be lowercase.

> +
> +void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features)
> +{
> +    Object *obj = OBJECT(cpu);
> +    const char *name;
> +    ObjectProperty *prop;
> +    bool is_32bit = !arm_feature(&cpu->env, ARM_FEATURE_AARCH64);
> +    int i;
> +
> +    for (i = 0; i < ARRAY_SIZE(cpu_features); ++i) {
> +        if (is_32bit != cpu_features[i].is_32bit) {
> +            continue;
> +        }
> +
> +        name = cpu_features[i].name;
> +        prop = object_property_find(obj, name, NULL);
> +        if (prop) {
> +            QObject *value;
> +            g_autofree char *tmp;
> +
> +            assert(prop->get);
> +            value = object_property_get_qobject(obj, name, &error_abort);
> +            tmp = strtolower(g_strdup(name));
> +
> +            qdict_put_obj(features, tmp, value);
> +        }
> +    }
> +}
> +
>  static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
>                                   void *opaque, Error **errp)
>  {
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 5d8074d03b..da68b7f8f4 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -3933,4 +3933,6 @@ static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
>  #define cpu_isar_feature(name, cpu) \
>      ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); })
>  
> +void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features);
> +
>  #endif
> diff --git a/target/arm/monitor.c b/target/arm/monitor.c
> index ba6e01abd0..f8eb29efec 100644
> --- a/target/arm/monitor.c
> +++ b/target/arm/monitor.c
> @@ -225,6 +225,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
>          }
>      }
>  
> +    arm_cpu_features_to_dict(ARM_CPU(obj), qdict_out);

Since nobody is looking for these features in qdict_in, then none
of these features can be changed by QMP user. How does the QMP
user probe whether or not the feature will work when enabled?

Thanks,
drew

> +
>      if (!qdict_size(qdict_out)) {
>          qobject_unref(qdict_out);
>      } else {
> -- 
> 2.18.4
> 



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

* Re: [RFC 0/9] Support disable/enable CPU features for AArch64
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
                   ` (8 preceding siblings ...)
  2020-08-13 10:26 ` [RFC 9/9] target/arm: Add more CPU features Peng Liang
@ 2020-08-13 14:10 ` Andrew Jones
  2020-08-13 16:30 ` no-reply
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Andrew Jones @ 2020-08-13 14:10 UTC (permalink / raw)
  To: Peng Liang
  Cc: peter.maydell, zhang.zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou, qemu-arm, pbonzini

On Thu, Aug 13, 2020 at 06:26:48PM +0800, Peng Liang wrote:
> QEMU does not support disable/enable CPU features in AArch64 for now.

Yes, it does. We have a handful of CPU features implemented as CPU
properties and we have QMP support for probing those features and
testing whether they may be enabled or disabled.

> This patch series add support for CPU features in AArch64.

Actually, it just adds all possible features as properties without
considering if those features make sense to expose to users and
without considering all invalid configurations. That's not a great
approach.

We should try to tackle migration between non-identical hosts, but not by
dumping all the burden of determining a functional configuration on the
user. Instead, I think we need to audit what we're currently exposing to
guests from KVM. If there are CPU features that make sense for the user
to control, then we can do so using patterns for other CPU features that
are already under user control. If there are other ID register bits that
we should be masking/adjusting, then we can make those changes too. IOW,
let's take this one ID register at a time. Eventually, we'll come to the
real crux, which is MIDR. We need to provide a guest an MIDR that allows
it to migrate between hosts with different MIDRs. That'll likely open the
errata can of worms.

Thanks,
drew



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

* Re: [RFC 1/9] target/arm: convert isar regs to array
  2020-08-13 10:42   ` Philippe Mathieu-Daudé
@ 2020-08-13 16:11     ` Richard Henderson
  0 siblings, 0 replies; 28+ messages in thread
From: Richard Henderson @ 2020-08-13 16:11 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Peng Liang, qemu-arm, qemu-devel
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	xiexiangyou, pbonzini

On 8/13/20 3:42 AM, Philippe Mathieu-Daudé wrote:
>>      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;
>> -        uint32_t id_mmfr3;
>> -        uint32_t id_mmfr4;
>> -        uint32_t mvfr0;
>> -        uint32_t mvfr1;
>> -        uint32_t mvfr2;
>> -        uint32_t id_dfr0;
>> -        uint32_t dbgdidr;
>> -        uint64_t id_aa64isar0;
>> -        uint64_t id_aa64isar1;
>> -        uint64_t id_aa64pfr0;
>> -        uint64_t id_aa64pfr1;
>> -        uint64_t id_aa64mmfr0;
>> -        uint64_t id_aa64mmfr1;
>> -        uint64_t id_aa64mmfr2;
>> -        uint64_t id_aa64dfr0;
>> -        uint64_t id_aa64dfr1;
>> +        uint64_t regs[ID_MAX];
>>      } isar;
> 
> Why not simply this?
> 
>        uint64_t isar[ID_MAX];

Because the ARMISARegisters type is used elsewhere.

r~


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

* Re: [RFC 0/9] Support disable/enable CPU features for AArch64
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
                   ` (9 preceding siblings ...)
  2020-08-13 14:10 ` [RFC 0/9] Support disable/enable CPU features for AArch64 Andrew Jones
@ 2020-08-13 16:30 ` no-reply
  2020-08-13 16:34 ` no-reply
  2020-08-13 16:38 ` no-reply
  12 siblings, 0 replies; 28+ messages in thread
From: no-reply @ 2020-08-13 16:30 UTC (permalink / raw)
  To: liangpeng10
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	qemu-devel, xiexiangyou, liangpeng10, qemu-arm, pbonzini

Patchew URL: https://patchew.org/QEMU/20200813102657.2588720-1-liangpeng10@huawei.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20200813102657.2588720-1-liangpeng10@huawei.com
Subject: [RFC 0/9] Support disable/enable CPU features for AArch64

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Switched to a new branch 'test'
155e490 target/arm: Add more CPU features
5564d59 target/arm: Update ID fields
2f12ecd target/arm: Add CPU features to query-cpu-model-expansion
0911682 target/arm: introduce KVM_CAP_ARM_CPU_FEATURE
9dddca9 target/arm: introduce CPU feature dependency mechanism
89874bb target/arm: Allow ID registers to synchronize to KVM
8286a4a target/arm: register CPU features for property
7101c88 target/arm: parse cpu feature related options
56111cc target/arm: convert isar regs to array

=== OUTPUT BEGIN ===
1/9 Checking commit 56111cc30af0 (target/arm: convert isar regs to array)
2/9 Checking commit 7101c885db04 (target/arm: parse cpu feature related options)
ERROR: consider using qemu_strtoupr in preference to strtoupr
#55: FILE: target/arm/cpu64.c:799:
+static char *strtoupr(char *str)

ERROR: consider using qemu_strtoupr in preference to strtoupr
#121: FILE: target/arm/cpu64.c:865:
+        tmp = strtoupr(tmp);

ERROR: consider using qemu_strtoupr in preference to strtoupr
#127: FILE: target/arm/cpu64.c:871:
+        const char *name = strtoupr(l->data); /* convert to upper string */

ERROR: consider using qemu_strtoupr in preference to strtoupr
#132: FILE: target/arm/cpu64.c:876:
+        const char *name = strtoupr(l->data);

total: 4 errors, 0 warnings, 119 lines checked

Patch 2/9 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

3/9 Checking commit 8286a4a789ed (target/arm: register CPU features for property)
4/9 Checking commit 89874bbdfd8e (target/arm: Allow ID registers to synchronize to KVM)
5/9 Checking commit 9dddca93c5b1 (target/arm: introduce CPU feature dependency mechanism)
6/9 Checking commit 091168210d47 (target/arm: introduce KVM_CAP_ARM_CPU_FEATURE)
7/9 Checking commit 2f12ecd63d30 (target/arm: Add CPU features to query-cpu-model-expansion)
ERROR: consider using qemu_strtolower in preference to strtolower
#32: FILE: target/arm/cpu.c:1520:
+static char *strtolower(char *src)

ERROR: consider using qemu_strtolower in preference to strtolower
#64: FILE: target/arm/cpu.c:1552:
+            tmp = strtolower(g_strdup(name));

total: 2 errors, 0 warnings, 67 lines checked

Patch 7/9 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

8/9 Checking commit 5564d59a9ee0 (target/arm: Update ID fields)
9/9 Checking commit 155e490920e3 (target/arm: Add more CPU features)
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20200813102657.2588720-1-liangpeng10@huawei.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

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

* Re: [RFC 0/9] Support disable/enable CPU features for AArch64
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
                   ` (10 preceding siblings ...)
  2020-08-13 16:30 ` no-reply
@ 2020-08-13 16:34 ` no-reply
  2020-08-13 16:38 ` no-reply
  12 siblings, 0 replies; 28+ messages in thread
From: no-reply @ 2020-08-13 16:34 UTC (permalink / raw)
  To: liangpeng10
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	qemu-devel, xiexiangyou, liangpeng10, qemu-arm, pbonzini

Patchew URL: https://patchew.org/QEMU/20200813102657.2588720-1-liangpeng10@huawei.com/



Hi,

This series failed the docker-mingw@fedora build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#! /bin/bash
export ARCH=x86_64
make docker-image-fedora V=1 NETWORK=1
time make docker-test-mingw@fedora J=14 NETWORK=1
=== TEST SCRIPT END ===

  CC      aarch64-softmmu/target/arm/translate-a64.o
  CC      aarch64-softmmu/target/arm/helper-a64.o
/tmp/qemu-test/src/target/arm/cpu.c: In function 'arm_cpu_set_bit_prop':
/tmp/qemu-test/src/target/arm/cpu.c:1586:10: error: implicit declaration of function 'kvm_arm_cpu_feature_supported'; did you mean 'kvm_arm_pmu_supported'? [-Werror=implicit-function-declaration]
 1586 |     if (!kvm_arm_cpu_feature_supported()) {
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |          kvm_arm_pmu_supported
/tmp/qemu-test/src/target/arm/cpu.c:1586:10: error: nested extern declaration of 'kvm_arm_cpu_feature_supported' [-Werror=nested-externs]
cc1: all warnings being treated as errors
make[1]: *** [/tmp/qemu-test/src/rules.mak:69: target/arm/cpu.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:527: aarch64-softmmu/all] Error 2
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 709, in <module>
    sys.exit(main())
---
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=82498ab48b9d4e83a6e3d551852f7ce7', '-u', '1003', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew2/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-05puycro/src/docker-src.2020-08-13-12.30.55.30563:/var/tmp/qemu:z,ro', 'qemu/fedora', '/var/tmp/qemu/run', 'test-mingw']' returned non-zero exit status 2.
filter=--filter=label=com.qemu.instance.uuid=82498ab48b9d4e83a6e3d551852f7ce7
make[1]: *** [docker-run] Error 1
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-05puycro/src'
make: *** [docker-run-test-mingw@fedora] Error 2

real    3m42.997s
user    0m9.285s


The full log is available at
http://patchew.org/logs/20200813102657.2588720-1-liangpeng10@huawei.com/testing.docker-mingw@fedora/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

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

* Re: [RFC 0/9] Support disable/enable CPU features for AArch64
  2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
                   ` (11 preceding siblings ...)
  2020-08-13 16:34 ` no-reply
@ 2020-08-13 16:38 ` no-reply
  12 siblings, 0 replies; 28+ messages in thread
From: no-reply @ 2020-08-13 16:38 UTC (permalink / raw)
  To: liangpeng10
  Cc: peter.maydell, drjones, zhang.zhanghailiang, mst, cohuck,
	qemu-devel, xiexiangyou, liangpeng10, qemu-arm, pbonzini

Patchew URL: https://patchew.org/QEMU/20200813102657.2588720-1-liangpeng10@huawei.com/



Hi,

This series failed the docker-quick@centos7 build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
make docker-image-centos7 V=1 NETWORK=1
time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
=== TEST SCRIPT END ===

  CC      aarch64-softmmu/target/arm/gdbstub64.o
  CC      aarch64-softmmu/target/arm/machine.o
/tmp/qemu-test/src/target/arm/cpu.c: In function 'arm_cpu_set_bit_prop':
/tmp/qemu-test/src/target/arm/cpu.c:1586:5: error: implicit declaration of function 'kvm_arm_cpu_feature_supported' [-Werror=implicit-function-declaration]
     if (!kvm_arm_cpu_feature_supported()) {
     ^
/tmp/qemu-test/src/target/arm/cpu.c:1586:5: error: nested extern declaration of 'kvm_arm_cpu_feature_supported' [-Werror=nested-externs]
cc1: all warnings being treated as errors
  CC      aarch64-softmmu/target/arm/arch_dump.o
  CC      aarch64-softmmu/target/arm/monitor.o
  CC      aarch64-softmmu/target/arm/arm-powerctl.o
make[1]: *** [target/arm/cpu.o] Error 1
make[1]: *** Waiting for unfinished jobs....
  CC      aarch64-softmmu/target/arm/kvm-stub.o
make: *** [aarch64-softmmu/all] Error 2
make: *** Waiting for unfinished jobs....
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 709, in <module>
---
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=66c80c872bf54d5084de54fbccc4353c', '-u', '1001', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-xzm_l9kf/src/docker-src.2020-08-13-12.35.23.5519:/var/tmp/qemu:z,ro', 'qemu/centos7', '/var/tmp/qemu/run', 'test-quick']' returned non-zero exit status 2.
filter=--filter=label=com.qemu.instance.uuid=66c80c872bf54d5084de54fbccc4353c
make[1]: *** [docker-run] Error 1
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-xzm_l9kf/src'
make: *** [docker-run-test-quick@centos7] Error 2

real    3m15.003s
user    0m8.959s


The full log is available at
http://patchew.org/logs/20200813102657.2588720-1-liangpeng10@huawei.com/testing.docker-quick@centos7/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

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

* Re: [RFC 7/9] target/arm: Add CPU features to query-cpu-model-expansion
  2020-08-13 12:56   ` Andrew Jones
@ 2020-08-15  2:19     ` Peng Liang
  2020-08-15  7:02       ` Andrew Jones
  0 siblings, 1 reply; 28+ messages in thread
From: Peng Liang @ 2020-08-15  2:19 UTC (permalink / raw)
  To: Andrew Jones
  Cc: peter.maydell, Zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou 00584000, qemu-arm, pbonzini, zhukeqian 00502301

On 8/13/2020 8:56 PM, Andrew Jones wrote:
> On Thu, Aug 13, 2020 at 06:26:55PM +0800, Peng Liang wrote:
>> Add CPU features to the result of query-cpu-model-expansion so that
>> other applications (such as libvirt) can know the supported CPU
>> features.
>>
>> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
>> Signed-off-by: Peng Liang <liangpeng10@huawei.com>
>> ---
>>  target/arm/cpu.c     | 41 +++++++++++++++++++++++++++++++++++++++++
>>  target/arm/cpu.h     |  2 ++
>>  target/arm/monitor.c |  2 ++
>>  3 files changed, 45 insertions(+)
>>
>> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
>> index 3fc54cb3a4..0f620e8afe 100644
>> --- a/target/arm/cpu.c
>> +++ b/target/arm/cpu.c
>> @@ -25,6 +25,8 @@
>>  #include "qemu/module.h"
>>  #include "qapi/error.h"
>>  #include "qapi/visitor.h"
>> +#include "qapi/qmp/qdict.h"
>> +#include "qom/qom-qobject.h"
>>  #include "cpu.h"
>>  #include "internals.h"
>>  #include "exec/exec-all.h"
>> @@ -1515,6 +1517,45 @@ static const CPUFeatureDep feature_dependencies[] = {
>>      },
>>  };
>>  
>> +static char *strtolower(char *src)
>> +{
>> +    char *start = src;
>> +
>> +    for (; *src; ++src) {
>> +        *src = tolower(*src);
>> +    }
>> +
>> +    return start;
>> +}
> 
> Shouldn't need this. The CPU property names should already be lowercase.
> 

For convenience, we use the field part defined in FIELD macro as the name of
a CPU feature.  So, the names of CPU features are upper...

>> +
>> +void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features)
>> +{
>> +    Object *obj = OBJECT(cpu);
>> +    const char *name;
>> +    ObjectProperty *prop;
>> +    bool is_32bit = !arm_feature(&cpu->env, ARM_FEATURE_AARCH64);
>> +    int i;
>> +
>> +    for (i = 0; i < ARRAY_SIZE(cpu_features); ++i) {
>> +        if (is_32bit != cpu_features[i].is_32bit) {
>> +            continue;
>> +        }
>> +
>> +        name = cpu_features[i].name;
>> +        prop = object_property_find(obj, name, NULL);
>> +        if (prop) {
>> +            QObject *value;
>> +            g_autofree char *tmp;
>> +
>> +            assert(prop->get);
>> +            value = object_property_get_qobject(obj, name, &error_abort);
>> +            tmp = strtolower(g_strdup(name));
>> +
>> +            qdict_put_obj(features, tmp, value);
>> +        }
>> +    }
>> +}
>> +
>>  static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
>>                                   void *opaque, Error **errp)
>>  {
>> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
>> index 5d8074d03b..da68b7f8f4 100644
>> --- a/target/arm/cpu.h
>> +++ b/target/arm/cpu.h
>> @@ -3933,4 +3933,6 @@ static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
>>  #define cpu_isar_feature(name, cpu) \
>>      ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); })
>>  
>> +void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features);
>> +
>>  #endif
>> diff --git a/target/arm/monitor.c b/target/arm/monitor.c
>> index ba6e01abd0..f8eb29efec 100644
>> --- a/target/arm/monitor.c
>> +++ b/target/arm/monitor.c
>> @@ -225,6 +225,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
>>          }
>>      }
>>  
>> +    arm_cpu_features_to_dict(ARM_CPU(obj), qdict_out);
> 
> Since nobody is looking for these features in qdict_in, then none
> of these features can be changed by QMP user. How does the QMP
> user probe whether or not the feature will work when enabled?
> 
> Thanks,
> drew
> 

My fault, I'll correct it.

Thanks,
Peng

>> +
>>      if (!qdict_size(qdict_out)) {
>>          qobject_unref(qdict_out);
>>      } else {
>> -- 
>> 2.18.4
>>
> 
> .
> 



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

* Re: [RFC 6/9] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE
  2020-08-13 11:00   ` Cornelia Huck
@ 2020-08-15  2:19     ` Peng Liang
  0 siblings, 0 replies; 28+ messages in thread
From: Peng Liang @ 2020-08-15  2:19 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: peter.maydell, Zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou 00584000, qemu-arm, pbonzini, zhukeqian 00502301

On 8/13/2020 7:00 PM, Cornelia Huck wrote:
> On Thu, 13 Aug 2020 18:26:54 +0800
> Peng Liang <liangpeng10@huawei.com> wrote:
> 
>> Introduce KVM_CAP_ARM_CPU_FEATURE to check whether KVM supports to set
>> CPU features in ARM.
>>
>> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
>> Signed-off-by: Peng Liang <liangpeng10@huawei.com>
>> ---
>>  linux-headers/linux/kvm.h |  1 +
>>  target/arm/cpu.c          |  5 +++++
>>  target/arm/kvm64.c        | 14 ++++++++++++++
>>  target/arm/kvm_arm.h      |  7 +++++++
>>  4 files changed, 27 insertions(+)
>>
>> diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
>> index a28c366737..0b83d2b4bb 100644
>> --- a/linux-headers/linux/kvm.h
>> +++ b/linux-headers/linux/kvm.h
>> @@ -1031,6 +1031,7 @@ struct kvm_ppc_resize_hpt {
>>  #define KVM_CAP_PPC_SECURE_GUEST 181
>>  #define KVM_CAP_HALT_POLL 182
>>  #define KVM_CAP_ASYNC_PF_INT 183
>> +#define KVM_CAP_ARM_CPU_FEATURE 187
>>  
>>  #ifdef KVM_CAP_IRQ_ROUTING
> 
> Please split out this header update into a separate patch so that it
> can be replaced by a proper headers update once the kernel code has been
> included.
> 
> .
> 
Sorry, I'll split out it.


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

* Re: [RFC 2/9] target/arm: parse cpu feature related options
  2020-08-13 12:21   ` Andrew Jones
@ 2020-08-15  2:19     ` Peng Liang
  2020-08-15  6:51       ` Andrew Jones
  0 siblings, 1 reply; 28+ messages in thread
From: Peng Liang @ 2020-08-15  2:19 UTC (permalink / raw)
  To: Andrew Jones
  Cc: peter.maydell, Zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou 00584000, qemu-arm, pbonzini, zhukeqian 00502301

On 8/13/2020 8:21 PM, Andrew Jones wrote:
> On Thu, Aug 13, 2020 at 06:26:50PM +0800, Peng Liang wrote:
>> The implementation of CPUClass::parse_features only supports CPU
>> features in "feature=value" format.  However, libvirt maybe send us a
>> CPU feature string in "+feature/-feature" format. 
> 
> Why would libvirt do that? If we have a boolean feature, then I'd think
> libvirt should be capable of sending feature=on/off just as easily as a
> +/-feature. Indeed libvirt seems to do the right thing with all the
> CPU features we already have: pmu, sve*, ...
> 
> Thanks,
> drew
> 
> .
> 

Libvirt before d47db7b16dd5422c7e487c8c8ee5b181a2f9cd66 ("qemu: command:
Support new cpu feature argument syntax") will send +/-feature.  Does QEMU
need to support it?  If not, I'll remote it.

Thanks,
Peng


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

* Re: [RFC 5/9] target/arm: introduce CPU feature dependency mechanism
  2020-08-13 12:48   ` Andrew Jones
@ 2020-08-15  2:19     ` Peng Liang
  2020-08-15  6:59       ` Andrew Jones
  0 siblings, 1 reply; 28+ messages in thread
From: Peng Liang @ 2020-08-15  2:19 UTC (permalink / raw)
  To: Andrew Jones
  Cc: peter.maydell, Zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou 00584000, qemu-arm, pbonzini, zhukeqian 00502301

On 8/13/2020 8:48 PM, Andrew Jones wrote:
> On Thu, Aug 13, 2020 at 06:26:53PM +0800, Peng Liang wrote:
>> Some CPU features are dependent on other CPU features.  For example,
>> ID_AA64PFR0_EL1.FP field and ID_AA64PFR0_EL1.AdvSIMD must have the same
>> value, which means FP and ADVSIMD are dependent on each other, FPHP and
>> ADVSIMDHP are dependent on each other.
>>
>> This commit introduces a mechanism for CPU feature dependency in
>> AArch64.  We build a directed graph from the CPU feature dependency
>> relationship, each edge from->to means the `to` CPU feature is dependent
>> on the `from` CPU feature.  And we will automatically enable/disable CPU
>> feature according to the directed graph.
>>
>> For example, a, b, and c CPU features are in relationship a->b->c, which
>> means c is dependent on b and b is dependent on a.  If c is enabled by
>> user, then a and b is enabled automatically.  And if a is disabled by
>> user, then b and c is disabled automatically.
> 
> And what if a is mutually exclusive with b? I.e. a and b can both be
> disabled, but only a or b may be enabled.
> 
> Thanks,
> drew
> 
> .
> 

Currently, a and b will be both enabled or disabled.  For example, a and b are
in relationship a->b, which means b is dependent on a.  If -cpu host,a=off,b=on,
then both a and b are enabled.  If -cpu host,b=on,a=off, then both a and b are
disabled.  Maybe we should report an error to user in this scenario?

Thanks,
Peng


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

* Re: [RFC 2/9] target/arm: parse cpu feature related options
  2020-08-15  2:19     ` Peng Liang
@ 2020-08-15  6:51       ` Andrew Jones
  0 siblings, 0 replies; 28+ messages in thread
From: Andrew Jones @ 2020-08-15  6:51 UTC (permalink / raw)
  To: Peng Liang
  Cc: peter.maydell, Zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou 00584000, qemu-arm, pbonzini, zhukeqian 00502301

On Sat, Aug 15, 2020 at 10:19:12AM +0800, Peng Liang wrote:
> On 8/13/2020 8:21 PM, Andrew Jones wrote:
> > On Thu, Aug 13, 2020 at 06:26:50PM +0800, Peng Liang wrote:
> >> The implementation of CPUClass::parse_features only supports CPU
> >> features in "feature=value" format.  However, libvirt maybe send us a
> >> CPU feature string in "+feature/-feature" format. 
> > 
> > Why would libvirt do that? If we have a boolean feature, then I'd think
> > libvirt should be capable of sending feature=on/off just as easily as a
> > +/-feature. Indeed libvirt seems to do the right thing with all the
> > CPU features we already have: pmu, sve*, ...
> > 
> > Thanks,
> > drew
> > 
> > .
> > 
> 
> Libvirt before d47db7b16dd5422c7e487c8c8ee5b181a2f9cd66 ("qemu: command:
> Support new cpu feature argument syntax") will send +/-feature.  Does QEMU
> need to support it?  If not, I'll remote it.

No, we don't need to support pre-2016 libvirt, at least not for ARM CPU
features, because libvirt didn't start querying QEMU for ARM CPU features
until just last year.

Thanks,
drew



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

* Re: [RFC 5/9] target/arm: introduce CPU feature dependency mechanism
  2020-08-15  2:19     ` Peng Liang
@ 2020-08-15  6:59       ` Andrew Jones
  0 siblings, 0 replies; 28+ messages in thread
From: Andrew Jones @ 2020-08-15  6:59 UTC (permalink / raw)
  To: Peng Liang
  Cc: peter.maydell, Zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou 00584000, qemu-arm, pbonzini, zhukeqian 00502301

On Sat, Aug 15, 2020 at 10:19:27AM +0800, Peng Liang wrote:
> On 8/13/2020 8:48 PM, Andrew Jones wrote:
> > On Thu, Aug 13, 2020 at 06:26:53PM +0800, Peng Liang wrote:
> >> Some CPU features are dependent on other CPU features.  For example,
> >> ID_AA64PFR0_EL1.FP field and ID_AA64PFR0_EL1.AdvSIMD must have the same
> >> value, which means FP and ADVSIMD are dependent on each other, FPHP and
> >> ADVSIMDHP are dependent on each other.
> >>
> >> This commit introduces a mechanism for CPU feature dependency in
> >> AArch64.  We build a directed graph from the CPU feature dependency
> >> relationship, each edge from->to means the `to` CPU feature is dependent
> >> on the `from` CPU feature.  And we will automatically enable/disable CPU
> >> feature according to the directed graph.
> >>
> >> For example, a, b, and c CPU features are in relationship a->b->c, which
> >> means c is dependent on b and b is dependent on a.  If c is enabled by
> >> user, then a and b is enabled automatically.  And if a is disabled by
> >> user, then b and c is disabled automatically.
> > 
> > And what if a is mutually exclusive with b? I.e. a and b can both be
> > disabled, but only a or b may be enabled.
> > 
> > Thanks,
> > drew
> > 
> > .
> > 
> 
> Currently, a and b will be both enabled or disabled.  For example, a and b are
> in relationship a->b, which means b is dependent on a.  If -cpu host,a=off,b=on,
> then both a and b are enabled.  If -cpu host,b=on,a=off, then both a and b are
> disabled.  Maybe we should report an error to user in this scenario?
>

Right. There are more relationships between features than "depends on",
such as "only if not" or "only if value is". The last one points out
that just setting the minimum feature value may not be sufficient to
control all the features. Also, there could be relationships involving
more than two features, such as 'a iff b and c', or 'a iff b and !c'.

We really have to take each feature of each ID register one at a time to
make sure we handle them appropriately. Exposing them all like this
without any checks just pushes all the pain onto the user to figure
everything out, and if there's not even errors generated, then how will
the user know when they got something wrong until their guest breaks
in some mysterious way?

Thanks,
drew



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

* Re: [RFC 7/9] target/arm: Add CPU features to query-cpu-model-expansion
  2020-08-15  2:19     ` Peng Liang
@ 2020-08-15  7:02       ` Andrew Jones
  0 siblings, 0 replies; 28+ messages in thread
From: Andrew Jones @ 2020-08-15  7:02 UTC (permalink / raw)
  To: Peng Liang
  Cc: peter.maydell, Zhanghailiang, mst, cohuck, qemu-devel,
	xiexiangyou 00584000, qemu-arm, pbonzini, zhukeqian 00502301

On Sat, Aug 15, 2020 at 10:19:05AM +0800, Peng Liang wrote:
> On 8/13/2020 8:56 PM, Andrew Jones wrote:
> > On Thu, Aug 13, 2020 at 06:26:55PM +0800, Peng Liang wrote:
> >> Add CPU features to the result of query-cpu-model-expansion so that
> >> other applications (such as libvirt) can know the supported CPU
> >> features.
> >>
> >> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> >> Signed-off-by: Peng Liang <liangpeng10@huawei.com>
> >> ---
> >>  target/arm/cpu.c     | 41 +++++++++++++++++++++++++++++++++++++++++
> >>  target/arm/cpu.h     |  2 ++
> >>  target/arm/monitor.c |  2 ++
> >>  3 files changed, 45 insertions(+)
> >>
> >> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> >> index 3fc54cb3a4..0f620e8afe 100644
> >> --- a/target/arm/cpu.c
> >> +++ b/target/arm/cpu.c
> >> @@ -25,6 +25,8 @@
> >>  #include "qemu/module.h"
> >>  #include "qapi/error.h"
> >>  #include "qapi/visitor.h"
> >> +#include "qapi/qmp/qdict.h"
> >> +#include "qom/qom-qobject.h"
> >>  #include "cpu.h"
> >>  #include "internals.h"
> >>  #include "exec/exec-all.h"
> >> @@ -1515,6 +1517,45 @@ static const CPUFeatureDep feature_dependencies[] = {
> >>      },
> >>  };
> >>  
> >> +static char *strtolower(char *src)
> >> +{
> >> +    char *start = src;
> >> +
> >> +    for (; *src; ++src) {
> >> +        *src = tolower(*src);
> >> +    }
> >> +
> >> +    return start;
> >> +}
> > 
> > Shouldn't need this. The CPU property names should already be lowercase.
> > 
> 
> For convenience, we use the field part defined in FIELD macro as the name of
> a CPU feature.  So, the names of CPU features are upper...

But then the command line requires capital letters for property names,
which isn't very convenient to the user. The field names could be
converted to lowercase when generating the property names.

Thanks,
drew



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

end of thread, other threads:[~2020-08-15 18:12 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-13 10:26 [RFC 0/9] Support disable/enable CPU features for AArch64 Peng Liang
2020-08-13 10:26 ` [RFC 1/9] target/arm: convert isar regs to array Peng Liang
2020-08-13 10:42   ` Philippe Mathieu-Daudé
2020-08-13 16:11     ` Richard Henderson
2020-08-13 10:26 ` [RFC 2/9] target/arm: parse cpu feature related options Peng Liang
2020-08-13 12:21   ` Andrew Jones
2020-08-15  2:19     ` Peng Liang
2020-08-15  6:51       ` Andrew Jones
2020-08-13 10:26 ` [RFC 3/9] target/arm: register CPU features for property Peng Liang
2020-08-13 12:34   ` Andrew Jones
2020-08-13 10:26 ` [RFC 4/9] target/arm: Allow ID registers to synchronize to KVM Peng Liang
2020-08-13 10:26 ` [RFC 5/9] target/arm: introduce CPU feature dependency mechanism Peng Liang
2020-08-13 12:48   ` Andrew Jones
2020-08-15  2:19     ` Peng Liang
2020-08-15  6:59       ` Andrew Jones
2020-08-13 10:26 ` [RFC 6/9] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE Peng Liang
2020-08-13 11:00   ` Cornelia Huck
2020-08-15  2:19     ` Peng Liang
2020-08-13 10:26 ` [RFC 7/9] target/arm: Add CPU features to query-cpu-model-expansion Peng Liang
2020-08-13 12:56   ` Andrew Jones
2020-08-15  2:19     ` Peng Liang
2020-08-15  7:02       ` Andrew Jones
2020-08-13 10:26 ` [RFC 8/9] target/arm: Update ID fields Peng Liang
2020-08-13 10:26 ` [RFC 9/9] target/arm: Add more CPU features Peng Liang
2020-08-13 14:10 ` [RFC 0/9] Support disable/enable CPU features for AArch64 Andrew Jones
2020-08-13 16:30 ` no-reply
2020-08-13 16:34 ` no-reply
2020-08-13 16:38 ` no-reply

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.