All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1)
@ 2026-01-19 17:27 Cornelia Huck
  2026-01-19 17:27 ` [PATCH RFC 1/3] arm: handle demuxed ID registers Cornelia Huck
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Cornelia Huck @ 2026-01-19 17:27 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Peter Maydell, Eric Auger, Cornelia Huck

Note: this is on top of <20260105154119.59853-1-cohuck@redhat.com>
("[PATCH v3 0/2] arm: move DCZID_EL0 to idregs array")

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.

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     |  6 ++++
 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, 114 insertions(+), 60 deletions(-)

-- 
2.52.0



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

* [PATCH RFC 1/3] arm: handle demuxed ID registers
  2026-01-19 17:27 [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1) Cornelia Huck
@ 2026-01-19 17:27 ` Cornelia Huck
  2026-01-21  9:40     ` Jonathan Cameron via qemu development
  2026-01-19 17:27 ` [PATCH RFC 2/3] arm: handle CCSIDR_EL1 as a demuxed register Cornelia Huck
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Cornelia Huck @ 2026-01-19 17:27 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Peter Maydell, Eric Auger, 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.

Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 target/arm/cpu-sysregs.h |  5 +++++
 target/arm/cpu.h         | 20 ++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h
index 7877a3b06a8e..31f82c6a0afc 100644
--- a/target/arm/cpu-sysregs.h
+++ b/target/arm/cpu-sysregs.h
@@ -35,6 +35,11 @@ typedef enum ARMSysRegs {
 
 #undef DEF
 
+/* ID registers that vary based upon another register */
+typedef enum ARMIDRegisterDemuxIdx {
+    NUM_ID_DEMUX_IDX,
+} ARMIDRegisterDemuxIdx;
+
 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 08b7d3fb936a..f7bd19f26fbd 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -905,6 +905,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
@@ -1083,6 +1102,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][16];
     } isar;
     uint64_t midr;
     uint32_t revidr;
-- 
2.52.0



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

* [PATCH RFC 2/3] arm: handle CCSIDR_EL1 as a demuxed register
  2026-01-19 17:27 [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1) Cornelia Huck
  2026-01-19 17:27 ` [PATCH RFC 1/3] arm: handle demuxed ID registers Cornelia Huck
@ 2026-01-19 17:27 ` Cornelia Huck
  2026-01-19 17:27 ` [PATCH RFC 3/3] arm/kvm: get demuxed ID registers from kvm Cornelia Huck
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Cornelia Huck @ 2026-01-19 17:27 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Peter Maydell, Eric Auger, Cornelia Huck

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

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 3a31eb56f362..4cc186ca5ba2 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 31f82c6a0afc..9ef4ace3db88 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 7f3aa8b991aa..1d5be3538c60 100644
--- a/target/arm/cpu-sysregs.h.inc
+++ b/target/arm/cpu-sysregs.h.inc
@@ -36,6 +36,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 f7bd19f26fbd..ee5e1c799045 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1112,10 +1112,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;
@@ -2072,8 +2068,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 2bcb01e45bbf..8babce17c278 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -866,7 +866,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 3db8d4694a7d..3c257e4f1839 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] 13+ messages in thread

* [PATCH RFC 3/3] arm/kvm: get demuxed ID registers from kvm
  2026-01-19 17:27 [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1) Cornelia Huck
  2026-01-19 17:27 ` [PATCH RFC 1/3] arm: handle demuxed ID registers Cornelia Huck
  2026-01-19 17:27 ` [PATCH RFC 2/3] arm: handle CCSIDR_EL1 as a demuxed register Cornelia Huck
@ 2026-01-19 17:27 ` Cornelia Huck
  2026-01-20 11:44   ` Alireza Sanaee via qemu development
  2026-01-20 15:40 ` Sebastian Ott
  4 siblings, 0 replies; 13+ messages in thread
From: Cornelia Huck @ 2026-01-19 17:27 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Peter Maydell, Eric Auger, 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.

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 48f853fff80e..ab73b3a29f0f 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] 13+ messages in thread

* Re: [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1)
  2026-01-19 17:27 [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1) Cornelia Huck
@ 2026-01-20 11:44   ` Alireza Sanaee via qemu development
  2026-01-19 17:27 ` [PATCH RFC 2/3] arm: handle CCSIDR_EL1 as a demuxed register Cornelia Huck
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Alireza Sanaee via @ 2026-01-20 11:44 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: qemu-arm, qemu-devel, Peter Maydell, Eric Auger, jonathan.cameron

