mbox series

[RFC,v2,00/19] riscv: add new ISA extensions and profile support

Message ID 20260930-riscv-tuning-rework-v2-0-9e29f3531d0e@baylibre.com
Headers show
Series riscv: add new ISA extensions and profile support | expand

Message

Trevor Gamblin Sept. 30, 2026, 4:38 p.m. UTC
Changes since v1:

- Fixed broken riscv32 changes
- Squashed zifencei changes into new profiles to avoid broken commits
- Kept legacy "riscv64" and "riscv32" as aliases to avoid breaking
  dependent layers
- Replaced use of 'contains()' with 'contains_any()' for
  TUNE_RISCV_MARCH lines in arch-riscv.inc where extensions implied
  others, e.g. 'm' and 'zmmul'. This means that existing riscv64gc
  builds will be rebuilt from scratch because TUNE_CCARGS is different.
  It could also cause issues with older toolchains - I haven't tested
  this.
- Fixed incorrect b -> zkt implied relationship
- Fixed missing extensions in rva23u64 commit message
- Fixed za64rs and za128rs ordering in arch-riscv.inc
- PACKAGE_EXTRA_ARCHS for the profile tunes now lists compatible lower
  archs (gc, then rva20, then rva22, and gcv under rva23)
- RISCV_PROFILES is now documented as a fixed ABI definition that cites
  the Profiles spec
- Implied extensions are dropped from package arch names, and existing
  names stay unchanged
- Added new riscv_implied() function, and a 'RISCV_IMPLIED' table to
  check against
- Added selftests for tune.py Python code in oelib/tune.py
- Added selftests checking integration of default and 'unusual' tunes
  against build system, using libgcc-initial as a build target
- Updated cover letter with new info, removed coreutils test results
  which were not helpful

# Overview

Support for the RISC-V architecture and a basic set of extensions has been
available in oe-core for a long time now, and as of late 2025, QEMU defaults to
the RVA23S64 profile when booting qemuriscv64 images. However, at the userspace
level, we currently support only the standard "riscv64gc" profile (behind a
generic "riscv64" identifier), which is common across the wider open-source
ecosystem, but lacks many of the features which are starting to become necessary
for more advanced experimentation and testing on RISC-V platforms. This series
aims to remedy that by introducing several distinct changes across a few files.
I've broken it up on a per-profile basis for easier review, but the final
version could probably feature some squashed commits. It could also go the route
of breaking tunings up more in the style of those in conf/machine/include/arm/,
but I'll leave them as-is for now to avoid even more rework that needs
reviewing.

A list of changes, by group:

1. Basic clarification changes and extra tunings:
    a. tune-riscv: be explicit about riscv32gc, riscv64gc defaults
    b. tune-riscv.inc: add 'riscv64gcv' tune
2. Adding official RVA20 profile extensions, and supporting the explicit choice
of 'rva20u64' as a tuning option for builds:
    a. arch-riscv.inc: add missing RVA20 extensions
    b. meta/lib/oe/tune.py: support profile strings, add rva20u64
    c. tune-riscv.inc: add rva20u64 to AVAILTUNES
3. Adding RVA22 profile support:
    a. arch-riscv.inc: add rva22u64 extensions
    b. meta/lib/oe/tune.py: add rva22u64 profile
    c. tune-riscv.inc: add rva22u64 to AVAILTUNES
4. Adding RVA23 profile support:
    a. arch-riscv.inc: add rva23u64 extensions
    b. meta/lib/oe/tune.py: add rva23u64 profile
    c. tune-riscv.inc: add rva23u64 to AVAILTUNES
5. Quality-of-life fixups after 1-4:
    a. meta/lib/oe/tune.py: add riscv_pkgarch()
    b. arch-riscv.inc: rename TUNE_RISCV_PKGARCH -> TUNE_RISCV_PKGARCH_EXACT
       in assignments
    c. tune.py: add implied tuning logic
    d. tune.py: add vector extensions to RISCV_IMPLIED
    e. tune-riscv.inc: add RISCV_PKGARCH vars, set PACKAGE_EXTRA_ARCHS
    f. tune-riscv.inc: clarify zifencei comment
6. Selftests:
    a. selftest: oelib: add tune.py
    b. selftest: cases: add riscvtune.py

These changes are also in my contrib branch[1]. The main sources of
truth used were gcc's '-march' options list[2], the official RISC-V
International documentation[3], and the RISC-V ISA Explorer[4], with the
gcc output used to cross-check the results. When comparing against gcc's
output, commands like the following were run:

|tgamblin@megalith ~/workspace/ypbuilds/poky-qemuriscv64/layers/openembedded-core (master)$ riscv64-linux-gnu-gcc -march=rva23u64 -mabi=lp64d -Q --help=target | grep rv64
|  -march=                               rv64imafdcbv_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicond_zicsr_zihintntl_zihintpause_zihpm_zimop_zmmul_za64rs_zaamo_zalrsc_zawrs_zfa_zfhmin_zca_zcb_zcd_zcmop_zba_zbb_zbs_zkt_zvbb_zve32f_zve32x_zve64d_zve64f_zve64x_zvfhmin_z

