[PATCH v6 06/14] gtrace: Add RISC-V Trace encoder driver

Zane Leung liangzhen at linux.spacemit.com
Wed Oct 14 21:36:36 PDT 2026


H,i Mayuresh

On 10/1/2026 1:22 PM, Mayuresh Chitale wrote:
> +static int rvtrace_encoder_probe(struct gtrace_component *comp)
> +{
> +	struct gtrace_platform_data *pdata = comp->pdata;
> +	struct rvtrace_encoder_priv *priv;
> +	u32 val, hw_srcbits, srcbits;
> +	int ret;
> +
> +	if (pdata->bound_cpu < 0) {
> +		dev_err(&comp->dev, "cpu property missing. Please fix firmware.\n");
> +		return -EINVAL;
> +	}
> +
> +	priv = devm_kzalloc(&comp->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	ret = rvtrace_encoder_set_format(pdata);
> +	if (ret) {
> +		dev_err(&comp->dev, "failed to set format %d\n", pdata->format);
> +		return ret;
> +	}
> +
> +	/* Check if trTeInhibitSrc is hardwired to 1 */
> +	val = gtrace_read32(pdata, RVTRACE_COMPONENT_CTRL_OFFSET);
> +	val &= ~BIT(RVTRACE_COMPONENT_CTRL_INHIBITSRC_SHIFT);
> +	gtrace_write32(pdata, val, RVTRACE_COMPONENT_CTRL_OFFSET);
> +	val = gtrace_read32(pdata, RVTRACE_COMPONENT_CTRL_OFFSET);
> +	if (!(val & BIT(RVTRACE_COMPONENT_CTRL_INHIBITSRC_SHIFT))) {
> +		/* Probe how many bits can trTeSrcID span in the emitted Trace messages */
> +		val = gtrace_read32(pdata, RVTRACE_ENCODER_INSTFEAT_OFFSET);
> +		val |= (RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK <<
> +			RVTRACE_ENCODER_INSTFEAT_SRCBITS_SHIFT);
> +		gtrace_write32(pdata, val, RVTRACE_ENCODER_INSTFEAT_OFFSET);
> +		val = gtrace_read32(pdata, RVTRACE_ENCODER_INSTFEAT_OFFSET);
> +		hw_srcbits = (val >> RVTRACE_ENCODER_INSTFEAT_SRCBITS_SHIFT) &
> +			     RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK;
> +		/* Determine if there are sufficient bits to hold max cpus */
> +		hw_srcbits = min_t(u32, hw_srcbits, RVTRACE_ENCODER_INSTFEAT_SRCBITS_MAX);
> +		srcbits = min_t(u32, hw_srcbits, order_base_2(nr_cpu_ids));

• Hardware Specs: The SRCBITS field has a bitmask of 15 but a hardware maximum legal value of 12.
• The Bug: The original code blindly wrote the full mask (15) to probe the field width. Because 15 exceeds the hardware maximum legal limit (12), the WARL architecture automatically rejected this illegal value and truncated/clamped it back to an invalid or default state.
• Impact: The read-back value returned 0 or an incorrect width, causing the probe to fail and falsely triggering the warning: "cpu %d trace will not carry source id".

#define RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK   GENMASK(31, 28)
#define RVTRACE_ENCODER_INSTFEAT_SRCBITS_MAX    12

                /* Probe how many bits can trTeSrcID span in the emitted Trace messages */
                val = gtrace_read32(pdata, RVTRACE_ENCODER_INSTFEAT_OFFSET);
               hw_srcbits = RVTRACE_ENCODER_INSTFEAT_SRCBITS_MAX;
               do {
                       val &= ~RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK;
                       val |= FIELD_PREP(RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK, srcbits);
                       gtrace__write32(pdata, val, RVTRACE_ENCODER_INSTFEAT_OFFSET);
                       val = gtrace_read32(pdata, RVTRACE_ENCODER_INSTFEAT_OFFSET);
                       if (FIELD_GET(RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK, val) == hw_srcbits)
                               break;
               } while (--hw_srcbits);
                /* Determine if there are sufficient bits to hold max cpus */
                srcbits = min_t(u32, hw_srcbits, order_base_2(nr_cpu_ids));

> +		if (srcbits && pdata->bound_cpu < BIT(srcbits)) {
> +			rvtrace_encoder_set_srcid(pdata, srcbits);
> +			priv->srcbits = srcbits;
> +		}
> +	}
> +	if (!priv->srcbits) {
> +		dev_warn(&comp->dev, "cpu %d trace will not carry source id\n",
> +			 pdata->bound_cpu);
> +		val = gtrace_read32(pdata, RVTRACE_COMPONENT_CTRL_OFFSET);
> +		val |= BIT(RVTRACE_COMPONENT_CTRL_INHIBITSRC_SHIFT);
> +		gtrace_write32(pdata, val, RVTRACE_COMPONENT_CTRL_OFFSET);
> +	}
> +	dev_set_drvdata(&comp->dev, priv);
> +	return 0;
> +}



More information about the linux-riscv mailing list