Unverified Commit 7017858e authored by Greentime Hu's avatar Greentime Hu Committed by Palmer Dabbelt
Browse files

riscv: Introduce riscv_v_vsize to record size of Vector context



This patch is used to detect the size of CPU vector registers and use
riscv_v_vsize to save the size of all the vector registers. It assumes all
harts has the same capabilities in a SMP system. If a core detects VLENB
that is different from the boot core, then it warns and turns off V
support for user space.

Co-developed-by: default avatarGuo Ren <guoren@linux.alibaba.com>
Signed-off-by: default avatarGuo Ren <guoren@linux.alibaba.com>
Co-developed-by: default avatarVincent Chen <vincent.chen@sifive.com>
Signed-off-by: default avatarVincent Chen <vincent.chen@sifive.com>
Signed-off-by: default avatarGreentime Hu <greentime.hu@sifive.com>
Signed-off-by: default avatarAndy Chiu <andy.chiu@sifive.com>
Reviewed-by: default avatarConor Dooley <conor.dooley@microchip.com>
Reviewed-by: default avatarHeiko Stuebner <heiko.stuebner@vrull.eu>
Tested-by: default avatarHeiko Stuebner <heiko.stuebner@vrull.eu>
Reviewed-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
Link: https://lore.kernel.org/r/20230605110724.21391-9-andy.chiu@sifive.com


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent 0a3381a0
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -7,12 +7,16 @@
#define __ASM_RISCV_VECTOR_H

#include <linux/types.h>
#include <uapi/asm-generic/errno.h>

#ifdef CONFIG_RISCV_ISA_V

#include <asm/hwcap.h>
#include <asm/csr.h>

extern unsigned long riscv_v_vsize;
int riscv_v_setup_vsize(void);

static __always_inline bool has_vector(void)
{
	return riscv_has_extension_unlikely(RISCV_ISA_EXT_v);
@@ -30,7 +34,11 @@ static __always_inline void riscv_v_disable(void)

#else /* ! CONFIG_RISCV_ISA_V  */

struct pt_regs;

static inline int riscv_v_setup_vsize(void) { return -EOPNOTSUPP; }
static __always_inline bool has_vector(void) { return false; }
#define riscv_v_vsize (0)

#endif /* CONFIG_RISCV_ISA_V */

+1 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ obj-$(CONFIG_MMU) += vdso.o vdso/

obj-$(CONFIG_RISCV_M_MODE)	+= traps_misaligned.o
obj-$(CONFIG_FPU)		+= fpu.o
obj-$(CONFIG_RISCV_ISA_V)	+= vector.o
obj-$(CONFIG_SMP)		+= smpboot.o
obj-$(CONFIG_SMP)		+= smp.o
obj-$(CONFIG_SMP)		+= cpu_ops.o
+2 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <asm/hwcap.h>
#include <asm/patch.h>
#include <asm/processor.h>
#include <asm/vector.h>

#define NUM_ALPHA_EXTS ('z' - 'a' + 1)

@@ -269,6 +270,7 @@ void __init riscv_fill_hwcap(void)
	}

	if (elf_hwcap & COMPAT_HWCAP_ISA_V) {
		riscv_v_setup_vsize();
		/*
		 * ISA string in device tree might have 'v' flag, but
		 * CONFIG_RISCV_ISA_V is disabled in kernel.
+7 −0
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@
#include <asm/tlbflush.h>
#include <asm/sections.h>
#include <asm/smp.h>
#include <uapi/asm/hwcap.h>
#include <asm/vector.h>

#include "head.h"

@@ -169,6 +171,11 @@ asmlinkage __visible void smp_callin(void)
	set_cpu_online(curr_cpuid, 1);
	probe_vendor_features(curr_cpuid);

	if (has_vector()) {
		if (riscv_v_setup_vsize())
			elf_hwcap &= ~COMPAT_HWCAP_ISA_V;
	}

	/*
	 * Remote TLB flushes are ignored while the CPU is offline, so emit
	 * a local TLB flush right now just in case.
+36 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2023 SiFive
 * Author: Andy Chiu <andy.chiu@sifive.com>
 */
#include <linux/export.h>

#include <asm/vector.h>
#include <asm/csr.h>
#include <asm/elf.h>
#include <asm/bug.h>

unsigned long riscv_v_vsize __read_mostly;
EXPORT_SYMBOL_GPL(riscv_v_vsize);

int riscv_v_setup_vsize(void)
{
	unsigned long this_vsize;

	/* There are 32 vector registers with vlenb length. */
	riscv_v_enable();
	this_vsize = csr_read(CSR_VLENB) * 32;
	riscv_v_disable();

	if (!riscv_v_vsize) {
		riscv_v_vsize = this_vsize;
		return 0;
	}

	if (riscv_v_vsize != this_vsize) {
		WARN(1, "RISCV_ISA_V only supports one vlenb on SMP systems");
		return -EOPNOTSUPP;
	}

	return 0;
}