RISC-V Patches for the 6.11 Merge Window, Part 2
* Support for NUMA (via SRAT and SLIT), console output (via SPCR), and cache info (via PPTT) on ACPI-based systems. * The trap entry/exit code no longer breaks the return address stack predictor on many systems, which results in an improvement to trap latency. * Support for HAVE_ARCH_STACKLEAK. * The sv39 linear map has been extended to support 128GiB mappings. * The frequency of the mtime CSR is now visible via hwprobe. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEKzw3R0RoQ7JKlDp6LhMZ81+7GIkFAmaj2EYTHHBhbG1lckBk YWJiZWx0LmNvbQAKCRAuExnzX7sYiVG3D/9kNHTI09iPDJd6fTChE3cpMxy7xXXE URX3Avu+gYsJmIbYyg4RnQ8FGFN7icKBCrQqs7JmLliU0NU+YMcCcjsJA2QaivbD VAlaex1qNcvNGteHrpbqhr3Zs4zw8GlBkB3KFTLyPAp61bybGo0a/A5ONJ7ScQIW RWHewAPgb86cQ0Q34JpO87TqvMM0KMvhQP5dip+olaFjLRBzhXmGFZfHqA80kTWl 0ytYclVCHZMtO/5mnQpuIOVs1IKw9L4wa0sivOQF0iLTqfKDFALa6yZsThHA/w3e JVuBAdQhcPZ3fgO2fUfJPlW16GmRC2/tdiFg5NFw8k4vo7DYBwX55ztPKXqDrJDM 8ah85IeLiPar/A/uHdn6bPjK+aGMuzklKF50r62XXAc2fL8mza1sdvKCVOy2EOLn JyGI9c/10KpvN/DW8g7hPefhvbx4+tCKkFcPqf++VQha6W8cQdCKi+Li0Pm8TTnp XPQjIvSlDDG1Pl4ofgBSFoyB8pkBXNzvv8NZp+YYtnqSOLAKaZuP+KwA8TwHdvGM pdCXcL3KHiLy4/pJWEoNTutD0mbJ7PUIb2P/KkjqYDgp4F1n0Hg+/aeSIp+7a4Pv yTBctIGxrlriQMIdtWCR8tyhcPP4pDpGYkW0K15EE16G0NK0fjD89LEXYqT6ae2R C0QgiwnVe/eopg== =zeUn -----END PGP SIGNATURE----- Merge tag 'riscv-for-linus-6.11-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux Pull more RISC-V updates from Palmer Dabbelt: - Support for NUMA (via SRAT and SLIT), console output (via SPCR), and cache info (via PPTT) on ACPI-based systems. - The trap entry/exit code no longer breaks the return address stack predictor on many systems, which results in an improvement to trap latency. - Support for HAVE_ARCH_STACKLEAK. - The sv39 linear map has been extended to support 128GiB mappings. - The frequency of the mtime CSR is now visible via hwprobe. * tag 'riscv-for-linus-6.11-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (21 commits) RISC-V: Provide the frequency of time CSR via hwprobe riscv: Extend sv39 linear mapping max size to 128G riscv: enable HAVE_ARCH_STACKLEAK riscv: signal: Remove unlikely() from WARN_ON() condition riscv: Improve exception and system call latency RISC-V: Select ACPI PPTT drivers riscv: cacheinfo: initialize cacheinfo's level and type from ACPI PPTT riscv: cacheinfo: remove the useless input parameter (node) of ci_leaf_init() RISC-V: ACPI: Enable SPCR table for console output on RISC-V riscv: boot: remove duplicated targets line trace: riscv: Remove deprecated kprobe on ftrace support riscv: cpufeature: Extract common elements from extension checking riscv: Introduce vendor variants of extension helpers riscv: Add vendor extensions to /proc/cpuinfo riscv: Extend cpufeature.c to detect vendor extensions RISC-V: run savedefconfig for defconfig RISC-V: hwprobe: sort EXT_KEY()s in hwprobe_isa_ext0() alphabetically ACPI: NUMA: replace pr_info with pr_debug in arch_acpi_numa_init ACPI: NUMA: change the ACPI_NUMA to a hidden option ACPI: NUMA: Add handler for SRAT RINTC affinity structure ...
This commit is contained in:
commit
c9f33436d8
@ -264,3 +264,5 @@ The following keys are defined:
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS`: An unsigned long which
|
||||
represent the highest userspace virtual address usable.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_TIME_CSR_FREQ`: Frequency (in Hz) of `time CSR`.
|
||||
|
@ -47,11 +47,12 @@ RISC-V Linux Kernel SV39
|
||||
| Kernel-space virtual memory, shared between all processes:
|
||||
____________________________________________________________|___________________________________________________________
|
||||
| | | |
|
||||
ffffffc6fea00000 | -228 GB | ffffffc6feffffff | 6 MB | fixmap
|
||||
ffffffc6ff000000 | -228 GB | ffffffc6ffffffff | 16 MB | PCI io
|
||||
ffffffc700000000 | -228 GB | ffffffc7ffffffff | 4 GB | vmemmap
|
||||
ffffffc800000000 | -224 GB | ffffffd7ffffffff | 64 GB | vmalloc/ioremap space
|
||||
ffffffd800000000 | -160 GB | fffffff6ffffffff | 124 GB | direct mapping of all physical memory
|
||||
ffffffc4fea00000 | -236 GB | ffffffc4feffffff | 6 MB | fixmap
|
||||
ffffffc4ff000000 | -236 GB | ffffffc4ffffffff | 16 MB | PCI io
|
||||
ffffffc500000000 | -236 GB | ffffffc5ffffffff | 4 GB | vmemmap
|
||||
ffffffc600000000 | -232 GB | ffffffd5ffffffff | 64 GB | vmalloc/ioremap space
|
||||
ffffffd600000000 | -168 GB | fffffff5ffffffff | 128 GB | direct mapping of all physical memory
|
||||
| | | |
|
||||
fffffff700000000 | -36 GB | fffffffeffffffff | 32 GB | kasan
|
||||
__________________|____________|__________________|_________|____________________________________________________________
|
||||
|
|
||||
|
@ -1471,7 +1471,6 @@ config HOTPLUG_CPU
|
||||
config NUMA
|
||||
bool "NUMA Memory Allocation and Scheduler Support"
|
||||
select GENERIC_ARCH_NUMA
|
||||
select ACPI_NUMA if ACPI
|
||||
select OF_NUMA
|
||||
select HAVE_SETUP_PER_CPU_AREA
|
||||
select NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
|
@ -476,7 +476,6 @@ config NR_CPUS
|
||||
config NUMA
|
||||
bool "NUMA Support"
|
||||
select SMP
|
||||
select ACPI_NUMA if ACPI
|
||||
help
|
||||
Say Y to compile the kernel with NUMA (Non-Uniform Memory Access)
|
||||
support. This option improves performance on systems with more
|
||||
|
@ -13,7 +13,9 @@ config 32BIT
|
||||
config RISCV
|
||||
def_bool y
|
||||
select ACPI_GENERIC_GSI if ACPI
|
||||
select ACPI_PPTT if ACPI
|
||||
select ACPI_REDUCED_HARDWARE_ONLY if ACPI
|
||||
select ACPI_SPCR_TABLE if ACPI
|
||||
select ARCH_DMA_DEFAULT_COHERENT
|
||||
select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
|
||||
select ARCH_ENABLE_MEMORY_HOTPLUG if SPARSEMEM_VMEMMAP
|
||||
@ -123,6 +125,7 @@ config RISCV
|
||||
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
|
||||
select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
|
||||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
select HAVE_ARCH_STACKLEAK
|
||||
select HAVE_ARCH_THREAD_STRUCT_WHITELIST
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT && MMU
|
||||
@ -154,7 +157,6 @@ config RISCV
|
||||
select HAVE_KERNEL_UNCOMPRESSED if !XIP_KERNEL && !EFI_ZBOOT
|
||||
select HAVE_KERNEL_ZSTD if !XIP_KERNEL && !EFI_ZBOOT
|
||||
select HAVE_KPROBES if !XIP_KERNEL
|
||||
select HAVE_KPROBES_ON_FTRACE if !XIP_KERNEL
|
||||
select HAVE_KRETPROBES if !XIP_KERNEL
|
||||
# https://github.com/ClangBuiltLinux/linux/issues/1881
|
||||
select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if !LD_IS_LLD
|
||||
@ -820,6 +822,8 @@ config RISCV_EFFICIENT_UNALIGNED_ACCESS
|
||||
|
||||
endchoice
|
||||
|
||||
source "arch/riscv/Kconfig.vendor"
|
||||
|
||||
endmenu # "Platform type"
|
||||
|
||||
menu "Kernel features"
|
||||
|
19
arch/riscv/Kconfig.vendor
Normal file
19
arch/riscv/Kconfig.vendor
Normal file
@ -0,0 +1,19 @@
|
||||
menu "Vendor extensions"
|
||||
|
||||
config RISCV_ISA_VENDOR_EXT
|
||||
bool
|
||||
|
||||
menu "Andes"
|
||||
config RISCV_ISA_VENDOR_EXT_ANDES
|
||||
bool "Andes vendor extension support"
|
||||
select RISCV_ISA_VENDOR_EXT
|
||||
default y
|
||||
help
|
||||
Say N here if you want to disable all Andes vendor extension
|
||||
support. This will cause any Andes vendor extensions that are
|
||||
requested by hardware probing to be ignored.
|
||||
|
||||
If you don't know what to do here, say Y.
|
||||
endmenu
|
||||
|
||||
endmenu
|
@ -18,7 +18,6 @@ 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
|
||||
targets := Image Image.* loader loader.o loader.lds loader.bin xipImage
|
||||
|
||||
ifeq ($(CONFIG_XIP_KERNEL),y)
|
||||
|
@ -7,6 +7,7 @@ CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
CONFIG_CGROUPS=y
|
||||
CONFIG_MEMCG=y
|
||||
CONFIG_BLK_CGROUP=y
|
||||
CONFIG_CGROUP_SCHED=y
|
||||
CONFIG_CFS_BANDWIDTH=y
|
||||
CONFIG_RT_GROUP_SCHED=y
|
||||
@ -35,9 +36,6 @@ CONFIG_ARCH_THEAD=y
|
||||
CONFIG_ARCH_VIRT=y
|
||||
CONFIG_ARCH_CANAAN=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_HOTPLUG_CPU=y
|
||||
CONFIG_PM=y
|
||||
CONFIG_CPU_IDLE=y
|
||||
CONFIG_CPU_FREQ=y
|
||||
CONFIG_CPU_FREQ_STAT=y
|
||||
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
|
||||
@ -52,13 +50,11 @@ CONFIG_ACPI=y
|
||||
CONFIG_JUMP_LABEL=y
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_SPARSEMEM_MANUAL=y
|
||||
CONFIG_BLK_DEV_THROTTLING=y
|
||||
CONFIG_SPARSEMEM_MANUAL=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_XFRM_USER=m
|
||||
CONFIG_INET=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
CONFIG_IP_ADVANCED_ROUTER=y
|
||||
CONFIG_IP_PNP=y
|
||||
@ -102,9 +98,9 @@ CONFIG_NET_SCHED=y
|
||||
CONFIG_NET_CLS_CGROUP=m
|
||||
CONFIG_NETLINK_DIAG=y
|
||||
CONFIG_CGROUP_NET_PRIO=y
|
||||
CONFIG_CAN=m
|
||||
CONFIG_NET_9P=y
|
||||
CONFIG_NET_9P_VIRTIO=y
|
||||
CONFIG_CAN=m
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
CONFIG_PCI_HOST_GENERIC=y
|
||||
@ -153,8 +149,8 @@ CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_DW=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
CONFIG_SERIAL_SH_SCI=y
|
||||
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
|
||||
CONFIG_SERIAL_SH_SCI=y
|
||||
CONFIG_VIRTIO_CONSOLE=y
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_HW_RANDOM_VIRTIO=y
|
||||
@ -179,7 +175,6 @@ CONFIG_DEVFREQ_THERMAL=y
|
||||
CONFIG_RZG2L_THERMAL=y
|
||||
CONFIG_WATCHDOG=y
|
||||
CONFIG_SUNXI_WATCHDOG=y
|
||||
CONFIG_RENESAS_RZG2LWDT=y
|
||||
CONFIG_MFD_AXP20X_I2C=y
|
||||
CONFIG_REGULATOR=y
|
||||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||
@ -193,11 +188,9 @@ CONFIG_DRM_NOUVEAU=m
|
||||
CONFIG_DRM_SUN4I=m
|
||||
CONFIG_DRM_VIRTIO_GPU=m
|
||||
CONFIG_FB=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_SND=y
|
||||
CONFIG_SND_SOC=y
|
||||
CONFIG_SND_SOC_RZ=m
|
||||
CONFIG_SND_DESIGNWARE_I2S=m
|
||||
CONFIG_SND_SOC_STARFIVE=m
|
||||
CONFIG_SND_SOC_JH7110_PWMDAC=m
|
||||
@ -239,34 +232,31 @@ CONFIG_USB_CONFIGFS_F_FS=y
|
||||
CONFIG_MMC=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_PLTFM=y
|
||||
CONFIG_MMC_SDHCI_CADENCE=y
|
||||
CONFIG_MMC_SDHCI_OF_DWCMSHC=y
|
||||
CONFIG_MMC_SDHCI_CADENCE=y
|
||||
CONFIG_MMC_SPI=y
|
||||
CONFIG_MMC_SDHI=y
|
||||
CONFIG_MMC_DW=y
|
||||
CONFIG_MMC_DW_STARFIVE=y
|
||||
CONFIG_MMC_SDHI=y
|
||||
CONFIG_MMC_SUNXI=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_DRV_SUN6I=y
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_DMA_SUN6I=m
|
||||
CONFIG_DW_AXI_DMAC=y
|
||||
CONFIG_RZ_DMAC=y
|
||||
CONFIG_VIRTIO_PCI=y
|
||||
CONFIG_VIRTIO_BALLOON=y
|
||||
CONFIG_VIRTIO_INPUT=y
|
||||
CONFIG_VIRTIO_MMIO=y
|
||||
CONFIG_RENESAS_OSTM=y
|
||||
CONFIG_CLK_SOPHGO_CV1800=y
|
||||
CONFIG_SUN8I_DE2_CCU=m
|
||||
CONFIG_RENESAS_OSTM=y
|
||||
CONFIG_SUN50I_IOMMU=y
|
||||
CONFIG_RPMSG_CHAR=y
|
||||
CONFIG_RPMSG_CTRL=y
|
||||
CONFIG_RPMSG_VIRTIO=y
|
||||
CONFIG_ARCH_R9A07G043=y
|
||||
CONFIG_PM_DEVFREQ=y
|
||||
CONFIG_IIO=y
|
||||
CONFIG_RZG2L_ADC=m
|
||||
CONFIG_RESET_RZG2L_USBPHY_CTRL=y
|
||||
CONFIG_PHY_SUN4I_USB=m
|
||||
CONFIG_PHY_RCAR_GEN3_USB2=y
|
||||
CONFIG_PHY_STARFIVE_JH7110_DPHY_RX=m
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/vendorid_list.h>
|
||||
#include <asm/vendor_extensions.h>
|
||||
|
||||
#define ANDES_AX45MP_MARCHID 0x8000000000008a45UL
|
||||
#define ANDES_AX45MP_MIMPID 0x500UL
|
||||
@ -65,6 +66,8 @@ void __init_or_module andes_errata_patch_func(struct alt_entry *begin, struct al
|
||||
unsigned long archid, unsigned long impid,
|
||||
unsigned int stage)
|
||||
{
|
||||
BUILD_BUG_ON(ERRATA_ANDES_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
|
||||
|
||||
if (stage == RISCV_ALTERNATIVES_BOOT)
|
||||
errata_probe_iocp(stage, archid, impid);
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/vendorid_list.h>
|
||||
#include <asm/errata_list.h>
|
||||
#include <asm/vendor_extensions.h>
|
||||
|
||||
struct errata_info_t {
|
||||
char name[32];
|
||||
@ -96,6 +97,8 @@ void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
|
||||
u32 cpu_apply_errata = 0;
|
||||
u32 tmp;
|
||||
|
||||
BUILD_BUG_ON(ERRATA_SIFIVE_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
|
||||
|
||||
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
|
||||
return;
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/patch.h>
|
||||
#include <asm/vendorid_list.h>
|
||||
#include <asm/vendor_extensions.h>
|
||||
|
||||
#define CSR_TH_SXSTATUS 0x5c0
|
||||
#define SXSTATUS_MAEE _AC(0x200000, UL)
|
||||
@ -166,6 +167,8 @@ void thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
|
||||
u32 tmp;
|
||||
void *oldptr, *altptr;
|
||||
|
||||
BUILD_BUG_ON(ERRATA_THEAD_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
|
||||
|
||||
for (alt = begin; alt < end; alt++) {
|
||||
if (alt->vendor_id != THEAD_VENDOR_ID)
|
||||
continue;
|
||||
|
@ -61,11 +61,14 @@ static inline void arch_fix_phys_package_id(int num, u32 slot) { }
|
||||
|
||||
void acpi_init_rintc_map(void);
|
||||
struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu);
|
||||
u32 get_acpi_id_for_cpu(int cpu);
|
||||
static inline u32 get_acpi_id_for_cpu(int cpu)
|
||||
{
|
||||
return acpi_cpu_get_madt_rintc(cpu)->uid;
|
||||
}
|
||||
|
||||
int acpi_get_riscv_isa(struct acpi_table_header *table,
|
||||
unsigned int cpu, const char **isa);
|
||||
|
||||
static inline int acpi_numa_get_nid(unsigned int cpu) { return NUMA_NO_NODE; }
|
||||
void acpi_get_cbo_block_size(struct acpi_table_header *table, u32 *cbom_size,
|
||||
u32 *cboz_size, u32 *cbop_size);
|
||||
#else
|
||||
@ -87,4 +90,12 @@ static inline void acpi_get_cbo_block_size(struct acpi_table_header *table,
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#ifdef CONFIG_ACPI_NUMA
|
||||
int acpi_numa_get_nid(unsigned int cpu);
|
||||
void acpi_map_cpus_to_nodes(void);
|
||||
#else
|
||||
static inline int acpi_numa_get_nid(unsigned int cpu) { return NUMA_NO_NODE; }
|
||||
static inline void acpi_map_cpus_to_nodes(void) { }
|
||||
#endif /* CONFIG_ACPI_NUMA */
|
||||
|
||||
#endif /*_ASM_ACPI_H*/
|
||||
|
@ -33,6 +33,31 @@ extern struct riscv_isainfo hart_isa[NR_CPUS];
|
||||
|
||||
void riscv_user_isa_enable(void);
|
||||
|
||||
#define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size, _validate) { \
|
||||
.name = #_name, \
|
||||
.property = #_name, \
|
||||
.id = _id, \
|
||||
.subset_ext_ids = _subset_exts, \
|
||||
.subset_ext_size = _subset_exts_size, \
|
||||
.validate = _validate \
|
||||
}
|
||||
|
||||
#define __RISCV_ISA_EXT_DATA(_name, _id) _RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, NULL)
|
||||
|
||||
#define __RISCV_ISA_EXT_DATA_VALIDATE(_name, _id, _validate) \
|
||||
_RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, _validate)
|
||||
|
||||
/* Used to declare pure "lasso" extension (Zk for instance) */
|
||||
#define __RISCV_ISA_EXT_BUNDLE(_name, _bundled_exts) \
|
||||
_RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \
|
||||
ARRAY_SIZE(_bundled_exts), NULL)
|
||||
|
||||
/* Used to declare extensions that are a superset of other extensions (Zvbb for instance) */
|
||||
#define __RISCV_ISA_EXT_SUPERSET(_name, _id, _sub_exts) \
|
||||
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), NULL)
|
||||
#define __RISCV_ISA_EXT_SUPERSET_VALIDATE(_name, _id, _sub_exts, _validate) \
|
||||
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate)
|
||||
|
||||
#if defined(CONFIG_RISCV_MISALIGNED)
|
||||
bool check_unaligned_access_emulated_all_cpus(void);
|
||||
void unaligned_emulation_finish(void);
|
||||
@ -79,59 +104,66 @@ extern bool riscv_isa_fallback;
|
||||
|
||||
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
|
||||
|
||||
#define STANDARD_EXT 0
|
||||
|
||||
bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, unsigned 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)
|
||||
static __always_inline bool __riscv_has_extension_likely(const unsigned long vendor,
|
||||
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 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;
|
||||
}
|
||||
asm goto(ALTERNATIVE("j %l[l_no]", "nop", %[vendor], %[ext], 1)
|
||||
:
|
||||
: [vendor] "i" (vendor), [ext] "i" (ext)
|
||||
:
|
||||
: l_no);
|
||||
|
||||
return true;
|
||||
l_no:
|
||||
return false;
|
||||
}
|
||||
|
||||
static __always_inline bool
|
||||
riscv_has_extension_unlikely(const unsigned long ext)
|
||||
static __always_inline bool __riscv_has_extension_unlikely(const unsigned long vendor,
|
||||
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 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;
|
||||
}
|
||||
asm goto(ALTERNATIVE("nop", "j %l[l_yes]", %[vendor], %[ext], 1)
|
||||
:
|
||||
: [vendor] "i" (vendor), [ext] "i" (ext)
|
||||
:
|
||||
: l_yes);
|
||||
|
||||
return false;
|
||||
l_yes:
|
||||
return true;
|
||||
}
|
||||
|
||||
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))
|
||||
return __riscv_has_extension_unlikely(STANDARD_EXT, ext);
|
||||
|
||||
return __riscv_isa_extension_available(NULL, 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))
|
||||
return __riscv_has_extension_likely(STANDARD_EXT, ext);
|
||||
|
||||
return __riscv_isa_extension_available(NULL, ext);
|
||||
}
|
||||
|
||||
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))
|
||||
compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
|
||||
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
|
||||
__riscv_has_extension_likely(STANDARD_EXT, ext))
|
||||
return true;
|
||||
|
||||
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
|
||||
@ -139,7 +171,10 @@ static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsign
|
||||
|
||||
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))
|
||||
compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
|
||||
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
|
||||
__riscv_has_extension_unlikely(STANDARD_EXT, ext))
|
||||
return true;
|
||||
|
||||
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
|
||||
|
@ -80,19 +80,18 @@
|
||||
#define RISCV_ISA_EXT_ZFA 71
|
||||
#define RISCV_ISA_EXT_ZTSO 72
|
||||
#define RISCV_ISA_EXT_ZACAS 73
|
||||
#define RISCV_ISA_EXT_XANDESPMU 74
|
||||
#define RISCV_ISA_EXT_ZVE32X 75
|
||||
#define RISCV_ISA_EXT_ZVE32F 76
|
||||
#define RISCV_ISA_EXT_ZVE64X 77
|
||||
#define RISCV_ISA_EXT_ZVE64F 78
|
||||
#define RISCV_ISA_EXT_ZVE64D 79
|
||||
#define RISCV_ISA_EXT_ZIMOP 80
|
||||
#define RISCV_ISA_EXT_ZCA 81
|
||||
#define RISCV_ISA_EXT_ZCB 82
|
||||
#define RISCV_ISA_EXT_ZCD 83
|
||||
#define RISCV_ISA_EXT_ZCF 84
|
||||
#define RISCV_ISA_EXT_ZCMOP 85
|
||||
#define RISCV_ISA_EXT_ZAWRS 86
|
||||
#define RISCV_ISA_EXT_ZVE32X 74
|
||||
#define RISCV_ISA_EXT_ZVE32F 75
|
||||
#define RISCV_ISA_EXT_ZVE64X 76
|
||||
#define RISCV_ISA_EXT_ZVE64F 77
|
||||
#define RISCV_ISA_EXT_ZVE64D 78
|
||||
#define RISCV_ISA_EXT_ZIMOP 79
|
||||
#define RISCV_ISA_EXT_ZCA 80
|
||||
#define RISCV_ISA_EXT_ZCB 81
|
||||
#define RISCV_ISA_EXT_ZCD 82
|
||||
#define RISCV_ISA_EXT_ZCF 83
|
||||
#define RISCV_ISA_EXT_ZCMOP 84
|
||||
#define RISCV_ISA_EXT_ZAWRS 85
|
||||
|
||||
#define RISCV_ISA_EXT_XLINUXENVCFG 127
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include <uapi/asm/hwprobe.h>
|
||||
|
||||
#define RISCV_HWPROBE_MAX_KEY 7
|
||||
#define RISCV_HWPROBE_MAX_KEY 8
|
||||
|
||||
static inline bool riscv_hwprobe_key_is_valid(__s64 key)
|
||||
{
|
||||
|
@ -37,7 +37,7 @@
|
||||
* define the PAGE_OFFSET value for SV48 and SV39.
|
||||
*/
|
||||
#define PAGE_OFFSET_L4 _AC(0xffffaf8000000000, UL)
|
||||
#define PAGE_OFFSET_L3 _AC(0xffffffd800000000, UL)
|
||||
#define PAGE_OFFSET_L3 _AC(0xffffffd600000000, UL)
|
||||
#else
|
||||
#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL)
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <linux/const.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
/* thread information allocation */
|
||||
#define THREAD_SIZE_ORDER CONFIG_THREAD_SIZE_ORDER
|
||||
|
104
arch/riscv/include/asm/vendor_extensions.h
Normal file
104
arch/riscv/include/asm/vendor_extensions.h
Normal file
@ -0,0 +1,104 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright 2024 Rivos, Inc
|
||||
*/
|
||||
|
||||
#ifndef _ASM_VENDOR_EXTENSIONS_H
|
||||
#define _ASM_VENDOR_EXTENSIONS_H
|
||||
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* The extension keys of each vendor must be strictly less than this value.
|
||||
*/
|
||||
#define RISCV_ISA_VENDOR_EXT_MAX 32
|
||||
|
||||
struct riscv_isavendorinfo {
|
||||
DECLARE_BITMAP(isa, RISCV_ISA_VENDOR_EXT_MAX);
|
||||
};
|
||||
|
||||
struct riscv_isa_vendor_ext_data_list {
|
||||
bool is_initialized;
|
||||
const size_t ext_data_count;
|
||||
const struct riscv_isa_ext_data *ext_data;
|
||||
struct riscv_isavendorinfo per_hart_isa_bitmap[NR_CPUS];
|
||||
struct riscv_isavendorinfo all_harts_isa_bitmap;
|
||||
};
|
||||
|
||||
extern struct riscv_isa_vendor_ext_data_list *riscv_isa_vendor_ext_list[];
|
||||
|
||||
extern const size_t riscv_isa_vendor_ext_list_size;
|
||||
|
||||
/*
|
||||
* The alternatives need some way of distinguishing between vendor extensions
|
||||
* and errata. Incrementing all of the vendor extension keys so they are at
|
||||
* least 0x8000 accomplishes that.
|
||||
*/
|
||||
#define RISCV_VENDOR_EXT_ALTERNATIVES_BASE 0x8000
|
||||
|
||||
#define VENDOR_EXT_ALL_CPUS -1
|
||||
|
||||
bool __riscv_isa_vendor_extension_available(int cpu, unsigned long vendor, unsigned int bit);
|
||||
#define riscv_cpu_isa_vendor_extension_available(cpu, vendor, ext) \
|
||||
__riscv_isa_vendor_extension_available(cpu, vendor, RISCV_ISA_VENDOR_EXT_##ext)
|
||||
#define riscv_isa_vendor_extension_available(vendor, ext) \
|
||||
__riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor, \
|
||||
RISCV_ISA_VENDOR_EXT_##ext)
|
||||
|
||||
static __always_inline bool riscv_has_vendor_extension_likely(const unsigned long vendor,
|
||||
const unsigned long ext)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
|
||||
return false;
|
||||
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
|
||||
return __riscv_has_extension_likely(vendor,
|
||||
ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
|
||||
|
||||
return __riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor, ext);
|
||||
}
|
||||
|
||||
static __always_inline bool riscv_has_vendor_extension_unlikely(const unsigned long vendor,
|
||||
const unsigned long ext)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
|
||||
return false;
|
||||
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
|
||||
return __riscv_has_extension_unlikely(vendor,
|
||||
ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
|
||||
|
||||
return __riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor, ext);
|
||||
}
|
||||
|
||||
static __always_inline bool riscv_cpu_has_vendor_extension_likely(const unsigned long vendor,
|
||||
int cpu, const unsigned long ext)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
|
||||
return false;
|
||||
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
|
||||
__riscv_has_extension_likely(vendor, ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE))
|
||||
return true;
|
||||
|
||||
return __riscv_isa_vendor_extension_available(cpu, vendor, ext);
|
||||
}
|
||||
|
||||
static __always_inline bool riscv_cpu_has_vendor_extension_unlikely(const unsigned long vendor,
|
||||
int cpu,
|
||||
const unsigned long ext)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
|
||||
return false;
|
||||
|
||||
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
|
||||
__riscv_has_extension_unlikely(vendor, ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE))
|
||||
return true;
|
||||
|
||||
return __riscv_isa_vendor_extension_available(cpu, vendor, ext);
|
||||
}
|
||||
|
||||
#endif /* _ASM_VENDOR_EXTENSIONS_H */
|
19
arch/riscv/include/asm/vendor_extensions/andes.h
Normal file
19
arch/riscv/include/asm/vendor_extensions/andes.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_RISCV_VENDOR_EXTENSIONS_ANDES_H
|
||||
#define _ASM_RISCV_VENDOR_EXTENSIONS_ANDES_H
|
||||
|
||||
#include <asm/vendor_extensions.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define RISCV_ISA_VENDOR_EXT_XANDESPMU 0
|
||||
|
||||
/*
|
||||
* Extension keys should be strictly less than max.
|
||||
* It is safe to increment this when necessary.
|
||||
*/
|
||||
#define RISCV_ISA_VENDOR_EXT_MAX_ANDES 32
|
||||
|
||||
extern struct riscv_isa_vendor_ext_data_list riscv_isa_vendor_ext_list_andes;
|
||||
|
||||
#endif
|
@ -81,6 +81,7 @@ struct riscv_hwprobe {
|
||||
#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
|
||||
#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6
|
||||
#define RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS 7
|
||||
#define RISCV_HWPROBE_KEY_TIME_CSR_FREQ 8
|
||||
/* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
|
||||
|
||||
/* Flags */
|
||||
|
@ -58,6 +58,8 @@ obj-y += riscv_ksyms.o
|
||||
obj-y += stacktrace.o
|
||||
obj-y += cacheinfo.o
|
||||
obj-y += patch.o
|
||||
obj-y += vendor_extensions.o
|
||||
obj-y += vendor_extensions/
|
||||
obj-y += probes/
|
||||
obj-y += tests/
|
||||
obj-$(CONFIG_MMU) += vdso.o vdso/
|
||||
@ -110,3 +112,4 @@ obj-$(CONFIG_COMPAT) += compat_vdso/
|
||||
|
||||
obj-$(CONFIG_64BIT) += pi/
|
||||
obj-$(CONFIG_ACPI) += acpi.o
|
||||
obj-$(CONFIG_ACPI_NUMA) += acpi_numa.o
|
||||
|
@ -17,7 +17,9 @@
|
||||
#include <linux/efi.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
int acpi_noirq = 1; /* skip ACPI IRQ initialization */
|
||||
int acpi_disabled = 1;
|
||||
@ -131,7 +133,7 @@ void __init acpi_boot_table_init(void)
|
||||
if (param_acpi_off ||
|
||||
(!param_acpi_on && !param_acpi_force &&
|
||||
efi.acpi20 == EFI_INVALID_TABLE_ADDR))
|
||||
return;
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* ACPI is disabled at this point. Enable it in order to parse
|
||||
@ -151,6 +153,14 @@ void __init acpi_boot_table_init(void)
|
||||
if (!param_acpi_force)
|
||||
disable_acpi();
|
||||
}
|
||||
|
||||
done:
|
||||
if (acpi_disabled) {
|
||||
if (earlycon_acpi_spcr_enable)
|
||||
early_init_dt_scan_chosen_stdout();
|
||||
} else {
|
||||
acpi_parse_spcr(earlycon_acpi_spcr_enable, true);
|
||||
}
|
||||
}
|
||||
|
||||
static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end)
|
||||
@ -191,11 +201,6 @@ struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu)
|
||||
return &cpu_madt_rintc[cpu];
|
||||
}
|
||||
|
||||
u32 get_acpi_id_for_cpu(int cpu)
|
||||
{
|
||||
return acpi_cpu_get_madt_rintc(cpu)->uid;
|
||||
}
|
||||
|
||||
/*
|
||||
* __acpi_map_table() will be called before paging_init(), so early_ioremap()
|
||||
* or early_memremap() should be called here to for ACPI table mapping.
|
||||
|
131
arch/riscv/kernel/acpi_numa.c
Normal file
131
arch/riscv/kernel/acpi_numa.c
Normal file
@ -0,0 +1,131 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ACPI 6.6 based NUMA setup for RISCV
|
||||
* Lots of code was borrowed from arch/arm64/kernel/acpi_numa.c
|
||||
*
|
||||
* Copyright 2004 Andi Kleen, SuSE Labs.
|
||||
* Copyright (C) 2013-2016, Linaro Ltd.
|
||||
* Author: Hanjun Guo <hanjun.guo@linaro.org>
|
||||
* Copyright (C) 2024 Intel Corporation.
|
||||
*
|
||||
* Reads the ACPI SRAT table to figure out what memory belongs to which CPUs.
|
||||
*
|
||||
* Called from acpi_numa_init while reading the SRAT and SLIT tables.
|
||||
* Assumes all memory regions belonging to a single proximity domain
|
||||
* are in one chunk. Holes between them will be included in the node.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ACPI: NUMA: " fmt
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/mmzone.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/topology.h>
|
||||
|
||||
#include <asm/numa.h>
|
||||
|
||||
static int acpi_early_node_map[NR_CPUS] __initdata = { NUMA_NO_NODE };
|
||||
|
||||
int __init acpi_numa_get_nid(unsigned int cpu)
|
||||
{
|
||||
return acpi_early_node_map[cpu];
|
||||
}
|
||||
|
||||
static inline int get_cpu_for_acpi_id(u32 uid)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
for (cpu = 0; cpu < nr_cpu_ids; cpu++)
|
||||
if (uid == get_acpi_id_for_cpu(cpu))
|
||||
return cpu;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int __init acpi_parse_rintc_pxm(union acpi_subtable_headers *header,
|
||||
const unsigned long end)
|
||||
{
|
||||
struct acpi_srat_rintc_affinity *pa;
|
||||
int cpu, pxm, node;
|
||||
|
||||
if (srat_disabled())
|
||||
return -EINVAL;
|
||||
|
||||
pa = (struct acpi_srat_rintc_affinity *)header;
|
||||
if (!pa)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(pa->flags & ACPI_SRAT_RINTC_ENABLED))
|
||||
return 0;
|
||||
|
||||
pxm = pa->proximity_domain;
|
||||
node = pxm_to_node(pxm);
|
||||
|
||||
/*
|
||||
* If we can't map the UID to a logical cpu this
|
||||
* means that the UID is not part of possible cpus
|
||||
* so we do not need a NUMA mapping for it, skip
|
||||
* the SRAT entry and keep parsing.
|
||||
*/
|
||||
cpu = get_cpu_for_acpi_id(pa->acpi_processor_uid);
|
||||
if (cpu < 0)
|
||||
return 0;
|
||||
|
||||
acpi_early_node_map[cpu] = node;
|
||||
pr_info("SRAT: PXM %d -> HARTID 0x%lx -> Node %d\n", pxm,
|
||||
cpuid_to_hartid_map(cpu), node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init acpi_map_cpus_to_nodes(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* In ACPI, SMP and CPU NUMA information is provided in separate
|
||||
* static tables, namely the MADT and the SRAT.
|
||||
*
|
||||
* Thus, it is simpler to first create the cpu logical map through
|
||||
* an MADT walk and then map the logical cpus to their node ids
|
||||
* as separate steps.
|
||||
*/
|
||||
acpi_table_parse_entries(ACPI_SIG_SRAT, sizeof(struct acpi_table_srat),
|
||||
ACPI_SRAT_TYPE_RINTC_AFFINITY, acpi_parse_rintc_pxm, 0);
|
||||
|
||||
for (i = 0; i < nr_cpu_ids; i++)
|
||||
early_map_cpu_to_node(i, acpi_numa_get_nid(i));
|
||||
}
|
||||
|
||||
/* Callback for Proximity Domain -> logical node ID mapping */
|
||||
void __init acpi_numa_rintc_affinity_init(struct acpi_srat_rintc_affinity *pa)
|
||||
{
|
||||
int pxm, node;
|
||||
|
||||
if (srat_disabled())
|
||||
return;
|
||||
|
||||
if (pa->header.length < sizeof(struct acpi_srat_rintc_affinity)) {
|
||||
pr_err("SRAT: Invalid SRAT header length: %d\n", pa->header.length);
|
||||
bad_srat();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(pa->flags & ACPI_SRAT_RINTC_ENABLED))
|
||||
return;
|
||||
|
||||
pxm = pa->proximity_domain;
|
||||
node = acpi_map_pxm_to_node(pxm);
|
||||
|
||||
if (node == NUMA_NO_NODE) {
|
||||
pr_err("SRAT: Too many proximity domains %d\n", pxm);
|
||||
bad_srat();
|
||||
return;
|
||||
}
|
||||
|
||||
node_set(node, numa_nodes_parsed);
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
* Copyright (C) 2017 SiFive
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/of.h>
|
||||
#include <asm/cacheinfo.h>
|
||||
@ -64,7 +65,6 @@ uintptr_t get_cache_geometry(u32 level, enum cache_type type)
|
||||
}
|
||||
|
||||
static void ci_leaf_init(struct cacheinfo *this_leaf,
|
||||
struct device_node *node,
|
||||
enum cache_type type, unsigned int level)
|
||||
{
|
||||
this_leaf->level = level;
|
||||
@ -79,12 +79,33 @@ int populate_cache_leaves(unsigned int cpu)
|
||||
struct device_node *prev = NULL;
|
||||
int levels = 1, level = 1;
|
||||
|
||||
if (!acpi_disabled) {
|
||||
int ret, fw_levels, split_levels;
|
||||
|
||||
ret = acpi_get_cache_info(cpu, &fw_levels, &split_levels);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
BUG_ON((split_levels > fw_levels) ||
|
||||
(split_levels + fw_levels > this_cpu_ci->num_leaves));
|
||||
|
||||
for (; level <= this_cpu_ci->num_levels; level++) {
|
||||
if (level <= split_levels) {
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level);
|
||||
} else {
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_UNIFIED, level);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (of_property_read_bool(np, "cache-size"))
|
||||
ci_leaf_init(this_leaf++, np, CACHE_TYPE_UNIFIED, level);
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_UNIFIED, level);
|
||||
if (of_property_read_bool(np, "i-cache-size"))
|
||||
ci_leaf_init(this_leaf++, np, CACHE_TYPE_INST, level);
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level);
|
||||
if (of_property_read_bool(np, "d-cache-size"))
|
||||
ci_leaf_init(this_leaf++, np, CACHE_TYPE_DATA, level);
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
|
||||
|
||||
prev = np;
|
||||
while ((np = of_find_next_cache_node(np))) {
|
||||
@ -97,11 +118,11 @@ int populate_cache_leaves(unsigned int cpu)
|
||||
if (level <= levels)
|
||||
break;
|
||||
if (of_property_read_bool(np, "cache-size"))
|
||||
ci_leaf_init(this_leaf++, np, CACHE_TYPE_UNIFIED, level);
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_UNIFIED, level);
|
||||
if (of_property_read_bool(np, "i-cache-size"))
|
||||
ci_leaf_init(this_leaf++, np, CACHE_TYPE_INST, level);
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level);
|
||||
if (of_property_read_bool(np, "d-cache-size"))
|
||||
ci_leaf_init(this_leaf++, np, CACHE_TYPE_DATA, level);
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
|
||||
levels = level;
|
||||
}
|
||||
of_node_put(np);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/vendor_extensions.h>
|
||||
|
||||
bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
|
||||
{
|
||||
@ -235,7 +236,33 @@ arch_initcall(riscv_cpuinfo_init);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
static void print_isa(struct seq_file *f, const unsigned long *isa_bitmap)
|
||||
#define ALL_CPUS -1
|
||||
|
||||
static void print_vendor_isa(struct seq_file *f, int cpu)
|
||||
{
|
||||
struct riscv_isavendorinfo *vendor_bitmap;
|
||||
struct riscv_isa_vendor_ext_data_list *ext_list;
|
||||
const struct riscv_isa_ext_data *ext_data;
|
||||
|
||||
for (int i = 0; i < riscv_isa_vendor_ext_list_size; i++) {
|
||||
ext_list = riscv_isa_vendor_ext_list[i];
|
||||
ext_data = riscv_isa_vendor_ext_list[i]->ext_data;
|
||||
|
||||
if (cpu == ALL_CPUS)
|
||||
vendor_bitmap = &ext_list->all_harts_isa_bitmap;
|
||||
else
|
||||
vendor_bitmap = &ext_list->per_hart_isa_bitmap[cpu];
|
||||
|
||||
for (int j = 0; j < ext_list->ext_data_count; j++) {
|
||||
if (!__riscv_isa_extension_available(vendor_bitmap->isa, ext_data[j].id))
|
||||
continue;
|
||||
|
||||
seq_printf(f, "_%s", ext_data[j].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void print_isa(struct seq_file *f, const unsigned long *isa_bitmap, int cpu)
|
||||
{
|
||||
|
||||
if (IS_ENABLED(CONFIG_32BIT))
|
||||
@ -254,6 +281,8 @@ static void print_isa(struct seq_file *f, const unsigned long *isa_bitmap)
|
||||
seq_printf(f, "%s", riscv_isa_ext[i].name);
|
||||
}
|
||||
|
||||
print_vendor_isa(f, cpu);
|
||||
|
||||
seq_puts(f, "\n");
|
||||
}
|
||||
|
||||
@ -316,7 +345,7 @@ static int c_show(struct seq_file *m, void *v)
|
||||
* line.
|
||||
*/
|
||||
seq_puts(m, "isa\t\t: ");
|
||||
print_isa(m, NULL);
|
||||
print_isa(m, NULL, ALL_CPUS);
|
||||
print_mmu(m);
|
||||
|
||||
if (acpi_disabled) {
|
||||
@ -338,7 +367,7 @@ static int c_show(struct seq_file *m, void *v)
|
||||
* additional extensions not present across all harts.
|
||||
*/
|
||||
seq_puts(m, "hart isa\t: ");
|
||||
print_isa(m, hart_isa[cpu_id].isa);
|
||||
print_isa(m, hart_isa[cpu_id].isa, cpu_id);
|
||||
seq_puts(m, "\n");
|
||||
|
||||
return 0;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/vector.h>
|
||||
#include <asm/vendor_extensions.h>
|
||||
|
||||
#define NUM_ALPHA_EXTS ('z' - 'a' + 1)
|
||||
|
||||
@ -100,31 +101,6 @@ static int riscv_ext_zicboz_validate(const struct riscv_isa_ext_data *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size, _validate) { \
|
||||
.name = #_name, \
|
||||
.property = #_name, \
|
||||
.id = _id, \
|
||||
.subset_ext_ids = _subset_exts, \
|
||||
.subset_ext_size = _subset_exts_size, \
|
||||
.validate = _validate \
|
||||
}
|
||||
|
||||
#define __RISCV_ISA_EXT_DATA(_name, _id) _RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, NULL)
|
||||
|
||||
#define __RISCV_ISA_EXT_DATA_VALIDATE(_name, _id, _validate) \
|
||||
_RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, _validate)
|
||||
|
||||
/* Used to declare pure "lasso" extension (Zk for instance) */
|
||||
#define __RISCV_ISA_EXT_BUNDLE(_name, _bundled_exts) \
|
||||
_RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \
|
||||
ARRAY_SIZE(_bundled_exts), NULL)
|
||||
|
||||
/* Used to declare extensions that are a superset of other extensions (Zvbb for instance) */
|
||||
#define __RISCV_ISA_EXT_SUPERSET(_name, _id, _sub_exts) \
|
||||
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), NULL)
|
||||
#define __RISCV_ISA_EXT_SUPERSET_VALIDATE(_name, _id, _sub_exts, _validate) \
|
||||
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate)
|
||||
|
||||
static int riscv_ext_zca_depends(const struct riscv_isa_ext_data *data,
|
||||
const unsigned long *isa_bitmap)
|
||||
{
|
||||
@ -405,7 +381,6 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
|
||||
__RISCV_ISA_EXT_DATA(svinval, RISCV_ISA_EXT_SVINVAL),
|
||||
__RISCV_ISA_EXT_DATA(svnapot, RISCV_ISA_EXT_SVNAPOT),
|
||||
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
|
||||
__RISCV_ISA_EXT_DATA(xandespmu, RISCV_ISA_EXT_XANDESPMU),
|
||||
};
|
||||
|
||||
const size_t riscv_isa_ext_count = ARRAY_SIZE(riscv_isa_ext);
|
||||
@ -512,6 +487,21 @@ static void __init riscv_parse_isa_string(const char *isa, unsigned long *bitmap
|
||||
bool ext_err = false;
|
||||
|
||||
switch (*ext) {
|
||||
case 'x':
|
||||
case 'X':
|
||||
if (acpi_disabled)
|
||||
pr_warn_once("Vendor extensions are ignored in riscv,isa. Use riscv,isa-extensions instead.");
|
||||
/*
|
||||
* To skip an extension, we find its end.
|
||||
* As multi-letter extensions must be split from other multi-letter
|
||||
* extensions with an "_", the end of a multi-letter extension will
|
||||
* either be the null character or the "_" at the start of the next
|
||||
* multi-letter extension.
|
||||
*/
|
||||
for (; *isa && *isa != '_'; ++isa)
|
||||
;
|
||||
ext_err = true;
|
||||
break;
|
||||
case 's':
|
||||
/*
|
||||
* Workaround for invalid single-letter 's' & 'u' (QEMU).
|
||||
@ -527,8 +517,6 @@ static void __init riscv_parse_isa_string(const char *isa, unsigned long *bitmap
|
||||
}
|
||||
fallthrough;
|
||||
case 'S':
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'z':
|
||||
case 'Z':
|
||||
/*
|
||||
@ -728,6 +716,61 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap)
|
||||
acpi_put_table((struct acpi_table_header *)rhct);
|
||||
}
|
||||
|
||||
static void __init riscv_fill_cpu_vendor_ext(struct device_node *cpu_node, int cpu)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < riscv_isa_vendor_ext_list_size; i++) {
|
||||
struct riscv_isa_vendor_ext_data_list *ext_list = riscv_isa_vendor_ext_list[i];
|
||||
|
||||
for (int j = 0; j < ext_list->ext_data_count; j++) {
|
||||
const struct riscv_isa_ext_data ext = ext_list->ext_data[j];
|
||||
struct riscv_isavendorinfo *isavendorinfo = &ext_list->per_hart_isa_bitmap[cpu];
|
||||
|
||||
if (of_property_match_string(cpu_node, "riscv,isa-extensions",
|
||||
ext.property) < 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Assume that subset extensions are all members of the
|
||||
* same vendor.
|
||||
*/
|
||||
if (ext.subset_ext_size)
|
||||
for (int k = 0; k < ext.subset_ext_size; k++)
|
||||
set_bit(ext.subset_ext_ids[k], isavendorinfo->isa);
|
||||
|
||||
set_bit(ext.id, isavendorinfo->isa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Populate all_harts_isa_bitmap for each vendor with all of the extensions that
|
||||
* are shared across CPUs for that vendor.
|
||||
*/
|
||||
static void __init riscv_fill_vendor_ext_list(int cpu)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < riscv_isa_vendor_ext_list_size; i++) {
|
||||
struct riscv_isa_vendor_ext_data_list *ext_list = riscv_isa_vendor_ext_list[i];
|
||||
|
||||
if (!ext_list->is_initialized) {
|
||||
bitmap_copy(ext_list->all_harts_isa_bitmap.isa,
|
||||
ext_list->per_hart_isa_bitmap[cpu].isa,
|
||||
RISCV_ISA_VENDOR_EXT_MAX);
|
||||
ext_list->is_initialized = true;
|
||||
} else {
|
||||
bitmap_and(ext_list->all_harts_isa_bitmap.isa,
|
||||
ext_list->all_harts_isa_bitmap.isa,
|
||||
ext_list->per_hart_isa_bitmap[cpu].isa,
|
||||
RISCV_ISA_VENDOR_EXT_MAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
|
||||
{
|
||||
unsigned int cpu;
|
||||
@ -760,6 +803,7 @@ static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
|
||||
}
|
||||
|
||||
riscv_resolve_isa(source_isa, isainfo->isa, &this_hwcap, isa2hwcap);
|
||||
riscv_fill_cpu_vendor_ext(cpu_node, cpu);
|
||||
|
||||
of_node_put(cpu_node);
|
||||
|
||||
@ -776,6 +820,8 @@ static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
|
||||
bitmap_copy(riscv_isa, isainfo->isa, RISCV_ISA_EXT_MAX);
|
||||
else
|
||||
bitmap_and(riscv_isa, riscv_isa, isainfo->isa, RISCV_ISA_EXT_MAX);
|
||||
|
||||
riscv_fill_vendor_ext_list(cpu);
|
||||
}
|
||||
|
||||
if (bitmap_empty(riscv_isa, RISCV_ISA_EXT_MAX))
|
||||
@ -918,29 +964,46 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
|
||||
{
|
||||
struct alt_entry *alt;
|
||||
void *oldptr, *altptr;
|
||||
u16 id, value;
|
||||
u16 id, value, vendor;
|
||||
|
||||
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
|
||||
return;
|
||||
|
||||
for (alt = begin; alt < end; alt++) {
|
||||
if (alt->vendor_id != 0)
|
||||
continue;
|
||||
|
||||
id = PATCH_ID_CPUFEATURE_ID(alt->patch_id);
|
||||
vendor = PATCH_ID_CPUFEATURE_ID(alt->vendor_id);
|
||||
|
||||
if (id >= RISCV_ISA_EXT_MAX) {
|
||||
/*
|
||||
* Any alternative with a patch_id that is less than
|
||||
* RISCV_ISA_EXT_MAX is interpreted as a standard extension.
|
||||
*
|
||||
* Any alternative with patch_id that is greater than or equal
|
||||
* to RISCV_VENDOR_EXT_ALTERNATIVES_BASE is interpreted as a
|
||||
* vendor extension.
|
||||
*/
|
||||
if (id < RISCV_ISA_EXT_MAX) {
|
||||
/*
|
||||
* This patch should be treated as errata so skip
|
||||
* processing here.
|
||||
*/
|
||||
if (alt->vendor_id != 0)
|
||||
continue;
|
||||
|
||||
if (!__riscv_isa_extension_available(NULL, id))
|
||||
continue;
|
||||
|
||||
value = PATCH_ID_CPUFEATURE_VALUE(alt->patch_id);
|
||||
if (!riscv_cpufeature_patch_check(id, value))
|
||||
continue;
|
||||
} else if (id >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE) {
|
||||
if (!__riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor,
|
||||
id - RISCV_VENDOR_EXT_ALTERNATIVES_BASE))
|
||||
continue;
|
||||
} else {
|
||||
WARN(1, "This extension id:%d is not in ISA extension list", id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!__riscv_isa_extension_available(NULL, id))
|
||||
continue;
|
||||
|
||||
value = PATCH_ID_CPUFEATURE_VALUE(alt->patch_id);
|
||||
if (!riscv_cpufeature_patch_check(id, value))
|
||||
continue;
|
||||
|
||||
oldptr = ALT_OLD_PTR(alt);
|
||||
altptr = ALT_ALT_PTR(alt);
|
||||
|
||||
|
@ -88,7 +88,6 @@ SYM_CODE_START(handle_exception)
|
||||
call riscv_v_context_nesting_start
|
||||
#endif
|
||||
move a0, sp /* pt_regs */
|
||||
la ra, ret_from_exception
|
||||
|
||||
/*
|
||||
* MSB of cause differentiates between
|
||||
@ -97,7 +96,8 @@ SYM_CODE_START(handle_exception)
|
||||
bge s4, zero, 1f
|
||||
|
||||
/* Handle interrupts */
|
||||
tail do_irq
|
||||
call do_irq
|
||||
j ret_from_exception
|
||||
1:
|
||||
/* Handle other exceptions */
|
||||
slli t0, s4, RISCV_LGPTR
|
||||
@ -105,11 +105,14 @@ SYM_CODE_START(handle_exception)
|
||||
la t2, excp_vect_table_end
|
||||
add t0, t1, t0
|
||||
/* Check if exception code lies within bounds */
|
||||
bgeu t0, t2, 1f
|
||||
REG_L t0, 0(t0)
|
||||
jr t0
|
||||
1:
|
||||
tail do_trap_unknown
|
||||
bgeu t0, t2, 3f
|
||||
REG_L t1, 0(t0)
|
||||
2: jalr t1
|
||||
j ret_from_exception
|
||||
3:
|
||||
|
||||
la t1, do_trap_unknown
|
||||
j 2b
|
||||
SYM_CODE_END(handle_exception)
|
||||
ASM_NOKPROBE(handle_exception)
|
||||
|
||||
@ -130,6 +133,10 @@ SYM_CODE_START_NOALIGN(ret_from_exception)
|
||||
#endif
|
||||
bnez s0, 1f
|
||||
|
||||
#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
|
||||
call stackleak_erase_on_task_stack
|
||||
#endif
|
||||
|
||||
/* Save unwound kernel stack pointer in thread_info */
|
||||
addi s0, sp, PT_SIZE_ON_STACK
|
||||
REG_S s0, TASK_TI_KERNEL_SP(tp)
|
||||
|
@ -1,7 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o simulate-insn.o
|
||||
obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o
|
||||
obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o
|
||||
obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o simulate-insn.o
|
||||
CFLAGS_REMOVE_simulate-insn.o = $(CC_FLAGS_FTRACE)
|
||||
CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE)
|
||||
|
@ -1,65 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
/* Ftrace callback handler for kprobes -- called under preepmt disabled */
|
||||
void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *ops, struct ftrace_regs *fregs)
|
||||
{
|
||||
struct kprobe *p;
|
||||
struct pt_regs *regs;
|
||||
struct kprobe_ctlblk *kcb;
|
||||
int bit;
|
||||
|
||||
if (unlikely(kprobe_ftrace_disabled))
|
||||
return;
|
||||
|
||||
bit = ftrace_test_recursion_trylock(ip, parent_ip);
|
||||
if (bit < 0)
|
||||
return;
|
||||
|
||||
p = get_kprobe((kprobe_opcode_t *)ip);
|
||||
if (unlikely(!p) || kprobe_disabled(p))
|
||||
goto out;
|
||||
|
||||
regs = ftrace_get_regs(fregs);
|
||||
kcb = get_kprobe_ctlblk();
|
||||
if (kprobe_running()) {
|
||||
kprobes_inc_nmissed_count(p);
|
||||
} else {
|
||||
unsigned long orig_ip = instruction_pointer(regs);
|
||||
|
||||
instruction_pointer_set(regs, ip);
|
||||
|
||||
__this_cpu_write(current_kprobe, p);
|
||||
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
|
||||
if (!p->pre_handler || !p->pre_handler(p, regs)) {
|
||||
/*
|
||||
* Emulate singlestep (and also recover regs->pc)
|
||||
* as if there is a nop
|
||||
*/
|
||||
instruction_pointer_set(regs,
|
||||
(unsigned long)p->addr + MCOUNT_INSN_SIZE);
|
||||
if (unlikely(p->post_handler)) {
|
||||
kcb->kprobe_status = KPROBE_HIT_SSDONE;
|
||||
p->post_handler(p, regs, 0);
|
||||
}
|
||||
instruction_pointer_set(regs, orig_ip);
|
||||
}
|
||||
|
||||
/*
|
||||
* If pre_handler returns !0, it changes regs->pc. We have to
|
||||
* skip emulating post_handler.
|
||||
*/
|
||||
__this_cpu_write(current_kprobe, NULL);
|
||||
}
|
||||
out:
|
||||
ftrace_test_recursion_unlock(bit);
|
||||
}
|
||||
NOKPROBE_SYMBOL(kprobe_ftrace_handler);
|
||||
|
||||
int arch_prepare_kprobe_ftrace(struct kprobe *p)
|
||||
{
|
||||
p->ainsn.api.insn = NULL;
|
||||
return 0;
|
||||
}
|
@ -281,8 +281,10 @@ void __init setup_arch(char **cmdline_p)
|
||||
setup_smp();
|
||||
#endif
|
||||
|
||||
if (!acpi_disabled)
|
||||
if (!acpi_disabled) {
|
||||
acpi_init_rintc_map();
|
||||
acpi_map_cpus_to_nodes();
|
||||
}
|
||||
|
||||
riscv_init_cbo_blocksizes();
|
||||
riscv_fill_hwcap();
|
||||
|
@ -84,7 +84,7 @@ static long save_v_state(struct pt_regs *regs, void __user **sc_vec)
|
||||
datap = state + 1;
|
||||
|
||||
/* datap is designed to be 16 byte aligned for better performance */
|
||||
WARN_ON(unlikely(!IS_ALIGNED((unsigned long)datap, 16)));
|
||||
WARN_ON(!IS_ALIGNED((unsigned long)datap, 16));
|
||||
|
||||
get_cpu_vector_context();
|
||||
riscv_v_vstate_save(¤t->thread.vstate, regs);
|
||||
|
@ -96,7 +96,6 @@ static int __init acpi_parse_rintc(union acpi_subtable_headers *header, const un
|
||||
if (hart == cpuid_to_hartid_map(0)) {
|
||||
BUG_ON(found_boot_cpu);
|
||||
found_boot_cpu = true;
|
||||
early_map_cpu_to_node(0, acpi_numa_get_nid(cpu_count));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -106,7 +105,6 @@ static int __init acpi_parse_rintc(union acpi_subtable_headers *header, const un
|
||||
}
|
||||
|
||||
cpuid_to_hartid_map(cpu_count) = hart;
|
||||
early_map_cpu_to_node(cpu_count, acpi_numa_get_nid(cpu_count));
|
||||
cpu_count++;
|
||||
|
||||
return 0;
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
|
||||
extern asmlinkage void ret_from_exception(void);
|
||||
extern asmlinkage void handle_exception(void);
|
||||
|
||||
static inline int fp_is_valid(unsigned long fp, unsigned long sp)
|
||||
{
|
||||
@ -71,7 +71,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
|
||||
fp = frame->fp;
|
||||
pc = ftrace_graph_ret_addr(current, &graph_idx, frame->ra,
|
||||
&frame->ra);
|
||||
if (pc == (unsigned long)ret_from_exception) {
|
||||
if (pc == (unsigned long)handle_exception) {
|
||||
if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc)))
|
||||
break;
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/hwprobe.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/switch_to.h>
|
||||
#include <asm/uaccess.h>
|
||||
@ -93,44 +94,45 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
|
||||
* regardless of the kernel's configuration, as no other checks, besides
|
||||
* presence in the hart_isa bitmap, are made.
|
||||
*/
|
||||
EXT_KEY(ZACAS);
|
||||
EXT_KEY(ZAWRS);
|
||||
EXT_KEY(ZBA);
|
||||
EXT_KEY(ZBB);
|
||||
EXT_KEY(ZBS);
|
||||
EXT_KEY(ZICBOZ);
|
||||
EXT_KEY(ZBC);
|
||||
|
||||
EXT_KEY(ZBKB);
|
||||
EXT_KEY(ZBKC);
|
||||
EXT_KEY(ZBKX);
|
||||
EXT_KEY(ZBS);
|
||||
EXT_KEY(ZCA);
|
||||
EXT_KEY(ZCB);
|
||||
EXT_KEY(ZCMOP);
|
||||
EXT_KEY(ZICBOZ);
|
||||
EXT_KEY(ZICOND);
|
||||
EXT_KEY(ZIHINTNTL);
|
||||
EXT_KEY(ZIHINTPAUSE);
|
||||
EXT_KEY(ZIMOP);
|
||||
EXT_KEY(ZKND);
|
||||
EXT_KEY(ZKNE);
|
||||
EXT_KEY(ZKNH);
|
||||
EXT_KEY(ZKSED);
|
||||
EXT_KEY(ZKSH);
|
||||
EXT_KEY(ZKT);
|
||||
EXT_KEY(ZIHINTNTL);
|
||||
EXT_KEY(ZTSO);
|
||||
EXT_KEY(ZACAS);
|
||||
EXT_KEY(ZICOND);
|
||||
EXT_KEY(ZIHINTPAUSE);
|
||||
EXT_KEY(ZIMOP);
|
||||
EXT_KEY(ZCA);
|
||||
EXT_KEY(ZCB);
|
||||
EXT_KEY(ZCMOP);
|
||||
EXT_KEY(ZAWRS);
|
||||
|
||||
/*
|
||||
* All the following extensions must depend on the kernel
|
||||
* support of V.
|
||||
*/
|
||||
if (has_vector()) {
|
||||
EXT_KEY(ZVE32X);
|
||||
EXT_KEY(ZVE32F);
|
||||
EXT_KEY(ZVE64X);
|
||||
EXT_KEY(ZVE64F);
|
||||
EXT_KEY(ZVE64D);
|
||||
EXT_KEY(ZVBB);
|
||||
EXT_KEY(ZVBC);
|
||||
EXT_KEY(ZVE32F);
|
||||
EXT_KEY(ZVE32X);
|
||||
EXT_KEY(ZVE64D);
|
||||
EXT_KEY(ZVE64F);
|
||||
EXT_KEY(ZVE64X);
|
||||
EXT_KEY(ZVFH);
|
||||
EXT_KEY(ZVFHMIN);
|
||||
EXT_KEY(ZVKB);
|
||||
EXT_KEY(ZVKG);
|
||||
EXT_KEY(ZVKNED);
|
||||
@ -139,16 +141,14 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
|
||||
EXT_KEY(ZVKSED);
|
||||
EXT_KEY(ZVKSH);
|
||||
EXT_KEY(ZVKT);
|
||||
EXT_KEY(ZVFH);
|
||||
EXT_KEY(ZVFHMIN);
|
||||
}
|
||||
|
||||
if (has_fpu()) {
|
||||
EXT_KEY(ZFH);
|
||||
EXT_KEY(ZFHMIN);
|
||||
EXT_KEY(ZFA);
|
||||
EXT_KEY(ZCD);
|
||||
EXT_KEY(ZCF);
|
||||
EXT_KEY(ZFA);
|
||||
EXT_KEY(ZFH);
|
||||
EXT_KEY(ZFHMIN);
|
||||
}
|
||||
#undef EXT_KEY
|
||||
}
|
||||
@ -237,6 +237,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
|
||||
pair->value = user_max_virt_addr();
|
||||
break;
|
||||
|
||||
case RISCV_HWPROBE_KEY_TIME_CSR_FREQ:
|
||||
pair->value = riscv_timebase;
|
||||
break;
|
||||
|
||||
/*
|
||||
* For forward compatibility, unknown keys don't fail the whole
|
||||
* call, but get their element key set to -1 and value set to 0
|
||||
|
56
arch/riscv/kernel/vendor_extensions.c
Normal file
56
arch/riscv/kernel/vendor_extensions.c
Normal file
@ -0,0 +1,56 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright 2024 Rivos, Inc
|
||||
*/
|
||||
|
||||
#include <asm/vendorid_list.h>
|
||||
#include <asm/vendor_extensions.h>
|
||||
#include <asm/vendor_extensions/andes.h>
|
||||
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct riscv_isa_vendor_ext_data_list *riscv_isa_vendor_ext_list[] = {
|
||||
#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_ANDES
|
||||
&riscv_isa_vendor_ext_list_andes,
|
||||
#endif
|
||||
};
|
||||
|
||||
const size_t riscv_isa_vendor_ext_list_size = ARRAY_SIZE(riscv_isa_vendor_ext_list);
|
||||
|
||||
/**
|
||||
* __riscv_isa_vendor_extension_available() - Check whether given vendor
|
||||
* extension is available or not.
|
||||
*
|
||||
* @cpu: check if extension is available on this cpu
|
||||
* @vendor: vendor that the extension is a member of
|
||||
* @bit: bit position of the desired extension
|
||||
* Return: true or false
|
||||
*
|
||||
* NOTE: When cpu is -1, will check if extension is available on all cpus
|
||||
*/
|
||||
bool __riscv_isa_vendor_extension_available(int cpu, unsigned long vendor, unsigned int bit)
|
||||
{
|
||||
struct riscv_isavendorinfo *bmap;
|
||||
struct riscv_isavendorinfo *cpu_bmap;
|
||||
|
||||
switch (vendor) {
|
||||
#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_ANDES
|
||||
case ANDES_VENDOR_ID:
|
||||
bmap = &riscv_isa_vendor_ext_list_andes.all_harts_isa_bitmap;
|
||||
cpu_bmap = &riscv_isa_vendor_ext_list_andes.per_hart_isa_bitmap[cpu];
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cpu != -1)
|
||||
bmap = &cpu_bmap[cpu];
|
||||
|
||||
if (bit >= RISCV_ISA_VENDOR_EXT_MAX)
|
||||
return false;
|
||||
|
||||
return test_bit(bit, bmap->isa) ? true : false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__riscv_isa_vendor_extension_available);
|
3
arch/riscv/kernel/vendor_extensions/Makefile
Normal file
3
arch/riscv/kernel/vendor_extensions/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_RISCV_ISA_VENDOR_EXT_ANDES) += andes.o
|
18
arch/riscv/kernel/vendor_extensions/andes.c
Normal file
18
arch/riscv/kernel/vendor_extensions/andes.c
Normal file
@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/vendor_extensions.h>
|
||||
#include <asm/vendor_extensions/andes.h>
|
||||
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* All Andes vendor extensions supported in Linux */
|
||||
const struct riscv_isa_ext_data riscv_isa_vendor_ext_andes[] = {
|
||||
__RISCV_ISA_EXT_DATA(xandespmu, RISCV_ISA_VENDOR_EXT_XANDESPMU),
|
||||
};
|
||||
|
||||
struct riscv_isa_vendor_ext_data_list riscv_isa_vendor_ext_list_andes = {
|
||||
.ext_data_count = ARRAY_SIZE(riscv_isa_vendor_ext_andes),
|
||||
.ext_data = riscv_isa_vendor_ext_andes,
|
||||
};
|
@ -1,9 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
config ACPI_NUMA
|
||||
bool "NUMA support"
|
||||
depends on NUMA
|
||||
depends on (X86 || ARM64 || LOONGARCH)
|
||||
default y if ARM64
|
||||
def_bool NUMA && !X86
|
||||
|
||||
config ACPI_HMAT
|
||||
bool "ACPI Heterogeneous Memory Attribute Table Support"
|
||||
|
@ -167,6 +167,19 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_SRAT_TYPE_RINTC_AFFINITY:
|
||||
{
|
||||
struct acpi_srat_rintc_affinity *p =
|
||||
(struct acpi_srat_rintc_affinity *)header;
|
||||
pr_debug("SRAT Processor (acpi id[0x%04x]) in proximity domain %d %s\n",
|
||||
p->acpi_processor_uid,
|
||||
p->proximity_domain,
|
||||
(p->flags & ACPI_SRAT_RINTC_ENABLED) ?
|
||||
"enabled" : "disabled");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_warn("Found unsupported SRAT entry (type = 0x%x)\n",
|
||||
header->type);
|
||||
@ -450,6 +463,21 @@ acpi_parse_gi_affinity(union acpi_subtable_headers *header,
|
||||
}
|
||||
#endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */
|
||||
|
||||
static int __init
|
||||
acpi_parse_rintc_affinity(union acpi_subtable_headers *header,
|
||||
const unsigned long end)
|
||||
{
|
||||
struct acpi_srat_rintc_affinity *rintc_affinity;
|
||||
|
||||
rintc_affinity = (struct acpi_srat_rintc_affinity *)header;
|
||||
acpi_table_print_srat_entry(&header->common);
|
||||
|
||||
/* let architecture-dependent part to do it */
|
||||
acpi_numa_rintc_affinity_init(rintc_affinity);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init acpi_parse_srat(struct acpi_table_header *table)
|
||||
{
|
||||
struct acpi_table_srat *srat = (struct acpi_table_srat *)table;
|
||||
@ -485,7 +513,7 @@ int __init acpi_numa_init(void)
|
||||
|
||||
/* SRAT: System Resource Affinity Table */
|
||||
if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
|
||||
struct acpi_subtable_proc srat_proc[4];
|
||||
struct acpi_subtable_proc srat_proc[5];
|
||||
|
||||
memset(srat_proc, 0, sizeof(srat_proc));
|
||||
srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
|
||||
@ -496,6 +524,8 @@ int __init acpi_numa_init(void)
|
||||
srat_proc[2].handler = acpi_parse_gicc_affinity;
|
||||
srat_proc[3].id = ACPI_SRAT_TYPE_GENERIC_AFFINITY;
|
||||
srat_proc[3].handler = acpi_parse_gi_affinity;
|
||||
srat_proc[4].id = ACPI_SRAT_TYPE_RINTC_AFFINITY;
|
||||
srat_proc[4].handler = acpi_parse_rintc_affinity;
|
||||
|
||||
acpi_table_parse_entries_array(ACPI_SIG_SRAT,
|
||||
sizeof(struct acpi_table_srat),
|
||||
|
@ -445,7 +445,7 @@ static int __init arch_acpi_numa_init(void)
|
||||
|
||||
ret = acpi_numa_init();
|
||||
if (ret) {
|
||||
pr_info("Failed to initialise from firmware\n");
|
||||
pr_debug("Failed to initialise from firmware\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,8 @@ cflags-$(CONFIG_ARM) += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \
|
||||
-DEFI_HAVE_MEMCHR -DEFI_HAVE_STRRCHR \
|
||||
-DEFI_HAVE_STRCMP -fno-builtin -fpic \
|
||||
$(call cc-option,-mno-single-pic-base)
|
||||
cflags-$(CONFIG_RISCV) += -fpic -DNO_ALTERNATIVE -mno-relax
|
||||
cflags-$(CONFIG_RISCV) += -fpic -DNO_ALTERNATIVE -mno-relax \
|
||||
$(DISABLE_STACKLEAK_PLUGIN)
|
||||
cflags-$(CONFIG_LOONGARCH) += -fpie
|
||||
|
||||
cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <asm/errata_list.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/vendor_extensions.h>
|
||||
#include <asm/vendor_extensions/andes.h>
|
||||
|
||||
#define ALT_SBI_PMU_OVERFLOW(__ovl) \
|
||||
asm volatile(ALTERNATIVE_2( \
|
||||
@ -33,7 +35,8 @@ asm volatile(ALTERNATIVE_2( \
|
||||
THEAD_VENDOR_ID, ERRATA_THEAD_PMU, \
|
||||
CONFIG_ERRATA_THEAD_PMU, \
|
||||
"csrr %0, " __stringify(ANDES_CSR_SCOUNTEROF), \
|
||||
0, RISCV_ISA_EXT_XANDESPMU, \
|
||||
ANDES_VENDOR_ID, \
|
||||
RISCV_ISA_VENDOR_EXT_XANDESPMU + RISCV_VENDOR_EXT_ALTERNATIVES_BASE, \
|
||||
CONFIG_ANDES_CUSTOM_PMU) \
|
||||
: "=r" (__ovl) : \
|
||||
: "memory")
|
||||
@ -42,7 +45,8 @@ asm volatile(ALTERNATIVE_2( \
|
||||
asm volatile(ALTERNATIVE( \
|
||||
"csrc " __stringify(CSR_IP) ", %0\n\t", \
|
||||
"csrc " __stringify(ANDES_CSR_SLIP) ", %0\n\t", \
|
||||
0, RISCV_ISA_EXT_XANDESPMU, \
|
||||
ANDES_VENDOR_ID, \
|
||||
RISCV_ISA_VENDOR_EXT_XANDESPMU + RISCV_VENDOR_EXT_ALTERNATIVES_BASE, \
|
||||
CONFIG_ANDES_CUSTOM_PMU) \
|
||||
: : "r"(__irq_mask) \
|
||||
: "memory")
|
||||
@ -1095,7 +1099,8 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde
|
||||
riscv_cached_mimpid(0) == 0) {
|
||||
riscv_pmu_irq_num = THEAD_C9XX_RV_IRQ_PMU;
|
||||
riscv_pmu_use_irq = true;
|
||||
} else if (riscv_isa_extension_available(NULL, XANDESPMU) &&
|
||||
} else if (riscv_has_vendor_extension_unlikely(ANDES_VENDOR_ID,
|
||||
RISCV_ISA_VENDOR_EXT_XANDESPMU) &&
|
||||
IS_ENABLED(CONFIG_ANDES_CUSTOM_PMU)) {
|
||||
riscv_pmu_irq_num = ANDES_SLI_CAUSE_BASE + ANDES_RV_IRQ_PMOVI;
|
||||
riscv_pmu_use_irq = true;
|
||||
|
@ -259,6 +259,12 @@ static inline void
|
||||
acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RISCV
|
||||
void acpi_numa_rintc_affinity_init(struct acpi_srat_rintc_affinity *pa);
|
||||
#else
|
||||
static inline void acpi_numa_rintc_affinity_init(struct acpi_srat_rintc_affinity *pa) { }
|
||||
#endif
|
||||
|
||||
#ifndef PHYS_CPUID_INVALID
|
||||
typedef u32 phys_cpuid_t;
|
||||
#define PHYS_CPUID_INVALID (phys_cpuid_t)(-1)
|
||||
|
Loading…
Reference in New Issue
Block a user