* [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; 4+ 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] 4+ 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-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, 0 replies; 4+ 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] 4+ 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-09 14:41 ` [PATCH v5 3/3] arm/kvm: get demuxed ID registers from kvm Sebastian Ott
2 siblings, 0 replies; 4+ 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] 4+ 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
2 siblings, 0 replies; 4+ 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] 4+ messages in thread
end of thread, other threads:[~2026-09-09 14:44 UTC | newest]
Thread overview: 4+ 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-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
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.