However, as is visible above, the extension list became so long for the RVA23
case that it was truncated, and so a more verbose output from the following was
checked instead:

|riscv64-linux-gnu-gcc -march=rva23u64 -mabi=lp64d -v -xc /dev/null -c -o /dev/null

For now, the default tuning remains riscv64gc (with the naming rework in
1a), despite the presence of the other profiles. There are also several
extensions which are depended on by others, and other known examples
which aren't strictly part of the official profiles but must be included
for the Yocto/OE case, such as 'zifencei' being necessary to build the
Linux Kernel (which already had been addressed before, but this series
handles slightly differently). No attempts are made to add extensions
which are not part of these profiles - those could be added in the
future, but these changes are significant enough for now. It might be
worth adding some more documentation about how all of this works - I'd
be happy to hear what people think about that too.

One significant change to the way profile strings are processed with
these patches shows up in sstate/build path naming, and is part of the
reason for patch 5a-5d above. Before, a build directory
might have a path in it like:

|build/tmp/work/riscv64imafdc_zicsr_zifencei-poky-linux/

This was fine when the extension list was short (for riscv64gc), but with the
full RVA profiles, the paths started to get so long that bitbake would produce
this error:

|ERROR: Unable to reduce sstate name to less than 255 chararacters

To solve this problem, meta/lib/oe/tune.py now supports a very short
list of profile names, and includes new functions (riscv_pkgarch() and
riscv_implied()) designed to compare selected extensions against
dependencies (profile and otherwise), and shorten path names
appropriately. As an example, if you set the following in local.conf:

|AVAILTUNES += "my-rva20-tune"
|TUNE_FEATURES:tune-my-rva20-tune = "${@oe.tune.riscv_isa_to_tune('rv64gc')} ziccamoa ziccif zicclsm ziccrse zicntr za128rs"
|PACKAGE_EXTRA_ARCHS:tune-my-rva20-tune = "${TUNE_RISCV_PKGARCH}"
|DEFAULTTUNE = "my-rva20-tune"

then 'bitbake-getvar --value TUNE_PKGARCH' shows that it is recognized
as the RVA20 profile:

|rva20u64_zifencei

Extensions implied by others (e.g. 'zmmul', implied by 'm') don't need
to be listed, but if they are the same result is obtained.

With all of this combined, subdirectories in tmp/work/ look like:

|tgamblin@megalith ~/workspace/ypbuilds/poky-qemuriscv64 $ ls build/tmp/work/
|all-poky-linux          qemuriscv64-poky-linux                   rva20u64_zcmop_zifencei_zihintpause_zimop_zvbb-poky-linux  rva23u64_zifencei-poky-linux
|qemuriscv32-poky-linux  riscv32imafdc_zicsr_zifencei-poky-linux  rva20u64_zifencei-poky-linux                               x86_64-linux

Note that 'rva20u64_zcmop_zifencei_zihintpause_zimop_zvbb-poky-linux' is
a custom configuration that I set in local.conf only for testing
purposes. Custom tunings still run the ris(c|k) of exceeding the naming
length, which we may need some extra hashing logic (maybe a bitmask?) to
handle if we want to enable freely customizing build tunings. 

# Testing

Testing different profiles' validity against the compiler involved
setting (for example) DEFAULTTUNE = "rva23u64" and then running 'bitbake
opensbi' (which also results in a kernel rebuild) as a quick smoke test.
I've also opted to do full image builds to make sure that the new
profiles fully boot and run without any obvious errors. I've also run a
series of boot tests (including ptests for packages like coreutils).
Note that when the vector extension is enabled (riscv64gcv, rva23u64),
test durations will generally be higher.

As of v2, I've added some selftests to help:

1. The 'oelib.tune' suite at meta/lib/oeqa/selftest/cases/oelib/tune.py,
   for testing the riscv_pkgarch(), riscv_isa_to_tune(), and
   riscv_implied() functions
2. The 'riscvtune' suite at meta/lib/oeqa/selftest/cases/riscvtune.py,
   for parsing and building against defined and unusual custom tunes to
   ensure they each yield a usable package arch

These can be run with:

oe-selftest --run-tests oelib.tune
oe-selftest --run-tests riscvtune

Results from each:

oe-selftest --run-tests oelib.tune:

|2026-09-30 11:29:04,157 - oe-selftest - INFO - ----------------------------------------------------------------------
|2026-09-30 11:29:04,157 - oe-selftest - INFO - Ran 14 tests in 5.131s
|2026-09-30 11:29:04,157 - oe-selftest - INFO - OK
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS:
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvImplied.test_implied: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvImplied.test_profiles_nest: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvImplied.test_zicsr_kept: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvIsaToTune.test_abbreviation: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvIsaToTune.test_explicit: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvIsaToTune.test_not_riscv: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvIsaToTune.test_profile: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvPkgarch.test_exact_drops_implied: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvPkgarch.test_exact_keeps_bitmanip: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvPkgarch.test_existing_names_unchanged: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvPkgarch.test_implied_not_listed: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvPkgarch.test_most_specific_profile: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvPkgarch.test_no_features: PASSED (0.00s)
|2026-09-30 11:29:06,594 - oe-selftest - INFO - RESULTS - oelib.tune.TestRiscvPkgarch.test_profiles: PASSED (0.00s)
|2026-09-30 11:29:06,595 - oe-selftest - INFO - SUMMARY:
|2026-09-30 11:29:06,595 - oe-selftest - INFO - oe-selftest () - Ran 14 tests in 5.131s
|2026-09-30 11:29:06,595 - oe-selftest - INFO - oe-selftest - OK - All required tests passed (successes=14, skipped=0, failures=0, errors=0)

