public inbox for qemu-arm@nongnu.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1)
@ 2026-02-04 13:32 Cornelia Huck
  2026-02-04 13:32 ` [PATCH v2 1/3] arm: handle demuxed ID registers Cornelia Huck
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Cornelia Huck @ 2026-02-04 13:32 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Peter Maydell, Eric Auger, Sebastian Ott, Jonathan Cameron,
	Alireza Sanaee, Cornelia Huck

[previously posted as RFC, but given that I got T-b and R-b, I promoted
it to full v2 :)]

Changes RFC->v2:
- use a proper #define so that it is clearer why we end up with that
  specific array size
- rebased on top of master
- collected T-bs and R-bs (thanks!)

Original cover letter follows. I'm not sure whether the questions contain
any actual blockers, or whether it is easier to just go ahead and deal
with it later.

--------8<---------8<--------

While trying to move to an autogenerated cpu-sysregs.h.inc (so that we
may keep a common view on registers), we should first address the ID
registers that are still kept outside of ARMISARegisters. Other than
DCZID_EL0 (addressed by the series this one goes on top of), that's
the CCSIDR_EL1 values kept in cpu->cssidr[] (indexed via CSSELR_EL1.)

My idea was to provide {GET,SET}_IDREG_DEMUX helper that work similar
to {GET,SET}_IDREG and operate on a two-dimensional array. As a side
effect, this also allows to get the values KVM provides for CCSIDR_EL1
(which are virtualized as well.)

RFC because there are still some open questions:
- The demux array cannot easily be autogenerated. We can get rid of the
  ccsidr[] array, but we now have an autogenerated entry in the non-demux
  array that does nothing. Both are not that nice.
- I'm not sure if we need any compat handling for KVM (on TCG, everything
  should stay the same.) In theory, the KVM interface allows setting
  values from userspace (I didn't try.)
- There's a slight disagreement between the current code (providing 16
  entries for CCSIDR_EL1) and the KVM code (providing (7 cache levels) *
  (data/unified, instruction) = 14 entries.) With FEAT_MTE2, we might be
  needing 7 more entries.

Feedback appreciated.

--------8<---------8<--------

Cornelia Huck (3):
  arm: handle demuxed ID registers
  arm: handle CCSIDR_EL1 as a demuxed register
  arm/kvm: get demuxed ID registers from kvm

 hw/intc/armv7m_nvic.c        |  2 +-
 target/arm/cpu-sysregs.h     | 14 +++++++++
 target/arm/cpu-sysregs.h.inc |  1 +
 target/arm/cpu.h             | 26 ++++++++++++----
 target/arm/cpu64.c           | 12 ++++----
 target/arm/helper.c          |  2 +-
 target/arm/kvm.c             | 33 ++++++++++++++++++++
 target/arm/tcg/cpu32.c       | 32 +++++++++----------
 target/arm/tcg/cpu64.c       | 60 ++++++++++++++++++------------------
 9 files changed, 122 insertions(+), 60 deletions(-)

-- 
2.52.0



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

* [PATCH v2 1/3] arm: handle demuxed ID registers
  2026-02-04 13:32 [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1) Cornelia Huck
@ 2026-02-04 13:32 ` Cornelia Huck
  2026-02-04 13:32 ` [PATCH v2 2/3] arm: handle CCSIDR_EL1 as a demuxed register Cornelia Huck
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Cornelia Huck @ 2026-02-04 13:32 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Peter Maydell, Eric Auger, Sebastian Ott, Jonathan Cameron,
	Alireza Sanaee, Cornelia Huck

For some registers, we do not have a single ID register, but actually
an array of values (e.g. CCSIDR_EL1, where the actual value is
determined by whatever CSSELR_EL1 points to.) If we want to avoid
using a different way to handle registers like that for every
instance, we should provide some kind of infrastructure. Therefore,
add accessors {GET,SET}_IDREG_DEMUX that are similar to the accessors
we already use for regular ID registers.

Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>
Reviewed-by: Sebastian Ott <sebott@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 target/arm/cpu-sysregs.h | 13 +++++++++++++
 target/arm/cpu.h         | 20 ++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h
index 7877a3b06a8e..911f54bc8a4f 100644
--- a/target/arm/cpu-sysregs.h
+++ b/target/arm/cpu-sysregs.h
@@ -35,6 +35,19 @@ typedef enum ARMSysRegs {
 
 #undef DEF
 
+/* ID registers that vary based upon another register */
+typedef enum ARMIDRegisterDemuxIdx {
+    NUM_ID_DEMUX_IDX,
+} ARMIDRegisterDemuxIdx;
+
+/*
+ * Number of register variants per demuxed register, trying to accommodate
+ * possible use cases.
+ * CCSIDR_EL1 currently needs 7*2, could be 7 more with FEAT_MTE2, in which
+ * case we would need to bump this number.
+ */
+#define ID_DEMUX_ARRAYLEN 16
+
 extern const uint32_t id_register_sysreg[NUM_ID_IDX];
 
 int get_sysreg_idx(ARMSysRegs sysreg);
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 21fee5e840b7..f9d51c0fc187 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -906,6 +906,25 @@ typedef struct {
         i_->idregs[REG ## _EL1_IDX];                                    \
     })
 
+#define SET_IDREG_DEMUX(ISAR, REG, INDEX, VALUE)                        \
+    ({                                                                  \
+        ARMISARegisters *i_ = (ISAR);                                   \
+        i_->idregs_demux[REG ## _EL1_DEMUX_IDX][INDEX] = VALUE;         \
+    })
+
+#define GET_IDREG_DEMUX(ISAR, REG, INDEX)                               \
+    ({                                                                  \
+        ARMISARegisters *i_ = (ISAR);                                   \
+        i_->idregs_demux[REG ## _EL1_DEMUX_IDX][INDEX];                 \
+    })
+
+#define COPY_IDREG_DEMUX(ISAR, REG, FROM_INDEX, TO_INDEX)               \
+    ({                                                                  \
+        ARMISARegisters *i_ = (ISAR);                                   \
+        i_->idregs_demux[REG ## _EL1_DEMUX_IDX][TO_INDEX] =             \
+            i_->idregs_demux[REG ## _EL1_DEMUX_IDX][FROM_INDEX];        \
+    })
+
 /**
  * ARMCPU:
  * @env: #CPUARMState
@@ -1084,6 +1103,7 @@ struct ArchCPU {
         uint32_t dbgdevid1;
         uint64_t reset_pmcr_el0;
         uint64_t idregs[NUM_ID_IDX];
+        uint64_t idregs_demux[NUM_ID_DEMUX_IDX][ID_DEMUX_ARRAYLEN];
     } isar;
     uint64_t midr;
     uint32_t revidr;
-- 
2.52.0



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

* [PATCH v2 2/3] arm: handle CCSIDR_EL1 as a demuxed register
  2026-02-04 13:32 [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1) Cornelia Huck
  2026-02-04 13:32 ` [PATCH v2 1/3] arm: handle demuxed ID registers Cornelia Huck
