Commit 61a9b712 authored by Palmer Dabbelt's avatar Palmer Dabbelt

Merge patch series "Putting some basic order on isa extension lists"

This cleans up the ISA string handling to more closely match a version
of the ISA spec.  This is visible in /proc/cpuinfo and the ordering
changes may break something in userspace, but these orderings have
changed before without issues so with any luck that's still the case.

This also adds documentation so userspace has a better idea of what is
intended when it comes to compatibility for /proc/cpuinfo, which should
help everyone as this will likely keep changing.

* b4-shazam-merge:
  Documentation: riscv: add a section about ISA string ordering in /proc/cpuinfo
  RISC-V: resort all extensions in consistent orders
  RISC-V: clarify ISA string ordering rules in cpu.c

Link: https://lore.kernel.org/r/20221205144525.2148448-1-conor.dooley@microchip.comSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parents ae4d39f7 f07b2b3f
...@@ -3,4 +3,46 @@ ...@@ -3,4 +3,46 @@
RISC-V Linux User ABI RISC-V Linux User ABI
===================== =====================
ISA string ordering in /proc/cpuinfo
------------------------------------
The canonical order of ISA extension names in the ISA string is defined in
chapter 27 of the unprivileged specification.
The specification uses vague wording, such as should, when it comes to ordering,
so for our purposes the following rules apply:
#. Single-letter extensions come first, in canonical order.
The canonical order is "IMAFDQLCBKJTPVH".
#. All multi-letter extensions will be separated from other extensions by an
underscore.
#. Additional standard extensions (starting with 'Z') will be sorted after
single-letter extensions and before any higher-privileged extensions.
#. For additional standard extensions, the first letter following the 'Z'
conventionally indicates the most closely related alphabetical
extension category. If multiple 'Z' extensions are named, they will be ordered
first by category, in canonical order, as listed above, then alphabetically
within a category.
#. Standard supervisor-level extensions (starting with 'S') will be listed
after standard unprivileged extensions. If multiple supervisor-level
extensions are listed, they will be ordered alphabetically.
#. Standard machine-level extensions (starting with 'Zxm') will be listed
after any lower-privileged, standard extensions. If multiple machine-level
extensions are listed, they will be ordered alphabetically.
#. Non-standard extensions (starting with 'X') will be listed after all standard
extensions. If multiple non-standard extensions are listed, they will be
ordered alphabetically.
An example string following the order is::
rv64imadc_zifoo_zigoo_zafoo_sbar_scar_zxmbaz_xqux_xrux
Misaligned accesses
-------------------
Misaligned accesses are supported in userspace, but they may perform poorly. Misaligned accesses are supported in userspace, but they may perform poorly.
...@@ -51,14 +51,15 @@ extern unsigned long elf_hwcap; ...@@ -51,14 +51,15 @@ extern unsigned long elf_hwcap;
* RISCV_ISA_EXT_MAX. 0-25 range is reserved for single letter * RISCV_ISA_EXT_MAX. 0-25 range is reserved for single letter
* extensions while all the multi-letter extensions should define the next * extensions while all the multi-letter extensions should define the next
* available logical extension id. * available logical extension id.
* Entries are sorted alphabetically.
*/ */
enum riscv_isa_ext_id { enum riscv_isa_ext_id {
RISCV_ISA_EXT_SSCOFPMF = RISCV_ISA_EXT_BASE, RISCV_ISA_EXT_SSCOFPMF = RISCV_ISA_EXT_BASE,
RISCV_ISA_EXT_SSTC,
RISCV_ISA_EXT_SVINVAL,
RISCV_ISA_EXT_SVPBMT, RISCV_ISA_EXT_SVPBMT,
RISCV_ISA_EXT_ZICBOM, RISCV_ISA_EXT_ZICBOM,
RISCV_ISA_EXT_ZIHINTPAUSE, RISCV_ISA_EXT_ZIHINTPAUSE,
RISCV_ISA_EXT_SSTC,
RISCV_ISA_EXT_SVINVAL,
RISCV_ISA_EXT_ID_MAX RISCV_ISA_EXT_ID_MAX
}; };
static_assert(RISCV_ISA_EXT_ID_MAX <= RISCV_ISA_EXT_MAX); static_assert(RISCV_ISA_EXT_ID_MAX <= RISCV_ISA_EXT_MAX);
...@@ -67,11 +68,12 @@ static_assert(RISCV_ISA_EXT_ID_MAX <= RISCV_ISA_EXT_MAX); ...@@ -67,11 +68,12 @@ static_assert(RISCV_ISA_EXT_ID_MAX <= RISCV_ISA_EXT_MAX);
* This enum represents the logical ID for each RISC-V ISA extension static * This enum represents the logical ID for each RISC-V ISA extension static
* keys. We can use static key to optimize code path if some ISA extensions * keys. We can use static key to optimize code path if some ISA extensions
* are available. * are available.
* Entries are sorted alphabetically.
*/ */
enum riscv_isa_ext_key { enum riscv_isa_ext_key {
RISCV_ISA_EXT_KEY_FPU, /* For 'F' and 'D' */ RISCV_ISA_EXT_KEY_FPU, /* For 'F' and 'D' */
RISCV_ISA_EXT_KEY_ZIHINTPAUSE,
RISCV_ISA_EXT_KEY_SVINVAL, RISCV_ISA_EXT_KEY_SVINVAL,
RISCV_ISA_EXT_KEY_ZIHINTPAUSE,
RISCV_ISA_EXT_KEY_MAX, RISCV_ISA_EXT_KEY_MAX,
}; };
...@@ -91,10 +93,10 @@ static __always_inline int riscv_isa_ext2key(int num) ...@@ -91,10 +93,10 @@ static __always_inline int riscv_isa_ext2key(int num)
return RISCV_ISA_EXT_KEY_FPU; return RISCV_ISA_EXT_KEY_FPU;
case RISCV_ISA_EXT_d: case RISCV_ISA_EXT_d:
return RISCV_ISA_EXT_KEY_FPU; return RISCV_ISA_EXT_KEY_FPU;
case RISCV_ISA_EXT_ZIHINTPAUSE:
return RISCV_ISA_EXT_KEY_ZIHINTPAUSE;
case RISCV_ISA_EXT_SVINVAL: case RISCV_ISA_EXT_SVINVAL:
return RISCV_ISA_EXT_KEY_SVINVAL; return RISCV_ISA_EXT_KEY_SVINVAL;
case RISCV_ISA_EXT_ZIHINTPAUSE:
return RISCV_ISA_EXT_KEY_ZIHINTPAUSE;
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -144,30 +144,53 @@ arch_initcall(riscv_cpuinfo_init); ...@@ -144,30 +144,53 @@ arch_initcall(riscv_cpuinfo_init);
.uprop = #UPROP, \ .uprop = #UPROP, \
.isa_ext_id = EXTID, \ .isa_ext_id = EXTID, \
} }
/* /*
* Here are the ordering rules of extension naming defined by RISC-V * The canonical order of ISA extension names in the ISA string is defined in
* specification : * chapter 27 of the unprivileged specification.
* 1. All extensions should be separated from other multi-letter extensions *
* by an underscore. * Ordinarily, for in-kernel data structures, this order is unimportant but
* 2. The first letter following the 'Z' conventionally indicates the most * isa_ext_arr defines the order of the ISA string in /proc/cpuinfo.
*
* The specification uses vague wording, such as should, when it comes to
* ordering, so for our purposes the following rules apply:
*
* 1. All multi-letter extensions must be separated from other extensions by an
* underscore.
*
* 2. Additional standard extensions (starting with 'Z') must be sorted after
* single-letter extensions and before any higher-privileged extensions.
* 3. The first letter following the 'Z' conventionally indicates the most
* closely related alphabetical extension category, IMAFDQLCBKJTPVH. * closely related alphabetical extension category, IMAFDQLCBKJTPVH.
* If multiple 'Z' extensions are named, they should be ordered first * If multiple 'Z' extensions are named, they must be ordered first by
* by category, then alphabetically within a category. * category, then alphabetically within a category.
* 3. Standard supervisor-level extensions (starts with 'S') should be *
* listed after standard unprivileged extensions. If multiple * 3. Standard supervisor-level extensions (starting with 'S') must be listed
* supervisor-level extensions are listed, they should be ordered * after standard unprivileged extensions. If multiple supervisor-level
* extensions are listed, they must be ordered alphabetically.
*
* 4. Standard machine-level extensions (starting with 'Zxm') must be listed
* after any lower-privileged, standard extensions. If multiple
* machine-level extensions are listed, they must be ordered
* alphabetically. * alphabetically.
* 4. Non-standard extensions (starts with 'X') must be listed after all *
* standard extensions. They must be separated from other multi-letter * 5. Non-standard extensions (starting with 'X') must be listed after all
* extensions by an underscore. * standard extensions. If multiple non-standard extensions are listed, they
* must be ordered alphabetically.
*
* An example string following the order is:
* rv64imadc_zifoo_zigoo_zafoo_sbar_scar_zxmbaz_xqux_xrux
*
* New entries to this struct should follow the ordering rules described above.
*/ */
static struct riscv_isa_ext_data isa_ext_arr[] = { static struct riscv_isa_ext_data isa_ext_arr[] = {
__RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),
__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF), __RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC), __RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
__RISCV_ISA_EXT_DATA(svinval, RISCV_ISA_EXT_SVINVAL), __RISCV_ISA_EXT_DATA(svinval, RISCV_ISA_EXT_SVINVAL),
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT), __RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
__RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),
__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
__RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX), __RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
}; };
......
...@@ -222,12 +222,13 @@ void __init riscv_fill_hwcap(void) ...@@ -222,12 +222,13 @@ void __init riscv_fill_hwcap(void)
set_bit(nr, this_isa); set_bit(nr, this_isa);
} }
} else { } else {
/* sorted alphabetically */
SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF); SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF);
SET_ISA_EXT_MAP("sstc", RISCV_ISA_EXT_SSTC);
SET_ISA_EXT_MAP("svinval", RISCV_ISA_EXT_SVINVAL);
SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT); SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM); SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM);
SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE); SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE);
SET_ISA_EXT_MAP("sstc", RISCV_ISA_EXT_SSTC);
SET_ISA_EXT_MAP("svinval", RISCV_ISA_EXT_SVINVAL);
} }
#undef SET_ISA_EXT_MAP #undef SET_ISA_EXT_MAP
} }
...@@ -307,6 +308,7 @@ static bool __init_or_module cpufeature_probe_zicbom(unsigned int stage) ...@@ -307,6 +308,7 @@ static bool __init_or_module cpufeature_probe_zicbom(unsigned int stage)
* This code may also be executed before kernel relocation, so we cannot use * This code may also be executed before kernel relocation, so we cannot use
* addresses generated by the address-of operator as they won't be valid in * addresses generated by the address-of operator as they won't be valid in
* this context. * this context.
* Tests, unless otherwise required, are to be added in alphabetical order.
*/ */
static u32 __init_or_module cpufeature_probe(unsigned int stage) static u32 __init_or_module cpufeature_probe(unsigned int stage)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment