* [RFC PATCH v2 1/9] riscv: implement Ssqosid extension and sqoscfg CSR
2023-04-25 20:38 [RFC PATCH v2 0/9] riscv: implement Ssqosid extension and CBQRI controllers Drew Fustini
@ 2023-04-25 20:38 ` Drew Fustini
2023-04-26 7:35 ` Weiwei Li
2023-04-25 20:38 ` [RFC PATCH v2 2/9] hw/riscv: define capabilities of CBQRI controllers Drew Fustini
` (7 subsequent siblings)
8 siblings, 1 reply; 11+ messages in thread
From: Drew Fustini @ 2023-04-25 20:38 UTC (permalink / raw)
To: Ved Shanbhogue, Palmer Dabbelt, Alistair Francis, Bin Meng,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, qemu-riscv,
qemu-devel, Nicolas Pitre, Adrien Ricciardi, Kornel Dulęba
Cc: Drew Fustini
From: Kornel Dulęba <mindal@semihalf.com>
Implement the sqoscfg CSR defined by 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
The CSR is defined for S-mode but accessing it when V=1 shall cause a
virtual instruction exception. Implement this behavior by calling the
hmode predicate.
Link: https://github.com/riscv-non-isa/riscv-cbqri/blob/main/riscv-cbqri.pdf
Signed-off-by: Kornel Dulęba <mindal@semihalf.com>
[dfustini: rebase on v8.0.50, reword commit message]
Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
Changes since v1:
- rebase on current master (v8.0.50) instead of 8.0.0-rc4
disas/riscv.c | 1 +
target/riscv/cpu.c | 2 ++
target/riscv/cpu.h | 3 +++
target/riscv/cpu_bits.h | 5 +++++
target/riscv/csr.c | 34 ++++++++++++++++++++++++++++++++++
5 files changed, 45 insertions(+)
diff --git a/disas/riscv.c b/disas/riscv.c
index d6b0fbe5e877..94336f54637b 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -2100,6 +2100,7 @@ static const char *csr_name(int csrno)
case 0x0143: return "stval";
case 0x0144: return "sip";
case 0x0180: return "satp";
+ case 0x0181: return "sqoscfg";
case 0x0200: return "hstatus";
case 0x0202: return "hedeleg";
case 0x0203: return "hideleg";
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1e97473af27b..fb3f8c43a32d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -114,6 +114,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia),
ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia),
ISA_EXT_DATA_ENTRY(sscofpmf, true, PRIV_VERSION_1_12_0, ext_sscofpmf),
+ ISA_EXT_DATA_ENTRY(ssqosid, true, PRIV_VERSION_1_12_0, ext_ssqosid),
ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc),
ISA_EXT_DATA_ENTRY(svadu, true, PRIV_VERSION_1_12_0, ext_svadu),
ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
@@ -1397,6 +1398,7 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true),
+ DEFINE_PROP_BOOL("ssqosid", RISCVCPU, cfg.ext_ssqosid, true),
DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 638e47c75a57..ffc1b5009d15 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -222,6 +222,8 @@ struct CPUArchState {
target_ulong mcause;
target_ulong mtval; /* since: priv-1.10.0 */
+ target_ulong sqoscfg;
+
/* Machine and Supervisor interrupt priorities */
uint8_t miprio[64];
uint8_t siprio[64];
@@ -454,6 +456,7 @@ struct RISCVCPUConfig {
bool ext_icboz;
bool ext_zicond;
bool ext_zihintpause;
+ bool ext_ssqosid;
bool ext_smstateen;
bool ext_sstc;
bool ext_svadu;
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index fca7ef0cef91..d11a3928735e 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -217,6 +217,7 @@
/* Supervisor Protection and Translation */
#define CSR_SPTBR 0x180
#define CSR_SATP 0x180
+#define CSR_SQOSCFG 0x181
/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
#define CSR_SISELECT 0x150
@@ -898,4 +899,8 @@ typedef enum RISCVException {
#define MHPMEVENT_IDX_MASK 0xFFFFF
#define MHPMEVENT_SSCOF_RESVD 16
+/* SQOSCFG BITS (QOSID) */
+#define SQOSCFG_RCID 0x00000FFF
+#define SQOSCFG_MCID 0x0FFF0000
+
#endif
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d522efc0b63a..5769b3545704 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2700,6 +2700,37 @@ static RISCVException write_satp(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
+static RISCVException check_sqoscfg(CPURISCVState *env, int csrno)
+{
+ RISCVCPU *cpu = env_archcpu(env);
+
+ if (!cpu->cfg.ext_ssqosid) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ /*
+ * Even though this is an S-mode CSR the spec says that we need to throw
+ * and virt instruction fault if a guest tries to access it.
+ */
+ return hmode(env, csrno);
+}
+
+static RISCVException read_sqoscfg(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ *val = env->sqoscfg;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_sqoscfg(CPURISCVState *env, int csrno,
+ target_ulong val)
+{
+ env->sqoscfg = val & (SQOSCFG_RCID | SQOSCFG_MCID);
+ return RISCV_EXCP_NONE;
+}
+
+
+
static int read_vstopi(CPURISCVState *env, int csrno, target_ulong *val)
{
int irq, ret;
@@ -4182,6 +4213,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
/* Supervisor Protection and Translation */
[CSR_SATP] = { "satp", smode, read_satp, write_satp },
+ /* Supervisor-Level Quality of Service Identifier */
+ [CSR_SQOSCFG] = { "sqoscfg", check_sqoscfg, read_sqoscfg, write_sqoscfg },
+
/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
[CSR_SISELECT] = { "siselect", aia_smode, NULL, NULL, rmw_xiselect },
[CSR_SIREG] = { "sireg", aia_smode, NULL, NULL, rmw_xireg },
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v2 1/9] riscv: implement Ssqosid extension and sqoscfg CSR
2023-04-25 20:38 ` [RFC PATCH v2 1/9] riscv: implement Ssqosid extension and sqoscfg CSR Drew Fustini
@ 2023-04-26 7:35 ` Weiwei Li
0 siblings, 0 replies; 11+ messages in thread
From: Weiwei Li @ 2023-04-26 7:35 UTC (permalink / raw)
To: Drew Fustini, Ved Shanbhogue, Palmer Dabbelt, Alistair Francis,
Bin Meng, Daniel Henrique Barboza, Liu Zhiwei, qemu-riscv,
qemu-devel, Nicolas Pitre, Adrien Ricciardi, Kornel Dulęba
Cc: liweiwei
On 2023/4/26 04:38, Drew Fustini wrote:
> From: Kornel Dulęba <mindal@semihalf.com>
>
> Implement the sqoscfg CSR defined by 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
>
> The CSR is defined for S-mode but accessing it when V=1 shall cause a
> virtual instruction exception. Implement this behavior by calling the
> hmode predicate.
>
> Link: https://github.com/riscv-non-isa/riscv-cbqri/blob/main/riscv-cbqri.pdf
> Signed-off-by: Kornel Dulęba <mindal@semihalf.com>
> [dfustini: rebase on v8.0.50, reword commit message]
> Signed-off-by: Drew Fustini <dfustini@baylibre.com>
> ---
> Changes since v1:
> - rebase on current master (v8.0.50) instead of 8.0.0-rc4
>
> disas/riscv.c | 1 +
> target/riscv/cpu.c | 2 ++
> target/riscv/cpu.h | 3 +++
> target/riscv/cpu_bits.h | 5 +++++
> target/riscv/csr.c | 34 ++++++++++++++++++++++++++++++++++
> 5 files changed, 45 insertions(+)
>
> diff --git a/disas/riscv.c b/disas/riscv.c
> index d6b0fbe5e877..94336f54637b 100644
> --- a/disas/riscv.c
> +++ b/disas/riscv.c
> @@ -2100,6 +2100,7 @@ static const char *csr_name(int csrno)
> case 0x0143: return "stval";
> case 0x0144: return "sip";
> case 0x0180: return "satp";
> + case 0x0181: return "sqoscfg";
> case 0x0200: return "hstatus";
> case 0x0202: return "hedeleg";
> case 0x0203: return "hideleg";
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 1e97473af27b..fb3f8c43a32d 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -114,6 +114,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
> ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia),
> ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia),
> ISA_EXT_DATA_ENTRY(sscofpmf, true, PRIV_VERSION_1_12_0, ext_sscofpmf),
> + ISA_EXT_DATA_ENTRY(ssqosid, true, PRIV_VERSION_1_12_0, ext_ssqosid),
> ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc),
> ISA_EXT_DATA_ENTRY(svadu, true, PRIV_VERSION_1_12_0, ext_svadu),
> ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
> @@ -1397,6 +1398,7 @@ static Property riscv_cpu_extensions[] = {
>
> DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true),
>
> + DEFINE_PROP_BOOL("ssqosid", RISCVCPU, cfg.ext_ssqosid, true),
> DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
> DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
> DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 638e47c75a57..ffc1b5009d15 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -222,6 +222,8 @@ struct CPUArchState {
> target_ulong mcause;
> target_ulong mtval; /* since: priv-1.10.0 */
>
> + target_ulong sqoscfg;
> +
> /* Machine and Supervisor interrupt priorities */
> uint8_t miprio[64];
> uint8_t siprio[64];
> @@ -454,6 +456,7 @@ struct RISCVCPUConfig {
> bool ext_icboz;
> bool ext_zicond;
> bool ext_zihintpause;
> + bool ext_ssqosid;
> bool ext_smstateen;
> bool ext_sstc;
> bool ext_svadu;
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index fca7ef0cef91..d11a3928735e 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -217,6 +217,7 @@
> /* Supervisor Protection and Translation */
> #define CSR_SPTBR 0x180
> #define CSR_SATP 0x180
> +#define CSR_SQOSCFG 0x181
>
> /* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
> #define CSR_SISELECT 0x150
> @@ -898,4 +899,8 @@ typedef enum RISCVException {
> #define MHPMEVENT_IDX_MASK 0xFFFFF
> #define MHPMEVENT_SSCOF_RESVD 16
>
> +/* SQOSCFG BITS (QOSID) */
> +#define SQOSCFG_RCID 0x00000FFF
> +#define SQOSCFG_MCID 0x0FFF0000
> +
> #endif
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index d522efc0b63a..5769b3545704 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -2700,6 +2700,37 @@ static RISCVException write_satp(CPURISCVState *env, int csrno,
> return RISCV_EXCP_NONE;
> }
>
> +static RISCVException check_sqoscfg(CPURISCVState *env, int csrno)
> +{
> + RISCVCPU *cpu = env_archcpu(env);
> +
> + if (!cpu->cfg.ext_ssqosid) {
> + return RISCV_EXCP_ILLEGAL_INST;
> + }
> +
> + /*
> + * Even though this is an S-mode CSR the spec says that we need to throw
> + * and virt instruction fault if a guest tries to access it.
> + */
> + return hmode(env, csrno);
If above comments is true, use hmode() here is not right, since it only
check whether H extension is supported.
It need another check for guest mode access. And we should use smode()
instead of hmode() here.
> +}
> +
> +static RISCVException read_sqoscfg(CPURISCVState *env, int csrno,
> + target_ulong *val)
'target_ulong' is better to align with 'CPURISCVState'.
Regards,
Weiwei Li
> +{
> + *val = env->sqoscfg;
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_sqoscfg(CPURISCVState *env, int csrno,
> + target_ulong val)
> +{
> + env->sqoscfg = val & (SQOSCFG_RCID | SQOSCFG_MCID);
> + return RISCV_EXCP_NONE;
> +}
> +
> +
> +
> static int read_vstopi(CPURISCVState *env, int csrno, target_ulong *val)
> {
> int irq, ret;
> @@ -4182,6 +4213,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> /* Supervisor Protection and Translation */
> [CSR_SATP] = { "satp", smode, read_satp, write_satp },
>
> + /* Supervisor-Level Quality of Service Identifier */
> + [CSR_SQOSCFG] = { "sqoscfg", check_sqoscfg, read_sqoscfg, write_sqoscfg },
> +
> /* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
> [CSR_SISELECT] = { "siselect", aia_smode, NULL, NULL, rmw_xiselect },
> [CSR_SIREG] = { "sireg", aia_smode, NULL, NULL, rmw_xireg },
^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH v2 2/9] hw/riscv: define capabilities of CBQRI controllers
2023-04-25 20:38 [RFC PATCH v2 0/9] riscv: implement Ssqosid extension and CBQRI controllers Drew Fustini
2023-04-25 20:38 ` [RFC PATCH v2 1/9] riscv: implement Ssqosid extension and sqoscfg CSR Drew Fustini
@ 2023-04-25 20:38 ` Drew Fustini
2023-04-25 20:38 ` [RFC PATCH v2 3/9] hw/riscv: implement CBQRI capacity controller Drew Fustini
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Drew Fustini @ 2023-04-25 20:38 UTC (permalink / raw)
To: Ved Shanbhogue, Palmer Dabbelt, Alistair Francis, Bin Meng,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, qemu-riscv,
qemu-devel, Nicolas Pitre, Adrien Ricciardi, Kornel Dulęba
Cc: Drew Fustini
From: Nicolas Pitre <npitre@baylibre.com>
Define structs to represent the hardware capabilities of capacity and
bandwidth controllers according to the RISC-V Capacity and Bandwidth QoS
Register Interface (CBQRI).
Link: https://github.com/riscv-non-isa/riscv-cbqri/blob/main/riscv-cbqri.pdf
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
Changes since v1:
- Move defines TYPE_RISCV_CBQRI_CC from cbqri_capacity.c and
TYPE_RISCV_CBQRI_BC from cbqri_bandwidth.c into include/hw/riscv.h
so machines can include it (suggested by Alistair)
include/hw/riscv/cbqri.h | 81 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
create mode 100644 include/hw/riscv/cbqri.h
diff --git a/include/hw/riscv/cbqri.h b/include/hw/riscv/cbqri.h
new file mode 100644
index 000000000000..8e1399994368
--- /dev/null
+++ b/include/hw/riscv/cbqri.h
@@ -0,0 +1,81 @@
+/*
+ * RISC-V Capacity and Bandwidth QoS Register Interface
+ * URL: https://github.com/riscv-non-isa/riscv-cbqri
+ *
+ * Copyright (c) 2023 BayLibre SAS
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_RISCV_CBQRI_H
+#define HW_RISCV_CBQRI_H
+
+#include "qemu/typedefs.h"
+
+#define RISCV_CBQRI_VERSION_MAJOR 0
+#define RISCV_CBQRI_VERSION_MINOR 1
+
+#define TYPE_RISCV_CBQRI_CC "riscv.cbqri.capacity"
+#define TYPE_RISCV_CBQRI_BC "riscv.cbqri.bandwidth"
+
+/* Capacity Controller hardware capabilities */
+typedef struct RiscvCbqriCapacityCaps {
+ uint16_t nb_mcids;
+ uint16_t nb_rcids;
+
+ uint16_t ncblks;
+
+ bool supports_at_data:1;
+ bool supports_at_code:1;
+
+ bool supports_alloc_op_config_limit:1;
+ bool supports_alloc_op_read_limit:1;
+ bool supports_alloc_op_flush_rcid:1;
+
+ bool supports_mon_op_config_event:1;
+ bool supports_mon_op_read_counter:1;
+
+ bool supports_mon_evt_id_none:1;
+ bool supports_mon_evt_id_occupancy:1;
+} RiscvCbqriCapacityCaps;
+
+/* Bandwidth Controller hardware capabilities */
+typedef struct RiscvCbqriBandwidthCaps {
+ uint16_t nb_mcids;
+ uint16_t nb_rcids;
+
+ uint16_t nbwblks;
+ uint16_t mrbwb;
+
+ bool supports_at_data:1;
+ bool supports_at_code:1;
+
+ bool supports_alloc_op_config_limit:1;
+ bool supports_alloc_op_read_limit:1;
+
+ bool supports_mon_op_config_event:1;
+ bool supports_mon_op_read_counter:1;
+
+ bool supports_mon_evt_id_none:1;
+ bool supports_mon_evt_id_rdwr_count:1;
+ bool supports_mon_evt_id_rdonly_count:1;
+ bool supports_mon_evt_id_wronly_count:1;
+} RiscvCbqriBandwidthCaps;
+
+DeviceState *riscv_cbqri_cc_create(hwaddr addr,
+ const RiscvCbqriCapacityCaps *caps,
+ const char *target_name);
+DeviceState *riscv_cbqri_bc_create(hwaddr addr,
+ const RiscvCbqriBandwidthCaps *caps,
+ const char *target_name);
+#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v2 3/9] hw/riscv: implement CBQRI capacity controller
2023-04-25 20:38 [RFC PATCH v2 0/9] riscv: implement Ssqosid extension and CBQRI controllers Drew Fustini
2023-04-25 20:38 ` [RFC PATCH v2 1/9] riscv: implement Ssqosid extension and sqoscfg CSR Drew Fustini
2023-04-25 20:38 ` [RFC PATCH v2 2/9] hw/riscv: define capabilities of CBQRI controllers Drew Fustini
@ 2023-04-25 20:38 ` Drew Fustini
2023-04-25 20:38 ` [RFC PATCH v2 4/9] hw/riscv: implement CBQRI bandwidth controller Drew Fustini
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Drew Fustini @ 2023-04-25 20:38 UTC (permalink / raw)
To: Ved Shanbhogue, Palmer Dabbelt, Alistair Francis, Bin Meng,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, qemu-riscv,
qemu-devel, Nicolas Pitre, Adrien Ricciardi, Kornel Dulęba
Cc: Drew Fustini
From: Nicolas Pitre <npitre@baylibre.com>
Implement a capacity controller according to the Capacity and Bandwidth
QoS Register Interface (CBQRI) which supports these capabilities:
- 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
Link: https://github.com/riscv-non-isa/riscv-cbqri/blob/main/riscv-cbqri.pdf
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
Changes since v1:
- Move TYPE_RISCV_CBQRI_CC to include/hw/riscv/cbqri.h so that machines
can use it (suggested by Alistair)
- Add device properties so that the capacity controller can be fully
configured from the command line
hw/riscv/cbqri_capacity.c | 614 ++++++++++++++++++++++++++++++++++++++
1 file changed, 614 insertions(+)
create mode 100644 hw/riscv/cbqri_capacity.c
diff --git a/hw/riscv/cbqri_capacity.c b/hw/riscv/cbqri_capacity.c
new file mode 100644
index 000000000000..db11a3c3fc5d
--- /dev/null
+++ b/hw/riscv/cbqri_capacity.c
@@ -0,0 +1,614 @@
+/*
+ * RISC-V Capacity and Bandwidth QoS Register Interface
+ * URL: https://github.com/riscv-non-isa/riscv-cbqri
+ *
+ * Copyright (c) 2023 BayLibre SAS
+ *
+ * This file contains the Capacity-controller QoS Register Interface.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/bitmap.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/cbqri.h"
+
+/* Encodings of `AT` field */
+enum {
+ CC_AT_DATA = 0,
+ CC_AT_CODE = 1,
+};
+
+/* Capabilities */
+REG64(CC_CAPABILITIES, 0);
+FIELD(CC_CAPABILITIES, VER, 0, 8);
+FIELD(CC_CAPABILITIES, VER_MINOR, 0, 4);
+FIELD(CC_CAPABILITIES, VER_MAJOR, 4, 4);
+FIELD(CC_CAPABILITIES, NCBLKS, 8, 16);
+FIELD(CC_CAPABILITIES, FRCID, 24, 1);
+
+/* Usage monitoring control */
+REG64(CC_MON_CTL, 8);
+FIELD(CC_MON_CTL, OP, 0, 5);
+FIELD(CC_MON_CTL, AT, 5, 3);
+FIELD(CC_MON_CTL, MCID, 8, 12);
+FIELD(CC_MON_CTL, EVT_ID, 20, 8);
+FIELD(CC_MON_CTL, ATV, 28, 1);
+FIELD(CC_MON_CTL, STATUS, 32, 7);
+FIELD(CC_MON_CTL, BUSY, 39, 1);
+
+/* Usage monitoring operations */
+enum {
+ CC_MON_OP_CONFIG_EVENT = 1,
+ CC_MON_OP_READ_COUNTER = 2,
+};
+
+/* Usage monitoring event ID */
+enum {
+ CC_EVT_ID_None = 0,
+ CC_EVT_ID_Occupancy = 1,
+};
+
+/* CC_MON_CTL.STATUS field encodings */
+enum {
+ CC_MON_CTL_STATUS_SUCCESS = 1,
+ CC_MON_CTL_STATUS_INVAL_OP = 2,
+ CC_MON_CTL_STATUS_INVAL_MCID = 3,
+ CC_MON_CTL_STATUS_INVAL_EVT_ID = 4,
+ CC_MON_CTL_STATUS_INVAL_AT = 5,
+};
+
+/* Monitoring counter value */
+REG64(CC_MON_CTR_VAL, 16);
+FIELD(CC_MON_CTR_VAL, CTR, 0, 63);
+FIELD(CC_MON_CTR_VAL, INVALID, 63, 1);
+
+/* Capacity allocation control */
+REG64(CC_ALLOC_CTL, 24);
+FIELD(CC_ALLOC_CTL, OP, 0, 5);
+FIELD(CC_ALLOC_CTL, AT, 5, 3);
+FIELD(CC_ALLOC_CTL, RCID, 8, 12);
+FIELD(CC_ALLOC_CTL, STATUS, 32, 7);
+FIELD(CC_ALLOC_CTL, BUSY, 39, 1);
+
+/* Capacity allocation operations */
+enum {
+ CC_ALLOC_OP_CONFIG_LIMIT = 1,
+ CC_ALLOC_OP_READ_LIMIT = 2,
+ CC_ALLOC_OP_FLUSH_RCID = 3,
+};
+
+/* CC_ALLOC_CTL.STATUS field encodings */
+enum {
+ CC_ALLOC_STATUS_SUCCESS = 1,
+ CC_ALLOC_STATUS_INVAL_OP = 2,
+ CC_ALLOC_STATUS_INVAL_RCID = 3,
+ CC_ALLOC_STATUS_INVAL_AT = 4,
+ CC_ALLOC_STATUS_INVAL_BLKMASK = 5,
+};
+
+REG64(CC_BLOCK_MASK, 32);
+
+
+typedef struct MonitorCounter {
+ uint64_t ctr_val;
+ int at;
+ int evt_id;
+ bool active;
+} MonitorCounter;
+
+typedef struct RiscvCbqriCapacityState {
+ SysBusDevice parent_obj;
+ MemoryRegion mmio;
+
+ /* cached value of some registers */
+ uint64_t cc_mon_ctl;
+ uint64_t cc_mon_ctr_val;
+ uint64_t cc_alloc_ctl;
+
+ /* monitoring counters */
+ MonitorCounter *mon_counters;
+
+ /* allocation blockmasks (1st one is the CC_BLOCK_MASK register) */
+ uint64_t *alloc_blockmasks;
+
+ /* properties */
+
+ uint64_t mmio_base;
+ char *target;
+ uint16_t nb_mcids;
+ uint16_t nb_rcids;
+
+ uint16_t ncblks;
+
+ bool supports_at_data;
+ bool supports_at_code;
+
+ bool supports_alloc_op_config_limit;
+ bool supports_alloc_op_read_limit;
+ bool supports_alloc_op_flush_rcid;
+
+ bool supports_mon_op_config_event;
+ bool supports_mon_op_read_counter;
+
+ bool supports_mon_evt_id_none;
+ bool supports_mon_evt_id_occupancy;
+} RiscvCbqriCapacityState;
+
+#define RISCV_CBQRI_CC(obj) \
+ OBJECT_CHECK(RiscvCbqriCapacityState, (obj), TYPE_RISCV_CBQRI_CC)
+
+static uint64_t *get_blockmask_location(RiscvCbqriCapacityState *cc,
+ uint32_t rcid, uint32_t at)
+{
+ /*
+ * All blockmasks are contiguous to simplify allocation.
+ * The first one is used to hold the CC_BLOCK_MASK register content,
+ * followed by respective blockmasks for each AT per RCID.
+ * Each blockmask is made of one or more uint64_t "slots".
+ */
+ unsigned int nb_ats = 0;
+ nb_ats += !!cc->supports_at_data;
+ nb_ats += !!cc->supports_at_code;
+ nb_ats = MAX(nb_ats, 1);
+ assert(at < nb_ats);
+
+ unsigned int blockmask_slots = (cc->ncblks + 63) / 64;
+ unsigned int blockmask_offset = blockmask_slots * (1 + rcid * nb_ats + at);
+
+ return cc->alloc_blockmasks + blockmask_offset;
+}
+
+static uint32_t alloc_blockmask_config(RiscvCbqriCapacityState *cc,
+ uint32_t rcid, uint32_t at,
+ bool *busy)
+{
+ unsigned int blockmask_slots = (cc->ncblks + 63) / 64;
+
+ if ((cc->ncblks % 64) != 0) {
+ /* make sure provided mask isn't too large */
+ uint64_t tail = cc->alloc_blockmasks[blockmask_slots - 1];
+ if ((tail >> (cc->ncblks % 64)) != 0) {
+ return CC_ALLOC_STATUS_INVAL_BLKMASK;
+ }
+ }
+
+ /* for now we only preserve the current CC_BLOCK_MASK register content */
+ memcpy(get_blockmask_location(cc, rcid, at),
+ cc->alloc_blockmasks, blockmask_slots * 8);
+ return CC_ALLOC_STATUS_SUCCESS;
+}
+
+static uint32_t alloc_blockmask_read(RiscvCbqriCapacityState *cc,
+ uint32_t rcid, uint32_t at,
+ bool *busy)
+{
+ unsigned int blockmask_slots = (cc->ncblks + 63) / 64;
+
+ memcpy(cc->alloc_blockmasks,
+ get_blockmask_location(cc, rcid, at),
+ blockmask_slots * 8);
+ return CC_ALLOC_STATUS_SUCCESS;
+}
+
+static uint32_t alloc_blockmask_init(RiscvCbqriCapacityState *cc,
+ uint32_t rcid, uint32_t at, bool set,
+ bool *busy)
+{
+ void *blockmask = get_blockmask_location(cc, rcid, at);
+
+ if (set) {
+ bitmap_fill(blockmask, cc->ncblks);
+ } else {
+ bitmap_zero(blockmask, cc->ncblks);
+ }
+ return CC_ALLOC_STATUS_SUCCESS;
+}
+
+static bool is_valid_at(RiscvCbqriCapacityState *cc, uint32_t at)
+{
+ switch (at) {
+ case CC_AT_DATA:
+ return cc->supports_at_data;
+ case CC_AT_CODE:
+ return cc->supports_at_code;
+ default:
+ return false;
+ }
+}
+
+static void riscv_cbqri_cc_write_mon_ctl(RiscvCbqriCapacityState *cc,
+ uint64_t value)
+{
+ if (!cc->supports_mon_op_config_event &&
+ !cc->supports_mon_op_read_counter) {
+ /* monitoring not supported: leave mon_ctl set to 0 */
+ return;
+ }
+
+ /* extract writable fields */
+ uint32_t op = FIELD_EX64(value, CC_MON_CTL, OP);
+ uint32_t at = FIELD_EX64(value, CC_MON_CTL, AT);
+ uint32_t mcid = FIELD_EX64(value, CC_MON_CTL, MCID);
+ uint32_t evt_id = FIELD_EX64(value, CC_MON_CTL, EVT_ID);
+ bool atv = FIELD_EX64(value, CC_MON_CTL, ATV);
+
+ /* extract read-only fields */
+ uint32_t status = FIELD_EX64(cc->cc_mon_ctl, CC_MON_CTL, STATUS);
+ bool busy = FIELD_EX64(cc->cc_mon_ctl, CC_MON_CTL, BUSY);
+
+ if (busy) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: busy flag still set, ignored",
+ __func__);
+ return;
+ }
+
+ if (!cc->supports_at_data &&
+ !cc->supports_at_code) {
+ /* AT not supported: hardwire to 0 */
+ at = 0;
+ atv = false;
+ }
+
+ if (mcid >= cc->nb_mcids) {
+ status = CC_MON_CTL_STATUS_INVAL_MCID;
+ } else if (op == CC_MON_OP_CONFIG_EVENT &&
+ cc->supports_mon_op_config_event) {
+ if (evt_id == CC_EVT_ID_None &&
+ cc->supports_mon_evt_id_none) {
+ cc->mon_counters[mcid].active = false;
+ status = CC_MON_CTL_STATUS_SUCCESS;
+ } else if (evt_id == CC_EVT_ID_Occupancy &&
+ cc->supports_mon_evt_id_occupancy) {
+ if (atv && !is_valid_at(cc, at)) {
+ status = CC_MON_CTL_STATUS_INVAL_AT;
+ } else {
+ cc->mon_counters[mcid].ctr_val =
+ FIELD_DP64(0, CC_MON_CTR_VAL, INVALID, 1);
+ cc->mon_counters[mcid].evt_id = evt_id;
+ cc->mon_counters[mcid].at = atv ? at : -1;
+ cc->mon_counters[mcid].active = true;
+ status = CC_MON_CTL_STATUS_SUCCESS;
+ }
+ } else {
+ status = CC_MON_CTL_STATUS_INVAL_EVT_ID;
+ }
+ } else if (op == CC_MON_OP_READ_COUNTER &&
+ cc->supports_mon_op_read_counter) {
+ cc->cc_mon_ctr_val = cc->mon_counters[mcid].ctr_val;
+ status = CC_MON_CTL_STATUS_SUCCESS;
+ } else {
+ status = CC_MON_CTL_STATUS_INVAL_OP;
+ }
+
+ /* reconstruct updated register value */
+ value = 0;
+ value = FIELD_DP64(value, CC_MON_CTL, OP, op);
+ value = FIELD_DP64(value, CC_MON_CTL, AT, at);
+ value = FIELD_DP64(value, CC_MON_CTL, MCID, mcid);
+ value = FIELD_DP64(value, CC_MON_CTL, EVT_ID, evt_id);
+ value = FIELD_DP64(value, CC_MON_CTL, ATV, atv);
+ value = FIELD_DP64(value, CC_MON_CTL, STATUS, status);
+ value = FIELD_DP64(value, CC_MON_CTL, BUSY, busy);
+ cc->cc_mon_ctl = value;
+}
+
+static void riscv_cbqri_cc_write_alloc_ctl(RiscvCbqriCapacityState *cc,
+ uint64_t value)
+{
+ if (cc->ncblks == 0 ||
+ (!cc->supports_alloc_op_config_limit &&
+ !cc->supports_alloc_op_read_limit &&
+ !cc->supports_alloc_op_flush_rcid)) {
+ /* capacity allocation not supported: leave alloc_ctl set to 0 */
+ return;
+ }
+
+ /* extract writable fields */
+ uint32_t op = FIELD_EX64(value, CC_ALLOC_CTL, OP);
+ uint32_t at = FIELD_EX64(value, CC_ALLOC_CTL, AT);
+ uint32_t rcid = FIELD_EX64(value, CC_ALLOC_CTL, RCID);
+
+ /* extract read-only fields */
+ uint32_t status = FIELD_EX64(cc->cc_alloc_ctl, CC_ALLOC_CTL, STATUS);
+ bool busy = FIELD_EX64(cc->cc_alloc_ctl, CC_ALLOC_CTL, BUSY);
+
+ if (busy) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: busy flag still set, ignored",
+ __func__);
+ return;
+ }
+
+ bool atv = true;
+ if (!cc->supports_at_data &&
+ !cc->supports_at_code) {
+ /* AT not supported: hardwire to 0 */
+ at = 0;
+ atv = false;
+ }
+
+ if (rcid >= cc->nb_rcids) {
+ status = CC_ALLOC_STATUS_INVAL_RCID;
+ } else if (atv && !is_valid_at(cc, at)) {
+ status = CC_ALLOC_STATUS_INVAL_AT;
+ } else if (op == CC_ALLOC_OP_CONFIG_LIMIT &&
+ cc->supports_alloc_op_config_limit) {
+ status = alloc_blockmask_config(cc, rcid, at, &busy);
+ } else if (op == CC_ALLOC_OP_READ_LIMIT &&
+ cc->supports_alloc_op_read_limit) {
+ status = alloc_blockmask_read(cc, rcid, at, &busy);
+ } else if (op == CC_ALLOC_OP_FLUSH_RCID &&
+ cc->supports_alloc_op_flush_rcid) {
+ status = alloc_blockmask_init(cc, rcid, at, false, &busy);
+ } else {
+ status = CC_ALLOC_STATUS_INVAL_OP;
+ }
+
+ /* reconstruct updated register value */
+ value = 0;
+ value = FIELD_DP64(value, CC_ALLOC_CTL, OP, op);
+ value = FIELD_DP64(value, CC_ALLOC_CTL, AT, at);
+ value = FIELD_DP64(value, CC_ALLOC_CTL, RCID, rcid);
+ value = FIELD_DP64(value, CC_ALLOC_CTL, STATUS, status);
+ value = FIELD_DP64(value, CC_ALLOC_CTL, BUSY, busy);
+ cc->cc_alloc_ctl = value;
+}
+
+static void riscv_cbqri_cc_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned size)
+{
+ RiscvCbqriCapacityState *cc = opaque;
+
+ assert((addr % 8) == 0);
+ assert(size == 8);
+
+ switch (addr) {
+ case A_CC_CAPABILITIES:
+ /* read-only register */
+ break;
+ case A_CC_MON_CTL:
+ riscv_cbqri_cc_write_mon_ctl(cc, value);
+ break;
+ case A_CC_ALLOC_CTL:
+ riscv_cbqri_cc_write_alloc_ctl(cc, value);
+ break;
+ case A_CC_MON_CTR_VAL:
+ /* read-only register */
+ break;
+ case A_CC_BLOCK_MASK:
+ if (cc->ncblks == 0) {
+ break;
+ }
+ /* fallthrough */
+ default:
+ uint32_t blkmask_slot = (addr - A_CC_BLOCK_MASK) / 8;
+ if (blkmask_slot >= (cc->ncblks + 63) / 64) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: out of bounds (addr=0x%x)",
+ __func__, (uint32_t)addr);
+ break;
+ }
+ cc->alloc_blockmasks[blkmask_slot] = value;
+ }
+}
+
+static uint64_t riscv_cbqri_cc_read(void *opaque, hwaddr addr, unsigned size)
+{
+ RiscvCbqriCapacityState *cc = opaque;
+ uint64_t value = 0;
+
+ assert((addr % 8) == 0);
+ assert(size == 8);
+
+ switch (addr) {
+ case A_CC_CAPABILITIES:
+ value = FIELD_DP64(value, CC_CAPABILITIES, VER_MAJOR,
+ RISCV_CBQRI_VERSION_MAJOR);
+ value = FIELD_DP64(value, CC_CAPABILITIES, VER_MINOR,
+ RISCV_CBQRI_VERSION_MINOR);
+ value = FIELD_DP64(value, CC_CAPABILITIES, NCBLKS,
+ cc->ncblks);
+ value = FIELD_DP64(value, CC_CAPABILITIES, FRCID,
+ cc->supports_alloc_op_flush_rcid);
+ break;
+ case A_CC_MON_CTL:
+ value = cc->cc_mon_ctl;
+ break;
+ case A_CC_ALLOC_CTL:
+ value = cc->cc_alloc_ctl;
+ break;
+ case A_CC_MON_CTR_VAL:
+ value = cc->cc_mon_ctr_val;
+ break;
+ case A_CC_BLOCK_MASK:
+ if (cc->ncblks == 0) {
+ break;
+ }
+ /* fallthrough */
+ default:
+ unsigned int blkmask_slot = (addr - A_CC_BLOCK_MASK) / 8;
+ if (blkmask_slot >= (cc->ncblks + 63) / 64) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: out of bounds (addr=0x%x)",
+ __func__, (uint32_t)addr);
+ break;
+ }
+ value = cc->alloc_blockmasks[blkmask_slot];
+ }
+
+ return value;
+}
+
+static const MemoryRegionOps riscv_cbqri_cc_ops = {
+ .read = riscv_cbqri_cc_read,
+ .write = riscv_cbqri_cc_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 8,
+ .impl.min_access_size = 8,
+ .impl.max_access_size = 8,
+};
+
+static void riscv_cbqri_cc_realize(DeviceState *dev, Error **errp)
+{
+ RiscvCbqriCapacityState *cc = RISCV_CBQRI_CC(dev);
+
+ if (!cc->mmio_base) {
+ error_setg(errp, "mmio_base property not set");
+ return;
+ }
+
+ assert(cc->mon_counters == NULL);
+ cc->mon_counters = g_new0(MonitorCounter, cc->nb_mcids);
+
+ assert(cc->alloc_blockmasks == NULL);
+ uint64_t *end = get_blockmask_location(cc, cc->nb_rcids, 0);
+ unsigned int blockmasks_size = end - cc->alloc_blockmasks;
+ cc->alloc_blockmasks = g_new0(uint64_t, blockmasks_size);
+
+ memory_region_init_io(&cc->mmio, OBJECT(dev), &riscv_cbqri_cc_ops,
+ cc, TYPE_RISCV_CBQRI_CC".mmio", 4 * 1024);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &cc->mmio);
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, cc->mmio_base);
+}
+
+static void riscv_cbqri_cc_reset(DeviceState *dev)
+{
+ RiscvCbqriCapacityState *cc = RISCV_CBQRI_CC(dev);
+
+ cc->cc_mon_ctl = 0;
+ cc->cc_alloc_ctl = 0;
+
+ /* assign all capacity only to rcid0 */
+ for (unsigned int rcid = 0; rcid < cc->nb_rcids; rcid++) {
+ bool any_at = false;
+
+ if (cc->supports_at_data) {
+ alloc_blockmask_init(cc, rcid, CC_AT_DATA,
+ rcid == 0, NULL);
+ any_at = true;
+ }
+ if (cc->supports_at_code) {
+ alloc_blockmask_init(cc, rcid, CC_AT_CODE,
+ rcid == 0, NULL);
+ any_at = true;
+ }
+ if (!any_at) {
+ alloc_blockmask_init(cc, rcid, 0,
+ rcid == 0, NULL);
+ }
+ }
+}
+
+static Property riscv_cbqri_cc_properties[] = {
+ DEFINE_PROP_UINT64("mmio_base", RiscvCbqriCapacityState, mmio_base, 0),
+ DEFINE_PROP_STRING("target", RiscvCbqriCapacityState, target),
+
+ DEFINE_PROP_UINT16("max_mcids", RiscvCbqriCapacityState, nb_mcids, 256),
+ DEFINE_PROP_UINT16("max_rcids", RiscvCbqriCapacityState, nb_rcids, 64),
+ DEFINE_PROP_UINT16("ncblks", RiscvCbqriCapacityState, ncblks, 16),
+
+ DEFINE_PROP_BOOL("at_data", RiscvCbqriCapacityState,
+ supports_at_data, true),
+ DEFINE_PROP_BOOL("at_code", RiscvCbqriCapacityState,
+ supports_at_code, true),
+
+ DEFINE_PROP_BOOL("alloc_op_config_limit", RiscvCbqriCapacityState,
+ supports_alloc_op_config_limit, true),
+ DEFINE_PROP_BOOL("alloc_op_read_limit", RiscvCbqriCapacityState,
+ supports_alloc_op_read_limit, true),
+ DEFINE_PROP_BOOL("alloc_op_flush_rcid", RiscvCbqriCapacityState,
+ supports_alloc_op_flush_rcid, true),
+
+ DEFINE_PROP_BOOL("mon_op_config_event", RiscvCbqriCapacityState,
+ supports_mon_op_config_event, true),
+ DEFINE_PROP_BOOL("mon_op_read_counter", RiscvCbqriCapacityState,
+ supports_mon_op_read_counter, true),
+
+ DEFINE_PROP_BOOL("mon_evt_id_none", RiscvCbqriCapacityState,
+ supports_mon_evt_id_none, true),
+ DEFINE_PROP_BOOL("mon_evt_id_occupancy", RiscvCbqriCapacityState,
+ supports_mon_evt_id_occupancy, true),
+
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void riscv_cbqri_cc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->realize = riscv_cbqri_cc_realize;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->desc = "RISC-V CBQRI Capacity Controller";
+ device_class_set_props(dc, riscv_cbqri_cc_properties);
+ dc->reset = riscv_cbqri_cc_reset;
+ dc->user_creatable = true;
+}
+
+static const TypeInfo riscv_cbqri_cc_info = {
+ .name = TYPE_RISCV_CBQRI_CC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(RiscvCbqriCapacityState),
+ .class_init = riscv_cbqri_cc_class_init,
+};
+
+static void riscv_cbqri_cc_register_types(void)
+{
+ type_register_static(&riscv_cbqri_cc_info);
+}
+
+DeviceState *riscv_cbqri_cc_create(hwaddr addr,
+ const RiscvCbqriCapacityCaps *caps,
+ const char *target_name)
+{
+ DeviceState *dev = qdev_new(TYPE_RISCV_CBQRI_CC);
+
+ qdev_prop_set_uint64(dev, "mmio_base", addr);
+ qdev_prop_set_string(dev, "target", target_name);
+ qdev_prop_set_uint16(dev, "max_mcids", caps->nb_mcids);
+ qdev_prop_set_uint16(dev, "max_rcids", caps->nb_rcids);
+ qdev_prop_set_uint16(dev, "ncblks", caps->ncblks);
+
+ qdev_prop_set_bit(dev, "at_data",
+ caps->supports_at_data);
+ qdev_prop_set_bit(dev, "at_code",
+ caps->supports_at_code);
+ qdev_prop_set_bit(dev, "alloc_op_config_limit",
+ caps->supports_alloc_op_config_limit);
+ qdev_prop_set_bit(dev, "alloc_op_read_limit",
+ caps->supports_alloc_op_read_limit);
+ qdev_prop_set_bit(dev, "alloc_op_flush_rcid",
+ caps->supports_alloc_op_flush_rcid);
+ qdev_prop_set_bit(dev, "mon_op_config_event",
+ caps->supports_mon_op_config_event);
+ qdev_prop_set_bit(dev, "mon_op_read_counter",
+ caps->supports_mon_op_read_counter);
+ qdev_prop_set_bit(dev, "mon_evt_id_none",
+ caps->supports_mon_evt_id_none);
+ qdev_prop_set_bit(dev, "mon_evt_id_occupancy",
+ caps->supports_mon_evt_id_occupancy);
+
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+
+ return dev;
+}
+
+type_init(riscv_cbqri_cc_register_types)
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v2 4/9] hw/riscv: implement CBQRI bandwidth controller
2023-04-25 20:38 [RFC PATCH v2 0/9] riscv: implement Ssqosid extension and CBQRI controllers Drew Fustini
` (2 preceding siblings ...)
2023-04-25 20:38 ` [RFC PATCH v2 3/9] hw/riscv: implement CBQRI capacity controller Drew Fustini
@ 2023-04-25 20:38 ` Drew Fustini
2023-04-25 20:38 ` [RFC PATCH v2 5/9] hw/riscv: Kconfig: add CBQRI options Drew Fustini
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Drew Fustini @ 2023-04-25 20:38 UTC (permalink / raw)
To: Ved Shanbhogue, Palmer Dabbelt, Alistair Francis, Bin Meng,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, qemu-riscv,
qemu-devel, Nicolas Pitre, Adrien Ricciardi, Kornel Dulęba
Cc: Drew Fustini
From: Nicolas Pitre <npitre@baylibre.com>
Implement a bandwidth controller according to the Capacity and Bandwidth
QoS Register Interface (CBQRI) which supports these capabilities:
- Number of access types: 2 (code and data)
- 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
Link: https://github.com/riscv-non-isa/riscv-cbqri/blob/main/riscv-cbqri.pdf
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
Changes since v1:
- Move TYPE_RISCV_CBQRI_BC into include/hw/riscv/cbqri.h so machines
can to include it (suggested by Alistair)
- Add device properties so that the bandwidth controller can be fully
configured from the command line
hw/riscv/cbqri_bandwidth.c | 600 +++++++++++++++++++++++++++++++++++++
1 file changed, 600 insertions(+)
create mode 100644 hw/riscv/cbqri_bandwidth.c
diff --git a/hw/riscv/cbqri_bandwidth.c b/hw/riscv/cbqri_bandwidth.c
new file mode 100644
index 000000000000..27874c6c3c79
--- /dev/null
+++ b/hw/riscv/cbqri_bandwidth.c
@@ -0,0 +1,600 @@
+/*
+ * RISC-V Capacity and Bandwidth QoS Register Interface
+ * URL: https://github.com/riscv-non-isa/riscv-cbqri
+ *
+ * Copyright (c) 2023 BayLibre SAS
+ *
+ * This file contains the Bandwidth-controller QoS Register Interface.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/cbqri.h"
+
+
+/* Encodings of `AT` field */
+enum {
+ BC_AT_DATA = 0,
+ BC_AT_CODE = 1,
+};
+
+/* Capabilities */
+REG64(BC_CAPABILITIES, 0);
+FIELD(BC_CAPABILITIES, VER, 0, 8);
+FIELD(BC_CAPABILITIES, VER_MINOR, 0, 4);
+FIELD(BC_CAPABILITIES, VER_MAJOR, 4, 4);
+FIELD(BC_CAPABILITIES, NBWBLKS, 8, 16);
+FIELD(BC_CAPABILITIES, MRBWB, 32, 16);
+
+/* Usage monitoring control */
+REG64(BC_MON_CTL, 8);
+FIELD(BC_MON_CTL, OP, 0, 5);
+FIELD(BC_MON_CTL, AT, 5, 3);
+FIELD(BC_MON_CTL, MCID, 8, 12);
+FIELD(BC_MON_CTL, EVT_ID, 20, 8);
+FIELD(BC_MON_CTL, ATV, 28, 1);
+FIELD(BC_MON_CTL, STATUS, 32, 7);
+FIELD(BC_MON_CTL, BUSY, 39, 1);
+
+/* Usage monitoring operations */
+enum {
+ BC_MON_OP_CONFIG_EVENT = 1,
+ BC_MON_OP_READ_COUNTER = 2,
+};
+
+/* Bandwidth monitoring event ID */
+enum {
+ BC_EVT_ID_None = 0,
+ BC_EVT_ID_RDWR_count = 1,
+ BC_EVT_ID_RDONLY_count = 2,
+ BC_EVT_ID_WRONLY_count = 3,
+};
+
+/* BC_MON_CTL.STATUS field encodings */
+enum {
+ BC_MON_CTL_STATUS_SUCCESS = 1,
+ BC_MON_CTL_STATUS_INVAL_OP = 2,
+ BC_MON_CTL_STATUS_INVAL_MCID = 3,
+ BC_MON_CTL_STATUS_INVAL_EVT_ID = 4,
+ BC_MON_CTL_STATUS_INVAL_AT = 5,
+};
+
+/* Monitoring counter value */
+REG64(BC_MON_CTR_VAL, 16);
+FIELD(BC_MON_CTR_VAL, CTR, 0, 62);
+FIELD(BC_MON_CTR_VAL, INVALID, 62, 1);
+FIELD(BC_MON_CTR_VAL, OVF, 63, 1);
+
+/* Bandwidth Allocation control */
+REG64(BC_ALLOC_CTL, 24);
+FIELD(BC_ALLOC_CTL, OP, 0, 5);
+FIELD(BC_ALLOC_CTL, AT, 5, 3);
+FIELD(BC_ALLOC_CTL, RCID, 8, 12);
+FIELD(BC_ALLOC_CTL, STATUS, 32, 7);
+FIELD(BC_ALLOC_CTL, BUSY, 39, 1);
+
+/* Bandwidth allocation operations */
+enum {
+ BC_ALLOC_OP_CONFIG_LIMIT = 1,
+ BC_ALLOC_OP_READ_LIMIT = 2,
+};
+
+/* BC_ALLOC_CTL.STATUS field encodings */
+enum {
+ BC_ALLOC_STATUS_SUCCESS = 1,
+ BC_ALLOC_STATUS_INVAL_OP = 2,
+ BC_ALLOC_STATUS_INVAL_RCID = 3,
+ BC_ALLOC_STATUS_INVAL_AT = 4,
+ BC_ALLOC_STATUS_INVAL_BLKS = 5,
+};
+
+/* Bandwidth allocation */
+REG64(BC_BW_ALLOC, 32);
+FIELD(BC_BW_ALLOC, Rbwb, 0, 16);
+FIELD(BC_BW_ALLOC, Mweight, 20, 8);
+FIELD(BC_BW_ALLOC, sharedAT, 28, 3);
+FIELD(BC_BW_ALLOC, useShared, 31, 1);
+
+
+typedef struct MonitorCounter {
+ uint64_t ctr_val;
+ int at;
+ int evt_id;
+ bool active;
+} MonitorCounter;
+
+typedef struct BandwidthAllocation {
+ uint32_t Rbwb:16;
+ uint32_t Mweight:8;
+ uint32_t sharedAT:3;
+ bool useShared:1;
+} BandwidthAllocation;
+
+typedef struct RiscvCbqriBandwidthState {
+ SysBusDevice parent_obj;
+ MemoryRegion mmio;
+
+ /* cached value of some registers */
+ uint64_t bc_mon_ctl;
+ uint64_t bc_mon_ctr_val;
+ uint64_t bc_alloc_ctl;
+ uint64_t bc_bw_alloc;
+
+ MonitorCounter *mon_counters;
+ BandwidthAllocation *bw_allocations;
+
+ /* properties */
+
+ uint64_t mmio_base;
+ char *target;
+ uint16_t nb_mcids;
+ uint16_t nb_rcids;
+
+ uint16_t nbwblks;
+ uint16_t mrbwb;
+
+ bool supports_at_data;
+ bool supports_at_code;
+
+ bool supports_alloc_op_config_limit;
+ bool supports_alloc_op_read_limit;
+
+ 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;
+} RiscvCbqriBandwidthState;
+
+#define RISCV_CBQRI_BC(obj) \
+ OBJECT_CHECK(RiscvCbqriBandwidthState, (obj), TYPE_RISCV_CBQRI_BC)
+
+static BandwidthAllocation *get_bw_alloc(RiscvCbqriBandwidthState *bc,
+ uint32_t rcid, uint32_t at)
+{
+ /*
+ * All bandwidth allocation records are contiguous to simplify
+ * allocation. The first one is used to hold the BC_BW_ALLOC register
+ * content, followed by respective records for each AT per RCID.
+ */
+
+ unsigned int nb_ats = 0;
+ nb_ats += !!bc->supports_at_data;
+ nb_ats += !!bc->supports_at_code;
+ nb_ats = MAX(nb_ats, 1);
+ assert(at < nb_ats);
+
+ return &bc->bw_allocations[1 + rcid * nb_ats + at];
+}
+
+static uint32_t bandwidth_config(RiscvCbqriBandwidthState *bc,
+ uint32_t rcid, uint32_t at,
+ bool *busy)
+{
+ BandwidthAllocation *bw_alloc = get_bw_alloc(bc, rcid, at);
+
+ /* for now we only preserve the current BC_BW_ALLOC register content */
+ *bw_alloc = bc->bw_allocations[0];
+ return BC_ALLOC_STATUS_SUCCESS;
+}
+
+static uint32_t bandwidth_read(RiscvCbqriBandwidthState *bc,
+ uint32_t rcid, uint32_t at,
+ bool *busy)
+{
+ BandwidthAllocation *bw_alloc = get_bw_alloc(bc, rcid, at);
+
+ /* populate BC_BW_ALLOC register with selected content */
+ bc->bw_allocations[0] = *bw_alloc;
+ return BC_ALLOC_STATUS_SUCCESS;
+}
+
+static bool is_valid_at(RiscvCbqriBandwidthState *bc, uint32_t at)
+{
+ switch (at) {
+ case BC_AT_DATA:
+ return bc->supports_at_data;
+ case BC_AT_CODE:
+ return bc->supports_at_code;
+ default:
+ return false;
+ }
+}
+
+static void riscv_cbqri_bc_write_mon_ctl(RiscvCbqriBandwidthState *bc,
+ uint64_t value)
+{
+ if (!bc->supports_mon_op_config_event &&
+ !bc->supports_mon_op_read_counter) {
+ /* monitoring not supported: leave mon_ctl set to 0 */
+ return;
+ }
+
+ /* extract writable fields */
+ uint32_t op = FIELD_EX64(value, BC_MON_CTL, OP);
+ uint32_t at = FIELD_EX64(value, BC_MON_CTL, AT);
+ uint32_t mcid = FIELD_EX64(value, BC_MON_CTL, MCID);
+ uint32_t evt_id = FIELD_EX64(value, BC_MON_CTL, EVT_ID);
+ bool atv = FIELD_EX64(value, BC_MON_CTL, ATV);
+
+ /* extract read-only fields */
+ uint32_t status = FIELD_EX64(bc->bc_mon_ctl, BC_MON_CTL, STATUS);
+ bool busy = FIELD_EX64(bc->bc_mon_ctl, BC_MON_CTL, BUSY);
+
+ if (busy) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: busy flag still set, ignored",
+ __func__);
+ return;
+ }
+
+ if (!bc->supports_at_data &&
+ !bc->supports_at_code) {
+ /* AT not supported: hardwire to 0 */
+ at = 0;
+ atv = false;
+ }
+
+ if (mcid >= bc->nb_mcids) {
+ status = BC_MON_CTL_STATUS_INVAL_MCID;
+ } else if (op == BC_MON_OP_CONFIG_EVENT &&
+ bc->supports_mon_op_config_event) {
+ if (evt_id == BC_EVT_ID_None &&
+ bc->supports_mon_evt_id_none) {
+ bc->mon_counters[mcid].active = false;
+ status = BC_MON_CTL_STATUS_SUCCESS;
+ } else if ((evt_id == BC_EVT_ID_RDWR_count &&
+ bc->supports_mon_evt_id_rdwr_count) ||
+ (evt_id == BC_EVT_ID_RDONLY_count &&
+ bc->supports_mon_evt_id_rdonly_count) ||
+ (evt_id == BC_EVT_ID_WRONLY_count &&
+ bc->supports_mon_evt_id_wronly_count)) {
+ if (atv && !is_valid_at(bc, at)) {
+ status = BC_MON_CTL_STATUS_INVAL_AT;
+ } else {
+ bc->mon_counters[mcid].ctr_val =
+ FIELD_DP64(0, BC_MON_CTR_VAL, INVALID, 1);
+ bc->mon_counters[mcid].evt_id = evt_id;
+ bc->mon_counters[mcid].at = atv ? at : -1;
+ bc->mon_counters[mcid].active = true;
+ status = BC_MON_CTL_STATUS_SUCCESS;
+ }
+ } else {
+ status = BC_MON_CTL_STATUS_INVAL_EVT_ID;
+ }
+ } else if (op == BC_MON_OP_READ_COUNTER &&
+ bc->supports_mon_op_read_counter) {
+ bc->bc_mon_ctr_val = bc->mon_counters[mcid].ctr_val;
+ status = BC_MON_CTL_STATUS_SUCCESS;
+ } else {
+ status = BC_MON_CTL_STATUS_INVAL_OP;
+ }
+
+ /* reconstruct updated register value */
+ value = 0;
+ value = FIELD_DP64(value, BC_MON_CTL, OP, op);
+ value = FIELD_DP64(value, BC_MON_CTL, AT, at);
+ value = FIELD_DP64(value, BC_MON_CTL, MCID, mcid);
+ value = FIELD_DP64(value, BC_MON_CTL, EVT_ID, evt_id);
+ value = FIELD_DP64(value, BC_MON_CTL, ATV, atv);
+ value = FIELD_DP64(value, BC_MON_CTL, STATUS, status);
+ value = FIELD_DP64(value, BC_MON_CTL, BUSY, busy);
+ bc->bc_mon_ctl = value;
+}
+
+static void riscv_cbqri_bc_write_alloc_ctl(RiscvCbqriBandwidthState *bc,
+ uint64_t value)
+{
+ if (bc->nbwblks == 0 ||
+ (!bc->supports_alloc_op_config_limit &&
+ !bc->supports_alloc_op_read_limit)) {
+ /* capacity allocation not supported: leave bc_alloc_ctl set to 0 */
+ return;
+ }
+
+ /* extract writable fields */
+ uint32_t op = FIELD_EX64(value, BC_ALLOC_CTL, OP);
+ uint32_t at = FIELD_EX64(value, BC_ALLOC_CTL, AT);
+ uint32_t rcid = FIELD_EX64(value, BC_ALLOC_CTL, RCID);
+
+ /* extract read-only fields */
+ uint32_t status = FIELD_EX64(bc->bc_alloc_ctl, BC_ALLOC_CTL, STATUS);
+ bool busy = FIELD_EX64(bc->bc_alloc_ctl, BC_ALLOC_CTL, BUSY);
+
+ if (busy) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: busy flag still set, ignored",
+ __func__);
+ return;
+ }
+
+ bool atv = true;
+ if (!bc->supports_at_data &&
+ !bc->supports_at_code) {
+ /* AT not supported: hardwire to 0 */
+ at = 0;
+ atv = false;
+ }
+
+ if (rcid >= bc->nb_rcids) {
+ status = BC_ALLOC_STATUS_INVAL_RCID;
+ } else if (atv && !is_valid_at(bc, at)) {
+ status = BC_ALLOC_STATUS_INVAL_AT;
+ } else if (op == BC_ALLOC_OP_CONFIG_LIMIT &&
+ bc->supports_alloc_op_config_limit) {
+ status = bandwidth_config(bc, rcid, at, &busy);
+ } else if (op == BC_ALLOC_OP_READ_LIMIT &&
+ bc->supports_alloc_op_read_limit) {
+ status = bandwidth_read(bc, rcid, at, &busy);
+ } else {
+ status = BC_ALLOC_STATUS_INVAL_OP;
+ }
+
+ /* reconstruct updated register value */
+ value = 0;
+ value = FIELD_DP64(value, BC_ALLOC_CTL, OP, op);
+ value = FIELD_DP64(value, BC_ALLOC_CTL, AT, at);
+ value = FIELD_DP64(value, BC_ALLOC_CTL, RCID, rcid);
+ value = FIELD_DP64(value, BC_ALLOC_CTL, STATUS, status);
+ value = FIELD_DP64(value, BC_ALLOC_CTL, BUSY, busy);
+ bc->bc_alloc_ctl = value;
+}
+
+static void riscv_cbqri_bc_write_bw_alloc(RiscvCbqriBandwidthState *bc,
+ uint64_t value)
+{
+ if (bc->nbwblks == 0) {
+ /* capacity allocation not supported: leave bw_alloc set to 0 */
+ return;
+ }
+
+ BandwidthAllocation *bc_bw_alloc = &bc->bw_allocations[0];
+
+ /* extract writable fields */
+ bc_bw_alloc->Rbwb = FIELD_EX64(value, BC_BW_ALLOC, Rbwb);
+ bc_bw_alloc->Mweight = FIELD_EX64(value, BC_BW_ALLOC, Mweight);
+ bc_bw_alloc->sharedAT = FIELD_EX64(value, BC_BW_ALLOC, sharedAT);
+ bc_bw_alloc->useShared = FIELD_EX64(value, BC_BW_ALLOC, useShared);
+
+ if (!bc->supports_at_data &&
+ !bc->supports_at_code) {
+ /* AT not supported: hardwire to 0 */
+ bc_bw_alloc->sharedAT = 0;
+ bc_bw_alloc->useShared = false;
+ }
+}
+
+static void riscv_cbqri_bc_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned size)
+{
+ RiscvCbqriBandwidthState *bc = opaque;
+
+ assert((addr % 8) == 0);
+ assert(size == 8);
+
+ switch (addr) {
+ case A_BC_CAPABILITIES:
+ /* read-only register */
+ break;
+ case A_BC_MON_CTL:
+ riscv_cbqri_bc_write_mon_ctl(bc, value);
+ break;
+ case A_BC_MON_CTR_VAL:
+ /* read-only register */
+ break;
+ case A_BC_ALLOC_CTL:
+ riscv_cbqri_bc_write_alloc_ctl(bc, value);
+ break;
+ case A_BC_BW_ALLOC:
+ riscv_cbqri_bc_write_bw_alloc(bc, value);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: out of bounds (addr=0x%x)",
+ __func__, (uint32_t)addr);
+ }
+}
+
+static uint64_t riscv_cbqri_bc_read(void *opaque, hwaddr addr, unsigned size)
+{
+ RiscvCbqriBandwidthState *bc = opaque;
+ uint64_t value = 0;
+
+ assert((addr % 8) == 0);
+ assert(size == 8);
+
+ switch (addr) {
+ case A_BC_CAPABILITIES:
+ value = FIELD_DP64(value, BC_CAPABILITIES, VER_MAJOR,
+ RISCV_CBQRI_VERSION_MAJOR);
+ value = FIELD_DP64(value, BC_CAPABILITIES, VER_MINOR,
+ RISCV_CBQRI_VERSION_MINOR);
+ value = FIELD_DP64(value, BC_CAPABILITIES, NBWBLKS,
+ bc->nbwblks);
+ value = FIELD_DP64(value, BC_CAPABILITIES, MRBWB,
+ bc->mrbwb);
+ break;
+ case A_BC_MON_CTL:
+ value = bc->bc_mon_ctl;
+ break;
+ case A_BC_MON_CTR_VAL:
+ value = bc->bc_mon_ctr_val;
+ break;
+ case A_BC_ALLOC_CTL:
+ value = bc->bc_alloc_ctl;
+ break;
+ case A_BC_BW_ALLOC:
+ BandwidthAllocation *bc_bw_alloc = &bc->bw_allocations[0];
+ value = FIELD_DP64(value, BC_BW_ALLOC, Rbwb, bc_bw_alloc->Rbwb);
+ value = FIELD_DP64(value, BC_BW_ALLOC, Mweight, bc_bw_alloc->Mweight);
+ value = FIELD_DP64(value, BC_BW_ALLOC, sharedAT, bc_bw_alloc->sharedAT);
+ value = FIELD_DP64(value, BC_BW_ALLOC, useShared, bc_bw_alloc->useShared);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: out of bounds (addr=0x%x)",
+ __func__, (uint32_t)addr);
+ }
+
+ return value;
+}
+
+static const MemoryRegionOps riscv_cbqri_bc_ops = {
+ .read = riscv_cbqri_bc_read,
+ .write = riscv_cbqri_bc_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 8,
+ .impl.min_access_size = 8,
+ .impl.max_access_size = 8,
+};
+
+static void riscv_cbqri_bc_realize(DeviceState *dev, Error **errp)
+{
+ RiscvCbqriBandwidthState *bc = RISCV_CBQRI_BC(dev);
+
+ if (!bc->mmio_base) {
+ error_setg(errp, "mmio_base property not set");
+ return;
+ }
+
+ assert(bc->mon_counters == NULL);
+ bc->mon_counters = g_new0(MonitorCounter, bc->nb_mcids);
+
+ assert(bc->bw_allocations == NULL);
+ BandwidthAllocation *bw_alloc_end = get_bw_alloc(bc, bc->nb_rcids, 0);
+ unsigned int bw_alloc_size = bw_alloc_end - bc->bw_allocations;
+ bc->bw_allocations = g_new0(BandwidthAllocation, bw_alloc_size);
+
+ memory_region_init_io(&bc->mmio, OBJECT(dev), &riscv_cbqri_bc_ops,
+ bc, TYPE_RISCV_CBQRI_BC".mmio", 4 * 1024);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &bc->mmio);
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, bc->mmio_base);
+}
+
+static void riscv_cbqri_bc_reset(DeviceState *dev)
+{
+ RiscvCbqriBandwidthState *bc = RISCV_CBQRI_BC(dev);
+
+ bc->bc_mon_ctl = 0;
+ bc->bc_alloc_ctl = 0;
+}
+
+static Property riscv_cbqri_bc_properties[] = {
+ DEFINE_PROP_UINT64("mmio_base", RiscvCbqriBandwidthState, mmio_base, 0),
+ DEFINE_PROP_STRING("target", RiscvCbqriBandwidthState, target),
+
+ DEFINE_PROP_UINT16("max_mcids", RiscvCbqriBandwidthState, nb_mcids, 256),
+ DEFINE_PROP_UINT16("max_rcids", RiscvCbqriBandwidthState, nb_rcids, 64),
+ DEFINE_PROP_UINT16("nbwblks", RiscvCbqriBandwidthState, nbwblks, 1024),
+ DEFINE_PROP_UINT16("mrbwb", RiscvCbqriBandwidthState, mrbwb, 819),
+
+ DEFINE_PROP_BOOL("at_data", RiscvCbqriBandwidthState,
+ supports_at_data, true),
+ DEFINE_PROP_BOOL("at_code", RiscvCbqriBandwidthState,
+ supports_at_code, true),
+
+ DEFINE_PROP_BOOL("alloc_op_config_limit", RiscvCbqriBandwidthState,
+ supports_alloc_op_config_limit, true),
+ DEFINE_PROP_BOOL("alloc_op_read_limit", RiscvCbqriBandwidthState,
+ supports_alloc_op_read_limit, true),
+
+ DEFINE_PROP_BOOL("mon_op_config_event", RiscvCbqriBandwidthState,
+ supports_mon_op_config_event, true),
+ DEFINE_PROP_BOOL("mon_op_read_counter", RiscvCbqriBandwidthState,
+ supports_mon_op_read_counter, true),
+
+ DEFINE_PROP_BOOL("mon_evt_id_none", RiscvCbqriBandwidthState,
+ supports_mon_evt_id_none, true),
+ DEFINE_PROP_BOOL("mon_evt_id_rdwr_count", RiscvCbqriBandwidthState,
+ supports_mon_evt_id_rdwr_count, true),
+ DEFINE_PROP_BOOL("mon_evt_id_rdonly_count", RiscvCbqriBandwidthState,
+ supports_mon_evt_id_rdonly_count, true),
+ DEFINE_PROP_BOOL("mon_evt_id_wronly_count", RiscvCbqriBandwidthState,
+ supports_mon_evt_id_wronly_count, true),
+
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void riscv_cbqri_bc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->realize = riscv_cbqri_bc_realize;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->desc = "RISC-V CBQRI Bandwidth Controller";
+ device_class_set_props(dc, riscv_cbqri_bc_properties);
+ dc->reset = riscv_cbqri_bc_reset;
+ dc->user_creatable = true;
+}
+
+static const TypeInfo riscv_cbqri_bc_info = {
+ .name = TYPE_RISCV_CBQRI_BC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(RiscvCbqriBandwidthState),
+ .class_init = riscv_cbqri_bc_class_init,
+};
+
+static void riscv_cbqri_bc_register_types(void)
+{
+ type_register_static(&riscv_cbqri_bc_info);
+}
+
+DeviceState *riscv_cbqri_bc_create(hwaddr addr,
+ const RiscvCbqriBandwidthCaps *caps,
+ const char *target_name)
+{
+ DeviceState *dev = qdev_new(TYPE_RISCV_CBQRI_BC);
+
+ qdev_prop_set_uint64(dev, "mmio_base", addr);
+ qdev_prop_set_string(dev, "target", target_name);
+ qdev_prop_set_uint16(dev, "max_mcids", caps->nb_mcids);
+ qdev_prop_set_uint16(dev, "max_rcids", caps->nb_rcids);
+ qdev_prop_set_uint16(dev, "nbwblks", caps->nbwblks);
+
+ qdev_prop_set_bit(dev, "at_data",
+ caps->supports_at_data);
+ qdev_prop_set_bit(dev, "at_code",
+ caps->supports_at_code);
+ qdev_prop_set_bit(dev, "alloc_op_config_limit",
+ caps->supports_alloc_op_config_limit);
+ qdev_prop_set_bit(dev, "alloc_op_read_limit",
+ caps->supports_alloc_op_read_limit);
+ qdev_prop_set_bit(dev, "mon_op_config_event",
+ caps->supports_mon_op_config_event);
+ qdev_prop_set_bit(dev, "mon_op_read_counter",
+ caps->supports_mon_op_read_counter);
+ qdev_prop_set_bit(dev, "mon_evt_id_none",
+ caps->supports_mon_evt_id_none);
+ qdev_prop_set_bit(dev, "mon_evt_id_rdwr_count",
+ caps->supports_mon_evt_id_rdwr_count);
+ qdev_prop_set_bit(dev, "mon_evt_id_rdonly_count",
+ caps->supports_mon_evt_id_rdonly_count);
+ qdev_prop_set_bit(dev, "mon_evt_id_wronly_count",
+ caps->supports_mon_evt_id_wronly_count);
+
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+
+ return dev;
+}
+
+type_init(riscv_cbqri_bc_register_types)
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v2 5/9] hw/riscv: Kconfig: add CBQRI options
2023-04-25 20:38 [RFC PATCH v2 0/9] riscv: implement Ssqosid extension and CBQRI controllers Drew Fustini
` (3 preceding siblings ...)
2023-04-25 20:38 ` [RFC PATCH v2 4/9] hw/riscv: implement CBQRI bandwidth controller Drew Fustini
@ 2023-04-25 20:38 ` Drew Fustini
2023-04-25 20:38 ` [RFC PATCH v2 6/9] hw/riscv: meson: add CBQRI controllers to the build Drew Fustini
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Drew Fustini @ 2023-04-25 20:38 UTC (permalink / raw)
To: Ved Shanbhogue, Palmer Dabbelt, Alistair Francis, Bin Meng,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, qemu-riscv,
qemu-devel, Nicolas Pitre, Adrien Ricciardi, Kornel Dulęba
Cc: Drew Fustini
From: Nicolas Pitre <npitre@baylibre.com>
Add boolean property for CBQRI and imply it should be enabled for the
RISC-V virt machine.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
Changes since v1:
- remove example SoC now that command line arguments supported for CBQRI
- change 'select RISC_CBQRI' to 'imply RISCV_CBQRI' for RISCV_VIRT
hw/riscv/Kconfig | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 6528ebfa3a3b..8fd4aebc77d1 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -1,3 +1,6 @@
+config RISCV_CBQRI
+ bool
+
config RISCV_NUMA
bool
@@ -45,6 +48,7 @@ config RISCV_VIRT
select FW_CFG_DMA
select PLATFORM_BUS
select ACPI
+ imply RISCV_CBQRI
config SHAKTI_C
bool
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v2 6/9] hw/riscv: meson: add CBQRI controllers to the build
2023-04-25 20:38 [RFC PATCH v2 0/9] riscv: implement Ssqosid extension and CBQRI controllers Drew Fustini
` (4 preceding siblings ...)
2023-04-25 20:38 ` [RFC PATCH v2 5/9] hw/riscv: Kconfig: add CBQRI options Drew Fustini
@ 2023-04-25 20:38 ` Drew Fustini
2023-04-25 20:38 ` [RFC PATCH v2 7/9] hw/riscv: add CBQRI controllers to virt machine Drew Fustini
` (2 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Drew Fustini @ 2023-04-25 20:38 UTC (permalink / raw)
To: Ved Shanbhogue, Palmer Dabbelt, Alistair Francis, Bin Meng,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, qemu-riscv,
qemu-devel, Nicolas Pitre, Adrien Ricciardi, Kornel Dulęba
Cc: Drew Fustini
From: Nicolas Pitre <npitre@baylibre.com>
Build the CBQRI controllers when RISC-V CBQRI is enabled by Kconfig.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
Changes since v1:
- remove example SoC now that command line arguments supported for CBQRI
hw/riscv/meson.build | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
index 2f7ee81be3ca..2281d17d0b09 100644
--- a/hw/riscv/meson.build
+++ b/hw/riscv/meson.build
@@ -10,5 +10,7 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c'))
riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c'))
riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfsoc.c'))
riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
+riscv_ss.add(when: 'CONFIG_RISCV_CBQRI',
+ if_true: files('cbqri_capacity.c', 'cbqri_bandwidth.c'))
hw_arch += {'riscv': riscv_ss}
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v2 7/9] hw/riscv: add CBQRI controllers to virt machine
2023-04-25 20:38 [RFC PATCH v2 0/9] riscv: implement Ssqosid extension and CBQRI controllers Drew Fustini
` (5 preceding siblings ...)
2023-04-25 20:38 ` [RFC PATCH v2 6/9] hw/riscv: meson: add CBQRI controllers to the build Drew Fustini
@ 2023-04-25 20:38 ` Drew Fustini
2023-04-25 20:38 ` [RFC PATCH v2 8/9] hw/riscv: instantiate CBQRI controllers for an example SoC Drew Fustini
2023-04-25 20:38 ` [RFC PATCH v2 9/9] hw/riscv: build example SoC when CBQRI_EXAMPLE_SOC enabled Drew Fustini
8 siblings, 0 replies; 11+ messages in thread
From: Drew Fustini @ 2023-04-25 20:38 UTC (permalink / raw)
To: Ved Shanbhogue, Palmer Dabbelt, Alistair Francis, Bin Meng,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, qemu-riscv,
qemu-devel, Nicolas Pitre, Adrien Ricciardi, Kornel Dulęba
Cc: Drew Fustini
From: Nicolas Pitre <npitre@baylibre.com>
Add CBQRI controllers to the RISC-V virt machine. The device properties
can be fully configured from the command line:
$ qemu-system-riscv64 -M virt ... \
-device riscv.cbqri.capacity,mmio_base=0x04828000[,...]
-device riscv.cbqri.bandwidth,mmio_base=0x04829000[,...]
The mmio_base option is mandatory, the others are optional.
Many -device arguments as wanted can be provided as long as their
mmio regions don't conflict.
To see all possible options:
$ qemu-system-riscv64 -device riscv.cbqri.capacity,help
riscv.cbqri.capacity options:
alloc_op_config_limit=<bool> - (default: true)
alloc_op_flush_rcid=<bool> - (default: true)
alloc_op_read_limit=<bool> - (default: true)
at_code=<bool> - (default: true)
at_data=<bool> - (default: true)
max_mcids=<uint16> - (default: 256)
max_rcids=<uint16> - (default: 64)
mmio_base=<uint64> - (default: 0)
mon_evt_id_none=<bool> - (default: true)
mon_evt_id_occupancy=<bool> - (default: true)
mon_op_config_event=<bool> - (default: true)
mon_op_read_counter=<bool> - (default: true)
ncblks=<uint16> - (default: 16)
target=<str>
$ qemu-system-riscv64 -device riscv.cbqri.bandwidth,help
riscv.cbqri.bandwidth options:
alloc_op_config_limit=<bool> - (default: true)
alloc_op_read_limit=<bool> - (default: true)
at_code=<bool> - (default: true)
at_data=<bool> - (default: true)
max_mcids=<uint16> - (default: 256)
max_rcids=<uint16> - (default: 64)
mmio_base=<uint64> - (default: 0)
mon_evt_id_none=<bool> - (default: true)
mon_evt_id_rdonly_count=<bool> - (default: true)
mon_evt_id_rdwr_count=<bool> - (default: true)
mon_evt_id_wronly_count=<bool> - (default: true)
mon_op_config_event=<bool> - (default: true)
mon_op_read_counter=<bool> - (default: true)
nbwblks=<uint16> - (default: 1024)
target=<str>
Boolean options correspond to hardware capabilities that can be disabled
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
Changes since v1:
- remove initialization of the example SoC now that device properties
can be use to configure controllers from the command line
hw/riscv/virt.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4e3efbee16f0..674a6a34de3a 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -50,6 +50,7 @@
#include "hw/pci-host/gpex.h"
#include "hw/display/ramfb.h"
#include "hw/acpi/aml-build.h"
+#include "hw/riscv/cbqri.h"
#include "qapi/qapi-visit-common.h"
/*
@@ -1688,6 +1689,8 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
#ifdef CONFIG_TPM
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
#endif
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RISCV_CBQRI_BC);
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RISCV_CBQRI_CC);
object_class_property_add_bool(oc, "aclint", virt_get_aclint,
virt_set_aclint);
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v2 8/9] hw/riscv: instantiate CBQRI controllers for an example SoC
2023-04-25 20:38 [RFC PATCH v2 0/9] riscv: implement Ssqosid extension and CBQRI controllers Drew Fustini
` (6 preceding siblings ...)
2023-04-25 20:38 ` [RFC PATCH v2 7/9] hw/riscv: add CBQRI controllers to virt machine Drew Fustini
@ 2023-04-25 20:38 ` Drew Fustini
2023-04-25 20:38 ` [RFC PATCH v2 9/9] hw/riscv: build example SoC when CBQRI_EXAMPLE_SOC enabled Drew Fustini
8 siblings, 0 replies; 11+ messages in thread
From: Drew Fustini @ 2023-04-25 20:38 UTC (permalink / raw)
To: Ved Shanbhogue, Palmer Dabbelt, Alistair Francis, Bin Meng,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, qemu-riscv,
qemu-devel, Nicolas Pitre, Adrien Ricciardi, Kornel Dulęba
Cc: Drew Fustini
From: Nicolas Pitre <npitre@baylibre.com>
Instantiate a hypothetical CBQRI configuration for testing purposes with
these properties:
- L2 cache controllers
- Resource type: Capacity
- NCBLKS: 12
- 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
- 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
- NBWBLKS: 1024
- 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 the CBQRI controllers in 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
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
Note: this example SoC instantiation code is only included for reference
and it is not required anymore for the CBQRI proof-of-concept to work.
The CBQRI controllers can be fully configured with device properties in
the Qemu command line.
hw/riscv/cbqri_example_soc.c | 124 +++++++++++++++++++++++++++++++++++
include/hw/riscv/cbqri.h | 2 +
2 files changed, 126 insertions(+)
create mode 100644 hw/riscv/cbqri_example_soc.c
diff --git a/hw/riscv/cbqri_example_soc.c b/hw/riscv/cbqri_example_soc.c
new file mode 100644
index 000000000000..91240cdd105e
--- /dev/null
+++ b/hw/riscv/cbqri_example_soc.c
@@ -0,0 +1,124 @@
+/*
+ * RISC-V Capacity and Bandwidth QoS Register Interface
+ * URL: https://github.com/riscv-non-isa/riscv-cbqri
+ *
+ * Copyright (c) 2023 BayLibre SAS
+ *
+ * This file contains an hypothetical CBQRI configuration instantiation
+ * for testing purposes. This may also be configured from the command
+ * line.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/cbqri.h"
+
+/*
+ * Example hardware:
+ *
+ * - Global
+ * - Number of RCIDs - 64
+ * - Number of MCIDs - 256
+ * - L2 cache
+ * - NCBLKS - 12
+ * - Number of access types - 2 (code and data)
+ * - Usage monitoring not supported
+ * - Capacity allocation operations - CONFIG_LIMIT, READ_LIMIT
+ * - LLC
+ * - NCBLKS - 16
+ * - Number of access types - 2 (code and data)
+ * - Usage monitoring operations - CONFIG_EVENT, READ_COUNTER
+ * - Event IDs supported - None, Occupancy
+ * - Capacity allocation operations - CONFIG_LIMIT, READ_LIMIT, FLUSH_RCID
+ * - Memory controllers
+ * - NBWBLKS - 1024
+ * - MRBWB - 80 (80%)
+ * - 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
+ * - Number of access types - 1 (no code/data differentiation)
+ *
+ * 0x04820000 Cluster 0 L2 cache controller
+ * 0x04821000 Cluster 1 L2 cache controller
+ * 0x0482B000 Shared LLC controller
+ * 0x04828000 Memory controller 0
+ * 0x04829000 Memory controller 1
+ * 0x0482A000 Memory controller 2
+ */
+
+#define CBQRI_NB_MCIDS 256
+#define CBQRI_NB_RCIDS 64
+
+static const RiscvCbqriCapacityCaps example_soc_L2_cluster = {
+ .nb_mcids = CBQRI_NB_MCIDS,
+ .nb_rcids = CBQRI_NB_RCIDS,
+ .ncblks = 12,
+ .supports_at_data = true,
+ .supports_at_code = true,
+ .supports_alloc_op_config_limit = true,
+ .supports_alloc_op_read_limit = true,
+};
+
+static const RiscvCbqriCapacityCaps example_soc_LLC = {
+ .nb_mcids = CBQRI_NB_MCIDS,
+ .nb_rcids = CBQRI_NB_RCIDS,
+ .ncblks = 16,
+ .supports_at_data = true,
+ .supports_at_code = true,
+ .supports_alloc_op_config_limit = true,
+ .supports_alloc_op_read_limit = true,
+ .supports_alloc_op_flush_rcid = true,
+ .supports_mon_op_config_event = true,
+ .supports_mon_op_read_counter = true,
+ .supports_mon_evt_id_none = true,
+ .supports_mon_evt_id_occupancy = true,
+};
+
+static const RiscvCbqriBandwidthCaps example_soc_memory = {
+ .nb_mcids = CBQRI_NB_MCIDS,
+ .nb_rcids = CBQRI_NB_RCIDS,
+ .nbwblks = 1024,
+ .mrbwb = 1024 * 80 / 100,
+ .supports_alloc_op_config_limit = true,
+ .supports_alloc_op_read_limit = true,
+ .supports_mon_op_config_event = true,
+ .supports_mon_op_read_counter = true,
+ .supports_mon_evt_id_none = true,
+ .supports_mon_evt_id_rdwr_count = true,
+ .supports_mon_evt_id_rdonly_count = true,
+ .supports_mon_evt_id_wronly_count = true,
+};
+
+void example_soc_cbqri_init(void)
+{
+ riscv_cbqri_cc_create(0x04820000, &example_soc_L2_cluster,
+ "cluster 0 L2 cache controller");
+ riscv_cbqri_cc_create(0x04821000, &example_soc_L2_cluster,
+ "cluster 1 L2 cache controller");
+ riscv_cbqri_cc_create(0x0482B000, &example_soc_LLC,
+ "shared LLC controller");
+ riscv_cbqri_bc_create(0x04828000, &example_soc_memory,
+ "memory controller 0");
+ riscv_cbqri_bc_create(0x04829000, &example_soc_memory,
+ "memory controller 1");
+ riscv_cbqri_bc_create(0x0482a000, &example_soc_memory,
+ "memory controller 2");
+}
diff --git a/include/hw/riscv/cbqri.h b/include/hw/riscv/cbqri.h
index 8e1399994368..49738187aacd 100644
--- a/include/hw/riscv/cbqri.h
+++ b/include/hw/riscv/cbqri.h
@@ -78,4 +78,6 @@ DeviceState *riscv_cbqri_cc_create(hwaddr addr,
DeviceState *riscv_cbqri_bc_create(hwaddr addr,
const RiscvCbqriBandwidthCaps *caps,
const char *target_name);
+
+void example_soc_cbqri_init(void);
#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v2 9/9] hw/riscv: build example SoC when CBQRI_EXAMPLE_SOC enabled
2023-04-25 20:38 [RFC PATCH v2 0/9] riscv: implement Ssqosid extension and CBQRI controllers Drew Fustini
` (7 preceding siblings ...)
2023-04-25 20:38 ` [RFC PATCH v2 8/9] hw/riscv: instantiate CBQRI controllers for an example SoC Drew Fustini
@ 2023-04-25 20:38 ` Drew Fustini
8 siblings, 0 replies; 11+ messages in thread
From: Drew Fustini @ 2023-04-25 20:38 UTC (permalink / raw)
To: Ved Shanbhogue, Palmer Dabbelt, Alistair Francis, Bin Meng,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, qemu-riscv,
qemu-devel, Nicolas Pitre, Adrien Ricciardi, Kornel Dulęba
Cc: Drew Fustini
Build the example SoC instantiation code when CBQRI_EXAMPLE_SOC is
enabled.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Signed-off-by: Drew Fustini <dfustini@baylibre.com>
---
Note: the example SoC instantiation code is only included for reference
and it is not required anymore for the CBQRI proof-of-concept to work.
The CBQRI controllers can be fully configured with device properties in
the Qemu command line.
hw/riscv/Kconfig | 5 +++++
hw/riscv/meson.build | 1 +
2 files changed, 6 insertions(+)
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 8fd4aebc77d1..e5892736733c 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -49,6 +49,7 @@ config RISCV_VIRT
select PLATFORM_BUS
select ACPI
imply RISCV_CBQRI
+ imply CBQRI_EXAMPLE_SOC
config SHAKTI_C
bool
@@ -88,3 +89,7 @@ config SPIKE
select HTIF
select RISCV_ACLINT
select SIFIVE_PLIC
+
+config CBQRI_EXAMPLE_SOC
+ bool
+ select RISCV_CBQRI
diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
index 2281d17d0b09..50e94f40de46 100644
--- a/hw/riscv/meson.build
+++ b/hw/riscv/meson.build
@@ -12,5 +12,6 @@ riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfsoc.c')
riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
riscv_ss.add(when: 'CONFIG_RISCV_CBQRI',
if_true: files('cbqri_capacity.c', 'cbqri_bandwidth.c'))
+riscv_ss.add(when: 'CONFIG_CBQRI_EXAMPLE_SOC', if_true: files('cbqri_example_soc.c'))
hw_arch += {'riscv': riscv_ss}
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread