Skip to content

Commit

Permalink
riscv: vector: Use vlenb from DT for thead
Browse files Browse the repository at this point in the history
If thead,vlenb is provided in the device tree, prefer that over reading
the vlenb csr.

Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Tested-by: Yangyu Chen <cyy@cyyself.name>
Link: https://lore.kernel.org/r/20241113-xtheadvector-v11-5-236c22791ef9@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
  • Loading branch information
Charlie Jenkins authored and Palmer Dabbelt committed Jan 18, 2025
1 parent cddd638 commit 377be47
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 1 deletion.
13 changes: 13 additions & 0 deletions arch/riscv/Kconfig.vendor
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ config RISCV_ISA_VENDOR_EXT_THEAD
extensions. Without this option enabled, T-Head vendor extensions will
not be detected at boot and their presence not reported to userspace.

If you don't know what to do here, say Y.

config RISCV_ISA_XTHEADVECTOR
bool "xtheadvector extension support"
depends on RISCV_ISA_VENDOR_EXT_THEAD
depends on RISCV_ISA_V
depends on FPU
default y
help
Say N here if you want to disable all xtheadvector related procedures
in the kernel. This will disable vector for any T-Head board that
contains xtheadvector rather than the standard vector.

If you don't know what to do here, say Y.
endmenu

Expand Down
2 changes: 2 additions & 0 deletions arch/riscv/include/asm/cpufeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);
/* Per-cpu ISA extensions. */
extern struct riscv_isainfo hart_isa[NR_CPUS];

extern u32 thead_vlenb_of;

void __init riscv_user_isa_enable(void);

#define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size, _validate) { \
Expand Down
6 changes: 6 additions & 0 deletions arch/riscv/include/asm/vendor_extensions/thead.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@

extern struct riscv_isa_vendor_ext_data_list riscv_isa_vendor_ext_list_thead;

#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_THEAD
void disable_xtheadvector(void);
#else
static inline void disable_xtheadvector(void) { }
#endif

#endif
48 changes: 48 additions & 0 deletions arch/riscv/kernel/cpufeature.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
/* Per-cpu ISA extensions. */
struct riscv_isainfo hart_isa[NR_CPUS];

u32 thead_vlenb_of;

/**
* riscv_isa_extension_base() - Get base extension word
*
Expand Down Expand Up @@ -779,6 +781,46 @@ static void __init riscv_fill_vendor_ext_list(int cpu)
}
}

static int has_thead_homogeneous_vlenb(void)
{
int cpu;
u32 prev_vlenb = 0;
u32 vlenb;

/* Ignore thead,vlenb property if xtheavector is not enabled in the kernel */
if (!IS_ENABLED(CONFIG_RISCV_ISA_XTHEADVECTOR))
return 0;

for_each_possible_cpu(cpu) {
struct device_node *cpu_node;

cpu_node = of_cpu_device_node_get(cpu);
if (!cpu_node) {
pr_warn("Unable to find cpu node\n");
return -ENOENT;
}

if (of_property_read_u32(cpu_node, "thead,vlenb", &vlenb)) {
of_node_put(cpu_node);

if (prev_vlenb)
return -ENOENT;
continue;
}

if (prev_vlenb && vlenb != prev_vlenb) {
of_node_put(cpu_node);
return -ENOENT;
}

prev_vlenb = vlenb;
of_node_put(cpu_node);
}

thead_vlenb_of = vlenb;
return 0;
}

static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
{
unsigned int cpu;
Expand Down Expand Up @@ -832,6 +874,12 @@ static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
riscv_fill_vendor_ext_list(cpu);
}

if (riscv_isa_vendor_extension_available(THEAD_VENDOR_ID, XTHEADVECTOR) &&
has_thead_homogeneous_vlenb() < 0) {
pr_warn("Unsupported heterogeneous vlenb detected, vector extension disabled.\n");
disable_xtheadvector();
}

if (bitmap_empty(riscv_isa, RISCV_ISA_EXT_MAX))
return -ENOENT;

Expand Down
12 changes: 11 additions & 1 deletion arch/riscv/kernel/vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,17 @@ int riscv_v_setup_vsize(void)
{
unsigned long this_vsize;

/* There are 32 vector registers with vlenb length. */
/*
* There are 32 vector registers with vlenb length.
*
* If the thead,vlenb property was provided by the firmware, use that
* instead of probing the CSRs.
*/
if (thead_vlenb_of) {
riscv_v_vsize = thead_vlenb_of * 32;
return 0;
}

riscv_v_enable();
this_vsize = csr_read(CSR_VLENB) * 32;
riscv_v_disable();
Expand Down
11 changes: 11 additions & 0 deletions arch/riscv/kernel/vendor_extensions/thead.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <asm/vendor_extensions/thead.h>

#include <linux/array_size.h>
#include <linux/cpumask.h>
#include <linux/types.h>

/* All T-Head vendor extensions supported in Linux */
Expand All @@ -16,3 +17,13 @@ struct riscv_isa_vendor_ext_data_list riscv_isa_vendor_ext_list_thead = {
.ext_data_count = ARRAY_SIZE(riscv_isa_vendor_ext_thead),
.ext_data = riscv_isa_vendor_ext_thead,
};

void disable_xtheadvector(void)
{
int cpu;

for_each_possible_cpu(cpu)
clear_bit(RISCV_ISA_VENDOR_EXT_XTHEADVECTOR, riscv_isa_vendor_ext_list_thead.per_hart_isa_bitmap[cpu].isa);

clear_bit(RISCV_ISA_VENDOR_EXT_XTHEADVECTOR, riscv_isa_vendor_ext_list_thead.all_harts_isa_bitmap.isa);
}

0 comments on commit 377be47

Please sign in to comment.