@ 2026-02-04 13:32 ` Cornelia Huck
  2026-04-01 16:46   ` Eric Auger
  2026-02-04 13:32 ` [PATCH v2 3/3] arm/kvm: get demuxed ID registers from kvm Cornelia Huck
  2026-02-05 11:52 ` [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1) Peter Maydell
  3 siblings, 1 reply; 10+ messages in thread
From: Cornelia Huck @ 2026-02-04 13:32 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Peter Maydell, Eric Auger, Sebastian Ott, Jonathan Cameron,
	Alireza Sanaee, Cornelia Huck

Move handling of CCSIDR_EL1 over to the new *_IDREG_DEMUX
infrastructure.

Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>
Reviewed-by: Sebastian Ott <sebott@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 hw/intc/armv7m_nvic.c        |  2 +-
 target/arm/cpu-sysregs.h     |  1 +
 target/arm/cpu-sysregs.h.inc |  1 +
 target/arm/cpu.h             |  6 ----
 target/arm/cpu64.c           | 12 ++++----
 target/arm/helper.c          |  2 +-
 target/arm/tcg/cpu32.c       | 32 +++++++++----------
 target/arm/tcg/cpu64.c       | 60 ++++++++++++++++++------------------
 8 files changed, 56 insertions(+), 60 deletions(-)

diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 28b34e99446f..271d16692910 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -1337,7 +1337,7 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
     case 0xd80: /* CSSIDR */
     {
         int idx = cpu->env.v7m.csselr[attrs.secure] & R_V7M_CSSELR_INDEX_MASK;
-        return cpu->ccsidr[idx];
+        return GET_IDREG_DEMUX(&cpu->isar, CCSIDR, idx);
     }
     case 0xd84: /* CSSELR */
         return cpu->env.v7m.csselr[attrs.secure];
diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h
index 911f54bc8a4f..ec04174d4a99 100644
--- a/target/arm/cpu-sysregs.h
+++ b/target/arm/cpu-sysregs.h
@@ -37,6 +37,7 @@ typedef enum ARMSysRegs {
 
 /* ID registers that vary based upon another register */
 typedef enum ARMIDRegisterDemuxIdx {
+    CCSIDR_EL1_DEMUX_IDX,
     NUM_ID_DEMUX_IDX,
 } ARMIDRegisterDemuxIdx;
 
diff --git a/target/arm/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc
index 3d1ed40f0439..ed466ffb7318 100644
--- a/target/arm/cpu-sysregs.h.inc
+++ b/target/arm/cpu-sysregs.h.inc
@@ -37,6 +37,7 @@ DEF(MVFR2_EL1, 3, 0, 0, 3, 2)
 DEF(ID_PFR2_EL1, 3, 0, 0, 3, 4)
 DEF(ID_DFR1_EL1, 3, 0, 0, 3, 5)
 DEF(ID_MMFR5_EL1, 3, 0, 0, 3, 6)
+DEF(CCSIDR_EL1, 3, 1, 0, 0, 0)
 DEF(CLIDR_EL1, 3, 1, 0, 0, 1)
 DEF(ID_AA64ZFR0_EL1, 3, 0, 0, 4, 4)
 DEF(CTR_EL0, 3, 3, 0, 0, 1)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index f9d51c0fc187..b26922ea4298 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1113,10 +1113,6 @@ struct ArchCPU {
     uint64_t pmceid0;
     uint64_t pmceid1;
     uint64_t mp_affinity; /* MP ID without feature bits */
-    /* The elements of this array are the CCSIDR values for each cache,
-     * in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
-     */
-    uint64_t ccsidr[16];
     uint64_t reset_cbar;
     uint32_t reset_auxcr;
     bool reset_hivecs;
@@ -2107,8 +2103,6 @@ FIELD(MFAR, FPA, 12, 40)
 FIELD(MFAR, NSE, 62, 1)
 FIELD(MFAR, NS, 63, 1)
 
-QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= R_V7M_CSSELR_INDEX_MASK);
-
 /* If adding a feature bit which corresponds to a Linux ELF
  * HWCAP bit, remember to update the feature-bit-to-hwcap
  * mapping in linux-user/elfload.c:get_elf_hwcap().
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 4dfc03973e17..798769a42bd3 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -684,11 +684,11 @@ static void aarch64_a57_initfn(Object *obj)
     cpu->isar.reset_pmcr_el0 = 0x41013000;
     SET_IDREG(isar, CLIDR, 0x0a200023);
     /* 32KB L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7));
     /* 48KB L1 icache */
-    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 3, 64, 48 * KiB, 2);
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 3, 64, 48 * KiB, 2));
     /* 2048KB L2 cache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 2 * MiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 2 * MiB, 7));
     set_dczid_bs(cpu, 4); /* 64 bytes */
     cpu->gic_num_lrs = 4;
     cpu->gic_vpribits = 5;
@@ -746,11 +746,11 @@ static void aarch64_a53_initfn(Object *obj)
     cpu->isar.reset_pmcr_el0 = 0x41033000;
     SET_IDREG(isar, CLIDR, 0x0a200023);
     /* 32KB L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7));
     /* 32KB L1 icache */
-    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 1, 64, 32 * KiB, 2);
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 1, 64, 32 * KiB, 2));
     /* 1024KB L2 cache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 1 * MiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 1 * MiB, 7));
     set_dczid_bs(cpu, 4); /* 64 bytes */
     cpu->gic_num_lrs = 4;
     cpu->gic_vpribits = 5;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e86ceb130ce9..f1c771461589 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -875,7 +875,7 @@ static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
     uint32_t index = A32_BANKED_REG_GET(env, csselr,
                                         ri->secure & ARM_CP_SECSTATE_S);
 
-    return cpu->ccsidr[index];
+    return GET_IDREG_DEMUX(&cpu->isar, CCSIDR, index);
 }
 
 static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
index 0b0bc96bac22..75b627f609f5 100644
--- a/target/arm/tcg/cpu32.c
+++ b/target/arm/tcg/cpu32.c
@@ -372,9 +372,9 @@ static void cortex_a8_initfn(Object *obj)
     SET_IDREG(isar, ID_ISAR4, 0x00111142);
     cpu->isar.dbgdidr = 0x15141000;
     SET_IDREG(isar, CLIDR, (1 << 27) | (2 << 24) | 3);
-    cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
-    cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
-    cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0xe007e01a); /* 16k L1 dcache. */
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x2007e01a); /* 16k L1 icache. */
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, 0xf0000000); /* No L2 icache. */
     cpu->reset_auxcr = 2;
     cpu->isar.reset_pmcr_el0 = 0x41002000;
     define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
@@ -448,8 +448,8 @@ static void cortex_a9_initfn(Object *obj)
     SET_IDREG(isar, ID_ISAR4, 0x00111142);
     cpu->isar.dbgdidr = 0x35141000;
     SET_IDREG(isar, CLIDR, (1 << 27) | (1 << 24) | 3);