oe-selftest --run-tests riscvtune:

|2026-09-30 11:29:53,910 - oe-selftest - INFO - Adding: "include selftest.inc" in /home/tgamblin/workspace/ypbuilds/poky-qemuriscv64/build-st/conf/local.conf
|2026-09-30 11:29:53,910 - oe-selftest - INFO - Adding: "include bblayers.inc" in bblayers.conf
|2026-09-30 11:29:54,568 - oe-selftest - INFO - test_riscv_default_tunes (riscvtune.RiscvTuneTests.test_riscv_default_tunes)
|2026-09-30 11:30:23,372 - oe-selftest - INFO -  ... ok
|2026-09-30 11:30:23,372 - oe-selftest - INFO - test_riscv_unusual_tunes (riscvtune.RiscvTuneTests.test_riscv_unusual_tunes)
|2026-09-30 11:31:34,612 - oe-selftest - INFO -  ... ok
|2026-09-30 11:31:39,676 - oe-selftest - INFO - ----------------------------------------------------------------------
|2026-09-30 11:31:39,676 - oe-selftest - INFO - Ran 2 tests in 105.884s
|2026-09-30 11:31:39,676 - oe-selftest - INFO - OK
|2026-09-30 11:31:42,109 - oe-selftest - INFO - RESULTS:
|2026-09-30 11:31:42,109 - oe-selftest - INFO - RESULTS - riscvtune.RiscvTuneTests.test_riscv_default_tunes: PASSED (28.80s)
|2026-09-30 11:31:42,109 - oe-selftest - INFO - RESULTS - riscvtune.RiscvTuneTests.test_riscv_unusual_tunes: PASSED (71.24s)
|2026-09-30 11:31:42,109 - oe-selftest - INFO - SUMMARY:
|2026-09-30 11:31:42,110 - oe-selftest - INFO - oe-selftest () - Ran 2 tests in 105.885s
|2026-09-30 11:31:42,110 - oe-selftest - INFO - oe-selftest - OK - All required tests passed (successes=2, skipped=0, failures=0, errors=0)

[1]: https://git.openembedded.org/openembedded-core-contrib/log/?h=tgamblin/riscv-tuning-rework
[2]: https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Options.html
[3]: https://docs.riscv.org/reference/home/index.html
[4]: https://riscv.github.io/riscv-isa-explorer/

---
Trevor Gamblin (19):
      tune-riscv: be explicit about riscv32gc, riscv64gc defaults
      tune-riscv.inc: add 'riscv64gcv' tune
      arch-riscv.inc: add missing RVA20 extensions
      meta/lib/oe/tune.py: support profile strings, add rva20u64
      tune-riscv.inc: add rva20u64 to AVAILTUNES
      arch-riscv.inc: add rva22u64 extensions
      meta/lib/oe/tune.py: add rva22u64 profile
      tune-riscv.inc: add rva22u64 to AVAILTUNES
      arch-riscv.inc: add rva23u64 extensions
      meta/lib/oe/tune.py: add rva23u64 profile
      tune-riscv.inc: add rva23u64 to AVAILTUNES
      meta/lib/oe/tune.py: add riscv_pkgarch()
      arch-riscv.inc: rename TUNE_RISCV_PKGARCH -> TUNE_RISCV_PKGARCH_EXACT in assignments
      tune.py: add implied tuning logic
      tune.py: add vector extensions to RISCV_IMPLIED
      tune-riscv.inc: add RISCV_PKGARCH vars, set PACKAGE_EXTRA_ARCHS
      tune-riscv.inc: clarify zifencei comment
      selftest: oelib: add tune.py
      selftest: cases: add riscvtune.py

 meta/conf/machine/include/riscv/arch-riscv.inc | 198 ++++++++++++++++++++++---
 meta/conf/machine/include/riscv/tune-riscv.inc |  43 +++++-
 meta/conf/machine/qemuriscv32.conf             |   2 +-
 meta/lib/oe/tune.py                            | 102 ++++++++++++-
 meta/lib/oeqa/selftest/cases/oelib/tune.py     |  88 +++++++++++
 meta/lib/oeqa/selftest/cases/riscvtune.py      |  96 ++++++++++++
 6 files changed, 503 insertions(+), 26 deletions(-)
---
base-commit: 187f1a5b8e61b0a09c617cd3ccc2e3fd1f6c42bd
change-id: 20260929-riscv-tuning-rework-417f68122f90

Best regards,
--  
Trevor Gamblin <tgamblin@baylibre.com>