[PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1)

Cornelia Huck posted 3 patches 2 days, 14 hours ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260204133229.297061-1-cohuck@redhat.com
Maintainers: Peter Maydell <peter.maydell@linaro.org>, Paolo Bonzini <pbonzini@redhat.com>
hw/intc/armv7m_nvic.c        |  2 +-
target/arm/cpu-sysregs.h     | 14 +++++++++
target/arm/cpu-sysregs.h.inc |  1 +
target/arm/cpu.h             | 26 ++++++++++++----
target/arm/cpu64.c           | 12 ++++----
target/arm/helper.c          |  2 +-
target/arm/kvm.c             | 33 ++++++++++++++++++++
target/arm/tcg/cpu32.c       | 32 +++++++++----------
target/arm/tcg/cpu64.c       | 60 ++++++++++++++++++------------------
9 files changed, 122 insertions(+), 60 deletions(-)
[PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1)
Posted by Cornelia Huck 2 days, 14 hours ago
[previously posted as RFC, but given that I got T-b and R-b, I promoted
it to full v2 :)]

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

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

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

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

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

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

Feedback appreciated.

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

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

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

-- 
2.52.0
Re: [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1)
Posted by Peter Maydell 1 day, 16 hours ago
On Wed, 4 Feb 2026 at 13:32, Cornelia Huck <cohuck@redhat.com> wrote:
> RFC because there are still some open questions:

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

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

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

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

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

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

-- PMM
Re: [PATCH v2 0/3] arm: demuxed ID registers (CCSIDR_EL1)
Posted by Cornelia Huck 1 day, 11 hours ago
On Thu, Feb 05 2026, Peter Maydell <peter.maydell@linaro.org> wrote:

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

That makes sense.

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

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

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