-    cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
-    cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0xe00fe019); /* 16k L1 dcache. */
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x200fe019); /* 16k L1 icache. */
     cpu->isar.reset_pmcr_el0 = 0x41093000;
     define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
 }
@@ -520,9 +520,9 @@ static void cortex_a7_initfn(Object *obj)
     cpu->isar.dbgdevid = 0x01110f13;
     cpu->isar.dbgdevid1 = 0x1;
     SET_IDREG(isar, CLIDR, 0x0a200023);
-    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
-    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
-    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0x701fe00a); /* 32K L1 dcache */
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x201fe00a); /* 32K L1 icache */
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, 0x711fe07a); /* 4096K L2 unified cache */
     cpu->isar.reset_pmcr_el0 = 0x41072000;
     define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
 }
@@ -568,9 +568,9 @@ static void cortex_a15_initfn(Object *obj)
     cpu->isar.dbgdevid = 0x01110f13;
     cpu->isar.dbgdevid1 = 0x0;
     SET_IDREG(isar, CLIDR, 0x0a200023);
-    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
-    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
-    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0x701fe00a); /* 32K L1 dcache */
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x201fe00a); /* 32K L1 icache */
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, 0x711fe07a); /* 4096K L2 unified cache */
     cpu->isar.reset_pmcr_el0 = 0x410F3000;
     define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
 }
@@ -759,8 +759,8 @@ static void cortex_r52_initfn(Object *obj)
     SET_IDREG(isar, ID_ISAR5, 0x00010001);
     cpu->isar.dbgdidr = 0x77168000;
     SET_IDREG(isar, CLIDR, (1 << 27) | (1 << 24) | 0x3);
-    cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */
-    cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0x700fe01a); /* 32KB L1 dcache */
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x201fe00a); /* 32KB L1 icache */
 
     cpu->pmsav7_dregion = 16;
     cpu->pmsav8r_hdregion = 16;
@@ -853,9 +853,9 @@ static void arm_max_initfn(Object *obj)
     SET_IDREG(isar, ID_ISAR6, 0);
     cpu->isar.reset_pmcr_el0 = 0x41013000;
     SET_IDREG(isar, CLIDR, 0x0a200023);
-    cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
-    cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
-    cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0x701fe00a); /* 32KB L1 dcache */
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x201fe012); /* 48KB L1 icache */
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, 0x70ffe07a); /* 2048KB L2 cache */
     define_cortex_a72_a57_a53_cp_reginfo(cpu);
 
     aa32_max_features(cpu);
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index fa80e48d2beb..3634af5dabf5 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -82,11 +82,11 @@ static void aarch64_a35_initfn(Object *obj)
 
     /* From B2.29 Cache ID registers */
     /* 32KB L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7));
     /* 32KB L1 icache */
-    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 2);
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 2));
     /* 512KB L2 cache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 512 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 512 * KiB, 7));
 
     /* From B3.5 VGIC Type register */
     cpu->gic_num_lrs = 4;
@@ -250,11 +250,11 @@ static void aarch64_a55_initfn(Object *obj)
 
     /* From B2.23 CCSIDR_EL1 */
     /* 32KB L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7));
     /* 32KB L1 icache */
-    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 2);
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 2));
     /* 512KB L2 cache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 512 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 512 * KiB, 7));
 
     /* From B2.96 SCTLR_EL3 */
     cpu->reset_sctlr = 0x30c50838;
@@ -320,11 +320,11 @@ static void aarch64_a72_initfn(Object *obj)
     cpu->isar.reset_pmcr_el0 = 0x41023000;
     SET_IDREG(isar, CLIDR, 0x0a200023);
     /* 32KB L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7));
     /* 48KB L1 dcache */
-    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 3, 64, 48 * KiB, 2);
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 3, 64, 48 * KiB, 2));
     /* 1MB L2 cache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 1 * MiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 1 * MiB, 7));
     set_dczid_bs(cpu, 4); /* 64 bytes */
     cpu->gic_num_lrs = 4;
     cpu->gic_vpribits = 5;
@@ -383,11 +383,11 @@ static void aarch64_a76_initfn(Object *obj)
 
     /* From B2.18 CCSIDR_EL1 */
     /* 64KB L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7));
     /* 64KB L1 icache */
-    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2);
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2));
     /* 512KB L2 cache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 512 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 512 * KiB, 7));
 
     /* From B2.93 SCTLR_EL3 */
     cpu->reset_sctlr = 0x30c50838;
@@ -455,11 +455,11 @@ static void aarch64_a78ae_initfn(Object *obj)
 
     /* From 3.2.33 CCSIDR_EL1 */
     /* 64KB L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7));
     /* 64KB L1 icache */
-    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2);
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2));
     /* 512KB L2 cache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 512 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 512 * KiB, 7));
 
     /* From 3.2.118 SCTLR_EL3 */
     cpu->reset_sctlr = 0x30c50838;
@@ -512,11 +512,11 @@ static void aarch64_a64fx_initfn(Object *obj)
     SET_IDREG(isar, ID_AA64ZFR0, 0x0000000000000000);
     SET_IDREG(isar, CLIDR, 0x0000000080000023);
     /* 64KB L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 256, 64 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 256, 64 * KiB, 7));
     /* 64KB L1 icache */
-    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 256, 64 * KiB, 2);
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 256, 64 * KiB, 2));
     /* 8MB L2 cache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 256, 8 * MiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 256, 8 * MiB, 7));
     set_dczid_bs(cpu, 6); /* 256 bytes */
     cpu->gic_num_lrs = 4;
     cpu->gic_vpribits = 5;
@@ -704,11 +704,11 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
 
     /* From B2.23 CCSIDR_EL1 */
     /* 64KB L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7));
     /* 64KB L1 icache */
-    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2);
+    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2));
     /* 1MB L2 dcache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 1 * MiB, 7);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 1 * MiB, 7));
 
     /* From B2.98 SCTLR_EL3 */
     cpu->reset_sctlr = 0x30c50838;
@@ -792,11 +792,11 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
      * L3: No L3 (this matches the CLIDR_EL1 value).
      */
     /* 64KB L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
     /* 64KB L1 icache */
-    cpu->ccsidr[1] = cpu->ccsidr[0];
+    COPY_IDREG_DEMUX(isar, CCSIDR, 0, 1);
     /* 1MB L2 cache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 1 * MiB, 0);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 1 * MiB, 0));
 
     /* From 3.2.115 SCTLR_EL3 */
     cpu->reset_sctlr = 0x30c50838;
@@ -1034,11 +1034,11 @@ static void aarch64_a710_initfn(Object *obj)
      * L2: 8-way set associative 64 byte line size, total either 256K or 512K.
      */
     /* L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
     /* L1 icache */
-    cpu->ccsidr[1] = cpu->ccsidr[0];
+    COPY_IDREG_DEMUX(isar, CCSIDR, 0, 1);
     /* L2 cache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0));
 
     /* FIXME: Not documented -- copied from neoverse-v1 */
     cpu->reset_sctlr = 0x30c50838;
@@ -1136,11 +1136,11 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
      * L2: 8-way set associative 64 byte line size, total either 512K or 1024K.
      */
     /* L1 dcache */
-    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0);
+    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
     /* L1 icache */
-    cpu->ccsidr[1] = cpu->ccsidr[0];
+    COPY_IDREG_DEMUX(isar, CCSIDR, 0, 1);
     /* L2 cache */
-    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0);
+    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0));
     /* FIXME: Not documented -- copied from neoverse-v1 */
     cpu->reset_sctlr = 0x30c50838;
 
-- 
2.52.0



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

* [PATCH v2 3/3] arm/kvm: get demuxed ID registers from kvm
  2026-02-04 13:32 [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1) Cornelia Huck
  2026-02-04 13:32 ` [PATCH v2 1/3] arm: handle demuxed ID registers Cornelia Huck
  2026-02-04 13:32 ` [PATCH v2 2/3] arm: handle CCSIDR_EL1 as a demuxed register Cornelia Huck
@ 2026-02-04 13:32 ` Cornelia Huck
  2026-04-01 17:00   ` Eric Auger
  2026-02-05 11:52 ` [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1) Peter Maydell
  3 siblings, 1 reply; 10+ messages in thread
From: Cornelia Huck @ 2026-02-04 13:32 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Peter Maydell, Eric Auger, Sebastian Ott, Jonathan Cameron,
	Alireza Sanaee, Cornelia Huck

We now have the infrastructure in place to get and save demuxed ID
registers from kvm. Use it to get the values that kvm emulates for
CCSIDR_EL1.

Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>
Reviewed-by: Sebastian Ott <sebott@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 target/arm/kvm.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 0828e8b87bac..9ed51969f075 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -243,6 +243,33 @@ static int get_host_cpu_reg(int fd, ARMHostCPUFeatures *ahcf,
     return ret;
 }
 
+static int get_host_cpu_reg_demux(int fd, ARMHostCPUFeatures *ahcf,
+                                  ARMIDRegisterIdx index, int subindex)
+{
+
+    struct kvm_one_reg one_reg = {
+        .id = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX,
+    };
+    ARMIDRegisterDemuxIdx demux_index;
+
+    switch (index) {
+    case CCSIDR_EL1_IDX:
+        if (subindex < 14) {
+            one_reg.id |= KVM_REG_ARM_DEMUX_ID_CCSIDR | subindex;
+        } else {
+            return -EINVAL;
+        }
+        demux_index = CCSIDR_EL1_DEMUX_IDX;
+        break;
+    default:
+        return -EINVAL;
+    }
+    one_reg.addr = (uintptr_t)&ahcf->isar.idregs_demux[demux_index][subindex];
+
+    return ioctl(fd, KVM_GET_ONE_REG, &one_reg);
+
+}
+
 static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
 {
     /* Identify the feature bits corresponding to the host CPU, and
@@ -256,6 +283,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
     bool pmu_supported = false;
     uint64_t features = 0;
     int err;
+    int i;
 
     /*
      * target = -1 informs kvm_arm_create_scratch_host_vcpu()
@@ -416,6 +444,11 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
              */
             err |= get_host_cpu_reg(fd, ahcf, ID_AA64ZFR0_EL1_IDX);
         }
+        /* grab demuxed registers */
+        for (i = 0; i < 14; i++) {
+            /* KVM only allows 0..13 */
+            err |= get_host_cpu_reg_demux(fd, ahcf, CCSIDR_EL1_IDX, i);
+        }
     }
 
     kvm_arm_destroy_scratch_host_vcpu(fdarray);
-- 
2.52.0



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

* Re: [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1)
  2026-02-04 13:32 [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1) Cornelia Huck
                   ` (2 preceding siblings ...)
  2026-02-04 13:32 ` [PATCH v2 3/3] arm/kvm: get demuxed ID registers from kvm Cornelia Huck
@ 2026-02-05 11:52 ` Peter Maydell
  2026-02-05 16:50   ` Cornelia Huck
  3 siblings, 1 reply; 10+ messages in thread
From: Peter Maydell @ 2026-02-05 11:52 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: qemu-arm, qemu-devel, Eric Auger, Sebastian Ott, Jonathan Cameron,
	Alireza Sanaee

On Wed, 4 Feb 2026 at 13:32, Cornelia Huck <cohuck@redhat.com> wrote:
> RFC because there are still some open questions:

> - There's a slight disagreement between the current code (providing 16
>   entries for CCSIDR_EL1) and the KVM code (providing (7 cache levels) *
>   (data/unified, instruction) = 14 entries.) With FEAT_MTE2, we might be
>   needing 7 more entries.

This is because architecturally the CCSELR_EL1 register is:
 bit 4 : TnD (tag-not-data)
 bits [3:1] : level
 bit 0 : InD (instruction-not-data)

but the 'level' field has 0b111 as Reserved, and KVM doesn't
(currently) handle the FEAT_MTE2 TnD bit, so from KVM's point
of view only 0..13 are valid values here.

The architecture says that if you set CSSELR_EL1 to an invalid
setting then reading CCSIDR_EL1 can be:
 * a NOP
 * UNDEF
 * return an UNKNOWN value

For TCG we opted to permit any indexes 0..15, so that we treat
the architecturally invalid 0b1110 and 0b1111 the same way as
we treat "you picked a level this particular CPU doesn't implement"
(and return a 0 from our cpu->cssidr[] array). Otherwise we would
have had to add an extra check for "and level isn't invalid".

TCG also doesn't do anything with the FEAT_MTE2 TnD bit: looks
like we missed that functionality when we added MTE2 emulation.
Setting TnD and InD at once isn't a valid combination, so we
could either extend our cpu->ccsidr[] array to 32 words (and
live with 8 of the extras being unused), or else add a new
8-word array for the MTE tag-cache ID values.

-- PMM


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

* Re: [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1)
  2026-02-05 11:52 ` [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1) Peter Maydell
@ 2026-02-05 16:50   ` Cornelia Huck
  0 siblings, 0 replies; 10+ messages in thread
From: Cornelia Huck @ 2026-02-05 16:50 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-arm, qemu-devel, Eric Auger, Sebastian Ott, Jonathan Cameron,
	Alireza Sanaee

On Thu, Feb 05 2026, Peter Maydell <peter.maydell@linaro.org> wrote:

> On Wed, 4 Feb 2026 at 13:32, Cornelia Huck <cohuck@redhat.com> wrote:
>> RFC because there are still some open questions:
>
>> - There's a slight disagreement between the current code (providing 16
>>   entries for CCSIDR_EL1) and the KVM code (providing (7 cache levels) *
>>   (data/unified, instruction) = 14 entries.) With FEAT_MTE2, we might be
>>   needing 7 more entries.
>
> This is because architecturally the CCSELR_EL1 register is:
>  bit 4 : TnD (tag-not-data)
>  bits [3:1] : level
>  bit 0 : InD (instruction-not-data)
>
> but the 'level' field has 0b111 as Reserved, and KVM doesn't
> (currently) handle the FEAT_MTE2 TnD bit, so from KVM's point
> of view only 0..13 are valid values here.
>
> The architecture says that if you set CSSELR_EL1 to an invalid
> setting then reading CCSIDR_EL1 can be:
>  * a NOP
>  * UNDEF
>  * return an UNKNOWN value
>
> For TCG we opted to permit any indexes 0..15, so that we treat
> the architecturally invalid 0b1110 and 0b1111 the same way as
> we treat "you picked a level this particular CPU doesn't implement"
> (and return a 0 from our cpu->cssidr[] array). Otherwise we would
> have had to add an extra check for "and level isn't invalid".

That makes sense.

>
> TCG also doesn't do anything with the FEAT_MTE2 TnD bit: looks
> like we missed that functionality when we added MTE2 emulation.
> Setting TnD and InD at once isn't a valid combination, so we
> could either extend our cpu->ccsidr[] array to 32 words (and
> live with 8 of the extras being unused), or else add a new
> 8-word array for the MTE tag-cache ID values.

Whatever we do, it would be easiest if KVM and TCG followed a similar
approach, so we don't end up having to special case the code.

As KVM also supports setting (virtual) CCSIDR_EL1 values, I think just
extending the array would be easiest, so that QEMU can just keep
everything in one place.



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

* Re: [PATCH v2 2/3] arm: handle CCSIDR_EL1 as a demuxed register
  2026-02-04 13:32 ` [PATCH v2 2/3] arm: handle CCSIDR_EL1 as a demuxed register Cornelia Huck
@ 2026-04-01 16:46   ` Eric Auger
  2026-04-02 15:04     ` Cornelia Huck
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Auger @ 2026-04-01 16:46 UTC (permalink / raw)
  To: Cornelia Huck, qemu-arm, qemu-devel
  Cc: Peter Maydell, Sebastian Ott, Jonathan Cameron, Alireza Sanaee

Hi Connie,

