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:
Linus Torvalds
2025-01-31 15:13:25 -08:00
47 changed files with 1112 additions and 283 deletions

View File

@@ -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. ").

View File

@@ -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

View File

@@ -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:

View File

@@ -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"

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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;
}

View 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 */

View File

@@ -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) { \

View File

@@ -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

View File

@@ -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__

View File

@@ -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"

View File

@@ -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;
}

View File

@@ -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(); \

View File

@@ -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; }

View 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

View 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

View 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 */

View File

@@ -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