mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-13 23:34:05 +08:00
RISC-V: enable extension detection from dedicated properties
Add support for parsing the new riscv,isa-extensions property in riscv_fill_hwcap(), by means of a new "property" member of the riscv_isa_ext_data struct. For now, this shadows the name of the extension for all users, however this may not be the case for all extensions, based on how the dt-binding is written. For the sake of backwards compatibility, fall back to the old scheme if the new properties are not detected. For now, just inform, rather than warn, when that happens. Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Signed-off-by: Conor Dooley <conor.dooley@microchip.com> Link: https://lore.kernel.org/r/20230713-vocation-profane-39a74b3c2649@wendy Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
parent
4265b0ec5e
commit
90700a4fbf
@ -76,6 +76,7 @@ unsigned long riscv_get_elf_hwcap(void);
|
||||
struct riscv_isa_ext_data {
|
||||
const unsigned int id;
|
||||
const char *name;
|
||||
const char *property;
|
||||
};
|
||||
|
||||
extern const struct riscv_isa_ext_data riscv_isa_ext[];
|
||||
|
@ -101,6 +101,7 @@ static bool riscv_isa_extension_check(int id)
|
||||
|
||||
#define __RISCV_ISA_EXT_DATA(_name, _id) { \
|
||||
.name = #_name, \
|
||||
.property = #_name, \
|
||||
.id = _id, \
|
||||
}
|
||||
|
||||
@ -414,11 +415,69 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap)
|
||||
acpi_put_table((struct acpi_table_header *)rhct);
|
||||
}
|
||||
|
||||
static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
|
||||
{
|
||||
unsigned int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
unsigned long this_hwcap = 0;
|
||||
struct device_node *cpu_node;
|
||||
struct riscv_isainfo *isainfo = &hart_isa[cpu];
|
||||
|
||||
cpu_node = of_cpu_device_node_get(cpu);
|
||||
if (!cpu_node) {
|
||||
pr_warn("Unable to find cpu node\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!of_property_present(cpu_node, "riscv,isa-extensions")) {
|
||||
of_node_put(cpu_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < riscv_isa_ext_count; i++) {
|
||||
if (of_property_match_string(cpu_node, "riscv,isa-extensions",
|
||||
riscv_isa_ext[i].property) < 0)
|
||||
continue;
|
||||
|
||||
if (!riscv_isa_extension_check(riscv_isa_ext[i].id))
|
||||
continue;
|
||||
|
||||
/* Only single letter extensions get set in hwcap */
|
||||
if (strnlen(riscv_isa_ext[i].name, 2) == 1)
|
||||
this_hwcap |= isa2hwcap[riscv_isa_ext[i].id];
|
||||
|
||||
set_bit(riscv_isa_ext[i].id, isainfo->isa);
|
||||
}
|
||||
|
||||
of_node_put(cpu_node);
|
||||
|
||||
/*
|
||||
* All "okay" harts should have same isa. Set HWCAP based on
|
||||
* common capabilities of every "okay" hart, in case they don't.
|
||||
*/
|
||||
if (elf_hwcap)
|
||||
elf_hwcap &= this_hwcap;
|
||||
else
|
||||
elf_hwcap = this_hwcap;
|
||||
|
||||
if (bitmap_empty(riscv_isa, RISCV_ISA_EXT_MAX))
|
||||
bitmap_copy(riscv_isa, isainfo->isa, RISCV_ISA_EXT_MAX);
|
||||
else
|
||||
bitmap_and(riscv_isa, riscv_isa, isainfo->isa, RISCV_ISA_EXT_MAX);
|
||||
}
|
||||
|
||||
if (bitmap_empty(riscv_isa, RISCV_ISA_EXT_MAX))
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init riscv_fill_hwcap(void)
|
||||
{
|
||||
char print_str[NUM_ALPHA_EXTS + 1];
|
||||
int i, j;
|
||||
unsigned long isa2hwcap[26] = {0};
|
||||
int i, j;
|
||||
|
||||
isa2hwcap['i' - 'a'] = COMPAT_HWCAP_ISA_I;
|
||||
isa2hwcap['m' - 'a'] = COMPAT_HWCAP_ISA_M;
|
||||
@ -428,10 +487,21 @@ void __init riscv_fill_hwcap(void)
|
||||
isa2hwcap['c' - 'a'] = COMPAT_HWCAP_ISA_C;
|
||||
isa2hwcap['v' - 'a'] = COMPAT_HWCAP_ISA_V;
|
||||
|
||||
riscv_fill_hwcap_from_isa_string(isa2hwcap);
|
||||
if (!acpi_disabled) {
|
||||
riscv_fill_hwcap_from_isa_string(isa2hwcap);
|
||||
} else {
|
||||
int ret = riscv_fill_hwcap_from_ext_list(isa2hwcap);
|
||||
|
||||
/* We don't support systems with F but without D, so mask those out
|
||||
* here. */
|
||||
if (ret) {
|
||||
pr_info("Falling back to deprecated \"riscv,isa\"\n");
|
||||
riscv_fill_hwcap_from_isa_string(isa2hwcap);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't support systems with F but without D, so mask those out
|
||||
* here.
|
||||
*/
|
||||
if ((elf_hwcap & COMPAT_HWCAP_ISA_F) && !(elf_hwcap & COMPAT_HWCAP_ISA_D)) {
|
||||
pr_info("This kernel does not support systems with F but not D\n");
|
||||
elf_hwcap &= ~COMPAT_HWCAP_ISA_F;
|
||||
|
Loading…
Reference in New Issue
Block a user