* [PATCH v5 0/3] arm: demuxed ID registers (CCSIDR_EL1)
@ 2026-09-09 14:41 Sebastian Ott
2026-09-09 14:41 ` [PATCH v5 1/3] arm: handle demuxed ID registers Sebastian Ott
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Sebastian Ott @ 2026-09-09 14:41 UTC (permalink / raw)
To: Peter Maydell, Eric Auger, Jonathan Cameron, Alireza Sanaee,
Richard Henderson, Cornelia Huck, khushit.shah
Cc: qemu-arm, qemu-devel, Sebastian Ott
To support efforts to generalize handling of writable System ID Registers
[1] this series addresses the demuxed registers that are kept outside of
ARMISARegisters namely CSSELR_EL1.
CSSELR_EL1 is moved within ARMISARegisters and accessors to retrieve
and set the demuxed values are provided. Initial values are gathered via
the usual KVM_GET_ONE_REG ioctl.
V4 of this series was posted here:
https://lore.kernel.org/qemu-devel/20260702133606.34529-1-sebott@redhat.com/
[1] https://lore.kernel.org/qemu-arm/20260616132625.1732031-1-eric.auger@redhat.com/
Changes V4->V5:
* changed diffstat format
* changed cover letter
Changes V3->V4:
* added R-B from Eric
* incorporated suggestions from Eric
Cornelia Huck (3):
arm: handle demuxed ID registers
arm: handle CCSIDR_EL1 as a demuxed register
arm/kvm: get demuxed ID registers from kvm
target/arm/cpu-sysregs.h | 9 +++++
target/arm/cpu.h | 18 ++++++----
target/arm/cpu-sysregs.h.inc | 1 +
hw/arm/virt.c | 19 ++++------
hw/intc/armv7m_nvic.c | 2 +-
target/arm/cpu-max.c | 6 ++--
target/arm/cpu64.c | 14 ++++++--
target/arm/helper.c | 2 +-
target/arm/kvm.c | 31 ++++++++++++++++
target/arm/tcg/cpu32.c | 26 +++++++-------
target/arm/tcg/cpu64.c | 68 ++++++++++++++++++------------------
11 files changed, 123 insertions(+), 73 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v5 1/3] arm: handle demuxed ID registers
2026-09-09 14:41 [PATCH v5 0/3] arm: demuxed ID registers (CCSIDR_EL1) Sebastian Ott
@ 2026-09-09 14:41 ` Sebastian Ott
2026-09-14 14:20 ` Peter Maydell
2026-09-09 14:41 ` [PATCH v5 2/3] arm: handle CCSIDR_EL1 as a demuxed register Sebastian Ott
2026-09-09 14:41 ` [PATCH v5 3/3] arm/kvm: get demuxed ID registers from kvm Sebastian Ott
2 siblings, 1 reply; 8+ messages in thread
From: Sebastian Ott @ 2026-09-09 14:41 UTC (permalink / raw)
To: Peter Maydell, Eric Auger, Jonathan Cameron, Alireza Sanaee,
Richard Henderson, Cornelia Huck, khushit.shah
Cc: qemu-arm, qemu-devel, Eric Auger, Sebastian Ott
From: Cornelia Huck <cohuck@redhat.com>
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>
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Sebastian Ott <sebott@redhat.com>
---
target/arm/cpu-sysregs.h | 9 +++++++++
target/arm/cpu.h | 12 ++++++++++++
target/arm/cpu64.c | 8 ++++++++
3 files changed, 29 insertions(+)
diff --git a/target/arm/cpu-sysregs.h b/target/arm/cpu-sysregs.h
index 7877a3b06a..a4b9621a7e 100644
--- a/target/arm/cpu-sysregs.h
+++ b/target/arm/cpu-sysregs.h
@@ -20,20 +20,29 @@
#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) NAME##_IDX,
+#define DEF_MUX(NAME, OP0, OP1, CRN, CRM, OP2, NUM) \
+ NAME##_IDX, \
+ NAME##_IDX_LAST = NAME##_IDX + NUM - 1,
+
typedef enum ARMIDRegisterIdx {
#include "cpu-sysregs.h.inc"
NUM_ID_IDX,
} ARMIDRegisterIdx;
#undef DEF
+#undef DEF_MUX
#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \
SYS_##NAME = ENCODE_ID_REG(OP0, OP1, CRN, CRM, OP2),
+#define DEF_MUX(NAME, OP0, OP1, CRN, CRM, OP2, NUM) \
+ DEF(NAME, OP0, OP1, CRN, CRM, OP2)
+
typedef enum ARMSysRegs {
#include "cpu-sysregs.h.inc"
} ARMSysRegs;
#undef DEF
+#undef DEF_MUX
extern const uint32_t id_register_sysreg[NUM_ID_IDX];
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index e3f931dba2..9652f8b0bf 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -919,6 +919,18 @@ typedef struct {
i_->idregs[REG ## _EL1_IDX]; \
})
+#define SET_IDREG_DEMUX(ISAR, REG, INDEX, VALUE) \
+ ({ \
+ ARMISARegisters *i_ = (ISAR); \
+ i_->idregs[REG ## _IDX + INDEX] = VALUE; \
+ })
+
+#define GET_IDREG_DEMUX(ISAR, REG, INDEX) \
+ ({ \
+ ARMISARegisters *i_ = (ISAR); \
+ i_->idregs[REG ## _IDX + INDEX]; \
+ })
+
/**
* ARMCPU:
* @env: #CPUARMState
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 4e8c472530..c11ab2da21 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -42,14 +42,21 @@
#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \
[NAME##_IDX] = SYS_##NAME,
+#define DEF_MUX(NAME, OP0, OP1, CRN, CRM, OP2, NUM) \
+ DEF(NAME, OP0, OP1, CRN, CRM, OP2)
+
const uint32_t id_register_sysreg[NUM_ID_IDX] = {
#include "cpu-sysregs.h.inc"
};
#undef DEF
+#undef DEF_MUX
#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \
case SYS_##NAME: return NAME##_IDX;
+#define DEF_MUX(NAME, OP0, OP1, CRN, CRM, OP2, NUM) \
+ DEF(NAME, OP0, OP1, CRN, CRM, OP2)
+
int get_sysreg_idx(ARMSysRegs sysreg)
{
switch (sysreg) {
@@ -59,6 +66,7 @@ int get_sysreg_idx(ARMSysRegs sysreg)
}
#undef DEF
+#undef DEF_MUX
void aarch64_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
{
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v5 2/3] arm: handle CCSIDR_EL1 as a demuxed register
2026-09-09 14:41 [PATCH v5 0/3] arm: demuxed ID registers (CCSIDR_EL1) Sebastian Ott
2026-09-09 14:41 ` [PATCH v5 1/3] arm: handle demuxed ID registers Sebastian Ott
@ 2026-09-09 14:41 ` Sebastian Ott
2026-09-14 12:09 ` Peter Maydell
2026-09-09 14:41 ` [PATCH v5 3/3] arm/kvm: get demuxed ID registers from kvm Sebastian Ott
2 siblings, 1 reply; 8+ messages in thread
From: Sebastian Ott @ 2026-09-09 14:41 UTC (permalink / raw)
To: Peter Maydell, Eric Auger, Jonathan Cameron, Alireza Sanaee,
Richard Henderson, Cornelia Huck, khushit.shah
Cc: qemu-arm, qemu-devel, Eric Auger, Sebastian Ott
From: Cornelia Huck <cohuck@redhat.com>
Move handling of CCSIDR_EL1 over to the new *_IDREG_DEMUX
infrastructure.
Note: the existing size of 16 is kept and might be extended
at a later time.
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Sebastian Ott <sebott@redhat.com>
---
target/arm/cpu.h | 6 ----
target/arm/cpu-sysregs.h.inc | 1 +
hw/arm/virt.c | 19 ++++------
hw/intc/armv7m_nvic.c | 2 +-
target/arm/cpu-max.c | 6 ++--
target/arm/cpu64.c | 6 ++--
target/arm/helper.c | 2 +-
target/arm/tcg/cpu32.c | 26 +++++++-------
target/arm/tcg/cpu64.c | 68 ++++++++++++++++++------------------
9 files changed, 63 insertions(+), 73 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 9652f8b0bf..f832cdd7e1 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1121,10 +1121,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;
@@ -2138,8 +2134,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/cpu-sysregs.h.inc b/target/arm/cpu-sysregs.h.inc
index 6e8b335b8f..d9e058a57e 100644
--- a/target/arm/cpu-sysregs.h.inc
+++ b/target/arm/cpu-sysregs.h.inc
@@ -39,6 +39,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_MUX(CCSIDR_EL1, 3, 1, 0, 0, 0, 16)
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/hw/arm/virt.c b/hw/arm/virt.c
index 0871a35e11..59ec51ddf3 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -306,24 +306,19 @@ void set_cpu_cache(CPUCoreCaches *cpu_cache, enum CacheType cache_type,
int bank_index = ((cache_level - 1) * 2) | is_i_cache0;
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
bool ccidx = cpu_isar_feature(any_ccidx, armcpu);
+ uint64_t ccsidr = GET_IDREG_DEMUX(&armcpu->isar, CCSIDR_EL1, bank_index);
if (ccidx) {
*cpu_cache = (CPUCoreCaches){
- .linesize = 1 << (FIELD_EX64(armcpu->ccsidr[bank_index], CCSIDR_EL1,
- CCIDX_LINESIZE) + 4),
- .associativity = FIELD_EX64(armcpu->ccsidr[bank_index], CCSIDR_EL1,
- CCIDX_ASSOCIATIVITY) + 1,
- .sets = FIELD_EX64(armcpu->ccsidr[bank_index], CCSIDR_EL1,
- CCIDX_NUMSETS) + 1,
+ .linesize = 1 << (FIELD_EX64(ccsidr, CCSIDR_EL1, CCIDX_LINESIZE) + 4),
+ .associativity = FIELD_EX64(ccsidr, CCSIDR_EL1, CCIDX_ASSOCIATIVITY) + 1,
+ .sets = FIELD_EX64(ccsidr, CCSIDR_EL1, CCIDX_NUMSETS) + 1,
};
} else {
*cpu_cache = (CPUCoreCaches){
- .linesize = 1 << (FIELD_EX64(armcpu->ccsidr[bank_index], CCSIDR_EL1,
- LINESIZE) + 4),
- .associativity = FIELD_EX64(armcpu->ccsidr[bank_index], CCSIDR_EL1,
- ASSOCIATIVITY) + 1,
- .sets =
- FIELD_EX64(armcpu->ccsidr[bank_index], CCSIDR_EL1, NUMSETS) + 1,
+ .linesize = 1 << (FIELD_EX64(ccsidr, CCSIDR_EL1, LINESIZE) + 4),
+ .associativity = FIELD_EX64(ccsidr, CCSIDR_EL1, ASSOCIATIVITY) + 1,
+ .sets = FIELD_EX64(ccsidr, CCSIDR_EL1, NUMSETS) + 1,
};
}
cpu_cache->type = cache_type;
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index a7651f831e..5dd867242b 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -1360,7 +1360,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_EL1, idx);
}
case 0xd84: /* CSSELR */
return cpu->env.v7m.csselr[attrs.secure];
diff --git a/target/arm/cpu-max.c b/target/arm/cpu-max.c
index 739500a04f..2ed1cfef9b 100644
--- a/target/arm/cpu-max.c
+++ b/target/arm/cpu-max.c
@@ -71,11 +71,11 @@ void aarch64_aa32_a57_init(ARMCPU *cpu, bool aarch64_enabled)
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_EL1, 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_EL1, 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_EL1, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 2 * MiB, 7));
if (aarch64_enabled) {
set_dczid_bs(cpu, 4); /* 64 bytes */
cpu->gic_num_lrs = 4;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index c11ab2da21..dcd0d698b3 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -749,11 +749,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_EL1, 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_EL1, 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_EL1, 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 c3f607e6d6..a608df1211 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -925,7 +925,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_EL1, 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 f292a269bf..7db35e1955 100644
--- a/target/arm/tcg/cpu32.c
+++ b/target/arm/tcg/cpu32.c
@@ -277,9 +277,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_EL1, 0, 0xe007e01a); /* 16k L1 dcache. */
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 1, 0x2007e01a); /* 16k L1 icache. */
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 2, 0xf0000000); /* No L2 icache. */
cpu->reset_auxcr = 2;
cpu->isar.reset_pmcr_el0 = 0x41002000;
define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
@@ -355,8 +355,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_EL1, 0, 0xe00fe019); /* 16k L1 dcache. */
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 1, 0x200fe019); /* 16k L1 icache. */
cpu->isar.reset_pmcr_el0 = 0x41093000;
define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
}
@@ -429,9 +429,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_EL1, 0, 0x701fe00a); /* 32K L1 dcache */
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 1, 0x201fe00a); /* 32K L1 icache */
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 2, 0x711fe07a); /* 4096K L2 unified cache */
cpu->isar.reset_pmcr_el0 = 0x41072000;
define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
}
@@ -478,9 +478,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_EL1, 0, 0x701fe00a); /* 32K L1 dcache */
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 1, 0x201fe00a); /* 32K L1 icache */
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 2, 0x711fe07a); /* 4096K L2 unified cache */
cpu->isar.reset_pmcr_el0 = 0x410F3000;
define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
}
@@ -670,8 +670,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_EL1, 0, 0x700fe01a); /* 32KB L1 dcache */
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 1, 0x201fe00a); /* 32KB L1 icache */
cpu->pmsav7_dregion = 16;
cpu->pmsav8r_hdregion = 16;
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index affd87a3ae..e156baf35d 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -83,11 +83,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_EL1, 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_EL1, 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_EL1, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 512 * KiB, 7));
/* From B3.5 VGIC Type register */
cpu->gic_num_lrs = 4;
@@ -252,11 +252,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_EL1, 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_EL1, 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_EL1, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 512 * KiB, 7));
/* From B2.96 SCTLR_EL3 */
cpu->reset_sctlr = 0x30c50838;
@@ -323,11 +323,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_EL1, 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_EL1, 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_EL1, 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;
@@ -387,11 +387,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_EL1, 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_EL1, 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_EL1, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 512 * KiB, 7));
/* From B2.93 SCTLR_EL3 */
cpu->reset_sctlr = 0x30c50838;
@@ -460,11 +460,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_EL1, 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_EL1, 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_EL1, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 512 * KiB, 7));
/* From 3.2.118 SCTLR_EL3 */
cpu->reset_sctlr = 0x30c50838;
@@ -518,11 +518,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_EL1, 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_EL1, 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_EL1, 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;
@@ -711,11 +711,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_EL1, 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_EL1, 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_EL1, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 1 * MiB, 7));
/* From B2.98 SCTLR_EL3 */
cpu->reset_sctlr = 0x30c50838;
@@ -800,11 +800,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_EL1, 0, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
/* 64KB L1 icache */
- cpu->ccsidr[1] = cpu->ccsidr[0];
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 1, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
/* 1MB L2 cache */
- cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 1 * MiB, 0);
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 2, make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 1 * MiB, 0));
/* From 3.2.115 SCTLR_EL3 */
cpu->reset_sctlr = 0x30c50838;
@@ -1043,11 +1043,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_EL1, 0, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
/* L1 icache */
- cpu->ccsidr[1] = cpu->ccsidr[0];
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 1, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
/* L2 cache */
- cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0);
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 2, make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0));
/* FIXME: Not documented -- copied from neoverse-v1 */
cpu->reset_sctlr = 0x30c50838;
@@ -1146,11 +1146,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_EL1, 0, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
/* L1 icache */
- cpu->ccsidr[1] = cpu->ccsidr[0];
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 1, make_ccsidr(CCSIDR_FORMAT_CCIDX, 4, 64, 64 * KiB, 0));
/* L2 cache */
- cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0);
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 2, make_ccsidr(CCSIDR_FORMAT_CCIDX, 8, 64, 512 * KiB, 0));
/* FIXME: Not documented -- copied from neoverse-v1 */
cpu->reset_sctlr = 0x30c50838;
@@ -1180,13 +1180,13 @@ void aarch64_max_v8_tcg_initfn(Object *obj)
SET_IDREG(isar, CLIDR, 0x8200123);
/* 64KB L1 dcache */
- cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 7);
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 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_EL1, 1, make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 64 * KiB, 2));
/* 1MB L2 unified cache */
- cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 1 * MiB, 7);
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 2, make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 1 * MiB, 7));
/* 2MB L3 unified cache */
- cpu->ccsidr[4] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 2 * MiB, 7);
+ SET_IDREG_DEMUX(isar, CCSIDR_EL1, 4, make_ccsidr(CCSIDR_FORMAT_LEGACY, 8, 64, 2 * MiB, 7));
/*
* Unset ARM_FEATURE_BACKCOMPAT_CNTFRQ, which we would otherwise default
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v5 3/3] arm/kvm: get demuxed ID registers from kvm
2026-09-09 14:41 [PATCH v5 0/3] arm: demuxed ID registers (CCSIDR_EL1) Sebastian Ott
2026-09-09 14:41 ` [PATCH v5 1/3] arm: handle demuxed ID registers Sebastian Ott
2026-09-09 14:41 ` [PATCH v5 2/3] arm: handle CCSIDR_EL1 as a demuxed register Sebastian Ott
@ 2026-09-09 14:41 ` Sebastian Ott
2026-09-14 12:16 ` Peter Maydell
2 siblings, 1 reply; 8+ messages in thread
From: Sebastian Ott @ 2026-09-09 14:41 UTC (permalink / raw)
To: Peter Maydell, Eric Auger, Jonathan Cameron, Alireza Sanaee,
Richard Henderson, Cornelia Huck, khushit.shah
Cc: qemu-arm, qemu-devel, Sebastian Ott
From: Cornelia Huck <cohuck@redhat.com>
We now have the infrastructure in place to handle 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>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Sebastian Ott <sebott@redhat.com>
---
target/arm/kvm.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index ed99be7fd8..1230acaff0 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -244,6 +244,33 @@ static int get_host_cpu_reg(int fd, ARMHostCPUFeatures *ahcf,
return ret;
}
+
+/* CSSELR values supported by kvm; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
+#define CSSELR_MAX 14
+
+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,
+ };
+
+ switch (index) {
+ case CCSIDR_EL1_IDX:
+ if (subindex >= CSSELR_MAX) {
+ return -EINVAL;
+ }
+ one_reg.id |= KVM_REG_ARM_DEMUX_ID_CCSIDR | subindex;
+ one_reg.addr = (uintptr_t)&ahcf->isar.idregs[index + subindex];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ioctl(fd, KVM_GET_ONE_REG, &one_reg);
+}
+
static uint32_t kvm_arm_sve_get_vls(int fd)
{
uint64_t vls[KVM_ARM64_SVE_VLS_WORDS];
@@ -454,6 +481,10 @@ static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
/* Read the set of supported vector lengths. */
arm_host_cpu_features.sve_vq_supported = kvm_arm_sve_get_vls(fd);
}
+ /* Grab demuxed registers. */
+ for (int i = 0; i < CSSELR_MAX; i++) {
+ err |= get_host_cpu_reg_demux(fd, ahcf, CCSIDR_EL1_IDX, i);
+ }
}
kvm_arm_destroy_scratch_host_vcpu(fdarray);
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v5 2/3] arm: handle CCSIDR_EL1 as a demuxed register
2026-09-09 14:41 ` [PATCH v5 2/3] arm: handle CCSIDR_EL1 as a demuxed register Sebastian Ott
@ 2026-09-14 12:09 ` Peter Maydell
0 siblings, 0 replies; 8+ messages in thread
From: Peter Maydell @ 2026-09-14 12:09 UTC (permalink / raw)
To: Sebastian Ott
Cc: Eric Auger, Jonathan Cameron, Alireza Sanaee, Richard Henderson,
Cornelia Huck, khushit.shah, qemu-arm, qemu-devel, Eric Auger
On Wed, 9 Sept 2026 at 15:42, Sebastian Ott <sebott@redhat.com> wrote:
>
> From: Cornelia Huck <cohuck@redhat.com>
>
> Move handling of CCSIDR_EL1 over to the new *_IDREG_DEMUX
> infrastructure.
>
> Note: the existing size of 16 is kept and might be extended
> at a later time.
>
> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> Tested-by: Alireza Sanaee <alireza.sanaee@huawei.com>
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> Signed-off-by: Sebastian Ott <sebott@redhat.com>
> ---
> target/arm/cpu.h | 6 ----
> target/arm/cpu-sysregs.h.inc | 1 +
> hw/arm/virt.c | 19 ++++------
> hw/intc/armv7m_nvic.c | 2 +-
> target/arm/cpu-max.c | 6 ++--
> target/arm/cpu64.c | 6 ++--
> target/arm/helper.c | 2 +-
> target/arm/tcg/cpu32.c | 26 +++++++-------
> target/arm/tcg/cpu64.c | 68 ++++++++++++++++++------------------
> 9 files changed, 63 insertions(+), 73 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 9652f8b0bf..f832cdd7e1 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1121,10 +1121,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];
Something somewhere should be providing the equivalent of this
documentation comment. That should also mention that currently
we only support 16 indexes into CCSIDR because we don't implement
separate MTE Allocation Tag caches.
> uint64_t reset_cbar;
> uint32_t reset_auxcr;
> bool reset_hivecs;
> @@ -2138,8 +2134,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);
> -
This change has lost this compile-time assertion that is checking
that when we read from the CCSIDR we aren't using an out-of-bounds
index.
-- PMM
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 3/3] arm/kvm: get demuxed ID registers from kvm
2026-09-09 14:41 ` [PATCH v5 3/3] arm/kvm: get demuxed ID registers from kvm Sebastian Ott
@ 2026-09-14 12:16 ` Peter Maydell
0 siblings, 0 replies; 8+ messages in thread
From: Peter Maydell @ 2026-09-14 12:16 UTC (permalink / raw)
To: Sebastian Ott
Cc: Eric Auger, Jonathan Cameron, Alireza Sanaee, Richard Henderson,
Cornelia Huck, khushit.shah, qemu-arm, qemu-devel
On Wed, 9 Sept 2026 at 15:42, Sebastian Ott <sebott@redhat.com> wrote:
>
> From: Cornelia Huck <cohuck@redhat.com>
>
> We now have the infrastructure in place to handle 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>
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> Signed-off-by: Sebastian Ott <sebott@redhat.com>
> ---
> target/arm/kvm.c | 31 +++++++++++++++++++++++++++++++
> 1 file changed, 31 insertions(+)
>
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index ed99be7fd8..1230acaff0 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -244,6 +244,33 @@ static int get_host_cpu_reg(int fd, ARMHostCPUFeatures *ahcf,
> return ret;
> }
>
> +
> +/* CSSELR values supported by kvm; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
> +#define CSSELR_MAX 14
This is a bit misleading as a constant name because that 14 limit
is KVM-specific, and doesn't apply to the architecture or QEMU.
Somewhere in here we should document why the KVM number is different
from what QEMU has and why it doesn't matter (i.e. that neither KVM
nor QEMU currently handle reporting separate MTE Allocation Tag caches,
so CCSELR_EL1 bit 4 is always 0, and that a Level of 0b111 is reserved
and so CCSELR values 14 and 15 are never valid and will always make
CCSIDR read as zero).
> +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,
> + };
> +
> + switch (index) {
> + case CCSIDR_EL1_IDX:
> + if (subindex >= CSSELR_MAX) {
> + return -EINVAL;
> + }
> + one_reg.id |= KVM_REG_ARM_DEMUX_ID_CCSIDR | subindex;
> + one_reg.addr = (uintptr_t)&ahcf->isar.idregs[index + subindex];
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return ioctl(fd, KVM_GET_ONE_REG, &one_reg);
> +}
> +
> static uint32_t kvm_arm_sve_get_vls(int fd)
> {
> uint64_t vls[KVM_ARM64_SVE_VLS_WORDS];
> @@ -454,6 +481,10 @@ static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
> /* Read the set of supported vector lengths. */
> arm_host_cpu_features.sve_vq_supported = kvm_arm_sve_get_vls(fd);
> }
> + /* Grab demuxed registers. */
> + for (int i = 0; i < CSSELR_MAX; i++) {
> + err |= get_host_cpu_reg_demux(fd, ahcf, CCSIDR_EL1_IDX, i);
> + }
> }
I think I would favour being a bit more explicit in code about how
we're converting from a KVM-ism to QEMU's underlying format here:
have this loop go from 0 to QEMU's maximum CCSELR index (currently 15),
and then have get_host_cpu_reg_demux() handle 14 and 15 as "this ID
register value is 0" (with suitable comment). At some later point
if we need to handle Allocation Tag cache ID values then that code
will expand to "read cache index values 16 and up, with suitable
fallback to 'is zero' for older kernels".
thanks
-- PMM
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 1/3] arm: handle demuxed ID registers
2026-09-09 14:41 ` [PATCH v5 1/3] arm: handle demuxed ID registers Sebastian Ott
@ 2026-09-14 14:20 ` Peter Maydell
2026-09-16 15:37 ` Sebastian Ott
0 siblings, 1 reply; 8+ messages in thread
From: Peter Maydell @ 2026-09-14 14:20 UTC (permalink / raw)
To: Sebastian Ott
Cc: Eric Auger, Jonathan Cameron, Alireza Sanaee, Richard Henderson,
Cornelia Huck, khushit.shah, qemu-arm, qemu-devel, Eric Auger
On Wed, 9 Sept 2026 at 15:42, Sebastian Ott <sebott@redhat.com> wrote:
>
> From: Cornelia Huck <cohuck@redhat.com>
>
> 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>
> Suggested-by: Richard Henderson <richard.henderson@linaro.org>
> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> Signed-off-by: Sebastian Ott <sebott@redhat.com>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index e3f931dba2..9652f8b0bf 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -919,6 +919,18 @@ typedef struct {
> i_->idregs[REG ## _EL1_IDX]; \
> })
>
> +#define SET_IDREG_DEMUX(ISAR, REG, INDEX, VALUE) \
> + ({ \
> + ARMISARegisters *i_ = (ISAR); \
> + i_->idregs[REG ## _IDX + INDEX] = VALUE; \
> + })
> +
> +#define GET_IDREG_DEMUX(ISAR, REG, INDEX) \
> + ({ \
> + ARMISARegisters *i_ = (ISAR); \
> + i_->idregs[REG ## _IDX + INDEX]; \
> + })
Would it be reasonable to assert() in these that the INDEX is within
the range we expect it to be (i.e. >=0 and <= REG ##_IDX_LAST) ?
That would compensate for the loss of the compile-time checks
in patch 2 and the fact that static checkers won't be able to
see the intended bounds now this is just a slice of idregs[]
rather than a standalone array.
thanks
- PMM
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 1/3] arm: handle demuxed ID registers
2026-09-14 14:20 ` Peter Maydell
@ 2026-09-16 15:37 ` Sebastian Ott
0 siblings, 0 replies; 8+ messages in thread
From: Sebastian Ott @ 2026-09-16 15:37 UTC (permalink / raw)
To: Peter Maydell
Cc: Eric Auger, Jonathan Cameron, Alireza Sanaee, Richard Henderson,
Cornelia Huck, khushit.shah, qemu-arm, qemu-devel, Eric Auger
On Mon, 14 Sep 2026, Peter Maydell wrote:
> On Wed, 9 Sept 2026 at 15:42, Sebastian Ott <sebott@redhat.com> wrote:
>>
>> From: Cornelia Huck <cohuck@redhat.com>
>>
>> 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>
>> Suggested-by: Richard Henderson <richard.henderson@linaro.org>
>> Reviewed-by: Eric Auger <eric.auger@redhat.com>
>> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
>> Signed-off-by: Sebastian Ott <sebott@redhat.com>
>
>> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
>> index e3f931dba2..9652f8b0bf 100644
>> --- a/target/arm/cpu.h
>> +++ b/target/arm/cpu.h
>> @@ -919,6 +919,18 @@ typedef struct {
>> i_->idregs[REG ## _EL1_IDX]; \
>> })
>>
>> +#define SET_IDREG_DEMUX(ISAR, REG, INDEX, VALUE) \
>> + ({ \
>> + ARMISARegisters *i_ = (ISAR); \
>> + i_->idregs[REG ## _IDX + INDEX] = VALUE; \
>> + })
>> +
>> +#define GET_IDREG_DEMUX(ISAR, REG, INDEX) \
>> + ({ \
>> + ARMISARegisters *i_ = (ISAR); \
>> + i_->idregs[REG ## _IDX + INDEX]; \
>> + })
>
> Would it be reasonable to assert() in these that the INDEX is within
> the range we expect it to be (i.e. >=0 and <= REG ##_IDX_LAST) ?
> That would compensate for the loss of the compile-time checks
> in patch 2 and the fact that static checkers won't be able to
> see the intended bounds now this is just a slice of idregs[]
> rather than a standalone array.
Sure. I'll send a V6.
Thanks,
Sebastian
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-09-16 15:38 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-09 14:41 [PATCH v5 0/3] arm: demuxed ID registers (CCSIDR_EL1) Sebastian Ott
2026-09-09 14:41 ` [PATCH v5 1/3] arm: handle demuxed ID registers Sebastian Ott
2026-09-14 14:20 ` Peter Maydell
2026-09-16 15:37 ` Sebastian Ott
2026-09-09 14:41 ` [PATCH v5 2/3] arm: handle CCSIDR_EL1 as a demuxed register Sebastian Ott
2026-09-14 12:09 ` Peter Maydell
2026-09-09 14:41 ` [PATCH v5 3/3] arm/kvm: get demuxed ID registers from kvm Sebastian Ott
2026-09-14 12:16 ` Peter Maydell
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.