Unverified Commit 4265b0ec authored by Conor Dooley's avatar Conor Dooley Committed by Palmer Dabbelt
Browse files

RISC-V: split riscv_fill_hwcap() in 3



Before adding more complexity to it, split riscv_fill_hwcap() into 3
distinct sections:
- riscv_fill_hwcap() still is the top level function, into which the
  additional complexity will be added.
- riscv_fill_hwcap_from_isa_string() handles getting the information
  from the riscv,isa/ACPI equivalent across harts & the various quirks
  there
- riscv_parse_isa_string() does what it says on the tin.

Reviewed-by: default avatarAndrew Jones <ajones@ventanamicro.com>
Signed-off-by: default avatarConor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20230713-daylight-puritan-37aeb41a4d9b@wendy


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent effc122a
Loading
Loading
Loading
Loading
+177 −168
Original line number Diff line number Diff line
@@ -178,60 +178,9 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {

const size_t riscv_isa_ext_count = ARRAY_SIZE(riscv_isa_ext);

void __init riscv_fill_hwcap(void)
static void __init riscv_parse_isa_string(unsigned long *this_hwcap, struct riscv_isainfo *isainfo,
					  unsigned long *isa2hwcap, const char *isa)
{
	struct device_node *node;
	const char *isa;
	char print_str[NUM_ALPHA_EXTS + 1];
	int i, j, rc;
	unsigned long isa2hwcap[26] = {0};
	struct acpi_table_header *rhct;
	acpi_status status;
	unsigned int cpu;

	isa2hwcap['i' - 'a'] = COMPAT_HWCAP_ISA_I;
	isa2hwcap['m' - 'a'] = COMPAT_HWCAP_ISA_M;
	isa2hwcap['a' - 'a'] = COMPAT_HWCAP_ISA_A;
	isa2hwcap['f' - 'a'] = COMPAT_HWCAP_ISA_F;
	isa2hwcap['d' - 'a'] = COMPAT_HWCAP_ISA_D;
	isa2hwcap['c' - 'a'] = COMPAT_HWCAP_ISA_C;
	isa2hwcap['v' - 'a'] = COMPAT_HWCAP_ISA_V;

	elf_hwcap = 0;

	bitmap_zero(riscv_isa, RISCV_ISA_EXT_MAX);

	if (!acpi_disabled) {
		status = acpi_get_table(ACPI_SIG_RHCT, 0, &rhct);
		if (ACPI_FAILURE(status))
			return;
	}

	for_each_possible_cpu(cpu) {
		struct riscv_isainfo *isainfo = &hart_isa[cpu];
		unsigned long this_hwcap = 0;

		if (acpi_disabled) {
			node = of_cpu_device_node_get(cpu);
			if (!node) {
				pr_warn("Unable to find cpu node\n");
				continue;
			}

			rc = of_property_read_string(node, "riscv,isa", &isa);
			of_node_put(node);
			if (rc) {
				pr_warn("Unable to find \"riscv,isa\" devicetree entry\n");
				continue;
			}
		} else {
			rc = acpi_get_riscv_isa(rhct, cpu, &isa);
			if (rc < 0) {
				pr_warn("Unable to get ISA for the hart - %d\n", cpu);
				continue;
			}
		}

	/*
	 * For all possible cpus, we have already validated in
	 * the boot process that they at least contain "rv" and
@@ -374,7 +323,7 @@ void __init riscv_fill_hwcap(void)
			int nr = tolower(*ext) - 'a';

			if (riscv_isa_extension_check(nr)) {
					this_hwcap |= isa2hwcap[nr];
				*this_hwcap |= isa2hwcap[nr];
				set_bit(nr, isainfo->isa);
			}
		} else {
@@ -384,6 +333,49 @@ void __init riscv_fill_hwcap(void)
		}
#undef SET_ISA_EXT_MAP
	}
}

static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap)
{
	struct device_node *node;
	const char *isa;
	int rc;
	struct acpi_table_header *rhct;
	acpi_status status;
	unsigned int cpu;

	if (!acpi_disabled) {
		status = acpi_get_table(ACPI_SIG_RHCT, 0, &rhct);
		if (ACPI_FAILURE(status))
			return;
	}

	for_each_possible_cpu(cpu) {
		struct riscv_isainfo *isainfo = &hart_isa[cpu];
		unsigned long this_hwcap = 0;

		if (acpi_disabled) {
			node = of_cpu_device_node_get(cpu);
			if (!node) {
				pr_warn("Unable to find cpu node\n");
				continue;
			}

			rc = of_property_read_string(node, "riscv,isa", &isa);
			of_node_put(node);
			if (rc) {
				pr_warn("Unable to find \"riscv,isa\" devicetree entry\n");
				continue;
			}
		} else {
			rc = acpi_get_riscv_isa(rhct, cpu, &isa);
			if (rc < 0) {
				pr_warn("Unable to get ISA for the hart - %d\n", cpu);
				continue;
			}
		}

		riscv_parse_isa_string(&this_hwcap, isainfo, isa2hwcap, isa);

		/*
		 * Linux requires the following extensions, so we may as well
@@ -420,6 +412,23 @@ void __init riscv_fill_hwcap(void)

	if (!acpi_disabled && rhct)
		acpi_put_table((struct acpi_table_header *)rhct);
}

void __init riscv_fill_hwcap(void)
{
	char print_str[NUM_ALPHA_EXTS + 1];
	int i, j;
	unsigned long isa2hwcap[26] = {0};

	isa2hwcap['i' - 'a'] = COMPAT_HWCAP_ISA_I;
	isa2hwcap['m' - 'a'] = COMPAT_HWCAP_ISA_M;
	isa2hwcap['a' - 'a'] = COMPAT_HWCAP_ISA_A;
	isa2hwcap['f' - 'a'] = COMPAT_HWCAP_ISA_F;
	isa2hwcap['d' - 'a'] = COMPAT_HWCAP_ISA_D;
	isa2hwcap['c' - 'a'] = COMPAT_HWCAP_ISA_C;
	isa2hwcap['v' - 'a'] = COMPAT_HWCAP_ISA_V;

	riscv_fill_hwcap_from_isa_string(isa2hwcap);

	/* We don't support systems with F but without D, so mask those out
	 * here. */