mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'riscv-for-linus-6.7-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux
Pull more RISC-V updates from Palmer Dabbelt: - Support for handling misaligned accesses in S-mode - Probing for misaligned access support is now properly cached and handled in parallel - PTDUMP now reflects the SW reserved bits, as well as the PBMT and NAPOT extensions - Performance improvements for TLB flushing - Support for many new relocations in the module loader - Various bug fixes and cleanups * tag 'riscv-for-linus-6.7-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (51 commits) riscv: Optimize bitops with Zbb extension riscv: Rearrange hwcap.h and cpufeature.h drivers: perf: Do not broadcast to other cpus when starting a counter drivers: perf: Check find_first_bit() return value of: property: Add fw_devlink support for msi-parent RISC-V: Don't fail in riscv_of_parent_hartid() for disabled HARTs riscv: Fix set_memory_XX() and set_direct_map_XX() by splitting huge linear mappings riscv: Don't use PGD entries for the linear mapping RISC-V: Probe misaligned access speed in parallel RISC-V: Remove __init on unaligned_emulation_finish() RISC-V: Show accurate per-hart isa in /proc/cpuinfo RISC-V: Don't rely on positional structure initialization riscv: Add tests for riscv module loading riscv: Add remaining module relocations riscv: Avoid unaligned access when relocating modules riscv: split cache ops out of dma-noncoherent.c riscv: Improve flush_tlb_kernel_range() riscv: Make __flush_tlb_range() loop over pte instead of flushing the whole tlb riscv: Improve flush_tlb_range() for hugetlb pages riscv: Improve tlb_flush() ...
This commit is contained in:
@@ -42,6 +42,26 @@ An example string following the order is::
|
||||
|
||||
rv64imadc_zifoo_zigoo_zafoo_sbar_scar_zxmbaz_xqux_xrux
|
||||
|
||||
"isa" and "hart isa" lines in /proc/cpuinfo
|
||||
-------------------------------------------
|
||||
|
||||
The "isa" line in /proc/cpuinfo describes the lowest common denominator of
|
||||
RISC-V ISA extensions recognized by the kernel and implemented on all harts. The
|
||||
"hart isa" line, in contrast, describes the set of extensions recognized by the
|
||||
kernel on the particular hart being described, even if those extensions may not
|
||||
be present on all harts in the system.
|
||||
|
||||
In both lines, the presence of an extension guarantees only that the hardware
|
||||
has the described capability. Additional kernel support or policy changes may be
|
||||
required before an extension's capability is fully usable by userspace programs.
|
||||
Similarly, for S-mode extensions, presence in one of these lines does not
|
||||
guarantee that the kernel is taking advantage of the extension, or that the
|
||||
feature will be visible in guest VMs managed by this kernel.
|
||||
|
||||
Inversely, the absence of an extension in these lines does not necessarily mean
|
||||
the hardware does not support that feature. The running kernel may not recognize
|
||||
the extension, or may have deliberately removed it from the listing.
|
||||
|
||||
Misaligned accesses
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -642,6 +642,15 @@ config THREAD_SIZE_ORDER
|
||||
Specify the Pages of thread stack size (from 4KB to 64KB), which also
|
||||
affects irq stack size, which is equal to thread stack size.
|
||||
|
||||
config RISCV_MISALIGNED
|
||||
bool "Support misaligned load/store traps for kernel and userspace"
|
||||
select SYSCTL_ARCH_UNALIGN_ALLOW
|
||||
default y
|
||||
help
|
||||
Say Y here if you want the kernel to embed support for misaligned
|
||||
load/store for both kernel and userspace. When disable, misaligned
|
||||
accesses will generate SIGBUS in userspace and panic in kernel.
|
||||
|
||||
endmenu # "Platform type"
|
||||
|
||||
menu "Kernel features"
|
||||
@@ -909,6 +918,9 @@ config PORTABLE
|
||||
select MMU
|
||||
select OF
|
||||
|
||||
config ARCH_PROC_KCORE_TEXT
|
||||
def_bool y
|
||||
|
||||
menu "Power management options"
|
||||
|
||||
source "kernel/power/Kconfig"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
source "arch/riscv/kernel/tests/Kconfig.debug"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
KCOV_INSTRUMENT := n
|
||||
|
||||
OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
|
||||
OBJCOPYFLAGS_loader.bin :=-O binary
|
||||
OBJCOPYFLAGS_xipImage :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
|
||||
|
||||
targets := Image Image.* loader loader.o loader.lds loader.bin
|
||||
|
||||
@@ -215,6 +215,8 @@ CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_PLTFM=y
|
||||
CONFIG_MMC_SDHCI_CADENCE=y
|
||||
CONFIG_MMC_SPI=y
|
||||
CONFIG_MMC_DW=y
|
||||
CONFIG_MMC_DW_STARFIVE=y
|
||||
CONFIG_MMC_SDHI=y
|
||||
CONFIG_MMC_SUNXI=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
|
||||
@@ -15,13 +15,261 @@
|
||||
#include <asm/barrier.h>
|
||||
#include <asm/bitsperlong.h>
|
||||
|
||||
#if !defined(CONFIG_RISCV_ISA_ZBB) || defined(NO_ALTERNATIVE)
|
||||
#include <asm-generic/bitops/__ffs.h>
|
||||
#include <asm-generic/bitops/ffz.h>
|
||||
#include <asm-generic/bitops/fls.h>
|
||||
#include <asm-generic/bitops/__fls.h>
|
||||
#include <asm-generic/bitops/ffs.h>
|
||||
#include <asm-generic/bitops/fls.h>
|
||||
|
||||
#else
|
||||
#include <asm/alternative-macros.h>
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
#if (BITS_PER_LONG == 64)
|
||||
#define CTZW "ctzw "
|
||||
#define CLZW "clzw "
|
||||
#elif (BITS_PER_LONG == 32)
|
||||
#define CTZW "ctz "
|
||||
#define CLZW "clz "
|
||||
#else
|
||||
#error "Unexpected BITS_PER_LONG"
|
||||
#endif
|
||||
|
||||
static __always_inline unsigned long variable__ffs(unsigned long word)
|
||||
{
|
||||
int num;
|
||||
|
||||
asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
|
||||
RISCV_ISA_EXT_ZBB, 1)
|
||||
: : : : legacy);
|
||||
|
||||
asm volatile (".option push\n"
|
||||
".option arch,+zbb\n"
|
||||
"ctz %0, %1\n"
|
||||
".option pop\n"
|
||||
: "=r" (word) : "r" (word) :);
|
||||
|
||||
return word;
|
||||
|
||||
legacy:
|
||||
num = 0;
|
||||
#if BITS_PER_LONG == 64
|
||||
if ((word & 0xffffffff) == 0) {
|
||||
num += 32;
|
||||
word >>= 32;
|
||||
}
|
||||
#endif
|
||||
if ((word & 0xffff) == 0) {
|
||||
num += 16;
|
||||
word >>= 16;
|
||||
}
|
||||
if ((word & 0xff) == 0) {
|
||||
num += 8;
|
||||
word >>= 8;
|
||||
}
|
||||
if ((word & 0xf) == 0) {
|
||||
num += 4;
|
||||
word >>= 4;
|
||||
}
|
||||
if ((word & 0x3) == 0) {
|
||||
num += 2;
|
||||
word >>= 2;
|
||||
}
|
||||
if ((word & 0x1) == 0)
|
||||
num += 1;
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* __ffs - find first set bit in a long word
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no set bit exists, so code should check against 0 first.
|
||||
*/
|
||||
#define __ffs(word) \
|
||||
(__builtin_constant_p(word) ? \
|
||||
(unsigned long)__builtin_ctzl(word) : \
|
||||
variable__ffs(word))
|
||||
|
||||
static __always_inline unsigned long variable__fls(unsigned long word)
|
||||
{
|
||||
int num;
|
||||
|
||||
asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
|
||||
RISCV_ISA_EXT_ZBB, 1)
|
||||
: : : : legacy);
|
||||
|
||||
asm volatile (".option push\n"
|
||||
".option arch,+zbb\n"
|
||||
"clz %0, %1\n"
|
||||
".option pop\n"
|
||||
: "=r" (word) : "r" (word) :);
|
||||
|
||||
return BITS_PER_LONG - 1 - word;
|
||||
|
||||
legacy:
|
||||
num = BITS_PER_LONG - 1;
|
||||
#if BITS_PER_LONG == 64
|
||||
if (!(word & (~0ul << 32))) {
|
||||
num -= 32;
|
||||
word <<= 32;
|
||||
}
|
||||
#endif
|
||||
if (!(word & (~0ul << (BITS_PER_LONG - 16)))) {
|
||||
num -= 16;
|
||||
word <<= 16;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG - 8)))) {
|
||||
num -= 8;
|
||||
word <<= 8;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG - 4)))) {
|
||||
num -= 4;
|
||||
word <<= 4;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG - 2)))) {
|
||||
num -= 2;
|
||||
word <<= 2;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG - 1))))
|
||||
num -= 1;
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* __fls - find last set bit in a long word
|
||||
* @word: the word to search
|
||||
*
|
||||
* Undefined if no set bit exists, so code should check against 0 first.
|
||||
*/
|
||||
#define __fls(word) \
|
||||
(__builtin_constant_p(word) ? \
|
||||
(unsigned long)(BITS_PER_LONG - 1 - __builtin_clzl(word)) : \
|
||||
variable__fls(word))
|
||||
|
||||
static __always_inline int variable_ffs(int x)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!x)
|
||||
return 0;
|
||||
|
||||
asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
|
||||
RISCV_ISA_EXT_ZBB, 1)
|
||||
: : : : legacy);
|
||||
|
||||
asm volatile (".option push\n"
|
||||
".option arch,+zbb\n"
|
||||
CTZW "%0, %1\n"
|
||||
".option pop\n"
|
||||
: "=r" (r) : "r" (x) :);
|
||||
|
||||
return r + 1;
|
||||
|
||||
legacy:
|
||||
r = 1;
|
||||
if (!(x & 0xffff)) {
|
||||
x >>= 16;
|
||||
r += 16;
|
||||
}
|
||||
if (!(x & 0xff)) {
|
||||
x >>= 8;
|
||||
r += 8;
|
||||
}
|
||||
if (!(x & 0xf)) {
|
||||
x >>= 4;
|
||||
r += 4;
|
||||
}
|
||||
if (!(x & 3)) {
|
||||
x >>= 2;
|
||||
r += 2;
|
||||
}
|
||||
if (!(x & 1)) {
|
||||
x >>= 1;
|
||||
r += 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* ffs - find first set bit in a word
|
||||
* @x: the word to search
|
||||
*
|
||||
* This is defined the same way as the libc and compiler builtin ffs routines.
|
||||
*
|
||||
* ffs(value) returns 0 if value is 0 or the position of the first set bit if
|
||||
* value is nonzero. The first (least significant) bit is at position 1.
|
||||
*/
|
||||
#define ffs(x) (__builtin_constant_p(x) ? __builtin_ffs(x) : variable_ffs(x))
|
||||
|
||||
static __always_inline int variable_fls(unsigned int x)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!x)
|
||||
return 0;
|
||||
|
||||
asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0,
|
||||
RISCV_ISA_EXT_ZBB, 1)
|
||||
: : : : legacy);
|
||||
|
||||
asm volatile (".option push\n"
|
||||
".option arch,+zbb\n"
|
||||
CLZW "%0, %1\n"
|
||||
".option pop\n"
|
||||
: "=r" (r) : "r" (x) :);
|
||||
|
||||
return 32 - r;
|
||||
|
||||
legacy:
|
||||
r = 32;
|
||||
if (!(x & 0xffff0000u)) {
|
||||
x <<= 16;
|
||||
r -= 16;
|
||||
}
|
||||
if (!(x & 0xff000000u)) {
|
||||
x <<= 8;
|
||||
r -= 8;
|
||||
}
|
||||
if (!(x & 0xf0000000u)) {
|
||||
x <<= 4;
|
||||
r -= 4;
|
||||
}
|
||||
if (!(x & 0xc0000000u)) {
|
||||
x <<= 2;
|
||||
r -= 2;
|
||||
}
|
||||
if (!(x & 0x80000000u)) {
|
||||
x <<= 1;
|
||||
r -= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* fls - find last set bit in a word
|
||||
* @x: the word to search
|
||||
*
|
||||
* This is defined in a similar way as ffs, but returns the position of the most
|
||||
* significant set bit.
|
||||
*
|
||||
* fls(value) returns 0 if value is 0 or the position of the last set bit if
|
||||
* value is nonzero. The last (most significant) bit is at position 32.
|
||||
*/
|
||||
#define fls(x) \
|
||||
({ \
|
||||
typeof(x) x_ = (x); \
|
||||
__builtin_constant_p(x_) ? \
|
||||
(int)((x_ != 0) ? (32 - __builtin_clz(x_)) : 0) \
|
||||
: \
|
||||
variable_fls(x_); \
|
||||
})
|
||||
|
||||
#endif /* !defined(CONFIG_RISCV_ISA_ZBB) || defined(NO_ALTERNATIVE) */
|
||||
|
||||
#include <asm-generic/bitops/ffz.h>
|
||||
#include <asm-generic/bitops/fls64.h>
|
||||
#include <asm-generic/bitops/sched.h>
|
||||
#include <asm-generic/bitops/ffs.h>
|
||||
|
||||
#include <asm-generic/bitops/hweight.h>
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
#define _ASM_CPUFEATURE_H
|
||||
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/jump_label.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/alternative-macros.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
/*
|
||||
* These are probed via a device_initcall(), via either the SBI or directly
|
||||
@@ -30,7 +33,104 @@ DECLARE_PER_CPU(long, misaligned_access_speed);
|
||||
/* Per-cpu ISA extensions. */
|
||||
extern struct riscv_isainfo hart_isa[NR_CPUS];
|
||||
|
||||
void check_unaligned_access(int cpu);
|
||||
void riscv_user_isa_enable(void);
|
||||
|
||||
#ifdef CONFIG_RISCV_MISALIGNED
|
||||
bool unaligned_ctl_available(void);
|
||||
bool check_unaligned_access_emulated(int cpu);
|
||||
void unaligned_emulation_finish(void);
|
||||
#else
|
||||
static inline bool unaligned_ctl_available(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool check_unaligned_access_emulated(int cpu)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void unaligned_emulation_finish(void) {}
|
||||
#endif
|
||||
|
||||
unsigned long riscv_get_elf_hwcap(void);
|
||||
|
||||
struct riscv_isa_ext_data {
|
||||
const unsigned int id;
|
||||
const char *name;
|
||||
const char *property;
|
||||
};
|
||||
|
||||
extern const struct riscv_isa_ext_data riscv_isa_ext[];
|
||||
extern const size_t riscv_isa_ext_count;
|
||||
extern bool riscv_isa_fallback;
|
||||
|
||||
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
|
||||
|
||||
bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
|
||||
#define riscv_isa_extension_available(isa_bitmap, ext) \
|
||||
__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
|
||||
|
||||
static __always_inline bool
|
||||
riscv_has_extension_likely(const unsigned long ext)
|
||||
{
|
||||
compiletime_assert(ext < RISCV_ISA_EXT_MAX,
|
||||
"ext must be < RISCV_ISA_EXT_MAX");
|
||||
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
|
||||
asm_volatile_goto(
|
||||
ALTERNATIVE("j %l[l_no]", "nop", 0, %[ext], 1)
|
||||
:
|
||||
: [ext] "i" (ext)
|
||||
:
|
||||
: l_no);
|
||||
} else {
|
||||
if (!__riscv_isa_extension_available(NULL, ext))
|
||||
goto l_no;
|
||||
}
|
||||
|
||||
return true;
|
||||
l_no:
|
||||
return false;
|
||||
}
|
||||
|
||||
static __always_inline bool
|
||||
riscv_has_extension_unlikely(const unsigned long ext)
|
||||
{
|
||||
compiletime_assert(ext < RISCV_ISA_EXT_MAX,
|
||||
"ext must be < RISCV_ISA_EXT_MAX");
|
||||
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
|
||||
asm_volatile_goto(
|
||||
ALTERNATIVE("nop", "j %l[l_yes]", 0, %[ext], 1)
|
||||
:
|
||||
: [ext] "i" (ext)
|
||||
:
|
||||
: l_yes);
|
||||
} else {
|
||||
if (__riscv_isa_extension_available(NULL, ext))
|
||||
goto l_yes;
|
||||
}
|
||||
|
||||
return false;
|
||||
l_yes:
|
||||
return true;
|
||||
}
|
||||
|
||||
static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_likely(ext))
|
||||
return true;
|
||||
|
||||
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
|
||||
}
|
||||
|
||||
static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsigned long ext)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_unlikely(ext))
|
||||
return true;
|
||||
|
||||
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <asm/auxvec.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/cacheinfo.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
/*
|
||||
* These are used to set parameters in the core dumps.
|
||||
|
||||
@@ -8,4 +8,18 @@
|
||||
void handle_page_fault(struct pt_regs *regs);
|
||||
void handle_break(struct pt_regs *regs);
|
||||
|
||||
#ifdef CONFIG_RISCV_MISALIGNED
|
||||
int handle_misaligned_load(struct pt_regs *regs);
|
||||
int handle_misaligned_store(struct pt_regs *regs);
|
||||
#else
|
||||
static inline int handle_misaligned_load(struct pt_regs *regs)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
static inline int handle_misaligned_store(struct pt_regs *regs)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_RISCV_ENTRY_COMMON_H */
|
||||
|
||||
@@ -117,9 +117,9 @@ asm volatile(ALTERNATIVE( \
|
||||
* | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
|
||||
* 0000000 11001 00000 000 00000 0001011
|
||||
*/
|
||||
#define THEAD_inval_A0 ".long 0x0265000b"
|
||||
#define THEAD_clean_A0 ".long 0x0255000b"
|
||||
#define THEAD_flush_A0 ".long 0x0275000b"
|
||||
#define THEAD_INVAL_A0 ".long 0x0265000b"
|
||||
#define THEAD_CLEAN_A0 ".long 0x0255000b"
|
||||
#define THEAD_FLUSH_A0 ".long 0x0275000b"
|
||||
#define THEAD_SYNC_S ".long 0x0190000b"
|
||||
|
||||
#define ALT_CMO_OP(_op, _start, _size, _cachesize) \
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
#ifndef _ASM_RISCV_HWCAP_H
|
||||
#define _ASM_RISCV_HWCAP_H
|
||||
|
||||
#include <asm/alternative-macros.h>
|
||||
#include <asm/errno.h>
|
||||
#include <linux/bits.h>
|
||||
#include <uapi/asm/hwcap.h>
|
||||
|
||||
#define RISCV_ISA_EXT_a ('a' - 'a')
|
||||
@@ -69,92 +66,4 @@
|
||||
#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SSAIA
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/jump_label.h>
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
unsigned long riscv_get_elf_hwcap(void);
|
||||
|
||||
struct riscv_isa_ext_data {
|
||||
const unsigned int id;
|
||||
const char *name;
|
||||
const char *property;
|
||||
};
|
||||
|
||||
extern const struct riscv_isa_ext_data riscv_isa_ext[];
|
||||
extern const size_t riscv_isa_ext_count;
|
||||
extern bool riscv_isa_fallback;
|
||||
|
||||
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
|
||||
|
||||
#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
|
||||
|
||||
bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
|
||||
#define riscv_isa_extension_available(isa_bitmap, ext) \
|
||||
__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
|
||||
|
||||
static __always_inline bool
|
||||
riscv_has_extension_likely(const unsigned long ext)
|
||||
{
|
||||
compiletime_assert(ext < RISCV_ISA_EXT_MAX,
|
||||
"ext must be < RISCV_ISA_EXT_MAX");
|
||||
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
|
||||
asm_volatile_goto(
|
||||
ALTERNATIVE("j %l[l_no]", "nop", 0, %[ext], 1)
|
||||
:
|
||||
: [ext] "i" (ext)
|
||||
:
|
||||
: l_no);
|
||||
} else {
|
||||
if (!__riscv_isa_extension_available(NULL, ext))
|
||||
goto l_no;
|
||||
}
|
||||
|
||||
return true;
|
||||
l_no:
|
||||
return false;
|
||||
}
|
||||
|
||||
static __always_inline bool
|
||||
riscv_has_extension_unlikely(const unsigned long ext)
|
||||
{
|
||||
compiletime_assert(ext < RISCV_ISA_EXT_MAX,
|
||||
"ext must be < RISCV_ISA_EXT_MAX");
|
||||
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
|
||||
asm_volatile_goto(
|
||||
ALTERNATIVE("nop", "j %l[l_yes]", 0, %[ext], 1)
|
||||
:
|
||||
: [ext] "i" (ext)
|
||||
:
|
||||
: l_yes);
|
||||
} else {
|
||||
if (__riscv_isa_extension_available(NULL, ext))
|
||||
goto l_yes;
|
||||
}
|
||||
|
||||
return false;
|
||||
l_yes:
|
||||
return true;
|
||||
}
|
||||
|
||||
static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_likely(ext))
|
||||
return true;
|
||||
|
||||
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
|
||||
}
|
||||
|
||||
static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsigned long ext)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_unlikely(ext))
|
||||
return true;
|
||||
|
||||
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_RISCV_HWCAP_H */
|
||||
|
||||
@@ -180,19 +180,19 @@
|
||||
INSN_R(OPCODE_SYSTEM, FUNC3(0), FUNC7(51), \
|
||||
__RD(0), RS1(gaddr), RS2(vmid))
|
||||
|
||||
#define CBO_inval(base) \
|
||||
#define CBO_INVAL(base) \
|
||||
INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
|
||||
RS1(base), SIMM12(0))
|
||||
|
||||
#define CBO_clean(base) \
|
||||
#define CBO_CLEAN(base) \
|
||||
INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
|
||||
RS1(base), SIMM12(1))
|
||||
|
||||
#define CBO_flush(base) \
|
||||
#define CBO_FLUSH(base) \
|
||||
INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
|
||||
RS1(base), SIMM12(2))
|
||||
|
||||
#define CBO_zero(base) \
|
||||
#define CBO_ZERO(base) \
|
||||
INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
|
||||
RS1(base), SIMM12(4))
|
||||
|
||||
|
||||
@@ -126,14 +126,18 @@ enum napot_cont_order {
|
||||
|
||||
/*
|
||||
* [63:59] T-Head Memory Type definitions:
|
||||
*
|
||||
* 00000 - NC Weakly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
|
||||
* bit[63] SO - Strong Order
|
||||
* bit[62] C - Cacheable
|
||||
* bit[61] B - Bufferable
|
||||
* bit[60] SH - Shareable
|
||||
* bit[59] Sec - Trustable
|
||||
* 00110 - NC Weakly-ordered, Non-cacheable, Bufferable, Shareable, Non-trustable
|
||||
* 01110 - PMA Weakly-ordered, Cacheable, Bufferable, Shareable, Non-trustable
|
||||
* 10000 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable
|
||||
* 10010 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Shareable, Non-trustable
|
||||
*/
|
||||
#define _PAGE_PMA_THEAD ((1UL << 62) | (1UL << 61) | (1UL << 60))
|
||||
#define _PAGE_NOCACHE_THEAD 0UL
|
||||
#define _PAGE_IO_THEAD (1UL << 63)
|
||||
#define _PAGE_NOCACHE_THEAD ((1UL < 61) | (1UL << 60))
|
||||
#define _PAGE_IO_THEAD ((1UL << 63) | (1UL << 60))
|
||||
#define _PAGE_MTMASK_THEAD (_PAGE_PMA_THEAD | _PAGE_IO_THEAD | (1UL << 59))
|
||||
|
||||
static inline u64 riscv_page_mtmask(void)
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
#define _PAGE_GLOBAL (1 << 5) /* Global */
|
||||
#define _PAGE_ACCESSED (1 << 6) /* Set by hardware on any access */
|
||||
#define _PAGE_DIRTY (1 << 7) /* Set by hardware on any write */
|
||||
#define _PAGE_SOFT (1 << 8) /* Reserved for software */
|
||||
#define _PAGE_SOFT (3 << 8) /* Reserved for software */
|
||||
|
||||
#define _PAGE_SPECIAL _PAGE_SOFT
|
||||
#define _PAGE_SPECIAL (1 << 8) /* RSW: 0x1 */
|
||||
#define _PAGE_TABLE _PAGE_PRESENT
|
||||
|
||||
/*
|
||||
|
||||
@@ -291,6 +291,7 @@ static inline pte_t pud_pte(pud_t pud)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RISCV_ISA_SVNAPOT
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
static __always_inline bool has_svnapot(void)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <linux/const.h>
|
||||
#include <linux/cache.h>
|
||||
#include <linux/prctl.h>
|
||||
|
||||
#include <vdso/processor.h>
|
||||
|
||||
@@ -82,6 +83,7 @@ struct thread_struct {
|
||||
unsigned long bad_cause;
|
||||
unsigned long vstate_ctrl;
|
||||
struct __riscv_v_ext_state vstate;
|
||||
unsigned long align_ctl;
|
||||
};
|
||||
|
||||
/* Whitelist the fstate from the task_struct for hardened usercopy */
|
||||
@@ -94,6 +96,7 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
|
||||
|
||||
#define INIT_THREAD { \
|
||||
.sp = sizeof(init_stack) + (long)&init_stack, \
|
||||
.align_ctl = PR_UNALIGN_NOPRINT, \
|
||||
}
|
||||
|
||||
#define task_pt_regs(tsk) \
|
||||
@@ -136,6 +139,12 @@ extern long riscv_v_vstate_ctrl_set_current(unsigned long arg);
|
||||
extern long riscv_v_vstate_ctrl_get_current(void);
|
||||
#endif /* CONFIG_RISCV_ISA_V */
|
||||
|
||||
extern int get_unalign_ctl(struct task_struct *tsk, unsigned long addr);
|
||||
extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
|
||||
|
||||
#define GET_UNALIGN_CTL(tsk, addr) get_unalign_ctl((tsk), (addr))
|
||||
#define SET_UNALIGN_CTL(tsk, val) set_unalign_ctl((tsk), (val))
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_RISCV_PROCESSOR_H */
|
||||
|
||||
@@ -280,9 +280,6 @@ void sbi_set_timer(uint64_t stime_value);
|
||||
void sbi_shutdown(void);
|
||||
void sbi_send_ipi(unsigned int cpu);
|
||||
int sbi_remote_fence_i(const struct cpumask *cpu_mask);
|
||||
int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
|
||||
unsigned long start,
|
||||
unsigned long size);
|
||||
|
||||
int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask,
|
||||
unsigned long start,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <linux/jump_label.h>
|
||||
#include <linux/sched/task_stack.h>
|
||||
#include <asm/vector.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/csr.h>
|
||||
|
||||
@@ -15,7 +15,13 @@ static void tlb_flush(struct mmu_gather *tlb);
|
||||
|
||||
static inline void tlb_flush(struct mmu_gather *tlb)
|
||||
{
|
||||
flush_tlb_mm(tlb->mm);
|
||||
#ifdef CONFIG_MMU
|
||||
if (tlb->fullmm || tlb->need_flush_all)
|
||||
flush_tlb_mm(tlb->mm);
|
||||
else
|
||||
flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end,
|
||||
tlb_get_unmap_size(tlb));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _ASM_RISCV_TLB_H */
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <asm/smp.h>
|
||||
#include <asm/errata_list.h>
|
||||
|
||||
#define FLUSH_TLB_MAX_SIZE ((unsigned long)-1)
|
||||
#define FLUSH_TLB_NO_ASID ((unsigned long)-1)
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
extern unsigned long asid_mask;
|
||||
|
||||
@@ -32,9 +35,12 @@ static inline void local_flush_tlb_page(unsigned long addr)
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_MMU)
|
||||
void flush_tlb_all(void);
|
||||
void flush_tlb_mm(struct mm_struct *mm);
|
||||
void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long end, unsigned int page_size);
|
||||
void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
|
||||
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
unsigned long end);
|
||||
void flush_tlb_kernel_range(unsigned long start, unsigned long end);
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
|
||||
void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
@@ -51,14 +57,15 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
||||
#define flush_tlb_mm(mm) flush_tlb_all()
|
||||
#endif /* !CONFIG_SMP || !CONFIG_MMU */
|
||||
|
||||
/* Flush a range of kernel pages */
|
||||
static inline void flush_tlb_kernel_range(unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
flush_tlb_all();
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
||||
#define flush_tlb_mm(mm) flush_tlb_all()
|
||||
#define flush_tlb_mm_range(mm, start, end, page_size) flush_tlb_all()
|
||||
#endif /* !CONFIG_SMP || !CONFIG_MMU */
|
||||
|
||||
#endif /* _ASM_RISCV_TLBFLUSH_H */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user