On 2/4/26 2:32 PM, Cornelia Huck wrote:
> Move handling of CCSIDR_EL1 over to the new *_IDREG_DEMUX
> infrastructure.
>
> Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>
> Reviewed-by: Sebastian Ott <sebott@redhat.com>
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> ---
>  hw/intc/armv7m_nvic.c        |  2 +-
>  target/arm/cpu-sysregs.h     |  1 +
>  target/arm/cpu-sysregs.h.inc |  1 +
>  target/arm/cpu.h             |  6 ----
>  target/arm/cpu64.c           | 12 ++++----
>  target/arm/helper.c          |  2 +-
>  target/arm/tcg/cpu32.c       | 32 +++++++++----------
>  target/arm/tcg/cpu64.c       | 60 ++++++++++++++++++------------------
>  8 files changed, 56 insertions(+), 60 deletions(-)
>
> diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
> index 28b34e99446f..271d16692910 100644
> --- a/hw/intc/armv7m_nvic.c
> +++ b/hw/intc/armv7m_nvic.c
> @@ -1337,7 +1337,7 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
>      case 0xd80: /* CSSIDR */
>      {
>          int idx = cpu->env.v7m.csselr[attrs.secure] & R_V7M_CSSELR_INDEX_MASK;
> -        return cpu->ccsidr[idx];
> +        return GET_IDREG_DEMUX(&cpu->isar, CCSIDR, idx);
>      }
>      case 0xd84: /* CSSELR */
>          return cpu->env.v7m.csselr[attrs.secure];
> diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h
> index 911f54bc8a4f..ec04174d4a99 100644
> --- a/target/arm/cpu-sysregs.h
> +++ b/target/arm/cpu-sysregs.h
> @@ -37,6 +37,7 @@ typedef enum ARMSysRegs {
>  
>  /* ID registers that vary based upon another register */
>  typedef enum ARMIDRegisterDemuxIdx {
> +    CCSIDR_EL1_DEMUX_IDX,
>      NUM_ID_DEMUX_IDX,
>  } ARMIDRegisterDemuxIdx;
>  
> diff --git a/target/arm/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc
> index 3d1ed40f0439..ed466ffb7318 100644
> --- a/target/arm/cpu-sysregs.h.inc
> +++ b/target/arm/cpu-sysregs.h.inc
> @@ -37,6 +37,7 @@ DEF(MVFR2_EL1, 3, 0, 0, 3, 2)
>  DEF(ID_PFR2_EL1, 3, 0, 0, 3, 4)
>  DEF(ID_DFR1_EL1, 3, 0, 0, 3, 5)
>  DEF(ID_MMFR5_EL1, 3, 0, 0, 3, 6)
> +DEF(CCSIDR_EL1, 3, 1, 0, 0, 0)
Currently, in [PATCH 0/3] Generate target/arm/cpu-sysregs.h.inc from
AARCHMRS Registers.json
and especially [PATCH 1/3] scripts: introduce
scripts/update-aarch64-sysreg-code.py
(https://lore.kernel.org/all/20251208163751.611186-4-eric.auger@redhat.com/)


CCSIDR_EL1 is not automatically generated. 

as target/arm/cpu-sysregs.h.inc should be eventually automatically generated, shouldn't we put this definition somewhere else or do we expect to also automatically generate this demux idreg?


>  DEF(CLIDR_EL1, 3, 1, 0, 0, 1)
>  DEF(ID_AA64ZFR0_EL1, 3, 0, 0, 4, 4)
>  DEF(CTR_EL0, 3, 3, 0, 0, 1)
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index f9d51c0fc187..b26922ea4298 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1113,10 +1113,6 @@ struct ArchCPU {
>      uint64_t pmceid0;
>      uint64_t pmceid1;
>      uint64_t mp_affinity; /* MP ID without feature bits */
> -    /* The elements of this array are the CCSIDR values for each cache,
> -     * in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
> -     */
> -    uint64_t ccsidr[16];
>      uint64_t reset_cbar;
>      uint32_t reset_auxcr;
>      bool reset_hivecs;
> @@ -2107,8 +2103,6 @@ FIELD(MFAR, FPA, 12, 40)
>  FIELD(MFAR, NSE, 62, 1)
>  FIELD(MFAR, NS, 63, 1)
>  
> -QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= R_V7M_CSSELR_INDEX_MASK);
> -
>  /* If adding a feature bit which corresponds to a Linux ELF
>   * HWCAP bit, remember to update the feature-bit-to-hwcap
>   * mapping in linux-user/elfload.c:get_elf_hwcap().
> diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
> index 4dfc03973e17..798769a42bd3 100644
> --- a/target/arm/cpu64.c
> +++ b/target/arm/cpu64.c
> @@ -684,11 +684,11 @@ static void aarch64_a57_initfn(Object *obj)
>      cpu->isar.reset_pmcr_el0 = 0x41013000;
>      SET_IDREG(isar, CLIDR, 0x0a200023);
>      /* 32KB L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7));
>      /* 48KB L1 icache */
> -    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 3, 64, 48 * KiB, 2);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 3, 64, 48 * KiB, 2));
>      /* 2048KB L2 cache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 2 * MiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 2 * MiB, 7));
>      set_dczid_bs(cpu, 4); /* 64 bytes */
>      cpu->gic_num_lrs = 4;
>      cpu->gic_vpribits = 5;
> @@ -746,11 +746,11 @@ static void aarch64_a53_initfn(Object *obj)
>      cpu->isar.reset_pmcr_el0 = 0x41033000;
>      SET_IDREG(isar, CLIDR, 0x0a200023);
>      /* 32KB L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7));
>      /* 32KB L1 icache */
> -    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 1, 64, 32 * KiB, 2);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 1, 64, 32 * KiB, 2));
>      /* 1024KB L2 cache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 1 * MiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 1 * MiB, 7));
>      set_dczid_bs(cpu, 4); /* 64 bytes */
>      cpu->gic_num_lrs = 4;
>      cpu->gic_vpribits = 5;
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index e86ceb130ce9..f1c771461589 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -875,7 +875,7 @@ static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
>      uint32_t index = A32_BANKED_REG_GET(env, csselr,
>                                          ri->secure & ARM_CP_SECSTATE_S);
>  
> -    return cpu->ccsidr[index];
> +    return GET_IDREG_DEMUX(&cpu->isar, CCSIDR, index);
>  }
>  
>  static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
> index 0b0bc96bac22..75b627f609f5 100644
> --- a/target/arm/tcg/cpu32.c
> +++ b/target/arm/tcg/cpu32.c
> @@ -372,9 +372,9 @@ static void cortex_a8_initfn(Object *obj)
>      SET_IDREG(isar, ID_ISAR4, 0x00111142);
>      cpu->isar.dbgdidr = 0x15141000;
>      SET_IDREG(isar, CLIDR, (1 << 27) | (2 << 24) | 3);
> -    cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
> -    cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
> -    cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0xe007e01a); /* 16k L1 dcache. */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x2007e01a); /* 16k L1 icache. */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, 0xf0000000); /* No L2 icache. */
>      cpu->reset_auxcr = 2;
>      cpu->isar.reset_pmcr_el0 = 0x41002000;
>      define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
> @@ -448,8 +448,8 @@ static void cortex_a9_initfn(Object *obj)
>      SET_IDREG(isar, ID_ISAR4, 0x00111142);
>      cpu->isar.dbgdidr = 0x35141000;
>      SET_IDREG(isar, CLIDR, (1 << 27) | (1 << 24) | 3);
> -    cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
> -    cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0xe00fe019); /* 16k L1 dcache. */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x200fe019); /* 16k L1 icache. */
>      cpu->isar.reset_pmcr_el0 = 0x41093000;
>      define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
>  }
> @@ -520,9 +520,9 @@ static void cortex_a7_initfn(Object *obj)
>      cpu->isar.dbgdevid = 0x01110f13;
>      cpu->isar.dbgdevid1 = 0x1;
>      SET_IDREG(isar, CLIDR, 0x0a200023);
> -    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
> -    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
> -    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0x701fe00a); /* 32K L1 dcache */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x201fe00a); /* 32K L1 icache */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, 0x711fe07a); /* 4096K L2 unified cache */
>      cpu->isar.reset_pmcr_el0 = 0x41072000;
>      define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
>  }
> @@ -568,9 +568,9 @@ static void cortex_a15_initfn(Object *obj)
>      cpu->isar.dbgdevid = 0x01110f13;
>      cpu->isar.dbgdevid1 = 0x0;
>      SET_IDREG(isar, CLIDR, 0x0a200023);
> -    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
> -    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
> -    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0x701fe00a); /* 32K L1 dcache */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x201fe00a); /* 32K L1 icache */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, 0x711fe07a); /* 4096K L2 unified cache */
>      cpu->isar.reset_pmcr_el0 = 0x410F3000;
>      define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
>  }
> @@ -759,8 +759,8 @@ static void cortex_r52_initfn(Object *obj)
>      SET_IDREG(isar, ID_ISAR5, 0x00010001);
>      cpu->isar.dbgdidr = 0x77168000;
>      SET_IDREG(isar, CLIDR, (1 << 27) | (1 << 24) | 0x3);
> -    cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */
> -    cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0x700fe01a); /* 32KB L1 dcache */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x201fe00a); /* 32KB L1 icache */
>  
>      cpu->pmsav7_dregion = 16;
>      cpu->pmsav8r_hdregion = 16;
> @@ -853,9 +853,9 @@ static void arm_max_initfn(Object *obj)
>      SET_IDREG(isar, ID_ISAR6, 0);
>      cpu->isar.reset_pmcr_el0 = 0x41013000;
>      SET_IDREG(isar, CLIDR, 0x0a200023);
> -    cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
> -    cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
> -    cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, 0x701fe00a); /* 32KB L1 dcache */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, 0x201fe012); /* 48KB L1 icache */
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, 0x70ffe07a); /* 2048KB L2 cache */
>      define_cortex_a72_a57_a53_cp_reginfo(cpu);
>  
>      aa32_max_features(cpu);
> diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
> index fa80e48d2beb..3634af5dabf5 100644
> --- a/target/arm/tcg/cpu64.c
> +++ b/target/arm/tcg/cpu64.c
> @@ -82,11 +82,11 @@ static void aarch64_a35_initfn(Object *obj)
>  
>      /* From B2.29 Cache ID registers */
>      /* 32KB L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7));
>      /* 32KB L1 icache */
> -    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 2);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 2));
>      /* 512KB L2 cache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 512 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 512 * KiB, 7));
>  
>      /* From B3.5 VGIC Type register */
>      cpu->gic_num_lrs = 4;
> @@ -250,11 +250,11 @@ static void aarch64_a55_initfn(Object *obj)
>  
>      /* From B2.23 CCSIDR_EL1 */
>      /* 32KB L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7));
>      /* 32KB L1 icache */
> -    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 2);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 2));
>      /* 512KB L2 cache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 512 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 512 * KiB, 7));
>  
>      /* From B2.96 SCTLR_EL3 */
>      cpu->reset_sctlr = 0x30c50838;
> @@ -320,11 +320,11 @@ static void aarch64_a72_initfn(Object *obj)
>      cpu->isar.reset_pmcr_el0 = 0x41023000;
>      SET_IDREG(isar, CLIDR, 0x0a200023);
>      /* 32KB L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7));
>      /* 48KB L1 dcache */
> -    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 3, 64, 48 * KiB, 2);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 3, 64, 48 * KiB, 2));
>      /* 1MB L2 cache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 1 * MiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 1 * MiB, 7));
>      set_dczid_bs(cpu, 4); /* 64 bytes */
>      cpu->gic_num_lrs = 4;
>      cpu->gic_vpribits = 5;
> @@ -383,11 +383,11 @@ static void aarch64_a76_initfn(Object *obj)
>  
>      /* From B2.18 CCSIDR_EL1 */
>      /* 64KB L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7));
>      /* 64KB L1 icache */
> -    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2));
>      /* 512KB L2 cache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 512 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 512 * KiB, 7));
>  
>      /* From B2.93 SCTLR_EL3 */
>      cpu->reset_sctlr = 0x30c50838;
> @@ -455,11 +455,11 @@ static void aarch64_a78ae_initfn(Object *obj)
>  
>      /* From 3.2.33 CCSIDR_EL1 */
>      /* 64KB L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7));
>      /* 64KB L1 icache */
> -    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2));
>      /* 512KB L2 cache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 512 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 512 * KiB, 7));
>  
>      /* From 3.2.118 SCTLR_EL3 */
>      cpu->reset_sctlr = 0x30c50838;
> @@ -512,11 +512,11 @@ static void aarch64_a64fx_initfn(Object *obj)
>      SET_IDREG(isar, ID_AA64ZFR0, 0x0000000000000000);
>      SET_IDREG(isar, CLIDR, 0x0000000080000023);
>      /* 64KB L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 256, 64 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 256, 64 * KiB, 7));
>      /* 64KB L1 icache */
> -    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 256, 64 * KiB, 2);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 256, 64 * KiB, 2));
>      /* 8MB L2 cache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 256, 8 * MiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 256, 8 * MiB, 7));
>      set_dczid_bs(cpu, 6); /* 256 bytes */
>      cpu->gic_num_lrs = 4;
>      cpu->gic_vpribits = 5;
> @@ -704,11 +704,11 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
>  
>      /* From B2.23 CCSIDR_EL1 */
>      /* 64KB L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7));
>      /* 64KB L1 icache */
> -    cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2));
>      /* 1MB L2 dcache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 1 * MiB, 7);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 1 * MiB, 7));
>  
>      /* From B2.98 SCTLR_EL3 */
>      cpu->reset_sctlr = 0x30c50838;
> @@ -792,11 +792,11 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
>       * L3: No L3 (this matches the CLIDR_EL1 value).
>       */
>      /* 64KB L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
>      /* 64KB L1 icache */
> -    cpu->ccsidr[1] = cpu->ccsidr[0];
> +    COPY_IDREG_DEMUX(isar, CCSIDR, 0, 1);
nit: maybe we don't need a COPY but do get + set, if it is just used in
this file. Or if we keep copy maybe use the memcpy convention?