On Mon, 19 Jan 2026 18:27:29 +0100
Cornelia Huck <cohuck@redhat.com> wrote:

Hi Cornelia,



> Note: this is on top of <20260105154119.59853-1-cohuck@redhat.com>
> ("[PATCH v3 0/2] arm: move DCZID_EL0 to idregs array")
> 
> 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.
> 
> 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     |  6 ++++
>  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, 114 insertions(+), 60 deletions(-)
> 

This impacts my set https://lore.kernel.org/all/20260106155828.643-1-alireza.sanaee@huawei.com/

I tested it with mine of course it required a few changes, but looks like working on TCG, didn't try KVM.

Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>


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

* Re: [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1)
@ 2026-01-20 11:44   ` Alireza Sanaee via qemu development
  0 siblings, 0 replies; 13+ messages in thread
From: Alireza Sanaee via qemu development @ 2026-01-20 11:44 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: qemu-arm, qemu-devel, Peter Maydell, Eric Auger, jonathan.cameron

On Mon, 19 Jan 2026 18:27:29 +0100
Cornelia Huck <cohuck@redhat.com> wrote:

Hi Cornelia,



> Note: this is on top of <20260105154119.59853-1-cohuck@redhat.com>
> ("[PATCH v3 0/2] arm: move DCZID_EL0 to idregs array")
> 
> 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.
> 
> 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     |  6 ++++
>  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, 114 insertions(+), 60 deletions(-)
> 

This impacts my set https://lore.kernel.org/all/20260106155828.643-1-alireza.sanaee@huawei.com/

I tested it with mine of course it required a few changes, but looks like working on TCG, didn't try KVM.

Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>


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

* Re: [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1)
  2026-01-19 17:27 [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1) Cornelia Huck
                   ` (3 preceding siblings ...)
  2026-01-20 11:44   ` Alireza Sanaee via qemu development
@ 2026-01-20 15:40 ` Sebastian Ott
  4 siblings, 0 replies; 13+ messages in thread
From: Sebastian Ott @ 2026-01-20 15:40 UTC (permalink / raw)
  To: Cornelia Huck; +Cc: qemu-arm, qemu-devel, Peter Maydell, Eric Auger

On Mon, 19 Jan 2026, Cornelia Huck wrote:
> Note: this is on top of <20260105154119.59853-1-cohuck@redhat.com>
> ("[PATCH v3 0/2] arm: move DCZID_EL0 to idregs array")
>
> 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.
>

LGTM!

Reviewed-by: Sebastian Ott <sebott@redhat.com>

Thanks,
Sebastian



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

* Re: [PATCH RFC 1/3] arm: handle demuxed ID registers
  2026-01-19 17:27 ` [PATCH RFC 1/3] arm: handle demuxed ID registers Cornelia Huck
@ 2026-01-21  9:40     ` Jonathan Cameron via qemu development
  0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron via @ 2026-01-21  9:40 UTC (permalink / raw)
  To: Cornelia Huck; +Cc: qemu-arm, qemu-devel, Peter Maydell, Eric Auger

On Mon, 19 Jan 2026 18:27:30 +0100
Cornelia Huck <cohuck@redhat.com> wrote:

> 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.
> 
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> ---
>  target/arm/cpu-sysregs.h |  5 +++++
>  target/arm/cpu.h         | 20 ++++++++++++++++++++
>  2 files changed, 25 insertions(+)
> 
> diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h
> index 7877a3b06a8e..31f82c6a0afc 100644
> --- a/target/arm/cpu-sysregs.h
> +++ b/target/arm/cpu-sysregs.h
> @@ -35,6 +35,11 @@ typedef enum ARMSysRegs {
>  
>  #undef DEF
>  
> +/* ID registers that vary based upon another register */
> +typedef enum ARMIDRegisterDemuxIdx {
> +    NUM_ID_DEMUX_IDX,
> +} ARMIDRegisterDemuxIdx;
> +
>  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 08b7d3fb936a..f7bd19f26fbd 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -905,6 +905,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
> @@ -1083,6 +1102,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][16];
Hi,

Trivial, but I'd like a comment on why 16. I assume because that's
the biggest you've seen so far (8 levels, 2 types for CCSIDR)
Just good to have a bread crumb here for future readers.

Otherwise seems reasonable to me.
>      } isar;
>      uint64_t midr;
>      uint32_t revidr;



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

* Re: [PATCH RFC 1/3] arm: handle demuxed ID registers
@ 2026-01-21  9:40     ` Jonathan Cameron via qemu development
  0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron via qemu development @ 2026-01-21  9:40 UTC (permalink / raw)
  To: Cornelia Huck; +Cc: qemu-arm, qemu-devel, Peter Maydell, Eric Auger

On Mon, 19 Jan 2026 18:27:30 +0100
Cornelia Huck <cohuck@redhat.com> wrote:

> 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.
> 
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> ---
>  target/arm/cpu-sysregs.h |  5 +++++
>  target/arm/cpu.h         | 20 ++++++++++++++++++++
>  2 files changed, 25 insertions(+)
> 
> diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h
> index 7877a3b06a8e..31f82c6a0afc 100644
> --- a/target/arm/cpu-sysregs.h
> +++ b/target/arm/cpu-sysregs.h
> @@ -35,6 +35,11 @@ typedef enum ARMSysRegs {
>  
>  #undef DEF
>  
> +/* ID registers that vary based upon another register */
> +typedef enum ARMIDRegisterDemuxIdx {
> +    NUM_ID_DEMUX_IDX,
> +} ARMIDRegisterDemuxIdx;
> +
>  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 08b7d3fb936a..f7bd19f26fbd 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -905,6 +905,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
> @@ -1083,6 +1102,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][16];
Hi,

Trivial, but I'd like a comment on why 16. I assume because that's
the biggest you've seen so far (8 levels, 2 types for CCSIDR)
Just good to have a bread crumb here for future readers.

Otherwise seems reasonable to me.
>      } isar;
>      uint64_t midr;
>      uint32_t revidr;



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

* Re: [PATCH RFC 1/3] arm: handle demuxed ID registers
  2026-01-21  9:40     ` Jonathan Cameron via qemu development
  (?)
@ 2026-01-21 16:25     ` Cornelia Huck
  -1 siblings, 0 replies; 13+ messages in thread
From: Cornelia Huck @ 2026-01-21 16:25 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: qemu-arm, qemu-devel, Peter Maydell, Eric Auger

On Wed, Jan 21 2026, Jonathan Cameron <jonathan.cameron@huawei.com> wrote:

> On Mon, 19 Jan 2026 18:27:30 +0100
> Cornelia Huck <cohuck@redhat.com> wrote:
>> @@ -1083,6 +1102,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][16];
> Hi,
>
> Trivial, but I'd like a comment on why 16. I assume because that's
> the biggest you've seen so far (8 levels, 2 types for CCSIDR)
> Just good to have a bread crumb here for future readers.

Yes, this came in via the current ccsidr[] sizing (which also might not
be quite the right thing to use, given that we could have 2*7 + 7
entries with FEAT_MTE2); I'm not at all sure whether that's a reasonable
value, but I'll certainly add a comment if we agree that it is. Or maybe
make it a #define.

>
> Otherwise seems reasonable to me.

Thanks for looking!

>>      } isar;
>>      uint64_t midr;
>>      uint32_t revidr;



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

* Re: [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1)
  2026-01-20 11:44   ` Alireza Sanaee via qemu development
  (?)
@ 2026-01-21 16:28   ` Cornelia Huck
  2026-01-22 13:31       ` Alireza Sanaee via qemu development
  -1 siblings, 1 reply; 13+ messages in thread
From: Cornelia Huck @ 2026-01-21 16:28 UTC (permalink / raw)
  To: Alireza Sanaee
  Cc: qemu-arm, qemu-devel, Peter Maydell, Eric Auger, jonathan.cameron

On Tue, Jan 20 2026, Alireza Sanaee <alireza.sanaee@huawei.com> wrote:

> On Mon, 19 Jan 2026 18:27:29 +0100
> Cornelia Huck <cohuck@redhat.com> wrote:
>
> Hi Cornelia,
>
>
>
>> Note: this is on top of <20260105154119.59853-1-cohuck@redhat.com>
>> ("[PATCH v3 0/2] arm: move DCZID_EL0 to idregs array")
>> 
>> 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.
>> 
>> 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     |  6 ++++
>>  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, 114 insertions(+), 60 deletions(-)
>> 
>
> This impacts my set https://lore.kernel.org/all/20260106155828.643-1-alireza.sanaee@huawei.com/

Duh, that series had actually been sitting in my "to look at" queue...

>
> I tested it with mine of course it required a few changes, but looks like working on TCG, didn't try KVM.
>
> Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>

Thanks for testing! I'll also try to take a look at your series.



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

* Re: [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1)
  2026-01-21 16:28   ` Cornelia Huck
@ 2026-01-22 13:31       ` Alireza Sanaee via qemu development
  0 siblings, 0 replies; 13+ messages in thread
From: Alireza Sanaee via @ 2026-01-22 13:31 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: qemu-arm, qemu-devel, Peter Maydell, Eric Auger, jonathan.cameron

On Wed, 21 Jan 2026 17:28:07 +0100
Cornelia Huck <cohuck@redhat.com> wrote:

> On Tue, Jan 20 2026, Alireza Sanaee <alireza.sanaee@huawei.com> wrote:
> 
> > On Mon, 19 Jan 2026 18:27:29 +0100
> > Cornelia Huck <cohuck@redhat.com> wrote:
> >
> > Hi Cornelia,
> >
> >
> >  
> >> Note: this is on top of <20260105154119.59853-1-cohuck@redhat.com>
> >> ("[PATCH v3 0/2] arm: move DCZID_EL0 to idregs array")
> >> 
> >> 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.
> >> 
> >> 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     |  6 ++++
> >>  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, 114 insertions(+), 60 deletions(-)
> >>   
> >
> > This impacts my set https://lore.kernel.org/all/20260106155828.643-1-alireza.sanaee@huawei.com/  
> 
> Duh, that series had actually been sitting in my "to look at" queue...
> 
> >
> > I tested it with mine of course it required a few changes, but looks like working on TCG, didn't try KVM.
> >
> > Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>  
> 
> Thanks for testing! I'll also try to take a look at your series.
> 
> 

Thanks Cornelia, that patch has been sitting there forever literally :)


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

* Re: [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1)
@ 2026-01-22 13:31       ` Alireza Sanaee via qemu development
  0 siblings, 0 replies; 13+ messages in thread
From: Alireza Sanaee via qemu development @ 2026-01-22 13:31 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: qemu-arm, qemu-devel, Peter Maydell, Eric Auger, jonathan.cameron

On Wed, 21 Jan 2026 17:28:07 +0100
Cornelia Huck <cohuck@redhat.com> wrote:

> On Tue, Jan 20 2026, Alireza Sanaee <alireza.sanaee@huawei.com> wrote:
> 
> > On Mon, 19 Jan 2026 18:27:29 +0100
> > Cornelia Huck <cohuck@redhat.com> wrote:
> >
> > Hi Cornelia,
> >
> >
> >  
> >> Note: this is on top of <20260105154119.59853-1-cohuck@redhat.com>
> >> ("[PATCH v3 0/2] arm: move DCZID_EL0 to idregs array")
> >> 
> >> 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.
> >> 
> >> 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     |  6 ++++
> >>  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, 114 insertions(+), 60 deletions(-)
> >>   
> >
> > This impacts my set https://lore.kernel.org/all/20260106155828.643-1-alireza.sanaee@huawei.com/  
> 
> Duh, that series had actually been sitting in my "to look at" queue...
> 
> >
> > I tested it with mine of course it required a few changes, but looks like working on TCG, didn't try KVM.
> >
> > Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>  
> 
> Thanks for testing! I'll also try to take a look at your series.
> 
> 

Thanks Cornelia, that patch has been sitting there forever literally :)


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

end of thread, other threads:[~2026-01-22 13:33 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-19 17:27 [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1) Cornelia Huck
2026-01-19 17:27 ` [PATCH RFC 1/3] arm: handle demuxed ID registers Cornelia Huck
2026-01-21  9:40   ` Jonathan Cameron via
2026-01-21  9:40     ` Jonathan Cameron via qemu development
2026-01-21 16:25     ` Cornelia Huck
2026-01-19 17:27 ` [PATCH RFC 2/3] arm: handle CCSIDR_EL1 as a demuxed register Cornelia Huck
2026-01-19 17:27 ` [PATCH RFC 3/3] arm/kvm: get demuxed ID registers from kvm Cornelia Huck
2026-01-20 11:44 ` [PATCH RFC 0/3] arm: demuxed ID registers (CCSIDR_EL1) Alireza Sanaee via
2026-01-20 11:44   ` Alireza Sanaee via qemu development
2026-01-21 16:28   ` Cornelia Huck
2026-01-22 13:31     ` Alireza Sanaee via
2026-01-22 13:31       ` Alireza Sanaee via qemu development
2026-01-20 15:40 ` Sebastian Ott

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.