mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 14:53:58 -04:00
riscv: Add support for kernel mode vector
Add kernel_vector_begin() and kernel_vector_end() function declarations and corresponding definitions in kernel_mode_vector.c These are needed to wrap uses of vector in kernel mode. Co-developed-by: Vincent Chen <vincent.chen@sifive.com> Signed-off-by: Vincent Chen <vincent.chen@sifive.com> Signed-off-by: Greentime Hu <greentime.hu@sifive.com> Signed-off-by: Andy Chiu <andy.chiu@sifive.com> Reviewed-by: Eric Biggers <ebiggers@google.com> Tested-by: Björn Töpel <bjorn@rivosinc.com> Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Link: https://lore.kernel.org/r/20240115055929.4736-2-andy.chiu@sifive.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
committed by
Palmer Dabbelt
parent
b85ea95d08
commit
ecd2ada8a5
116
arch/riscv/kernel/kernel_mode_vector.c
Normal file
116
arch/riscv/kernel/kernel_mode_vector.c
Normal file
@@ -0,0 +1,116 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2012 ARM Ltd.
|
||||
* Author: Catalin Marinas <catalin.marinas@arm.com>
|
||||
* Copyright (C) 2017 Linaro Ltd. <ard.biesheuvel@linaro.org>
|
||||
* Copyright (C) 2021 SiFive
|
||||
*/
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/irqflags.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/vector.h>
|
||||
#include <asm/switch_to.h>
|
||||
#include <asm/simd.h>
|
||||
|
||||
static inline void riscv_v_flags_set(u32 flags)
|
||||
{
|
||||
current->thread.riscv_v_flags = flags;
|
||||
}
|
||||
|
||||
static inline void riscv_v_start(u32 flags)
|
||||
{
|
||||
int orig;
|
||||
|
||||
orig = riscv_v_flags();
|
||||
BUG_ON((orig & flags) != 0);
|
||||
riscv_v_flags_set(orig | flags);
|
||||
}
|
||||
|
||||
static inline void riscv_v_stop(u32 flags)
|
||||
{
|
||||
int orig;
|
||||
|
||||
orig = riscv_v_flags();
|
||||
BUG_ON((orig & flags) == 0);
|
||||
riscv_v_flags_set(orig & ~flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Claim ownership of the CPU vector context for use by the calling context.
|
||||
*
|
||||
* The caller may freely manipulate the vector context metadata until
|
||||
* put_cpu_vector_context() is called.
|
||||
*/
|
||||
void get_cpu_vector_context(void)
|
||||
{
|
||||
preempt_disable();
|
||||
|
||||
riscv_v_start(RISCV_KERNEL_MODE_V);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the CPU vector context.
|
||||
*
|
||||
* Must be called from a context in which get_cpu_vector_context() was
|
||||
* previously called, with no call to put_cpu_vector_context() in the
|
||||
* meantime.
|
||||
*/
|
||||
void put_cpu_vector_context(void)
|
||||
{
|
||||
riscv_v_stop(RISCV_KERNEL_MODE_V);
|
||||
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* kernel_vector_begin(): obtain the CPU vector registers for use by the calling
|
||||
* context
|
||||
*
|
||||
* Must not be called unless may_use_simd() returns true.
|
||||
* Task context in the vector registers is saved back to memory as necessary.
|
||||
*
|
||||
* A matching call to kernel_vector_end() must be made before returning from the
|
||||
* calling context.
|
||||
*
|
||||
* The caller may freely use the vector registers until kernel_vector_end() is
|
||||
* called.
|
||||
*/
|
||||
void kernel_vector_begin(void)
|
||||
{
|
||||
if (WARN_ON(!has_vector()))
|
||||
return;
|
||||
|
||||
BUG_ON(!may_use_simd());
|
||||
|
||||
get_cpu_vector_context();
|
||||
|
||||
riscv_v_vstate_save(current, task_pt_regs(current));
|
||||
|
||||
riscv_v_enable();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kernel_vector_begin);
|
||||
|
||||
/*
|
||||
* kernel_vector_end(): give the CPU vector registers back to the current task
|
||||
*
|
||||
* Must be called from a context in which kernel_vector_begin() was previously
|
||||
* called, with no call to kernel_vector_end() in the meantime.
|
||||
*
|
||||
* The caller must not use the vector registers after this function is called,
|
||||
* unless kernel_vector_begin() is called again in the meantime.
|
||||
*/
|
||||
void kernel_vector_end(void)
|
||||
{
|
||||
if (WARN_ON(!has_vector()))
|
||||
return;
|
||||
|
||||
riscv_v_vstate_restore(current, task_pt_regs(current));
|
||||
|
||||
riscv_v_disable();
|
||||
|
||||
put_cpu_vector_context();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kernel_vector_end);
|
||||
Reference in New Issue
Block a user