Eric
>      /* 1MB L2 cache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 1 * MiB, 0);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 1 * MiB, 0));
>  
>      /* From 3.2.115 SCTLR_EL3 */
>      cpu->reset_sctlr = 0x30c50838;
> @@ -1034,11 +1034,11 @@ static void aarch64_a710_initfn(Object *obj)
>       * L2: 8-way set associative 64 byte line size, total either 256K or 512K.
>       */
>      /* L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
>      /* L1 icache */
> -    cpu->ccsidr[1] = cpu->ccsidr[0];
> +    COPY_IDREG_DEMUX(isar, CCSIDR, 0, 1);
>      /* L2 cache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0));
>  
>      /* FIXME: Not documented -- copied from neoverse-v1 */
>      cpu->reset_sctlr = 0x30c50838;
> @@ -1136,11 +1136,11 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
>       * L2: 8-way set associative 64 byte line size, total either 512K or 1024K.
>       */
>      /* L1 dcache */
> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
>      /* L1 icache */
> -    cpu->ccsidr[1] = cpu->ccsidr[0];
> +    COPY_IDREG_DEMUX(isar, CCSIDR, 0, 1);
>      /* L2 cache */
> -    cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0);
> +    SET_IDREG_DEMUX(isar, CCSIDR, 2, make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0));
>      /* FIXME: Not documented -- copied from neoverse-v1 */
>      cpu->reset_sctlr = 0x30c50838;
>  



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

* Re: [PATCH v2 3/3] arm/kvm: get demuxed ID registers from kvm
  2026-02-04 13:32 ` [PATCH v2 3/3] arm/kvm: get demuxed ID registers from kvm Cornelia Huck
@ 2026-04-01 17:00   ` Eric Auger
  2026-04-02 15:19     ` Cornelia Huck
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Auger @ 2026-04-01 17:00 UTC (permalink / raw)
  To: Cornelia Huck, qemu-arm, qemu-devel
  Cc: Peter Maydell, Sebastian Ott, Jonathan Cameron, Alireza Sanaee



On 2/4/26 2:32 PM, Cornelia Huck wrote:
> We now have the infrastructure in place to get and save demuxed ID
Here we only get their values? What about the save?
> registers from kvm. Use it to get the values that kvm emulates for
> CCSIDR_EL1.
>
> Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>
> Reviewed-by: Sebastian Ott <sebott@redhat.com>
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> ---
>  target/arm/kvm.c | 33 +++++++++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
>
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index 0828e8b87bac..9ed51969f075 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -243,6 +243,33 @@ static int get_host_cpu_reg(int fd, ARMHostCPUFeatures *ahcf,
>      return ret;
>  }
>  
> +static int get_host_cpu_reg_demux(int fd, ARMHostCPUFeatures *ahcf,
> +                                  ARMIDRegisterIdx index, int subindex)
> +{
> +
> +    struct kvm_one_reg one_reg = {
> +        .id = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX,
> +    };
> +    ARMIDRegisterDemuxIdx demux_index;
> +
> +    switch (index) {
> +    case CCSIDR_EL1_IDX:
> +        if (subindex < 14) {
> +            one_reg.id |= KVM_REG_ARM_DEMUX_ID_CCSIDR | subindex;
> +        } else {
> +            return -EINVAL;
> +        }
> +        demux_index = CCSIDR_EL1_DEMUX_IDX;
> +        break;
> +    default:
> +        return -EINVAL;
> +    }
> +    one_reg.addr = (uintptr_t)&ahcf->isar.idregs_demux[demux_index][subindex];
> +
> +    return ioctl(fd, KVM_GET_ONE_REG, &one_reg);
> +
> +}
> +
>  static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
>  {
>      /* Identify the feature bits corresponding to the host CPU, and
> @@ -256,6 +283,7 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
>      bool pmu_supported = false;
>      uint64_t features = 0;
>      int err;
> +    int i;
>  
>      /*
>       * target = -1 informs kvm_arm_create_scratch_host_vcpu()
> @@ -416,6 +444,11 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
>               */
>              err |= get_host_cpu_reg(fd, ahcf, ID_AA64ZFR0_EL1_IDX);
>          }
> +        /* grab demuxed registers */
> +        for (i = 0; i < 14; i++) {
> +            /* KVM only allows 0..13 */
where is it documented? Maybe add a comment or justification in the
commit msg. Use a define?
> +            err |= get_host_cpu_reg_demux(fd, ahcf, CCSIDR_EL1_IDX, i);
> +        }
>      }
>  
>      kvm_arm_destroy_scratch_host_vcpu(fdarray);
Thanks

Eric



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

* Re: [PATCH v2 2/3] arm: handle CCSIDR_EL1 as a demuxed register
  2026-04-01 16:46   ` Eric Auger
