mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'riscv-for-linus-6.14-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux
Pull RISC-V updates from Palmer Dabbelt: - The PH1520 pinctrl and dwmac drivers are enabeled in defconfig - A redundant AQRL barrier has been removed from the futex cmpxchg implementation - Support for the T-Head vector extensions, which includes exposing these extensions to userspace on systems that implement them - Some more page table information is now printed on die() and systems that cause PA overflows * tag 'riscv-for-linus-6.14-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: riscv: add a warning when physical memory address overflows riscv/mm/fault: add show_pte() before die() riscv: Add ghostwrite vulnerability selftests: riscv: Support xtheadvector in vector tests selftests: riscv: Fix vector tests riscv: hwprobe: Document thead vendor extensions and xtheadvector extension riscv: hwprobe: Add thead vendor extension probing riscv: vector: Support xtheadvector save/restore riscv: Add xtheadvector instruction definitions riscv: csr: Add CSR encodings for CSR_VXRM/CSR_VXSAT RISC-V: define the elements of the VCSR vector CSR riscv: vector: Use vlenb from DT for thead riscv: Add thead and xtheadvector as a vendor extension riscv: dts: allwinner: Add xtheadvector to the D1/D1s devicetree dt-bindings: cpus: add a thead vlen register length property dt-bindings: riscv: Add xtheadvector ISA extension description RISC-V: Mark riscv_v_init() as __init riscv: defconfig: drop RT_GROUP_SCHED=y riscv/futex: Optimize atomic cmpxchg riscv: defconfig: enable pinctrl and dwmac support for TH1520
This commit is contained in:
@@ -293,3 +293,13 @@ The following keys are defined:
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED`: Misaligned vector accesses are
|
||||
not supported at all and will generate a misaligned address fault.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0`: A bitmask containing the
|
||||
thead vendor extensions that are compatible with the
|
||||
:c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_IMA`: base system behavior.
|
||||
|
||||
* T-HEAD
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XTHEADVECTOR`: The xtheadvector vendor
|
||||
extension is supported in the T-Head ISA extensions spec starting from
|
||||
commit a18c801634 ("Add T-Head VECTOR vendor extension. ").
|
||||
|
||||
@@ -26,6 +26,18 @@ description: |
|
||||
allOf:
|
||||
- $ref: /schemas/cpu.yaml#
|
||||
- $ref: extensions.yaml
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- thead,c906
|
||||
- thead,c910
|
||||
- thead,c920
|
||||
then:
|
||||
properties:
|
||||
thead,vlenb: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@@ -96,6 +108,13 @@ properties:
|
||||
description:
|
||||
The blocksize in bytes for the Zicboz cache operations.
|
||||
|
||||
thead,vlenb:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
VLEN/8, the vector register length in bytes. This property is required on
|
||||
thead systems where the vector register length is not identical on all harts, or
|
||||
the vlenb CSR is not available.
|
||||
|
||||
# RISC-V has multiple properties for cache op block sizes as the sizes
|
||||
# differ between individual CBO extensions
|
||||
cache-op-block-size: false
|
||||
|
||||
@@ -621,6 +621,10 @@ properties:
|
||||
latency, as ratified in commit 56ed795 ("Update
|
||||
riscv-crypto-spec-vector.adoc") of riscv-crypto.
|
||||
|
||||
# vendor extensions, each extension sorted alphanumerically under the
|
||||
# vendor they belong to. Vendors are sorted alphanumerically as well.
|
||||
|
||||
# Andes
|
||||
- const: xandespmu
|
||||
description:
|
||||
The Andes Technology performance monitor extension for counter overflow
|
||||
@@ -628,6 +632,12 @@ properties:
|
||||
Registers in the AX45MP datasheet.
|
||||
https://www.andestech.com/wp-content/uploads/AX45MP-1C-Rev.-5.0.0-Datasheet.pdf
|
||||
|
||||
# T-HEAD
|
||||
- const: xtheadvector
|
||||
description:
|
||||
The T-HEAD specific 0.7.1 vector implementation as written in
|
||||
https://github.com/T-head-Semi/thead-extension-spec/blob/95358cb2cca9489361c61d335e03d3134b14133f/xtheadvector.adoc.
|
||||
|
||||
allOf:
|
||||
# Zcb depends on Zca
|
||||
- if:
|
||||
|
||||
@@ -119,4 +119,15 @@ config ERRATA_THEAD_PMU
|
||||
|
||||
If you don't know what to do here, say "Y".
|
||||
|
||||
config ERRATA_THEAD_GHOSTWRITE
|
||||
bool "Apply T-Head Ghostwrite errata"
|
||||
depends on ERRATA_THEAD && RISCV_ISA_XTHEADVECTOR
|
||||
default y
|
||||
help
|
||||
The T-Head C9xx cores have a vulnerability in the xtheadvector
|
||||
instruction set. When this errata is enabled, the CPUs will be probed
|
||||
to determine if they are vulnerable and disable xtheadvector.
|
||||
|
||||
If you don't know what to do here, say "Y".
|
||||
|
||||
endmenu # "CPU errata selection"
|
||||
|
||||
@@ -16,4 +16,30 @@ config RISCV_ISA_VENDOR_EXT_ANDES
|
||||
If you don't know what to do here, say Y.
|
||||
endmenu
|
||||
|
||||
menu "T-Head"
|
||||
config RISCV_ISA_VENDOR_EXT_THEAD
|
||||
bool "T-Head vendor extension support"
|
||||
select RISCV_ISA_VENDOR_EXT
|
||||
default y
|
||||
help
|
||||
Say N here to disable detection of and support for all T-Head vendor
|
||||
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
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
riscv,isa = "rv64imafdc";
|
||||
riscv,isa-base = "rv64i";
|
||||
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
|
||||
"zifencei", "zihpm";
|
||||
"zifencei", "zihpm", "xtheadvector";
|
||||
thead,vlenb = <128>;
|
||||
#cooling-cells = <2>;
|
||||
|
||||
cpu0_intc: interrupt-controller {
|
||||
|
||||
@@ -10,7 +10,6 @@ CONFIG_MEMCG=y
|
||||
CONFIG_BLK_CGROUP=y
|
||||
CONFIG_CGROUP_SCHED=y
|
||||
CONFIG_CFS_BANDWIDTH=y
|
||||
CONFIG_RT_GROUP_SCHED=y
|
||||
CONFIG_CGROUP_PIDS=y
|
||||
CONFIG_CGROUP_FREEZER=y
|
||||
CONFIG_CGROUP_HUGETLB=y
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/bugs.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/dma-noncoherent.h>
|
||||
@@ -142,6 +143,31 @@ static bool errata_probe_pmu(unsigned int stage,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool errata_probe_ghostwrite(unsigned int stage,
|
||||
unsigned long arch_id, unsigned long impid)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_ERRATA_THEAD_GHOSTWRITE))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* target-c9xx cores report arch_id and impid as 0
|
||||
*
|
||||
* While ghostwrite may not affect all c9xx cores that implement
|
||||
* xtheadvector, there is no futher granularity than c9xx. Assume
|
||||
* vulnerable for this entire class of processors when xtheadvector is
|
||||
* enabled.
|
||||
*/
|
||||
if (arch_id != 0 || impid != 0)
|
||||
return false;
|
||||
|
||||
if (stage != RISCV_ALTERNATIVES_EARLY_BOOT)
|
||||
return false;
|
||||
|
||||
ghostwrite_set_vulnerable();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static u32 thead_errata_probe(unsigned int stage,
|
||||
unsigned long archid, unsigned long impid)
|
||||
{
|
||||
@@ -155,6 +181,8 @@ static u32 thead_errata_probe(unsigned int stage,
|
||||
if (errata_probe_pmu(stage, archid, impid))
|
||||
cpu_req_errata |= BIT(ERRATA_THEAD_PMU);
|
||||
|
||||
errata_probe_ghostwrite(stage, archid, impid);
|
||||
|
||||
return cpu_req_errata;
|
||||
}
|
||||
|
||||
|
||||
22
arch/riscv/include/asm/bugs.h
Normal file
22
arch/riscv/include/asm/bugs.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Interface for managing mitigations for riscv vulnerabilities.
|
||||
*
|
||||
* Copyright (C) 2024 Rivos Inc.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_BUGS_H
|
||||
#define __ASM_BUGS_H
|
||||
|
||||
/* Watch out, ordering is important here. */
|
||||
enum mitigation_state {
|
||||
UNAFFECTED,
|
||||
MITIGATED,
|
||||
VULNERABLE,
|
||||
};
|
||||
|
||||
void ghostwrite_set_vulnerable(void);
|
||||
bool ghostwrite_enable_mitigation(void);
|
||||
enum mitigation_state ghostwrite_get_state(void);
|
||||
|
||||
#endif /* __ASM_BUGS_H */
|
||||
@@ -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) { \
|
||||
|
||||
@@ -30,6 +30,12 @@
|
||||
#define SR_VS_CLEAN _AC(0x00000400, UL)
|
||||
#define SR_VS_DIRTY _AC(0x00000600, UL)
|
||||
|
||||
#define SR_VS_THEAD _AC(0x01800000, UL) /* xtheadvector Status */
|
||||
#define SR_VS_OFF_THEAD _AC(0x00000000, UL)
|
||||
#define SR_VS_INITIAL_THEAD _AC(0x00800000, UL)
|
||||
#define SR_VS_CLEAN_THEAD _AC(0x01000000, UL)
|
||||
#define SR_VS_DIRTY_THEAD _AC(0x01800000, UL)
|
||||
|
||||
#define SR_XS _AC(0x00018000, UL) /* Extension Status */
|
||||
#define SR_XS_OFF _AC(0x00000000, UL)
|
||||
#define SR_XS_INITIAL _AC(0x00008000, UL)
|
||||
@@ -315,6 +321,15 @@
|
||||
#define CSR_STIMECMP 0x14D
|
||||
#define CSR_STIMECMPH 0x15D
|
||||
|
||||
/* xtheadvector symbolic CSR names */
|
||||
#define CSR_VXSAT 0x9
|
||||
#define CSR_VXRM 0xa
|
||||
|
||||
/* xtheadvector CSR masks */
|
||||
#define CSR_VXRM_MASK 3
|
||||
#define CSR_VXRM_SHIFT 1
|
||||
#define CSR_VXSAT_MASK 1
|
||||
|
||||
/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
|
||||
#define CSR_SISELECT 0x150
|
||||
#define CSR_SIREG 0x151
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#ifdef CONFIG_ERRATA_THEAD
|
||||
#define ERRATA_THEAD_MAE 0
|
||||
#define ERRATA_THEAD_PMU 1
|
||||
#define ERRATA_THEAD_NUMBER 2
|
||||
#define ERRATA_THEAD_GHOSTWRITE 2
|
||||
#define ERRATA_THEAD_NUMBER 3
|
||||
#endif
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
@@ -85,7 +85,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||
|
||||
__enable_user_access();
|
||||
__asm__ __volatile__ (
|
||||
"1: lr.w.aqrl %[v],%[u] \n"
|
||||
"1: lr.w %[v],%[u] \n"
|
||||
" bne %[v],%z[ov],3f \n"
|
||||
"2: sc.w.aqrl %[t],%z[nv],%[u] \n"
|
||||
" bnez %[t],1b \n"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright 2023 Rivos, Inc
|
||||
* Copyright 2023-2024 Rivos, Inc
|
||||
*/
|
||||
|
||||
#ifndef _ASM_HWPROBE_H
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <uapi/asm/hwprobe.h>
|
||||
|
||||
#define RISCV_HWPROBE_MAX_KEY 10
|
||||
#define RISCV_HWPROBE_MAX_KEY 11
|
||||
|
||||
static inline bool riscv_hwprobe_key_is_valid(__s64 key)
|
||||
{
|
||||
@@ -21,6 +21,7 @@ static inline bool hwprobe_key_is_bitmask(__s64 key)
|
||||
case RISCV_HWPROBE_KEY_BASE_BEHAVIOR:
|
||||
case RISCV_HWPROBE_KEY_IMA_EXT_0:
|
||||
case RISCV_HWPROBE_KEY_CPUPERF_0:
|
||||
case RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ do { \
|
||||
__set_prev_cpu(__prev->thread); \
|
||||
if (has_fpu()) \
|
||||
__switch_to_fpu(__prev, __next); \
|
||||
if (has_vector()) \
|
||||
if (has_vector() || has_xtheadvector()) \
|
||||
__switch_to_vector(__prev, __next); \
|
||||
if (switch_to_should_flush_icache(__next)) \
|
||||
local_flush_icache_all(); \
|
||||
|
||||
@@ -18,6 +18,27 @@
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/csr.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/vendorid_list.h>
|
||||
#include <asm/vendor_extensions.h>
|
||||
#include <asm/vendor_extensions/thead.h>
|
||||
|
||||
#define __riscv_v_vstate_or(_val, TYPE) ({ \
|
||||
typeof(_val) _res = _val; \
|
||||
if (has_xtheadvector()) \
|
||||
_res = (_res & ~SR_VS_THEAD) | SR_VS_##TYPE##_THEAD; \
|
||||
else \
|
||||
_res = (_res & ~SR_VS) | SR_VS_##TYPE; \
|
||||
_res; \
|
||||
})
|
||||
|
||||
#define __riscv_v_vstate_check(_val, TYPE) ({ \
|
||||
bool _res; \
|
||||
if (has_xtheadvector()) \
|
||||
_res = ((_val) & SR_VS_THEAD) == SR_VS_##TYPE##_THEAD; \
|
||||
else \
|
||||
_res = ((_val) & SR_VS) == SR_VS_##TYPE; \
|
||||
_res; \
|
||||
})
|
||||
|
||||
extern unsigned long riscv_v_vsize;
|
||||
int riscv_v_setup_vsize(void);
|
||||
@@ -41,39 +62,62 @@ static __always_inline bool has_vector(void)
|
||||
return riscv_has_extension_unlikely(RISCV_ISA_EXT_ZVE32X);
|
||||
}
|
||||
|
||||
static __always_inline bool has_xtheadvector_no_alternatives(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_RISCV_ISA_XTHEADVECTOR))
|
||||
return riscv_isa_vendor_extension_available(THEAD_VENDOR_ID, XTHEADVECTOR);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static __always_inline bool has_xtheadvector(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_RISCV_ISA_XTHEADVECTOR))
|
||||
return riscv_has_vendor_extension_unlikely(THEAD_VENDOR_ID,
|
||||
RISCV_ISA_VENDOR_EXT_XTHEADVECTOR);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void __riscv_v_vstate_clean(struct pt_regs *regs)
|
||||
{
|
||||
regs->status = (regs->status & ~SR_VS) | SR_VS_CLEAN;
|
||||
regs->status = __riscv_v_vstate_or(regs->status, CLEAN);
|
||||
}
|
||||
|
||||
static inline void __riscv_v_vstate_dirty(struct pt_regs *regs)
|
||||
{
|
||||
regs->status = (regs->status & ~SR_VS) | SR_VS_DIRTY;
|
||||
regs->status = __riscv_v_vstate_or(regs->status, DIRTY);
|
||||
}
|
||||
|
||||
static inline void riscv_v_vstate_off(struct pt_regs *regs)
|
||||
{
|
||||
regs->status = (regs->status & ~SR_VS) | SR_VS_OFF;
|
||||
regs->status = __riscv_v_vstate_or(regs->status, OFF);
|
||||
}
|
||||
|
||||
static inline void riscv_v_vstate_on(struct pt_regs *regs)
|
||||
{
|
||||
regs->status = (regs->status & ~SR_VS) | SR_VS_INITIAL;
|
||||
regs->status = __riscv_v_vstate_or(regs->status, INITIAL);
|
||||
}
|
||||
|
||||
static inline bool riscv_v_vstate_query(struct pt_regs *regs)
|
||||
{
|
||||
return (regs->status & SR_VS) != 0;
|
||||
return !__riscv_v_vstate_check(regs->status, OFF);
|
||||
}
|
||||
|
||||
static __always_inline void riscv_v_enable(void)
|
||||
{
|
||||
csr_set(CSR_SSTATUS, SR_VS);
|
||||
if (has_xtheadvector())
|
||||
csr_set(CSR_SSTATUS, SR_VS_THEAD);
|
||||
else
|
||||
csr_set(CSR_SSTATUS, SR_VS);
|
||||
}
|
||||
|
||||
static __always_inline void riscv_v_disable(void)
|
||||
{
|
||||
csr_clear(CSR_SSTATUS, SR_VS);
|
||||
if (has_xtheadvector())
|
||||
csr_clear(CSR_SSTATUS, SR_VS_THEAD);
|
||||
else
|
||||
csr_clear(CSR_SSTATUS, SR_VS);
|
||||
}
|
||||
|
||||
static __always_inline void __vstate_csr_save(struct __riscv_v_ext_state *dest)
|
||||
@@ -82,10 +126,36 @@ static __always_inline void __vstate_csr_save(struct __riscv_v_ext_state *dest)
|
||||
"csrr %0, " __stringify(CSR_VSTART) "\n\t"
|
||||
"csrr %1, " __stringify(CSR_VTYPE) "\n\t"
|
||||
"csrr %2, " __stringify(CSR_VL) "\n\t"
|
||||
"csrr %3, " __stringify(CSR_VCSR) "\n\t"
|
||||
"csrr %4, " __stringify(CSR_VLENB) "\n\t"
|
||||
: "=r" (dest->vstart), "=r" (dest->vtype), "=r" (dest->vl),
|
||||
"=r" (dest->vcsr), "=r" (dest->vlenb) : :);
|
||||
"=r" (dest->vcsr) : :);
|
||||
|
||||
if (has_xtheadvector()) {
|
||||
unsigned long status;
|
||||
|
||||
/*
|
||||
* CSR_VCSR is defined as
|
||||
* [2:1] - vxrm[1:0]
|
||||
* [0] - vxsat
|
||||
* The earlier vector spec implemented by T-Head uses separate
|
||||
* registers for the same bit-elements, so just combine those
|
||||
* into the existing output field.
|
||||
*
|
||||
* Additionally T-Head cores need FS to be enabled when accessing
|
||||
* the VXRM and VXSAT CSRs, otherwise ending in illegal instructions.
|
||||
* Though the cores do not implement the VXRM and VXSAT fields in the
|
||||
* FCSR CSR that vector-0.7.1 specifies.
|
||||
*/
|
||||
status = csr_read_set(CSR_STATUS, SR_FS_DIRTY);
|
||||
dest->vcsr = csr_read(CSR_VXSAT) | csr_read(CSR_VXRM) << CSR_VXRM_SHIFT;
|
||||
|
||||
dest->vlenb = riscv_v_vsize / 32;
|
||||
|
||||
if ((status & SR_FS) != SR_FS_DIRTY)
|
||||
csr_write(CSR_STATUS, status);
|
||||
} else {
|
||||
dest->vcsr = csr_read(CSR_VCSR);
|
||||
dest->vlenb = csr_read(CSR_VLENB);
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline void __vstate_csr_restore(struct __riscv_v_ext_state *src)
|
||||
@@ -96,9 +166,25 @@ static __always_inline void __vstate_csr_restore(struct __riscv_v_ext_state *src
|
||||
"vsetvl x0, %2, %1\n\t"
|
||||
".option pop\n\t"
|
||||
"csrw " __stringify(CSR_VSTART) ", %0\n\t"
|
||||
"csrw " __stringify(CSR_VCSR) ", %3\n\t"
|
||||
: : "r" (src->vstart), "r" (src->vtype), "r" (src->vl),
|
||||
"r" (src->vcsr) :);
|
||||
: : "r" (src->vstart), "r" (src->vtype), "r" (src->vl));
|
||||
|
||||
if (has_xtheadvector()) {
|
||||
unsigned long status = csr_read(CSR_SSTATUS);
|
||||
|
||||
/*
|
||||
* Similar to __vstate_csr_save above, restore values for the
|
||||
* separate VXRM and VXSAT CSRs from the vcsr variable.
|
||||
*/
|
||||
status = csr_read_set(CSR_STATUS, SR_FS_DIRTY);
|
||||
|
||||
csr_write(CSR_VXRM, (src->vcsr >> CSR_VXRM_SHIFT) & CSR_VXRM_MASK);
|
||||
csr_write(CSR_VXSAT, src->vcsr & CSR_VXSAT_MASK);
|
||||
|
||||
if ((status & SR_FS) != SR_FS_DIRTY)
|
||||
csr_write(CSR_STATUS, status);
|
||||
} else {
|
||||
csr_write(CSR_VCSR, src->vcsr);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __riscv_v_vstate_save(struct __riscv_v_ext_state *save_to,
|
||||
@@ -108,19 +194,33 @@ static inline void __riscv_v_vstate_save(struct __riscv_v_ext_state *save_to,
|
||||
|
||||
riscv_v_enable();
|
||||
__vstate_csr_save(save_to);
|
||||
asm volatile (
|
||||
".option push\n\t"
|
||||
".option arch, +zve32x\n\t"
|
||||
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
||||
"vse8.v v0, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vse8.v v8, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vse8.v v16, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vse8.v v24, (%1)\n\t"
|
||||
".option pop\n\t"
|
||||
: "=&r" (vl) : "r" (datap) : "memory");
|
||||
if (has_xtheadvector()) {
|
||||
asm volatile (
|
||||
"mv t0, %0\n\t"
|
||||
THEAD_VSETVLI_T4X0E8M8D1
|
||||
THEAD_VSB_V_V0T0
|
||||
"add t0, t0, t4\n\t"
|
||||
THEAD_VSB_V_V0T0
|
||||
"add t0, t0, t4\n\t"
|
||||
THEAD_VSB_V_V0T0
|
||||
"add t0, t0, t4\n\t"
|
||||
THEAD_VSB_V_V0T0
|
||||
: : "r" (datap) : "memory", "t0", "t4");
|
||||
} else {
|
||||
asm volatile (
|
||||
".option push\n\t"
|
||||
".option arch, +zve32x\n\t"
|
||||
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
||||
"vse8.v v0, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vse8.v v8, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vse8.v v16, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vse8.v v24, (%1)\n\t"
|
||||
".option pop\n\t"
|
||||
: "=&r" (vl) : "r" (datap) : "memory");
|
||||
}
|
||||
riscv_v_disable();
|
||||
}
|
||||
|
||||
@@ -130,19 +230,33 @@ static inline void __riscv_v_vstate_restore(struct __riscv_v_ext_state *restore_
|
||||
unsigned long vl;
|
||||
|
||||
riscv_v_enable();
|
||||
asm volatile (
|
||||
".option push\n\t"
|
||||
".option arch, +zve32x\n\t"
|
||||
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
||||
"vle8.v v0, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vle8.v v8, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vle8.v v16, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vle8.v v24, (%1)\n\t"
|
||||
".option pop\n\t"
|
||||
: "=&r" (vl) : "r" (datap) : "memory");
|
||||
if (has_xtheadvector()) {
|
||||
asm volatile (
|
||||
"mv t0, %0\n\t"
|
||||
THEAD_VSETVLI_T4X0E8M8D1
|
||||
THEAD_VLB_V_V0T0
|
||||
"add t0, t0, t4\n\t"
|
||||
THEAD_VLB_V_V0T0
|
||||
"add t0, t0, t4\n\t"
|
||||
THEAD_VLB_V_V0T0
|
||||
"add t0, t0, t4\n\t"
|
||||
THEAD_VLB_V_V0T0
|
||||
: : "r" (datap) : "memory", "t0", "t4");
|
||||
} else {
|
||||
asm volatile (
|
||||
".option push\n\t"
|
||||
".option arch, +zve32x\n\t"
|
||||
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
||||
"vle8.v v0, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vle8.v v8, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vle8.v v16, (%1)\n\t"
|
||||
"add %1, %1, %0\n\t"
|
||||
"vle8.v v24, (%1)\n\t"
|
||||
".option pop\n\t"
|
||||
: "=&r" (vl) : "r" (datap) : "memory");
|
||||
}
|
||||
__vstate_csr_restore(restore_from);
|
||||
riscv_v_disable();
|
||||
}
|
||||
@@ -152,33 +266,41 @@ static inline void __riscv_v_vstate_discard(void)
|
||||
unsigned long vl, vtype_inval = 1UL << (BITS_PER_LONG - 1);
|
||||
|
||||
riscv_v_enable();
|
||||
if (has_xtheadvector())
|
||||
asm volatile (THEAD_VSETVLI_T4X0E8M8D1 : : : "t4");
|
||||
else
|
||||
asm volatile (
|
||||
".option push\n\t"
|
||||
".option arch, +zve32x\n\t"
|
||||
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
||||
".option pop\n\t": "=&r" (vl));
|
||||
|
||||
asm volatile (
|
||||
".option push\n\t"
|
||||
".option arch, +zve32x\n\t"
|
||||
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
||||
"vmv.v.i v0, -1\n\t"
|
||||
"vmv.v.i v8, -1\n\t"
|
||||
"vmv.v.i v16, -1\n\t"
|
||||
"vmv.v.i v24, -1\n\t"
|
||||
"vsetvl %0, x0, %1\n\t"
|
||||
".option pop\n\t"
|
||||
: "=&r" (vl) : "r" (vtype_inval) : "memory");
|
||||
: "=&r" (vl) : "r" (vtype_inval));
|
||||
|
||||
riscv_v_disable();
|
||||
}
|
||||
|
||||
static inline void riscv_v_vstate_discard(struct pt_regs *regs)
|
||||
{
|
||||
if ((regs->status & SR_VS) == SR_VS_OFF)
|
||||
return;
|
||||
|
||||
__riscv_v_vstate_discard();
|
||||
__riscv_v_vstate_dirty(regs);
|
||||
if (riscv_v_vstate_query(regs)) {
|
||||
__riscv_v_vstate_discard();
|
||||
__riscv_v_vstate_dirty(regs);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void riscv_v_vstate_save(struct __riscv_v_ext_state *vstate,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if ((regs->status & SR_VS) == SR_VS_DIRTY) {
|
||||
if (__riscv_v_vstate_check(regs->status, DIRTY)) {
|
||||
__riscv_v_vstate_save(vstate, vstate->datap);
|
||||
__riscv_v_vstate_clean(regs);
|
||||
}
|
||||
@@ -187,7 +309,7 @@ static inline void riscv_v_vstate_save(struct __riscv_v_ext_state *vstate,
|
||||
static inline void riscv_v_vstate_restore(struct __riscv_v_ext_state *vstate,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if ((regs->status & SR_VS) != SR_VS_OFF) {
|
||||
if (riscv_v_vstate_query(regs)) {
|
||||
__riscv_v_vstate_restore(vstate, vstate->datap);
|
||||
__riscv_v_vstate_clean(regs);
|
||||
}
|
||||
@@ -196,7 +318,7 @@ static inline void riscv_v_vstate_restore(struct __riscv_v_ext_state *vstate,
|
||||
static inline void riscv_v_vstate_set_restore(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if ((regs->status & SR_VS) != SR_VS_OFF) {
|
||||
if (riscv_v_vstate_query(regs)) {
|
||||
set_tsk_thread_flag(task, TIF_RISCV_V_DEFER_RESTORE);
|
||||
riscv_v_vstate_on(regs);
|
||||
}
|
||||
@@ -270,6 +392,8 @@ struct pt_regs;
|
||||
static inline int riscv_v_setup_vsize(void) { return -EOPNOTSUPP; }
|
||||
static __always_inline bool has_vector(void) { return false; }
|
||||
static __always_inline bool insn_is_vector(u32 insn_buf) { return false; }
|
||||
static __always_inline bool has_xtheadvector_no_alternatives(void) { return false; }
|
||||
static __always_inline bool has_xtheadvector(void) { return false; }
|
||||
static inline bool riscv_v_first_use_handler(struct pt_regs *regs) { return false; }
|
||||
static inline bool riscv_v_vstate_query(struct pt_regs *regs) { return false; }
|
||||
static inline bool riscv_v_vstate_ctrl_user_allowed(void) { return false; }
|
||||
|
||||
47
arch/riscv/include/asm/vendor_extensions/thead.h
Normal file
47
arch/riscv/include/asm/vendor_extensions/thead.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_RISCV_VENDOR_EXTENSIONS_THEAD_H
|
||||
#define _ASM_RISCV_VENDOR_EXTENSIONS_THEAD_H
|
||||
|
||||
#include <asm/vendor_extensions.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* Extension keys must be strictly less than RISCV_ISA_VENDOR_EXT_MAX.
|
||||
*/
|
||||
#define RISCV_ISA_VENDOR_EXT_XTHEADVECTOR 0
|
||||
|
||||
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
|
||||
|
||||
/* Extension specific helpers */
|
||||
|
||||
/*
|
||||
* Vector 0.7.1 as used for example on T-Head Xuantie cores, uses an older
|
||||
* encoding for vsetvli (ta, ma vs. d1), so provide an instruction for
|
||||
* vsetvli t4, x0, e8, m8, d1
|
||||
*/
|
||||
#define THEAD_VSETVLI_T4X0E8M8D1 ".long 0x00307ed7\n\t"
|
||||
|
||||
/*
|
||||
* While in theory, the vector-0.7.1 vsb.v and vlb.v result in the same
|
||||
* encoding as the standard vse8.v and vle8.v, compilers seem to optimize
|
||||
* the call resulting in a different encoding and then using a value for
|
||||
* the "mop" field that is not part of vector-0.7.1
|
||||
* So encode specific variants for vstate_save and _restore.
|
||||
*/
|
||||
#define THEAD_VSB_V_V0T0 ".long 0x02028027\n\t"
|
||||
#define THEAD_VSB_V_V8T0 ".long 0x02028427\n\t"
|
||||
#define THEAD_VSB_V_V16T0 ".long 0x02028827\n\t"
|
||||
#define THEAD_VSB_V_V24T0 ".long 0x02028c27\n\t"
|
||||
#define THEAD_VLB_V_V0T0 ".long 0x012028007\n\t"
|
||||
#define THEAD_VLB_V_V8T0 ".long 0x012028407\n\t"
|
||||
#define THEAD_VLB_V_V16T0 ".long 0x012028807\n\t"
|
||||
#define THEAD_VLB_V_V24T0 ".long 0x012028c07\n\t"
|
||||
|
||||
#endif
|
||||
19
arch/riscv/include/asm/vendor_extensions/thead_hwprobe.h
Normal file
19
arch/riscv/include/asm/vendor_extensions/thead_hwprobe.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_RISCV_VENDOR_EXTENSIONS_THEAD_HWPROBE_H
|
||||
#define _ASM_RISCV_VENDOR_EXTENSIONS_THEAD_HWPROBE_H
|
||||
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
#include <uapi/asm/hwprobe.h>
|
||||
|
||||
#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_THEAD
|
||||
void hwprobe_isa_vendor_ext_thead_0(struct riscv_hwprobe *pair, const struct cpumask *cpus);
|
||||
#else
|
||||
static inline void hwprobe_isa_vendor_ext_thead_0(struct riscv_hwprobe *pair,
|
||||
const struct cpumask *cpus)
|
||||
{
|
||||
pair->value = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
37
arch/riscv/include/asm/vendor_extensions/vendor_hwprobe.h
Normal file
37
arch/riscv/include/asm/vendor_extensions/vendor_hwprobe.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright 2024 Rivos, Inc
|
||||
*/
|
||||
|
||||
#ifndef _ASM_RISCV_SYS_HWPROBE_H
|
||||
#define _ASM_RISCV_SYS_HWPROBE_H
|
||||
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
#define VENDOR_EXT_KEY(ext) \
|
||||
do { \
|
||||
if (__riscv_isa_extension_available(isainfo->isa, RISCV_ISA_VENDOR_EXT_##ext)) \
|
||||
pair->value |= RISCV_HWPROBE_VENDOR_EXT_##ext; \
|
||||
else \
|
||||
missing |= RISCV_HWPROBE_VENDOR_EXT_##ext; \
|
||||
} while (false)
|
||||
|
||||
/*
|
||||
* Loop through and record extensions that 1) anyone has, and 2) anyone
|
||||
* doesn't have.
|
||||
*
|
||||
* _extension_checks is an arbitrary C block to set the values of pair->value
|
||||
* and missing. It should be filled with VENDOR_EXT_KEY expressions.
|
||||
*/
|
||||
#define VENDOR_EXTENSION_SUPPORTED(pair, cpus, per_hart_vendor_bitmap, _extension_checks) \
|
||||
do { \
|
||||
int cpu; \
|
||||
u64 missing = 0; \
|
||||
for_each_cpu(cpu, (cpus)) { \
|
||||
struct riscv_isavendorinfo *isainfo = &(per_hart_vendor_bitmap)[cpu]; \
|
||||
_extension_checks \
|
||||
} \
|
||||
(pair)->value &= ~missing; \
|
||||
} while (false) \
|
||||
|
||||
#endif /* _ASM_RISCV_SYS_HWPROBE_H */
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright 2023 Rivos, Inc
|
||||
* Copyright 2023-2024 Rivos, Inc
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_ASM_HWPROBE_H
|
||||
@@ -94,6 +94,7 @@ struct riscv_hwprobe {
|
||||
#define RISCV_HWPROBE_MISALIGNED_VECTOR_SLOW 2
|
||||
#define RISCV_HWPROBE_MISALIGNED_VECTOR_FAST 3
|
||||
#define RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED 4
|
||||
#define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0 11
|
||||
/* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
|
||||
|
||||
/* Flags */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user