public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface
@ 2026-01-20  4:14 Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 01/19] dt-bindings: riscv: Add Ssqosid extension description Drew Fustini
                   ` (20 more replies)
  0 siblings, 21 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86
  Cc: Conor Dooley

This RFC series implements the RISC-V Quality-of-Service Identifiers
(Ssqosid) extension [1] which adds the srmcfg register. It also
implements the RISC-V Capacity and Bandwidth Controller QoS Register
Interface (CBQRI) specification [2] and integrates resctrl [3] support.
The patches are also available as a branch [4].

There is a Qemu patch series [5] that implements Ssqosid and CBQRI, and
a corresponding Qemu branch with those patches too [6].

[1] https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0
[2] https://github.com/riscv-non-isa/riscv-cbqri/releases/tag/v1.0
[3] https://docs.kernel.org/filesystems/resctrl.html
[4] https://git.kernel.org/pub/scm/linux/kernel/git/fustini/linux.git/log/?h=b4/ssqosid-cbqri
[5] https://lore.kernel.org/qemu-devel/20260105-riscv-ssqosid-cbqri-v4-0-9ad7671dde78@kernel.org/
[6] https://github.com/tt-fustini/qemu/tree/b4/riscv-ssqosid-cbqri

RISC-V QoS
----------
QoS (Quality of Service) in this context is concerned with shared
resources on an SoC such as cache capacity and memory bandwidth.

The Sssqosid extension defines the srmcfg CSR which configures a hart
with two identifiers:

 - Resource Control ID (RCID)
 - Monitoring Counter ID (MCID)

These identifiers accompany each request issued by the hart to shared
resource controllers. This allows the capacity and bandwidth resources
used by a software workload (e.g. a process or a set of processes) to be
controlled and monitored.

CBQRI defines operations to configure resource usage limits, in the form
of capacity or bandwidth, for an RCID. CBQRI also defines operations to
configure counters to track resource utilization per MCID. Furthermore,
the Access Type (AT) field allows resource usage to be differentiated
between data and code.

x86 comparison
--------------
The existing QoS identifiers on x86 map well:

  CLOSID (Class of Service ID) on x86 is RCID on RISC-V
    RMID (Resource Monitoring ID) on x86 is MCID on RISC-V

In addition, CDP (code data prioritization) on x86 is similar to the
AT (access type) field in CBQRI which defines code and data types.

One aspect of CBQRI that simplifies the RISC-V resctrl interface is that
any cpu (technically a hart, or hardware thread, in RISC-V terminology)
can access the memory-mapped registers of any CBQRI controller in the
system. This means it does not matter which cpu runs the resctrl code.

Example SoC
-----------
This series also includes a Qemu device tree and platform drivers for a
hypothetical SoC with a cache controller that implements CBQRI capacity
operations and a memory controller that implements CBQRI bandwidth
operations.

  - L2 cache controllers
    - Resource type: Capacity
    - Number of capacity blocks (NCBLKS): 12
    	- In the context of a set-associative cache, the number of
	  capacity blocks can be thought of as the number of ways
    - Number of access types: 2 (code and data)
    - Usage monitoring not supported
    - Capacity allocation operations: CONFIG_LIMIT, READ_LIMIT

  - Last-level cache (LLC) controller
    - Resource type: Capacity
    - Number of capacity blocks (NCBLKS): 16
    - Number of access types: 2 (code and data)
    - Usage monitoring operations: CONFIG_EVENT, READ_COUNTER
    - Event IDs supported: None, Occupancy
    - Capacity allocation ops: CONFIG_LIMIT, READ_LIMIT, FLUSH_RCID

  - Memory controllers
    - Resource type: Bandwidth
    - Number of bandwidth blocks (NBWBLKS): 1024
       - Bandwidth blocks do not have a unit but instead represent a
         portion of the total bandwidth resource. For NWBLKS of 1024,
	 each block represents about 0.1% of the bandwidth resource.
    - Maximum reserved bandwidth blocks (MRBWB): 819 (80% of NBWBLKS)
    - Number of access types: 1 (no code/data differentiation)
    - Usage monitoring operations: CONFIG_EVENT, READ_COUNTER
    - Event IDs supported: None, Total read/write byte count, Total
                           read byte count, Total write byte count
    - Bandwidth allocation operations: CONFIG_LIMIT, READ_LIMIT

The memory map for this example SoC:

  Base addr  Size
  0x4820000  4KB  Cluster 0 L2 cache controller
  0x4821000  4KB  Cluster 1 L2 cache controller
  0x4828000  4KB  Memory controller 0
  0x4829000  4KB  Memory controller 1
  0X482a000  4KB  Memory controller 2
  0X482b000  4KB  Shared LLC cache controller

This configuration is only meant to provide a "concrete" example, and it
represents just one of many possible ways that hardware can implement
the CBQRI spec.

The example SoC configuration is created with the following:

  qemu-system-riscv64 \
        -M virt \
        -nographic \
        -smp 8 \
        -device riscv.cbqri.capacity,max_mcids=256,max_rcids=64,ncblks=12,alloc_op_flush_rcid=false,mon_op_config_event=false,mon_op_read_counter=false,mon_evt_id_none=false,mon_evt_id_occupancy=false,mmio_base=0x04820000 \
        -device riscv.cbqri.capacity,max_mcids=256,max_rcids=64,ncblks=12,alloc_op_flush_rcid=false,mon_op_config_event=false,mon_op_read_counter=false,mon_evt_id_none=false,mon_evt_id_occupancy=false,mmio_base=0x04821000 \
        -device riscv.cbqri.capacity,max_mcids=256,max_rcids=64,ncblks=16,mmio_base=0x0482B000 \
        -device riscv.cbqri.bandwidth,max_mcids=256,max_rcids=64,nbwblks=1024,mrbwb=819,mmio_base=0x04828000 \
        -device riscv.cbqri.bandwidth,max_mcids=256,max_rcids=64,nbwblks=1024,mrbwb=819,mmio_base=0x04829000 \
        -device riscv.cbqri.bandwidth,max_mcids=256,max_rcids=64,nbwblks=1024,mrbwb=819,mmio_base=0x0482a000

In addition, please note that this series only implements the register
interface that CBQRI specifies. It does not attempt to emulate the
performance impact of configuring limits on shared resources like cache
and memory bandwidth. 

Versioning
----------
I chose to make this series v1 as there have been many changes from the
old proof-of-concept. However, here are previous series to make the
history clear:

 [RFC PATCH 00/21] RISC-V: QoS: add CBQRI resctrl interface
 https://lore.kernel.org/all/20230419111111.477118-1-dfustini@baylibre.com/
 The original RFC from the CBQRI proof-of-concept in 2023 that worked
 in conjunction with the Qemu patch series for the proof-of-concept.

 [PATCH v4 0/3] RISC-V: Detect Ssqosid extension and handle srmcfg CSR
 https://lore.kernel.org/all/20251007-ssqosid-v4-0-e8b57e59d812@kernel.org/
 More recently I thought it would be simpler to upstream just the
 Ssqosid patches first. However, I got feedback that it was hard to
 review without the CBQRI patches in the same series.

Open issues:
------------
 - Checkpatch false positive: there is a checkpatch warning about
   "Argument '__next' is not used in function-like macro"
   - __switch_to_srmcfg(__next) is needed to avoid the error reported
     by LKP for riscv-allnoconfig:
     https://lore.kernel.org/oe-kbuild-all/202509162355.wByessnb-lkp@intel.com/
   - __switch_to_srmcfg() will trigger a build error in clang when
     CONFIG_RISCV_ISA_SSQOSID is turned off.

 - The number of CBQRI controllers is hard coded
   - This was done as a simple approach in the proof-of-concept as there
     were 6 controllers
   - I need to refactor this so that it is dynamically allocated based
     on the number of controllers present in the system

 - Stub platform drivers are included to demonstrate device tree integration
   - I am expecting a real CBQRI-enabled hardware platform using device
     tree would have real platform drivers for controllers that
     implement CBQRI.
   - To demonstrate the interaction with the qemu model, I have included
     patches which create "stub" drivers for a cache controller and a
     generic bandwidth controller. These patches are not meant for
     upstream, so I did not create binding documentation for the
     compatibles.

 - Add RQSC table support for ACPI platforms
   - My kernel patches from the RQSC proof-of-concept were based on
     v6.14, so I need to rebase them.
   - The necessary PPTT helpers are already in 6.19 thanks to the MPAM
     driver series. This should help reduce the number of patches in my
     RQSC series.
   - My Qemu patches for RQSC will also take some work to rebase on top
     of my recent Qemu CBQRI+Ssqosid v4 series.

 - No L2 and L3 cache occupancy monitoring
   - This is not currently implemented and I have to decided to leave
     it as an enhancement for a future series after the Ssqosid and
     CBQRI core are merged.

 - No MBM (bandwidth monitoring)
   - MBA schema works ok for the CBQRI-enabled memory controllers, but
     resctrl does not currently have solution for representing MBM for
     bandwidth resources that are not associated with a L3 cache.
   - For the old CBQRI proof-of-concept RFC, two separate domains were
     created for each memory controller: one for MB (allocation) and one
     for MBM (monitoring).
   - The monitoring domains had to pretend that these memory controllers
     were L3 caches which is not the case. I have removed this as it was
     too complicated and not the right solution.
   - Fenghua Yu talked about a similar problem last month at LPC in the
     resctrl BoF during the "MBA/MBM on CPU-less Memory Node" topic:
     https://lpc.events/event/19/contributions/2093/
   - I hope to work with resctrl developers on finding a solution.

---
Drew Fustini (19):
      dt-bindings: riscv: Add Ssqosid extension description
      RISC-V: Detect the Ssqosid extension
      RISC-V: Add support for srmcfg CSR from Ssqosid ext
      RISC-V: QoS: define properties of CBQRI controllers
      RISC-V: QoS: define CBQRI capacity and bandwidth capabilities
      RISC-V: QoS: define CBQRI resctrl resources and domains
      RISC-V: QoS: define prototypes for resctrl interface
      RISC-V: QoS: add resctrl interface for CBQRI controllers
      RISC-V: QoS: expose implementation to resctrl
      RISC-V: QoS: add late_initcall to setup resctrl interface
      RISC-V: QoS: add to build when CONFIG_RISCV_ISA_SSQOSID set
      RISC-V: QoS: make CONFIG_RISCV_ISA_SSQOSID select resctrl
      dt-bindings: riscv: add riscv,cbqri bindings
      [NFU] resctrl: riscv: add CBQRI cache controller driver
      [NFU] resctrl: riscv: add CBQRI bandwidth controller driver
      [NFU] resctrl: riscv: build CBQRI drivers
      [NFU] riscv: dts: qemu: add dump from virt machine
      [NFU] riscv: dts: qemu: add CBQRI controller nodes
      [NFU] riscv: dts: build qemu dtb for CONFIG_ARCH_VIRT

 .../devicetree/bindings/riscv/extensions.yaml      |    6 +
 .../devicetree/bindings/riscv/riscv,cbqri.yaml     |   28 +
 MAINTAINERS                                        |   10 +
 arch/riscv/Kconfig                                 |   20 +
 arch/riscv/boot/dts/Makefile                       |    1 +
 arch/riscv/boot/dts/qemu/Makefile                  |    3 +
 arch/riscv/boot/dts/qemu/qemu-virt-cbqri.dts       |  458 ++++++++
 arch/riscv/include/asm/csr.h                       |    8 +
 arch/riscv/include/asm/hwcap.h                     |    1 +
 arch/riscv/include/asm/processor.h                 |    3 +
 arch/riscv/include/asm/qos.h                       |   41 +
 arch/riscv/include/asm/resctrl.h                   |    2 +
 arch/riscv/include/asm/switch_to.h                 |    3 +
 arch/riscv/kernel/Makefile                         |    2 +
 arch/riscv/kernel/cpufeature.c                     |    1 +
 arch/riscv/kernel/qos/Makefile                     |    2 +
 arch/riscv/kernel/qos/internal.h                   |  155 +++
 arch/riscv/kernel/qos/qos.c                        |   32 +
 arch/riscv/kernel/qos/qos_resctrl.c                | 1191 ++++++++++++++++++++
 drivers/resctrl/Kconfig                            |    2 +
 drivers/resctrl/Makefile                           |    2 +
 drivers/resctrl/riscv/Kconfig                      |   25 +
 drivers/resctrl/riscv/Makefile                     |    4 +
 drivers/resctrl/riscv/cbqri_bandwidth.c            |   79 ++
 drivers/resctrl/riscv/cbqri_cache.c                |  106 ++
 include/linux/riscv_qos.h                          |   78 ++
 26 files changed, 2263 insertions(+)
---
base-commit: 9ace4753a5202b02191d54e9fdf7f9e3d02b85eb
change-id: 20260112-ssqosid-cbqri-407cfcda9ff4

Best regards,
-- 
Drew Fustini <fustini@kernel.org>


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

* [PATCH RFC 01/19] dt-bindings: riscv: Add Ssqosid extension description
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 02/19] RISC-V: Detect the Ssqosid extension Drew Fustini
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86
  Cc: Conor Dooley

Document the ratified Supervisor-mode Quality of Service ID (Ssqosid)
extension v1.0.

Link: https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 Documentation/devicetree/bindings/riscv/extensions.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml
index 5bab356addc8..27a7b4e63eb1 100644
--- a/Documentation/devicetree/bindings/riscv/extensions.yaml
+++ b/Documentation/devicetree/bindings/riscv/extensions.yaml
@@ -165,6 +165,12 @@ properties:
             ratified at commit d70011dde6c2 ("Update to ratified state")
             of riscv-j-extension.
 
+        - const: ssqosid
+          description: |
+            The Ssqosid extension for Quality of Service ID is ratified
+            as v1.0 in commit 5059e0ca641c  ("Merge pull request #7 from
+            ved-rivos/Ratified") of riscv-ssqosid.
+
         - const: sstc
           description: |
             The standard Sstc supervisor-level extension for time compare as

-- 
2.43.0


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

* [PATCH RFC 02/19] RISC-V: Detect the Ssqosid extension
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 01/19] dt-bindings: riscv: Add Ssqosid extension description Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 03/19] RISC-V: Add support for srmcfg CSR from Ssqosid ext Drew Fustini
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

Ssqosid is the RISC-V Quality-of-Service (QoS) Identifiers specification
which defines the Supervisor Resource Management Configuration (srmcfg)
register.

Link: https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0
Signed-off-by: Kornel Dulęba <mindal@semihalf.com>
[fustini: rebase on riscv/for-next]
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 arch/riscv/include/asm/hwcap.h | 1 +
 arch/riscv/kernel/cpufeature.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index 4369a2338541..28dff8233b34 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -110,6 +110,7 @@
 #define RISCV_ISA_EXT_ZALASR		101
 #define RISCV_ISA_EXT_ZILSD		102
 #define RISCV_ISA_EXT_ZCLSD		103
+#define RISCV_ISA_EXT_SSQOSID		104
 
 #define RISCV_ISA_EXT_XLINUXENVCFG	127
 
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index c05b11596c19..bf704b48679c 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -558,6 +558,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
 	__RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA),
 	__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
 	__RISCV_ISA_EXT_SUPERSET(ssnpm, RISCV_ISA_EXT_SSNPM, riscv_xlinuxenvcfg_exts),
+	__RISCV_ISA_EXT_DATA(ssqosid, RISCV_ISA_EXT_SSQOSID),
 	__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
 	__RISCV_ISA_EXT_DATA(svade, RISCV_ISA_EXT_SVADE),
 	__RISCV_ISA_EXT_DATA_VALIDATE(svadu, RISCV_ISA_EXT_SVADU, riscv_ext_svadu_validate),

-- 
2.43.0


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

* [PATCH RFC 03/19] RISC-V: Add support for srmcfg CSR from Ssqosid ext
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 01/19] dt-bindings: riscv: Add Ssqosid extension description Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 02/19] RISC-V: Detect the Ssqosid extension Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 04/19] RISC-V: QoS: define properties of CBQRI controllers Drew Fustini
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

Add support for the srmcfg CSR defined in the Ssqosid ISA extension
(Supervisor-mode Quality of Service ID). The CSR contains two fields:

  - Resource Control ID (RCID) used determine resource allocation
  - Monitoring Counter ID (MCID) used to track resource usage

Requests from a hart to shared resources like cache will be tagged with
these IDs. This allows the usage of shared resources to be associated
with the task currently running on the hart.

A srmcfg field is added to thread_struct and has the same format as the
srmcfg CSR. This allows the scheduler to set the hart's srmcfg CSR to
contain the RCID and MCID for the task that is being scheduled in. The
srmcfg CSR is only written to if the thread_struct.srmcfg is different
than the current value of the CSR.

A per-cpu variable cpu_srmcfg is used to mirror that state of the CSR.
This is because access to L1D hot memory should be several times faster
than a CSR read. Also, in the case of virtualization, accesses to this
CSR are trapped in the hypervisor.

Link: https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0
Co-developed-by: Kornel Dulęba <mindal@semihalf.com>
Signed-off-by: Kornel Dulęba <mindal@semihalf.com>
[fustini: rename csr, refactor switch_to, rebase on riscv/for-next]
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 MAINTAINERS                        |  7 +++++++
 arch/riscv/Kconfig                 | 17 ++++++++++++++++
 arch/riscv/include/asm/csr.h       |  8 ++++++++
 arch/riscv/include/asm/processor.h |  3 +++
 arch/riscv/include/asm/qos.h       | 41 ++++++++++++++++++++++++++++++++++++++
 arch/riscv/include/asm/switch_to.h |  3 +++
 arch/riscv/kernel/Makefile         |  2 ++
 arch/riscv/kernel/qos/Makefile     |  2 ++
 arch/riscv/kernel/qos/qos.c        |  5 +++++
 9 files changed, 88 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 765ad2daa218..e98d553bd0ca 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22505,6 +22505,13 @@ F:	drivers/perf/riscv_pmu.c
 F:	drivers/perf/riscv_pmu_legacy.c
 F:	drivers/perf/riscv_pmu_sbi.c
 
+RISC-V QOS RESCTRL SUPPORT
+M:	Drew Fustini <fustini@kernel.org>
+L:	linux-riscv@lists.infradead.org
+S:	Supported
+F:	arch/riscv/include/asm/qos.h
+F:	arch/riscv/kernel/qos/
+
 RISC-V RPMI AND MPXY DRIVERS
 M:	Rahul Pathak <rahul@summations.net>
 M:	Anup Patel <anup@brainfault.org>
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6b39f37f769a..35a6238b02c5 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -595,6 +595,23 @@ config RISCV_ISA_SVNAPOT
 
 	  If you don't know what to do here, say Y.
 
+config RISCV_ISA_SSQOSID
+	bool "Ssqosid extension support for supervisor mode Quality of Service ID"
+	default y
+	help
+	  Adds support for the Ssqosid ISA extension (Supervisor-mode
+	  Quality of Service ID).
+
+	  Ssqosid defines the srmcfg CSR which allows the system to tag the
+	  running process with an RCID (Resource Control ID) and MCID
+	  (Monitoring Counter ID). The RCID is used to determine resource
+	  allocation. The MCID is used to track resource usage in event
+	  counters.
+
+	  For example, a cache controller may use the RCID to apply a
+	  cache partitioning scheme and use the MCID to track how much
+	  cache a process, or a group of processes, is using.
+
 config RISCV_ISA_SVPBMT
 	bool "Svpbmt extension support for supervisor mode page-based memory types"
 	depends on 64BIT && MMU
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 4a37a98398ad..2590b89b8f72 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -75,6 +75,13 @@
 #define SATP_ASID_MASK	_AC(0xFFFF, UL)
 #endif
 
+/* SRMCFG fields */
+#define SRMCFG_RCID_MASK	_AC(0x00000FFF, UL)
+#define SRMCFG_MCID_MASK	SRMCFG_RCID_MASK
+#define SRMCFG_MCID_SHIFT	16
+#define SRMCFG_MASK		((SRMCFG_MCID_MASK << SRMCFG_MCID_SHIFT) | \
+				  SRMCFG_RCID_MASK)
+
 /* Exception cause high bit - is an interrupt if set */
 #define CAUSE_IRQ_FLAG		(_AC(1, UL) << (__riscv_xlen - 1))
 
@@ -317,6 +324,7 @@
 #define CSR_STVAL		0x143
 #define CSR_SIP			0x144
 #define CSR_SATP		0x180
+#define CSR_SRMCFG		0x181
 
 #define CSR_STIMECMP		0x14D
 #define CSR_STIMECMPH		0x15D
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index da5426122d28..183c55e32b96 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -122,6 +122,9 @@ struct thread_struct {
 	/* A forced icache flush is not needed if migrating to the previous cpu. */
 	unsigned int prev_cpu;
 #endif
+#ifdef CONFIG_RISCV_ISA_SSQOSID
+	u32 srmcfg;
+#endif
 };
 
 /* Whitelist the fstate from the task_struct for hardened usercopy */
diff --git a/arch/riscv/include/asm/qos.h b/arch/riscv/include/asm/qos.h
new file mode 100644
index 000000000000..84830d7c6dc4
--- /dev/null
+++ b/arch/riscv/include/asm/qos.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RISCV_QOS_H
+#define _ASM_RISCV_QOS_H
+
+#ifdef CONFIG_RISCV_ISA_SSQOSID
+
+#include <linux/sched.h>
+#include <linux/jump_label.h>
+
+#include <asm/barrier.h>
+#include <asm/csr.h>
+#include <asm/hwcap.h>
+
+/* cached value of srmcfg csr for each cpu */
+DECLARE_PER_CPU(u32, cpu_srmcfg);
+
+static inline void __switch_to_srmcfg(struct task_struct *next)
+{
+	u32 *cpu_srmcfg_ptr = this_cpu_ptr(&cpu_srmcfg);
+	u32 thread_srmcfg;
+
+	thread_srmcfg = READ_ONCE(next->thread.srmcfg);
+
+	if (thread_srmcfg != *cpu_srmcfg_ptr) {
+		*cpu_srmcfg_ptr = thread_srmcfg;
+		csr_write(CSR_SRMCFG, thread_srmcfg);
+	}
+}
+
+static __always_inline bool has_srmcfg(void)
+{
+	return riscv_has_extension_unlikely(RISCV_ISA_EXT_SSQOSID);
+}
+
+#else /* ! CONFIG_RISCV_ISA_SSQOSID  */
+
+static __always_inline bool has_srmcfg(void) { return false; }
+#define __switch_to_srmcfg(__next) do { } while (0)
+
+#endif /* CONFIG_RISCV_ISA_SSQOSID */
+#endif /* _ASM_RISCV_QOS_H */
diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h
index 0e71eb82f920..a684a3795d3d 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -14,6 +14,7 @@
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/csr.h>
+#include <asm/qos.h>
 
 #ifdef CONFIG_FPU
 extern void __fstate_save(struct task_struct *save_to);
@@ -119,6 +120,8 @@ do {							\
 		__switch_to_fpu(__prev, __next);	\
 	if (has_vector() || has_xtheadvector())		\
 		__switch_to_vector(__prev, __next);	\
+	if (has_srmcfg())				\
+		__switch_to_srmcfg(__next);	\
 	if (switch_to_should_flush_icache(__next))	\
 		local_flush_icache_all();		\
 	__switch_to_envcfg(__next);			\
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index f60fce69b725..a3c36d18145c 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -125,3 +125,5 @@ obj-$(CONFIG_ACPI)		+= acpi.o
 obj-$(CONFIG_ACPI_NUMA)	+= acpi_numa.o
 
 obj-$(CONFIG_GENERIC_CPU_VULNERABILITIES) += bugs.o
+
+obj-$(CONFIG_RISCV_ISA_SSQOSID) += qos/
diff --git a/arch/riscv/kernel/qos/Makefile b/arch/riscv/kernel/qos/Makefile
new file mode 100644
index 000000000000..9f996263a86d
--- /dev/null
+++ b/arch/riscv/kernel/qos/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_RISCV_ISA_SSQOSID) += qos.o
diff --git a/arch/riscv/kernel/qos/qos.c b/arch/riscv/kernel/qos/qos.c
new file mode 100644
index 000000000000..7b06f7ae9056
--- /dev/null
+++ b/arch/riscv/kernel/qos/qos.c
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <asm/qos.h>
+
+/* cached value of sqoscfg csr for each cpu */
+DEFINE_PER_CPU(u32, cpu_srmcfg);

-- 
2.43.0


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

* [PATCH RFC 04/19] RISC-V: QoS: define properties of CBQRI controllers
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (2 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH RFC 03/19] RISC-V: Add support for srmcfg CSR from Ssqosid ext Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 05/19] RISC-V: QoS: define CBQRI capacity and bandwidth capabilities Drew Fustini
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

Define data structure to represent the CBQRI properties that a driver
for an CBQRI-capable controller would discover during probe.

Each instance of a CBQRI-capable controller is added to a list that the
RISC-V CBQRI resctrl implementation will consume.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 MAINTAINERS               |  1 +
 include/linux/riscv_qos.h | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index e98d553bd0ca..31e536304972 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22511,6 +22511,7 @@ L:	linux-riscv@lists.infradead.org
 S:	Supported
 F:	arch/riscv/include/asm/qos.h
 F:	arch/riscv/kernel/qos/
+F:	include/linux/riscv_qos.h
 
 RISC-V RPMI AND MPXY DRIVERS
 M:	Rahul Pathak <rahul@summations.net>
diff --git a/include/linux/riscv_qos.h b/include/linux/riscv_qos.h
new file mode 100644
index 000000000000..51c3a96bbcd0
--- /dev/null
+++ b/include/linux/riscv_qos.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __LINUX_RISCV_QOS_H
+#define __LINUX_RISCV_QOS_H
+
+#include <linux/iommu.h>
+#include <linux/types.h>
+
+#include <asm/qos.h>
+
+enum cbqri_controller_type {
+	CBQRI_CONTROLLER_TYPE_CAPACITY,
+	CBQRI_CONTROLLER_TYPE_BANDWIDTH,
+	CBQRI_CONTROLLER_TYPE_UNKNOWN
+};
+
+struct cbqri_controller_info {
+	unsigned long addr;
+	unsigned long size;
+	enum cbqri_controller_type type;
+	u32 rcid_count;
+	u32 mcid_count;
+	struct list_head list;
+
+	struct cache_controller {
+		u32 cache_level;
+		u32 cache_size; /* in bytes */
+		struct cpumask cpu_mask;
+	} cache;
+};
+
+extern struct list_head cbqri_controllers;
+
+#endif /* __LINUX_RISCV_QOS_H */

-- 
2.43.0


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

* [PATCH RFC 05/19] RISC-V: QoS: define CBQRI capacity and bandwidth capabilities
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (3 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH RFC 04/19] RISC-V: QoS: define properties of CBQRI controllers Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 06/19] RISC-V: QoS: define CBQRI resctrl resources and domains Drew Fustini
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

Define data structures to store the capacity and bandwidth capabilities
that are discovered for a CBQRI-capable controller.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 arch/riscv/kernel/qos/internal.h | 128 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 128 insertions(+)

diff --git a/arch/riscv/kernel/qos/internal.h b/arch/riscv/kernel/qos/internal.h
new file mode 100644
index 000000000000..ff2c7eff50be
--- /dev/null
+++ b/arch/riscv/kernel/qos/internal.h
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _ASM_RISCV_QOS_INTERNAL_H
+#define _ASM_RISCV_QOS_INTERNAL_H
+
+#include <linux/resctrl.h>
+
+#define CBQRI_CC_CAPABILITIES_OFF 0
+#define CBQRI_CC_MON_CTL_OFF      8
+#define CBQRI_CC_MON_CTL_VAL_OFF 16
+#define CBQRI_CC_ALLOC_CTL_OFF   24
+#define CBQRI_CC_BLOCK_MASK_OFF  32
+
+#define CBQRI_BC_CAPABILITIES_OFF 0
+#define CBQRI_BC_MON_CTL_OFF      8
+#define CBQRI_BC_MON_CTR_VAL_OFF 16
+#define CBQRI_BC_ALLOC_CTL_OFF   24
+#define CBQRI_BC_BW_ALLOC_OFF    32
+
+#define CBQRI_CC_CAPABILITIES_VER_MINOR_MASK  GENMASK(3, 0)
+#define CBQRI_CC_CAPABILITIES_VER_MAJOR_MASK  GENMASK(7, 4)
+
+#define CBQRI_CC_CAPABILITIES_FRCID_MASK   0x1
+#define CBQRI_CC_CAPABILITIES_FRCID_SHIFT  24
+
+#define CBQRI_CC_CAPABILITIES_NCBLKS_SHIFT 8
+#define CBQRI_CC_CAPABILITIES_NCBLKS_MASK  0xFFFF
+
+#define CBQRI_BC_CAPABILITIES_VER_MINOR_MASK  GENMASK(3, 0)
+#define CBQRI_BC_CAPABILITIES_VER_MAJOR_MASK  GENMASK(7, 4)
+
+#define CBQRI_BC_CAPABILITIES_NBWBLKS_SHIFT 8
+#define CBQRI_BC_CAPABILITIES_NBWBLKS_MASK  0xFFFF
+#define CBQRI_BC_CAPABILITIES_MRBWB_SHIFT   32
+#define CBQRI_BC_CAPABILITIES_MRBWB_MASK    0xFFFF
+
+#define CBQRI_CONTROL_REGISTERS_BUSY_SHIFT   39
+#define CBQRI_CONTROL_REGISTERS_BUSY_MASK    0x01
+#define CBQRI_CONTROL_REGISTERS_STATUS_SHIFT 32
+#define CBQRI_CONTROL_REGISTERS_STATUS_MASK  0x7F
+#define CBQRI_CONTROL_REGISTERS_OP_SHIFT     0
+#define CBQRI_CONTROL_REGISTERS_OP_MASK      0x1F
+#define CBQRI_CONTROL_REGISTERS_AT_SHIFT     5
+#define CBQRI_CONTROL_REGISTERS_AT_MASK      0x07
+#define CBQRI_CONTROL_REGISTERS_AT_DATA      0
+#define CBQRI_CONTROL_REGISTERS_AT_CODE      1
+#define CBQRI_CONTROL_REGISTERS_RCID_SHIFT   8
+#define CBQRI_CONTROL_REGISTERS_RCID_MASK    0xFFF
+#define CBQRI_CONTROL_REGISTERS_RBWB_SHIFT   0
+#define CBQRI_CONTROL_REGISTERS_RBWB_MASK    0xFFFF
+
+#define CBQRI_CC_MON_CTL_OP_CONFIG_EVENT 1
+#define CBQRI_CC_MON_CTL_OP_READ_COUNTER 2
+#define CBQRI_CC_MON_CTL_STATUS_SUCCESS  1
+
+#define CBQRI_CC_ALLOC_CTL_OP_CONFIG_LIMIT 1
+#define CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT   2
+#define CBQRI_CC_ALLOC_CTL_OP_FLUSH_RCID   3
+#define CBQRI_CC_ALLOC_CTL_STATUS_SUCCESS  1
+
+#define CBQRI_BC_MON_CTL_OP_CONFIG_EVENT 1
+#define CBQRI_BC_MON_CTL_OP_READ_COUNTER 2
+#define CBQRI_BC_MON_CTL_STATUS_SUCCESS  1
+
+#define CBQRI_BC_ALLOC_CTL_OP_CONFIG_LIMIT 1
+#define CBQRI_BC_ALLOC_CTL_OP_READ_LIMIT   2
+#define CBQRI_BC_ALLOC_CTL_STATUS_SUCCESS  1
+
+/* Capacity Controller hardware capabilities */
+struct riscv_cbqri_capacity_caps {
+	u16 ncblks; /* number of capacity blocks */
+	u16 cache_level;
+	u32 blk_size;
+
+	bool supports_alloc_at_data;
+	bool supports_alloc_at_code;
+
+	bool supports_alloc_op_config_limit;
+	bool supports_alloc_op_read_limit;
+	bool supports_alloc_op_flush_rcid;
+
+	bool supports_mon_at_data;
+	bool supports_mon_at_code;
+
+	bool supports_mon_op_config_event;
+	bool supports_mon_op_read_counter;
+
+	bool supports_mon_evt_id_none;
+	bool supports_mon_evt_id_occupancy;
+};
+
+/* Bandwidth Controller hardware capabilities */
+struct riscv_cbqri_bandwidth_caps {
+	u16 nbwblks; /* number of bandwidth blocks */
+	u16 mrbwb;   /* max reserved bw blocks */
+
+	bool supports_alloc_at_data;
+	bool supports_alloc_at_code;
+
+	bool supports_alloc_op_config_limit;
+	bool supports_alloc_op_read_limit;
+
+	bool supports_mon_at_data;
+	bool supports_mon_at_code;
+
+	bool supports_mon_op_config_event;
+	bool supports_mon_op_read_counter;
+
+	bool supports_mon_evt_id_none;
+	bool supports_mon_evt_id_rdwr_count;
+	bool supports_mon_evt_id_rdonly_count;
+	bool supports_mon_evt_id_wronly_count;
+};
+
+struct cbqri_controller {
+	struct cbqri_controller_info *ctrl_info;
+	void __iomem *base;
+
+	int ver_major;
+	int ver_minor;
+
+	struct riscv_cbqri_bandwidth_caps bc;
+	struct riscv_cbqri_capacity_caps cc;
+
+	bool alloc_capable;
+	bool mon_capable;
+};
+
+#endif /* _ASM_RISCV_QOS_INTERNAL_H */

-- 
2.43.0


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

* [PATCH RFC 06/19] RISC-V: QoS: define CBQRI resctrl resources and domains
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (4 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH RFC 05/19] RISC-V: QoS: define CBQRI capacity and bandwidth capabilities Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 07/19] RISC-V: QoS: define prototypes for resctrl interface Drew Fustini
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

Define data structures to encapsulate the resctrl resource
and domain structures.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
[fustini: rebased on riscv/for-next]
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 arch/riscv/kernel/qos/internal.h | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/riscv/kernel/qos/internal.h b/arch/riscv/kernel/qos/internal.h
index ff2c7eff50be..c0402dd06cfa 100644
--- a/arch/riscv/kernel/qos/internal.h
+++ b/arch/riscv/kernel/qos/internal.h
@@ -65,6 +65,11 @@
 #define CBQRI_BC_ALLOC_CTL_OP_READ_LIMIT   2
 #define CBQRI_BC_ALLOC_CTL_STATUS_SUCCESS  1
 
+int qos_resctrl_setup(void);
+void qos_resctrl_exit(void);
+int qos_resctrl_online_cpu(unsigned int cpu);
+int qos_resctrl_offline_cpu(unsigned int cpu);
+
 /* Capacity Controller hardware capabilities */
 struct riscv_cbqri_capacity_caps {
 	u16 ncblks; /* number of capacity blocks */
@@ -125,4 +130,26 @@ struct cbqri_controller {
 	bool mon_capable;
 };
 
+struct cbqri_resctrl_res {
+	struct rdt_resource     resctrl_res;
+	struct cbqri_controller controller;
+	u32 max_rcid;
+	u32 max_mcid;
+};
+
+struct cbqri_resctrl_dom {
+	struct rdt_domain_hdr       resctrl_dom_hdr;
+	struct rdt_ctrl_domain  resctrl_ctrl_dom;
+	struct rdt_mon_domain   resctrl_mon_dom;
+	u64 cbm;
+	u64 rbwb;
+	u64 *ctrl_val;
+	struct cbqri_controller *hw_ctrl;
+};
+
+struct cbqri_config {
+	u64 cbm; /* capacity block mask */
+	u64 rbwb; /* reserved bandwidth blocks */
+};
+
 #endif /* _ASM_RISCV_QOS_INTERNAL_H */

-- 
2.43.0


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

* [PATCH RFC 07/19] RISC-V: QoS: define prototypes for resctrl interface
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (5 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH RFC 06/19] RISC-V: QoS: define CBQRI resctrl resources and domains Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 08/19] RISC-V: QoS: add resctrl interface for CBQRI controllers Drew Fustini
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

Define the prototypes for the resctrl interface functions that are
implemented on RISC-V.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
[fustini: rebased on riscv/for-next]
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 include/linux/riscv_qos.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/include/linux/riscv_qos.h b/include/linux/riscv_qos.h
index 51c3a96bbcd0..0c551ed85fe1 100644
--- a/include/linux/riscv_qos.h
+++ b/include/linux/riscv_qos.h
@@ -3,6 +3,7 @@
 #ifndef __LINUX_RISCV_QOS_H
 #define __LINUX_RISCV_QOS_H
 
+#include <linux/resctrl_types.h>
 #include <linux/iommu.h>
 #include <linux/types.h>
 
@@ -31,4 +32,47 @@ struct cbqri_controller_info {
 
 extern struct list_head cbqri_controllers;
 
+bool resctrl_arch_alloc_capable(void);
+bool resctrl_arch_mon_capable(void);
+bool resctrl_arch_is_llc_occupancy_enabled(void);
+bool resctrl_arch_is_mbm_local_enabled(void);
+bool resctrl_arch_is_mbm_total_enabled(void);
+
+struct rdt_resource;
+/*
+ * Note about terminology between x86 (Intel RDT/AMD QoS) and RISC-V:
+ *   CLOSID on x86 is RCID on RISC-V
+ *     RMID on x86 is MCID on RISC-V
+ *      CDP on x86 is AT (access type) on RISC-V
+ */
+u32  resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid);
+void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid);
+void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 pmg);
+void resctrl_arch_sched_in(struct task_struct *tsk);
+void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid);
+bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid);
+bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid);
+void resctrl_arch_reset_resources(void);
+void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r, enum resctrl_event_id evtid);
+void resctrl_arch_mon_ctx_free(struct rdt_resource *r, enum resctrl_event_id evtid,
+			       void *arch_mon_ctx);
+struct rdt_domain_hdr *resctrl_arch_find_domain(struct list_head *domain_list, int id);
+
+static inline bool resctrl_arch_event_is_free_running(enum resctrl_event_id evt)
+{
+	/* must be true for resctrl L3 monitoring files to be created */
+	return true;
+}
+
+static inline unsigned int resctrl_arch_round_mon_val(unsigned int val)
+{
+	return val;
+}
+
+/* Not needed for RISC-V */
+static inline void resctrl_arch_enable_mon(void) { }
+static inline void resctrl_arch_disable_mon(void) { }
+static inline void resctrl_arch_enable_alloc(void) { }
+static inline void resctrl_arch_disable_alloc(void) { }
+
 #endif /* __LINUX_RISCV_QOS_H */

-- 
2.43.0


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

* [PATCH RFC 08/19] RISC-V: QoS: add resctrl interface for CBQRI controllers
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (6 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH RFC 07/19] RISC-V: QoS: define prototypes for resctrl interface Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-26 13:01   ` [External] " yunhui cui
  2026-03-26 11:05   ` guo.wenjia23
  2026-01-20  4:14 ` [PATCH RFC 09/19] RISC-V: QoS: expose implementation to resctrl Drew Fustini
                   ` (12 subsequent siblings)
  20 siblings, 2 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

Add interface for CBQRI controller drivers to make use of the resctrl
filesystem.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 arch/riscv/kernel/qos/qos_resctrl.c | 1191 +++++++++++++++++++++++++++++++++++
 1 file changed, 1191 insertions(+)

diff --git a/arch/riscv/kernel/qos/qos_resctrl.c b/arch/riscv/kernel/qos/qos_resctrl.c
new file mode 100644
index 000000000000..5e3a65342e9b
--- /dev/null
+++ b/arch/riscv/kernel/qos/qos_resctrl.c
@@ -0,0 +1,1191 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#define pr_fmt(fmt) "qos: resctrl: " fmt
+
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/riscv_qos.h>
+#include <linux/resctrl.h>
+#include <linux/types.h>
+#include <asm/csr.h>
+#include <asm/qos.h>
+#include "internal.h"
+
+#define MAX_CONTROLLERS 6
+static struct cbqri_controller controllers[MAX_CONTROLLERS];
+static struct cbqri_resctrl_res cbqri_resctrl_resources[RDT_NUM_RESOURCES];
+
+static bool exposed_alloc_capable;
+static bool exposed_mon_capable;
+/* CDP (code data prioritization) on x86 is AT (access type) on RISC-V */
+static bool exposed_cdp_l2_capable;
+static bool exposed_cdp_l3_capable;
+static bool is_cdp_l2_enabled;
+static bool is_cdp_l3_enabled;
+
+/* used by resctrl_arch_system_num_rmid_idx() */
+static u32 max_rmid;
+
+LIST_HEAD(cbqri_controllers);
+
+static int cbqri_wait_busy_flag(struct cbqri_controller *ctrl, int reg_offset);
+
+bool resctrl_arch_alloc_capable(void)
+{
+	return exposed_alloc_capable;
+}
+
+bool resctrl_arch_mon_capable(void)
+{
+	return exposed_mon_capable;
+}
+
+bool resctrl_arch_is_llc_occupancy_enabled(void)
+{
+	return true;
+}
+
+bool resctrl_arch_is_mbm_local_enabled(void)
+{
+	return false;
+}
+
+bool resctrl_arch_is_mbm_total_enabled(void)
+{
+	return false;
+}
+
+bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level rid)
+{
+	switch (rid) {
+	case RDT_RESOURCE_L2:
+		return is_cdp_l2_enabled;
+
+	case RDT_RESOURCE_L3:
+		return is_cdp_l3_enabled;
+
+	default:
+		return false;
+	}
+}
+
+int resctrl_arch_set_cdp_enabled(enum resctrl_res_level rid, bool enable)
+{
+	switch (rid) {
+	case RDT_RESOURCE_L2:
+		if (!exposed_cdp_l2_capable)
+			return -ENODEV;
+		is_cdp_l2_enabled = enable;
+		break;
+
+	case RDT_RESOURCE_L3:
+		if (!exposed_cdp_l3_capable)
+			return -ENODEV;
+		is_cdp_l3_enabled = enable;
+		break;
+
+	default:
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l)
+{
+	if (l >= RDT_NUM_RESOURCES)
+		return NULL;
+
+	return &cbqri_resctrl_resources[l].resctrl_res;
+}
+
+struct rdt_domain_hdr *resctrl_arch_find_domain(struct list_head *domain_list, int id)
+{
+	struct rdt_domain_hdr *hdr;
+
+	lockdep_assert_cpus_held();
+
+	list_for_each_entry(hdr, domain_list, list) {
+		if (hdr->id == id)
+			return hdr;
+	}
+
+	return NULL;
+}
+
+bool resctrl_arch_is_evt_configurable(enum resctrl_event_id evt)
+{
+	return false;
+}
+
+void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r,
+				 enum resctrl_event_id evtid)
+{
+	/* RISC-V can always read an rmid, nothing needs allocating */
+	return NULL;
+}
+
+void resctrl_arch_mon_ctx_free(struct rdt_resource *r,
+			       enum resctrl_event_id evtid, void *arch_mon_ctx)
+{
+	/* not implemented for the RISC-V resctrl interface */
+}
+
+void resctrl_arch_reset_resources(void)
+{
+	/* not implemented for the RISC-V resctrl implementation */
+}
+
+void resctrl_arch_config_cntr(struct rdt_resource *r, struct rdt_mon_domain *d,
+			      enum resctrl_event_id evtid, u32 rmid, u32 closid,
+			      u32 cntr_id, bool assign)
+{
+	/* not implemented for the RISC-V resctrl implementation */
+}
+
+int resctrl_arch_cntr_read(struct rdt_resource *r, struct rdt_mon_domain *d,
+			   u32 unused, u32 rmid, int cntr_id,
+			   enum resctrl_event_id eventid, u64 *val)
+{
+	/* not implemented for the RISC-V resctrl implementation */
+	return 0;
+}
+
+bool resctrl_arch_mbm_cntr_assign_enabled(struct rdt_resource *r)
+{
+	/* not implemented for the RISC-V resctrl implementation */
+	return false;
+}
+
+int resctrl_arch_mbm_cntr_assign_set(struct rdt_resource *r, bool enable)
+{
+	/* not implemented for the RISC-V resctrl implementation */
+	return 0;
+}
+
+void resctrl_arch_reset_cntr(struct rdt_resource *r, struct rdt_mon_domain *d,
+			     u32 unused, u32 rmid, int cntr_id,
+			     enum resctrl_event_id eventid)
+{
+	/* not implemented for the RISC-V resctrl implementation */
+}
+
+bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r)
+{
+	/* not implemented for the RISC-V resctrl implementation */
+	return false;
+}
+
+int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable)
+{
+	/* not implemented for the RISC-V resctrl implementation */
+	return 0;
+}
+
+/*
+ * Note about terminology between x86 (Intel RDT/AMD QoS) and RISC-V:
+ *   CLOSID on x86 is RCID on RISC-V
+ *     RMID on x86 is MCID on RISC-V
+ */
+u32 resctrl_arch_get_num_closid(struct rdt_resource *res)
+{
+	struct cbqri_resctrl_res *hw_res;
+
+	hw_res = container_of(res, struct cbqri_resctrl_res, resctrl_res);
+
+	return hw_res->max_rcid;
+}
+
+u32 resctrl_arch_system_num_rmid_idx(void)
+{
+	return max_rmid;
+}
+
+u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid)
+{
+	return rmid;
+}
+
+void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid)
+{
+	*closid = ((u32)~0); /* refer to X86_RESCTRL_BAD_CLOSID */
+	*rmid = idx;
+}
+
+/* RISC-V resctrl interface does not maintain a default srmcfg value for a given CPU */
+void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid) { }
+
+void resctrl_arch_sched_in(struct task_struct *tsk)
+{
+	__switch_to_srmcfg(tsk);
+}
+
+void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid)
+{
+	u32 srmcfg;
+
+	WARN_ON_ONCE((closid & SRMCFG_RCID_MASK) != closid);
+	WARN_ON_ONCE((rmid & SRMCFG_MCID_MASK) != rmid);
+
+	srmcfg = rmid << SRMCFG_MCID_SHIFT;
+	srmcfg |= closid;
+	WRITE_ONCE(tsk->thread.srmcfg, srmcfg);
+}
+
+void resctrl_arch_sync_cpu_closid_rmid(void *info)
+{
+	struct resctrl_cpu_defaults *r = info;
+
+	lockdep_assert_preemption_disabled();
+
+	if (r) {
+		resctrl_arch_set_cpu_default_closid_rmid(smp_processor_id(),
+							 r->closid, r->rmid);
+	}
+
+	resctrl_arch_sched_in(current);
+}
+
+bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid)
+{
+	u32 srmcfg;
+	bool match;
+
+	srmcfg = READ_ONCE(tsk->thread.srmcfg);
+	match = (srmcfg & SRMCFG_RCID_MASK) == closid;
+	return match;
+}
+
+bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid)
+{
+	u32 tsk_rmid;
+
+	tsk_rmid = READ_ONCE(tsk->thread.srmcfg);
+	tsk_rmid >>= SRMCFG_MCID_SHIFT;
+	tsk_rmid &= SRMCFG_MCID_MASK;
+
+	return tsk_rmid == rmid;
+}
+
+int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_mon_domain *d,
+			   u32 closid, u32 rmid, enum resctrl_event_id eventid,
+			   u64 *val, void *arch_mon_ctx)
+{
+	/*
+	 * The current Qemu implementation of CBQRI capacity and bandwidth
+	 * controllers do not emulate the utilization of resources over
+	 * time. Therefore, Qemu currently sets the invalid bit in
+	 * cc_mon_ctr_val and bc_mon_ctr_val, and there is no meaningful
+	 * value other than 0 to return for reading an RMID (e.g. MCID in
+	 * CBQRI terminology)
+	 */
+
+	return 0;
+}
+
+void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_mon_domain *d,
+			     u32 closid, u32 rmid, enum resctrl_event_id eventid)
+{
+	/* not implemented for the RISC-V resctrl interface */
+}
+
+void resctrl_arch_mon_event_config_read(void *info)
+{
+	/* not implemented for the RISC-V resctrl interface */
+}
+
+void resctrl_arch_mon_event_config_write(void *info)
+{
+	/* not implemented for the RISC-V resctrl interface */
+}
+
+void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain *d)
+{
+	/* not implemented for the RISC-V resctrl implementation */
+}
+
+void resctrl_arch_reset_all_ctrls(struct rdt_resource *r)
+{
+	/* not implemented for the RISC-V resctrl implementation */
+}
+
+/* Set capacity block mask (cc_block_mask) */
+static void cbqri_set_cbm(struct cbqri_controller *ctrl, u64 cbm)
+{
+		int reg_offset;
+		u64 reg;
+
+		reg_offset = CBQRI_CC_BLOCK_MASK_OFF;
+		reg = ioread64(ctrl->base + reg_offset);
+
+		reg = cbm;
+		iowrite64(reg, ctrl->base + reg_offset);
+}
+
+/* Set the Rbwb (reserved bandwidth blocks) field in bc_bw_alloc */
+static void cbqri_set_rbwb(struct cbqri_controller *ctrl, u64 rbwb)
+{
+		int reg_offset;
+		u64 reg;
+
+		reg_offset = CBQRI_BC_BW_ALLOC_OFF;
+		reg = ioread64(ctrl->base + reg_offset);
+		reg &= ~CBQRI_CONTROL_REGISTERS_RBWB_MASK;
+		rbwb &= CBQRI_CONTROL_REGISTERS_RBWB_MASK;
+		reg |= rbwb;
+		iowrite64(reg, ctrl->base + reg_offset);
+}
+
+/* Get the Rbwb (reserved bandwidth blocks) field in bc_bw_alloc */
+static u64 cbqri_get_rbwb(struct cbqri_controller *ctrl)
+{
+		int reg_offset;
+		u64 reg;
+
+		reg_offset = CBQRI_BC_BW_ALLOC_OFF;
+		reg = ioread64(ctrl->base + reg_offset);
+		reg &= CBQRI_CONTROL_REGISTERS_RBWB_MASK;
+		return reg;
+}
+
+static int cbqri_wait_busy_flag(struct cbqri_controller *ctrl, int reg_offset)
+{
+	unsigned long timeout = jiffies + (HZ / 10); /* Timeout after 100ms */
+	int busy;
+	u64 reg;
+
+	while (time_before(jiffies, timeout)) {
+		reg = ioread64(ctrl->base + reg_offset);
+		busy = (reg >> CBQRI_CONTROL_REGISTERS_BUSY_SHIFT) &
+			CBQRI_CONTROL_REGISTERS_BUSY_MASK;
+		if (!busy)
+			return 0;
+	}
+
+	pr_warn("%s(): busy timeout", __func__);
+	return -EIO;
+}
+
+/* Perform capacity allocation control operation on capacity controller */
+static int cbqri_cc_alloc_op(struct cbqri_controller *ctrl, int operation, int rcid,
+			     enum resctrl_conf_type type)
+{
+	int reg_offset = CBQRI_CC_ALLOC_CTL_OFF;
+	int status;
+	u64 reg;
+
+	reg = ioread64(ctrl->base + reg_offset);
+	reg &= ~(CBQRI_CONTROL_REGISTERS_OP_MASK << CBQRI_CONTROL_REGISTERS_OP_SHIFT);
+	reg |= (operation & CBQRI_CONTROL_REGISTERS_OP_MASK) <<
+		CBQRI_CONTROL_REGISTERS_OP_SHIFT;
+	reg &= ~(CBQRI_CONTROL_REGISTERS_RCID_MASK <<
+		 CBQRI_CONTROL_REGISTERS_RCID_SHIFT);
+	reg |= (rcid & CBQRI_CONTROL_REGISTERS_RCID_MASK) <<
+		CBQRI_CONTROL_REGISTERS_RCID_SHIFT;
+
+	/* CBQRI capacity AT is only supported on L2 and L3 caches for now */
+	if (ctrl->ctrl_info->type == CBQRI_CONTROLLER_TYPE_CAPACITY &&
+	    ((ctrl->ctrl_info->cache.cache_level == 2 && is_cdp_l2_enabled) ||
+	    (ctrl->ctrl_info->cache.cache_level == 3 && is_cdp_l3_enabled))) {
+		reg &= ~(CBQRI_CONTROL_REGISTERS_AT_MASK <<
+			 CBQRI_CONTROL_REGISTERS_AT_SHIFT);
+		switch (type) {
+		case CDP_CODE:
+			reg |= (CBQRI_CONTROL_REGISTERS_AT_CODE &
+				CBQRI_CONTROL_REGISTERS_AT_MASK) <<
+				CBQRI_CONTROL_REGISTERS_AT_SHIFT;
+			break;
+		case CDP_DATA:
+		default:
+			reg |= (CBQRI_CONTROL_REGISTERS_AT_DATA &
+				CBQRI_CONTROL_REGISTERS_AT_MASK) <<
+				CBQRI_CONTROL_REGISTERS_AT_SHIFT;
+			break;
+		}
+	}
+
+	iowrite64(reg, ctrl->base + reg_offset);
+
+	if (cbqri_wait_busy_flag(ctrl, reg_offset) < 0) {
+		pr_err("%s(): BUSY timeout when executing the operation", __func__);
+		return -EIO;
+	}
+
+	reg = ioread64(ctrl->base + reg_offset);
+	status = (reg >> CBQRI_CONTROL_REGISTERS_STATUS_SHIFT) &
+		  CBQRI_CONTROL_REGISTERS_STATUS_MASK;
+	if (status != 1) {
+		pr_err("%s(): operation %d failed: status=%d", __func__, operation, status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int cbqri_apply_cache_config(struct cbqri_resctrl_dom *hw_dom, u32 closid,
+				    enum resctrl_conf_type type, struct cbqri_config *cfg)
+{
+	struct cbqri_controller *ctrl = hw_dom->hw_ctrl;
+	int reg_offset;
+	int err = 0;
+	u64 reg;
+
+	if (cfg->cbm != hw_dom->ctrl_val[closid]) {
+		/* Store the new cbm in the ctrl_val array for this closid in this domain */
+		hw_dom->ctrl_val[closid] = cfg->cbm;
+
+		/* Set capacity block mask (cc_block_mask) */
+		cbqri_set_cbm(ctrl, cfg->cbm);
+
+		/* Capacity config limit operation */
+		err = cbqri_cc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_CONFIG_LIMIT, closid, type);
+		if (err < 0) {
+			pr_err("%s(): operation failed: err = %d", __func__, err);
+			return err;
+		}
+
+		/* Clear cc_block_mask before read limit to verify op works*/
+		cbqri_set_cbm(ctrl, 0);
+
+		/* Performa capacity read limit operation to verify blockmask */
+		err = cbqri_cc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, closid, type);
+		if (err < 0) {
+			pr_err("%s(): operation failed: err = %d", __func__, err);
+			return err;
+		}
+
+		/* Read capacity blockmask to verify it matches the requested config */
+		reg_offset = CBQRI_CC_BLOCK_MASK_OFF;
+		reg = ioread64(ctrl->base + reg_offset);
+		if (reg != cfg->cbm) {
+			pr_warn("%s(): failed to verify allocation (reg:%llx != cbm:%llx)",
+				__func__, reg, cfg->cbm);
+			return -EIO;
+		}
+	}
+
+	return err;
+}
+
+/* Perform bandwidth allocation control operation on bandwidth controller */
+static int cbqri_bc_alloc_op(struct cbqri_controller *ctrl, int operation, int rcid)
+{
+	int reg_offset = CBQRI_BC_ALLOC_CTL_OFF;
+	int status;
+	u64 reg;
+
+	reg = ioread64(ctrl->base + reg_offset);
+	reg &= ~(CBQRI_CONTROL_REGISTERS_OP_MASK << CBQRI_CONTROL_REGISTERS_OP_SHIFT);
+	reg |=  (operation & CBQRI_CONTROL_REGISTERS_OP_MASK) <<
+		 CBQRI_CONTROL_REGISTERS_OP_SHIFT;
+	reg &= ~(CBQRI_CONTROL_REGISTERS_RCID_MASK << CBQRI_CONTROL_REGISTERS_RCID_SHIFT);
+	reg |=  (rcid & CBQRI_CONTROL_REGISTERS_RCID_MASK) <<
+		 CBQRI_CONTROL_REGISTERS_RCID_SHIFT;
+	iowrite64(reg, ctrl->base + reg_offset);
+
+	if (cbqri_wait_busy_flag(ctrl, reg_offset) < 0) {
+		pr_err("%s(): BUSY timeout when executing the operation", __func__);
+		return -EIO;
+	}
+
+	reg = ioread64(ctrl->base + reg_offset);
+	status = (reg >> CBQRI_CONTROL_REGISTERS_STATUS_SHIFT) &
+		  CBQRI_CONTROL_REGISTERS_STATUS_MASK;
+	if (status != 1) {
+		pr_err("%s(): operation %d failed with status = %d",
+		       __func__, operation, status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int cbqri_apply_bw_config(struct cbqri_resctrl_dom *hw_dom, u32 closid,
+				 enum resctrl_conf_type type, struct cbqri_config *cfg)
+{
+	struct cbqri_controller *ctrl = hw_dom->hw_ctrl;
+	int ret = 0;
+	u64 reg;
+
+	if (cfg->rbwb != hw_dom->ctrl_val[closid]) {
+		/* Store the new rbwb in the ctrl_val array for this closid in this domain */
+		hw_dom->ctrl_val[closid] = cfg->rbwb;
+
+		/* Set reserved bandwidth blocks */
+		cbqri_set_rbwb(ctrl, cfg->rbwb);
+
+		/* Bandwidth config limit operation */
+		ret = cbqri_bc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_CONFIG_LIMIT, closid);
+		if (ret < 0) {
+			pr_err("%s(): operation failed: ret = %d", __func__, ret);
+			return ret;
+		}
+
+		/* Clear rbwb before read limit to verify op works*/
+		cbqri_set_rbwb(ctrl, 0);
+
+		/* Bandwidth allocation read limit operation to verify */
+		ret = cbqri_bc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, closid);
+		if (ret < 0) {
+			pr_err("%s(): operation failed: ret = %d", __func__, ret);
+			return ret;
+		}
+
+		/* Read bandwidth allocation to verify it matches the requested config */
+		reg = cbqri_get_rbwb(ctrl);
+		if (reg != cfg->rbwb) {
+			pr_warn("%s(): failed to verify allocation (reg:%llx != rbwb:%llu)",
+				__func__, reg, cfg->rbwb);
+			return -EIO;
+		}
+	}
+
+	return ret;
+}
+
+int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
+			    u32 closid, enum resctrl_conf_type t, u32 cfg_val)
+{
+	struct cbqri_controller *ctrl;
+	struct cbqri_resctrl_dom *dom;
+	struct cbqri_config cfg;
+	int err = 0;
+
+	dom = container_of(d, struct cbqri_resctrl_dom, resctrl_ctrl_dom);
+	ctrl = dom->hw_ctrl;
+
+	if (!r->alloc_capable)
+		return -EINVAL;
+
+	switch (r->rid) {
+	case RDT_RESOURCE_L2:
+	case RDT_RESOURCE_L3:
+		cfg.cbm = cfg_val;
+		err = cbqri_apply_cache_config(dom, closid, t, &cfg);
+		break;
+	case RDT_RESOURCE_MBA:
+		/* covert from percentage to bandwidth blocks */
+		cfg.rbwb = cfg_val * ctrl->bc.nbwblks / 100;
+		err = cbqri_apply_bw_config(dom, closid, t, &cfg);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err;
+}
+
+int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid)
+{
+	struct resctrl_staged_config *cfg;
+	enum resctrl_conf_type t;
+	struct rdt_ctrl_domain *d;
+	int err = 0;
+
+	list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
+		for (t = 0; t < CDP_NUM_TYPES; t++) {
+			cfg = &d->staged_config[t];
+			if (!cfg->have_new_ctrl)
+				continue;
+			err = resctrl_arch_update_one(r, d, closid, t, cfg->new_ctrl);
+			if (err) {
+				pr_warn("%s(): update failed (err=%d)", __func__, err);
+				return err;
+			}
+		}
+	}
+	return err;
+}
+
+u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
+			    u32 closid, enum resctrl_conf_type type)
+{
+	struct cbqri_resctrl_dom *hw_dom;
+	struct cbqri_controller *ctrl;
+	int reg_offset;
+	u32 percent;
+	u32 rbwb;
+	u64 reg;
+	int err;
+
+	hw_dom = container_of(d, struct cbqri_resctrl_dom, resctrl_ctrl_dom);
+
+	ctrl = hw_dom->hw_ctrl;
+
+	if (!r->alloc_capable)
+		return -EINVAL;
+
+	switch (r->rid) {
+	case RDT_RESOURCE_L2:
+	case RDT_RESOURCE_L3:
+		/* Clear cc_block_mask before read limit operation */
+		cbqri_set_cbm(ctrl, 0);
+
+		/* Capacity read limit operation for RCID (closid) */
+		err = cbqri_cc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, type, closid);
+		if (err < 0) {
+			pr_err("%s(): operation failed: err = %d", __func__, err);
+			return -EIO;
+		}
+
+		/* Read capacity block mask for RCID (closid) */
+		reg_offset = CBQRI_CC_BLOCK_MASK_OFF;
+		reg = ioread64(ctrl->base + reg_offset);
+
+		/* Update the config value for the closid in this domain */
+		hw_dom->ctrl_val[closid] = reg;
+		return hw_dom->ctrl_val[closid];
+
+	case RDT_RESOURCE_MBA:
+		/* Capacity read limit operation for RCID (closid) */
+		err = cbqri_bc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, closid);
+		if (err < 0) {
+			pr_err("%s(): operation failed: err = %d", __func__, err);
+			return -EIO;
+		}
+
+		hw_dom->ctrl_val[closid] = cbqri_get_rbwb(ctrl);
+
+		/* Convert from bandwidth blocks to percent */
+		rbwb = hw_dom->ctrl_val[closid];
+		rbwb *= 100;
+		percent = rbwb / ctrl->bc.nbwblks;
+		if (rbwb % ctrl->bc.nbwblks)
+			percent++;
+		return percent;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int cbqri_probe_feature(struct cbqri_controller *ctrl, int reg_offset,
+			       int operation, int *status, bool *access_type_supported)
+{
+	u64 reg, saved_reg;
+	int at;
+
+	/* Keep the initial register value to preserve the WPRI fields */
+	reg = ioread64(ctrl->base + reg_offset);
+	saved_reg = reg;
+
+	/* Execute the requested operation to find if the register is implemented */
+	reg &= ~(CBQRI_CONTROL_REGISTERS_OP_MASK << CBQRI_CONTROL_REGISTERS_OP_SHIFT);
+	reg |= (operation & CBQRI_CONTROL_REGISTERS_OP_MASK) << CBQRI_CONTROL_REGISTERS_OP_SHIFT;
+	iowrite64(reg, ctrl->base + reg_offset);
+	if (cbqri_wait_busy_flag(ctrl, reg_offset) < 0) {
+		pr_err("%s(): BUSY timeout when executing the operation", __func__);
+		return -EIO;
+	}
+
+	/* Get the operation status */
+	reg = ioread64(ctrl->base + reg_offset);
+	*status = (reg >> CBQRI_CONTROL_REGISTERS_STATUS_SHIFT) &
+		   CBQRI_CONTROL_REGISTERS_STATUS_MASK;
+
+	/*
+	 * Check for the AT support if the register is implemented
+	 * (if not, the status value will remain 0)
+	 */
+	if (*status != 0) {
+		/* Set the AT field to a valid value */
+		reg = saved_reg;
+		reg &= ~(CBQRI_CONTROL_REGISTERS_AT_MASK << CBQRI_CONTROL_REGISTERS_AT_SHIFT);
+		reg |= CBQRI_CONTROL_REGISTERS_AT_CODE << CBQRI_CONTROL_REGISTERS_AT_SHIFT;
+		iowrite64(reg, ctrl->base + reg_offset);
+		if (cbqri_wait_busy_flag(ctrl, reg_offset) < 0) {
+			pr_err("%s(): BUSY timeout when setting AT field", __func__);
+			return -EIO;
+		}
+
+		/*
+		 * If the AT field value has been reset to zero,
+		 * then the AT support is not present
+		 */
+		reg = ioread64(ctrl->base + reg_offset);
+		at = (reg >> CBQRI_CONTROL_REGISTERS_AT_SHIFT) & CBQRI_CONTROL_REGISTERS_AT_MASK;
+		if (at == CBQRI_CONTROL_REGISTERS_AT_CODE)
+			*access_type_supported = true;
+		else
+			*access_type_supported = false;
+	}
+
+	/* Restore the original register value */
+	iowrite64(saved_reg, ctrl->base + reg_offset);
+	if (cbqri_wait_busy_flag(ctrl, reg_offset) < 0) {
+		pr_err("%s(): BUSY timeout when restoring the original register value", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * Note: for the purposes of the CBQRI proof-of-concept, debug logging
+ * has been left in this function that detects the properties of CBQRI
+ * capable controllers in the system. pr_info calls would be removed
+ * before submitting non-RFC patches.
+ */
+static int cbqri_probe_controller(struct cbqri_controller_info *ctrl_info,
+				  struct cbqri_controller *ctrl)
+{
+	int err = 0, status;
+	u64 reg;
+
+	pr_info("controller info: type=%d addr=0x%lx size=%lu max-rcid=%u max-mcid=%u",
+		ctrl_info->type, ctrl_info->addr, ctrl_info->size,
+		ctrl_info->rcid_count, ctrl_info->mcid_count);
+
+	/* max_rmid is used by resctrl_arch_system_num_rmid_idx() */
+	max_rmid = ctrl_info->mcid_count;
+
+	ctrl->ctrl_info = ctrl_info;
+
+	/* Try to access the memory-mapped CBQRI registers */
+	if (!request_mem_region(ctrl_info->addr, ctrl_info->size, "cbqri_controller")) {
+		pr_warn("%s(): return %d", __func__, err);
+		return err;
+	}
+	ctrl->base = ioremap(ctrl_info->addr, ctrl_info->size);
+	if (!ctrl->base) {
+		pr_warn("%s(): goto err_release_mem_region", __func__);
+		goto err_release_mem_region;
+	}
+
+	ctrl->alloc_capable = false;
+	ctrl->mon_capable = false;
+
+	/* Probe capacity allocation and monitoring features */
+	if (ctrl_info->type == CBQRI_CONTROLLER_TYPE_CAPACITY) {
+		pr_info("probe capacity controller");
+
+		/* Make sure the register is implemented */
+		reg = ioread64(ctrl->base + CBQRI_CC_CAPABILITIES_OFF);
+		if (reg == 0) {
+			err = -ENODEV;
+			goto err_iounmap;
+		}
+
+		ctrl->ver_minor = reg & CBQRI_CC_CAPABILITIES_VER_MINOR_MASK;
+		ctrl->ver_major = reg & CBQRI_CC_CAPABILITIES_VER_MAJOR_MASK;
+
+		ctrl->cc.supports_alloc_op_flush_rcid = (reg >> CBQRI_CC_CAPABILITIES_FRCID_SHIFT)
+			& CBQRI_CC_CAPABILITIES_FRCID_MASK;
+
+		ctrl->cc.ncblks = (reg >> CBQRI_CC_CAPABILITIES_NCBLKS_SHIFT) &
+				   CBQRI_CC_CAPABILITIES_NCBLKS_MASK;
+
+		/* Calculate size of capacity block in bytes */
+		ctrl->cc.blk_size = ctrl_info->cache.cache_size / ctrl->cc.ncblks;
+		ctrl->cc.cache_level = ctrl_info->cache.cache_level;
+
+		pr_info("version=%d.%d ncblks=%d blk_size=%d cache_level=%d",
+			ctrl->ver_major, ctrl->ver_minor,
+			ctrl->cc.ncblks, ctrl->cc.blk_size, ctrl->cc.cache_level);
+
+		/* Probe monitoring features */
+		err = cbqri_probe_feature(ctrl, CBQRI_CC_MON_CTL_OFF,
+					  CBQRI_CC_MON_CTL_OP_READ_COUNTER, &status,
+					  &ctrl->cc.supports_mon_at_code);
+		if (err) {
+			pr_warn("%s() failed to probe cc_mon_ctl feature", __func__);
+			goto err_iounmap;
+		}
+
+		if (status == CBQRI_CC_MON_CTL_STATUS_SUCCESS) {
+			pr_info("cc_mon_ctl is supported");
+			ctrl->cc.supports_mon_op_config_event = true;
+			ctrl->cc.supports_mon_op_read_counter = true;
+			ctrl->mon_capable = true;
+		} else {
+			pr_info("cc_mon_ctl is NOT supported");
+			ctrl->cc.supports_mon_op_config_event = false;
+			ctrl->cc.supports_mon_op_read_counter = false;
+			ctrl->mon_capable = false;
+		}
+		/*
+		 * AT data is "always" supported as it has the same value
+		 * than when AT field is not supported.
+		 */
+		ctrl->cc.supports_mon_at_data = true;
+		pr_info("supports_mon_at_data: %d, supports_mon_at_code: %d",
+			ctrl->cc.supports_mon_at_data, ctrl->cc.supports_mon_at_code);
+
+		/* Probe allocation features */
+		err = cbqri_probe_feature(ctrl, CBQRI_CC_ALLOC_CTL_OFF,
+					  CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT,
+					  &status, &ctrl->cc.supports_alloc_at_code);
+		if (err) {
+			pr_warn("%s() failed to probe cc_alloc_ctl feature", __func__);
+			goto err_iounmap;
+		}
+
+		if (status == CBQRI_CC_ALLOC_CTL_STATUS_SUCCESS) {
+			pr_info("cc_alloc_ctl is supported");
+			ctrl->cc.supports_alloc_op_config_limit = true;
+			ctrl->cc.supports_alloc_op_read_limit = true;
+			ctrl->alloc_capable = true;
+			exposed_alloc_capable = true;
+		} else {
+			pr_info("cc_alloc_ctl is NOT supported");
+			ctrl->cc.supports_alloc_op_config_limit = false;
+			ctrl->cc.supports_alloc_op_read_limit = false;
+			ctrl->alloc_capable = false;
+		}
+		/*
+		 * AT data is "always" supported as it has the same value
+		 * than when AT field is not supported
+		 */
+		ctrl->cc.supports_alloc_at_data = true;
+		pr_info("supports_alloc_at_data: %d, supports_alloc_at_code: %d",
+			ctrl->cc.supports_alloc_at_data,
+			ctrl->cc.supports_alloc_at_code);
+	} else if (ctrl_info->type == CBQRI_CONTROLLER_TYPE_BANDWIDTH) {
+		pr_info("probe bandwidth controller");
+
+		/* Make sure the register is implemented */
+		reg = ioread64(ctrl->base + CBQRI_BC_CAPABILITIES_OFF);
+		if (reg == 0) {
+			err = -ENODEV;
+			goto err_iounmap;
+		}
+
+		ctrl->ver_minor = reg & CBQRI_BC_CAPABILITIES_VER_MINOR_MASK;
+		ctrl->ver_major = reg & CBQRI_BC_CAPABILITIES_VER_MAJOR_MASK;
+
+		ctrl->bc.nbwblks = (reg >> CBQRI_BC_CAPABILITIES_NBWBLKS_SHIFT) &
+				    CBQRI_BC_CAPABILITIES_NBWBLKS_MASK;
+		ctrl->bc.mrbwb = (reg >> CBQRI_BC_CAPABILITIES_MRBWB_SHIFT) &
+				  CBQRI_BC_CAPABILITIES_MRBWB_MASK;
+
+		pr_info("version=%d.%d nbwblks=%d mrbwb=%d",
+			ctrl->ver_major, ctrl->ver_minor,
+			ctrl->bc.nbwblks, ctrl->bc.mrbwb);
+
+		/* Probe monitoring features */
+		err = cbqri_probe_feature(ctrl, CBQRI_BC_MON_CTL_OFF,
+					  CBQRI_BC_MON_CTL_OP_READ_COUNTER,
+					  &status, &ctrl->bc.supports_mon_at_code);
+		if (err) {
+			pr_warn("%s() failed to probe bc_mon_ctl feature", __func__);
+			goto err_iounmap;
+		}
+
+		if (status == CBQRI_BC_MON_CTL_STATUS_SUCCESS) {
+			pr_info("bc_mon_ctl is supported");
+			ctrl->bc.supports_mon_op_config_event = true;
+			ctrl->bc.supports_mon_op_read_counter = true;
+			ctrl->mon_capable = true;
+			exposed_mon_capable = true;
+		} else {
+			pr_info("bc_mon_ctl is NOT supported");
+			ctrl->bc.supports_mon_op_config_event = false;
+			ctrl->bc.supports_mon_op_read_counter = false;
+			ctrl->mon_capable = false;
+		}
+		/*
+		 * AT data is "always" supported as it has the same value
+		 * than when AT field is not supported
+		 */
+		ctrl->bc.supports_mon_at_data = true;
+		pr_info("supports_mon_at_data: %d, supports_mon_at_code: %d",
+			ctrl->bc.supports_mon_at_data, ctrl->bc.supports_mon_at_code);
+
+		/* Probe allocation features */
+		err = cbqri_probe_feature(ctrl, CBQRI_BC_ALLOC_CTL_OFF,
+					  CBQRI_BC_ALLOC_CTL_OP_READ_LIMIT,
+					  &status, &ctrl->bc.supports_alloc_at_code);
+		if (err) {
+			pr_warn("%s() failed to probe bc_alloc_ctl feature", __func__);
+			goto err_iounmap;
+		}
+
+		if (status == CBQRI_BC_ALLOC_CTL_STATUS_SUCCESS) {
+			pr_warn("bc_alloc_ctl is supported");
+			ctrl->bc.supports_alloc_op_config_limit = true;
+			ctrl->bc.supports_alloc_op_read_limit = true;
+			ctrl->alloc_capable = true;
+			exposed_alloc_capable = true;
+		} else {
+			pr_warn("bc_alloc_ctl is NOT supported");
+			ctrl->bc.supports_alloc_op_config_limit = false;
+			ctrl->bc.supports_alloc_op_read_limit = false;
+			ctrl->alloc_capable = false;
+		}
+
+		/*
+		 * AT data is "always" supported as it has the same value
+		 * than when AT field is not supported
+		 */
+		ctrl->bc.supports_alloc_at_data = true;
+		pr_warn("supports_alloc_at_data: %d, supports_alloc_at_code: %d",
+			ctrl->bc.supports_alloc_at_data, ctrl->bc.supports_alloc_at_code);
+	} else {
+		pr_warn("controller type is UNKNOWN");
+		err = -ENODEV;
+		goto err_release_mem_region;
+	}
+
+	return 0;
+
+err_iounmap:
+	pr_warn("%s(): err_iounmap", __func__);
+	iounmap(ctrl->base);
+
+err_release_mem_region:
+	pr_warn("%s(): err_release_mem_region", __func__);
+	release_mem_region(ctrl_info->addr, ctrl_info->size);
+
+	return err;
+}
+
+static struct rdt_ctrl_domain *qos_new_domain(struct cbqri_controller *ctrl)
+{
+	struct cbqri_resctrl_dom *hw_dom;
+	struct rdt_ctrl_domain *domain;
+
+	hw_dom = kzalloc(sizeof(*hw_dom), GFP_KERNEL);
+	if (!hw_dom)
+		return NULL;
+
+	/* associate this cbqri_controller with the domain */
+	hw_dom->hw_ctrl = ctrl;
+
+	/* the rdt_domain struct from inside the cbqri_resctrl_dom struct */
+	domain = &hw_dom->resctrl_ctrl_dom;
+
+	INIT_LIST_HEAD(&domain->hdr.list);
+
+	return domain;
+}
+
+static int qos_init_domain_ctrlval(struct rdt_resource *r, struct rdt_ctrl_domain *d)
+{
+	struct cbqri_resctrl_res *hw_res;
+	struct cbqri_resctrl_dom *hw_dom;
+	u64 *dc;
+	int err = 0;
+	int i;
+
+	hw_res = container_of(r, struct cbqri_resctrl_res, resctrl_res);
+	if (!hw_res)
+		return -ENOMEM;
+
+	hw_dom = container_of(d, struct cbqri_resctrl_dom, resctrl_ctrl_dom);
+	if (!hw_dom)
+		return -ENOMEM;
+
+	dc = kmalloc_array(hw_res->max_rcid, sizeof(*hw_dom->ctrl_val),
+			   GFP_KERNEL);
+	if (!dc)
+		return -ENOMEM;
+
+	hw_dom->ctrl_val = dc;
+
+	for (i = 0; i < hw_res->max_rcid; i++, dc++) {
+		err = resctrl_arch_update_one(r, d, i, 0, resctrl_get_default_ctrl(r));
+		if (err)
+			return 0;
+		*dc = resctrl_get_default_ctrl(r);
+	}
+	return 0;
+}
+
+static int qos_resctrl_add_controller_domain(struct cbqri_controller *ctrl, int *id)
+{
+	struct rdt_ctrl_domain *domain = NULL;
+	struct cbqri_resctrl_res *cbqri_res = NULL;
+	struct rdt_resource *res = NULL;
+	int internal_id = *id;
+	int err = 0;
+
+	domain = qos_new_domain(ctrl);
+	if (!domain)
+		return -ENOSPC;
+	if (ctrl->ctrl_info->type == CBQRI_CONTROLLER_TYPE_CAPACITY) {
+		cpumask_copy(&domain->hdr.cpu_mask, &ctrl->ctrl_info->cache.cpu_mask);
+		if (ctrl->ctrl_info->cache.cache_level == 2) {
+			cbqri_res = &cbqri_resctrl_resources[RDT_RESOURCE_L2];
+			cbqri_res->max_rcid = ctrl->ctrl_info->rcid_count;
+			cbqri_res->max_mcid = ctrl->ctrl_info->mcid_count;
+			res = &cbqri_res->resctrl_res;
+			res->mon.num_rmid = ctrl->ctrl_info->mcid_count;
+			res->rid = RDT_RESOURCE_L2;
+			res->name = "L2";
+			res->alloc_capable = ctrl->alloc_capable;
+			res->mon_capable = ctrl->mon_capable;
+			res->schema_fmt = RESCTRL_SCHEMA_BITMAP;
+			res->ctrl_scope = RESCTRL_L2_CACHE;
+			res->cache.arch_has_sparse_bitmasks = false;
+			res->cache.arch_has_per_cpu_cfg = false;
+			res->cache.cbm_len = ctrl->cc.ncblks;
+			res->cache.shareable_bits = resctrl_get_default_ctrl(res);
+			res->cache.min_cbm_bits = 1;
+		} else if (ctrl->ctrl_info->cache.cache_level == 3) {
+			cbqri_res = &cbqri_resctrl_resources[RDT_RESOURCE_L3];
+			cbqri_res->max_rcid = ctrl->ctrl_info->rcid_count;
+			cbqri_res->max_mcid = ctrl->ctrl_info->mcid_count;
+			res = &cbqri_res->resctrl_res;
+			res->mon.num_rmid = ctrl->ctrl_info->mcid_count;
+			res->rid = RDT_RESOURCE_L3;
+			res->name = "L3";
+			res->schema_fmt = RESCTRL_SCHEMA_BITMAP;
+			res->ctrl_scope = RESCTRL_L3_CACHE;
+			res->alloc_capable = ctrl->alloc_capable;
+			res->mon_capable = ctrl->mon_capable;
+			res->cache.arch_has_sparse_bitmasks = false;
+			res->cache.arch_has_per_cpu_cfg = false;
+			res->cache.cbm_len = ctrl->cc.ncblks;
+			res->cache.shareable_bits = resctrl_get_default_ctrl(res);
+			res->cache.min_cbm_bits = 1;
+		} else {
+			pr_warn("%s(): unknown cache level %d", __func__,
+				ctrl->ctrl_info->cache.cache_level);
+			err = -ENODEV;
+			goto err_free_domain;
+		}
+	} else if (ctrl->ctrl_info->type == CBQRI_CONTROLLER_TYPE_BANDWIDTH) {
+		if (ctrl->alloc_capable) {
+			cbqri_res = &cbqri_resctrl_resources[RDT_RESOURCE_MBA];
+			cbqri_res->max_rcid = ctrl->ctrl_info->rcid_count;
+			cbqri_res->max_mcid = ctrl->ctrl_info->mcid_count;
+			res = &cbqri_res->resctrl_res;
+			res->mon.num_rmid = ctrl->ctrl_info->mcid_count;
+			res->rid = RDT_RESOURCE_MBA;
+			res->name = "MB";
+			res->schema_fmt = RESCTRL_SCHEMA_RANGE;
+			res->ctrl_scope = RESCTRL_L3_CACHE;
+			res->alloc_capable = ctrl->alloc_capable;
+			res->mon_capable = false;
+			res->membw.delay_linear = true;
+			res->membw.arch_needs_linear = true;
+			res->membw.throttle_mode = THREAD_THROTTLE_UNDEFINED;
+			// The minimum percentage allowed by the CBQRI spec
+			res->membw.min_bw = 1;
+			// The maximum percentage allowed by the CBQRI spec
+			res->membw.max_bw = 80;
+			res->membw.bw_gran = 1;
+		}
+	} else {
+		pr_warn("%s(): unknown resource %d", __func__, ctrl->ctrl_info->type);
+		err = -ENODEV;
+		goto err_free_domain;
+	}
+
+	domain->hdr.id = internal_id;
+	err = qos_init_domain_ctrlval(res, domain);
+	if (err)
+		goto err_free_domain;
+
+	if (cbqri_res) {
+		list_add_tail(&domain->hdr.list, &cbqri_res->resctrl_res.ctrl_domains);
+		*id = internal_id;
+		err = resctrl_online_ctrl_domain(res, domain);
+		if (err) {
+			pr_warn("%s(): failed to online cbqri_res domain", __func__);
+			goto err_free_domain;
+		}
+	}
+
+	return 0;
+
+err_free_domain:
+	pr_warn("%s(): err_free_domain", __func__);
+	kfree(container_of(domain, struct cbqri_resctrl_dom, resctrl_ctrl_dom));
+
+	return err;
+}
+
+int qos_resctrl_setup(void)
+{
+	struct rdt_ctrl_domain *domain, *domain_temp;
+	struct cbqri_controller_info *ctrl_info;
+	struct cbqri_controller *ctrl;
+	struct cbqri_resctrl_res *res;
+	static int found_controllers;
+	int err = 0;
+	int id = 0;
+	int i;
+
+	list_for_each_entry(ctrl_info, &cbqri_controllers, list) {
+		err = cbqri_probe_controller(ctrl_info, &controllers[found_controllers]);
+		if (err) {
+			pr_warn("%s(): failed (%d)", __func__, err);
+			goto err_unmap_controllers;
+		}
+
+		found_controllers++;
+		if (found_controllers > MAX_CONTROLLERS) {
+			pr_warn("%s(): increase MAX_CONTROLLERS value", __func__);
+			break;
+		}
+	}
+
+	for (i = 0; i < RDT_NUM_RESOURCES; i++) {
+		res = &cbqri_resctrl_resources[i];
+		INIT_LIST_HEAD(&res->resctrl_res.ctrl_domains);
+		INIT_LIST_HEAD(&res->resctrl_res.mon_domains);
+		res->resctrl_res.rid = i;
+	}
+
+	for (i = 0; i < found_controllers; i++) {
+		ctrl = &controllers[i];
+		err = qos_resctrl_add_controller_domain(ctrl, &id);
+		if (err) {
+			pr_warn("%s(): failed to add controller domain (%d)", __func__, err);
+			goto err_free_controllers_list;
+		}
+		id++;
+
+		/*
+		 * CDP (code data prioritization) on x86 is similar to
+		 * the AT (access type) field in CBQRI. CDP only supports
+		 * caches so this must be a CBQRI capacity controller.
+		 */
+		if (ctrl->ctrl_info->type == CBQRI_CONTROLLER_TYPE_CAPACITY &&
+		    ctrl->cc.supports_alloc_at_code &&
+		    ctrl->cc.supports_alloc_at_data) {
+			if (ctrl->ctrl_info->cache.cache_level == 2)
+				exposed_cdp_l2_capable = true;
+			else
+				exposed_cdp_l3_capable = true;
+		}
+	}
+
+	pr_info("exposed_alloc_capable = %d", exposed_alloc_capable);
+	pr_info("exposed_mon_capable = %d", exposed_mon_capable);
+	pr_info("exposed_cdp_l2_capable = %d", exposed_cdp_l2_capable);
+	pr_info("exposed_cdp_l3_capable = %d", exposed_cdp_l3_capable);
+
+	return resctrl_init();
+
+err_free_controllers_list:
+	for (i = 0; i < RDT_NUM_RESOURCES; i++) {
+		res = &cbqri_resctrl_resources[i];
+		list_for_each_entry_safe(domain, domain_temp, &res->resctrl_res.ctrl_domains,
+					 hdr.list) {
+			kfree(domain);
+		}
+	}
+
+err_unmap_controllers:
+	for (i = 0; i < found_controllers; i++) {
+		iounmap(controllers[i].base);
+		release_mem_region(controllers[i].ctrl_info->addr, controllers[i].ctrl_info->size);
+	}
+
+	return err;
+}
+
+int qos_resctrl_online_cpu(unsigned int cpu)
+{
+	resctrl_online_cpu(cpu);
+	return 0;
+}
+
+int qos_resctrl_offline_cpu(unsigned int cpu)
+{
+	resctrl_offline_cpu(cpu);
+	return 0;
+}
+

-- 
2.43.0


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

* [PATCH RFC 09/19] RISC-V: QoS: expose implementation to resctrl
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (7 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH RFC 08/19] RISC-V: QoS: add resctrl interface for CBQRI controllers Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 10/19] RISC-V: QoS: add late_initcall to setup resctrl interface Drew Fustini
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

The generic resctrl header include/linux/resctrl.h includes
linux/riscv_qos.h when CONFIG_ARCH_HAS_CPU_RESCTRL is set.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 MAINTAINERS                      | 1 +
 arch/riscv/include/asm/resctrl.h | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 31e536304972..96ead357a634 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22510,6 +22510,7 @@ M:	Drew Fustini <fustini@kernel.org>
 L:	linux-riscv@lists.infradead.org
 S:	Supported
 F:	arch/riscv/include/asm/qos.h
+F:	arch/riscv/include/asm/resctrl.h
 F:	arch/riscv/kernel/qos/
 F:	include/linux/riscv_qos.h
 
diff --git a/arch/riscv/include/asm/resctrl.h b/arch/riscv/include/asm/resctrl.h
new file mode 100644
index 000000000000..7d247d87dab9
--- /dev/null
+++ b/arch/riscv/include/asm/resctrl.h
@@ -0,0 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <linux/riscv_qos.h>

-- 
2.43.0


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

* [PATCH RFC 10/19] RISC-V: QoS: add late_initcall to setup resctrl interface
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (8 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH RFC 09/19] RISC-V: QoS: expose implementation to resctrl Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 11/19] RISC-V: QoS: add to build when CONFIG_RISCV_ISA_SSQOSID set Drew Fustini
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

Add late_initcall which checks if the Ssqosid extension is present, and
if so, calls resctrl setup and sets cpu hotplug state to "qos:online".

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 arch/riscv/kernel/qos/qos.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/riscv/kernel/qos/qos.c b/arch/riscv/kernel/qos/qos.c
index 7b06f7ae9056..2cd5d7be1d10 100644
--- a/arch/riscv/kernel/qos/qos.c
+++ b/arch/riscv/kernel/qos/qos.c
@@ -1,5 +1,32 @@
 // SPDX-License-Identifier: GPL-2.0-only
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/riscv_qos.h>
+
+#include <asm/csr.h>
 #include <asm/qos.h>
 
+#include "internal.h"
+
 /* cached value of sqoscfg csr for each cpu */
 DEFINE_PER_CPU(u32, cpu_srmcfg);
+
+static int __init qos_arch_late_init(void)
+{
+	int err;
+
+	if (!riscv_isa_extension_available(NULL, SSQOSID))
+		return -ENODEV;
+
+	err = qos_resctrl_setup();
+	if (err != 0)
+		return err;
+
+	cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "qos:online", qos_resctrl_online_cpu,
+			  qos_resctrl_offline_cpu);
+
+	return err;
+}
+late_initcall(qos_arch_late_init);

-- 
2.43.0


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

* [PATCH RFC 11/19] RISC-V: QoS: add to build when CONFIG_RISCV_ISA_SSQOSID set
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (9 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH RFC 10/19] RISC-V: QoS: add late_initcall to setup resctrl interface Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 12/19] RISC-V: QoS: make CONFIG_RISCV_ISA_SSQOSID select resctrl Drew Fustini
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

Add the srmcfg CSR handling and the resctrl interface to the build when
CONFIG_RISCV_ISA_SSQOSID is set.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 arch/riscv/kernel/qos/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/riscv/kernel/qos/Makefile b/arch/riscv/kernel/qos/Makefile
index 9f996263a86d..9ed0c13a854d 100644
--- a/arch/riscv/kernel/qos/Makefile
+++ b/arch/riscv/kernel/qos/Makefile
@@ -1,2 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_RISCV_ISA_SSQOSID) += qos.o
+obj-$(CONFIG_RISCV_ISA_SSQOSID) += qos.o qos_resctrl.o

-- 
2.43.0


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

* [PATCH RFC 12/19] RISC-V: QoS: make CONFIG_RISCV_ISA_SSQOSID select resctrl
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (10 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH RFC 11/19] RISC-V: QoS: add to build when CONFIG_RISCV_ISA_SSQOSID set Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH RFC 13/19] dt-bindings: riscv: add riscv,cbqri bindings Drew Fustini
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

Make CONFIG_RISCV_ISA_SSQOSID select the config options for resctrl:
ARCH_HAS_CPU_RESCTRL, RESCTRL_FS and MISC_FILESYSTEMS.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 arch/riscv/Kconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 35a6238b02c5..8ff6d962b6b2 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -598,6 +598,9 @@ config RISCV_ISA_SVNAPOT
 config RISCV_ISA_SSQOSID
 	bool "Ssqosid extension support for supervisor mode Quality of Service ID"
 	default y
+	select ARCH_HAS_CPU_RESCTRL
+	select RESCTRL_FS
+	select MISC_FILESYSTEMS
 	help
 	  Adds support for the Ssqosid ISA extension (Supervisor-mode
 	  Quality of Service ID).

-- 
2.43.0


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

* [PATCH RFC 13/19] dt-bindings: riscv: add riscv,cbqri bindings
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (11 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH RFC 12/19] RISC-V: QoS: make CONFIG_RISCV_ISA_SSQOSID select resctrl Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH NFU RFC 14/19] resctrl: riscv: add CBQRI cache controller driver Drew Fustini
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

Document properties that can be used in the bindings for controllers
that implement the RISC-V CBQRI specification.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 .../devicetree/bindings/riscv/riscv,cbqri.yaml     | 28 ++++++++++++++++++++++
 MAINTAINERS                                        |  1 +
 2 files changed, 29 insertions(+)

diff --git a/Documentation/devicetree/bindings/riscv/riscv,cbqri.yaml b/Documentation/devicetree/bindings/riscv/riscv,cbqri.yaml
new file mode 100644
index 000000000000..7d0482c31a46
--- /dev/null
+++ b/Documentation/devicetree/bindings/riscv/riscv,cbqri.yaml
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/riscv/riscv,cbqri.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: RISC-V Capacity and Bandwidth Register Interface (CBQRI) properties
+
+description: |
+  Common properties for cache and memory controllers that implement the
+  RISC-V CBQRI specification:
+  https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0
+
+maintainers:
+  - Drew Fustini <fustini@kernel.org>
+
+properties:
+  riscv,cbqri-rcid:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: The maximum number of RCIDs the controller supports
+
+  riscv,cbqri-mcid:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: The maximum number of MCIDs the controller supports
+
+additionalProperties: true
+
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 96ead357a634..2c9151e34d2b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22509,6 +22509,7 @@ RISC-V QOS RESCTRL SUPPORT
 M:	Drew Fustini <fustini@kernel.org>
 L:	linux-riscv@lists.infradead.org
 S:	Supported
+F:	Documentation/devicetree/bindings/riscv/riscv,cbqri.yaml
 F:	arch/riscv/include/asm/qos.h
 F:	arch/riscv/include/asm/resctrl.h
 F:	arch/riscv/kernel/qos/

-- 
2.43.0


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

* [PATCH NFU RFC 14/19] resctrl: riscv: add CBQRI cache controller driver
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (12 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH RFC 13/19] dt-bindings: riscv: add riscv,cbqri bindings Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH NFU RFC 15/19] resctrl: riscv: add CBQRI bandwidth " Drew Fustini
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

[NOT FOR UPSTREAM]

Add example driver for a cache controller that implements CBQRI capacity
allocation.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 drivers/resctrl/riscv/cbqri_cache.c | 106 ++++++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/drivers/resctrl/riscv/cbqri_cache.c b/drivers/resctrl/riscv/cbqri_cache.c
new file mode 100644
index 000000000000..0bee65eefb2d
--- /dev/null
+++ b/drivers/resctrl/riscv/cbqri_cache.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#define pr_fmt(fmt) "cbqri-cache: " fmt
+
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/riscv_qos.h>
+
+static const struct of_device_id cbqri_cache_ids[] = {
+	{ .compatible = "riscv,cbqri-cache" },
+	{ }
+};
+
+static int __init cbqri_cache_init(void)
+{
+	struct cbqri_controller_info *ctrl_info;
+	struct device_node *np;
+	u32 value;
+	int err;
+
+	for_each_matching_node(np, cbqri_cache_ids) {
+		if (!of_device_is_available(np)) {
+			of_node_put(np);
+			continue;
+		}
+
+		ctrl_info = kzalloc(sizeof(*ctrl_info), GFP_KERNEL);
+		if (!ctrl_info)
+			goto err_node_put;
+		ctrl_info->type = CBQRI_CONTROLLER_TYPE_CAPACITY;
+
+		err = of_property_read_u32_index(np, "reg", 1, &value);
+		if (err) {
+			pr_err("Failed to read reg base address (%d)", err);
+			goto err_kfree_ctrl_info;
+		}
+		ctrl_info->addr = value;
+
+		err = of_property_read_u32_index(np, "reg", 3, &value);
+		if (err) {
+			pr_err("Failed to read reg size (%d)", err);
+			goto err_kfree_ctrl_info;
+		}
+		ctrl_info->size = value;
+
+		err = of_property_read_u32(np, "cache-level", &value);
+		if (err) {
+			pr_err("Failed to read cache level (%d)", err);
+			goto err_kfree_ctrl_info;
+		}
+		ctrl_info->cache.cache_level = value;
+
+		err = of_property_read_u32(np, "cache-size", &value);
+		if (err) {
+			pr_err("Failed to read cache size (%d)", err);
+			goto err_kfree_ctrl_info;
+		}
+		ctrl_info->cache.cache_size = value;
+
+		err = of_property_read_u32(np, "riscv,cbqri-rcid", &value);
+		if (err) {
+			pr_err("Failed to read RCID count (%d)", err);
+			goto err_kfree_ctrl_info;
+		}
+		ctrl_info->rcid_count = value;
+
+		err = of_property_read_u32(np, "riscv,cbqri-mcid", &value);
+		if (err) {
+			pr_err("Failed to read MCID count (%d)", err);
+			goto err_kfree_ctrl_info;
+		}
+		ctrl_info->mcid_count = value;
+
+		/*
+		 * For CBQRI, any cpu (technically a hart in RISC-V terms)
+		 * can access the memory-mapped registers of any CBQRI
+		 * controller in the system. Therefore, set the CPU mask
+		 * to 'FF' to allow all 8 cores in the example Qemu SoC
+		 */
+		err = cpumask_parse("FF", &ctrl_info->cache.cpu_mask);
+		if (err) {
+			pr_err("Failed to convert cores mask string to cpumask (%d)", err);
+			goto err_kfree_ctrl_info;
+		}
+
+		of_node_put(np);
+
+		pr_debug("addr=0x%lx max-rcid=%u max-mcid=%u level=%d size=%u",
+			 ctrl_info->addr, ctrl_info->rcid_count, ctrl_info->mcid_count,
+			 ctrl_info->cache.cache_level, ctrl_info->cache.cache_size);
+
+		/* Fill the list shared with RISC-V QoS resctrl */
+		INIT_LIST_HEAD(&ctrl_info->list);
+		list_add_tail(&ctrl_info->list, &cbqri_controllers);
+	}
+
+	return 0;
+
+err_kfree_ctrl_info:
+	kfree(ctrl_info);
+
+err_node_put:
+	of_node_put(np);
+
+	return err;
+}
+device_initcall(cbqri_cache_init);

-- 
2.43.0


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

* [PATCH NFU RFC 15/19] resctrl: riscv: add CBQRI bandwidth controller driver
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (13 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH NFU RFC 14/19] resctrl: riscv: add CBQRI cache controller driver Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH NFU RFC 16/19] resctrl: riscv: build CBQRI drivers Drew Fustini
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

[NOT FOR UPSTREAM]

Add example driver for a CBQRI bandwidth controller.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 drivers/resctrl/riscv/cbqri_bandwidth.c | 79 +++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/drivers/resctrl/riscv/cbqri_bandwidth.c b/drivers/resctrl/riscv/cbqri_bandwidth.c
new file mode 100644
index 000000000000..13649d56b7dc
--- /dev/null
+++ b/drivers/resctrl/riscv/cbqri_bandwidth.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#define pr_fmt(fmt) "cbqri-bandwidth: " fmt
+
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/riscv_qos.h>
+
+static const struct of_device_id cbqri_mem_ctrl_ids[] = {
+	{ .compatible = "riscv,cbqri-bandwidth" },
+	{ }
+};
+
+static int __init cbqri_mem_ctrl_init(void)
+{
+	struct cbqri_controller_info *ctrl_info;
+	struct device_node *np;
+	u32 value;
+	int err;
+
+	for_each_matching_node(np, cbqri_mem_ctrl_ids) {
+		if (!of_device_is_available(np)) {
+			of_node_put(np);
+			continue;
+		}
+
+		ctrl_info = kzalloc(sizeof(*ctrl_info), GFP_KERNEL);
+		if (!ctrl_info)
+			goto err_node_put;
+		ctrl_info->type = CBQRI_CONTROLLER_TYPE_BANDWIDTH;
+
+		err = of_property_read_u32_index(np, "reg", 1, &value);
+		if (err) {
+			pr_err("Failed to read reg base address (%d)", err);
+			goto err_kfree_ctrl_info;
+		}
+		ctrl_info->addr = value;
+
+		err = of_property_read_u32_index(np, "reg", 3, &value);
+		if (err) {
+			pr_err("Failed to read reg size (%d)", err);
+			goto err_kfree_ctrl_info;
+		}
+		ctrl_info->size = value;
+
+		err = of_property_read_u32(np, "riscv,cbqri-rcid", &value);
+		if (err) {
+			pr_err("Failed to read RCID count (%d)", err);
+			goto err_kfree_ctrl_info;
+		}
+		ctrl_info->rcid_count = value;
+
+		err = of_property_read_u32(np, "riscv,cbqri-mcid", &value);
+		if (err) {
+			pr_err("Failed to read MCID count (%d)", err);
+			goto err_kfree_ctrl_info;
+		}
+		ctrl_info->mcid_count = value;
+
+		of_node_put(np);
+
+		pr_debug("addr=0x%lx max-rcid=%u max-mcid=%u", ctrl_info->addr,
+			 ctrl_info->rcid_count, ctrl_info->mcid_count);
+
+		/* Fill the list shared with RISC-V QoS resctrl */
+		INIT_LIST_HEAD(&ctrl_info->list);
+		list_add_tail(&ctrl_info->list, &cbqri_controllers);
+	}
+
+	return 0;
+
+err_kfree_ctrl_info:
+	kfree(ctrl_info);
+
+err_node_put:
+	of_node_put(np);
+
+	return err;
+}
+device_initcall(cbqri_mem_ctrl_init);

-- 
2.43.0


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

* [PATCH NFU RFC 16/19] resctrl: riscv: build CBQRI drivers
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (14 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH NFU RFC 15/19] resctrl: riscv: add CBQRI bandwidth " Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH NFU RFC 17/19] riscv: dts: qemu: add dump from virt machine Drew Fustini
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

[NOT FOR UPSTREAM]

Add RISC-V CBQRI cache and bandwidth controller drivers to the build.

Link: https://github.com/riscv-non-isa/riscv-cbqri/releases/tag/v1.0
Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 drivers/resctrl/Kconfig        |  2 ++
 drivers/resctrl/Makefile       |  2 ++
 drivers/resctrl/riscv/Kconfig  | 25 +++++++++++++++++++++++++
 drivers/resctrl/riscv/Makefile |  4 ++++
 4 files changed, 33 insertions(+)

diff --git a/drivers/resctrl/Kconfig b/drivers/resctrl/Kconfig
index c808e0470394..6c1d909dd20c 100644
--- a/drivers/resctrl/Kconfig
+++ b/drivers/resctrl/Kconfig
@@ -22,3 +22,5 @@ config MPAM_KUNIT_TEST
 	  If unsure, say N.
 
 endif
+
+source "drivers/resctrl/riscv/Kconfig"
diff --git a/drivers/resctrl/Makefile b/drivers/resctrl/Makefile
index 898199dcf80d..48fa4d69d76f 100644
--- a/drivers/resctrl/Makefile
+++ b/drivers/resctrl/Makefile
@@ -2,3 +2,5 @@ obj-$(CONFIG_ARM64_MPAM_DRIVER)			+= mpam.o
 mpam-y						+= mpam_devices.o
 
 ccflags-$(CONFIG_ARM64_MPAM_DRIVER_DEBUG)	+= -DDEBUG
+
+obj-y						+= riscv/
diff --git a/drivers/resctrl/riscv/Kconfig b/drivers/resctrl/riscv/Kconfig
new file mode 100644
index 000000000000..d9a774fb856b
--- /dev/null
+++ b/drivers/resctrl/riscv/Kconfig
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config RESCTRL_RISCV_CBQRI_CACHE
+	bool "RISC-V QoS cache controller (CBQRI)"
+	default y
+	depends on RISCV
+	select RISCV_ISA_SSQOSID
+	help
+	  Support RISC-V platform which implements a QoS capacity
+	  controller according to the RISC-V Capacity and Bandwidth QoS
+	  Register Interface (CBQRI) specification.
+
+	  If you do not care about testing RISC-V CBQRI, then choose 'N'.
+
+config RESCTRL_RISCV_CBQRI_BANDWIDTH
+	bool "RISC-V QoS bandwidth controller (CBQRI)"
+	default y
+	depends on RISCV
+	select RISCV_ISA_SSQOSID
+	help
+	  Support RISC-V platform which implements a QoS bandwidth
+	  controller according to the RISC-V Capacity and Bandwidth QoS
+	  Register Interface (CBQRI) specification.
+
+	  If you do not care about testing RISC-V CBQRI, then choose 'N'.
diff --git a/drivers/resctrl/riscv/Makefile b/drivers/resctrl/riscv/Makefile
new file mode 100644
index 000000000000..e6937a8632d6
--- /dev/null
+++ b/drivers/resctrl/riscv/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_RESCTRL_RISCV_CBQRI_CACHE)      += cbqri_cache.o
+obj-$(CONFIG_RESCTRL_RISCV_CBQRI_BANDWIDTH)  += cbqri_bandwidth.o

-- 
2.43.0


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

* [PATCH NFU RFC 17/19] riscv: dts: qemu: add dump from virt machine
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (15 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH NFU RFC 16/19] resctrl: riscv: build CBQRI drivers Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH NFU RFC 18/19] riscv: dts: qemu: add CBQRI controller nodes Drew Fustini
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

[NOT FOR UPSTREAM]

Dumped dtb from qemu branch based on the v4 riscv-ssqosid-cbqri series.

 $ qemu-system-riscv64 -version
 QEMU emulator version 10.2.50 (v10.2.0-208-g087112467867)
 Copyright (c) 2003-2025 Fabrice Bellard and the QEMU Project developers

 $ qemu-system-riscv64 \
      -M virt \
      -nographic \
      -smp 8 \
      -bios output/images/fw_jump.elf \
      -kernel $HOME/kernel/cbqri-linux/arch/riscv/boot/Image \
      -append "root=/dev/vda ro" \
      -drive file=output/images/rootfs.ext2,format=raw,id=hd0 \
      -device virtio-blk-device,drive=hd0 \
      -machine dumpdtb=qemu.dtb

Link: https://lore.kernel.org/all/20260105-riscv-ssqosid-cbqri-v4-0-9ad7671dde78@kernel.org/
Link: https://github.com/tt-fustini/qemu/tree/b4/riscv-ssqosid-cbqri
Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 arch/riscv/boot/dts/qemu/qemu-virt-cbqri.dts | 399 +++++++++++++++++++++++++++
 1 file changed, 399 insertions(+)

diff --git a/arch/riscv/boot/dts/qemu/qemu-virt-cbqri.dts b/arch/riscv/boot/dts/qemu/qemu-virt-cbqri.dts
new file mode 100644
index 000000000000..4c6257bec42d
--- /dev/null
+++ b/arch/riscv/boot/dts/qemu/qemu-virt-cbqri.dts
@@ -0,0 +1,399 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/dts-v1/;
+
+/ {
+	#address-cells = <0x02>;
+	#size-cells = <0x02>;
+	compatible = "riscv-virtio";
+	model = "riscv-virtio,qemu";
+
+	poweroff {
+		value = <0x5555>;
+		offset = <0x00>;
+		regmap = <0x12>;
+		compatible = "syscon-poweroff";
+	};
+
+	reboot {
+		value = <0x7777>;
+		offset = <0x00>;
+		regmap = <0x12>;
+		compatible = "syscon-reboot";
+	};
+
+	platform-bus@4000000 {
+		interrupt-parent = <0x11>;
+		ranges = <0x00 0x00 0x4000000 0x2000000>;
+		#address-cells = <0x01>;
+		#size-cells = <0x01>;
+		compatible = "qemu,platform\0simple-bus";
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x00 0x80000000 0x00 0x8000000>;
+	};
+
+	cpus {
+		#address-cells = <0x01>;
+		#size-cells = <0x00>;
+		timebase-frequency = <0x989680>;
+
+		cpu@0 {
+			phandle = <0x0f>;
+			device_type = "cpu";
+			reg = <0x00>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,cbop-block-size = <0x40>;
+			riscv,cboz-block-size = <0x40>;
+			riscv,cbom-block-size = <0x40>;
+			riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0h\0zic64b\0zicbom\0zicbop\0zicboz\0ziccamoa\0ziccif\0zicclsm\0ziccrse\0zicntr\0zicsr\0zifencei\0zihintntl\0zihintpause\0zihpm\0zmmul\0za64rs\0zaamo\0zalrsc\0zawrs\0zfa\0zca\0zcd\0zba\0zbb\0zbc\0zbs\0sdtrig\0shcounterenw\0shgatpa\0shtvala\0shvsatpa\0shvstvala\0shvstvecd\0ssccptr\0sscounterenw\0ssqosid\0ssstrict\0sstc\0sstvala\0sstvecd\0ssu64xl\0svadu\0svvptc";
+			riscv,isa-base = "rv64i";
+			riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zmmul_za64rs_zaamo_zalrsc_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sdtrig_shcounterenw_shgatpa_shtvala_shvsatpa_shvstvala_shvstvecd_ssccptr_sscounterenw_ssqosid_ssstrict_sstc_sstvala_sstvecd_ssu64xl_svadu_svvptc";
+			mmu-type = "riscv,sv57";
+
+			interrupt-controller {
+				#interrupt-cells = <0x01>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+				phandle = <0x10>;
+			};
+		};
+
+		cpu@1 {
+			phandle = <0x0d>;
+			device_type = "cpu";
+			reg = <0x01>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,cbop-block-size = <0x40>;
+			riscv,cboz-block-size = <0x40>;
+			riscv,cbom-block-size = <0x40>;
+			riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0h\0zic64b\0zicbom\0zicbop\0zicboz\0ziccamoa\0ziccif\0zicclsm\0ziccrse\0zicntr\0zicsr\0zifencei\0zihintntl\0zihintpause\0zihpm\0zmmul\0za64rs\0zaamo\0zalrsc\0zawrs\0zfa\0zca\0zcd\0zba\0zbb\0zbc\0zbs\0sdtrig\0shcounterenw\0shgatpa\0shtvala\0shvsatpa\0shvstvala\0shvstvecd\0ssccptr\0sscounterenw\0ssqosid\0ssstrict\0sstc\0sstvala\0sstvecd\0ssu64xl\0svadu\0svvptc";
+			riscv,isa-base = "rv64i";
+			riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zmmul_za64rs_zaamo_zalrsc_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sdtrig_shcounterenw_shgatpa_shtvala_shvsatpa_shvstvala_shvstvecd_ssccptr_sscounterenw_ssqosid_ssstrict_sstc_sstvala_sstvecd_ssu64xl_svadu_svvptc";
+			mmu-type = "riscv,sv57";
+
+			interrupt-controller {
+				#interrupt-cells = <0x01>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+				phandle = <0x0e>;
+			};
+		};
+
+		cpu@2 {
+			phandle = <0x0b>;
+			device_type = "cpu";
+			reg = <0x02>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,cbop-block-size = <0x40>;
+			riscv,cboz-block-size = <0x40>;
+			riscv,cbom-block-size = <0x40>;
+			riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0h\0zic64b\0zicbom\0zicbop\0zicboz\0ziccamoa\0ziccif\0zicclsm\0ziccrse\0zicntr\0zicsr\0zifencei\0zihintntl\0zihintpause\0zihpm\0zmmul\0za64rs\0zaamo\0zalrsc\0zawrs\0zfa\0zca\0zcd\0zba\0zbb\0zbc\0zbs\0sdtrig\0shcounterenw\0shgatpa\0shtvala\0shvsatpa\0shvstvala\0shvstvecd\0ssccptr\0sscounterenw\0ssqosid\0ssstrict\0sstc\0sstvala\0sstvecd\0ssu64xl\0svadu\0svvptc";
+			riscv,isa-base = "rv64i";
+			riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zmmul_za64rs_zaamo_zalrsc_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sdtrig_shcounterenw_shgatpa_shtvala_shvsatpa_shvstvala_shvstvecd_ssccptr_sscounterenw_ssqosid_ssstrict_sstc_sstvala_sstvecd_ssu64xl_svadu_svvptc";
+			mmu-type = "riscv,sv57";
+
+			interrupt-controller {
+				#interrupt-cells = <0x01>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+				phandle = <0x0c>;
+			};
+		};
+
+		cpu@3 {
+			phandle = <0x09>;
+			device_type = "cpu";
+			reg = <0x03>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,cbop-block-size = <0x40>;
+			riscv,cboz-block-size = <0x40>;
+			riscv,cbom-block-size = <0x40>;
+			riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0h\0zic64b\0zicbom\0zicbop\0zicboz\0ziccamoa\0ziccif\0zicclsm\0ziccrse\0zicntr\0zicsr\0zifencei\0zihintntl\0zihintpause\0zihpm\0zmmul\0za64rs\0zaamo\0zalrsc\0zawrs\0zfa\0zca\0zcd\0zba\0zbb\0zbc\0zbs\0sdtrig\0shcounterenw\0shgatpa\0shtvala\0shvsatpa\0shvstvala\0shvstvecd\0ssccptr\0sscounterenw\0ssqosid\0ssstrict\0sstc\0sstvala\0sstvecd\0ssu64xl\0svadu\0svvptc";
+			riscv,isa-base = "rv64i";
+			riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zmmul_za64rs_zaamo_zalrsc_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sdtrig_shcounterenw_shgatpa_shtvala_shvsatpa_shvstvala_shvstvecd_ssccptr_sscounterenw_ssqosid_ssstrict_sstc_sstvala_sstvecd_ssu64xl_svadu_svvptc";
+			mmu-type = "riscv,sv57";
+
+			interrupt-controller {
+				#interrupt-cells = <0x01>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+				phandle = <0x0a>;
+			};
+		};
+
+		cpu@4 {
+			phandle = <0x07>;
+			device_type = "cpu";
+			reg = <0x04>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,cbop-block-size = <0x40>;
+			riscv,cboz-block-size = <0x40>;
+			riscv,cbom-block-size = <0x40>;
+			riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0h\0zic64b\0zicbom\0zicbop\0zicboz\0ziccamoa\0ziccif\0zicclsm\0ziccrse\0zicntr\0zicsr\0zifencei\0zihintntl\0zihintpause\0zihpm\0zmmul\0za64rs\0zaamo\0zalrsc\0zawrs\0zfa\0zca\0zcd\0zba\0zbb\0zbc\0zbs\0sdtrig\0shcounterenw\0shgatpa\0shtvala\0shvsatpa\0shvstvala\0shvstvecd\0ssccptr\0sscounterenw\0ssqosid\0ssstrict\0sstc\0sstvala\0sstvecd\0ssu64xl\0svadu\0svvptc";
+			riscv,isa-base = "rv64i";
+			riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zmmul_za64rs_zaamo_zalrsc_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sdtrig_shcounterenw_shgatpa_shtvala_shvsatpa_shvstvala_shvstvecd_ssccptr_sscounterenw_ssqosid_ssstrict_sstc_sstvala_sstvecd_ssu64xl_svadu_svvptc";
+			mmu-type = "riscv,sv57";
+
+			interrupt-controller {
+				#interrupt-cells = <0x01>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+				phandle = <0x08>;
+			};
+		};
+
+		cpu@5 {
+			phandle = <0x05>;
+			device_type = "cpu";
+			reg = <0x05>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,cbop-block-size = <0x40>;
+			riscv,cboz-block-size = <0x40>;
+			riscv,cbom-block-size = <0x40>;
+			riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0h\0zic64b\0zicbom\0zicbop\0zicboz\0ziccamoa\0ziccif\0zicclsm\0ziccrse\0zicntr\0zicsr\0zifencei\0zihintntl\0zihintpause\0zihpm\0zmmul\0za64rs\0zaamo\0zalrsc\0zawrs\0zfa\0zca\0zcd\0zba\0zbb\0zbc\0zbs\0sdtrig\0shcounterenw\0shgatpa\0shtvala\0shvsatpa\0shvstvala\0shvstvecd\0ssccptr\0sscounterenw\0ssqosid\0ssstrict\0sstc\0sstvala\0sstvecd\0ssu64xl\0svadu\0svvptc";
+			riscv,isa-base = "rv64i";
+			riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zmmul_za64rs_zaamo_zalrsc_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sdtrig_shcounterenw_shgatpa_shtvala_shvsatpa_shvstvala_shvstvecd_ssccptr_sscounterenw_ssqosid_ssstrict_sstc_sstvala_sstvecd_ssu64xl_svadu_svvptc";
+			mmu-type = "riscv,sv57";
+
+			interrupt-controller {
+				#interrupt-cells = <0x01>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+				phandle = <0x06>;
+			};
+		};
+
+		cpu@6 {
+			phandle = <0x03>;
+			device_type = "cpu";
+			reg = <0x06>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,cbop-block-size = <0x40>;
+			riscv,cboz-block-size = <0x40>;
+			riscv,cbom-block-size = <0x40>;
+			riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0h\0zic64b\0zicbom\0zicbop\0zicboz\0ziccamoa\0ziccif\0zicclsm\0ziccrse\0zicntr\0zicsr\0zifencei\0zihintntl\0zihintpause\0zihpm\0zmmul\0za64rs\0zaamo\0zalrsc\0zawrs\0zfa\0zca\0zcd\0zba\0zbb\0zbc\0zbs\0sdtrig\0shcounterenw\0shgatpa\0shtvala\0shvsatpa\0shvstvala\0shvstvecd\0ssccptr\0sscounterenw\0ssqosid\0ssstrict\0sstc\0sstvala\0sstvecd\0ssu64xl\0svadu\0svvptc";
+			riscv,isa-base = "rv64i";
+			riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zmmul_za64rs_zaamo_zalrsc_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sdtrig_shcounterenw_shgatpa_shtvala_shvsatpa_shvstvala_shvstvecd_ssccptr_sscounterenw_ssqosid_ssstrict_sstc_sstvala_sstvecd_ssu64xl_svadu_svvptc";
+			mmu-type = "riscv,sv57";
+
+			interrupt-controller {
+				#interrupt-cells = <0x01>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+				phandle = <0x04>;
+			};
+		};
+
+		cpu@7 {
+			phandle = <0x01>;
+			device_type = "cpu";
+			reg = <0x07>;
+			status = "okay";
+			compatible = "riscv";
+			riscv,cbop-block-size = <0x40>;
+			riscv,cboz-block-size = <0x40>;
+			riscv,cbom-block-size = <0x40>;
+			riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0h\0zic64b\0zicbom\0zicbop\0zicboz\0ziccamoa\0ziccif\0zicclsm\0ziccrse\0zicntr\0zicsr\0zifencei\0zihintntl\0zihintpause\0zihpm\0zmmul\0za64rs\0zaamo\0zalrsc\0zawrs\0zfa\0zca\0zcd\0zba\0zbb\0zbc\0zbs\0sdtrig\0shcounterenw\0shgatpa\0shtvala\0shvsatpa\0shvstvala\0shvstvecd\0ssccptr\0sscounterenw\0ssqosid\0ssstrict\0sstc\0sstvala\0sstvecd\0ssu64xl\0svadu\0svvptc";
+			riscv,isa-base = "rv64i";
+			riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zmmul_za64rs_zaamo_zalrsc_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sdtrig_shcounterenw_shgatpa_shtvala_shvsatpa_shvstvala_shvstvecd_ssccptr_sscounterenw_ssqosid_ssstrict_sstc_sstvala_sstvecd_ssu64xl_svadu_svvptc";
+			mmu-type = "riscv,sv57";
+
+			interrupt-controller {
+				#interrupt-cells = <0x01>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+				phandle = <0x02>;
+			};
+		};
+
+		cpu-map {
+
+			cluster0 {
+
+				core0 {
+					cpu = <0x0f>;
+				};
+
+				core1 {
+					cpu = <0x0d>;
+				};
+
+				core2 {
+					cpu = <0x0b>;
+				};
+
+				core3 {
+					cpu = <0x09>;
+				};
+
+				core4 {
+					cpu = <0x07>;
+				};
+
+				core5 {
+					cpu = <0x05>;
+				};
+
+				core6 {
+					cpu = <0x03>;
+				};
+
+				core7 {
+					cpu = <0x01>;
+				};
+			};
+		};
+	};
+
+	pmu {
+		riscv,event-to-mhpmcounters = <0x01 0x01 0x7fff9 0x02 0x02 0x7fffc 0x10019 0x10019 0x7fff8 0x1001b 0x1001b 0x7fff8 0x10021 0x10021 0x7fff8>;
+		compatible = "riscv,pmu";
+	};
+
+	fw-cfg@10100000 {
+		dma-coherent;
+		reg = <0x00 0x10100000 0x00 0x18>;
+		compatible = "qemu,fw-cfg-mmio";
+	};
+
+	flash@20000000 {
+		bank-width = <0x04>;
+		reg = <0x00 0x20000000 0x00 0x2000000 0x00 0x22000000 0x00 0x2000000>;
+		compatible = "cfi-flash";
+	};
+
+	aliases {
+		serial0 = "/soc/serial@10000000";
+	};
+
+	chosen {
+		bootargs = "root=/dev/vda ro loglevel=8";
+		stdout-path = "/soc/serial@10000000";
+		rng-seed = <0x56a2904d 0x281bbaec 0x55c405c1 0x602a34cd 0x3490edca 0x3ed9ed5d 0xa98e5ed6 0xa663e102>;
+	};
+
+	soc {
+		#address-cells = <0x02>;
+		#size-cells = <0x02>;
+		compatible = "simple-bus";
+		ranges;
+
+		rtc@101000 {
+			interrupts = <0x0b>;
+			interrupt-parent = <0x11>;
+			reg = <0x00 0x101000 0x00 0x1000>;
+			compatible = "google,goldfish-rtc";
+		};
+
+		serial@10000000 {
+			interrupts = <0x0a>;
+			interrupt-parent = <0x11>;
+			clock-frequency = "\08@";
+			reg = <0x00 0x10000000 0x00 0x100>;
+			compatible = "ns16550a";
+		};
+
+		test@100000 {
+			phandle = <0x12>;
+			reg = <0x00 0x100000 0x00 0x1000>;
+			compatible = "sifive,test1\0sifive,test0\0syscon";
+		};
+
+		virtio_mmio@10008000 {
+			interrupts = <0x08>;
+			interrupt-parent = <0x11>;
+			reg = <0x00 0x10008000 0x00 0x1000>;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10007000 {
+			interrupts = <0x07>;
+			interrupt-parent = <0x11>;
+			reg = <0x00 0x10007000 0x00 0x1000>;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10006000 {
+			interrupts = <0x06>;
+			interrupt-parent = <0x11>;
+			reg = <0x00 0x10006000 0x00 0x1000>;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10005000 {
+			interrupts = <0x05>;
+			interrupt-parent = <0x11>;
+			reg = <0x00 0x10005000 0x00 0x1000>;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10004000 {
+			interrupts = <0x04>;
+			interrupt-parent = <0x11>;
+			reg = <0x00 0x10004000 0x00 0x1000>;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10003000 {
+			interrupts = <0x03>;
+			interrupt-parent = <0x11>;
+			reg = <0x00 0x10003000 0x00 0x1000>;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10002000 {
+			interrupts = <0x02>;
+			interrupt-parent = <0x11>;
+			reg = <0x00 0x10002000 0x00 0x1000>;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10001000 {
+			interrupts = <0x01>;
+			interrupt-parent = <0x11>;
+			reg = <0x00 0x10001000 0x00 0x1000>;
+			compatible = "virtio,mmio";
+		};
+
+		plic@c000000 {
+			phandle = <0x11>;
+			riscv,ndev = <0x5f>;
+			reg = <0x00 0xc000000 0x00 0x600000>;
+			interrupts-extended = <0x10 0x0b 0x10 0x09 0x0e 0x0b 0x0e 0x09 0x0c 0x0b 0x0c 0x09 0x0a 0x0b 0x0a 0x09 0x08 0x0b 0x08 0x09 0x06 0x0b 0x06 0x09 0x04 0x0b 0x04 0x09 0x02 0x0b 0x02 0x09>;
+			interrupt-controller;
+			compatible = "sifive,plic-1.0.0\0riscv,plic0";
+			#address-cells = <0x00>;
+			#interrupt-cells = <0x01>;
+		};
+
+		clint@2000000 {
+			interrupts-extended = <0x10 0x03 0x10 0x07 0x0e 0x03 0x0e 0x07 0x0c 0x03 0x0c 0x07 0x0a 0x03 0x0a 0x07 0x08 0x03 0x08 0x07 0x06 0x03 0x06 0x07 0x04 0x03 0x04 0x07 0x02 0x03 0x02 0x07>;
+			reg = <0x00 0x2000000 0x00 0x10000>;
+			compatible = "sifive,clint0\0riscv,clint0";
+		};
+
+		pci@30000000 {
+			interrupt-map-mask = <0x1800 0x00 0x00 0x07>;
+			interrupt-map = <0x00 0x00 0x00 0x01 0x11 0x20 0x00 0x00 0x00 0x02 0x11 0x21 0x00 0x00 0x00 0x03 0x11 0x22 0x00 0x00 0x00 0x04 0x11 0x23 0x800 0x00 0x00 0x01 0x11 0x21 0x800 0x00 0x00 0x02 0x11 0x22 0x800 0x00 0x00 0x03 0x11 0x23 0x800 0x00 0x00 0x04 0x11 0x20 0x1000 0x00 0x00 0x01 0x11 0x22 0x1000 0x00 0x00 0x02 0x11 0x23 0x1000 0x00 0x00 0x03 0x11 0x20 0x1000 0x00 0x00 0x04 0x11 0x21 0x1800 0x00 0x00 0x01 0x11 0x23 0x1800 0x00 0x00 0x02 0x11 0x20 0x1800 0x00 0x00 0x03 0x11 0x21 0x1800 0x00 0x00 0x04 0x11 0x22>;
+			ranges = <0x1000000 0x00 0x00 0x00 0x3000000 0x00 0x10000 0x2000000 0x00 0x40000000 0x00 0x40000000 0x00 0x40000000 0x3000000 0x04 0x00 0x04 0x00 0x04 0x00>;
+			reg = <0x00 0x30000000 0x00 0x10000000>;
+			dma-coherent;
+			bus-range = <0x00 0xff>;
+			linux,pci-domain = <0x00>;
+			device_type = "pci";
+			compatible = "pci-host-ecam-generic";
+			#size-cells = <0x02>;
+			#interrupt-cells = <0x01>;
+			#address-cells = <0x03>;
+		};
+	};
+};

-- 
2.43.0


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

* [PATCH NFU RFC 18/19] riscv: dts: qemu: add CBQRI controller nodes
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (16 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH NFU RFC 17/19] riscv: dts: qemu: add dump from virt machine Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-20  4:14 ` [PATCH NFU RFC 19/19] riscv: dts: build qemu dtb for CONFIG_ARCH_VIRT Drew Fustini
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