@ 2026-04-02 15:04     ` Cornelia Huck
  0 siblings, 0 replies; 10+ messages in thread
From: Cornelia Huck @ 2026-04-02 15:04 UTC (permalink / raw)
  To: eric.auger, qemu-arm, qemu-devel
  Cc: Peter Maydell, Sebastian Ott, Jonathan Cameron, Alireza Sanaee

On Wed, Apr 01 2026, Eric Auger <eric.auger@redhat.com> wrote:

> Hi Connie,
>
> On 2/4/26 2:32 PM, Cornelia Huck wrote:
>> Move handling of CCSIDR_EL1 over to the new *_IDREG_DEMUX
>> infrastructure.
>>
>> Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>
>> Reviewed-by: Sebastian Ott <sebott@redhat.com>
>> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
>> ---
>>  hw/intc/armv7m_nvic.c        |  2 +-
>>  target/arm/cpu-sysregs.h     |  1 +
>>  target/arm/cpu-sysregs.h.inc |  1 +
>>  target/arm/cpu.h             |  6 ----
>>  target/arm/cpu64.c           | 12 ++++----
>>  target/arm/helper.c          |  2 +-
>>  target/arm/tcg/cpu32.c       | 32 +++++++++----------
>>  target/arm/tcg/cpu64.c       | 60 ++++++++++++++++++------------------
>>  8 files changed, 56 insertions(+), 60 deletions(-)
>> diff --git a/target/arm/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc
>> index 3d1ed40f0439..ed466ffb7318 100644
>> --- a/target/arm/cpu-sysregs.h.inc
>> +++ b/target/arm/cpu-sysregs.h.inc
>> @@ -37,6 +37,7 @@ DEF(MVFR2_EL1, 3, 0, 0, 3, 2)
>>  DEF(ID_PFR2_EL1, 3, 0, 0, 3, 4)
>>  DEF(ID_DFR1_EL1, 3, 0, 0, 3, 5)
>>  DEF(ID_MMFR5_EL1, 3, 0, 0, 3, 6)
>> +DEF(CCSIDR_EL1, 3, 1, 0, 0, 0)
> Currently, in [PATCH 0/3] Generate target/arm/cpu-sysregs.h.inc from
> AARCHMRS Registers.json
> and especially [PATCH 1/3] scripts: introduce
> scripts/update-aarch64-sysreg-code.py
> (https://lore.kernel.org/all/20251208163751.611186-4-eric.auger@redhat.com/)
>
>
> CCSIDR_EL1 is not automatically generated. 
>
> as target/arm/cpu-sysregs.h.inc should be eventually automatically generated, shouldn't we put this definition somewhere else or do we expect to also automatically generate this demux idreg?

The generation script was explicitly skipping CCSIDR_EL1; when I played
with that script, I just removed it from the list of skipped registers.

I'm not sure if we have information to automatically generate any
demuxed registers, let me see if I can find something.

>
>>  DEF(CLIDR_EL1, 3, 1, 0, 0, 1)
>>  DEF(ID_AA64ZFR0_EL1, 3, 0, 0, 4, 4)
>>  DEF(CTR_EL0, 3, 3, 0, 0, 1)

(...)

>> @@ -792,11 +792,11 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
>>       * L3: No L3 (this matches the CLIDR_EL1 value).
>>       */
>>      /* 64KB L1 dcache */
>> -    cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0);
>> +    SET_IDREG_DEMUX(isar, CCSIDR, 0, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
>>      /* 64KB L1 icache */
>> -    cpu->ccsidr[1] = cpu->ccsidr[0];
>> +    COPY_IDREG_DEMUX(isar, CCSIDR, 0, 1);
> nit: maybe we don't need a COPY but do get + set, if it is just used in
> this file. Or if we keep copy maybe use the memcpy convention?

Alternatively, we could just set the individual registers to the same
value instead of copying them. I wanted to keep the change obvious here,
but we can also defer adding a copy/memcopy macro until we really need
it.



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

* Re: [PATCH v2 3/3] arm/kvm: get demuxed ID registers from kvm
  2026-04-01 17:00   ` Eric Auger
@ 2026-04-02 15:19     ` Cornelia Huck
  0 siblings, 0 replies; 10+ messages in thread
From: Cornelia Huck @ 2026-04-02 15:19 UTC (permalink / raw)
  To: eric.auger, qemu-arm, qemu-devel
  Cc: Peter Maydell, Sebastian Ott, Jonathan Cameron, Alireza Sanaee

On Wed, Apr 01 2026, Eric Auger <eric.auger@redhat.com> wrote:

> On 2/4/26 2:32 PM, Cornelia Huck wrote:
>> We now have the infrastructure in place to get and save demuxed ID
> Here we only get their values? What about the save?

We only get, but we could also save, if we had the right interfaces :)
I'll try to reword it to be less confusing.

>> registers from kvm. Use it to get the values that kvm emulates for
>> CCSIDR_EL1.
>>
>> Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>
>> Reviewed-by: Sebastian Ott <sebott@redhat.com>
>> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
>> ---
>>  target/arm/kvm.c | 33 +++++++++++++++++++++++++++++++++
>>  1 file changed, 33 insertions(+)
>>
>> @@ -416,6 +444,11 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
>>               */
>>              err |= get_host_cpu_reg(fd, ahcf, ID_AA64ZFR0_EL1_IDX);
>>          }
>> +        /* grab demuxed registers */
>> +        for (i = 0; i < 14; i++) {
>> +            /* KVM only allows 0..13 */
> where is it documented? Maybe add a comment or justification in the
> commit msg. Use a define?

Linux arch/arm64/kvm/sys_regs.c has

#define CSSELR_MAX 14

Not sure if there is any actual documentation.

>> +            err |= get_host_cpu_reg_demux(fd, ahcf, CCSIDR_EL1_IDX, i);
>> +        }
>>      }
>>  
>>      kvm_arm_destroy_scratch_host_vcpu(fdarray);
> Thanks
>
> Eric



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

end of thread, other threads:[~2026-04-02 15:19 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-04 13:32 [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1) Cornelia Huck
2026-02-04 13:32 ` [PATCH v2 1/3] arm: handle demuxed ID registers Cornelia Huck
2026-02-04 13:32 ` [PATCH v2 2/3] arm: handle CCSIDR_EL1 as a demuxed register Cornelia Huck
2026-04-01 16:46   ` Eric Auger
2026-04-02 15:04     ` Cornelia Huck
2026-02-04 13:32 ` [PATCH v2 3/3] arm/kvm: get demuxed ID registers from kvm Cornelia Huck
2026-04-01 17:00   ` Eric Auger
2026-04-02 15:19     ` Cornelia Huck
2026-02-05 11:52 ` [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1) Peter Maydell
2026-02-05 16:50   ` Cornelia Huck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox