2026-02-01T15:58:10-08:00, Drew Fustini <[email protected]>:
> From: Nicolas Pitre <[email protected]>
>
> 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/releases/tag/v1.0
> Signed-off-by: Nicolas Pitre <[email protected]>
> [fustini: add fields introduced in the ratified spec: rpfx and p]
> Signed-off-by: Drew Fustini <[email protected]>
> ---
> diff --git a/hw/riscv/cbqri_bandwidth.c b/hw/riscv/cbqri_bandwidth.c
> [...]
> +static uint32_t bandwidth_config(RiscvCbqriBandwidthState *bc,
> +                                 uint32_t rcid, uint32_t at,
> +                                 bool *busy)
> +{
> +    BandwidthAllocation *bw_alloc = get_bw_alloc(bc, rcid, at);
> +
> +    /*
> +     * Bandwidth is allocated in multiples of bandwidth blocks, and the
> +     * value in Rbwb must be at least 1 and must not exceed MRBWB value.
> +     */
> +    if (bc->bw_allocations[0].Rbwb < 1) {
> +        return BC_ALLOC_STATUS_INVAL_OP;
> +    } else if (bc->bw_allocations[0].Rbwb > bc->mrbwb) {
> +        return BC_ALLOC_STATUS_INVAL_OP;
> +    }

"the sum of Rbwb allocated across all RCIDs must not exceed MRBWB".

> [...]
> +static void riscv_cbqri_bc_write_mon_ctl(RiscvCbqriBandwidthState *bc,
> +                                         uint64_t value)
> +{
> [...]
> +    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);

This caught my attention even in the capacity controller.
Maybe a it's worth a short comment that we set INVALID, because we don't
actually do any bookkeeping?

> [...]
> +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);

Missing mrbwb.

Thanks.

Reply via email to