From d8d0fb556e53d2c54967e1d1c227747f66a3aaad Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Fri, 7 Aug 2026 19:24:29 -0600 Subject: [PATCH 01/39] riscv: efi: Power off via EFI runtime services when available When booted via UEFI with runtime services enabled, EFI Reset Shutdown is the firmware-preferred shutdown path: it lets firmware run its own shutdown hooks which may invoke SBI SRST extension internally. However, RISC-V always powers off via the SBI SRST extension today and EFI runtime path is never used even when firmware provides it. Enable the poweroff via EFI by overriding efi_poweroff_required() Signed-off-by: Atish Patra Reviewed-by: Sunil V L Link: https://patch.msgid.link/20260615-efi_reset_shutdown-v1-1-9414edcbbab0@meta.com Signed-off-by: Paul Walmsley --- arch/riscv/kernel/efi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/riscv/kernel/efi.c b/arch/riscv/kernel/efi.c index b64bf1624a05..2d3cc57b4535 100644 --- a/arch/riscv/kernel/efi.c +++ b/arch/riscv/kernel/efi.c @@ -95,3 +95,8 @@ int __init efi_set_mapping_permissions(struct mm_struct *mm, md->num_pages << EFI_PAGE_SHIFT, set_permissions, md); } + +bool efi_poweroff_required(void) +{ + return efi_enabled(EFI_RUNTIME_SERVICES); +} From c888e324b24941c1a377a7c4ee030ac789cda035 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Fri, 7 Aug 2026 19:24:29 -0600 Subject: [PATCH 02/39] riscv: Restart via EFI runtime services when available Firmware-preferred reset and EFI capsule update support requires reset via EFI runtime services rather than direction M-mode firmware invocation via SBI. Unlike poweroff, restart mechanism is directly controlled from machine_restart function though. Prefer the EFI runtime ResetSystem() service for restart when UEFI runtime services are available. Signed-off-by: Atish Patra Reviewed-by: Sunil V L Link: https://patch.msgid.link/20260615-efi_reset_shutdown-v1-2-9414edcbbab0@meta.com Signed-off-by: Paul Walmsley --- arch/riscv/kernel/reset.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/riscv/kernel/reset.c b/arch/riscv/kernel/reset.c index 912288572226..541e2162c85a 100644 --- a/arch/riscv/kernel/reset.c +++ b/arch/riscv/kernel/reset.c @@ -3,6 +3,7 @@ * Copyright (C) 2012 Regents of the University of California */ +#include #include #include @@ -17,6 +18,12 @@ EXPORT_SYMBOL(pm_power_off); void machine_restart(char *cmd) { + /* + * UpdateCapsule() depends on the system being reset via ResetSystem(). + */ + if (efi_enabled(EFI_RUNTIME_SERVICES)) + efi_reboot(reboot_mode, NULL); + do_kernel_restart(cmd); while (1); } From d3436d33341b774ebe842d87ae39a9c7944757dc Mon Sep 17 00:00:00 2001 From: Vivian Wang Date: Fri, 7 Aug 2026 19:24:29 -0600 Subject: [PATCH 03/39] ACPI: tables: Add missing #include drivers/acpi/tables.c uses NR_FIX_BTMAPS without including . This isn't a problem for existing archs, but would be when ARCH_HAS_ACPI_TABLE_UPGRADE is enabled for RISC-V. Add the missing include. Signed-off-by: Vivian Wang Link: https://patch.msgid.link/20260616-riscv-acpi-table-upgrade-v1-1-45902d2dedf9@iscas.ac.cn Signed-off-by: Paul Walmsley --- drivers/acpi/tables.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 4286e4af1092..eb93c060426f 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "internal.h" #ifdef CONFIG_ACPI_CUSTOM_DSDT From 6a48dea3449c220b1c607ecdad4d1cd18eac9b78 Mon Sep 17 00:00:00 2001 From: Vivian Wang Date: Fri, 7 Aug 2026 19:24:29 -0600 Subject: [PATCH 04/39] riscv: acpi: Enable ARCH_HAS_ACPI_TABLE_UPGRADE Implement the various required hooks and enable ARCH_HAS_ACPI_TABLE_UPGRADE to allow use for ACPI_TABLE_UPGRADE, which is useful for debugging ACPI table problems. The implementation is based on arm64's of the same feature due to the similarities of the requirements of the two platforms. Signed-off-by: Vivian Wang Link: https://patch.msgid.link/20260616-riscv-acpi-table-upgrade-v1-2-45902d2dedf9@iscas.ac.cn [pjw@kernel.org: updated to apply] Signed-off-by: Paul Walmsley --- arch/riscv/Kconfig | 1 + arch/riscv/include/asm/acpi.h | 2 ++ arch/riscv/kernel/acpi.c | 5 +++++ arch/riscv/kernel/setup.c | 2 ++ 4 files changed, 10 insertions(+) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index f7028caaeae0..c2c2f5f3ed5e 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -23,6 +23,7 @@ config RISCV select ARCH_ENABLE_MEMORY_HOTPLUG if SPARSEMEM_VMEMMAP select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2 select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE + select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI select ARCH_HAS_BINFMT_FLAT select ARCH_HAS_CC_CAN_LINK select ARCH_HAS_CURRENT_STACK_POINTER diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h index 26ab37c171bc..d59bd06347cc 100644 --- a/arch/riscv/include/asm/acpi.h +++ b/arch/riscv/include/asm/acpi.h @@ -92,4 +92,6 @@ void acpi_map_cpus_to_nodes(void); static inline void acpi_map_cpus_to_nodes(void) { } #endif /* CONFIG_ACPI_NUMA */ +#define ACPI_TABLE_UPGRADE_MAX_PHYS MEMBLOCK_ALLOC_ACCESSIBLE + #endif /*_ASM_ACPI_H*/ diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c index 068e0b404b6f..efd52a5d05b5 100644 --- a/arch/riscv/kernel/acpi.c +++ b/arch/riscv/kernel/acpi.c @@ -353,3 +353,8 @@ int acpi_get_cpu_uid(unsigned int cpu, u32 *uid) return 0; } EXPORT_SYMBOL_GPL(acpi_get_cpu_uid); + +void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size) +{ + memblock_mark_nomap(addr, size); +} diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 52d1d2b8f338..a32344bb220d 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -321,6 +321,8 @@ void __init setup_arch(char **cmdline_p) efi_init(); paging_init(); + acpi_table_upgrade(); + /* Parse the ACPI tables for possible boot-time configuration */ acpi_boot_table_init(); From 540ad5ad05a5945575b154caedfcdc08ed75b810 Mon Sep 17 00:00:00 2001 From: Xiaofeng Yuan Date: Fri, 7 Aug 2026 19:24:29 -0600 Subject: [PATCH 05/39] riscv: probes: simulate c.jal instruction The c.jal instruction is currently marked REJECTED in kprobes instruction decoding, but it should be SIMULATED like other compressed jump instructions. Add simulate_c_jal() which saves the return address to RA and sets the program counter to the target offset, reusing simulate_c_j for the common jump logic. Although c.jal is RV32-only, the function compiles unconditionally. On RV64, riscv_insn_is_c_jal() always returns 0, so the simulation code is never invoked and the small overhead in kernel size is acceptable. Signed-off-by: Xiaofeng Yuan Reviewed-by: Charlie Jenkins Tested-by: Charlie Jenkins Reviewed-by: Nam Cao Tested-by: Nam Cao Link: https://patch.msgid.link/20260701081033.49871-2-xiaofengmian@163.com Signed-off-by: Paul Walmsley --- arch/riscv/kernel/probes/decode-insn.c | 2 +- arch/riscv/kernel/probes/simulate-insn.c | 7 +++++++ arch/riscv/kernel/probes/simulate-insn.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c index 65d9590bfb9f..433d9035b888 100644 --- a/arch/riscv/kernel/probes/decode-insn.c +++ b/arch/riscv/kernel/probes/decode-insn.c @@ -29,12 +29,12 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api) * TODO: the REJECTED ones below need to be implemented */ #ifdef CONFIG_RISCV_ISA_C - RISCV_INSN_REJECTED(c_jal, insn); RISCV_INSN_REJECTED(c_ebreak, insn); RISCV_INSN_SET_SIMULATE(c_j, insn); RISCV_INSN_SET_SIMULATE(c_jr, insn); RISCV_INSN_SET_SIMULATE(c_jalr, insn); + RISCV_INSN_SET_SIMULATE(c_jal, insn); RISCV_INSN_SET_SIMULATE(c_beqz, insn); RISCV_INSN_SET_SIMULATE(c_bnez, insn); #endif diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c index fa581590c1f8..f8a2f6857877 100644 --- a/arch/riscv/kernel/probes/simulate-insn.c +++ b/arch/riscv/kernel/probes/simulate-insn.c @@ -163,6 +163,13 @@ bool __kprobes simulate_c_j(u32 opcode, unsigned long addr, struct pt_regs *regs return true; } +bool __kprobes simulate_c_jal(u32 opcode, unsigned long addr, struct pt_regs *regs) +{ + regs->ra = addr + 2; + + return simulate_c_j(opcode, addr, regs); +} + static bool __kprobes simulate_c_jr_jalr(u32 opcode, unsigned long addr, struct pt_regs *regs, bool is_jalr) { diff --git a/arch/riscv/kernel/probes/simulate-insn.h b/arch/riscv/kernel/probes/simulate-insn.h index 44ebbc444db9..b89e1bb01842 100644 --- a/arch/riscv/kernel/probes/simulate-insn.h +++ b/arch/riscv/kernel/probes/simulate-insn.h @@ -25,6 +25,7 @@ bool simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs); bool simulate_jal(u32 opcode, unsigned long addr, struct pt_regs *regs); bool simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *regs); bool simulate_c_j(u32 opcode, unsigned long addr, struct pt_regs *regs); +bool simulate_c_jal(u32 opcode, unsigned long addr, struct pt_regs *regs); bool simulate_c_jr(u32 opcode, unsigned long addr, struct pt_regs *regs); bool simulate_c_jalr(u32 opcode, unsigned long addr, struct pt_regs *regs); bool simulate_c_bnez(u32 opcode, unsigned long addr, struct pt_regs *regs); From 0d4a777c4cdaf6d55aa337a3c9fb825fd03fd371 Mon Sep 17 00:00:00 2001 From: Nam Cao Date: Fri, 7 Aug 2026 19:24:29 -0600 Subject: [PATCH 06/39] riscv: kprobes: add test case for c.jal instruction simulation Add a test case validating that kprobes correctly simulates the c.jal instruction on RV32. The test uses two probe points: a forward c.jal and a backward c.jal, and verifies that the containing function returns the expected magic value KPROBE_TEST_MAGIC after kprobe interception. Co-developed-by: Xiaofeng Yuan Signed-off-by: Nam Cao Signed-off-by: Xiaofeng Yuan Reviewed-by: Charlie Jenkins Tested-by: Charlie Jenkins Link: https://patch.msgid.link/20260701081033.49871-3-xiaofengmian@163.com Signed-off-by: Paul Walmsley --- .../kernel/tests/kprobes/test-kprobes-asm.S | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S b/arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S index f16deee9e091..15e50934bbd7 100644 --- a/arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S +++ b/arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S @@ -179,6 +179,23 @@ test_kprobes_c_bnez_addr3: ret SYM_FUNC_END(test_kprobes_c_bnez) +#ifdef CONFIG_32BIT +SYM_FUNC_START(test_kprobes_c_jal) + li a0, 0 + mv a1, ra +test_kprobes_c_jal_addr1: + c.jal 2f + ret +1: li a0, KPROBE_TEST_MAGIC_UPPER + ret +test_kprobes_c_jal_addr2: +2: c.jal 1b + li a2, KPROBE_TEST_MAGIC_LOWER + add a0, a0, a2 + jr a1 +SYM_FUNC_END(test_kprobes_c_jal) +#endif + #endif /* CONFIG_RISCV_ISA_C */ .section .rodata @@ -209,6 +226,10 @@ SYM_DATA_START(test_kprobes_addresses) RISCV_PTR test_kprobes_c_bnez_addr1 RISCV_PTR test_kprobes_c_bnez_addr2 RISCV_PTR test_kprobes_c_bnez_addr3 +#ifdef CONFIG_32BIT + RISCV_PTR test_kprobes_c_jal_addr1 + RISCV_PTR test_kprobes_c_jal_addr2 +#endif #endif /* CONFIG_RISCV_ISA_C */ RISCV_PTR 0 SYM_DATA_END(test_kprobes_addresses) @@ -226,6 +247,9 @@ SYM_DATA_START(test_kprobes_functions) RISCV_PTR test_kprobes_c_jalr RISCV_PTR test_kprobes_c_beqz RISCV_PTR test_kprobes_c_bnez +#ifdef CONFIG_32BIT + RISCV_PTR test_kprobes_c_jal +#endif #endif /* CONFIG_RISCV_ISA_C */ RISCV_PTR 0 SYM_DATA_END(test_kprobes_functions) From af842aea58d86e8c5b471821f18282c6b7747881 Mon Sep 17 00:00:00 2001 From: Xu Lu Date: Fri, 7 Aug 2026 19:24:29 -0600 Subject: [PATCH 07/39] riscv: mm: Use ASID in update_mmu_cache() Only flush TLB entries for the specified mm in update_mmu_cache_range(). Signed-off-by: Xu Lu Link: https://patch.msgid.link/20260715132009.10634-2-luxu.kernel@bytedance.com Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/pgtable.h | 4 +++- arch/riscv/include/asm/tlbflush.h | 5 +++++ arch/riscv/mm/tlbflush.c | 5 ----- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 5d5756bda82e..9926556099ae 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma, unsigned long address, pte_t *ptep, unsigned int nr) { + unsigned long asid = get_mm_asid(vma->vm_mm); + /* * Svvptc guarantees that the new valid pte will be visible within * a bounded timeframe, so when the uarch does not cache invalid @@ -584,7 +586,7 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf, * the extra traps reduce performance. So, eagerly SFENCE.VMA. */ while (nr--) - local_flush_tlb_page(address + nr * PAGE_SIZE); + local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid); } #define update_mmu_cache(vma, addr, ptep) \ diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h index eed0abc40514..7c2cd5cc92d3 100644 --- a/arch/riscv/include/asm/tlbflush.h +++ b/arch/riscv/include/asm/tlbflush.h @@ -15,6 +15,11 @@ #define FLUSH_TLB_NO_ASID ((unsigned long)-1) #ifdef CONFIG_MMU +static inline unsigned long get_mm_asid(struct mm_struct *mm) +{ + return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID; +} + static inline void local_flush_tlb_all(void) { __asm__ __volatile__ ("sfence.vma" : : : "memory"); diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c index 8404530ec00f..73c226f719c7 100644 --- a/arch/riscv/mm/tlbflush.c +++ b/arch/riscv/mm/tlbflush.c @@ -110,11 +110,6 @@ static void __ipi_flush_tlb_range_asid(void *info) local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid); } -static inline unsigned long get_mm_asid(struct mm_struct *mm) -{ - return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID; -} - static void __flush_tlb_range(struct mm_struct *mm, const struct cpumask *cmask, unsigned long start, unsigned long size, From 905be00304bd3658fb0ce2914ed7a95ee799e0f3 Mon Sep 17 00:00:00 2001 From: Xu Lu Date: Fri, 7 Aug 2026 19:24:29 -0600 Subject: [PATCH 08/39] riscv: mm: Apply Svinval in update_mmu_cache() Use Svinval in update_mmu_cache_range() when the extension is available. Signed-off-by: Xu Lu Link: https://patch.msgid.link/20260715132009.10634-3-luxu.kernel@bytedance.com Tested-by: Klara Modin Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/pgtable.h | 8 ++++++++ arch/riscv/include/asm/tlbflush.h | 18 ++++++++++++++++++ arch/riscv/mm/tlbflush.c | 18 ------------------ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 9926556099ae..823805cc465a 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -578,6 +578,14 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf, if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC)) return; + if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)) { + local_sfence_w_inval(); + while (nr--) + local_sinval_vma(address + nr * PAGE_SIZE, asid); + local_sfence_inval_ir(); + return; + } + /* * The kernel assumes that TLBs don't cache invalid entries, but * in RISC-V, SFENCE.VMA specifies an ordering constraint, not a diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h index 7c2cd5cc92d3..9636d07fe9ee 100644 --- a/arch/riscv/include/asm/tlbflush.h +++ b/arch/riscv/include/asm/tlbflush.h @@ -20,6 +20,24 @@ static inline unsigned long get_mm_asid(struct mm_struct *mm) return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID; } +static inline void local_sfence_inval_ir(void) +{ + asm volatile(SFENCE_INVAL_IR() ::: "memory"); +} + +static inline void local_sfence_w_inval(void) +{ + asm volatile(SFENCE_W_INVAL() ::: "memory"); +} + +static inline void local_sinval_vma(unsigned long vma, unsigned long asid) +{ + if (asid != FLUSH_TLB_NO_ASID) + asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory"); + else + asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory"); +} + static inline void local_flush_tlb_all(void) { __asm__ __volatile__ ("sfence.vma" : : : "memory"); diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c index 73c226f719c7..962db300a166 100644 --- a/arch/riscv/mm/tlbflush.c +++ b/arch/riscv/mm/tlbflush.c @@ -11,24 +11,6 @@ #define has_svinval() riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL) -static inline void local_sfence_inval_ir(void) -{ - asm volatile(SFENCE_INVAL_IR() ::: "memory"); -} - -static inline void local_sfence_w_inval(void) -{ - asm volatile(SFENCE_W_INVAL() ::: "memory"); -} - -static inline void local_sinval_vma(unsigned long vma, unsigned long asid) -{ - if (asid != FLUSH_TLB_NO_ASID) - asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory"); - else - asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory"); -} - /* * Flush entire TLB if number of entries to be flushed is greater * than the threshold below. From 9cfff2edcc5ef84bdbf91892b7e127a41b9db35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Fri, 7 Aug 2026 19:24:30 -0600 Subject: [PATCH 09/39] riscv: vdso: Simplify cflags remove logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Listing all flags for each object file is tedious and error-prone. Replace it with a simpler solution. Link: https://lore.kernel.org/all/20260630135316-f26f0e0f-c08c-4d4d-9963-10f9985a7689@linutronix.de/ Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20260701-riscv-vdso-lto-v1-2-89db0cd82077@linutronix.de Signed-off-by: Paul Walmsley --- arch/riscv/kernel/vdso/Makefile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile index 43ee881f6c6f..8dbf2532a573 100644 --- a/arch/riscv/kernel/vdso/Makefile +++ b/arch/riscv/kernel/vdso/Makefile @@ -41,6 +41,8 @@ ccflags-y += $(CFI_FULL) asflags-y += $(KBUILD_BASE_ISA)$(CFI_MARCH) asflags-y += $(CFI_FULL) +ccflags-remove-y += $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_LTO) + ifneq ($(c-gettimeofday-y),) CFLAGS_vgettimeofday.o += -fPIC -include $(c-gettimeofday-y) endif @@ -68,11 +70,6 @@ ifneq ($(filter vgettimeofday, $(vdso-syms)),) CPPFLAGS_$(vdso_lds) += -DHAS_VGETTIMEOFDAY endif -# Disable -pg to prevent insert call site -CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_LTO) -CFLAGS_REMOVE_getrandom.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_LTO) -CFLAGS_REMOVE_hwprobe.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_LTO) - # Force dependency $(obj)/$(vdso_o): $(obj)/$(vdso_so) From 2ee1cc0bbd9b8a798d108828a3a749e9683e519c Mon Sep 17 00:00:00 2001 From: Zong Li Date: Fri, 7 Aug 2026 19:24:30 -0600 Subject: [PATCH 10/39] riscv: cfi: reduce shadow stack size limit from 2GB to 512MB Change the shadow stack size calculation from RLIMIT_STACK/2 (capped at 2GB) to RLIMIT_STACK/8 (capped at 512MB), following David Laight's analysis and recommendation. Rationale: David Laight pointed out that the focus should be on the ratio between shadow stack size and the normal stack size, rather than just the absolute upper limit. His analysis showed that while there are many functions with small stack frames, the majority have stack deltas of over 64 bytes due to saved registers and local variables. Shadow stacks only store return addresses (8 bytes per entry on 64-bit systems), whereas normal stack frames typically consume 64+ bytes. This 8:64 byte ratio means that programs using a lot of stack space are dominated by large buffer allocations and local variables, not extreme recursion depths with minimal local data. For example, with the default RLIMIT_STACK of 8MB: - RLIMIT_STACK/2 gives a 4MB shadow stack supporting 512K nested calls - RLIMIT_STACK/8 gives a 1MB shadow stack supporting 128K nested calls Given typical stack frame sizes of 64+ bytes, RLIMIT_STACK/8 is still conservative and provides adequate depth for practical applications. David noted that this could even be safely halved again. This reduction also better accommodates memory-constrained platforms. On systems with limited physical memory, allocating large shadow stacks can cause virtual memory allocation failures when overcommit mode is set to OVERCOMMIT_GUESS or OVERCOMMIT_NEVER. Suggested-by: David Laight Link: https://lore.kernel.org/all/20260518105725.7afe7a4c@pumpkin/ Signed-off-by: Zong Li Link: https://patch.msgid.link/20260522093634.3530233-1-zong.li@sifive.com Signed-off-by: Paul Walmsley --- arch/riscv/kernel/usercfi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/riscv/kernel/usercfi.c b/arch/riscv/kernel/usercfi.c index 5a7113d69bad..f027e6e05251 100644 --- a/arch/riscv/kernel/usercfi.c +++ b/arch/riscv/kernel/usercfi.c @@ -110,7 +110,7 @@ void set_indir_lp_lock(struct task_struct *task, bool lock) } /* * The shadow stack only stores the return address and not any variables - * this should be more than sufficient for most applications. + * 512M should be more than sufficient for most applications. * Else PAGE_ALIGN it and return back */ static unsigned long calc_shstk_size(unsigned long size) @@ -118,7 +118,7 @@ static unsigned long calc_shstk_size(unsigned long size) if (size) return PAGE_ALIGN(size); - return PAGE_ALIGN(min(rlimit(RLIMIT_STACK) / 2, SZ_2G)); + return PAGE_ALIGN(min(rlimit(RLIMIT_STACK) / 8, SZ_512M)); } /* From 627c32d418108bd298e255709d51b9d6db6ef8b9 Mon Sep 17 00:00:00 2001 From: Eder Zulian Date: Fri, 7 Aug 2026 19:24:30 -0600 Subject: [PATCH 11/39] riscv: mm: Move dma_contiguous_reserve() after NUMA initialization Move the dma_contiguous_reserve() call from setup_bootmem() to misc_mem_init(), placing it after arch_numa_init(). This ensures that NUMA topology is initialized when reserving contiguous memory for DMA. Tested with CMA_SIZE_PERNUMA enabled and two NUMA nodes on QEMU: qemu-system-riscv64 \ -machine virt \ -nographic \ -smp 2 -m 512M \ -numa node,nodeid=0,cpus=0,memdev=m0 \ -numa node,nodeid=1,cpus=1,memdev=m1 \ -object memory-backend-ram,id=m0,size=256M \ -object memory-backend-ram,id=m1,size=256M \ -kernel arch/riscv/boot/Image \ -append "console=ttyS0 earlycon loglevel=7 cma=16M" Unpatched kernel's log (one global CMA pool and no per-nodepools, 16 MiB cma-reserved): [ 0.000000] cma: Reserved 16 MiB at 0x000000009ee00000 ... [ 0.000000] Initmem setup node 0 [mem 0x0000000080000000-0x000000008fffffff] [ 0.000000] Initmem setup node 1 [mem 0x0000000090000000-0x000000009fffffff] ... [ 0.056397] smp: Brought up 2 nodes, 2 CPUs [ 0.066135] Memory: 449288K/524288K available (12279K kernel code, 5980K rwdata, 6144K rodata, 2467K init, 482K bss, 54504K reserved, 16384K cma-reserved) Patched kernel's log (three CMA pools are created, 48 MiB total), [ 0.000000] cma: Reserved 16 MiB at 0x000000009ee00000 [ 0.000000] cma: Reserved 16 MiB at 0x000000008ee00000 [ 0.000000] cma: Reserved 16 MiB at 0x000000009de00000 ... [ 0.054251] smp: Brought up 2 nodes, 2 CPUs [ 0.064082] Memory: 416520K/524288K available (12279K kernel code, 5980K rwdata, 6144K rodata, 2467K init, 482K bss, 54504K reserved, 49152K cma-reserved) Signed-off-by: Eder Zulian Link: https://patch.msgid.link/20260714185648.1082483-1-ezulian@redhat.com Signed-off-by: Paul Walmsley --- arch/riscv/mm/init.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 01d252c741d2..25ccee50e6dd 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -305,8 +305,6 @@ static void __init setup_bootmem(void) */ if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); - - dma_contiguous_reserve(dma32_phys_limit); } #ifdef CONFIG_RELOCATABLE @@ -1360,6 +1358,7 @@ void __init misc_mem_init(void) { early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT); arch_numa_init(); + dma_contiguous_reserve(dma32_phys_limit); #ifdef CONFIG_SPARSEMEM_VMEMMAP /* The entire VMEMMAP region has been populated. Flush TLB for this region */ local_flush_tlb_kernel_range(VMEMMAP_START, VMEMMAP_END); From 9e29ec46f736c485eddd2e8a4d774f131964ba47 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Fri, 7 Aug 2026 19:24:30 -0600 Subject: [PATCH 12/39] riscv: Mark default_power_off() as __noreturn Since default_power_off() never returns, annotate it with the __noreturn attribute to improve compiler optimizations. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20260727100339.410466-2-thorsten.blum@linux.dev Signed-off-by: Paul Walmsley --- arch/riscv/kernel/reset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/kernel/reset.c b/arch/riscv/kernel/reset.c index 541e2162c85a..14eb08a6db85 100644 --- a/arch/riscv/kernel/reset.c +++ b/arch/riscv/kernel/reset.c @@ -7,7 +7,7 @@ #include #include -static void default_power_off(void) +static void __noreturn default_power_off(void) { while (1) wait_for_interrupt(); From 34c9cfcde29b938c416924ee6ec3519270bc2238 Mon Sep 17 00:00:00 2001 From: Nam Cao Date: Fri, 7 Aug 2026 19:24:30 -0600 Subject: [PATCH 13/39] riscv: unaligned: stop using kthread for check_vector_unaligned_access() A kthread is used to run check_vector_unaligned_access() to optimize boot time, allowing the kernel to continue booting without waiting for the unaligned vector speed probe to finish. However, this asynchronous approach introduces several complications. First, the kthread may not complete before a user reads vDSO data, resulting in incorrect values. This was previously addressed by commit 5d15d2ad36b0 ("riscv: hwprobe: Fix stale vDSO data for late-initialized keys at boot"), which added complex synchronization between the kthread and vDSO reads. Second, it was discovered that the kthread may not finish before vec_check_unaligned_access_speed_all_cpus() (marked with __init) is freed, triggering a page fault. These issues raise the question of whether the kthread is worth the added complexity. A past boot time regression report was actually unrelated to synchronous probing; it was caused by the probe running serially. Since switching to a parallel probe, no further complaints have been made. Furthermore, the unaligned scalar access speed probe takes the same amount of time, runs synchronously, and has caused no issues. Testing shows no noticeable boot time slowdown when running the vector probe synchronously (0.464474s with kthread vs. 0.457991s without). Remove the kthread usage and run the probe synchronously. This simplifies the boot flow and allows for the revert of commit 5d15d2ad36b0 ("riscv: hwprobe: Fix stale vDSO data for late-initialized keys at boot") Reported-by: Anirudh Srinivasan Closes: https://lore.kernel.org/linux-riscv/20260612-vec_unaligned_drop_init-v1-1-df969210ae34@oss.tenstorrent.com/ Fixes: e7c9d66e313b ("RISC-V: Report vector unaligned access speed hwprobe") Cc: stable@vger.kernel.org Signed-off-by: Nam Cao Acked-by: Jesse Taube Tested-by: Anirudh Srinivasan Link: https://patch.msgid.link/1c378963f27c5960e8a57c50b8b444d30954cb54.1781666867.git.namcao@linutronix.de [pjw@kernel.org: updated to apply; adjusted Fixes: tag; fixed my own manual patch application error] Signed-off-by: Paul Walmsley --- arch/riscv/kernel/unaligned_access_speed.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c index 36201613d2ca..67f1a0371659 100644 --- a/arch/riscv/kernel/unaligned_access_speed.c +++ b/arch/riscv/kernel/unaligned_access_speed.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -288,18 +287,9 @@ static void check_vector_unaligned_access(struct work_struct *work __always_unus __free_pages(page, MISALIGNED_BUFFER_ORDER); } -/* Measure unaligned access speed on all CPUs present at boot in parallel. */ -static int vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) -{ - schedule_on_each_cpu(check_vector_unaligned_access); - riscv_hwprobe_complete_async_probe(); - - return 0; -} #else /* CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS */ -static int vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) +static void check_vector_unaligned_access(struct work_struct *work __always_unused) { - return 0; } #endif @@ -387,12 +377,7 @@ static int __init check_unaligned_access_all_cpus(void) per_cpu(vector_misaligned_access, cpu) = unaligned_vector_speed_param; } else if (!check_vector_unaligned_access_emulated_all_cpus() && IS_ENABLED(CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS)) { - riscv_hwprobe_register_async_probe(); - if (IS_ERR(kthread_run(vec_check_unaligned_access_speed_all_cpus, - NULL, "vec_check_unaligned_access_speed_all_cpus"))) { - pr_warn("Failed to create vec_unalign_check kthread\n"); - riscv_hwprobe_complete_async_probe(); - } + schedule_on_each_cpu(check_vector_unaligned_access); } /* From 7e14e42edfaa872cd56deda6951c8cd56a2678d4 Mon Sep 17 00:00:00 2001 From: Nam Cao Date: Fri, 7 Aug 2026 19:24:30 -0600 Subject: [PATCH 14/39] Revert "riscv: hwprobe: Fix stale vDSO data for late-initialized keys at boot" This reverts commit 5d15d2ad36b0 ("riscv: hwprobe: Fix stale vDSO data for late-initialized keys at boot"). The commit ensures synchronization between the unaligned vector access speed probe kthread and vDSO data read. But now that the kthread has been removed, this commit can be reverted. Signed-off-by: Nam Cao Tested-by: Anirudh Srinivasan Link: https://patch.msgid.link/50ca78a649faf53f8941bc94c9cf8268b3644d38.1781666867.git.namcao@linutronix.de Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/hwprobe.h | 7 --- arch/riscv/include/asm/vdso/arch_data.h | 6 -- arch/riscv/kernel/sys_hwprobe.c | 74 +++++-------------------- arch/riscv/kernel/vdso/hwprobe.c | 2 +- 4 files changed, 15 insertions(+), 74 deletions(-) diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h index 8b9f5e1cf4cb..9b04377c0f98 100644 --- a/arch/riscv/include/asm/hwprobe.h +++ b/arch/riscv/include/asm/hwprobe.h @@ -43,11 +43,4 @@ static inline bool riscv_hwprobe_pair_cmp(struct riscv_hwprobe *pair, return pair->value == other_pair->value; } -#ifdef CONFIG_MMU -void riscv_hwprobe_register_async_probe(void); -void riscv_hwprobe_complete_async_probe(void); -#else -static inline void riscv_hwprobe_register_async_probe(void) {} -static inline void riscv_hwprobe_complete_async_probe(void) {} -#endif #endif diff --git a/arch/riscv/include/asm/vdso/arch_data.h b/arch/riscv/include/asm/vdso/arch_data.h index 88b37af55175..da57a3786f7a 100644 --- a/arch/riscv/include/asm/vdso/arch_data.h +++ b/arch/riscv/include/asm/vdso/arch_data.h @@ -12,12 +12,6 @@ struct vdso_arch_data { /* Boolean indicating all CPUs have the same static hwprobe values. */ __u8 homogeneous_cpus; - - /* - * A gate to check and see if the hwprobe data is actually ready, as - * probing is deferred to avoid boot slowdowns. - */ - __u8 ready; }; #endif /* __RISCV_ASM_VDSO_ARCH_DATA_H */ diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c index caf6762427c8..c11d9e765372 100644 --- a/arch/riscv/kernel/sys_hwprobe.c +++ b/arch/riscv/kernel/sys_hwprobe.c @@ -5,9 +5,6 @@ * more details. */ #include -#include -#include -#include #include #include #include @@ -505,32 +502,28 @@ static int hwprobe_get_cpus(struct riscv_hwprobe __user *pairs, return 0; } +static int do_riscv_hwprobe(struct riscv_hwprobe __user *pairs, + size_t pair_count, size_t cpusetsize, + unsigned long __user *cpus_user, + unsigned int flags) +{ + if (flags & RISCV_HWPROBE_WHICH_CPUS) + return hwprobe_get_cpus(pairs, pair_count, cpusetsize, + cpus_user, flags); + + return hwprobe_get_values(pairs, pair_count, cpusetsize, + cpus_user, flags); +} + #ifdef CONFIG_MMU -static DECLARE_COMPLETION(boot_probes_done); -static atomic_t pending_boot_probes = ATOMIC_INIT(1); - -void riscv_hwprobe_register_async_probe(void) -{ - atomic_inc(&pending_boot_probes); -} - -void riscv_hwprobe_complete_async_probe(void) -{ - if (atomic_dec_and_test(&pending_boot_probes)) - complete(&boot_probes_done); -} - -static int complete_hwprobe_vdso_data(void) +static int __init init_hwprobe_vdso_data(void) { struct vdso_arch_data *avd = vdso_k_arch_data; u64 id_bitsmash = 0; struct riscv_hwprobe pair; int key; - if (unlikely(!atomic_dec_and_test(&pending_boot_probes))) - wait_for_completion(&boot_probes_done); - /* * Initialize vDSO data with the answers for the "all CPUs" case, to * save a syscall in the common case. @@ -558,52 +551,13 @@ static int complete_hwprobe_vdso_data(void) * vDSO should defer to the kernel for exotic cpu masks. */ avd->homogeneous_cpus = id_bitsmash != 0 && id_bitsmash != -1; - - /* - * Make sure all the VDSO values are visible before we look at them. - * This pairs with the implicit "no speculativly visible accesses" - * barrier in the VDSO hwprobe code. - */ - smp_wmb(); - avd->ready = true; - return 0; -} - -static int __init init_hwprobe_vdso_data(void) -{ - struct vdso_arch_data *avd = vdso_k_arch_data; - - /* - * Prevent the vDSO cached values from being used, as they're not ready - * yet. - */ - avd->ready = false; return 0; } arch_initcall_sync(init_hwprobe_vdso_data); -#else - -static int complete_hwprobe_vdso_data(void) { return 0; } - #endif /* CONFIG_MMU */ -static int do_riscv_hwprobe(struct riscv_hwprobe __user *pairs, - size_t pair_count, size_t cpusetsize, - unsigned long __user *cpus_user, - unsigned int flags) -{ - DO_ONCE_SLEEPABLE(complete_hwprobe_vdso_data); - - if (flags & RISCV_HWPROBE_WHICH_CPUS) - return hwprobe_get_cpus(pairs, pair_count, cpusetsize, - cpus_user, flags); - - return hwprobe_get_values(pairs, pair_count, cpusetsize, - cpus_user, flags); -} - SYSCALL_DEFINE5(riscv_hwprobe, struct riscv_hwprobe __user *, pairs, size_t, pair_count, size_t, cpusetsize, unsigned long __user *, cpus, unsigned int, flags) diff --git a/arch/riscv/kernel/vdso/hwprobe.c b/arch/riscv/kernel/vdso/hwprobe.c index 8f45500d0a6e..2ddeba6c68dd 100644 --- a/arch/riscv/kernel/vdso/hwprobe.c +++ b/arch/riscv/kernel/vdso/hwprobe.c @@ -27,7 +27,7 @@ static int riscv_vdso_get_values(struct riscv_hwprobe *pairs, size_t pair_count, * homogeneous, then this function can handle requests for arbitrary * masks. */ - if (flags != 0 || (!all_cpus && !avd->homogeneous_cpus) || unlikely(!avd->ready)) + if ((flags != 0) || (!all_cpus && !avd->homogeneous_cpus)) return riscv_hwprobe(pairs, pair_count, cpusetsize, cpus, flags); /* This is something we can handle, fill out the pairs. */ From e24a1418e90beac2ef4384bc9b0b5a10f19b806e Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Fri, 7 Aug 2026 19:24:30 -0600 Subject: [PATCH 15/39] RISC-V: perf: fix resource cleanup on driver probe failure Sashiko pointed out various UAF and memory leak issues around pmu_sbi_device_probe() error paths. If the probe fails, here are list of cleanups needed. a. Already registered pmu must be freed b. per cpu IRQ must be released c. pmu_ctr_list data structure must be freed d. cpu hotplug state must be cleaned up only if added. Fix the resource cleanup by reorganizing the code around probe failure. Reported-by: Sashiko AI Reviewed-by: Charlie Jenkins Signed-off-by: Atish Patra Link: https://patch.msgid.link/20260807-counter_delegation-v9-1-58658104e487@meta.com Signed-off-by: Paul Walmsley --- drivers/perf/riscv_pmu_sbi.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c index dfc886dee5ad..50220f7b46d9 100644 --- a/drivers/perf/riscv_pmu_sbi.c +++ b/drivers/perf/riscv_pmu_sbi.c @@ -1219,22 +1219,29 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde DOMAIN_BUS_ANY); if (!domain) { pr_err("Failed to find INTC IRQ root domain\n"); - return -ENODEV; + ret = -ENODEV; + goto err; } riscv_pmu_irq = irq_create_mapping(domain, riscv_pmu_irq_num); if (!riscv_pmu_irq) { pr_err("Failed to map PMU interrupt for node\n"); - return -ENODEV; + ret = -ENODEV; + goto err; } ret = request_percpu_irq(riscv_pmu_irq, pmu_sbi_ovf_handler, "riscv-pmu", hw_events); if (ret) { pr_err("registering percpu irq failed [%d]\n", ret); - return ret; + irq_dispose_mapping(riscv_pmu_irq); + riscv_pmu_irq = 0; + goto err; } return 0; +err: + riscv_pmu_use_irq = false; + return ret; } #ifdef CONFIG_CPU_PM @@ -1301,7 +1308,8 @@ static void riscv_pmu_destroy(struct riscv_pmu *pmu) } } riscv_pm_pmu_unregister(pmu); - cpuhp_state_remove_instance(CPUHP_AP_PERF_RISCV_STARTING, &pmu->node); + if (!hlist_unhashed(&pmu->node)) + cpuhp_state_remove_instance(CPUHP_AP_PERF_RISCV_STARTING, &pmu->node); } static void pmu_sbi_event_init(struct perf_event *event) @@ -1423,6 +1431,7 @@ static int pmu_sbi_device_probe(struct platform_device *pdev) struct riscv_pmu *pmu = NULL; int ret = -ENODEV; int num_counters; + bool irq_requested = false; pr_info("SBI PMU extension is available\n"); pmu = riscv_pmu_alloc(); @@ -1451,6 +1460,7 @@ static int pmu_sbi_device_probe(struct platform_device *pdev) pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT; pmu->pmu.capabilities |= PERF_PMU_CAP_NO_EXCLUDE; } + irq_requested = (ret == 0); pmu->pmu.attr_groups = riscv_pmu_attr_groups; pmu->pmu.parent = &pdev->dev; @@ -1469,11 +1479,11 @@ static int pmu_sbi_device_probe(struct platform_device *pdev) ret = riscv_pm_pmu_register(pmu); if (ret) - goto out_unregister; + goto out_destroy; ret = perf_pmu_register(&pmu->pmu, "cpu", PERF_TYPE_RAW); if (ret) - goto out_unregister; + goto out_destroy; /* SBI PMU Snapsphot is only available in SBI v2.0 */ if (sbi_v2_available) { @@ -1514,9 +1524,20 @@ static int pmu_sbi_device_probe(struct platform_device *pdev) return 0; out_unregister: + perf_pmu_unregister(&pmu->pmu); + +out_destroy: riscv_pmu_destroy(pmu); + if (irq_requested) { + free_percpu_irq(riscv_pmu_irq, pmu->hw_events); + irq_dispose_mapping(riscv_pmu_irq); + riscv_pmu_irq = 0; + } out_free: + free_percpu(pmu->hw_events); + kfree(pmu_ctr_list); + pmu_ctr_list = NULL; kfree(pmu); return ret; } From 09b5f358e85376c1e014bd8ea9d6806754d659e7 Mon Sep 17 00:00:00 2001 From: Kaiwen Xue Date: Fri, 7 Aug 2026 19:24:31 -0600 Subject: [PATCH 16/39] RISC-V: Add Smcsrind and Sscsrind ISA extension CSR definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds definitions of new CSRs and bits defined in the Smcsrind and Sscsrind ISA extensions. These CSRs enable the indirect CSR accesses mechanism to access any indirect CSRs in M-, S-, and VS-mode. The range of the select values and ireg will be defined by the ISA extension that are based on the Smcsrind and Sscsrind extensions. Signed-off-by: Kaiwen Xue Reviewed-by: Clément Léger Signed-off-by: Atish Patra Reviewed-by: Charlie Jenkins Tested-by: Charlie Jenkins [pjw@kernel.org: clean up the patch description; use official RISC-V extension names] Link: https://patch.msgid.link/20260807-counter_delegation-v9-2-58658104e487@meta.com Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/csr.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index 31b8988f4488..7f09e54a0f9a 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -347,6 +347,12 @@ /* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */ #define CSR_SISELECT 0x150 #define CSR_SIREG 0x151 +/* Supervisor-Level Window to Indirectly Accessed Registers (Sscsrind) */ +#define CSR_SIREG2 0x152 +#define CSR_SIREG3 0x153 +#define CSR_SIREG4 0x155 +#define CSR_SIREG5 0x156 +#define CSR_SIREG6 0x157 /* Supervisor-Level Interrupts (AIA) */ #define CSR_STOPEI 0x15c @@ -394,6 +400,14 @@ /* VS-Level Window to Indirectly Accessed Registers (H-extension with AIA) */ #define CSR_VSISELECT 0x250 #define CSR_VSIREG 0x251 +/* + * VS-Level Window to Indirectly Accessed Registers (H-extension with Sscsrind) + */ +#define CSR_VSIREG2 0x252 +#define CSR_VSIREG3 0x253 +#define CSR_VSIREG4 0x255 +#define CSR_VSIREG5 0x256 +#define CSR_VSIREG6 0x257 /* VS-Level Interrupts (H-extension with AIA) */ #define CSR_VSTOPEI 0x25c @@ -436,6 +450,12 @@ /* Machine-Level Window to Indirectly Accessed Registers (AIA) */ #define CSR_MISELECT 0x350 #define CSR_MIREG 0x351 +/* Machine-Level Window to Indirectly Accessed Registers (Smcsrind) */ +#define CSR_MIREG2 0x352 +#define CSR_MIREG3 0x353 +#define CSR_MIREG4 0x355 +#define CSR_MIREG5 0x356 +#define CSR_MIREG6 0x357 /* Machine-Level Interrupts (AIA) */ #define CSR_MTOPEI 0x35c @@ -498,6 +518,11 @@ # define CSR_IEH CSR_MIEH # define CSR_ISELECT CSR_MISELECT # define CSR_IREG CSR_MIREG +# define CSR_IREG2 CSR_MIREG2 +# define CSR_IREG3 CSR_MIREG3 +# define CSR_IREG4 CSR_MIREG4 +# define CSR_IREG5 CSR_MIREG5 +# define CSR_IREG6 CSR_MIREG6 # define CSR_IPH CSR_MIPH # define CSR_TOPEI CSR_MTOPEI # define CSR_TOPI CSR_MTOPI @@ -523,6 +548,11 @@ # define CSR_IEH CSR_SIEH # define CSR_ISELECT CSR_SISELECT # define CSR_IREG CSR_SIREG +# define CSR_IREG2 CSR_SIREG2 +# define CSR_IREG3 CSR_SIREG3 +# define CSR_IREG4 CSR_SIREG4 +# define CSR_IREG5 CSR_SIREG5 +# define CSR_IREG6 CSR_SIREG6 # define CSR_IPH CSR_SIPH # define CSR_TOPEI CSR_STOPEI # define CSR_TOPI CSR_STOPI From 0ce0702f5ee69a953845a498bbed7383ebc6b5da Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Fri, 7 Aug 2026 19:24:31 -0600 Subject: [PATCH 17/39] RISC-V: Add Smcsrind and Sscsrind ISA extension definition and parsing The S[m|s]csrind extensions extend the indirect CSR access mechanism defined in Smaia/Ssaia extensions. This patch just enables the definition and parsing. Signed-off-by: Atish Patra Reviewed-by: Charlie Jenkins Tested-by: Charlie Jenkins [pjw@kernel.org: use official RISC-V extension names in the patch description] Link: https://patch.msgid.link/20260807-counter_delegation-v9-3-58658104e487@meta.com Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/hwcap.h | 4 ++++ arch/riscv/kernel/cpufeature.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index 7ef8e5f55c8d..d4a7b90e2d78 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -112,6 +112,8 @@ #define RISCV_ISA_EXT_ZCLSD 103 #define RISCV_ISA_EXT_ZICFILP 104 #define RISCV_ISA_EXT_ZICFISS 105 +#define RISCV_ISA_EXT_SSCSRIND 106 +#define RISCV_ISA_EXT_SMCSRIND 107 #define RISCV_ISA_EXT_XLINUXENVCFG 127 @@ -121,9 +123,11 @@ #ifdef CONFIG_RISCV_M_MODE #define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SMAIA #define RISCV_ISA_EXT_SUPM RISCV_ISA_EXT_SMNPM +#define RISCV_ISA_EXT_SxCSRIND RISCV_ISA_EXT_SMCSRIND #else #define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SSAIA #define RISCV_ISA_EXT_SUPM RISCV_ISA_EXT_SSNPM +#define RISCV_ISA_EXT_SxCSRIND RISCV_ISA_EXT_SSCSRIND #endif #endif /* _ASM_RISCV_HWCAP_H */ diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index f46aa5602d74..3fa0a563fb21 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -576,11 +576,13 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_BUNDLE_VALIDATE(zvksg, riscv_zvksg_bundled_exts, riscv_ext_vector_crypto_validate), __RISCV_ISA_EXT_DATA_VALIDATE(zvkt, RISCV_ISA_EXT_ZVKT, riscv_ext_vector_crypto_validate), __RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA), + __RISCV_ISA_EXT_DATA(smcsrind, RISCV_ISA_EXT_SMCSRIND), __RISCV_ISA_EXT_DATA(smmpm, RISCV_ISA_EXT_SMMPM), __RISCV_ISA_EXT_SUPERSET(smnpm, RISCV_ISA_EXT_SMNPM, riscv_xlinuxenvcfg_exts), __RISCV_ISA_EXT_DATA(smstateen, RISCV_ISA_EXT_SMSTATEEN), __RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA), __RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF), + __RISCV_ISA_EXT_DATA(sscsrind, RISCV_ISA_EXT_SSCSRIND), __RISCV_ISA_EXT_SUPERSET(ssnpm, RISCV_ISA_EXT_SSNPM, riscv_xlinuxenvcfg_exts), __RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC), __RISCV_ISA_EXT_DATA(svade, RISCV_ISA_EXT_SVADE), From 7e1b80880747d616316860eca8781f4066cedc9c Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Fri, 7 Aug 2026 19:24:31 -0600 Subject: [PATCH 18/39] dt-bindings: riscv: add Smcsrind and Sscsrind ISA extension descriptions Add the S[m|s]csrind ISA extension description. Acked-by: Rob Herring (Arm) Signed-off-by: Atish Patra [pjw@kernel.org: use official extension names in the patch description] Link: https://patch.msgid.link/20260807-counter_delegation-v9-4-58658104e487@meta.com Signed-off-by: Paul Walmsley --- .../devicetree/bindings/riscv/extensions.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml index 5ffc40d599c0..ccff2be1224d 100644 --- a/Documentation/devicetree/bindings/riscv/extensions.yaml +++ b/Documentation/devicetree/bindings/riscv/extensions.yaml @@ -181,6 +181,14 @@ properties: changes to interrupts as frozen at commit ccbddab ("Merge pull request #42 from riscv/jhauser-2023-RC4") of riscv-aia. + - const: smcsrind + description: | + The standard Smcsrind machine-level extension extends the + indirect CSR access mechanism defined by the Smaia extension. This + extension allows other ISA extensions to use indirect CSR access + mechanism in M-mode as ratified in the 20240326 version of the + privileged ISA specification. + - const: smmpm description: | The standard Smmpm extension for M-mode pointer masking as @@ -226,6 +234,14 @@ properties: Profiles Version 1.0, with commit b1d806605f87 ("Updated to ratified state.") + - const: sscsrind + description: | + The standard Sscsrind supervisor-level extension extends the + indirect CSR access mechanism defined by the Ssaia extension. This + extension allows other ISA extensions to use indirect CSR access + mechanism in S-mode as ratified in the 20240326 version of the + privileged ISA specification. + - const: ssnpm description: | The standard Ssnpm extension for next-mode pointer masking as From e6b8e7f217c772b53491ecf395748ba409ba181b Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Fri, 7 Aug 2026 19:24:31 -0600 Subject: [PATCH 19/39] RISC-V: Define indirect CSR access helpers The indirect CSR requires multiple instructions to read/write CSR. Add a few helper macros for ease of usage. These have to be macros rather than functions. csr_read()/csr_write() stringify their CSR argument into the inline asm template via __ASM_STR(), so the CSR number must be a literal token; passing it as a function parameter emits "csrr %0, iregcsr", which the assembler rejects with "unknown CSR `iregcsr'". The stringification happens in the preprocessor, before inlining or constant propagation, so it cannot be worked around by forcing inlining or by only ever passing constants - gcc 12, gcc 16 and clang 22 all reject it alike. Underneath, csrr/csrw encode the CSR as a 12-bit immediate and RISC-V has no register-indirect form, which is also why asm/csr.h keeps every one of its accessors as a macro. Signed-off-by: Atish Patra Reviewed-by: Charlie Jenkins Tested-by: Charlie Jenkins [pjw@kernel.org: expand "ind" abbreviation] Link: https://patch.msgid.link/20260807-counter_delegation-v9-5-58658104e487@meta.com Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/csr_indirect.h | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 arch/riscv/include/asm/csr_indirect.h diff --git a/arch/riscv/include/asm/csr_indirect.h b/arch/riscv/include/asm/csr_indirect.h new file mode 100644 index 000000000000..0f558fac8f5f --- /dev/null +++ b/arch/riscv/include/asm/csr_indirect.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _ASM_RISCV_CSR_INDIRECT_H +#define _ASM_RISCV_CSR_INDIRECT_H + +#include + +#include + +/* + * These have to be macros rather than functions: csr_read()/csr_write() + * stringify their CSR argument into the inline asm template via __ASM_STR(), + * so the CSR number must be a literal token at preprocessing time. Passing it + * as a function parameter emits "csrr %0, iregcsr", which no assembler can + * resolve. RISC-V has no register-indirect form of csrr/csrw - the CSR is a + * 12-bit immediate - so the sireg CSR selecting the indirect window cannot + * itself be a variable. + */ +#define csr_indirect_read(iregcsr, iselbase, iseloff) ({ \ + unsigned long __value = 0; \ + unsigned long __flags; \ + local_irq_save(__flags); \ + csr_write(CSR_ISELECT, (iselbase) + (iseloff)); \ + __value = csr_read(iregcsr); \ + local_irq_restore(__flags); \ + __value; \ +}) + +#define csr_indirect_write(iregcsr, iselbase, iseloff, value) ({ \ + unsigned long __flags; \ + local_irq_save(__flags); \ + csr_write(CSR_ISELECT, (iselbase) + (iseloff)); \ + csr_write(iregcsr, (value)); \ + local_irq_restore(__flags); \ +}) + +#define csr_indirect_warl(iregcsr, iselbase, iseloff, warl_val) ({ \ + unsigned long __old_val = 0, __value = 0; \ + unsigned long __flags; \ + local_irq_save(__flags); \ + csr_write(CSR_ISELECT, (iselbase) + (iseloff)); \ + __old_val = csr_read(iregcsr); \ + csr_write(iregcsr, (warl_val)); \ + __value = csr_read(iregcsr); \ + csr_write(iregcsr, __old_val); \ + local_irq_restore(__flags); \ + __value; \ +}) + +#endif From 9e350913142b9ea518b13254b4ff0d82b6c0e696 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Fri, 7 Aug 2026 19:24:31 -0600 Subject: [PATCH 20/39] RISC-V: Add Smcntrpmf extension parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Smcntrpmf extension allows M-mode to enable privilege mode filtering for cycle/instret counters. However, the cyclecfg/instretcfg CSRs are available in Ssccfg only if Smcntrpmf is present. That's why, kernel needs to detect presence of Smcntrpmf extension and enable privilege mode filtering for cycle/instret counters. Reviewed-by: Clément Léger Signed-off-by: Atish Patra Reviewed-by: Charlie Jenkins Tested-by: Charlie Jenkins Link: https://patch.msgid.link/20260807-counter_delegation-v9-6-58658104e487@meta.com Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/hwcap.h | 1 + arch/riscv/kernel/cpufeature.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index d4a7b90e2d78..51ad55b9677a 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -114,6 +114,7 @@ #define RISCV_ISA_EXT_ZICFISS 105 #define RISCV_ISA_EXT_SSCSRIND 106 #define RISCV_ISA_EXT_SMCSRIND 107 +#define RISCV_ISA_EXT_SMCNTRPMF 108 #define RISCV_ISA_EXT_XLINUXENVCFG 127 diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 3fa0a563fb21..1452521d740a 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -576,6 +576,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_BUNDLE_VALIDATE(zvksg, riscv_zvksg_bundled_exts, riscv_ext_vector_crypto_validate), __RISCV_ISA_EXT_DATA_VALIDATE(zvkt, RISCV_ISA_EXT_ZVKT, riscv_ext_vector_crypto_validate), __RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA), + __RISCV_ISA_EXT_DATA(smcntrpmf, RISCV_ISA_EXT_SMCNTRPMF), __RISCV_ISA_EXT_DATA(smcsrind, RISCV_ISA_EXT_SMCSRIND), __RISCV_ISA_EXT_DATA(smmpm, RISCV_ISA_EXT_SMMPM), __RISCV_ISA_EXT_SUPERSET(smnpm, RISCV_ISA_EXT_SMNPM, riscv_xlinuxenvcfg_exts), From 1c40a2d06d0313cdb19aec4f0bb81959a0da1765 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Fri, 7 Aug 2026 19:24:31 -0600 Subject: [PATCH 21/39] dt-bindings: riscv: add Smcntrpmf ISA extension description Add the description for Smcntrpmf ISA extension Acked-by: Rob Herring (Arm) Signed-off-by: Atish Patra Link: https://patch.msgid.link/20260807-counter_delegation-v9-7-58658104e487@meta.com Signed-off-by: Paul Walmsley --- Documentation/devicetree/bindings/riscv/extensions.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml index ccff2be1224d..eee65cf73d6c 100644 --- a/Documentation/devicetree/bindings/riscv/extensions.yaml +++ b/Documentation/devicetree/bindings/riscv/extensions.yaml @@ -181,6 +181,12 @@ properties: changes to interrupts as frozen at commit ccbddab ("Merge pull request #42 from riscv/jhauser-2023-RC4") of riscv-aia. + - const: smcntrpmf + description: | + The standard Smcntrpmf machine-level extension for the machine mode + to enable privilege mode filtering for cycle and instret counters as + ratified in the 20240326 version of the privileged ISA specification. + - const: smcsrind description: | The standard Smcsrind machine-level extension extends the From 05e44c11f68c3a3cbf706f2c565d3b60337de7db Mon Sep 17 00:00:00 2001 From: Kaiwen Xue Date: Fri, 7 Aug 2026 19:24:31 -0600 Subject: [PATCH 22/39] RISC-V: Add Ssccfg extension CSR definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the scountinhibit CSR definition and S-mode accessible hpmevent bits defined by smcdeleg/ssccfg. scountinhibit allows S-mode to start/stop counters directly from S-mode without invoking SBI calls to M-mode. It is also used to figure out the counters delegated to S-mode by the M-mode as well. Signed-off-by: Kaiwen Xue Reviewed-by: Clément Léger Reviewed-by: Charlie Jenkins Tested-by: Charlie Jenkins [pjw@kernel.org: fixed subject typo] Link: https://patch.msgid.link/20260807-counter_delegation-v9-8-58658104e487@meta.com Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/csr.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index 7f09e54a0f9a..c8b94f3337c1 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -241,6 +241,23 @@ #define SMSTATEEN0_HSENVCFG (_ULL(1) << SMSTATEEN0_HSENVCFG_SHIFT) #define SMSTATEEN0_SSTATEEN0_SHIFT 63 #define SMSTATEEN0_SSTATEEN0 (_ULL(1) << SMSTATEEN0_SSTATEEN0_SHIFT) +/* HPMEVENT bits. These are accessible in S-mode via Smcdeleg/Ssccfg */ +#define HPMEVENT_OF (BIT_ULL(63)) +#define HPMEVENT_MINH (BIT_ULL(62)) +#define HPMEVENT_SINH (BIT_ULL(61)) +#define HPMEVENT_UINH (BIT_ULL(60)) +#define HPMEVENT_VSINH (BIT_ULL(59)) +#define HPMEVENT_VUINH (BIT_ULL(58)) +#ifndef CONFIG_64BIT +#define HPMEVENTH_OF (BIT(31)) +#define HPMEVENTH_MINH (BIT(30)) +#define HPMEVENTH_SINH (BIT(29)) +#define HPMEVENTH_UINH (BIT(28)) +#define HPMEVENTH_VSINH (BIT(27)) +#define HPMEVENTH_VUINH (BIT(26)) +#endif + +#define SISELECT_SSCCFG_BASE 0x40 /* mseccfg bits */ #define MSECCFG_PMM ENVCFG_PMM @@ -322,6 +339,7 @@ #define CSR_SCOUNTEREN 0x106 #define CSR_SENVCFG 0x10a #define CSR_SSTATEEN0 0x10c +#define CSR_SCOUNTINHIBIT 0x120 #define CSR_SSCRATCH 0x140 #define CSR_SEPC 0x141 #define CSR_SCAUSE 0x142 From ebdec8d2c156b8e662cb350ce05b0f92275f6ffd Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Fri, 7 Aug 2026 19:24:32 -0600 Subject: [PATCH 23/39] RISC-V: Add Ssccfg/Smcdeleg ISA extension definition and parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Smcdeleg extension allows the M-mode to delegate selected counters to S-mode so that it can access those counters and correpsonding hpmevent CSRs without M-mode. Ssccfg (‘Ss’ for Privileged architecture and Supervisor-level extension, ‘ccfg’ for Counter Configuration) provides access to delegated counters and new supervisor-level state. This patch just enables these definitions and enable parsing. Signed-off-by: Atish Patra Reviewed-by: Charlie Jenkins Link: https://patch.msgid.link/20260807-counter_delegation-v9-9-58658104e487@meta.com Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/hwcap.h | 2 ++ arch/riscv/kernel/cpufeature.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index 51ad55b9677a..089353b250b0 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -115,6 +115,8 @@ #define RISCV_ISA_EXT_SSCSRIND 106 #define RISCV_ISA_EXT_SMCSRIND 107 #define RISCV_ISA_EXT_SMCNTRPMF 108 +#define RISCV_ISA_EXT_SSCCFG 109 +#define RISCV_ISA_EXT_SMCDELEG 110 #define RISCV_ISA_EXT_XLINUXENVCFG 127 diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 1452521d740a..1fe647e03515 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -330,6 +330,27 @@ static const unsigned int riscv_a_exts[] = { RISCV_ISA_EXT_ZKNE, \ RISCV_ISA_EXT_ZKNH +static int riscv_ext_smcdeleg_validate(const struct riscv_isa_ext_data *data, + const unsigned long *isa_bitmap) +{ + if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_SSCSRIND) && + __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZIHPM) && + __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZICNTR)) + return 0; + + return -EPROBE_DEFER; +} + +static int riscv_ext_ssccfg_validate(const struct riscv_isa_ext_data *data, + const unsigned long *isa_bitmap) +{ + if (!riscv_ext_smcdeleg_validate(data, isa_bitmap) && + __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_SMCDELEG)) + return 0; + + return -EPROBE_DEFER; +} + static const unsigned int riscv_zk_bundled_exts[] = { RISCV_ISA_EXT_ZKN, RISCV_ISA_EXT_ZKR, @@ -576,12 +597,15 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_BUNDLE_VALIDATE(zvksg, riscv_zvksg_bundled_exts, riscv_ext_vector_crypto_validate), __RISCV_ISA_EXT_DATA_VALIDATE(zvkt, RISCV_ISA_EXT_ZVKT, riscv_ext_vector_crypto_validate), __RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA), + __RISCV_ISA_EXT_DATA_VALIDATE(smcdeleg, RISCV_ISA_EXT_SMCDELEG, + riscv_ext_smcdeleg_validate), __RISCV_ISA_EXT_DATA(smcntrpmf, RISCV_ISA_EXT_SMCNTRPMF), __RISCV_ISA_EXT_DATA(smcsrind, RISCV_ISA_EXT_SMCSRIND), __RISCV_ISA_EXT_DATA(smmpm, RISCV_ISA_EXT_SMMPM), __RISCV_ISA_EXT_SUPERSET(smnpm, RISCV_ISA_EXT_SMNPM, riscv_xlinuxenvcfg_exts), __RISCV_ISA_EXT_DATA(smstateen, RISCV_ISA_EXT_SMSTATEEN), __RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA), + __RISCV_ISA_EXT_DATA_VALIDATE(ssccfg, RISCV_ISA_EXT_SSCCFG, riscv_ext_ssccfg_validate), __RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF), __RISCV_ISA_EXT_DATA(sscsrind, RISCV_ISA_EXT_SSCSRIND), __RISCV_ISA_EXT_SUPERSET(ssnpm, RISCV_ISA_EXT_SSNPM, riscv_xlinuxenvcfg_exts), From 641f9fe9017420b41659e048253c0849eda02a96 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Fri, 7 Aug 2026 19:24:32 -0600 Subject: [PATCH 24/39] dt-bindings: riscv: add Counter delegation ISA extensions description Add description for the Smcdeleg/Ssccfg extension. Signed-off-by: Atish Patra Acked-by: Conor Dooley Link: https://patch.msgid.link/20260807-counter_delegation-v9-10-58658104e487@meta.com Signed-off-by: Paul Walmsley --- .../devicetree/bindings/riscv/extensions.yaml | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml index eee65cf73d6c..24efd3e1cf8e 100644 --- a/Documentation/devicetree/bindings/riscv/extensions.yaml +++ b/Documentation/devicetree/bindings/riscv/extensions.yaml @@ -181,6 +181,13 @@ properties: changes to interrupts as frozen at commit ccbddab ("Merge pull request #42 from riscv/jhauser-2023-RC4") of riscv-aia. + - const: smcdeleg + description: | + The standard Smcdeleg machine-level extension for the machine mode + to delegate the hpmcounters to supervisor mode so that they are + directly accessible in the supervisor mode as ratified in the + 20240213 version of the privileged ISA specification. + - const: smcntrpmf description: | The standard Smcntrpmf machine-level extension for the machine mode @@ -220,6 +227,14 @@ properties: behavioural changes to interrupts as frozen at commit ccbddab ("Merge pull request #42 from riscv/jhauser-2023-RC4") of riscv-aia. + - const: ssccfg + description: | + The standard Ssccfg supervisor-level extension for configuring + the delegated hpmcounters to be accessible directly in supervisor + mode as ratified in the 20240213 version of the privileged ISA + specification. This extension depends on Sscsrind, Smcdeleg, Zihpm, + Zicntr extensions. + - const: ssccptr description: | The standard Ssccptr extension for main memory (cacheability and @@ -1135,6 +1150,32 @@ properties: allOf: - const: zilsd - const: zca + # Smcdeleg depends on Sscsrind, Zihpm, Zicntr + - if: + contains: + const: smcdeleg + then: + allOf: + - contains: + const: sscsrind + - contains: + const: zihpm + - contains: + const: zicntr + # Ssccfg depends on Smcdeleg, Sscsrind, Zihpm, Zicntr + - if: + contains: + const: ssccfg + then: + allOf: + - contains: + const: smcdeleg + - contains: + const: sscsrind + - contains: + const: zihpm + - contains: + const: zicntr allOf: # Zcf extension does not exist on rv64 From 3ec6f50a91bd2bdf9ab4e9f6ff64ac2665aa03ce Mon Sep 17 00:00:00 2001 From: Drew Fustini Date: Fri, 7 Aug 2026 19:24:32 -0600 Subject: [PATCH 25/39] dt-bindings: riscv: Add Ssqosid extension description Document the ratified Supervisor-mode Quality of Service ID (Ssqosid) extension v1.0. Link: https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0 Acked-by: Conor Dooley Signed-off-by: Drew Fustini Link: https://patch.msgid.link/20260729-dfustini-atl-sc-cbqri-dt-v6-1-7c22b05d461b@kernel.org Signed-off-by: Paul Walmsley --- Documentation/devicetree/bindings/riscv/extensions.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml index 24efd3e1cf8e..577d7ae5576b 100644 --- a/Documentation/devicetree/bindings/riscv/extensions.yaml +++ b/Documentation/devicetree/bindings/riscv/extensions.yaml @@ -269,6 +269,12 @@ properties: ratified at commit d70011dde6c2 ("Update to ratified state") of riscv-j-extension. + - const: ssqosid + description: | + The standard Ssqosid extension for Quality of Service ID is + ratified as v1.0 in commit d9c616497fde ("Merge pull + request #7 from ved-rivos/Ratified") of riscv-ssqosid. + - const: ssstateen description: | The standard Ssstateen extension for supervisor-mode view of the From 5a17eb5f1c4ccbc353ec9f7c6125901fd87e1149 Mon Sep 17 00:00:00 2001 From: Drew Fustini Date: Fri, 7 Aug 2026 19:24:32 -0600 Subject: [PATCH 26/39] riscv: Detect the Ssqosid extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ssqosid is the RISC-V Quality-of-Service (QoS) Identifiers specification which defines the Supervisor Resource Management Configuration (srmcfg) register. Link: https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0 Co-developed-by: Kornel Dulęba Signed-off-by: Kornel Dulęba Signed-off-by: Drew Fustini Link: https://patch.msgid.link/20260729-dfustini-atl-sc-cbqri-dt-v6-2-7c22b05d461b@kernel.org [pjw@kernel.org: updated to apply] Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/hwcap.h | 1 + arch/riscv/kernel/cpufeature.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index 089353b250b0..b656f5627f2e 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -117,6 +117,7 @@ #define RISCV_ISA_EXT_SMCNTRPMF 108 #define RISCV_ISA_EXT_SSCCFG 109 #define RISCV_ISA_EXT_SMCDELEG 110 +#define RISCV_ISA_EXT_SSQOSID 111 #define RISCV_ISA_EXT_XLINUXENVCFG 127 diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 1fe647e03515..53f63f560349 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -609,6 +609,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF), __RISCV_ISA_EXT_DATA(sscsrind, RISCV_ISA_EXT_SSCSRIND), __RISCV_ISA_EXT_SUPERSET(ssnpm, RISCV_ISA_EXT_SSNPM, riscv_xlinuxenvcfg_exts), + __RISCV_ISA_EXT_DATA(ssqosid, RISCV_ISA_EXT_SSQOSID), __RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC), __RISCV_ISA_EXT_DATA(svade, RISCV_ISA_EXT_SVADE), __RISCV_ISA_EXT_DATA_VALIDATE(svadu, RISCV_ISA_EXT_SVADU, riscv_ext_svadu_validate), From 326ba66db9494e71ddcafd1c4c063b49c3101495 Mon Sep 17 00:00:00 2001 From: Drew Fustini Date: Fri, 7 Aug 2026 19:24:32 -0600 Subject: [PATCH 27/39] riscv: Add support for srmcfg CSR from Ssqosid extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the srmcfg CSR defined in the Ssqosid ISA extension. The CSR contains two fields: - Resource Control ID (RCID) for resource allocation - Monitoring Counter ID (MCID) for tracking resource usage Requests from a hart to shared resources are tagged with these IDs, allowing resource usage to be associated with the running task. Add a srmcfg field to thread_struct with the same format as the CSR. The context-switch path writes the field to the CSR, and resctrl_arch_set_closid_rmid() updates it when a task is assigned to a resctrl control or monitoring group. A per-cpu cpu_srmcfg_default holds the default srmcfg for each CPU, set by resctrl_arch_set_cpu_default_closid_rmid() on CPU group assignment. On context switch, RCID and MCID inherit from the CPU default independently: a task whose thread RCID field is zero takes the CPU default's RCID, and likewise for MCID. A per-cpu cpu_srmcfg variable mirrors the CSR state to avoid redundant writes. L1D-hot memory access is faster than a CSR read and avoids traps under virtualization. Link: https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0 Assisted-by: Claude:claude-opus-4-7 Co-developed-by: Kornel Dulęba Signed-off-by: Kornel Dulęba Signed-off-by: Drew Fustini Link: https://patch.msgid.link/20260729-dfustini-atl-sc-cbqri-dt-v6-3-7c22b05d461b@kernel.org Signed-off-by: Paul Walmsley --- MAINTAINERS | 8 +++ arch/riscv/Kconfig | 18 +++++ arch/riscv/include/asm/csr.h | 5 ++ arch/riscv/include/asm/processor.h | 3 + arch/riscv/include/asm/qos.h | 74 +++++++++++++++++++++ arch/riscv/include/asm/switch_to.h | 3 + arch/riscv/kernel/Makefile | 2 + arch/riscv/kernel/qos.c | 101 +++++++++++++++++++++++++++++ 8 files changed, 214 insertions(+) create mode 100644 arch/riscv/include/asm/qos.h create mode 100644 arch/riscv/kernel/qos.c diff --git a/MAINTAINERS b/MAINTAINERS index 5114e6db7307..c82a7348baa3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23296,6 +23296,14 @@ F: drivers/perf/riscv_pmu.c F: drivers/perf/riscv_pmu_legacy.c F: drivers/perf/riscv_pmu_sbi.c +RISC-V QOS RESCTRL SUPPORT +M: Drew Fustini +R: yunhui cui +L: linux-riscv@lists.infradead.org +S: Supported +F: arch/riscv/include/asm/qos.h +F: arch/riscv/kernel/qos.c + RISC-V RPMI AND MPXY DRIVERS M: Rahul Pathak M: Anup Patel diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index c2c2f5f3ed5e..f8a7c48b5a03 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -592,6 +592,24 @@ config RISCV_ISA_SVNAPOT If you don't know what to do here, say Y. +config RISCV_ISA_SSQOSID + bool "Ssqosid extension support for supervisor mode Quality of Service ID" + depends on 64BIT + default n + help + Adds support for the Ssqosid ISA extension (Supervisor-mode + Quality of Service ID). + + Ssqosid defines the srmcfg CSR which allows the system to tag the + running process with an RCID (Resource Control ID) and MCID + (Monitoring Counter ID). The RCID is used to determine resource + allocation. The MCID is used to track resource usage in event + counters. + + For example, a cache controller may use the RCID to apply a + cache partitioning scheme and use the MCID to track how much + cache a process, or a group of processes, is using. + config RISCV_ISA_SVPBMT bool "Svpbmt extension support for supervisor mode page-based memory types" depends on 64BIT && MMU diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index c8b94f3337c1..7f909629d21d 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -84,6 +84,10 @@ #define SATP_ASID_MASK _AC(0xFFFF, UL) #endif +/* SRMCFG fields */ +#define SRMCFG_RCID_MASK GENMASK(11, 0) +#define SRMCFG_MCID_MASK GENMASK(27, 16) + /* Exception cause high bit - is an interrupt if set */ #define CAUSE_IRQ_FLAG (_AC(1, UL) << (__riscv_xlen - 1)) @@ -346,6 +350,7 @@ #define CSR_STVAL 0x143 #define CSR_SIP 0x144 #define CSR_SATP 0x180 +#define CSR_SRMCFG 0x181 #define CSR_STIMECMP 0x14D #define CSR_STIMECMPH 0x15D diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h index 812517b2cec1..49a386d74cd3 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -123,6 +123,9 @@ struct thread_struct { /* A forced icache flush is not needed if migrating to the previous cpu. */ unsigned int prev_cpu; #endif +#ifdef CONFIG_RISCV_ISA_SSQOSID + u32 srmcfg; +#endif }; /* Whitelist the fstate from the task_struct for hardened usercopy */ diff --git a/arch/riscv/include/asm/qos.h b/arch/riscv/include/asm/qos.h new file mode 100644 index 000000000000..cf19e8438bb9 --- /dev/null +++ b/arch/riscv/include/asm/qos.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_RISCV_QOS_H +#define _ASM_RISCV_QOS_H + +#include + +#ifdef CONFIG_RISCV_ISA_SSQOSID + +#include +#include +#include + +#include +#include + +/* cached value of srmcfg csr for each cpu */ +DECLARE_PER_CPU(u32, cpu_srmcfg); + +/* default srmcfg value for each cpu, set via resctrl cpu assignment */ +DECLARE_PER_CPU(u32, cpu_srmcfg_default); + +static inline void __switch_to_srmcfg(struct task_struct *next) +{ + u32 thread_srmcfg, default_srmcfg; + + thread_srmcfg = READ_ONCE(next->thread.srmcfg); + default_srmcfg = __this_cpu_read(cpu_srmcfg_default); + + /* + * RCID and MCID inherit from cpu_srmcfg_default independently. + * RESCTRL_RESERVED_CLOSID and RESCTRL_RESERVED_RMID are both 0, so a + * zero field means "unassigned" and takes the CPU default. + */ + if (thread_srmcfg == 0) { + thread_srmcfg = default_srmcfg; + } else { + u32 rcid = FIELD_GET(SRMCFG_RCID_MASK, thread_srmcfg); + u32 mcid = FIELD_GET(SRMCFG_MCID_MASK, thread_srmcfg); + + if (rcid == 0 || mcid == 0) { + if (rcid == 0) + rcid = FIELD_GET(SRMCFG_RCID_MASK, default_srmcfg); + if (mcid == 0) + mcid = FIELD_GET(SRMCFG_MCID_MASK, default_srmcfg); + thread_srmcfg = FIELD_PREP(SRMCFG_RCID_MASK, rcid) | + FIELD_PREP(SRMCFG_MCID_MASK, mcid); + } + } + + if (thread_srmcfg != __this_cpu_read(cpu_srmcfg)) { + /* + * No fence around the csrw. Ssqosid is silent on srmcfg + * ordering versus memory accesses, so a few accesses at the + * switch boundary may carry the previous RCID/MCID. The + * tagging inaccuracy is bounded and acceptable for QoS. + */ + __this_cpu_write(cpu_srmcfg, thread_srmcfg); + csr_write(CSR_SRMCFG, thread_srmcfg); + } +} + +static __always_inline bool has_srmcfg(void) +{ + return riscv_has_extension_unlikely(RISCV_ISA_EXT_SSQOSID); +} + +#else /* ! CONFIG_RISCV_ISA_SSQOSID */ + +struct task_struct; +static __always_inline bool has_srmcfg(void) { return false; } +static inline void __switch_to_srmcfg(struct task_struct *next) { } + +#endif /* CONFIG_RISCV_ISA_SSQOSID */ +#endif /* _ASM_RISCV_QOS_H */ diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h index 0e71eb82f920..1c7ea53ec012 100644 --- a/arch/riscv/include/asm/switch_to.h +++ b/arch/riscv/include/asm/switch_to.h @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef CONFIG_FPU extern void __fstate_save(struct task_struct *save_to); @@ -119,6 +120,8 @@ do { \ __switch_to_fpu(__prev, __next); \ if (has_vector() || has_xtheadvector()) \ __switch_to_vector(__prev, __next); \ + if (has_srmcfg()) \ + __switch_to_srmcfg(__next); \ if (switch_to_should_flush_icache(__next)) \ local_flush_icache_all(); \ __switch_to_envcfg(__next); \ diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index cabb99cadfb6..ebe1c3588177 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -128,3 +128,5 @@ obj-$(CONFIG_ACPI_NUMA) += acpi_numa.o obj-$(CONFIG_GENERIC_CPU_VULNERABILITIES) += bugs.o obj-$(CONFIG_RISCV_USER_CFI) += usercfi.o + +obj-$(CONFIG_RISCV_ISA_SSQOSID) += qos.o diff --git a/arch/riscv/kernel/qos.c b/arch/riscv/kernel/qos.c new file mode 100644 index 000000000000..99925c0e93dd --- /dev/null +++ b/arch/riscv/kernel/qos.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * Cached value of srmcfg csr for each cpu. Seeded to U32_MAX so the next + * __switch_to_srmcfg() unconditionally writes the CSR. The encoding + * MCID << 16 | RCID with both fields well under 16 bits can never + * produce this sentinel. This covers early-boot context switches that + * happen before riscv_srmcfg_init() runs as an arch_initcall. + */ +DEFINE_PER_CPU(u32, cpu_srmcfg) = U32_MAX; + +/* default srmcfg value for each cpu, set via resctrl cpu assignment */ +DEFINE_PER_CPU(u32, cpu_srmcfg_default); + +/* + * Invalidate the per-CPU srmcfg cache. Used as both the cpuhp startup + * and teardown callback. U32_MAX is not a valid srmcfg value + * (MCID << 16 | RCID, both fields under 16 bits), so the next + * __switch_to_srmcfg() always writes the CSR. + * + * Ssqosid leaves the CSR implementation-defined across hart stop/start, + * so the cached value cannot be trusted after online. The startup + * callback runs at CPUHP_AP_ONLINE_DYN, before CPUHP_AP_ACTIVE makes + * the CPU schedulable, so the cache is invalidated before any normal + * task runs and the CSR is written on that task's first switch. + * The teardown callback is not relied on. Idle and per-CPU kthreads keep + * switching as the CPU goes down and overwrite the sentinel with the CPU + * default, so it does not survive the offline period. + */ +static int riscv_srmcfg_reset_cache(unsigned int cpu) +{ + per_cpu(cpu_srmcfg, cpu) = U32_MAX; + return 0; +} + +/* + * CPU PM notifier: invalidate the cached srmcfg on resume from a deep + * idle / suspend. Ssqosid leaves CSR_SRMCFG state across low-power + * transitions implementation-defined, and the boot CPU never goes + * through the cpuhp online callback during system suspend, so without + * this hook __switch_to_srmcfg() would skip the CSR write when the + * outgoing task happens to share its srmcfg with the pre-suspend cache. + */ +static int riscv_srmcfg_pm_notify(struct notifier_block *nb, + unsigned long action, void *unused) +{ + switch (action) { + case CPU_PM_EXIT: + case CPU_PM_ENTER_FAILED: + /* + * The CSR is implementation-defined across the low-power + * transition. Invalidate the cache and eagerly rewrite the + * CSR for the current task so it does not run mis-tagged + * until the next context switch. + */ + __this_cpu_write(cpu_srmcfg, U32_MAX); + __switch_to_srmcfg(current); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block riscv_srmcfg_pm_nb = { + .notifier_call = riscv_srmcfg_pm_notify, +}; + +static int __init riscv_srmcfg_init(void) +{ + int err; + + if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SSQOSID)) + return 0; + + /* + * cpuhp_setup_state() invokes the startup callback locally on every + * already-online CPU, so no separate seed loop is needed here. + */ + err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "riscv/srmcfg:online", + riscv_srmcfg_reset_cache, riscv_srmcfg_reset_cache); + if (err < 0) + pr_warn("srmcfg: cpuhp setup failed (%d), cache not invalidated on CPU online\n", + err); + + /* + * Register the PM notifier even if the cpuhp setup failed. It is + * independent of the cpuhp state and guards suspend/resume. + */ + cpu_pm_register_notifier(&riscv_srmcfg_pm_nb); + return 0; +} +arch_initcall(riscv_srmcfg_init); From abcdefbe49655c1b8b12445f73e6116b4f123db2 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 7 Aug 2026 19:24:32 -0600 Subject: [PATCH 28/39] riscv: further remove XIP After commit 9b3a2be84803 ("riscv: Remove support for XIP kernel"), something relatd with XIP are still there. Remove them to clean up the code. Signed-off-by: Jisheng Zhang Reviewed-by: Nam Cao Link: https://patch.msgid.link/20260805010049.13918-1-jszhang@kernel.org Signed-off-by: Paul Walmsley --- arch/riscv/Makefile | 4 +- arch/riscv/boot/.gitignore | 1 - arch/riscv/boot/Makefile | 3 +- arch/riscv/kernel/vmlinux-xip.lds.S | 143 ---------------------------- 4 files changed, 3 insertions(+), 148 deletions(-) delete mode 100644 arch/riscv/kernel/vmlinux-xip.lds.S diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 1363e5bef35c..07194525ce0a 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -172,12 +172,12 @@ vdso-install-$(CONFIG_MMU) += arch/riscv/kernel/vdso/vdso.so.dbg vdso-install-$(CONFIG_RISCV_USER_CFI) += arch/riscv/kernel/vdso_cfi/vdso-cfi.so.dbg vdso-install-$(CONFIG_COMPAT) += arch/riscv/kernel/compat_vdso/compat_vdso.so.dbg -BOOT_TARGETS := Image Image.gz Image.bz2 Image.lz4 Image.lzma Image.lzo Image.zst Image.xz loader loader.bin xipImage vmlinuz.efi +BOOT_TARGETS := Image Image.gz Image.bz2 Image.lz4 Image.lzma Image.lzo Image.zst Image.xz loader loader.bin vmlinuz.efi all: $(notdir $(KBUILD_IMAGE)) loader.bin: loader -Image.gz Image.bz2 Image.lz4 Image.lzma Image.lzo Image.zst Image.xz loader xipImage vmlinuz.efi: Image +Image.gz Image.bz2 Image.lz4 Image.lzma Image.lzo Image.zst Image.xz loader vmlinuz.efi: Image $(BOOT_TARGETS): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ diff --git a/arch/riscv/boot/.gitignore b/arch/riscv/boot/.gitignore index e1bc507e8cb2..5d123ceaa012 100644 --- a/arch/riscv/boot/.gitignore +++ b/arch/riscv/boot/.gitignore @@ -5,4 +5,3 @@ loader loader.lds loader.bin vmlinuz* -xipImage diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile index fcfbe3f814d6..4a2d75b7e42d 100644 --- a/arch/riscv/boot/Makefile +++ b/arch/riscv/boot/Makefile @@ -16,9 +16,8 @@ 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 xipImage +targets := Image Image.* loader loader.o loader.lds loader.bin $(obj)/Image: vmlinux FORCE $(call if_changed,objcopy) diff --git a/arch/riscv/kernel/vmlinux-xip.lds.S b/arch/riscv/kernel/vmlinux-xip.lds.S deleted file mode 100644 index a7611789bad5..000000000000 --- a/arch/riscv/kernel/vmlinux-xip.lds.S +++ /dev/null @@ -1,143 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2012 Regents of the University of California - * Copyright (C) 2017 SiFive - * Copyright (C) 2020 Vitaly Wool, Konsulko AB - */ - -#include -#define LOAD_OFFSET KERNEL_LINK_ADDR -/* No __ro_after_init data in the .rodata section - which will always be ro */ -#define RO_AFTER_INIT_DATA - -#include -#include -#include -#include -#include - -OUTPUT_ARCH(riscv) -ENTRY(_start) - -jiffies = jiffies_64; - -SECTIONS -{ - /* Beginning of code and text segment */ - . = LOAD_OFFSET; - _xiprom = .; - _start = .; - HEAD_TEXT_SECTION - INIT_TEXT_SECTION(PAGE_SIZE) - /* we have to discard exit text and such at runtime, not link time */ - __exittext_begin = .; - .exit.text : - { - EXIT_TEXT - } - __exittext_end = .; - - .text : { - _text = .; - _stext = .; - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - KPROBES_TEXT - ENTRY_TEXT - IRQENTRY_TEXT - SOFTIRQENTRY_TEXT - _etext = .; - } - RO_DATA(L1_CACHE_BYTES) - .srodata : { - *(.srodata*) - } - .init.rodata : { - INIT_SETUP(16) - INIT_CALLS - CON_INITCALL - INIT_RAM_FS - } - _exiprom = .; /* End of XIP ROM area */ - - -/* - * From this point, stuff is considered writable and will be copied to RAM - */ - __data_loc = ALIGN(PAGE_SIZE); /* location in file */ - . = ALIGN(SECTION_ALIGN); /* location in memory */ - -#undef LOAD_OFFSET -#define LOAD_OFFSET (KERNEL_LINK_ADDR + _sdata - __data_loc) - - _sdata = .; /* Start of data section */ - _data = .; - RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) - _edata = .; - __start_ro_after_init = .; - .data.ro_after_init : AT(ADDR(.data.ro_after_init) - LOAD_OFFSET) { - *(.data..ro_after_init) - } - __end_ro_after_init = .; - - . = ALIGN(PAGE_SIZE); - __init_begin = .; - .init.data : { - INIT_DATA - } - .exit.data : { - EXIT_DATA - } - . = ALIGN(8); - __soc_early_init_table : { - __soc_early_init_table_start = .; - KEEP(*(__soc_early_init_table)) - __soc_early_init_table_end = .; - } - __soc_builtin_dtb_table : { - __soc_builtin_dtb_table_start = .; - KEEP(*(__soc_builtin_dtb_table)) - __soc_builtin_dtb_table_end = .; - } - - __init_end = .; - - . = ALIGN(16); - .xip.traps : { - __xip_traps_start = .; - *(.xip.traps) - __xip_traps_end = .; - } - - . = ALIGN(PAGE_SIZE); - .sdata : { - __global_pointer$ = . + 0x800; - *(.sdata*) - *(.sbss*) - } - - BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0) - - PERCPU_SECTION(L1_CACHE_BYTES) - - .rel.dyn : AT(ADDR(.rel.dyn) - LOAD_OFFSET) { - *(.rel.dyn*) - } - - /* - * End of copied data. We need a dummy section to get its LMA. - * Also located before final ALIGN() as trailing padding is not stored - * in the resulting binary file and useless to copy. - */ - .data.endmark : AT(ADDR(.data.endmark) - LOAD_OFFSET) { } - _edata_loc = LOADADDR(.data.endmark); - - . = ALIGN(PAGE_SIZE); - _end = .; - - STABS_DEBUG - DWARF_DEBUG - - DISCARDS -} From 7e4cb63d61a7e0bef20f0d00e831c7fac06e4a1c Mon Sep 17 00:00:00 2001 From: Peixin Xie Date: Fri, 7 Aug 2026 19:24:32 -0600 Subject: [PATCH 29/39] riscv: acpi: Handle LPI architectural context loss flags Commit 4785aa802853 ("cpuidle, ACPI: Evaluate LPI arch_flags for broadcast timer") replaced the generic nonzero check for LPI architectural context loss flags with arch_get_idle_state_flags(). RISC-V does not implement the helper, so it falls back to the stub that returns 0. Consequently, CPUIDLE_FLAG_TIMER_STOP is not set when an LPI state loses the hart timer context, preventing cpuidle from using a broadcast timer for that state. Implement the RISC-V helper and map the hart timer context loss flag to CPUIDLE_FLAG_TIMER_STOP. Fixes: 4785aa802853 ("cpuidle, ACPI: Evaluate LPI arch_flags for broadcast timer") Cc: stable@vger.kernel.org Acked-by: Sudeep Holla Reviewed-by: Yixun Lan Reviewed-by: Sunil V L Reviewed-by: Huisong Li Signed-off-by: Peixin Xie Link: https://patch.msgid.link/20260803-riscv-acpi-lpi-timer-v3-1-520fa13732f5@linux.spacemit.com Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/acpi.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h index d59bd06347cc..980aa11d7741 100644 --- a/arch/riscv/include/asm/acpi.h +++ b/arch/riscv/include/asm/acpi.h @@ -12,6 +12,8 @@ #ifndef _ASM_ACPI_H #define _ASM_ACPI_H +#include + /* Basic configuration for ACPI */ #ifdef CONFIG_ACPI @@ -67,6 +69,23 @@ int acpi_get_riscv_isa(struct acpi_table_header *table, void acpi_get_cbo_block_size(struct acpi_table_header *table, u32 *cbom_size, u32 *cboz_size, u32 *cbop_size); + +/* + * RISC-V Functional Fixed Hardware Specification Version v1.0.1, + * Chapter 3.1.2, Table 4: Arch. Context Lost Flags + */ +#define RISCV_LPI_HART_TIMER_CTXT_LOST BIT(0) + +static inline unsigned int arch_get_idle_state_flags(u32 arch_flags) +{ + if (arch_flags & RISCV_LPI_HART_TIMER_CTXT_LOST) + return CPUIDLE_FLAG_TIMER_STOP; + + return 0; +} + +#define arch_get_idle_state_flags arch_get_idle_state_flags + #else static inline void acpi_init_rintc_map(void) { } static inline struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) From 76555252981eefa209ba2a16544c4f1704ca330b Mon Sep 17 00:00:00 2001 From: Vivian Wang Date: Fri, 7 Aug 2026 19:24:32 -0600 Subject: [PATCH 30/39] riscv: cmpxchg: Use .option arch for Zacas and Zabha Instead of adding these to -march globally, use .option arch to use instructions from these extensions only in code paths where we know they are available, like how it is done for most other extensions. TOOLCHAIN_HAS_{ZACAS,ZABHA} already depend on AS_HAS_OPTION_ARCH, so this is not a functionality regression even on older assemblers. Although the compiler is unlikely to generate atomics on its own accord, this aligns handling of Zacas and Zabha with most other extensions and improves consistency on how assembly code requiring extra extensions is written in kernel code. This is analogous to the use of __LSE_PREAMBLE or .arch_extension lse in arm64 code. Signed-off-by: Vivian Wang Reviewed-by: Jesse Taube Link: https://patch.msgid.link/20260717-riscv-no-zacas-zabha-in-march-v1-1-82b5b0799fb6@iscas.ac.cn Signed-off-by: Paul Walmsley --- arch/riscv/Makefile | 6 ------ arch/riscv/include/asm/cmpxchg.h | 14 +++++++++++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 07194525ce0a..44f5a439741a 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -75,12 +75,6 @@ else riscv-march-$(CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI) := $(riscv-march-y)_zicsr_zifencei endif -# Check if the toolchain supports Zacas -riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZACAS) := $(riscv-march-y)_zacas - -# Check if the toolchain supports Zabha -riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZABHA) := $(riscv-march-y)_zabha - KBUILD_BASE_ISA = -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64ima)fd([^v_]*)v?/\1\2/') export KBUILD_BASE_ISA diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h index 8712cf9c69dc..662e160b0522 100644 --- a/arch/riscv/include/asm/cmpxchg.h +++ b/arch/riscv/include/asm/cmpxchg.h @@ -23,7 +23,10 @@ riscv_has_extension_unlikely(RISCV_ISA_EXT_ZABHA)) { \ __asm__ __volatile__ ( \ prepend \ + " .option push\n" \ + " .option arch, +zabha\n" \ " amoswap" swap_sfx " %0, %z2, %1\n" \ + " .option pop\n" \ swap_append \ : "=&r" (r), "+A" (*(p)) \ : "rJ" (n) \ @@ -141,7 +144,10 @@ \ __asm__ __volatile__ ( \ cas_prepend \ + " .option push\n" \ + " .option arch, +zacas, +zabha\n" \ " amocas" cas_sfx " %0, %z2, %1\n" \ + " .option pop\n" \ cas_append \ : "+&r" (r), "+A" (*(p)) \ : "rJ" (n) \ @@ -188,7 +194,10 @@ \ __asm__ __volatile__ ( \ cas_prepend \ + " .option push\n" \ + " .option arch, +zacas\n" \ " amocas" cas_sfx " %0, %z2, %1\n" \ + " .option pop\n" \ cas_append \ : "+&r" (r), "+A" (*(p)) \ : "rJ" (n) \ @@ -340,7 +349,10 @@ union __u128_halves { register unsigned long t4 asm ("t4") = __ho.high; \ \ __asm__ __volatile__ ( \ - " amocas.q" cas_sfx " %0, %z3, %2" \ + " .option push\n" \ + " .option arch, +zacas\n" \ + " amocas.q" cas_sfx " %0, %z3, %2\n" \ + " .option pop\n" \ : "+&r" (t3), "+&r" (t4), "+A" (*(p)) \ : "rJ" (t1), "rJ" (t2) \ : "memory"); \ From e7d8ea6c6d1bc685a8943ffad2d3679be92d164f Mon Sep 17 00:00:00 2001 From: Rui Qi Date: Fri, 7 Aug 2026 19:24:33 -0600 Subject: [PATCH 31/39] riscv: kprobes: Prevent probes in breakpoint handlers The ftrace selftest multiple_kprobes.tc registers kprobe events on the first 256 text symbols from /proc/kallsyms. If handle_break() is selected as a probe target on RISC-V, the breakpoint exception path can trap again before it reaches the kprobe breakpoint handler. That recursively enters do_trap_break() and can make the system unresponsive. Mark handle_break() and its local probe dispatch helpers as nokprobe symbols so they are added to the kprobe blacklist, matching other low-level breakpoint exception paths. Signed-off-by: Rui Qi Reviewed-by: Nam Cao Link: https://patch.msgid.link/20260806043807.2583001-1-qirui.001@bytedance.com Signed-off-by: Paul Walmsley --- arch/riscv/kernel/traps.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index 8c62c771a656..f459f0c8aad2 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -270,6 +270,7 @@ static bool probe_single_step_handler(struct pt_regs *regs) return user ? uprobe_single_step_handler(regs) : kprobe_single_step_handler(regs); } +NOKPROBE_SYMBOL(probe_single_step_handler); static bool probe_breakpoint_handler(struct pt_regs *regs) { @@ -277,6 +278,7 @@ static bool probe_breakpoint_handler(struct pt_regs *regs) return user ? uprobe_breakpoint_handler(regs) : kprobe_breakpoint_handler(regs); } +NOKPROBE_SYMBOL(probe_breakpoint_handler); void handle_break(struct pt_regs *regs) { @@ -301,6 +303,7 @@ void handle_break(struct pt_regs *regs) else die(regs, "Kernel BUG"); } +NOKPROBE_SYMBOL(handle_break); asmlinkage __visible __trap_section void do_trap_break(struct pt_regs *regs) { From 0c5a9ab5192b8cc15fa7b32a1f747c70aaee51b0 Mon Sep 17 00:00:00 2001 From: Charlie Jenkins Date: Fri, 7 Aug 2026 19:24:33 -0600 Subject: [PATCH 32/39] riscv: Standardize extension capitalization The base extensions are often lowercase and were written as lowercase in hwcap, but other references to these extensions in the kernel are uppercase. Standardize the case to make it easier to handle macro expansion. Acked-by: Anup Patel Reviewed-by: Anup Patel Signed-off-by: Charlie Jenkins [andrew.jones: Apply KVM_ISA_EXT_ARR(), fixup all KVM use.] Signed-off-by: Andrew Jones Signed-off-by: Guodong Xu Link: https://patch.msgid.link/20260701-rva23u64-hwprobe-v2-v5-4-2c61f94a695a@gmail.com [pjw@kernel.org: fixed a checkpatch warning; added Andrew's username to his tag comments] Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/hwcap.h | 18 ++++++------ arch/riscv/include/asm/switch_to.h | 4 +-- arch/riscv/kernel/cpufeature.c | 45 +++++++++++++++--------------- arch/riscv/kernel/sys_hwprobe.c | 4 +-- arch/riscv/kvm/isa.c | 16 +++++------ arch/riscv/kvm/main.c | 2 +- arch/riscv/kvm/vcpu_fp.c | 20 ++++++------- arch/riscv/kvm/vcpu_onereg.c | 6 ++-- arch/riscv/kvm/vcpu_vector.c | 10 +++---- 9 files changed, 63 insertions(+), 62 deletions(-) diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index b656f5627f2e..c0cb576b134f 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -10,15 +10,15 @@ #include -#define RISCV_ISA_EXT_a ('a' - 'a') -#define RISCV_ISA_EXT_c ('c' - 'a') -#define RISCV_ISA_EXT_d ('d' - 'a') -#define RISCV_ISA_EXT_f ('f' - 'a') -#define RISCV_ISA_EXT_h ('h' - 'a') -#define RISCV_ISA_EXT_i ('i' - 'a') -#define RISCV_ISA_EXT_m ('m' - 'a') -#define RISCV_ISA_EXT_q ('q' - 'a') -#define RISCV_ISA_EXT_v ('v' - 'a') +#define RISCV_ISA_EXT_A ('a' - 'a') +#define RISCV_ISA_EXT_C ('c' - 'a') +#define RISCV_ISA_EXT_D ('d' - 'a') +#define RISCV_ISA_EXT_F ('f' - 'a') +#define RISCV_ISA_EXT_H ('h' - 'a') +#define RISCV_ISA_EXT_I ('i' - 'a') +#define RISCV_ISA_EXT_M ('m' - 'a') +#define RISCV_ISA_EXT_Q ('q' - 'a') +#define RISCV_ISA_EXT_V ('v' - 'a') /* * These macros represent the logical IDs of each multi-letter RISC-V ISA diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h index 1c7ea53ec012..04f10a949066 100644 --- a/arch/riscv/include/asm/switch_to.h +++ b/arch/riscv/include/asm/switch_to.h @@ -61,8 +61,8 @@ static inline void __switch_to_fpu(struct task_struct *prev, static __always_inline bool has_fpu(void) { - return riscv_has_extension_likely(RISCV_ISA_EXT_f) || - riscv_has_extension_likely(RISCV_ISA_EXT_d); + return riscv_has_extension_likely(RISCV_ISA_EXT_F) || + riscv_has_extension_likely(RISCV_ISA_EXT_D); } #else static __always_inline bool has_fpu(void) { return false; } diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 53f63f560349..ebe4a2593c40 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -84,7 +84,7 @@ EXPORT_SYMBOL_GPL(__riscv_isa_extension_available); static int riscv_ext_f_depends(const struct riscv_isa_ext_data *data, const unsigned long *isa_bitmap) { - if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_f)) + if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_F)) return 0; return -EPROBE_DEFER; @@ -146,7 +146,7 @@ static int riscv_ext_f_validate(const struct riscv_isa_ext_data *data, * Due to extension ordering, d is checked before f, so no deferral * is required. */ - if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_d)) { + if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_D)) { pr_warn_once("This kernel does not support systems with F but not D\n"); return -EINVAL; } @@ -189,7 +189,7 @@ static int riscv_ext_vector_float_validate(const struct riscv_isa_ext_data *data * Since this function validates vector only, and v/Zve* are probed * after f/d, there's no need for a deferral here. */ - if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_d)) + if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_D)) return -EINVAL; return 0; @@ -224,7 +224,7 @@ static int riscv_ext_zcd_validate(const struct riscv_isa_ext_data *data, const unsigned long *isa_bitmap) { if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZCA) && - __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_d)) + __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_D)) return 0; return -EPROBE_DEFER; @@ -237,7 +237,7 @@ static int riscv_ext_zcf_validate(const struct riscv_isa_ext_data *data, return -EINVAL; if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZCA) && - __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_f)) + __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_F)) return 0; return -EPROBE_DEFER; @@ -511,15 +511,16 @@ static const unsigned int riscv_c_exts[] = { * New entries to this struct should follow the ordering rules described above. */ const struct riscv_isa_ext_data riscv_isa_ext[] = { - __RISCV_ISA_EXT_DATA(i, RISCV_ISA_EXT_i), - __RISCV_ISA_EXT_DATA(m, RISCV_ISA_EXT_m), - __RISCV_ISA_EXT_SUPERSET(a, RISCV_ISA_EXT_a, riscv_a_exts), - __RISCV_ISA_EXT_DATA_VALIDATE(f, RISCV_ISA_EXT_f, riscv_ext_f_validate), - __RISCV_ISA_EXT_DATA_VALIDATE(d, RISCV_ISA_EXT_d, riscv_ext_d_validate), - __RISCV_ISA_EXT_DATA(q, RISCV_ISA_EXT_q), - __RISCV_ISA_EXT_SUPERSET(c, RISCV_ISA_EXT_c, riscv_c_exts), - __RISCV_ISA_EXT_SUPERSET_VALIDATE(v, RISCV_ISA_EXT_v, riscv_v_exts, riscv_ext_vector_float_validate), - __RISCV_ISA_EXT_DATA(h, RISCV_ISA_EXT_h), + __RISCV_ISA_EXT_DATA(i, RISCV_ISA_EXT_I), + __RISCV_ISA_EXT_DATA(m, RISCV_ISA_EXT_M), + __RISCV_ISA_EXT_SUPERSET(a, RISCV_ISA_EXT_A, riscv_a_exts), + __RISCV_ISA_EXT_DATA_VALIDATE(f, RISCV_ISA_EXT_F, riscv_ext_f_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(d, RISCV_ISA_EXT_D, riscv_ext_d_validate), + __RISCV_ISA_EXT_DATA(q, RISCV_ISA_EXT_Q), + __RISCV_ISA_EXT_SUPERSET(c, RISCV_ISA_EXT_C, riscv_c_exts), + __RISCV_ISA_EXT_SUPERSET_VALIDATE(v, RISCV_ISA_EXT_V, riscv_v_exts, + riscv_ext_vector_float_validate), + __RISCV_ISA_EXT_DATA(h, RISCV_ISA_EXT_H), __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicbom, RISCV_ISA_EXT_ZICBOM, riscv_xlinuxenvcfg_exts, riscv_ext_zicbom_validate), __RISCV_ISA_EXT_DATA_VALIDATE(zicbop, RISCV_ISA_EXT_ZICBOP, riscv_ext_zicbop_validate), __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicboz, RISCV_ISA_EXT_ZICBOZ, riscv_xlinuxenvcfg_exts, riscv_ext_zicboz_validate), @@ -925,7 +926,7 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap) * marchid. */ if (acpi_disabled && boot_vendorid == THEAD_VENDOR_ID && boot_archid == 0x0) - clear_bit(RISCV_ISA_EXT_v, source_isa); + clear_bit(RISCV_ISA_EXT_V, source_isa); riscv_resolve_isa(source_isa, isainfo->isa, &this_hwcap, isa2hwcap); @@ -1133,13 +1134,13 @@ void __init riscv_fill_hwcap(void) unsigned long isa2hwcap[RISCV_ISA_EXT_BASE] = {0}; int i, j; - isa2hwcap[RISCV_ISA_EXT_i] = COMPAT_HWCAP_ISA_I; - isa2hwcap[RISCV_ISA_EXT_m] = COMPAT_HWCAP_ISA_M; - isa2hwcap[RISCV_ISA_EXT_a] = COMPAT_HWCAP_ISA_A; - isa2hwcap[RISCV_ISA_EXT_f] = COMPAT_HWCAP_ISA_F; - isa2hwcap[RISCV_ISA_EXT_d] = COMPAT_HWCAP_ISA_D; - isa2hwcap[RISCV_ISA_EXT_c] = COMPAT_HWCAP_ISA_C; - isa2hwcap[RISCV_ISA_EXT_v] = COMPAT_HWCAP_ISA_V; + isa2hwcap[RISCV_ISA_EXT_I] = COMPAT_HWCAP_ISA_I; + isa2hwcap[RISCV_ISA_EXT_M] = COMPAT_HWCAP_ISA_M; + isa2hwcap[RISCV_ISA_EXT_A] = COMPAT_HWCAP_ISA_A; + isa2hwcap[RISCV_ISA_EXT_F] = COMPAT_HWCAP_ISA_F; + isa2hwcap[RISCV_ISA_EXT_D] = COMPAT_HWCAP_ISA_D; + isa2hwcap[RISCV_ISA_EXT_C] = COMPAT_HWCAP_ISA_C; + isa2hwcap[RISCV_ISA_EXT_V] = COMPAT_HWCAP_ISA_V; if (!acpi_disabled) { riscv_fill_hwcap_from_isa_string(isa2hwcap); diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c index c11d9e765372..5d6732641c57 100644 --- a/arch/riscv/kernel/sys_hwprobe.c +++ b/arch/riscv/kernel/sys_hwprobe.c @@ -85,10 +85,10 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair, if (has_fpu()) pair->value |= RISCV_HWPROBE_IMA_FD; - if (riscv_isa_extension_available(NULL, c)) + if (riscv_isa_extension_available(NULL, C)) pair->value |= RISCV_HWPROBE_IMA_C; - if (has_vector() && riscv_isa_extension_available(NULL, v)) + if (has_vector() && riscv_isa_extension_available(NULL, V)) pair->value |= RISCV_HWPROBE_IMA_V; /* diff --git a/arch/riscv/kvm/isa.c b/arch/riscv/kvm/isa.c index 1132d909cc25..94077117d113 100644 --- a/arch/riscv/kvm/isa.c +++ b/arch/riscv/kvm/isa.c @@ -17,14 +17,14 @@ /* Mapping between KVM ISA Extension ID & guest ISA extension ID */ static const unsigned long kvm_isa_ext_arr[] = { /* Single letter extensions (alphabetically sorted) */ - [KVM_RISCV_ISA_EXT_A] = RISCV_ISA_EXT_a, - [KVM_RISCV_ISA_EXT_C] = RISCV_ISA_EXT_c, - [KVM_RISCV_ISA_EXT_D] = RISCV_ISA_EXT_d, - [KVM_RISCV_ISA_EXT_F] = RISCV_ISA_EXT_f, - [KVM_RISCV_ISA_EXT_H] = RISCV_ISA_EXT_h, - [KVM_RISCV_ISA_EXT_I] = RISCV_ISA_EXT_i, - [KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m, - [KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v, + KVM_ISA_EXT_ARR(A), + KVM_ISA_EXT_ARR(C), + KVM_ISA_EXT_ARR(D), + KVM_ISA_EXT_ARR(F), + KVM_ISA_EXT_ARR(H), + KVM_ISA_EXT_ARR(I), + KVM_ISA_EXT_ARR(M), + KVM_ISA_EXT_ARR(V), /* Multi letter extensions (alphabetically sorted) */ KVM_ISA_EXT_ARR(SMNPM), KVM_ISA_EXT_ARR(SMSTATEEN), diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c index 0924c75100a2..0b8bf5f9eab1 100644 --- a/arch/riscv/kvm/main.c +++ b/arch/riscv/kvm/main.c @@ -85,7 +85,7 @@ static int __init riscv_kvm_init(void) char slist[64]; const char *str; - if (!riscv_isa_extension_available(NULL, h)) { + if (!riscv_isa_extension_available(NULL, H)) { kvm_info("hypervisor extension not available\n"); return -ENODEV; } diff --git a/arch/riscv/kvm/vcpu_fp.c b/arch/riscv/kvm/vcpu_fp.c index 6ad6df26a2fd..bb11e6757d34 100644 --- a/arch/riscv/kvm/vcpu_fp.c +++ b/arch/riscv/kvm/vcpu_fp.c @@ -21,8 +21,8 @@ void kvm_riscv_vcpu_fp_reset(struct kvm_vcpu *vcpu) struct kvm_cpu_context *cntx = &vcpu->arch.guest_context; cntx->sstatus &= ~SR_FS; - if (riscv_isa_extension_available(vcpu->arch.isa, f) || - riscv_isa_extension_available(vcpu->arch.isa, d)) + if (riscv_isa_extension_available(vcpu->arch.isa, F) || + riscv_isa_extension_available(vcpu->arch.isa, D)) cntx->sstatus |= SR_FS_INITIAL; else cntx->sstatus |= SR_FS_OFF; @@ -38,9 +38,9 @@ void kvm_riscv_vcpu_guest_fp_save(struct kvm_cpu_context *cntx, const unsigned long *isa) { if ((cntx->sstatus & SR_FS) == SR_FS_DIRTY) { - if (riscv_isa_extension_available(isa, d)) + if (riscv_isa_extension_available(isa, D)) __kvm_riscv_fp_d_save(cntx); - else if (riscv_isa_extension_available(isa, f)) + else if (riscv_isa_extension_available(isa, F)) __kvm_riscv_fp_f_save(cntx); kvm_riscv_vcpu_fp_clean(cntx); } @@ -50,9 +50,9 @@ void kvm_riscv_vcpu_guest_fp_restore(struct kvm_cpu_context *cntx, const unsigned long *isa) { if ((cntx->sstatus & SR_FS) != SR_FS_OFF) { - if (riscv_isa_extension_available(isa, d)) + if (riscv_isa_extension_available(isa, D)) __kvm_riscv_fp_d_restore(cntx); - else if (riscv_isa_extension_available(isa, f)) + else if (riscv_isa_extension_available(isa, F)) __kvm_riscv_fp_f_restore(cntx); kvm_riscv_vcpu_fp_clean(cntx); } @@ -89,7 +89,7 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu, void *reg_val; if ((rtype == KVM_REG_RISCV_FP_F) && - riscv_isa_extension_available(vcpu->arch.isa, f)) { + riscv_isa_extension_available(vcpu->arch.isa, F)) { if (KVM_REG_SIZE(reg->id) != sizeof(u32)) return -EINVAL; if (reg_num == KVM_REG_RISCV_FP_F_REG(fcsr)) @@ -102,7 +102,7 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu, } else return -ENOENT; } else if ((rtype == KVM_REG_RISCV_FP_D) && - riscv_isa_extension_available(vcpu->arch.isa, d)) { + riscv_isa_extension_available(vcpu->arch.isa, D)) { if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) { if (KVM_REG_SIZE(reg->id) != sizeof(u32)) return -EINVAL; @@ -138,7 +138,7 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu, void *reg_val; if ((rtype == KVM_REG_RISCV_FP_F) && - riscv_isa_extension_available(vcpu->arch.isa, f)) { + riscv_isa_extension_available(vcpu->arch.isa, F)) { if (KVM_REG_SIZE(reg->id) != sizeof(u32)) return -EINVAL; if (reg_num == KVM_REG_RISCV_FP_F_REG(fcsr)) @@ -151,7 +151,7 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu, } else return -ENOENT; } else if ((rtype == KVM_REG_RISCV_FP_D) && - riscv_isa_extension_available(vcpu->arch.isa, d)) { + riscv_isa_extension_available(vcpu->arch.isa, D)) { if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) { if (KVM_REG_SIZE(reg->id) != sizeof(u32)) return -EINVAL; diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c index 99b9107b1ac1..afcfdc79a145 100644 --- a/arch/riscv/kvm/vcpu_onereg.c +++ b/arch/riscv/kvm/vcpu_onereg.c @@ -748,7 +748,7 @@ static inline unsigned long num_fp_f_regs(const struct kvm_vcpu *vcpu) { const struct kvm_cpu_context *cntx = &vcpu->arch.guest_context; - if (riscv_isa_extension_available(vcpu->arch.isa, f)) + if (riscv_isa_extension_available(vcpu->arch.isa, F)) return sizeof(cntx->fp.f) / sizeof(u32); else return 0; @@ -777,7 +777,7 @@ static inline unsigned long num_fp_d_regs(const struct kvm_vcpu *vcpu) { const struct kvm_cpu_context *cntx = &vcpu->arch.guest_context; - if (riscv_isa_extension_available(vcpu->arch.isa, d)) + if (riscv_isa_extension_available(vcpu->arch.isa, D)) return sizeof(cntx->fp.d.f) / sizeof(u64) + 1; else return 0; @@ -856,7 +856,7 @@ static inline unsigned long num_sbi_regs(struct kvm_vcpu *vcpu) static inline unsigned long num_vector_regs(const struct kvm_vcpu *vcpu) { - if (!riscv_isa_extension_available(vcpu->arch.isa, v)) + if (!riscv_isa_extension_available(vcpu->arch.isa, V)) return 0; /* vstart, vl, vtype, vcsr, vlenb and 32 vector regs */ diff --git a/arch/riscv/kvm/vcpu_vector.c b/arch/riscv/kvm/vcpu_vector.c index 3708616e2c32..3c3183b39ae2 100644 --- a/arch/riscv/kvm/vcpu_vector.c +++ b/arch/riscv/kvm/vcpu_vector.c @@ -27,7 +27,7 @@ void kvm_riscv_vcpu_vector_reset(struct kvm_vcpu *vcpu) cntx->vector.vlenb = riscv_v_vsize / 32; - if (riscv_isa_extension_available(isa, v)) { + if (riscv_isa_extension_available(isa, V)) { cntx->sstatus |= SR_VS_INITIAL; WARN_ON(!cntx->vector.datap); memset(cntx->vector.datap, 0, riscv_v_vsize); @@ -46,7 +46,7 @@ void kvm_riscv_vcpu_guest_vector_save(struct kvm_cpu_context *cntx, unsigned long *isa) { if ((cntx->sstatus & SR_VS) == SR_VS_DIRTY) { - if (riscv_isa_extension_available(isa, v)) + if (riscv_isa_extension_available(isa, V)) __kvm_riscv_vector_save(cntx); kvm_riscv_vcpu_vector_clean(cntx); } @@ -56,7 +56,7 @@ void kvm_riscv_vcpu_guest_vector_restore(struct kvm_cpu_context *cntx, unsigned long *isa) { if ((cntx->sstatus & SR_VS) != SR_VS_OFF) { - if (riscv_isa_extension_available(isa, v)) + if (riscv_isa_extension_available(isa, V)) __kvm_riscv_vector_restore(cntx); kvm_riscv_vcpu_vector_clean(cntx); } @@ -164,7 +164,7 @@ int kvm_riscv_vcpu_get_reg_vector(struct kvm_vcpu *vcpu, void *reg_addr; int rc; - if (!riscv_isa_extension_available(isa, v)) + if (!riscv_isa_extension_available(isa, V)) return -ENOENT; rc = kvm_riscv_vcpu_vreg_addr(vcpu, reg_num, reg_size, ®_addr); @@ -190,7 +190,7 @@ int kvm_riscv_vcpu_set_reg_vector(struct kvm_vcpu *vcpu, void *reg_addr; int rc; - if (!riscv_isa_extension_available(isa, v)) + if (!riscv_isa_extension_available(isa, V)) return -ENOENT; if (reg_num == KVM_REG_RISCV_VECTOR_CSR_REG(vlenb)) { From fdef048705daa3d4ed1fa212ee071bcbdac02d80 Mon Sep 17 00:00:00 2001 From: Guodong Xu Date: Fri, 7 Aug 2026 19:24:33 -0600 Subject: [PATCH 33/39] riscv: cpufeature: Clarify ISA spec version for canonical order Specify that chapter 27 refers to version 20191213 of the RISC-V ISA Unprivileged Architecture. The chapter numbering differs across specification versions - for example, in version 20250508, the ISA Extension Naming Conventions is chapter 36, not chapter 27. Historical versions of the RISC-V specification can be found via Link [1]. Acked-by: Conor Dooley Link: https://riscv.org/specifications/ratified/ [1] Fixes: 99e2266f2460 ("RISC-V: clarify ISA string ordering rules in cpu.c") Signed-off-by: Guodong Xu Link: https://patch.msgid.link/20260125-supm-ext-id-v2-3-1e3b9714c860@riscstar.com Signed-off-by: Paul Walmsley --- arch/riscv/kernel/cpufeature.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index ebe4a2593c40..16488b33f238 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -473,7 +473,8 @@ static const unsigned int riscv_c_exts[] = { /* * The canonical order of ISA extension names in the ISA string is defined in - * chapter 27 of the unprivileged specification. + * Chapter 27 of the RISC-V Instruction Set Manual Volume I Unprivileged ISA + * (Document Version 20191213). * * Ordinarily, for in-kernel data structures, this order is unimportant but * isa_ext_arr defines the order of the ISA string in /proc/cpuinfo. From 3cd63bc30cda8651c50c9dd0551fac8a506a5f36 Mon Sep 17 00:00:00 2001 From: Jesse Taube Date: Fri, 7 Aug 2026 19:24:33 -0600 Subject: [PATCH 34/39] riscv: Add Zicclsm to cpufeature and hwprobe Zicclsm requires misaligned support for all regular load and store instructions, both scalar and vector, but not AMOs or other specialized forms of memory access, to main memory regions with both the cacheability and coherence PMAs, as defined in the profiles spec. Even though mandated, misaligned loads and stores might execute extremely slowly. Standard software distributions should assume their existence only for correctness, not for performance. Reviewed-by: Conor Dooley Reviewed-by: Andy Chiu Reviewed-by: Charlie Jenkins Tested-by: Charlie Jenkins Signed-off-by: Jesse Taube [andrew.jones: Rebased, rewrote doc text, minor commit message revisions] Signed-off-by: Andrew Jones Signed-off-by: Guodong Xu Link: https://patch.msgid.link/20260701-rva23u64-hwprobe-v2-v5-5-2c61f94a695a@gmail.com [pjw@kernel.org: updated to apply; added Andrew's username to his tag comments] Signed-off-by: Paul Walmsley --- Documentation/arch/riscv/hwprobe.rst | 4 ++++ arch/riscv/include/asm/hwcap.h | 1 + arch/riscv/include/uapi/asm/hwprobe.h | 1 + arch/riscv/kernel/cpufeature.c | 1 + arch/riscv/kernel/sys_hwprobe.c | 1 + 5 files changed, 8 insertions(+) diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst index d9928641deb9..49d9fb68632d 100644 --- a/Documentation/arch/riscv/hwprobe.rst +++ b/Documentation/arch/riscv/hwprobe.rst @@ -401,3 +401,7 @@ The following keys are defined: as defined in version 1.0 of the RISC-V Control-flow Integrity (CFI) extensions specification, ratified in commit 302a2d45c243 ("Update build-pdf.yml") of riscv-cfi. + + * :c:macro:`RISCV_HWPROBE_EXT_ZICCLSM`: The Zicclsm extension is supported, + as defined in the RISC-V Profiles specification starting from commit + b1d80660 ("Updated to ratified state.") diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index c0cb576b134f..1e80e634bb0f 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -118,6 +118,7 @@ #define RISCV_ISA_EXT_SSCCFG 109 #define RISCV_ISA_EXT_SMCDELEG 110 #define RISCV_ISA_EXT_SSQOSID 111 +#define RISCV_ISA_EXT_ZICCLSM 112 #define RISCV_ISA_EXT_XLINUXENVCFG 127 diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h index 9139edba0aec..6819df159c51 100644 --- a/arch/riscv/include/uapi/asm/hwprobe.h +++ b/arch/riscv/include/uapi/asm/hwprobe.h @@ -116,6 +116,7 @@ struct riscv_hwprobe { #define RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE 15 #define RISCV_HWPROBE_KEY_IMA_EXT_1 16 #define RISCV_HWPROBE_EXT_ZICFISS (1ULL << 0) +#define RISCV_HWPROBE_EXT_ZICCLSM (1ULL << 1) /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */ diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 16488b33f238..05e05f42fa93 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -525,6 +525,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicbom, RISCV_ISA_EXT_ZICBOM, riscv_xlinuxenvcfg_exts, riscv_ext_zicbom_validate), __RISCV_ISA_EXT_DATA_VALIDATE(zicbop, RISCV_ISA_EXT_ZICBOP, riscv_ext_zicbop_validate), __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicboz, RISCV_ISA_EXT_ZICBOZ, riscv_xlinuxenvcfg_exts, riscv_ext_zicboz_validate), + __RISCV_ISA_EXT_DATA(zicclsm, RISCV_ISA_EXT_ZICCLSM), __RISCV_ISA_EXT_DATA(ziccrse, RISCV_ISA_EXT_ZICCRSE), __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicfilp, RISCV_ISA_EXT_ZICFILP, riscv_xlinuxenvcfg_exts, riscv_cfilp_validate), diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c index 5d6732641c57..70dc1d6136c8 100644 --- a/arch/riscv/kernel/sys_hwprobe.c +++ b/arch/riscv/kernel/sys_hwprobe.c @@ -202,6 +202,7 @@ static void hwprobe_isa_ext1(struct riscv_hwprobe *pair, * in the hart_isa bitmap, are made. */ EXT_KEY(isainfo->isa, ZICFISS, pair->value, missing); + EXT_KEY(isainfo->isa, ZICCLSM, pair->value, missing); } /* Now turn off reporting features if any CPU is missing it. */ From f61959a3a8b5522eb43cf71f293e091417bbf11c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 7 Aug 2026 19:24:33 -0600 Subject: [PATCH 35/39] riscv: Add Ziccamoa, Ziccif, Ziccrse, and Za64rs to cpufeature and hwprobe Add Ziccamoa, Ziccif, and Za64rs to riscv_isa_ext[] so they can be parsed from devicetree/ACPI ISA strings. Ziccrse is already present in cpufeature; this patch only adds its hwprobe exposure. Expose all four extensions via hwprobe through new bits in RISCV_HWPROBE_KEY_IMA_EXT_1 (RISCV_HWPROBE_EXT_ZICCAMOA, _ZICCIF, _ZICCRSE, _ZA64RS), so userspace can probe each of these RVA23U64-mandatory extensions individually. Reviewed-by: Jesse Taube Signed-off-by: Andrew Jones Signed-off-by: Guodong Xu Link: https://patch.msgid.link/20260701-rva23u64-hwprobe-v2-v5-6-2c61f94a695a@gmail.com [pjw@kernel.org: updated to apply] Signed-off-by: Paul Walmsley --- Documentation/arch/riscv/hwprobe.rst | 16 ++++++++++++++++ arch/riscv/include/asm/hwcap.h | 3 +++ arch/riscv/include/uapi/asm/hwprobe.h | 4 ++++ arch/riscv/kernel/cpufeature.c | 3 +++ arch/riscv/kernel/sys_hwprobe.c | 4 ++++ 5 files changed, 30 insertions(+) diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst index 49d9fb68632d..893e1a1215d2 100644 --- a/Documentation/arch/riscv/hwprobe.rst +++ b/Documentation/arch/riscv/hwprobe.rst @@ -405,3 +405,19 @@ The following keys are defined: * :c:macro:`RISCV_HWPROBE_EXT_ZICCLSM`: The Zicclsm extension is supported, as defined in the RISC-V Profiles specification starting from commit b1d80660 ("Updated to ratified state.") + + * :c:macro:`RISCV_HWPROBE_EXT_ZICCAMOA`: The Ziccamoa extension is supported, + as defined in the RISC-V Profiles specification starting from commit + b1d80660 ("Updated to ratified state.") + + * :c:macro:`RISCV_HWPROBE_EXT_ZICCIF`: The Ziccif extension is supported, + as defined in the RISC-V Profiles specification starting from commit + b1d80660 ("Updated to ratified state.") + + * :c:macro:`RISCV_HWPROBE_EXT_ZICCRSE`: The Ziccrse extension is supported, + as defined in the RISC-V Profiles specification starting from commit + b1d80660 ("Updated to ratified state.") + + * :c:macro:`RISCV_HWPROBE_EXT_ZA64RS`: The Za64rs extension is supported, + as defined in the RISC-V Profiles specification starting from commit + b1d80660 ("Updated to ratified state.") diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index 1e80e634bb0f..f8db798b2654 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -119,6 +119,9 @@ #define RISCV_ISA_EXT_SMCDELEG 110 #define RISCV_ISA_EXT_SSQOSID 111 #define RISCV_ISA_EXT_ZICCLSM 112 +#define RISCV_ISA_EXT_ZICCAMOA 113 +#define RISCV_ISA_EXT_ZICCIF 114 +#define RISCV_ISA_EXT_ZA64RS 115 #define RISCV_ISA_EXT_XLINUXENVCFG 127 diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h index 6819df159c51..58d1e86e47ae 100644 --- a/arch/riscv/include/uapi/asm/hwprobe.h +++ b/arch/riscv/include/uapi/asm/hwprobe.h @@ -117,6 +117,10 @@ struct riscv_hwprobe { #define RISCV_HWPROBE_KEY_IMA_EXT_1 16 #define RISCV_HWPROBE_EXT_ZICFISS (1ULL << 0) #define RISCV_HWPROBE_EXT_ZICCLSM (1ULL << 1) +#define RISCV_HWPROBE_EXT_ZICCAMOA (1ULL << 2) +#define RISCV_HWPROBE_EXT_ZICCIF (1ULL << 3) +#define RISCV_HWPROBE_EXT_ZICCRSE (1ULL << 4) +#define RISCV_HWPROBE_EXT_ZA64RS (1ULL << 5) /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */ diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 05e05f42fa93..d2ec96843456 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -525,6 +525,8 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicbom, RISCV_ISA_EXT_ZICBOM, riscv_xlinuxenvcfg_exts, riscv_ext_zicbom_validate), __RISCV_ISA_EXT_DATA_VALIDATE(zicbop, RISCV_ISA_EXT_ZICBOP, riscv_ext_zicbop_validate), __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicboz, RISCV_ISA_EXT_ZICBOZ, riscv_xlinuxenvcfg_exts, riscv_ext_zicboz_validate), + __RISCV_ISA_EXT_DATA(ziccamoa, RISCV_ISA_EXT_ZICCAMOA), + __RISCV_ISA_EXT_DATA(ziccif, RISCV_ISA_EXT_ZICCIF), __RISCV_ISA_EXT_DATA(zicclsm, RISCV_ISA_EXT_ZICCLSM), __RISCV_ISA_EXT_DATA(ziccrse, RISCV_ISA_EXT_ZICCRSE), __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicfilp, RISCV_ISA_EXT_ZICFILP, riscv_xlinuxenvcfg_exts, @@ -539,6 +541,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE), __RISCV_ISA_EXT_DATA(zihpm, RISCV_ISA_EXT_ZIHPM), __RISCV_ISA_EXT_DATA(zimop, RISCV_ISA_EXT_ZIMOP), + __RISCV_ISA_EXT_DATA(za64rs, RISCV_ISA_EXT_ZA64RS), __RISCV_ISA_EXT_DATA(zaamo, RISCV_ISA_EXT_ZAAMO), __RISCV_ISA_EXT_DATA(zabha, RISCV_ISA_EXT_ZABHA), __RISCV_ISA_EXT_DATA(zacas, RISCV_ISA_EXT_ZACAS), diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c index 70dc1d6136c8..bd6ca7d769da 100644 --- a/arch/riscv/kernel/sys_hwprobe.c +++ b/arch/riscv/kernel/sys_hwprobe.c @@ -203,6 +203,10 @@ static void hwprobe_isa_ext1(struct riscv_hwprobe *pair, */ EXT_KEY(isainfo->isa, ZICFISS, pair->value, missing); EXT_KEY(isainfo->isa, ZICCLSM, pair->value, missing); + EXT_KEY(isainfo->isa, ZICCAMOA, pair->value, missing); + EXT_KEY(isainfo->isa, ZICCIF, pair->value, missing); + EXT_KEY(isainfo->isa, ZICCRSE, pair->value, missing); + EXT_KEY(isainfo->isa, ZA64RS, pair->value, missing); } /* Now turn off reporting features if any CPU is missing it. */ From 7f2a7bbcd992735a8ef0b042d8ce36cb5f7698ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Fri, 7 Aug 2026 19:24:33 -0600 Subject: [PATCH 36/39] riscv: vdso: Add symbols for the alternative section boundaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the alternative sections are extracted from the vDSO binaries at runtime. This has runtime overhead and also doesn't work for the compat vDSO. Extract the offsets of the alternative section during the build with the existing symbol extraction machinery. Also add dummy symbols as fallback. Signed-off-by: Thomas Weißschuh Reviewed-by: Nam Cao Link: https://patch.msgid.link/20260630-riscv-vdso32-alternative-v1-1-a32fd89b7b1c@linutronix.de Signed-off-by: Paul Walmsley --- arch/riscv/include/asm/vdso.h | 6 ++++++ arch/riscv/kernel/vdso/vdso.lds.S | 2 ++ 2 files changed, 8 insertions(+) diff --git a/arch/riscv/include/asm/vdso.h b/arch/riscv/include/asm/vdso.h index f7998d9ad9b2..0259bbc98e93 100644 --- a/arch/riscv/include/asm/vdso.h +++ b/arch/riscv/include/asm/vdso.h @@ -19,10 +19,14 @@ #ifdef CONFIG_MMU #include +#else +extern size_t __vdso_alternatives_start_offset, __vdso_alternatives_end_offset; #endif #ifdef CONFIG_RISCV_USER_CFI #include +#else +extern size_t __vdso_alternatives_start_cfi_offset, __vdso_alternatives_end_cfi_offset; #endif #ifdef CONFIG_RISCV_USER_CFI @@ -41,6 +45,8 @@ #define COMPAT_VDSO_SYMBOL(base, name) \ (void __user *)((unsigned long)(base) + compat__vdso_##name##_offset) +#else +extern size_t compat__vdso_alternatives_start_offset, compat__vdso_alternatives_end_offset; #endif /* CONFIG_COMPAT */ extern char vdso_start[], vdso_end[]; diff --git a/arch/riscv/kernel/vdso/vdso.lds.S b/arch/riscv/kernel/vdso/vdso.lds.S index c29ef12a63bb..5e9424df932b 100644 --- a/arch/riscv/kernel/vdso/vdso.lds.S +++ b/arch/riscv/kernel/vdso/vdso.lds.S @@ -45,9 +45,11 @@ SECTIONS .text : { *(.text .text.*) } :text . = ALIGN(4); + __vdso_alternatives_start = .; .alternative : { *(.alternative) } + __vdso_alternatives_end = .; } /* From 63aecaba41a4b2593697f208e91bf542248ec4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Fri, 7 Aug 2026 19:24:33 -0600 Subject: [PATCH 37/39] riscv: alternative: Use the statically extracted vDSO section offsets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the alternative sections are extracted from the vDSO binaries at runtime. This has runtime overhead and also doesn't work for the compat vDSO. Use the offsets generated during the build instead, fixing both issues. Signed-off-by: Thomas Weißschuh Reviewed-by: Nam Cao Link: https://patch.msgid.link/20260630-riscv-vdso32-alternative-v1-2-a32fd89b7b1c@linutronix.de Signed-off-by: Paul Walmsley --- arch/riscv/kernel/alternative.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c index 104dc0862c5c..6aba169fb213 100644 --- a/arch/riscv/kernel/alternative.c +++ b/arch/riscv/kernel/alternative.c @@ -173,24 +173,14 @@ static void __init_or_module _apply_alternatives(struct alt_entry *begin, stage); } -static void __init apply_vdso_alternatives(void *start) +static __always_inline +void __init apply_vdso_alternatives(void *base, size_t alternatives_begin, size_t alternatives_end) { - const Elf_Ehdr *hdr; - const Elf_Shdr *shdr; - const Elf_Shdr *alt; - struct alt_entry *begin, *end; - - hdr = (Elf_Ehdr *)start; - shdr = (void *)hdr + hdr->e_shoff; - alt = find_section(hdr, shdr, ".alternative"); - if (!alt) + if (alternatives_begin == alternatives_end) return; - begin = (void *)hdr + alt->sh_offset, - end = (void *)hdr + alt->sh_offset + alt->sh_size, - - _apply_alternatives((struct alt_entry *)begin, - (struct alt_entry *)end, + _apply_alternatives(base + alternatives_begin, + base + alternatives_end, RISCV_ALTERNATIVES_BOOT); } @@ -204,10 +194,14 @@ void __init apply_boot_alternatives(void) RISCV_ALTERNATIVES_BOOT); if (IS_ENABLED(CONFIG_MMU)) - apply_vdso_alternatives(vdso_start); + apply_vdso_alternatives(vdso_start, + __vdso_alternatives_start_offset, + __vdso_alternatives_end_offset); if (IS_ENABLED(CONFIG_RISCV_USER_CFI)) - apply_vdso_alternatives(vdso_cfi_start); + apply_vdso_alternatives(vdso_cfi_start, + __vdso_alternatives_start_cfi_offset, + __vdso_alternatives_end_cfi_offset); } /* From 42cd1e1fc8995ec7ed5cc61957fc503eb065e0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Fri, 7 Aug 2026 19:24:34 -0600 Subject: [PATCH 38/39] riscv: alternative: Also patch the compat vDSO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vDSO for compat processes can also contain alternative entries. Patch those, too. Signed-off-by: Thomas Weißschuh Reviewed-by: Nam Cao Link: https://patch.msgid.link/20260630-riscv-vdso32-alternative-v1-3-a32fd89b7b1c@linutronix.de Signed-off-by: Paul Walmsley --- arch/riscv/kernel/alternative.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c index 6aba169fb213..c0c9306022c5 100644 --- a/arch/riscv/kernel/alternative.c +++ b/arch/riscv/kernel/alternative.c @@ -202,6 +202,11 @@ void __init apply_boot_alternatives(void) apply_vdso_alternatives(vdso_cfi_start, __vdso_alternatives_start_cfi_offset, __vdso_alternatives_end_cfi_offset); + + if (IS_ENABLED(CONFIG_COMPAT)) + apply_vdso_alternatives(compat_vdso_start, + compat__vdso_alternatives_start_offset, + compat__vdso_alternatives_end_offset); } /* From 8da45c93dfa98f25b148512d92ecfa75d027a5cc Mon Sep 17 00:00:00 2001 From: Jesse Taube Date: Fri, 7 Aug 2026 19:24:34 -0600 Subject: [PATCH 39/39] RISC-V: hwprobe: Use BIT macro to avoid warnings In uapi/asm/hwprobe.h file, (1 << N) is used to define the bit field which causes checkpatch to warn. Use _BITUL(N) and _BITULL(N) to avoid these warnings. Signed-off-by: Jesse Taube Link: https://patch.msgid.link/20260805153346.1036988-1-jtaubepe@redhat.com [pjw@kernel.org: updated to apply and to cover new extensions] Signed-off-by: Paul Walmsley --- arch/riscv/include/uapi/asm/hwprobe.h | 157 +++++++++++++------------- 1 file changed, 79 insertions(+), 78 deletions(-) diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h index 58d1e86e47ae..e6a394fbe7fc 100644 --- a/arch/riscv/include/uapi/asm/hwprobe.h +++ b/arch/riscv/include/uapi/asm/hwprobe.h @@ -7,6 +7,7 @@ #define _UAPI_ASM_HWPROBE_H #include +#include /* * Interface for probing hardware capabilities from userspace, see @@ -21,80 +22,80 @@ struct riscv_hwprobe { #define RISCV_HWPROBE_KEY_MARCHID 1 #define RISCV_HWPROBE_KEY_MIMPID 2 #define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3 -#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0) +#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA _BITULL(0) #define RISCV_HWPROBE_KEY_IMA_EXT_0 4 -#define RISCV_HWPROBE_IMA_FD (1 << 0) -#define RISCV_HWPROBE_IMA_C (1 << 1) -#define RISCV_HWPROBE_IMA_V (1 << 2) -#define RISCV_HWPROBE_EXT_ZBA (1 << 3) -#define RISCV_HWPROBE_EXT_ZBB (1 << 4) -#define RISCV_HWPROBE_EXT_ZBS (1 << 5) -#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6) -#define RISCV_HWPROBE_EXT_ZBC (1 << 7) -#define RISCV_HWPROBE_EXT_ZBKB (1 << 8) -#define RISCV_HWPROBE_EXT_ZBKC (1 << 9) -#define RISCV_HWPROBE_EXT_ZBKX (1 << 10) -#define RISCV_HWPROBE_EXT_ZKND (1 << 11) -#define RISCV_HWPROBE_EXT_ZKNE (1 << 12) -#define RISCV_HWPROBE_EXT_ZKNH (1 << 13) -#define RISCV_HWPROBE_EXT_ZKSED (1 << 14) -#define RISCV_HWPROBE_EXT_ZKSH (1 << 15) -#define RISCV_HWPROBE_EXT_ZKT (1 << 16) -#define RISCV_HWPROBE_EXT_ZVBB (1 << 17) -#define RISCV_HWPROBE_EXT_ZVBC (1 << 18) -#define RISCV_HWPROBE_EXT_ZVKB (1 << 19) -#define RISCV_HWPROBE_EXT_ZVKG (1 << 20) -#define RISCV_HWPROBE_EXT_ZVKNED (1 << 21) -#define RISCV_HWPROBE_EXT_ZVKNHA (1 << 22) -#define RISCV_HWPROBE_EXT_ZVKNHB (1 << 23) -#define RISCV_HWPROBE_EXT_ZVKSED (1 << 24) -#define RISCV_HWPROBE_EXT_ZVKSH (1 << 25) -#define RISCV_HWPROBE_EXT_ZVKT (1 << 26) -#define RISCV_HWPROBE_EXT_ZFH (1 << 27) -#define RISCV_HWPROBE_EXT_ZFHMIN (1 << 28) -#define RISCV_HWPROBE_EXT_ZIHINTNTL (1 << 29) -#define RISCV_HWPROBE_EXT_ZVFH (1 << 30) -#define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31) -#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32) -#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33) -#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34) -#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35) -#define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36) -#define RISCV_HWPROBE_EXT_ZVE32X (1ULL << 37) -#define RISCV_HWPROBE_EXT_ZVE32F (1ULL << 38) -#define RISCV_HWPROBE_EXT_ZVE64X (1ULL << 39) -#define RISCV_HWPROBE_EXT_ZVE64F (1ULL << 40) -#define RISCV_HWPROBE_EXT_ZVE64D (1ULL << 41) -#define RISCV_HWPROBE_EXT_ZIMOP (1ULL << 42) -#define RISCV_HWPROBE_EXT_ZCA (1ULL << 43) -#define RISCV_HWPROBE_EXT_ZCB (1ULL << 44) -#define RISCV_HWPROBE_EXT_ZCD (1ULL << 45) -#define RISCV_HWPROBE_EXT_ZCF (1ULL << 46) -#define RISCV_HWPROBE_EXT_ZCMOP (1ULL << 47) -#define RISCV_HWPROBE_EXT_ZAWRS (1ULL << 48) -#define RISCV_HWPROBE_EXT_SUPM (1ULL << 49) -#define RISCV_HWPROBE_EXT_ZICNTR (1ULL << 50) -#define RISCV_HWPROBE_EXT_ZIHPM (1ULL << 51) -#define RISCV_HWPROBE_EXT_ZFBFMIN (1ULL << 52) -#define RISCV_HWPROBE_EXT_ZVFBFMIN (1ULL << 53) -#define RISCV_HWPROBE_EXT_ZVFBFWMA (1ULL << 54) -#define RISCV_HWPROBE_EXT_ZICBOM (1ULL << 55) -#define RISCV_HWPROBE_EXT_ZAAMO (1ULL << 56) -#define RISCV_HWPROBE_EXT_ZALRSC (1ULL << 57) -#define RISCV_HWPROBE_EXT_ZABHA (1ULL << 58) -#define RISCV_HWPROBE_EXT_ZALASR (1ULL << 59) -#define RISCV_HWPROBE_EXT_ZICBOP (1ULL << 60) -#define RISCV_HWPROBE_EXT_ZILSD (1ULL << 61) -#define RISCV_HWPROBE_EXT_ZCLSD (1ULL << 62) -#define RISCV_HWPROBE_EXT_ZICFILP (1ULL << 63) +#define RISCV_HWPROBE_IMA_FD _BITULL(0) +#define RISCV_HWPROBE_IMA_C _BITULL(1) +#define RISCV_HWPROBE_IMA_V _BITULL(2) +#define RISCV_HWPROBE_EXT_ZBA _BITULL(3) +#define RISCV_HWPROBE_EXT_ZBB _BITULL(4) +#define RISCV_HWPROBE_EXT_ZBS _BITULL(5) +#define RISCV_HWPROBE_EXT_ZICBOZ _BITULL(6) +#define RISCV_HWPROBE_EXT_ZBC _BITULL(7) +#define RISCV_HWPROBE_EXT_ZBKB _BITULL(8) +#define RISCV_HWPROBE_EXT_ZBKC _BITULL(9) +#define RISCV_HWPROBE_EXT_ZBKX _BITULL(10) +#define RISCV_HWPROBE_EXT_ZKND _BITULL(11) +#define RISCV_HWPROBE_EXT_ZKNE _BITULL(12) +#define RISCV_HWPROBE_EXT_ZKNH _BITULL(13) +#define RISCV_HWPROBE_EXT_ZKSED _BITULL(14) +#define RISCV_HWPROBE_EXT_ZKSH _BITULL(15) +#define RISCV_HWPROBE_EXT_ZKT _BITULL(16) +#define RISCV_HWPROBE_EXT_ZVBB _BITULL(17) +#define RISCV_HWPROBE_EXT_ZVBC _BITULL(18) +#define RISCV_HWPROBE_EXT_ZVKB _BITULL(19) +#define RISCV_HWPROBE_EXT_ZVKG _BITULL(20) +#define RISCV_HWPROBE_EXT_ZVKNED _BITULL(21) +#define RISCV_HWPROBE_EXT_ZVKNHA _BITULL(22) +#define RISCV_HWPROBE_EXT_ZVKNHB _BITULL(23) +#define RISCV_HWPROBE_EXT_ZVKSED _BITULL(24) +#define RISCV_HWPROBE_EXT_ZVKSH _BITULL(25) +#define RISCV_HWPROBE_EXT_ZVKT _BITULL(26) +#define RISCV_HWPROBE_EXT_ZFH _BITULL(27) +#define RISCV_HWPROBE_EXT_ZFHMIN _BITULL(28) +#define RISCV_HWPROBE_EXT_ZIHINTNTL _BITULL(29) +#define RISCV_HWPROBE_EXT_ZVFH _BITULL(30) +#define RISCV_HWPROBE_EXT_ZVFHMIN _BITULL(31) +#define RISCV_HWPROBE_EXT_ZFA _BITULL(32) +#define RISCV_HWPROBE_EXT_ZTSO _BITULL(33) +#define RISCV_HWPROBE_EXT_ZACAS _BITULL(34) +#define RISCV_HWPROBE_EXT_ZICOND _BITULL(35) +#define RISCV_HWPROBE_EXT_ZIHINTPAUSE _BITULL(36) +#define RISCV_HWPROBE_EXT_ZVE32X _BITULL(37) +#define RISCV_HWPROBE_EXT_ZVE32F _BITULL(38) +#define RISCV_HWPROBE_EXT_ZVE64X _BITULL(39) +#define RISCV_HWPROBE_EXT_ZVE64F _BITULL(40) +#define RISCV_HWPROBE_EXT_ZVE64D _BITULL(41) +#define RISCV_HWPROBE_EXT_ZIMOP _BITULL(42) +#define RISCV_HWPROBE_EXT_ZCA _BITULL(43) +#define RISCV_HWPROBE_EXT_ZCB _BITULL(44) +#define RISCV_HWPROBE_EXT_ZCD _BITULL(45) +#define RISCV_HWPROBE_EXT_ZCF _BITULL(46) +#define RISCV_HWPROBE_EXT_ZCMOP _BITULL(47) +#define RISCV_HWPROBE_EXT_ZAWRS _BITULL(48) +#define RISCV_HWPROBE_EXT_SUPM _BITULL(49) +#define RISCV_HWPROBE_EXT_ZICNTR _BITULL(50) +#define RISCV_HWPROBE_EXT_ZIHPM _BITULL(51) +#define RISCV_HWPROBE_EXT_ZFBFMIN _BITULL(52) +#define RISCV_HWPROBE_EXT_ZVFBFMIN _BITULL(53) +#define RISCV_HWPROBE_EXT_ZVFBFWMA _BITULL(54) +#define RISCV_HWPROBE_EXT_ZICBOM _BITULL(55) +#define RISCV_HWPROBE_EXT_ZAAMO _BITULL(56) +#define RISCV_HWPROBE_EXT_ZALRSC _BITULL(57) +#define RISCV_HWPROBE_EXT_ZABHA _BITULL(58) +#define RISCV_HWPROBE_EXT_ZALASR _BITULL(59) +#define RISCV_HWPROBE_EXT_ZICBOP _BITULL(60) +#define RISCV_HWPROBE_EXT_ZILSD _BITULL(61) +#define RISCV_HWPROBE_EXT_ZCLSD _BITULL(62) +#define RISCV_HWPROBE_EXT_ZICFILP _BITULL(63) #define RISCV_HWPROBE_KEY_CPUPERF_0 5 -#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) -#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0) -#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0) -#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0) -#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0) -#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0) +#define RISCV_HWPROBE_MISALIGNED_UNKNOWN 0 +#define RISCV_HWPROBE_MISALIGNED_EMULATED 1 +#define RISCV_HWPROBE_MISALIGNED_SLOW 2 +#define RISCV_HWPROBE_MISALIGNED_FAST 3 +#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED 4 +#define RISCV_HWPROBE_MISALIGNED_MASK 7 #define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6 #define RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS 7 #define RISCV_HWPROBE_KEY_TIME_CSR_FREQ 8 @@ -115,16 +116,16 @@ struct riscv_hwprobe { #define RISCV_HWPROBE_KEY_VENDOR_EXT_MIPS_0 14 #define RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE 15 #define RISCV_HWPROBE_KEY_IMA_EXT_1 16 -#define RISCV_HWPROBE_EXT_ZICFISS (1ULL << 0) -#define RISCV_HWPROBE_EXT_ZICCLSM (1ULL << 1) -#define RISCV_HWPROBE_EXT_ZICCAMOA (1ULL << 2) -#define RISCV_HWPROBE_EXT_ZICCIF (1ULL << 3) -#define RISCV_HWPROBE_EXT_ZICCRSE (1ULL << 4) -#define RISCV_HWPROBE_EXT_ZA64RS (1ULL << 5) +#define RISCV_HWPROBE_EXT_ZICFISS _BITULL(0) +#define RISCV_HWPROBE_EXT_ZICCLSM _BITULL(1) +#define RISCV_HWPROBE_EXT_ZICCAMOA _BITULL(2) +#define RISCV_HWPROBE_EXT_ZICCIF _BITULL(3) +#define RISCV_HWPROBE_EXT_ZICCRSE _BITULL(4) +#define RISCV_HWPROBE_EXT_ZA64RS _BITULL(5) /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */ /* Flags */ -#define RISCV_HWPROBE_WHICH_CPUS (1 << 0) +#define RISCV_HWPROBE_WHICH_CPUS _BITUL(0) #endif