20.5-7CMO II: CSR Controls & Instruction Encodings

Part III Linux boot: recommended Vol. I (Unprivileged) pp. 104–111 · ~4 min read

The xenvcfg gating trees

You met the CBIE/CBCFE/CBZE fields on the menvcfg, senvcfg, and henvcfg pages; here is the full decision logic they feed. The shape is always the same cascade — M’s denial is illegal-instruction; the hypervisor’s or guest kernel’s denial is virtual-instruction, so the trap lands at the layer that can emulate or reject:

CBO.INVAL under the CBIE fields (00 = trap, 01 = execute as FLUSH, 11 = execute as invalidate; 10 reserved)
Outcome
priv < M ∧ menvcfg.CBIE=00, or U ∧ senvcfg.CBIE=00Illegal-instruction exception.
VS ∧ henvcfg.CBIE=00, or VU ∧ (henvcfg or senvcfg =00)Virtual-instruction exception.
ANY governing level has CBIE=01Executes, but performs a FLUSH operation.
All governing levels CBIE=11Executes a true invalidate.
Dotted-underlined cells have explanations — click one.

CBO.CLEAN/CBO.FLUSH follow the same tree on the boolean CBCFE bits (execute or trap — no downgrade tier), and CBO.ZERO on CBZE. The fields in different xenvcfg registers never affect each other’s read/write behavior; all are WARL, with the legal values learned from the platform’s discovery data.

Encodings

imm12 = op3120rs11915010141200000117000111160CBO.* (MISC-MEM, funct3=010)
Click a field for its role.
offset[11:5]31250/1/32420rs11915110141200000117001001160PREFETCH.I/R/W (OP-IMM: ORI with rd=x0)
Click a field for its role.

Semantics fine print: cbo.clean may legally be implemented as a flush, and so may cbo.inval (writeback-then-invalidate is indistinguishable from the permitted outcomes). CBO management ops ignore cacheability attributes — a PBMT-downgraded page still gets its block operated on. CBO.ZERO writes its zeros in any order, granularity, and atomicity, cacheable target or not. Prefetch composition with NTL hints steers the destination level.

Discovery: software must learn the management/prefetch block size, the (possibly different) CBO.ZERO block size, and per-level CBIE support from the execution environment — device tree (riscv,cbom-block-size, riscv,cboz-block-size) or ACPI, not CSRs.

Hardware Designer Notes

Sizing note for CBO.ZERO: advertise the zero-block size equal to your cache-line size only if a full-line non-allocating store path exists; otherwise a smaller advertised size (even 8 bytes) is conformant and keeps clear_page correct, just slower. The discovery split between cbom/cboz block sizes exists precisely for this freedom.

Minimal Linux-boot hart MUST

  • Implement the three gating cascades exactly, including the any-level-01 flush downgrade for CBIE and the illegal-vs-virtual selection
  • Keep the CBO imm12 decode strict — values other than 0/1/2/4 under funct3=010 are reserved and must trap
  • Block-align internally from an arbitrary rs1, while reporting the unaligned rs1 in xtval on faults

MAY simplify / trap-and-emulate

  • Implement CBO.ZERO as a full-line store-buffer allocation without fetching the old line — its raison d’être (Linux uses it for clear_page when advertised)
  • Treat all three prefetches as no-ops, or route them into your existing prefetcher’s request queue with I/R/W intent

Check yourself — CBO controls & encodings

1.Why would an OS deliberately set senvcfg.CBIE = 01 (execute-as-flush) instead of 11 (invalidate) for user mode?

2.In VU-mode, CBO.ZERO executes only when which enables are set?

3.How are the four CBO instructions and three prefetches distinguished in the encoding?

4.What must software discover before using these instructions, and how?

4 questions