[PATCH v3 2/3] lib: sbi: ISA extension emulation.

Olof Johansson olof at lixom.net
Mon May 18 17:33:17 PDT 2026


Hi,

This is really useful, even if it's not very fast, for obvious reasons.

Fairly late feedback on this, but I found two bugs and a nit when working
to get Ubuntu 26.04 working on X280 (Tenstorrent Blackhole). It boots
with these fixes applied. In particular, without the cbo.zero fix Python
crashes on init.

For those curious, booting is quite slow due to the massive amount of emulation
needed. Implemented stats, boot to login prompt takes:

L2CPU 0 ISA-emulation counters (version 5, hart 0):
  ID  Extension      count
----  -------------  ---------------
   1  ANY                  128201838 (sum of all below)
   2  Zcb                  103287492
   5  Zbs                   12818741
   6  Zicond                12090563
   9  Zfa                       4517
  17  Zvbb                        69
  18  VS-off-bounce              455



-Olof

On Sat, Dec 27, 2025 at 01:18:01PM +0100, Benedikt Freisen wrote:
> Add trap-based emulation code or compatibility stubs for the following ISA extensions:
> Zicbom, Zicboz, Zicond, Zimop, Zawrs, Zfa, Zfhmin, Zcb, Zcmop, Zba, Zbb, Zbc, Zbs, Supm
> 
> Signed-off-by: Benedikt Freisen <b.freisen at gmx.net>
> ---

[...]

> diff --git a/lib/sbi/sbi_insn_emu.c b/lib/sbi/sbi_insn_emu.c
> new file mode 100644
> index 00000000..ffc3bade
> --- /dev/null
> +++ b/lib/sbi/sbi_insn_emu.c

[...]

> +#if defined(CONFIG_EMU_ZBA) || defined(CONFIG_EMU_ZBB) ||     \
> +	defined(CONFIG_EMU_ZBC) || defined(CONFIG_EMU_ZBS) || \
> +	defined(CONFIG_EMU_ZICOND)
> +int sbi_insn_emu_op(ulong insn, struct sbi_trap_regs *regs)
> +{

[...]

> +#ifdef CONFIG_EMU_ZBC
> +	/* Emulate Zbc instructions */
> +	case INSN_MATCH_CLMUL:
> +		rd_val = 0;
> +		for (int i = 0; i < __riscv_xlen; i++) {
> +			if ((rs2_val >> i) & 1)
> +				rd_val ^= rs1_val << i;
> +		}
> +		break;
> +	case INSN_MATCH_CLMULH:
> +		rd_val = 0;
> +		for (int i = 1; i <= __riscv_xlen; i++) {
> +			if ((rs2_val >> i) & 1)
> +				rd_val ^= rs1_val >> (__riscv_xlen - i);
> +		}
> +		break;

The above needs to be < __riscv_xlen. Per the spec:

        for (int i = 1; i < XLEN; i++)
            if ((rs2 >> i) & 1)
                x ^= rs1 >> (XLEN - i);

> +	case INSN_MATCH_CLMULR:
> +		rd_val = 0;
> +		for (int i = 0; i < __riscv_xlen; i++) {
> +			if ((rs2_val >> i) & 1)
> +				rd_val ^= rs1_val >> (__riscv_xlen - i - 1);
> +		}
> +		break;
> +#endif

[...]

> +int sbi_insn_emu_zicbom_zicboz(ulong insn, struct sbi_trap_regs *regs)
> +{
> +	/* NOTE: Errata workarounds for fence instructions are handled in
> +	 * misc_mem_opcode_insn. */
> +
> +	/* Emulate Zicbom and Zicboz */
> +	switch (insn & INSN_MASK_CBO) {
> +	case INSN_MATCH_CBO_ZERO: {
> +		/* Check whether the instruction was even allowed */
> +		ulong prev_mode = sbi_mstatus_prev_mode(regs->mstatus);
> +		if ((prev_mode == PRV_U &&
> +		     !(read_senvcfg_or_emu() & ENVCFG_CBZE)) ||
> +		    (prev_mode == PRV_S &&
> +		     !(read_menvcfg_or_emu() & ENVCFG_CBZE)))
> +			return truly_illegal_insn(insn, regs);
> +
> +		u32 *addr =
> +			(u32 *)(GET_RS1S(insn, regs) & 0xffffffffffffffc0ull);

This needs to be GET_RS1(), or you end up picking up the wrong register in some
cases (gpr[8]). 

[...]

> +int sbi_insn_emu_store_fp(ulong insn, struct sbi_trap_regs *regs)
> +{
> +	struct sbi_trap_context *tcntx =
> +		container_of(regs, struct sbi_trap_context, regs);
> +
> +	/* If floating point is available and insn is FSH,
> +	 * simply use the misaligned store handler */
> +	if ((regs->mstatus & MSTATUS_FS) != 0 &&
> +	    (sbi_mstatus_prev_mode(regs->mstatus) != PRV_U ||
> +	     (csr_read(CSR_SSTATUS) & SSTATUS_FS) != 0) &&
> +	    (insn & INSN_MASK_FSH) == INSN_MATCH_FSH) {
> +		tcntx->trap.cause = CAUSE_MISALIGNED_LOAD;

Nit: This should be CAUSE_MISALIGNED_STORE

> +		tcntx->trap.tval  = GET_RS1(insn, regs) + IMM_S(insn);
> +		return sbi_misaligned_store_handler(tcntx);
> +	}
> +
> +	return truly_illegal_insn(insn, regs);
> +}



-Olof



More information about the opensbi mailing list