[NOT FOR UPSTREAM]

Add nodes to for CBQRI-capable cache and bandwidth controllers.

Link: https://github.com/tt-fustini/qemu/tree/b4/riscv-ssqosid-cbqri
Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 arch/riscv/boot/dts/qemu/qemu-virt-cbqri.dts | 59 ++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/arch/riscv/boot/dts/qemu/qemu-virt-cbqri.dts b/arch/riscv/boot/dts/qemu/qemu-virt-cbqri.dts
index 4c6257bec42d..9f65de65f758 100644
--- a/arch/riscv/boot/dts/qemu/qemu-virt-cbqri.dts
+++ b/arch/riscv/boot/dts/qemu/qemu-virt-cbqri.dts
@@ -395,5 +395,64 @@ pci@30000000 {
 			#interrupt-cells = <0x01>;
 			#address-cells = <0x03>;
 		};
+
+		cluster0_l2: controller@4820000 {
+			compatible = "riscv,cbqri-cache";
+			reg = <0x0 0x4820000 0x0 0x1000>; /* 4KB at 0x04820000 */
+			cache-unified;
+			cache-line-size = <64>;
+			cache-level = <2>;
+			cache-sets = <1000>;
+			cache-size = <768000>; /* 750 KiB */
+			next-level-cache = <&shared_llc>;
+			riscv,cbqri-rcid = <64>;
+			riscv,cbqri-mcid = <256>;
+		};
+
+		cluster1_l2: controller@4821000 {
+			compatible = "riscv,cbqri-cache";
+			reg = <0x0 0x4821000 0x0 0x1000>; /* 4KB at 0x04821000 */
+			cache-unified;
+			cache-line-size = <64>;
+			cache-level = <2>;
+			cache-sets = <1000>;
+			cache-size = <768000>; /* 750 KiB */
+			next-level-cache = <&shared_llc>;
+			riscv,cbqri-rcid = <64>;
+			riscv,cbqri-mcid = <256>;
+		};
+
+		shared_llc: controller@482b000 {
+			compatible = "riscv,cbqri-cache";
+			reg = <0x0 0x482b000 0x0 0x1000>; /* 4KB at 0x0482B000 */
+			cache-unified;
+			cache-line-size = <64>;
+			cache-level = <3>;
+			cache-sets = <4096>;
+			cache-size = <3145728>; /* 3 MiB */
+			riscv,cbqri-rcid = <64>;
+			riscv,cbqri-mcid = <256>;
+		};
+
+		mem0: controller@4828000 {
+			compatible = "riscv,cbqri-bandwidth";
+			reg = <0x0 0x4828000 0x0 0x1000>; /* 4KB at 0x04828000 */
+			riscv,cbqri-rcid = <64>;
+			riscv,cbqri-mcid = <256>;
+		};
+
+		mem1: controller@4829000 {
+			compatible = "riscv,cbqri-bandwidth";
+			reg = <0x0 0x4829000 0x0 0x1000>; /* 4KB at 0x04829000 */
+			riscv,cbqri-rcid = <64>;
+			riscv,cbqri-mcid = <256>;
+		};
+
+		mem2: controller@482a000 {
+			compatible = "riscv,cbqri-bandwidth";
+			reg = <0x0 0x482a000 0x0 0x1000>; /* 4KB at 0x0482A000 */
+			riscv,cbqri-rcid = <64>;
+			riscv,cbqri-mcid = <256>;
+		};
 	};
 };

-- 
2.43.0


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

* [PATCH NFU RFC 19/19] riscv: dts: build qemu dtb for CONFIG_ARCH_VIRT
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (17 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH NFU RFC 18/19] riscv: dts: qemu: add CBQRI controller nodes Drew Fustini
@ 2026-01-20  4:14 ` Drew Fustini
  2026-01-22 22:31 ` [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Reinette Chatre
  2026-01-26 13:14 ` [External] " yunhui cui
  20 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-20  4:14 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, Drew Fustini, devicetree, linux-kernel, linux-riscv,
	x86

[NOT FOR UPSTREAM]

Build DTB based on Qemu generated DTS when CONFIG_ARCH_VIRT is enabled.
The resulting dtb will be consumed by qemu-system-riscv64.

Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 arch/riscv/boot/dts/Makefile      | 1 +
 arch/riscv/boot/dts/qemu/Makefile | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile
index 69d8751fb17c..edd25cf000cc 100644
--- a/arch/riscv/boot/dts/Makefile
+++ b/arch/riscv/boot/dts/Makefile
@@ -5,6 +5,7 @@ subdir-y += anlogic
 subdir-y += canaan
 subdir-y += eswin
 subdir-y += microchip
+subdir-y += qemu
 subdir-y += renesas
 subdir-y += sifive
 subdir-y += sophgo
diff --git a/arch/riscv/boot/dts/qemu/Makefile b/arch/riscv/boot/dts/qemu/Makefile
new file mode 100644
index 000000000000..a6b06ef1a75a
--- /dev/null
+++ b/arch/riscv/boot/dts/qemu/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_VIRT) += qemu-virt-cbqri.dtb
+obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))

-- 
2.43.0


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

* Re: [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (18 preceding siblings ...)
  2026-01-20  4:14 ` [PATCH NFU RFC 19/19] riscv: dts: build qemu dtb for CONFIG_ARCH_VIRT Drew Fustini
@ 2026-01-22 22:31 ` Reinette Chatre
  2026-01-24 18:00   ` Drew Fustini
  2026-01-26 13:14 ` [External] " yunhui cui
  20 siblings, 1 reply; 29+ messages in thread
From: Reinette Chatre @ 2026-01-22 22:31 UTC (permalink / raw)
  To: Drew Fustini, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Radim Krčmář, Samuel Holland,
	Adrien Ricciardi, Nicolas Pitre, Kornel Dulęba, Atish Patra,
	Atish Kumar Patra, Vasudevan Srinivasan, Ved Shanbhogue,
	yunhui cui, Chen Pei, Liu Zhiwei, Weiwei Li, guo.wenjia23,
	liu.qingtao2, Conor Dooley, Krzysztof Kozlowski, Rob Herring,
	Tony Luck, Babu Moger, Peter Newman, Fenghua Yu, James Morse,
	Ben Horgan, Dave Martin, devicetree, linux-kernel, linux-riscv,
	x86
  Cc: Conor Dooley

Hi Drew,

On 1/19/26 8:14 PM, Drew Fustini wrote:
>  - No MBM (bandwidth monitoring)
>    - MBA schema works ok for the CBQRI-enabled memory controllers, but
>      resctrl does not currently have solution for representing MBM for
>      bandwidth resources that are not associated with a L3 cache.
>    - For the old CBQRI proof-of-concept RFC, two separate domains were
>      created for each memory controller: one for MB (allocation) and one
>      for MBM (monitoring).
>    - The monitoring domains had to pretend that these memory controllers
>      were L3 caches which is not the case. I have removed this as it was
>      too complicated and not the right solution.
>    - Fenghua Yu talked about a similar problem last month at LPC in the
>      resctrl BoF during the "MBA/MBM on CPU-less Memory Node" topic:
>      https://lpc.events/event/19/contributions/2093/
>    - I hope to work with resctrl developers on finding a solution.

Specific to this open, could you please consider [1] that proposes a way for
resctrl to handle allocation and monitoring of resources at different scope?

Reinette

[1] https://lore.kernel.org/lkml/fb1e2686-237b-4536-acd6-15159abafcba@intel.com/



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

* Re: [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface
  2026-01-22 22:31 ` [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Reinette Chatre
@ 2026-01-24 18:00   ` Drew Fustini
  0 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-24 18:00 UTC (permalink / raw)
  To: Reinette Chatre
  Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, yunhui cui, Chen Pei,
	Liu Zhiwei, Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Tony Luck, Babu Moger,
	Peter Newman, Fenghua Yu, James Morse, Ben Horgan, Dave Martin,
	devicetree, linux-kernel, linux-riscv, x86, Conor Dooley

On Thu, Jan 22, 2026 at 02:31:06PM -0800, Reinette Chatre wrote:
> Hi Drew,
> 
> On 1/19/26 8:14 PM, Drew Fustini wrote:
> >  - No MBM (bandwidth monitoring)
> >    - MBA schema works ok for the CBQRI-enabled memory controllers, but
> >      resctrl does not currently have solution for representing MBM for
> >      bandwidth resources that are not associated with a L3 cache.
> >    - For the old CBQRI proof-of-concept RFC, two separate domains were
> >      created for each memory controller: one for MB (allocation) and one
> >      for MBM (monitoring).
> >    - The monitoring domains had to pretend that these memory controllers
> >      were L3 caches which is not the case. I have removed this as it was
> >      too complicated and not the right solution.
> >    - Fenghua Yu talked about a similar problem last month at LPC in the
> >      resctrl BoF during the "MBA/MBM on CPU-less Memory Node" topic:
> >      https://lpc.events/event/19/contributions/2093/
> >    - I hope to work with resctrl developers on finding a solution.
> 
> Specific to this open, could you please consider [1] that proposes a way for
> resctrl to handle allocation and monitoring of resources at different scope?

Thank you for pointing that out. I think that the different scope for
bandwidth monitoring would fit CBQRI well. I will reply in that other
thread.

-Drew

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

* Re: [External] [PATCH RFC 08/19] RISC-V: QoS: add resctrl interface for CBQRI controllers
  2026-01-20  4:14 ` [PATCH RFC 08/19] RISC-V: QoS: add resctrl interface for CBQRI controllers Drew Fustini
@ 2026-01-26 13:01   ` yunhui cui
  2026-01-26 21:02     ` Drew Fustini
  2026-03-26 11:05   ` guo.wenjia23
  1 sibling, 1 reply; 29+ messages in thread
From: yunhui cui @ 2026-01-26 13:01 UTC (permalink / raw)
  To: Drew Fustini
  Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, Chen Pei, Liu Zhiwei,
	Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, devicetree, linux-kernel, linux-riscv, x86

Hi Drew,

On Tue, Jan 20, 2026 at 12:15 PM Drew Fustini <fustini@kernel.org> wrote:
>
> Add interface for CBQRI controller drivers to make use of the resctrl
> filesystem.
>
> Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
> Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
> Signed-off-by: Drew Fustini <fustini@kernel.org>
> ---
>  arch/riscv/kernel/qos/qos_resctrl.c | 1191 +++++++++++++++++++++++++++++++++++
>  1 file changed, 1191 insertions(+)
>
> diff --git a/arch/riscv/kernel/qos/qos_resctrl.c b/arch/riscv/kernel/qos/qos_resctrl.c
> new file mode 100644
> index 000000000000..5e3a65342e9b
> --- /dev/null
> +++ b/arch/riscv/kernel/qos/qos_resctrl.c
> @@ -0,0 +1,1191 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +#define pr_fmt(fmt) "qos: resctrl: " fmt
> +
> +#include <linux/slab.h>
> +#include <linux/err.h>
> +#include <linux/riscv_qos.h>
> +#include <linux/resctrl.h>
> +#include <linux/types.h>
> +#include <asm/csr.h>
> +#include <asm/qos.h>
> +#include "internal.h"
> +
> +#define MAX_CONTROLLERS 6
> +static struct cbqri_controller controllers[MAX_CONTROLLERS];
> +static struct cbqri_resctrl_res cbqri_resctrl_resources[RDT_NUM_RESOURCES];
> +
> +static bool exposed_alloc_capable;
> +static bool exposed_mon_capable;
> +/* CDP (code data prioritization) on x86 is AT (access type) on RISC-V */
> +static bool exposed_cdp_l2_capable;
> +static bool exposed_cdp_l3_capable;
> +static bool is_cdp_l2_enabled;
> +static bool is_cdp_l3_enabled;
> +
> +/* used by resctrl_arch_system_num_rmid_idx() */
> +static u32 max_rmid;
> +
> +LIST_HEAD(cbqri_controllers);
> +
> +static int cbqri_wait_busy_flag(struct cbqri_controller *ctrl, int reg_offset);
> +
> +bool resctrl_arch_alloc_capable(void)
> +{
> +       return exposed_alloc_capable;
> +}
> +
> +bool resctrl_arch_mon_capable(void)
> +{
> +       return exposed_mon_capable;
> +}
> +
> +bool resctrl_arch_is_llc_occupancy_enabled(void)
> +{
> +       return true;
> +}
> +
> +bool resctrl_arch_is_mbm_local_enabled(void)
> +{
> +       return false;
> +}
> +
> +bool resctrl_arch_is_mbm_total_enabled(void)
> +{
> +       return false;
> +}
> +
> +bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level rid)
> +{
> +       switch (rid) {
> +       case RDT_RESOURCE_L2:
> +               return is_cdp_l2_enabled;
> +
> +       case RDT_RESOURCE_L3:
> +               return is_cdp_l3_enabled;
> +
> +       default:
> +               return false;
> +       }
> +}
> +
> +int resctrl_arch_set_cdp_enabled(enum resctrl_res_level rid, bool enable)
> +{
> +       switch (rid) {
> +       case RDT_RESOURCE_L2:
> +               if (!exposed_cdp_l2_capable)
> +                       return -ENODEV;
> +               is_cdp_l2_enabled = enable;
> +               break;
> +
> +       case RDT_RESOURCE_L3:
> +               if (!exposed_cdp_l3_capable)
> +                       return -ENODEV;
> +               is_cdp_l3_enabled = enable;
> +               break;
> +
> +       default:
> +               return -ENODEV;
> +       }
> +
> +       return 0;
> +}
> +
> +struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l)
> +{
> +       if (l >= RDT_NUM_RESOURCES)
> +               return NULL;
> +
> +       return &cbqri_resctrl_resources[l].resctrl_res;
> +}
> +
> +struct rdt_domain_hdr *resctrl_arch_find_domain(struct list_head *domain_list, int id)
> +{
> +       struct rdt_domain_hdr *hdr;
> +
> +       lockdep_assert_cpus_held();
> +
> +       list_for_each_entry(hdr, domain_list, list) {
> +               if (hdr->id == id)
> +                       return hdr;
> +       }
> +
> +       return NULL;
> +}
> +
> +bool resctrl_arch_is_evt_configurable(enum resctrl_event_id evt)
> +{
> +       return false;
> +}
> +
> +void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r,
> +                                enum resctrl_event_id evtid)
> +{
> +       /* RISC-V can always read an rmid, nothing needs allocating */
> +       return NULL;
> +}
> +
> +void resctrl_arch_mon_ctx_free(struct rdt_resource *r,
> +                              enum resctrl_event_id evtid, void *arch_mon_ctx)
> +{
> +       /* not implemented for the RISC-V resctrl interface */
> +}
> +
> +void resctrl_arch_reset_resources(void)
> +{
> +       /* not implemented for the RISC-V resctrl implementation */
> +}
> +
> +void resctrl_arch_config_cntr(struct rdt_resource *r, struct rdt_mon_domain *d,
> +                             enum resctrl_event_id evtid, u32 rmid, u32 closid,
> +                             u32 cntr_id, bool assign)
> +{
> +       /* not implemented for the RISC-V resctrl implementation */
> +}
> +
> +int resctrl_arch_cntr_read(struct rdt_resource *r, struct rdt_mon_domain *d,
> +                          u32 unused, u32 rmid, int cntr_id,
> +                          enum resctrl_event_id eventid, u64 *val)
> +{
> +       /* not implemented for the RISC-V resctrl implementation */
> +       return 0;
> +}
> +
> +bool resctrl_arch_mbm_cntr_assign_enabled(struct rdt_resource *r)
> +{
> +       /* not implemented for the RISC-V resctrl implementation */
> +       return false;
> +}
> +
> +int resctrl_arch_mbm_cntr_assign_set(struct rdt_resource *r, bool enable)
> +{
> +       /* not implemented for the RISC-V resctrl implementation */
> +       return 0;
> +}
> +
> +void resctrl_arch_reset_cntr(struct rdt_resource *r, struct rdt_mon_domain *d,
> +                            u32 unused, u32 rmid, int cntr_id,
> +                            enum resctrl_event_id eventid)
> +{
> +       /* not implemented for the RISC-V resctrl implementation */
> +}
> +
> +bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r)
> +{
> +       /* not implemented for the RISC-V resctrl implementation */
> +       return false;
> +}
> +
> +int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable)
> +{
> +       /* not implemented for the RISC-V resctrl implementation */
> +       return 0;
> +}
> +
> +/*
> + * Note about terminology between x86 (Intel RDT/AMD QoS) and RISC-V:
> + *   CLOSID on x86 is RCID on RISC-V
> + *     RMID on x86 is MCID on RISC-V
> + */
> +u32 resctrl_arch_get_num_closid(struct rdt_resource *res)
> +{
> +       struct cbqri_resctrl_res *hw_res;
> +
> +       hw_res = container_of(res, struct cbqri_resctrl_res, resctrl_res);
> +
> +       return hw_res->max_rcid;
> +}
> +
> +u32 resctrl_arch_system_num_rmid_idx(void)
> +{
> +       return max_rmid;
> +}
> +
> +u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid)
> +{
> +       return rmid;
> +}
> +
> +void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid)
> +{
> +       *closid = ((u32)~0); /* refer to X86_RESCTRL_BAD_CLOSID */
> +       *rmid = idx;
> +}
> +
> +/* RISC-V resctrl interface does not maintain a default srmcfg value for a given CPU */
> +void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid) { }
> +
> +void resctrl_arch_sched_in(struct task_struct *tsk)
> +{
> +       __switch_to_srmcfg(tsk);
> +}
> +
> +void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid)
> +{
> +       u32 srmcfg;
> +
> +       WARN_ON_ONCE((closid & SRMCFG_RCID_MASK) != closid);
> +       WARN_ON_ONCE((rmid & SRMCFG_MCID_MASK) != rmid);
> +
> +       srmcfg = rmid << SRMCFG_MCID_SHIFT;
> +       srmcfg |= closid;
> +       WRITE_ONCE(tsk->thread.srmcfg, srmcfg);
> +}
> +
> +void resctrl_arch_sync_cpu_closid_rmid(void *info)
> +{
> +       struct resctrl_cpu_defaults *r = info;
> +
> +       lockdep_assert_preemption_disabled();
> +
> +       if (r) {
> +               resctrl_arch_set_cpu_default_closid_rmid(smp_processor_id(),
> +                                                        r->closid, r->rmid);
> +       }
> +
> +       resctrl_arch_sched_in(current);
> +}
> +
> +bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid)
> +{
> +       u32 srmcfg;
> +       bool match;
> +
> +       srmcfg = READ_ONCE(tsk->thread.srmcfg);
> +       match = (srmcfg & SRMCFG_RCID_MASK) == closid;
> +       return match;
> +}
> +
> +bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid)
> +{
> +       u32 tsk_rmid;
> +
> +       tsk_rmid = READ_ONCE(tsk->thread.srmcfg);
> +       tsk_rmid >>= SRMCFG_MCID_SHIFT;
> +       tsk_rmid &= SRMCFG_MCID_MASK;
> +
> +       return tsk_rmid == rmid;
> +}
> +
> +int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_mon_domain *d,
> +                          u32 closid, u32 rmid, enum resctrl_event_id eventid,
> +                          u64 *val, void *arch_mon_ctx)
> +{
> +       /*
> +        * The current Qemu implementation of CBQRI capacity and bandwidth
> +        * controllers do not emulate the utilization of resources over
> +        * time. Therefore, Qemu currently sets the invalid bit in
> +        * cc_mon_ctr_val and bc_mon_ctr_val, and there is no meaningful
> +        * value other than 0 to return for reading an RMID (e.g. MCID in
> +        * CBQRI terminology)
> +        */
> +
> +       return 0;
> +}
> +
> +void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_mon_domain *d,
> +                            u32 closid, u32 rmid, enum resctrl_event_id eventid)
> +{
> +       /* not implemented for the RISC-V resctrl interface */
> +}
> +
> +void resctrl_arch_mon_event_config_read(void *info)
> +{
> +       /* not implemented for the RISC-V resctrl interface */
> +}
> +
> +void resctrl_arch_mon_event_config_write(void *info)
> +{
> +       /* not implemented for the RISC-V resctrl interface */
> +}
> +
> +void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_mon_domain *d)
> +{
> +       /* not implemented for the RISC-V resctrl implementation */
> +}
> +
> +void resctrl_arch_reset_all_ctrls(struct rdt_resource *r)
> +{
> +       /* not implemented for the RISC-V resctrl implementation */
> +}
> +
> +/* Set capacity block mask (cc_block_mask) */
> +static void cbqri_set_cbm(struct cbqri_controller *ctrl, u64 cbm)
> +{
> +               int reg_offset;
> +               u64 reg;
> +
> +               reg_offset = CBQRI_CC_BLOCK_MASK_OFF;
> +               reg = ioread64(ctrl->base + reg_offset);
> +
> +               reg = cbm;
> +               iowrite64(reg, ctrl->base + reg_offset);
> +}
> +

too much indentation ?

> +/* Set the Rbwb (reserved bandwidth blocks) field in bc_bw_alloc */
> +static void cbqri_set_rbwb(struct cbqri_controller *ctrl, u64 rbwb)
> +{
> +               int reg_offset;
> +               u64 reg;
> +
> +               reg_offset = CBQRI_BC_BW_ALLOC_OFF;
> +               reg = ioread64(ctrl->base + reg_offset);
> +               reg &= ~CBQRI_CONTROL_REGISTERS_RBWB_MASK;
> +               rbwb &= CBQRI_CONTROL_REGISTERS_RBWB_MASK;
> +               reg |= rbwb;
> +               iowrite64(reg, ctrl->base + reg_offset);
> +}
> +
> +/* Get the Rbwb (reserved bandwidth blocks) field in bc_bw_alloc */
> +static u64 cbqri_get_rbwb(struct cbqri_controller *ctrl)
> +{
> +               int reg_offset;
> +               u64 reg;
> +
> +               reg_offset = CBQRI_BC_BW_ALLOC_OFF;
> +               reg = ioread64(ctrl->base + reg_offset);
> +               reg &= CBQRI_CONTROL_REGISTERS_RBWB_MASK;
> +               return reg;
> +}
> +
> +static int cbqri_wait_busy_flag(struct cbqri_controller *ctrl, int reg_offset)
> +{
> +       unsigned long timeout = jiffies + (HZ / 10); /* Timeout after 100ms */

hung task ?


> +       int busy;
> +       u64 reg;
> +
> +       while (time_before(jiffies, timeout)) {
> +               reg = ioread64(ctrl->base + reg_offset);
> +               busy = (reg >> CBQRI_CONTROL_REGISTERS_BUSY_SHIFT) &
> +                       CBQRI_CONTROL_REGISTERS_BUSY_MASK;
> +               if (!busy)
> +                       return 0;
> +       }
> +
> +       pr_warn("%s(): busy timeout", __func__);
> +       return -EIO;
> +}
> +
> +/* Perform capacity allocation control operation on capacity controller */
> +static int cbqri_cc_alloc_op(struct cbqri_controller *ctrl, int operation, int rcid,
> +                            enum resctrl_conf_type type)
> +{
> +       int reg_offset = CBQRI_CC_ALLOC_CTL_OFF;
> +       int status;
> +       u64 reg;
> +
> +       reg = ioread64(ctrl->base + reg_offset);
> +       reg &= ~(CBQRI_CONTROL_REGISTERS_OP_MASK << CBQRI_CONTROL_REGISTERS_OP_SHIFT);
> +       reg |= (operation & CBQRI_CONTROL_REGISTERS_OP_MASK) <<
> +               CBQRI_CONTROL_REGISTERS_OP_SHIFT;
> +       reg &= ~(CBQRI_CONTROL_REGISTERS_RCID_MASK <<
> +                CBQRI_CONTROL_REGISTERS_RCID_SHIFT);
> +       reg |= (rcid & CBQRI_CONTROL_REGISTERS_RCID_MASK) <<
> +               CBQRI_CONTROL_REGISTERS_RCID_SHIFT;
> +
> +       /* CBQRI capacity AT is only supported on L2 and L3 caches for now */
> +       if (ctrl->ctrl_info->type == CBQRI_CONTROLLER_TYPE_CAPACITY &&
> +           ((ctrl->ctrl_info->cache.cache_level == 2 && is_cdp_l2_enabled) ||
> +           (ctrl->ctrl_info->cache.cache_level == 3 && is_cdp_l3_enabled))) {
> +               reg &= ~(CBQRI_CONTROL_REGISTERS_AT_MASK <<
> +                        CBQRI_CONTROL_REGISTERS_AT_SHIFT);
> +               switch (type) {
> +               case CDP_CODE:
> +                       reg |= (CBQRI_CONTROL_REGISTERS_AT_CODE &
> +                               CBQRI_CONTROL_REGISTERS_AT_MASK) <<
> +                               CBQRI_CONTROL_REGISTERS_AT_SHIFT;
> +                       break;
> +               case CDP_DATA:
> +               default:
> +                       reg |= (CBQRI_CONTROL_REGISTERS_AT_DATA &
> +                               CBQRI_CONTROL_REGISTERS_AT_MASK) <<
> +                               CBQRI_CONTROL_REGISTERS_AT_SHIFT;
> +                       break;
> +               }
> +       }
> +
> +       iowrite64(reg, ctrl->base + reg_offset);
> +
> +       if (cbqri_wait_busy_flag(ctrl, reg_offset) < 0) {
> +               pr_err("%s(): BUSY timeout when executing the operation", __func__);
> +               return -EIO;
> +       }
> +
> +       reg = ioread64(ctrl->base + reg_offset);
> +       status = (reg >> CBQRI_CONTROL_REGISTERS_STATUS_SHIFT) &
> +                 CBQRI_CONTROL_REGISTERS_STATUS_MASK;
> +       if (status != 1) {
> +               pr_err("%s(): operation %d failed: status=%d", __func__, operation, status);
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +static int cbqri_apply_cache_config(struct cbqri_resctrl_dom *hw_dom, u32 closid,
> +                                   enum resctrl_conf_type type, struct cbqri_config *cfg)
> +{
> +       struct cbqri_controller *ctrl = hw_dom->hw_ctrl;
> +       int reg_offset;
> +       int err = 0;
> +       u64 reg;
> +
> +       if (cfg->cbm != hw_dom->ctrl_val[closid]) {
> +               /* Store the new cbm in the ctrl_val array for this closid in this domain */
> +               hw_dom->ctrl_val[closid] = cfg->cbm;
> +
> +               /* Set capacity block mask (cc_block_mask) */
> +               cbqri_set_cbm(ctrl, cfg->cbm);
> +
> +               /* Capacity config limit operation */
> +               err = cbqri_cc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_CONFIG_LIMIT, closid, type);
> +               if (err < 0) {
> +                       pr_err("%s(): operation failed: err = %d", __func__, err);
> +                       return err;
> +               }
> +
> +               /* Clear cc_block_mask before read limit to verify op works*/
> +               cbqri_set_cbm(ctrl, 0);
> +
> +               /* Performa capacity read limit operation to verify blockmask */
> +               err = cbqri_cc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, closid, type);
> +               if (err < 0) {
> +                       pr_err("%s(): operation failed: err = %d", __func__, err);
> +                       return err;
> +               }
> +
> +               /* Read capacity blockmask to verify it matches the requested config */
> +               reg_offset = CBQRI_CC_BLOCK_MASK_OFF;
> +               reg = ioread64(ctrl->base + reg_offset);
> +               if (reg != cfg->cbm) {
> +                       pr_warn("%s(): failed to verify allocation (reg:%llx != cbm:%llx)",
> +                               __func__, reg, cfg->cbm);
> +                       return -EIO;
> +               }
> +       }
> +
> +       return err;
> +}
> +
> +/* Perform bandwidth allocation control operation on bandwidth controller */
> +static int cbqri_bc_alloc_op(struct cbqri_controller *ctrl, int operation, int rcid)
> +{
> +       int reg_offset = CBQRI_BC_ALLOC_CTL_OFF;
> +       int status;
> +       u64 reg;
> +
> +       reg = ioread64(ctrl->base + reg_offset);
> +       reg &= ~(CBQRI_CONTROL_REGISTERS_OP_MASK << CBQRI_CONTROL_REGISTERS_OP_SHIFT);
> +       reg |=  (operation & CBQRI_CONTROL_REGISTERS_OP_MASK) <<
> +                CBQRI_CONTROL_REGISTERS_OP_SHIFT;
> +       reg &= ~(CBQRI_CONTROL_REGISTERS_RCID_MASK << CBQRI_CONTROL_REGISTERS_RCID_SHIFT);
> +       reg |=  (rcid & CBQRI_CONTROL_REGISTERS_RCID_MASK) <<
> +                CBQRI_CONTROL_REGISTERS_RCID_SHIFT;
> +       iowrite64(reg, ctrl->base + reg_offset);
> +
> +       if (cbqri_wait_busy_flag(ctrl, reg_offset) < 0) {
> +               pr_err("%s(): BUSY timeout when executing the operation", __func__);
> +               return -EIO;
> +       }
> +
> +       reg = ioread64(ctrl->base + reg_offset);
> +       status = (reg >> CBQRI_CONTROL_REGISTERS_STATUS_SHIFT) &
> +                 CBQRI_CONTROL_REGISTERS_STATUS_MASK;
> +       if (status != 1) {
> +               pr_err("%s(): operation %d failed with status = %d",
> +                      __func__, operation, status);
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +static int cbqri_apply_bw_config(struct cbqri_resctrl_dom *hw_dom, u32 closid,
> +                                enum resctrl_conf_type type, struct cbqri_config *cfg)
> +{
> +       struct cbqri_controller *ctrl = hw_dom->hw_ctrl;
> +       int ret = 0;
> +       u64 reg;
> +
> +       if (cfg->rbwb != hw_dom->ctrl_val[closid]) {
> +               /* Store the new rbwb in the ctrl_val array for this closid in this domain */
> +               hw_dom->ctrl_val[closid] = cfg->rbwb;
> +
> +               /* Set reserved bandwidth blocks */
> +               cbqri_set_rbwb(ctrl, cfg->rbwb);
> +
> +               /* Bandwidth config limit operation */
> +               ret = cbqri_bc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_CONFIG_LIMIT, closid);
> +               if (ret < 0) {
> +                       pr_err("%s(): operation failed: ret = %d", __func__, ret);
> +                       return ret;
> +               }
> +
> +               /* Clear rbwb before read limit to verify op works*/
> +               cbqri_set_rbwb(ctrl, 0);
> +
> +               /* Bandwidth allocation read limit operation to verify */
> +               ret = cbqri_bc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, closid);
> +               if (ret < 0) {
> +                       pr_err("%s(): operation failed: ret = %d", __func__, ret);
> +                       return ret;
> +               }
> +
> +               /* Read bandwidth allocation to verify it matches the requested config */
> +               reg = cbqri_get_rbwb(ctrl);
> +               if (reg != cfg->rbwb) {
> +                       pr_warn("%s(): failed to verify allocation (reg:%llx != rbwb:%llu)",
> +                               __func__, reg, cfg->rbwb);
> +                       return -EIO;
> +               }
> +       }
> +
> +       return ret;
> +}
> +
> +int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
> +                           u32 closid, enum resctrl_conf_type t, u32 cfg_val)
> +{
> +       struct cbqri_controller *ctrl;
> +       struct cbqri_resctrl_dom *dom;
> +       struct cbqri_config cfg;
> +       int err = 0;
> +
> +       dom = container_of(d, struct cbqri_resctrl_dom, resctrl_ctrl_dom);
> +       ctrl = dom->hw_ctrl;
> +
> +       if (!r->alloc_capable)
> +               return -EINVAL;
> +
> +       switch (r->rid) {
> +       case RDT_RESOURCE_L2:
> +       case RDT_RESOURCE_L3:
> +               cfg.cbm = cfg_val;
> +               err = cbqri_apply_cache_config(dom, closid, t, &cfg);
> +               break;
> +       case RDT_RESOURCE_MBA:
> +               /* covert from percentage to bandwidth blocks */
> +               cfg.rbwb = cfg_val * ctrl->bc.nbwblks / 100;
> +               err = cbqri_apply_bw_config(dom, closid, t, &cfg);
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       return err;
> +}
> +
> +int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid)
> +{
> +       struct resctrl_staged_config *cfg;
> +       enum resctrl_conf_type t;
> +       struct rdt_ctrl_domain *d;
> +       int err = 0;
> +
> +       list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
> +               for (t = 0; t < CDP_NUM_TYPES; t++) {
> +                       cfg = &d->staged_config[t];
> +                       if (!cfg->have_new_ctrl)
> +                               continue;
> +                       err = resctrl_arch_update_one(r, d, closid, t, cfg->new_ctrl);
> +                       if (err) {
> +                               pr_warn("%s(): update failed (err=%d)", __func__, err);
> +                               return err;
> +                       }
> +               }
> +       }
> +       return err;
> +}
> +
> +u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
> +                           u32 closid, enum resctrl_conf_type type)
> +{
> +       struct cbqri_resctrl_dom *hw_dom;
> +       struct cbqri_controller *ctrl;
> +       int reg_offset;
> +       u32 percent;
> +       u32 rbwb;
> +       u64 reg;
> +       int err;
> +
> +       hw_dom = container_of(d, struct cbqri_resctrl_dom, resctrl_ctrl_dom);
> +
> +       ctrl = hw_dom->hw_ctrl;
> +
> +       if (!r->alloc_capable)
> +               return -EINVAL;

u32 ?

> +
> +       switch (r->rid) {
> +       case RDT_RESOURCE_L2:
> +       case RDT_RESOURCE_L3:
> +               /* Clear cc_block_mask before read limit operation */
> +               cbqri_set_cbm(ctrl, 0);
> +
> +               /* Capacity read limit operation for RCID (closid) */
> +               err = cbqri_cc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, type, closid);
> +               if (err < 0) {
> +                       pr_err("%s(): operation failed: err = %d", __func__, err);
> +                       return -EIO;

u32 ?

> +               }
> +
> +               /* Read capacity block mask for RCID (closid) */
> +               reg_offset = CBQRI_CC_BLOCK_MASK_OFF;
> +               reg = ioread64(ctrl->base + reg_offset);
> +
> +               /* Update the config value for the closid in this domain */
> +               hw_dom->ctrl_val[closid] = reg;
> +               return hw_dom->ctrl_val[closid];
> +
> +       case RDT_RESOURCE_MBA:
> +               /* Capacity read limit operation for RCID (closid) */
> +               err = cbqri_bc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, closid);
> +               if (err < 0) {
> +                       pr_err("%s(): operation failed: err = %d", __func__, err);
> +                       return -EIO;
> +               }
> +
> +               hw_dom->ctrl_val[closid] = cbqri_get_rbwb(ctrl);
> +
> +               /* Convert from bandwidth blocks to percent */
> +               rbwb = hw_dom->ctrl_val[closid];
> +               rbwb *= 100;
> +               percent = rbwb / ctrl->bc.nbwblks;
> +               if (rbwb % ctrl->bc.nbwblks)
> +                       percent++;

set: 10, get 11 ?

> +               return percent;
> +
> +       default:
> +               return -EINVAL;
> +       }
> +}
> +
> +static int cbqri_probe_feature(struct cbqri_controller *ctrl, int reg_offset,
> +                              int operation, int *status, bool *access_type_supported)
> +{
> +       u64 reg, saved_reg;
> +       int at;
> +
> +       /* Keep the initial register value to preserve the WPRI fields */
> +       reg = ioread64(ctrl->base + reg_offset);
> +       saved_reg = reg;
> +
> +       /* Execute the requested operation to find if the register is implemented */
> +       reg &= ~(CBQRI_CONTROL_REGISTERS_OP_MASK << CBQRI_CONTROL_REGISTERS_OP_SHIFT);
> +       reg |= (operation & CBQRI_CONTROL_REGISTERS_OP_MASK) << CBQRI_CONTROL_REGISTERS_OP_SHIFT;
> +       iowrite64(reg, ctrl->base + reg_offset);
> +       if (cbqri_wait_busy_flag(ctrl, reg_offset) < 0) {
> +               pr_err("%s(): BUSY timeout when executing the operation", __func__);
> +               return -EIO;
> +       }
> +
> +       /* Get the operation status */
> +       reg = ioread64(ctrl->base + reg_offset);
> +       *status = (reg >> CBQRI_CONTROL_REGISTERS_STATUS_SHIFT) &
> +                  CBQRI_CONTROL_REGISTERS_STATUS_MASK;
> +
> +       /*
> +        * Check for the AT support if the register is implemented
> +        * (if not, the status value will remain 0)
> +        */
> +       if (*status != 0) {
> +               /* Set the AT field to a valid value */
> +               reg = saved_reg;
> +               reg &= ~(CBQRI_CONTROL_REGISTERS_AT_MASK << CBQRI_CONTROL_REGISTERS_AT_SHIFT);
> +               reg |= CBQRI_CONTROL_REGISTERS_AT_CODE << CBQRI_CONTROL_REGISTERS_AT_SHIFT;
> +               iowrite64(reg, ctrl->base + reg_offset);
> +               if (cbqri_wait_busy_flag(ctrl, reg_offset) < 0) {
> +                       pr_err("%s(): BUSY timeout when setting AT field", __func__);
> +                       return -EIO;
> +               }
> +
> +               /*
> +                * If the AT field value has been reset to zero,
> +                * then the AT support is not present
> +                */
> +               reg = ioread64(ctrl->base + reg_offset);
> +               at = (reg >> CBQRI_CONTROL_REGISTERS_AT_SHIFT) & CBQRI_CONTROL_REGISTERS_AT_MASK;
> +               if (at == CBQRI_CONTROL_REGISTERS_AT_CODE)
> +                       *access_type_supported = true;
> +               else
> +                       *access_type_supported = false;
> +       }
> +
> +       /* Restore the original register value */
> +       iowrite64(saved_reg, ctrl->base + reg_offset);
> +       if (cbqri_wait_busy_flag(ctrl, reg_offset) < 0) {
> +               pr_err("%s(): BUSY timeout when restoring the original register value", __func__);
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +/*
> + * Note: for the purposes of the CBQRI proof-of-concept, debug logging
> + * has been left in this function that detects the properties of CBQRI
> + * capable controllers in the system. pr_info calls would be removed
> + * before submitting non-RFC patches.
> + */
> +static int cbqri_probe_controller(struct cbqri_controller_info *ctrl_info,
> +                                 struct cbqri_controller *ctrl)
> +{
> +       int err = 0, status;
> +       u64 reg;
> +
> +       pr_info("controller info: type=%d addr=0x%lx size=%lu max-rcid=%u max-mcid=%u",
> +               ctrl_info->type, ctrl_info->addr, ctrl_info->size,
> +               ctrl_info->rcid_count, ctrl_info->mcid_count);
> +
> +       /* max_rmid is used by resctrl_arch_system_num_rmid_idx() */
> +       max_rmid = ctrl_info->mcid_count;
> +
> +       ctrl->ctrl_info = ctrl_info;
> +
> +       /* Try to access the memory-mapped CBQRI registers */
> +       if (!request_mem_region(ctrl_info->addr, ctrl_info->size, "cbqri_controller")) {
> +               pr_warn("%s(): return %d", __func__, err);
> +               return err;

err = 0?

> +       }
> +       ctrl->base = ioremap(ctrl_info->addr, ctrl_info->size);
> +       if (!ctrl->base) {
> +               pr_warn("%s(): goto err_release_mem_region", __func__);
> +               goto err_release_mem_region;
> +       }
> +
> +       ctrl->alloc_capable = false;
> +       ctrl->mon_capable = false;
> +
> +       /* Probe capacity allocation and monitoring features */
> +       if (ctrl_info->type == CBQRI_CONTROLLER_TYPE_CAPACITY) {
> +               pr_info("probe capacity controller");
> +
> +               /* Make sure the register is implemented */
> +               reg = ioread64(ctrl->base + CBQRI_CC_CAPABILITIES_OFF);
> +               if (reg == 0) {
> +                       err = -ENODEV;
> +                       goto err_iounmap;
> +               }
> +
> +               ctrl->ver_minor = reg & CBQRI_CC_CAPABILITIES_VER_MINOR_MASK;
> +               ctrl->ver_major = reg & CBQRI_CC_CAPABILITIES_VER_MAJOR_MASK;
> +
> +               ctrl->cc.supports_alloc_op_flush_rcid = (reg >> CBQRI_CC_CAPABILITIES_FRCID_SHIFT)
> +                       & CBQRI_CC_CAPABILITIES_FRCID_MASK;
> +
> +               ctrl->cc.ncblks = (reg >> CBQRI_CC_CAPABILITIES_NCBLKS_SHIFT) &
> +                                  CBQRI_CC_CAPABILITIES_NCBLKS_MASK;
> +
> +               /* Calculate size of capacity block in bytes */
> +               ctrl->cc.blk_size = ctrl_info->cache.cache_size / ctrl->cc.ncblks;
> +               ctrl->cc.cache_level = ctrl_info->cache.cache_level;
> +
> +               pr_info("version=%d.%d ncblks=%d blk_size=%d cache_level=%d",
> +                       ctrl->ver_major, ctrl->ver_minor,
> +                       ctrl->cc.ncblks, ctrl->cc.blk_size, ctrl->cc.cache_level);
> +
> +               /* Probe monitoring features */
> +               err = cbqri_probe_feature(ctrl, CBQRI_CC_MON_CTL_OFF,
> +                                         CBQRI_CC_MON_CTL_OP_READ_COUNTER, &status,
> +                                         &ctrl->cc.supports_mon_at_code);
> +               if (err) {
> +                       pr_warn("%s() failed to probe cc_mon_ctl feature", __func__);
> +                       goto err_iounmap;
> +               }
> +
> +               if (status == CBQRI_CC_MON_CTL_STATUS_SUCCESS) {
> +                       pr_info("cc_mon_ctl is supported");
> +                       ctrl->cc.supports_mon_op_config_event = true;
> +                       ctrl->cc.supports_mon_op_read_counter = true;
> +                       ctrl->mon_capable = true;
> +               } else {
> +                       pr_info("cc_mon_ctl is NOT supported");
> +                       ctrl->cc.supports_mon_op_config_event = false;
> +                       ctrl->cc.supports_mon_op_read_counter = false;
> +                       ctrl->mon_capable = false;
> +               }
> +               /*
> +                * AT data is "always" supported as it has the same value
> +                * than when AT field is not supported.
> +                */
> +               ctrl->cc.supports_mon_at_data = true;
> +               pr_info("supports_mon_at_data: %d, supports_mon_at_code: %d",
> +                       ctrl->cc.supports_mon_at_data, ctrl->cc.supports_mon_at_code);
> +
> +               /* Probe allocation features */
> +               err = cbqri_probe_feature(ctrl, CBQRI_CC_ALLOC_CTL_OFF,
> +                                         CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT,
> +                                         &status, &ctrl->cc.supports_alloc_at_code);
> +               if (err) {
> +                       pr_warn("%s() failed to probe cc_alloc_ctl feature", __func__);
> +                       goto err_iounmap;
> +               }
> +
> +               if (status == CBQRI_CC_ALLOC_CTL_STATUS_SUCCESS) {
> +                       pr_info("cc_alloc_ctl is supported");
> +                       ctrl->cc.supports_alloc_op_config_limit = true;
> +                       ctrl->cc.supports_alloc_op_read_limit = true;
> +                       ctrl->alloc_capable = true;
> +                       exposed_alloc_capable = true;
> +               } else {
> +                       pr_info("cc_alloc_ctl is NOT supported");
> +                       ctrl->cc.supports_alloc_op_config_limit = false;
> +                       ctrl->cc.supports_alloc_op_read_limit = false;
> +                       ctrl->alloc_capable = false;
> +               }
> +               /*
> +                * AT data is "always" supported as it has the same value
> +                * than when AT field is not supported
> +                */
> +               ctrl->cc.supports_alloc_at_data = true;
> +               pr_info("supports_alloc_at_data: %d, supports_alloc_at_code: %d",
> +                       ctrl->cc.supports_alloc_at_data,
> +                       ctrl->cc.supports_alloc_at_code);
> +       } else if (ctrl_info->type == CBQRI_CONTROLLER_TYPE_BANDWIDTH) {
> +               pr_info("probe bandwidth controller");
> +
> +               /* Make sure the register is implemented */
> +               reg = ioread64(ctrl->base + CBQRI_BC_CAPABILITIES_OFF);
> +               if (reg == 0) {
> +                       err = -ENODEV;
> +                       goto err_iounmap;
> +               }
> +
> +               ctrl->ver_minor = reg & CBQRI_BC_CAPABILITIES_VER_MINOR_MASK;
> +               ctrl->ver_major = reg & CBQRI_BC_CAPABILITIES_VER_MAJOR_MASK;
> +
> +               ctrl->bc.nbwblks = (reg >> CBQRI_BC_CAPABILITIES_NBWBLKS_SHIFT) &
> +                                   CBQRI_BC_CAPABILITIES_NBWBLKS_MASK;
> +               ctrl->bc.mrbwb = (reg >> CBQRI_BC_CAPABILITIES_MRBWB_SHIFT) &
> +                                 CBQRI_BC_CAPABILITIES_MRBWB_MASK;
> +
> +               pr_info("version=%d.%d nbwblks=%d mrbwb=%d",
> +                       ctrl->ver_major, ctrl->ver_minor,
> +                       ctrl->bc.nbwblks, ctrl->bc.mrbwb);
> +
> +               /* Probe monitoring features */
> +               err = cbqri_probe_feature(ctrl, CBQRI_BC_MON_CTL_OFF,
> +                                         CBQRI_BC_MON_CTL_OP_READ_COUNTER,
> +                                         &status, &ctrl->bc.supports_mon_at_code);
> +               if (err) {
> +                       pr_warn("%s() failed to probe bc_mon_ctl feature", __func__);
> +                       goto err_iounmap;
> +               }
> +
> +               if (status == CBQRI_BC_MON_CTL_STATUS_SUCCESS) {
> +                       pr_info("bc_mon_ctl is supported");
> +                       ctrl->bc.supports_mon_op_config_event = true;
> +                       ctrl->bc.supports_mon_op_read_counter = true;
> +                       ctrl->mon_capable = true;
> +                       exposed_mon_capable = true;
> +               } else {
> +                       pr_info("bc_mon_ctl is NOT supported");
> +                       ctrl->bc.supports_mon_op_config_event = false;
> +                       ctrl->bc.supports_mon_op_read_counter = false;
> +                       ctrl->mon_capable = false;
> +               }
> +               /*
> +                * AT data is "always" supported as it has the same value
> +                * than when AT field is not supported
> +                */
> +               ctrl->bc.supports_mon_at_data = true;
> +               pr_info("supports_mon_at_data: %d, supports_mon_at_code: %d",
> +                       ctrl->bc.supports_mon_at_data, ctrl->bc.supports_mon_at_code);
> +
> +               /* Probe allocation features */
> +               err = cbqri_probe_feature(ctrl, CBQRI_BC_ALLOC_CTL_OFF,
> +                                         CBQRI_BC_ALLOC_CTL_OP_READ_LIMIT,
> +                                         &status, &ctrl->bc.supports_alloc_at_code);
> +               if (err) {
> +                       pr_warn("%s() failed to probe bc_alloc_ctl feature", __func__);
> +                       goto err_iounmap;
> +               }
> +
> +               if (status == CBQRI_BC_ALLOC_CTL_STATUS_SUCCESS) {
> +                       pr_warn("bc_alloc_ctl is supported");
> +                       ctrl->bc.supports_alloc_op_config_limit = true;
> +                       ctrl->bc.supports_alloc_op_read_limit = true;
> +                       ctrl->alloc_capable = true;
> +                       exposed_alloc_capable = true;
> +               } else {
> +                       pr_warn("bc_alloc_ctl is NOT supported");
> +                       ctrl->bc.supports_alloc_op_config_limit = false;
> +                       ctrl->bc.supports_alloc_op_read_limit = false;
> +                       ctrl->alloc_capable = false;
> +               }
> +
> +               /*
> +                * AT data is "always" supported as it has the same value
> +                * than when AT field is not supported
> +                */
> +               ctrl->bc.supports_alloc_at_data = true;
> +               pr_warn("supports_alloc_at_data: %d, supports_alloc_at_code: %d",
> +                       ctrl->bc.supports_alloc_at_data, ctrl->bc.supports_alloc_at_code);
> +       } else {
> +               pr_warn("controller type is UNKNOWN");
> +               err = -ENODEV;
> +               goto err_release_mem_region;
> +       }
> +
> +       return 0;
> +
> +err_iounmap:
> +       pr_warn("%s(): err_iounmap", __func__);
> +       iounmap(ctrl->base);
> +
> +err_release_mem_region:
> +       pr_warn("%s(): err_release_mem_region", __func__);
> +       release_mem_region(ctrl_info->addr, ctrl_info->size);
> +
> +       return err;
> +}
> +
> +static struct rdt_ctrl_domain *qos_new_domain(struct cbqri_controller *ctrl)
> +{
> +       struct cbqri_resctrl_dom *hw_dom;
> +       struct rdt_ctrl_domain *domain;
> +
> +       hw_dom = kzalloc(sizeof(*hw_dom), GFP_KERNEL);
> +       if (!hw_dom)
> +               return NULL;
> +
> +       /* associate this cbqri_controller with the domain */
> +       hw_dom->hw_ctrl = ctrl;
> +
> +       /* the rdt_domain struct from inside the cbqri_resctrl_dom struct */
> +       domain = &hw_dom->resctrl_ctrl_dom;
> +
> +       INIT_LIST_HEAD(&domain->hdr.list);
> +
> +       return domain;
> +}
> +
> +static int qos_init_domain_ctrlval(struct rdt_resource *r, struct rdt_ctrl_domain *d)
> +{
> +       struct cbqri_resctrl_res *hw_res;
> +       struct cbqri_resctrl_dom *hw_dom;
> +       u64 *dc;
> +       int err = 0;
> +       int i;
> +
> +       hw_res = container_of(r, struct cbqri_resctrl_res, resctrl_res);
> +       if (!hw_res)
> +               return -ENOMEM;
> +
> +       hw_dom = container_of(d, struct cbqri_resctrl_dom, resctrl_ctrl_dom);
> +       if (!hw_dom)
> +               return -ENOMEM;
> +
> +       dc = kmalloc_array(hw_res->max_rcid, sizeof(*hw_dom->ctrl_val),
> +                          GFP_KERNEL);
> +       if (!dc)
> +               return -ENOMEM;
> +
> +       hw_dom->ctrl_val = dc;
> +
> +       for (i = 0; i < hw_res->max_rcid; i++, dc++) {
> +               err = resctrl_arch_update_one(r, d, i, 0, resctrl_get_default_ctrl(r));
> +               if (err)
> +                       return 0;
> +               *dc = resctrl_get_default_ctrl(r);
> +       }
> +       return 0;
> +}
> +
> +static int qos_resctrl_add_controller_domain(struct cbqri_controller *ctrl, int *id)
> +{
> +       struct rdt_ctrl_domain *domain = NULL;
> +       struct cbqri_resctrl_res *cbqri_res = NULL;
> +       struct rdt_resource *res = NULL;
> +       int internal_id = *id;
> +       int err = 0;
> +
> +       domain = qos_new_domain(ctrl);
> +       if (!domain)
> +               return -ENOSPC;
> +       if (ctrl->ctrl_info->type == CBQRI_CONTROLLER_TYPE_CAPACITY) {
> +               cpumask_copy(&domain->hdr.cpu_mask, &ctrl->ctrl_info->cache.cpu_mask);
> +               if (ctrl->ctrl_info->cache.cache_level == 2) {
> +                       cbqri_res = &cbqri_resctrl_resources[RDT_RESOURCE_L2];
> +                       cbqri_res->max_rcid = ctrl->ctrl_info->rcid_count;
> +                       cbqri_res->max_mcid = ctrl->ctrl_info->mcid_count;
> +                       res = &cbqri_res->resctrl_res;
> +                       res->mon.num_rmid = ctrl->ctrl_info->mcid_count;
> +                       res->rid = RDT_RESOURCE_L2;
> +                       res->name = "L2";
> +                       res->alloc_capable = ctrl->alloc_capable;
> +                       res->mon_capable = ctrl->mon_capable;
> +                       res->schema_fmt = RESCTRL_SCHEMA_BITMAP;
> +                       res->ctrl_scope = RESCTRL_L2_CACHE;
> +                       res->cache.arch_has_sparse_bitmasks = false;
> +                       res->cache.arch_has_per_cpu_cfg = false;
> +                       res->cache.cbm_len = ctrl->cc.ncblks;
> +                       res->cache.shareable_bits = resctrl_get_default_ctrl(res);
> +                       res->cache.min_cbm_bits = 1;
> +               } else if (ctrl->ctrl_info->cache.cache_level == 3) {
> +                       cbqri_res = &cbqri_resctrl_resources[RDT_RESOURCE_L3];
> +                       cbqri_res->max_rcid = ctrl->ctrl_info->rcid_count;
> +                       cbqri_res->max_mcid = ctrl->ctrl_info->mcid_count;
> +                       res = &cbqri_res->resctrl_res;
> +                       res->mon.num_rmid = ctrl->ctrl_info->mcid_count;
> +                       res->rid = RDT_RESOURCE_L3;
> +                       res->name = "L3";
> +                       res->schema_fmt = RESCTRL_SCHEMA_BITMAP;
> +                       res->ctrl_scope = RESCTRL_L3_CACHE;
> +                       res->alloc_capable = ctrl->alloc_capable;
> +                       res->mon_capable = ctrl->mon_capable;
> +                       res->cache.arch_has_sparse_bitmasks = false;
> +                       res->cache.arch_has_per_cpu_cfg = false;
> +                       res->cache.cbm_len = ctrl->cc.ncblks;
> +                       res->cache.shareable_bits = resctrl_get_default_ctrl(res);
> +                       res->cache.min_cbm_bits = 1;
> +               } else {
> +                       pr_warn("%s(): unknown cache level %d", __func__,
> +                               ctrl->ctrl_info->cache.cache_level);
> +                       err = -ENODEV;
> +                       goto err_free_domain;
> +               }
> +       } else if (ctrl->ctrl_info->type == CBQRI_CONTROLLER_TYPE_BANDWIDTH) {
> +               if (ctrl->alloc_capable) {
> +                       cbqri_res = &cbqri_resctrl_resources[RDT_RESOURCE_MBA];
> +                       cbqri_res->max_rcid = ctrl->ctrl_info->rcid_count;
> +                       cbqri_res->max_mcid = ctrl->ctrl_info->mcid_count;
> +                       res = &cbqri_res->resctrl_res;
> +                       res->mon.num_rmid = ctrl->ctrl_info->mcid_count;
> +                       res->rid = RDT_RESOURCE_MBA;
> +                       res->name = "MB";
> +                       res->schema_fmt = RESCTRL_SCHEMA_RANGE;
> +                       res->ctrl_scope = RESCTRL_L3_CACHE;
> +                       res->alloc_capable = ctrl->alloc_capable;
> +                       res->mon_capable = false;
> +                       res->membw.delay_linear = true;
> +                       res->membw.arch_needs_linear = true;
> +                       res->membw.throttle_mode = THREAD_THROTTLE_UNDEFINED;
> +                       // The minimum percentage allowed by the CBQRI spec
> +                       res->membw.min_bw = 1;
> +                       // The maximum percentage allowed by the CBQRI spec
> +                       res->membw.max_bw = 80;
> +                       res->membw.bw_gran = 1;
> +               }
> +       } else {
> +               pr_warn("%s(): unknown resource %d", __func__, ctrl->ctrl_info->type);
> +               err = -ENODEV;
> +               goto err_free_domain;
> +       }
> +
> +       domain->hdr.id = internal_id;
> +       err = qos_init_domain_ctrlval(res, domain);
> +       if (err)
> +               goto err_free_domain;
> +
> +       if (cbqri_res) {
> +               list_add_tail(&domain->hdr.list, &cbqri_res->resctrl_res.ctrl_domains);
> +               *id = internal_id;
> +               err = resctrl_online_ctrl_domain(res, domain);
> +               if (err) {
> +                       pr_warn("%s(): failed to online cbqri_res domain", __func__);
> +                       goto err_free_domain;
> +               }
> +       }
> +
> +       return 0;
> +
> +err_free_domain:
> +       pr_warn("%s(): err_free_domain", __func__);
> +       kfree(container_of(domain, struct cbqri_resctrl_dom, resctrl_ctrl_dom));
> +
> +       return err;
> +}
> +
> +int qos_resctrl_setup(void)
> +{
> +       struct rdt_ctrl_domain *domain, *domain_temp;
> +       struct cbqri_controller_info *ctrl_info;
> +       struct cbqri_controller *ctrl;
> +       struct cbqri_resctrl_res *res;
> +       static int found_controllers;
> +       int err = 0;
> +       int id = 0;
> +       int i;
> +
> +       list_for_each_entry(ctrl_info, &cbqri_controllers, list) {
> +               err = cbqri_probe_controller(ctrl_info, &controllers[found_controllers]);
> +               if (err) {
> +                       pr_warn("%s(): failed (%d)", __func__, err);
> +                       goto err_unmap_controllers;
> +               }
> +
> +               found_controllers++;
> +               if (found_controllers > MAX_CONTROLLERS) {
> +                       pr_warn("%s(): increase MAX_CONTROLLERS value", __func__);
> +                       break;
> +               }
> +       }
> +
> +       for (i = 0; i < RDT_NUM_RESOURCES; i++) {
> +               res = &cbqri_resctrl_resources[i];
> +               INIT_LIST_HEAD(&res->resctrl_res.ctrl_domains);
> +               INIT_LIST_HEAD(&res->resctrl_res.mon_domains);
> +               res->resctrl_res.rid = i;
> +       }
> +
> +       for (i = 0; i < found_controllers; i++) {
> +               ctrl = &controllers[i];

controllers[6] ?

> +               err = qos_resctrl_add_controller_domain(ctrl, &id);
> +               if (err) {
> +                       pr_warn("%s(): failed to add controller domain (%d)", __func__, err);
> +                       goto err_free_controllers_list;
> +               }
> +               id++;
> +
> +               /*
> +                * CDP (code data prioritization) on x86 is similar to
> +                * the AT (access type) field in CBQRI. CDP only supports
> +                * caches so this must be a CBQRI capacity controller.
> +                */
> +               if (ctrl->ctrl_info->type == CBQRI_CONTROLLER_TYPE_CAPACITY &&
> +                   ctrl->cc.supports_alloc_at_code &&
> +                   ctrl->cc.supports_alloc_at_data) {
> +                       if (ctrl->ctrl_info->cache.cache_level == 2)
> +                               exposed_cdp_l2_capable = true;
> +                       else
> +                               exposed_cdp_l3_capable = true;
> +               }
> +       }
> +
> +       pr_info("exposed_alloc_capable = %d", exposed_alloc_capable);
> +       pr_info("exposed_mon_capable = %d", exposed_mon_capable);
> +       pr_info("exposed_cdp_l2_capable = %d", exposed_cdp_l2_capable);
> +       pr_info("exposed_cdp_l3_capable = %d", exposed_cdp_l3_capable);
> +
> +       return resctrl_init();
> +
> +err_free_controllers_list:
> +       for (i = 0; i < RDT_NUM_RESOURCES; i++) {
> +               res = &cbqri_resctrl_resources[i];
> +               list_for_each_entry_safe(domain, domain_temp, &res->resctrl_res.ctrl_domains,
> +                                        hdr.list) {
> +                       kfree(domain);
> +               }
> +       }
> +
> +err_unmap_controllers:
> +       for (i = 0; i < found_controllers; i++) {
> +               iounmap(controllers[i].base);
> +               release_mem_region(controllers[i].ctrl_info->addr, controllers[i].ctrl_info->size);
> +       }
> +
> +       return err;
> +}
> +
> +int qos_resctrl_online_cpu(unsigned int cpu)
> +{
> +       resctrl_online_cpu(cpu);
> +       return 0;
> +}
> +
> +int qos_resctrl_offline_cpu(unsigned int cpu)
> +{
> +       resctrl_offline_cpu(cpu);
> +       return 0;
> +}
> +
>
> --
> 2.43.0
>

Thanks,
Yunhui

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

* Re: [External] [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface
  2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
                   ` (19 preceding siblings ...)
  2026-01-22 22:31 ` [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Reinette Chatre
@ 2026-01-26 13:14 ` yunhui cui
  2026-01-26 20:11   ` Drew Fustini
  20 siblings, 1 reply; 29+ messages in thread
From: yunhui cui @ 2026-01-26 13:14 UTC (permalink / raw)
  To: Drew Fustini
  Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, Chen Pei, Liu Zhiwei,
	Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, devicetree, linux-kernel, linux-riscv, x86,
	Conor Dooley

Hi Drew,


On Tue, Jan 20, 2026 at 12:15 PM Drew Fustini <fustini@kernel.org> wrote:
>
> This RFC series implements the RISC-V Quality-of-Service Identifiers
> (Ssqosid) extension [1] which adds the srmcfg register. It also
> implements the RISC-V Capacity and Bandwidth Controller QoS Register
> Interface (CBQRI) specification [2] and integrates resctrl [3] support.
> The patches are also available as a branch [4].
>
> There is a Qemu patch series [5] that implements Ssqosid and CBQRI, and
> a corresponding Qemu branch with those patches too [6].
>
> [1] https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0
> [2] https://github.com/riscv-non-isa/riscv-cbqri/releases/tag/v1.0
> [3] https://docs.kernel.org/filesystems/resctrl.html
> [4] https://git.kernel.org/pub/scm/linux/kernel/git/fustini/linux.git/log/?h=b4/ssqosid-cbqri
> [5] https://lore.kernel.org/qemu-devel/20260105-riscv-ssqosid-cbqri-v4-0-9ad7671dde78@kernel.org/
> [6] https://github.com/tt-fustini/qemu/tree/b4/riscv-ssqosid-cbqri
>
> RISC-V QoS
> ----------
> QoS (Quality of Service) in this context is concerned with shared
> resources on an SoC such as cache capacity and memory bandwidth.
>
> The Sssqosid extension defines the srmcfg CSR which configures a hart
> with two identifiers:
>
>  - Resource Control ID (RCID)
>  - Monitoring Counter ID (MCID)
>
> These identifiers accompany each request issued by the hart to shared
> resource controllers. This allows the capacity and bandwidth resources
> used by a software workload (e.g. a process or a set of processes) to be
> controlled and monitored.
>
> CBQRI defines operations to configure resource usage limits, in the form
> of capacity or bandwidth, for an RCID. CBQRI also defines operations to
> configure counters to track resource utilization per MCID. Furthermore,
> the Access Type (AT) field allows resource usage to be differentiated
> between data and code.
>
> x86 comparison
> --------------
> The existing QoS identifiers on x86 map well:
>
>   CLOSID (Class of Service ID) on x86 is RCID on RISC-V
>     RMID (Resource Monitoring ID) on x86 is MCID on RISC-V
>
> In addition, CDP (code data prioritization) on x86 is similar to the
> AT (access type) field in CBQRI which defines code and data types.
>
> One aspect of CBQRI that simplifies the RISC-V resctrl interface is that
> any cpu (technically a hart, or hardware thread, in RISC-V terminology)
> can access the memory-mapped registers of any CBQRI controller in the
> system. This means it does not matter which cpu runs the resctrl code.
>
> Example SoC
> -----------
> This series also includes a Qemu device tree and platform drivers for a
> hypothetical SoC with a cache controller that implements CBQRI capacity
> operations and a memory controller that implements CBQRI bandwidth
> operations.
>
>   - L2 cache controllers
>     - Resource type: Capacity
>     - Number of capacity blocks (NCBLKS): 12
>         - In the context of a set-associative cache, the number of
>           capacity blocks can be thought of as the number of ways
>     - Number of access types: 2 (code and data)
>     - Usage monitoring not supported
>     - Capacity allocation operations: CONFIG_LIMIT, READ_LIMIT
>
>   - Last-level cache (LLC) controller
>     - Resource type: Capacity
>     - Number of capacity blocks (NCBLKS): 16
>     - Number of access types: 2 (code and data)
>     - Usage monitoring operations: CONFIG_EVENT, READ_COUNTER
>     - Event IDs supported: None, Occupancy
>     - Capacity allocation ops: CONFIG_LIMIT, READ_LIMIT, FLUSH_RCID
>
>   - Memory controllers
>     - Resource type: Bandwidth
>     - Number of bandwidth blocks (NBWBLKS): 1024
>        - Bandwidth blocks do not have a unit but instead represent a
>          portion of the total bandwidth resource. For NWBLKS of 1024,
>          each block represents about 0.1% of the bandwidth resource.
>     - Maximum reserved bandwidth blocks (MRBWB): 819 (80% of NBWBLKS)
>     - Number of access types: 1 (no code/data differentiation)
>     - Usage monitoring operations: CONFIG_EVENT, READ_COUNTER
>     - Event IDs supported: None, Total read/write byte count, Total
>                            read byte count, Total write byte count
>     - Bandwidth allocation operations: CONFIG_LIMIT, READ_LIMIT
>
> The memory map for this example SoC:
>
>   Base addr  Size
>   0x4820000  4KB  Cluster 0 L2 cache controller
>   0x4821000  4KB  Cluster 1 L2 cache controller
>   0x4828000  4KB  Memory controller 0
>   0x4829000  4KB  Memory controller 1
>   0X482a000  4KB  Memory controller 2
>   0X482b000  4KB  Shared LLC cache controller
>
> This configuration is only meant to provide a "concrete" example, and it
> represents just one of many possible ways that hardware can implement
> the CBQRI spec.
>
> The example SoC configuration is created with the following:
>
>   qemu-system-riscv64 \
>         -M virt \
>         -nographic \
>         -smp 8 \
>         -device riscv.cbqri.capacity,max_mcids=256,max_rcids=64,ncblks=12,alloc_op_flush_rcid=false,mon_op_config_event=false,mon_op_read_counter=false,mon_evt_id_none=false,mon_evt_id_occupancy=false,mmio_base=0x04820000 \
>         -device riscv.cbqri.capacity,max_mcids=256,max_rcids=64,ncblks=12,alloc_op_flush_rcid=false,mon_op_config_event=false,mon_op_read_counter=false,mon_evt_id_none=false,mon_evt_id_occupancy=false,mmio_base=0x04821000 \
>         -device riscv.cbqri.capacity,max_mcids=256,max_rcids=64,ncblks=16,mmio_base=0x0482B000 \
>         -device riscv.cbqri.bandwidth,max_mcids=256,max_rcids=64,nbwblks=1024,mrbwb=819,mmio_base=0x04828000 \
>         -device riscv.cbqri.bandwidth,max_mcids=256,max_rcids=64,nbwblks=1024,mrbwb=819,mmio_base=0x04829000 \
>         -device riscv.cbqri.bandwidth,max_mcids=256,max_rcids=64,nbwblks=1024,mrbwb=819,mmio_base=0x0482a000
>
> In addition, please note that this series only implements the register
> interface that CBQRI specifies. It does not attempt to emulate the
> performance impact of configuring limits on shared resources like cache
> and memory bandwidth.
>
> Versioning
> ----------
> I chose to make this series v1 as there have been many changes from the
> old proof-of-concept. However, here are previous series to make the
> history clear:
>
>  [RFC PATCH 00/21] RISC-V: QoS: add CBQRI resctrl interface
>  https://lore.kernel.org/all/20230419111111.477118-1-dfustini@baylibre.com/
>  The original RFC from the CBQRI proof-of-concept in 2023 that worked
>  in conjunction with the Qemu patch series for the proof-of-concept.
>
>  [PATCH v4 0/3] RISC-V: Detect Ssqosid extension and handle srmcfg CSR
>  https://lore.kernel.org/all/20251007-ssqosid-v4-0-e8b57e59d812@kernel.org/
>  More recently I thought it would be simpler to upstream just the
>  Ssqosid patches first. However, I got feedback that it was hard to
>  review without the CBQRI patches in the same series.
>
> Open issues:
> ------------
>  - Checkpatch false positive: there is a checkpatch warning about
>    "Argument '__next' is not used in function-like macro"
>    - __switch_to_srmcfg(__next) is needed to avoid the error reported
>      by LKP for riscv-allnoconfig:
>      https://lore.kernel.org/oe-kbuild-all/202509162355.wByessnb-lkp@intel.com/
>    - __switch_to_srmcfg() will trigger a build error in clang when
>      CONFIG_RISCV_ISA_SSQOSID is turned off.
>
>  - The number of CBQRI controllers is hard coded
>    - This was done as a simple approach in the proof-of-concept as there
>      were 6 controllers
>    - I need to refactor this so that it is dynamically allocated based
>      on the number of controllers present in the system
>
>  - Stub platform drivers are included to demonstrate device tree integration
>    - I am expecting a real CBQRI-enabled hardware platform using device
>      tree would have real platform drivers for controllers that
>      implement CBQRI.
>    - To demonstrate the interaction with the qemu model, I have included
>      patches which create "stub" drivers for a cache controller and a
>      generic bandwidth controller. These patches are not meant for
>      upstream, so I did not create binding documentation for the
>      compatibles.
>
>  - Add RQSC table support for ACPI platforms
>    - My kernel patches from the RQSC proof-of-concept were based on
>      v6.14, so I need to rebase them.
>    - The necessary PPTT helpers are already in 6.19 thanks to the MPAM
>      driver series. This should help reduce the number of patches in my
>      RQSC series.
>    - My Qemu patches for RQSC will also take some work to rebase on top
>      of my recent Qemu CBQRI+Ssqosid v4 series.

1. What about the relevant logic for mweight?
2. What is the support plan for IOMMU?
3. Can we also add the patches that support RQSC to this patchset?

>
>  - No L2 and L3 cache occupancy monitoring
>    - This is not currently implemented and I have to decided to leave
>      it as an enhancement for a future series after the Ssqosid and
>      CBQRI core are merged.
>
>  - No MBM (bandwidth monitoring)
>    - MBA schema works ok for the CBQRI-enabled memory controllers, but
>      resctrl does not currently have solution for representing MBM for
>      bandwidth resources that are not associated with a L3 cache.
>    - For the old CBQRI proof-of-concept RFC, two separate domains were
>      created for each memory controller: one for MB (allocation) and one
>      for MBM (monitoring).
>    - The monitoring domains had to pretend that these memory controllers
>      were L3 caches which is not the case. I have removed this as it was
>      too complicated and not the right solution.
>    - Fenghua Yu talked about a similar problem last month at LPC in the
>      resctrl BoF during the "MBA/MBM on CPU-less Memory Node" topic:
>      https://lpc.events/event/19/contributions/2093/
>    - I hope to work with resctrl developers on finding a solution.
>
> ---
> Drew Fustini (19):
>       dt-bindings: riscv: Add Ssqosid extension description
>       RISC-V: Detect the Ssqosid extension
>       RISC-V: Add support for srmcfg CSR from Ssqosid ext
>       RISC-V: QoS: define properties of CBQRI controllers
>       RISC-V: QoS: define CBQRI capacity and bandwidth capabilities
>       RISC-V: QoS: define CBQRI resctrl resources and domains
>       RISC-V: QoS: define prototypes for resctrl interface
>       RISC-V: QoS: add resctrl interface for CBQRI controllers
>       RISC-V: QoS: expose implementation to resctrl
>       RISC-V: QoS: add late_initcall to setup resctrl interface
>       RISC-V: QoS: add to build when CONFIG_RISCV_ISA_SSQOSID set
>       RISC-V: QoS: make CONFIG_RISCV_ISA_SSQOSID select resctrl
>       dt-bindings: riscv: add riscv,cbqri bindings
>       [NFU] resctrl: riscv: add CBQRI cache controller driver
>       [NFU] resctrl: riscv: add CBQRI bandwidth controller driver
>       [NFU] resctrl: riscv: build CBQRI drivers
>       [NFU] riscv: dts: qemu: add dump from virt machine
>       [NFU] riscv: dts: qemu: add CBQRI controller nodes
>       [NFU] riscv: dts: build qemu dtb for CONFIG_ARCH_VIRT
>
>  .../devicetree/bindings/riscv/extensions.yaml      |    6 +
>  .../devicetree/bindings/riscv/riscv,cbqri.yaml     |   28 +
>  MAINTAINERS                                        |   10 +
>  arch/riscv/Kconfig                                 |   20 +
>  arch/riscv/boot/dts/Makefile                       |    1 +
>  arch/riscv/boot/dts/qemu/Makefile                  |    3 +
>  arch/riscv/boot/dts/qemu/qemu-virt-cbqri.dts       |  458 ++++++++
>  arch/riscv/include/asm/csr.h                       |    8 +
>  arch/riscv/include/asm/hwcap.h                     |    1 +
>  arch/riscv/include/asm/processor.h                 |    3 +
>  arch/riscv/include/asm/qos.h                       |   41 +
>  arch/riscv/include/asm/resctrl.h                   |    2 +
>  arch/riscv/include/asm/switch_to.h                 |    3 +
>  arch/riscv/kernel/Makefile                         |    2 +
>  arch/riscv/kernel/cpufeature.c                     |    1 +
>  arch/riscv/kernel/qos/Makefile                     |    2 +
>  arch/riscv/kernel/qos/internal.h                   |  155 +++
>  arch/riscv/kernel/qos/qos.c                        |   32 +
>  arch/riscv/kernel/qos/qos_resctrl.c                | 1191 ++++++++++++++++++++
>  drivers/resctrl/Kconfig                            |    2 +
>  drivers/resctrl/Makefile                           |    2 +
>  drivers/resctrl/riscv/Kconfig                      |   25 +
>  drivers/resctrl/riscv/Makefile                     |    4 +
>  drivers/resctrl/riscv/cbqri_bandwidth.c            |   79 ++
>  drivers/resctrl/riscv/cbqri_cache.c                |  106 ++
>  include/linux/riscv_qos.h                          |   78 ++
>  26 files changed, 2263 insertions(+)
> ---
> base-commit: 9ace4753a5202b02191d54e9fdf7f9e3d02b85eb
> change-id: 20260112-ssqosid-cbqri-407cfcda9ff4
>
> Best regards,
> --
> Drew Fustini <fustini@kernel.org>
>

Thanks,
Yunhui

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

* Re: [External] [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface
  2026-01-26 13:14 ` [External] " yunhui cui
@ 2026-01-26 20:11   ` Drew Fustini
  2026-01-27  2:33     ` yunhui cui
  0 siblings, 1 reply; 29+ messages in thread
From: Drew Fustini @ 2026-01-26 20:11 UTC (permalink / raw)
  To: yunhui cui
  Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, Chen Pei, Liu Zhiwei,
	Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, devicetree, linux-kernel, linux-riscv, x86,
	Conor Dooley

On Mon, Jan 26, 2026 at 09:14:24PM +0800, yunhui cui wrote:
> 1. What about the relevant logic for mweight?

My intention for this series is to just add support for functionality
that matches the existing resctrl schemata. I think mweight could be
added later. There is active discussion [1] about how to expand schemas
in resctrl.

> 2. What is the support plan for IOMMU?

Similarly, I wanted to land the basic resctrl support before expanding
to other resource types.

> 3. Can we also add the patches that support RQSC to this patchset?

I'm about to send it as part of v2 of this series. I removed the
platform drivers and use to ACPI to boot the system. I will finish
editing the cover letter and send today. The b4/ssqosid-cbqri branch
contains what will be the v2 series.

Thanks,
Drew

[1] https://lore.kernel.org/all/aXUK7XFsHl+gnwA%2F@x1/
[2] https://github.com/tt-fustini/linux/commits/b4/ssqosid-cbqri/

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

* Re: [External] [PATCH RFC 08/19] RISC-V: QoS: add resctrl interface for CBQRI controllers
  2026-01-26 13:01   ` [External] " yunhui cui
@ 2026-01-26 21:02     ` Drew Fustini
  2026-01-27 22:10       ` Drew Fustini
  0 siblings, 1 reply; 29+ messages in thread
From: Drew Fustini @ 2026-01-26 21:02 UTC (permalink / raw)
  To: yunhui cui
  Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, Chen Pei, Liu Zhiwei,
	Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, devicetree, linux-kernel, linux-riscv, x86

On Mon, Jan 26, 2026 at 09:01:30PM +0800, yunhui cui wrote:
> Hi Drew,
> 
> On Tue, Jan 20, 2026 at 12:15 PM Drew Fustini <fustini@kernel.org> wrote:
> >
> > Add interface for CBQRI controller drivers to make use of the resctrl
> > filesystem.
> >
> > Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
> > Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
> > Signed-off-by: Drew Fustini <fustini@kernel.org>
> > ---
> >  arch/riscv/kernel/qos/qos_resctrl.c | 1191 +++++++++++++++++++++++++++++++++++
> >  1 file changed, 1191 insertions(+)
> >
> > diff --git a/arch/riscv/kernel/qos/qos_resctrl.c b/arch/riscv/kernel/qos/qos_resctrl.c
> > new file mode 100644
> > index 000000000000..5e3a65342e9b
> > --- /dev/null
> > +++ b/arch/riscv/kernel/qos/qos_resctrl.c
[..]
> > +/* Set capacity block mask (cc_block_mask) */
> > +static void cbqri_set_cbm(struct cbqri_controller *ctrl, u64 cbm)
> > +{
> > +               int reg_offset;
> > +               u64 reg;
> > +
> > +               reg_offset = CBQRI_CC_BLOCK_MASK_OFF;
> > +               reg = ioread64(ctrl->base + reg_offset);
> > +
> > +               reg = cbm;
> > +               iowrite64(reg, ctrl->base + reg_offset);
> > +}
> > +
> 
> too much indentation ?

Thanks, will fix indentation for cbqri_set_cbm, cbqri_set_rbwb, and
cbqri_get_rbwb.

> > +static int cbqri_wait_busy_flag(struct cbqri_controller *ctrl, int reg_offset)
> > +{
> > +       unsigned long timeout = jiffies + (HZ / 10); /* Timeout after 100ms */
> 
> hung task ?

Good point, this is too long. I tried 100 us which wasn't long enough
for Qemu on my system but 1,000 us worked okay.

I will change to 1,000 us.

        unsigned long timeout = jiffies + usecs_to_jiffies(1000);

> > +u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
> > +                           u32 closid, enum resctrl_conf_type type)
> > +{
> > +       struct cbqri_resctrl_dom *hw_dom;
> > +       struct cbqri_controller *ctrl;
> > +       int reg_offset;
> > +       u32 percent;
> > +       u32 rbwb;
> > +       u64 reg;
> > +       int err;
> > +
> > +       hw_dom = container_of(d, struct cbqri_resctrl_dom, resctrl_ctrl_dom);
> > +
> > +       ctrl = hw_dom->hw_ctrl;
> > +
> > +       if (!r->alloc_capable)
> > +               return -EINVAL;
> 
> u32 ?

Good point.  I looked at mpam_resctrl.c and it returns the default value
on error:
https://lore.kernel.org/all/20260112165914.4086692-19-ben.horgan@arm.com/

I will change to 'return resctrl_get_default_ctrl(r)'.

> > +
> > +       switch (r->rid) {
> > +       case RDT_RESOURCE_L2:
> > +       case RDT_RESOURCE_L3:
> > +               /* Clear cc_block_mask before read limit operation */
> > +               cbqri_set_cbm(ctrl, 0);
> > +
> > +               /* Capacity read limit operation for RCID (closid) */
> > +               err = cbqri_cc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, type, closid);
> > +               if (err < 0) {
> > +                       pr_err("%s(): operation failed: err = %d", __func__, err);
> > +                       return -EIO;
> 
> u32 ?

Same as above.

> > +               }
> > +
> > +               /* Read capacity block mask for RCID (closid) */
> > +               reg_offset = CBQRI_CC_BLOCK_MASK_OFF;
> > +               reg = ioread64(ctrl->base + reg_offset);
> > +
> > +               /* Update the config value for the closid in this domain */
> > +               hw_dom->ctrl_val[closid] = reg;
> > +               return hw_dom->ctrl_val[closid];
> > +
> > +       case RDT_RESOURCE_MBA:
> > +               /* Capacity read limit operation for RCID (closid) */
> > +               err = cbqri_bc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, closid);
> > +               if (err < 0) {
> > +                       pr_err("%s(): operation failed: err = %d", __func__, err);
> > +                       return -EIO;
> > +               }
> > +
> > +               hw_dom->ctrl_val[closid] = cbqri_get_rbwb(ctrl);
> > +
> > +               /* Convert from bandwidth blocks to percent */
> > +               rbwb = hw_dom->ctrl_val[closid];
> > +               rbwb *= 100;
> > +               percent = rbwb / ctrl->bc.nbwblks;
> > +               if (rbwb % ctrl->bc.nbwblks)
> > +                       percent++;
> 
> set: 10, get 11 ?

The intention was to handle rounding up but I can drop this increment.

[..]
> > +static int cbqri_probe_controller(struct cbqri_controller_info *ctrl_info,
> > +                                 struct cbqri_controller *ctrl)
> > +{
> > +       int err = 0, status;
> > +       u64 reg;
> > +
> > +       pr_info("controller info: type=%d addr=0x%lx size=%lu max-rcid=%u max-mcid=%u",
> > +               ctrl_info->type, ctrl_info->addr, ctrl_info->size,
> > +               ctrl_info->rcid_count, ctrl_info->mcid_count);
> > +
> > +       /* max_rmid is used by resctrl_arch_system_num_rmid_idx() */
> > +       max_rmid = ctrl_info->mcid_count;
> > +
> > +       ctrl->ctrl_info = ctrl_info;
> > +
> > +       /* Try to access the memory-mapped CBQRI registers */
> > +       if (!request_mem_region(ctrl_info->addr, ctrl_info->size, "cbqri_controller")) {
> > +               pr_warn("%s(): return %d", __func__, err);
> > +               return err;
> 
> err = 0?

Good point, I will change it to return -EBUSY.

[..]
> > +int qos_resctrl_setup(void)
> > +{
> > +       struct rdt_ctrl_domain *domain, *domain_temp;
> > +       struct cbqri_controller_info *ctrl_info;
> > +       struct cbqri_controller *ctrl;
> > +       struct cbqri_resctrl_res *res;
> > +       static int found_controllers;
> > +       int err = 0;
> > +       int id = 0;
> > +       int i;
> > +
> > +       list_for_each_entry(ctrl_info, &cbqri_controllers, list) {
> > +               err = cbqri_probe_controller(ctrl_info, &controllers[found_controllers]);
> > +               if (err) {
> > +                       pr_warn("%s(): failed (%d)", __func__, err);
> > +                       goto err_unmap_controllers;
> > +               }
> > +
> > +               found_controllers++;
> > +               if (found_controllers > MAX_CONTROLLERS) {
> > +                       pr_warn("%s(): increase MAX_CONTROLLERS value", __func__);
> > +                       break;
> > +               }
> > +       }
> > +
> > +       for (i = 0; i < RDT_NUM_RESOURCES; i++) {
> > +               res = &cbqri_resctrl_resources[i];
> > +               INIT_LIST_HEAD(&res->resctrl_res.ctrl_domains);
> > +               INIT_LIST_HEAD(&res->resctrl_res.mon_domains);
> > +               res->resctrl_res.rid = i;
> > +       }
> > +
> > +       for (i = 0; i < found_controllers; i++) {
> > +               ctrl = &controllers[i];
> 
> controllers[6] ?

This is limitation from the proof-of-concept. I need to refactor this so
that it is dynamically allocated based on the number of controllers
present in the system

Thanks,
Drew

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

* Re: [External] [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface
  2026-01-26 20:11   ` Drew Fustini
@ 2026-01-27  2:33     ` yunhui cui
  0 siblings, 0 replies; 29+ messages in thread
From: yunhui cui @ 2026-01-27  2:33 UTC (permalink / raw)
  To: Drew Fustini
  Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, Chen Pei, Liu Zhiwei,
	Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, devicetree, linux-kernel, linux-riscv, x86,
	Conor Dooley

Hi Drew,

On Tue, Jan 27, 2026 at 4:11 AM Drew Fustini <fustini@kernel.org> wrote:
>
> On Mon, Jan 26, 2026 at 09:14:24PM +0800, yunhui cui wrote:
> > 1. What about the relevant logic for mweight?
>
> My intention for this series is to just add support for functionality
> that matches the existing resctrl schemata. I think mweight could be
> added later. There is active discussion [1] about how to expand schemas
> in resctrl.

The common layer may consider adding a resource type
RDT_RESOURCE_MB_WEIGHT (similar to RDT_RESOURCE_L3), which can evolve
in tandem with resctrl in the common layer. The RISC-V QoS layer shall
implement the logic for mweight — this part is fixed, and it is
recommended to add this logic to the patchset. RBWB only provides
static capabilities, while mweight enables dynamic traffic limiting
functionality, making it quite important in terms of overall feature
support.

>
> > 2. What is the support plan for IOMMU?
>
> Similarly, I wanted to land the basic resctrl support before expanding
> to other resource types.

Alright, this part can be incorporated in once the review for the
cache/mem + ACPI patchset is nearly mature.

>
> > 3. Can we also add the patches that support RQSC to this patchset?
>
> I'm about to send it as part of v2 of this series. I removed the
> platform drivers and use to ACPI to boot the system. I will finish
> editing the cover letter and send today. The b4/ssqosid-cbqri branch
> contains what will be the v2 series.
>
> Thanks,
> Drew
>
> [1] https://lore.kernel.org/all/aXUK7XFsHl+gnwA%2F@x1/
> [2] https://github.com/tt-fustini/linux/commits/b4/ssqosid-cbqri/


Thanks,
Yunhui

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

* Re: [External] [PATCH RFC 08/19] RISC-V: QoS: add resctrl interface for CBQRI controllers
  2026-01-26 21:02     ` Drew Fustini
@ 2026-01-27 22:10       ` Drew Fustini
  0 siblings, 0 replies; 29+ messages in thread
From: Drew Fustini @ 2026-01-27 22:10 UTC (permalink / raw)
  To: yunhui cui
  Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Radim Krčmář, Samuel Holland, Adrien Ricciardi,
	Nicolas Pitre, Kornel Dulęba, Atish Patra, Atish Kumar Patra,
	Vasudevan Srinivasan, Ved Shanbhogue, Chen Pei, Liu Zhiwei,
	Weiwei Li, guo.wenjia23, liu.qingtao2, Conor Dooley,
	Krzysztof Kozlowski, Rob Herring, Reinette Chatre, Tony Luck,
	Babu Moger, Peter Newman, Fenghua Yu, James Morse, Ben Horgan,
	Dave Martin, devicetree, linux-kernel, linux-riscv, x86

On Mon, Jan 26, 2026 at 01:02:12PM -0800, Drew Fustini wrote:
> On Mon, Jan 26, 2026 at 09:01:30PM +0800, yunhui cui wrote:
> > Hi Drew,
> > 
> > On Tue, Jan 20, 2026 at 12:15 PM Drew Fustini <fustini@kernel.org> wrote:
> > >
> > > Add interface for CBQRI controller drivers to make use of the resctrl
> > > filesystem.
> > >
> > > Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
> > > Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
> > > Signed-off-by: Drew Fustini <fustini@kernel.org>
> > > ---
> > >  arch/riscv/kernel/qos/qos_resctrl.c | 1191 +++++++++++++++++++++++++++++++++++
> > >  1 file changed, 1191 insertions(+)
> > >
> > > diff --git a/arch/riscv/kernel/qos/qos_resctrl.c b/arch/riscv/kernel/qos/qos_resctrl.c
> > > new file mode 100644
> > > index 000000000000..5e3a65342e9b
> > > --- /dev/null
> > > +++ b/arch/riscv/kernel/qos/qos_resctrl.c
[..]
> > > +       case RDT_RESOURCE_MBA:
> > > +               /* Capacity read limit operation for RCID (closid) */
> > > +               err = cbqri_bc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, closid);
> > > +               if (err < 0) {
> > > +                       pr_err("%s(): operation failed: err = %d", __func__, err);
> > > +                       return -EIO;
> > > +               }
> > > +
> > > +               hw_dom->ctrl_val[closid] = cbqri_get_rbwb(ctrl);
> > > +
> > > +               /* Convert from bandwidth blocks to percent */
> > > +               rbwb = hw_dom->ctrl_val[closid];
> > > +               rbwb *= 100;
> > > +               percent = rbwb / ctrl->bc.nbwblks;
> > > +               if (rbwb % ctrl->bc.nbwblks)
> > > +                       percent++;
> > 
> > set: 10, get 11 ?
> 
> The intention was to handle rounding up but I can drop this increment.

Actually, this increment of one is necessary. Without it, the default
value of 80% will be displayed as 79%. And writing a value like 55% will
result in 54%.

# mount -t resctrl resctrl /sys/fs/resctrl
# cd /sys/fs/resctrl
# cat schemata
MB:0=79;1=79;2=79
L2:4=fff;5=fff
L3:3=ffff

# echo 'MB:2=55' > schemata
# cat schemata
MB:0=79;1=79;2=54
L2:4=fff;5=fff
L3:3=ffff

# echo 'MB:2=80' > schemata
# cat schemata
MB:0=79;1=79;2=79
L2:4=fff;5=fff
L3:3=ffff

Thanks,
Drew

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

* Re: [PATCH RFC 08/19] RISC-V: QoS: add resctrl interface for CBQRI controllers
  2026-01-20  4:14 ` [PATCH RFC 08/19] RISC-V: QoS: add resctrl interface for CBQRI controllers Drew Fustini
  2026-01-26 13:01   ` [External] " yunhui cui
@ 2026-03-26 11:05   ` guo.wenjia23
  1 sibling, 0 replies; 29+ messages in thread
From: guo.wenjia23 @ 2026-03-26 11:05 UTC (permalink / raw)
  To: fustini
  Cc: dave.martin, acpica-devel, alex, aou, aricciardi, atish.patra,
	atishp, babu.moger, ben.horgan, conor+dt, cp0613, cuiyunhui,
	devicetree, fenghua.yu, guo.wenjia23, james.morse, krzk+dt, lenb,
	linux-acpi, linux-kernel, linux-riscv, liu.qingtao2, liwei1518,
	mindal, npitre, palmer, paul.walmsley, peternewman, pjw, rafael,
	reinette.chatre, rkrcmar, robert.moore, robh, samuel.holland,
	sunilvl, tony.luck, vasu, ved, x86, zhiwei_liu

Hi Drew,

On Thu, Jan 29, 2026 at 4:28 AM Drew Fustini <fustini@kernel.org> wrote:>
> Add interface for CBQRI controller drivers to make use of the resctrl
> filesystem.
>
> Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com>
> Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com>
> Signed-off-by: Drew Fustini <fustini@kernel.org>
> ---
>  arch/riscv/kernel/qos/qos_resctrl.c | 1192 +++++++++++++++++++++++++++++++++++
>  1 file changed, 1192 insertions(+)
>
> ...
>
> +
> +int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
> +                           u32 closid, enum resctrl_conf_type t, u32 cfg_val)
> +{
> +       struct cbqri_controller *ctrl;
> +       struct cbqri_resctrl_dom *dom;
> +       struct cbqri_config cfg;
> +       int err = 0;
> +
> +       dom = container_of(d, struct cbqri_resctrl_dom, resctrl_ctrl_dom);
> +       ctrl = dom->hw_ctrl;
> +
> +       if (!r->alloc_capable)
> +               return -EINVAL;
> +
> +       switch (r->rid) {
> +       case RDT_RESOURCE_L2:
> +       case RDT_RESOURCE_L3:
> +               cfg.cbm = cfg_val;
> +               err = cbqri_apply_cache_config(dom, closid, t, &cfg);
> +               break;
> +       case RDT_RESOURCE_MBA:
> +               /* covert from percentage to bandwidth blocks */
> +               cfg.rbwb = cfg_val * ctrl->bc.nbwblks / 100;

Should use bc.mrbwb to calculate rbwb? 
I think bc.nbwblks represent the available bw blks in the controller. It should should decrease as they are allocated.

> +               err = cbqri_apply_bw_config(dom, closid, t, &cfg);
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       return err;
> +}
>
> ...
>
> +u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
> +                           u32 closid, enum resctrl_conf_type type)
> +{
> +       struct cbqri_resctrl_dom *hw_dom;
> +       struct cbqri_controller *ctrl;
> +       int reg_offset;
> +       u32 percent;
> +       u32 rbwb;
> +       u64 reg;
> +       int err;
> +
> +       hw_dom = container_of(d, struct cbqri_resctrl_dom, resctrl_ctrl_dom);
> +
> +       ctrl = hw_dom->hw_ctrl;
> +
> +       if (!r->alloc_capable)
> +               return resctrl_get_default_ctrl(r);
> +
> +       switch (r->rid) {
> +       case RDT_RESOURCE_L2:
> +       case RDT_RESOURCE_L3:
> +               /* Clear cc_block_mask before read limit operation */
> +               cbqri_set_cbm(ctrl, 0);
> +
> +               /* Capacity read limit operation for RCID (closid) */
> +               err = cbqri_cc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, type, closid);
> +               if (err < 0) {
> +                       pr_err("%s(): operation failed: err = %d", __func__, err);
> +                       return resctrl_get_default_ctrl(r);
> +               }
> +
> +               /* Read capacity block mask for RCID (closid) */
> +               reg_offset = CBQRI_CC_BLOCK_MASK_OFF;
> +               reg = ioread64(ctrl->base + reg_offset);
> +
> +               /* Update the config value for the closid in this domain */
> +               hw_dom->ctrl_val[closid] = reg;
> +               return hw_dom->ctrl_val[closid];
> +
> +       case RDT_RESOURCE_MBA:
> +               /* Capacity read limit operation for RCID (closid) */
> +               err = cbqri_bc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, closid);
> +               if (err < 0) {
> +                       pr_err("%s(): operation failed: err = %d", __func__, err);
> +                       return resctrl_get_default_ctrl(r);
> +               }
> +
> +               hw_dom->ctrl_val[closid] = cbqri_get_rbwb(ctrl);
> +
> +               /* Convert from bandwidth blocks to percent */
> +               rbwb = hw_dom->ctrl_val[closid];
> +               rbwb *= 100;
> +               percent = rbwb / ctrl->bc.nbwblks;
> +               if (rbwb % ctrl->bc.nbwblks)

Same problem.

> +                       percent++;
> +               return percent;
> +
> +       default:
> +               return resctrl_get_default_ctrl(r);
> +       }
> +}


Thank,
Wenjia

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

end of thread, other threads:[~2026-03-26 11:13 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-20  4:14 [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 01/19] dt-bindings: riscv: Add Ssqosid extension description Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 02/19] RISC-V: Detect the Ssqosid extension Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 03/19] RISC-V: Add support for srmcfg CSR from Ssqosid ext Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 04/19] RISC-V: QoS: define properties of CBQRI controllers Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 05/19] RISC-V: QoS: define CBQRI capacity and bandwidth capabilities Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 06/19] RISC-V: QoS: define CBQRI resctrl resources and domains Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 07/19] RISC-V: QoS: define prototypes for resctrl interface Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 08/19] RISC-V: QoS: add resctrl interface for CBQRI controllers Drew Fustini
2026-01-26 13:01   ` [External] " yunhui cui
2026-01-26 21:02     ` Drew Fustini
2026-01-27 22:10       ` Drew Fustini
2026-03-26 11:05   ` guo.wenjia23
2026-01-20  4:14 ` [PATCH RFC 09/19] RISC-V: QoS: expose implementation to resctrl Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 10/19] RISC-V: QoS: add late_initcall to setup resctrl interface Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 11/19] RISC-V: QoS: add to build when CONFIG_RISCV_ISA_SSQOSID set Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 12/19] RISC-V: QoS: make CONFIG_RISCV_ISA_SSQOSID select resctrl Drew Fustini
2026-01-20  4:14 ` [PATCH RFC 13/19] dt-bindings: riscv: add riscv,cbqri bindings Drew Fustini
2026-01-20  4:14 ` [PATCH NFU RFC 14/19] resctrl: riscv: add CBQRI cache controller driver Drew Fustini
2026-01-20  4:14 ` [PATCH NFU RFC 15/19] resctrl: riscv: add CBQRI bandwidth " Drew Fustini
2026-01-20  4:14 ` [PATCH NFU RFC 16/19] resctrl: riscv: build CBQRI drivers Drew Fustini
2026-01-20  4:14 ` [PATCH NFU RFC 17/19] riscv: dts: qemu: add dump from virt machine Drew Fustini
2026-01-20  4:14 ` [PATCH NFU RFC 18/19] riscv: dts: qemu: add CBQRI controller nodes Drew Fustini
2026-01-20  4:14 ` [PATCH NFU RFC 19/19] riscv: dts: build qemu dtb for CONFIG_ARCH_VIRT Drew Fustini
2026-01-22 22:31 ` [PATCH RFC 00/19] RISC-V: QoS: add CBQRI resctrl interface Reinette Chatre
2026-01-24 18:00   ` Drew Fustini
2026-01-26 13:14 ` [External] " yunhui cui
2026-01-26 20:11   ` Drew Fustini
2026-01-27  2:33     ` yunhui cui

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