Merge tag 'riscv-for-linus-7.2-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux

Pull RISC-V updates from Paul Walmsley:

 - Prevent get_free_mem_region() from returning regions that are
   unmappable in certain circumstances by defining
   DIRECT_MAP_PHYSMEM_END for RISC-V

 - Fix an early boot problem with kexec_file when the amount of
   installed physical memory installed on the system exceeds the direct
   map size, which is possible in certain RISC-V virtual memory modes

 - Unconditionally sfence.vma in the new vmalloc area handling code in
   the page fault handler, since even the presence of Svvptc doesn't
   guarantee that the CPU won't immediately fault again after the
   exception handler completes and subsequently crash

 - Fix ftrace_graph_ret_addr() to use the correct task pointer (aligning
   with what other architectures do)

 - Fix the misaligned access performance checking code in cases when
   performance is specified on the kernel command line and when CPUs
   have been brought offline and back online

 - Get rid of a bogus address offset in the non-frame-pointer version of
   walk_stackframe(), aligning it with the frame pointer-based code

 - Fix a RISC-V kfence issue causing bogus use-after-free warnings

 - Add ARCH_HAS_CC_CAN_LINK for RISC-V, which needs different compiler
   command line flags than other architectures

 - Implement _THIS_IP_ using RISC-V-specific assembly, which seems to be
   less brittle (from a compiler point of view) than taking the address
   of a label

 - Reduce kernel startup overhead by defining
   HAVE_BUILDTIME_MCOUNT_SORT, since arch/riscv meets all the
   requirements

 - Patch the CFI vDSO during alternatives processing, not only the
   standard vDSO

 - Fix a potential memory leak in the cacheinfo code

 - Clean up kernel/setup.c:add_resource() to pass along the return value
   from insert_resource() and to improve the display of resource ranges

 - Clean up our purgatory.[ch] by aligning our purgatory() prototype to
   what's in arch/x86, and by cleaning up verify_sha256_digest()

 - Clean up cpu_is_stopped() to align its function a little more closely
   to its name

 - Replace some unbounded string function usage in get_early_cmdline()
   and the ptdump code with strscpy()

 - Replace sprintf() with sysfs_emit() in cpu_show_ghostwrite() for
   safer bounds checking

 - Standardize how compiler output flags are specified in the RISC-V
   kselftests, aligning them with what other architectures do

 - Use the Linux-generic cmp_int() macro in place of an open-coded
   "cmp_3way()" macro in kernel/module-sections.c

 - Panic early in boot if IRQ handler stacks can't be allocated rather
   than pretending to continue normally

 - Add support for Eswin SoCs in the RISC-V defconfig

 - Remove some unnecessary conditionals in sbi_hsm_hart_{start,stop}()

 - Clean up some Kconfig infelicities found by Kconfirm

 - Replace an open-coded version of min() in the kexec_elf code with
   the standard min() function

* tag 'riscv-for-linus-7.2-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (36 commits)
  riscv: traps_misaligned: Avoid redundant unaligned access speed probe
  riscv: misaligned: Fix fast_unaligned_access_speed_key init
  riscv: also select ARCH_KEEP_MEMBLOCK if kexec is selected
  riscv: alternative: Also patch the CFI vDSO
  riscv: alternative: Pass vDSO start as parameter to apply_vdso_alternatives()
  riscv: alternative: Use IS_ENABLED() over ifdeffery for apply_vdso_alternatives()
  riscv: vdso: Always declare vdso_start symbols
  riscv: kexec: use min to simplify riscv_kexec_elf_load
  riscv: panic if IRQ handler stacks cannot be allocated
  riscv: mm: Unconditionally sfence.vma for spurious fault
  riscv: mm: Use the bitmap API for new_valid_map_cpus
  riscv: mm: Rename new_vmalloc into new_valid_map_cpus
  riscv: kfence: Call mark_new_valid_map() for kfence_unprotect()
  riscv: mm: Extract helper mark_new_valid_map()
  riscv: stacktrace: Remove bogus -0x4 offset in non-FP walk_stackframe
  riscv: cacheinfo: Fix node reference leak in populate_cache_leaves
  riscv: kexec_file: Constrain segment placement to direct map
  riscv: mm: Define DIRECT_MAP_PHYSMEM_END
  riscv: defconfig: Enable Eswin SoCs
  riscv: cpu_ops_sbi: No need to be bothered to check ret.error
  ...
This commit is contained in:
Linus Torvalds
2026-06-18 21:55:24 -07:00
33 changed files with 205 additions and 191 deletions

View File

@@ -24,6 +24,7 @@ config RISCV
select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2
select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
select ARCH_HAS_BINFMT_FLAT
select ARCH_HAS_CC_CAN_LINK
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VIRTUAL if MMU
select ARCH_HAS_DEBUG_VM_PGTABLE
@@ -55,7 +56,7 @@ config RISCV
select ARCH_HAS_UBSAN
select ARCH_HAS_VDSO_ARCH_DATA if HAVE_GENERIC_VDSO
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_KEEP_MEMBLOCK if ACPI
select ARCH_KEEP_MEMBLOCK if ACPI || KEXEC
select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if 64BIT && MMU
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
@@ -151,6 +152,7 @@ config RISCV
select HAVE_ARCH_USERFAULTFD_WP if 64BIT && MMU && USERFAULTFD && RISCV_ISA_SVRSW60T59B
select HAVE_ARCH_VMAP_STACK if MMU && 64BIT
select HAVE_ASM_MODVERSIONS
select HAVE_BUILDTIME_MCOUNT_SORT
select HAVE_CONTEXT_TRACKING_USER
select HAVE_DEBUG_KMEMLEAK
select HAVE_DMA_CONTIGUOUS if MMU
@@ -1022,7 +1024,6 @@ choice
config RISCV_PROBE_VECTOR_UNALIGNED_ACCESS
bool "Probe speed of vector unaligned accesses"
select RISCV_VECTOR_MISALIGNED
depends on RISCV_ISA_V
help
During boot, the kernel will run a series of tests to determine the
speed of vector unaligned accesses if they are supported. This probing
@@ -1162,7 +1163,7 @@ config RELOCATABLE
config RANDOMIZE_BASE
bool "Randomize the address of the kernel image"
select RELOCATABLE
depends on RELOCATABLE
depends on MMU && 64BIT
help
Randomizes the virtual address at which the kernel image is
@@ -1352,6 +1353,20 @@ config PORTABLE
config ARCH_PROC_KCORE_TEXT
def_bool y
config ARCH_CC_CAN_LINK
bool
default $(cc_can_link_user,-march=rv64g -mabi=lp64d) if 64BIT && FPU
default $(cc_can_link_user,-march=rv64g -mabi=lp64) if 64BIT
default $(cc_can_link_user,-march=rv32g -mabi=ilp32d) if FPU
default $(cc_can_link_user,-march=rv32g -mabi=ilp32)
config ARCH_USERFLAGS
string
default "-march=rv64g -mabi=lp64d" if 64BIT && FPU
default "-march=rv64g -mabi=lp64" if 64BIT
default "-march=rv32g -mabi=ilp32d" if FPU
default "-march=rv32g -mabi=ilp32"
menu "Power management options"
source "kernel/power/Kconfig"

View File

@@ -24,6 +24,7 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_PROFILING=y
CONFIG_ARCH_ANDES=y
CONFIG_ARCH_ANLOGIC=y
CONFIG_ARCH_ESWIN=y
CONFIG_ARCH_MICROCHIP=y
CONFIG_ARCH_SIFIVE=y
CONFIG_ARCH_SOPHGO=y

View File

@@ -41,22 +41,23 @@ do { \
} while (0)
#ifdef CONFIG_64BIT
extern u64 new_vmalloc[NR_CPUS / sizeof(u64) + 1];
/* This is accessed in assembly code. cpumask_var_t would be too complex. */
extern DECLARE_BITMAP(new_valid_map_cpus, NR_CPUS);
extern char _end[];
static inline void mark_new_valid_map(void)
{
/*
* We don't care if concurrently a cpu resets this value since
* the only place this can happen is in handle_exception() where
* an sfence.vma is emitted.
*/
bitmap_fill(new_valid_map_cpus, NR_CPUS);
}
#define flush_cache_vmap flush_cache_vmap
static inline void flush_cache_vmap(unsigned long start, unsigned long end)
{
if (is_vmalloc_or_module_addr((void *)start)) {
int i;
/*
* We don't care if concurrently a cpu resets this value since
* the only place this can happen is in handle_exception() where
* an sfence.vma is emitted.
*/
for (i = 0; i < ARRAY_SIZE(new_vmalloc); ++i)
new_vmalloc[i] = -1ULL;
}
if (is_vmalloc_or_module_addr((void *)start))
mark_new_valid_map();
}
#define flush_cache_vmap_early(start, end) local_flush_tlb_kernel_range(start, end)
#endif

View File

@@ -24,7 +24,7 @@ struct cpu_operations {
struct task_struct *tidle);
#ifdef CONFIG_HOTPLUG_CPU
void (*cpu_stop)(void);
int (*cpu_is_stopped)(unsigned int cpu);
bool (*cpu_is_stopped)(unsigned int cpu);
#endif
};

View File

@@ -6,6 +6,7 @@
#include <linux/kfence.h>
#include <linux/pfn.h>
#include <asm-generic/pgalloc.h>
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
static inline bool arch_kfence_init_pool(void)
@@ -17,10 +18,12 @@ static inline bool kfence_protect_page(unsigned long addr, bool protect)
{
pte_t *pte = virt_to_kpte(addr);
if (protect)
if (protect) {
set_pte(pte, __pte(pte_val(ptep_get(pte)) & ~_PAGE_PRESENT));
else
} else {
set_pte(pte, __pte(pte_val(ptep_get(pte)) | _PAGE_PRESENT));
mark_new_valid_map();
}
preempt_disable();
local_flush_tlb_kernel_range(addr, addr + PAGE_SIZE);

View File

@@ -9,4 +9,6 @@
#define __ALIGN .balign 4
#define __ALIGN_STR ".balign 4"
#define _THIS_IP_ ({ unsigned long __ip; asm volatile("auipc %0, 0" : "=r" (__ip)); __ip; })
#endif /* _ASM_RISCV_LINKAGE_H */

View File

@@ -93,6 +93,16 @@
*/
#define vmemmap ((struct page *)VMEMMAP_START - vmemmap_start_pfn)
/* Needed to limit get_free_mem_region() */
#if defined(CONFIG_FLATMEM)
#define DIRECT_MAP_PHYSMEM_END (phys_ram_base + KERN_VIRT_SIZE - 1)
#elif defined(CONFIG_SPARSEMEM_VMEMMAP)
#define DIRECT_MAP_PHYSMEM_END \
((vmemmap_start_pfn + VMEMMAP_SIZE / sizeof(struct page)) * PAGE_SIZE - 1)
#elif defined(CONFIG_SPARSEMEM)
/* DIRECT_MAP_PHYSMEM_END is not limited by VA space assignment in this case */
#endif
#define PCI_IO_SIZE SZ_16M
#define PCI_IO_END VMEMMAP_START
#define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE)

View File

@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_RISCV_PURGATORY_H
#define _ASM_RISCV_PURGATORY_H
#ifndef __ASSEMBLER__
#include <linux/purgatory.h>
void purgatory(void);
#endif /* __ASSEMBLER__ */
#endif /* _ASM_RISCV_PURGATORY_H */

View File

@@ -12,12 +12,15 @@
* All systems with an MMU have a VDSO, but systems without an MMU don't
* support shared libraries and therefore don't have one.
*/
#ifdef CONFIG_MMU
#define __VDSO_PAGES 4
#ifndef __ASSEMBLER__
#ifdef CONFIG_MMU
#include <generated/vdso-offsets.h>
#endif
#ifdef CONFIG_RISCV_USER_CFI
#include <generated/vdso-cfi-offsets.h>
#endif
@@ -38,15 +41,12 @@
#define COMPAT_VDSO_SYMBOL(base, name) \
(void __user *)((unsigned long)(base) + compat__vdso_##name##_offset)
extern char compat_vdso_start[], compat_vdso_end[];
#endif /* CONFIG_COMPAT */
extern char vdso_start[], vdso_end[];
extern char vdso_cfi_start[], vdso_cfi_end[];
extern char compat_vdso_start[], compat_vdso_end[];
#endif /* !__ASSEMBLER__ */
#endif /* CONFIG_MMU */
#endif /* _ASM_RISCV_VDSO_H */

View File

@@ -173,15 +173,14 @@ static void __init_or_module _apply_alternatives(struct alt_entry *begin,
stage);
}
#ifdef CONFIG_MMU
static void __init apply_vdso_alternatives(void)
static void __init apply_vdso_alternatives(void *start)
{
const Elf_Ehdr *hdr;
const Elf_Shdr *shdr;
const Elf_Shdr *alt;
struct alt_entry *begin, *end;
hdr = (Elf_Ehdr *)vdso_start;
hdr = (Elf_Ehdr *)start;
shdr = (void *)hdr + hdr->e_shoff;
alt = find_section(hdr, shdr, ".alternative");
if (!alt)
@@ -194,9 +193,6 @@ static void __init apply_vdso_alternatives(void)
(struct alt_entry *)end,
RISCV_ALTERNATIVES_BOOT);
}
#else
static void __init apply_vdso_alternatives(void) { }
#endif
void __init apply_boot_alternatives(void)
{
@@ -207,7 +203,11 @@ void __init apply_boot_alternatives(void)
(struct alt_entry *)__alt_end,
RISCV_ALTERNATIVES_BOOT);
apply_vdso_alternatives();
if (IS_ENABLED(CONFIG_MMU))
apply_vdso_alternatives(vdso_start);
if (IS_ENABLED(CONFIG_RISCV_USER_CFI))
apply_vdso_alternatives(vdso_cfi_start);
}
/*

View File

@@ -5,7 +5,7 @@
#include <linux/cpu.h>
#include <linux/device.h>
#include <linux/sprintf.h>
#include <linux/sysfs.h>
#include <asm/bugs.h>
#include <asm/vendor_extensions/thead.h>
@@ -46,15 +46,15 @@ ssize_t cpu_show_ghostwrite(struct device *dev, struct device_attribute *attr, c
if (IS_ENABLED(CONFIG_RISCV_ISA_XTHEADVECTOR)) {
switch (ghostwrite_state) {
case UNAFFECTED:
return sprintf(buf, "Not affected\n");
return sysfs_emit(buf, "Not affected\n");
case MITIGATED:
return sprintf(buf, "Mitigation: xtheadvector disabled\n");
return sysfs_emit(buf, "Mitigation: xtheadvector disabled\n");
case VULNERABLE:
fallthrough;
default:
return sprintf(buf, "Vulnerable\n");
return sysfs_emit(buf, "Vulnerable\n");
}
} else {
return sprintf(buf, "Not affected\n");
}
return sysfs_emit(buf, "Not affected\n");
}

View File

@@ -133,7 +133,7 @@ int populate_cache_leaves(unsigned int cpu)
ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
levels = level;
}
of_node_put(np);
of_node_put(prev);
return 0;
}

View File

@@ -57,8 +57,8 @@ void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu)
/* Verify from the firmware if the cpu is really stopped*/
if (cpu_ops->cpu_is_stopped)
ret = cpu_ops->cpu_is_stopped(cpu);
if (ret)
pr_warn("CPU%u may not have stopped: %d\n", cpu, ret);
if (!ret)
pr_warn("CPU%u may not have stopped\n", cpu);
}
/*

View File

@@ -30,10 +30,8 @@ static int sbi_hsm_hart_start(unsigned long hartid, unsigned long saddr,
ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START,
hartid, saddr, priv, 0, 0, 0);
if (ret.error)
return sbi_err_map_linux_errno(ret.error);
else
return 0;
return sbi_err_map_linux_errno(ret.error);
}
#ifdef CONFIG_HOTPLUG_CPU
@@ -43,10 +41,7 @@ static int sbi_hsm_hart_stop(void)
ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP, 0, 0, 0, 0, 0, 0);
if (ret.error)
return sbi_err_map_linux_errno(ret.error);
else
return 0;
return sbi_err_map_linux_errno(ret.error);
}
static int sbi_hsm_hart_get_status(unsigned long hartid)
@@ -88,16 +83,19 @@ static void sbi_cpu_stop(void)
pr_crit("Unable to stop the cpu %d (%d)\n", smp_processor_id(), ret);
}
static int sbi_cpu_is_stopped(unsigned int cpuid)
static bool sbi_cpu_is_stopped(unsigned int cpuid)
{
int rc;
unsigned long hartid = cpuid_to_hartid_map(cpuid);
rc = sbi_hsm_hart_get_status(hartid);
if (rc == SBI_HSM_STATE_STOPPED)
return 0;
return rc;
if (rc != SBI_HSM_STATE_STOPPED) {
pr_warn("HART%lu isn't stopped; status %d\n", hartid, rc);
return false;
}
return true;
}
#endif

View File

@@ -20,44 +20,44 @@
.section .irqentry.text, "ax"
.macro new_vmalloc_check
.macro new_valid_map_cpus_check
REG_S a0, TASK_TI_A0(tp)
csrr a0, CSR_CAUSE
/* Exclude IRQs */
blt a0, zero, .Lnew_vmalloc_restore_context_a0
blt a0, zero, .Lnew_valid_map_cpus_restore_context_a0
REG_S a1, TASK_TI_A1(tp)
/* Only check new_vmalloc if we are in page/protection fault */
/* Only check new_valid_map_cpus if we are in page/protection fault */
li a1, EXC_LOAD_PAGE_FAULT
beq a0, a1, .Lnew_vmalloc_kernel_address
beq a0, a1, .Lnew_valid_map_cpus_kernel_address
li a1, EXC_STORE_PAGE_FAULT
beq a0, a1, .Lnew_vmalloc_kernel_address
beq a0, a1, .Lnew_valid_map_cpus_kernel_address
li a1, EXC_INST_PAGE_FAULT
bne a0, a1, .Lnew_vmalloc_restore_context_a1
bne a0, a1, .Lnew_valid_map_cpus_restore_context_a1
.Lnew_vmalloc_kernel_address:
.Lnew_valid_map_cpus_kernel_address:
/* Is it a kernel address? */
csrr a0, CSR_TVAL
bge a0, zero, .Lnew_vmalloc_restore_context_a1
bge a0, zero, .Lnew_valid_map_cpus_restore_context_a1
/* Check if a new vmalloc mapping appeared that could explain the trap */
REG_S a2, TASK_TI_A2(tp)
/*
* Computes:
* a0 = &new_vmalloc[BIT_WORD(cpu)]
* a0 = &new_valid_map_cpus[BIT_WORD(cpu)]
* a1 = BIT_MASK(cpu)
*/
lw a2, TASK_TI_CPU(tp)
/*
* Compute the new_vmalloc element position:
* Compute the new_valid_map_cpus element position:
* (cpu / 64) * 8 = (cpu >> 6) << 3
*/
srli a1, a2, 6
slli a1, a1, 3
la a0, new_vmalloc
la a0, new_valid_map_cpus
add a0, a0, a1
/*
* Compute the bit position in the new_vmalloc element:
* Compute the bit position in the new_valid_map_cpus element:
* bit_pos = cpu % 64 = cpu - (cpu / 64) * 64 = cpu - (cpu >> 6) << 6
* = cpu - ((cpu >> 6) << 3) << 3
*/
@@ -67,16 +67,19 @@
li a2, 1
sll a1, a2, a1
/* Check the value of new_vmalloc for this cpu */
/* Check the value of new_valid_map_cpus for this cpu */
REG_L a2, 0(a0)
and a2, a2, a1
beq a2, zero, .Lnew_vmalloc_restore_context
beq a2, zero, .Lnew_valid_map_cpus_restore_context
/* Atomically reset the current cpu bit in new_vmalloc */
/* Atomically reset the current cpu bit in new_valid_map_cpus */
amoxor.d a0, a1, (a0)
/* Only emit a sfence.vma if the uarch caches invalid entries */
ALTERNATIVE("sfence.vma", "nop", 0, RISCV_ISA_EXT_SVVPTC, 1)
/*
* A sfence.vma is required here. Even if we had Svvptc, there's no
* guarantee that after returning we wouldn't just fault again.
*/
sfence.vma
REG_L a0, TASK_TI_A0(tp)
REG_L a1, TASK_TI_A1(tp)
@@ -84,11 +87,11 @@
csrw CSR_SCRATCH, x0
sret
.Lnew_vmalloc_restore_context:
.Lnew_valid_map_cpus_restore_context:
REG_L a2, TASK_TI_A2(tp)
.Lnew_vmalloc_restore_context_a1:
.Lnew_valid_map_cpus_restore_context_a1:
REG_L a1, TASK_TI_A1(tp)
.Lnew_vmalloc_restore_context_a0:
.Lnew_valid_map_cpus_restore_context_a0:
REG_L a0, TASK_TI_A0(tp)
.endm
@@ -136,15 +139,17 @@ SYM_CODE_START(handle_exception)
#ifdef CONFIG_64BIT
/*
* The RISC-V kernel does not eagerly emit a sfence.vma after each
* new vmalloc mapping, which may result in exceptions:
* The RISC-V kernel does not flush TLBs on all CPUS after each new
* vmalloc mapping or kfence_unprotect(), which may result in
* exceptions:
*
* - if the uarch caches invalid entries, the new mapping would not be
* observed by the page table walker and an invalidation is needed.
* - if the uarch does not cache invalid entries, a reordered access
* could "miss" the new mapping and traps: in that case, we only need
* to retry the access, no sfence.vma is required.
*/
new_vmalloc_check
new_valid_map_cpus_check
#endif
REG_S sp, TASK_TI_KERNEL_SP(tp)

View File

@@ -75,28 +75,34 @@ DECLARE_PER_CPU(ulong *, irq_shadow_call_stack_ptr);
DEFINE_PER_CPU(ulong *, irq_shadow_call_stack_ptr);
#endif
static void init_irq_scs(void)
static void __init init_irq_scs(void)
{
int cpu;
void *s;
if (!scs_is_enabled())
return;
for_each_possible_cpu(cpu)
per_cpu(irq_shadow_call_stack_ptr, cpu) =
scs_alloc(cpu_to_node(cpu));
for_each_possible_cpu(cpu) {
s = scs_alloc(cpu_to_node(cpu));
if (!s)
panic("Failed to allocate IRQ shadow call stack resources\n");
per_cpu(irq_shadow_call_stack_ptr, cpu) = s;
}
}
DEFINE_PER_CPU(ulong *, irq_stack_ptr);
#ifdef CONFIG_VMAP_STACK
static void init_irq_stacks(void)
static void __init init_irq_stacks(void)
{
int cpu;
ulong *p;
for_each_possible_cpu(cpu) {
p = arch_alloc_vmap_stack(IRQ_STACK_SIZE, cpu_to_node(cpu));
if (!p)
panic("Failed to allocate IRQ stack resources\n");
per_cpu(irq_stack_ptr, cpu) = p;
}
}
@@ -104,7 +110,7 @@ static void init_irq_stacks(void)
/* irq stack only needs to be 16 byte aligned - not IRQ_STACK_SIZE aligned. */
DEFINE_PER_CPU_ALIGNED(ulong [IRQ_STACK_SIZE/sizeof(ulong)], irq_stack);
static void init_irq_stacks(void)
static void __init init_irq_stacks(void)
{
int cpu;
@@ -129,8 +135,8 @@ void do_softirq_own_stack(void)
#endif /* CONFIG_SOFTIRQ_ON_OWN_STACK */
#else
static void init_irq_scs(void) {}
static void init_irq_stacks(void) {}
static void __init init_irq_scs(void) {}
static void __init init_irq_stacks(void) {}
#endif /* CONFIG_IRQ_STACKS */
int arch_show_interrupts(struct seq_file *p, int prec)

View File

@@ -10,8 +10,6 @@
* for kernel.
*/
#define pr_fmt(fmt) "kexec_image: " fmt
#include <linux/elf.h>
#include <linux/kexec.h>
#include <linux/slab.h>
@@ -19,6 +17,7 @@
#include <linux/libfdt.h>
#include <linux/types.h>
#include <linux/memblock.h>
#include <linux/minmax.h>
#include <asm/setup.h>
static int riscv_kexec_elf_load(struct kimage *image, struct elfhdr *ehdr,
@@ -27,7 +26,6 @@ static int riscv_kexec_elf_load(struct kimage *image, struct elfhdr *ehdr,
{
int i;
int ret = 0;
size_t size;
struct kexec_buf kbuf = {};
const struct elf_phdr *phdr;
@@ -38,12 +36,8 @@ static int riscv_kexec_elf_load(struct kimage *image, struct elfhdr *ehdr,
if (phdr->p_type != PT_LOAD)
continue;
size = phdr->p_filesz;
if (size > phdr->p_memsz)
size = phdr->p_memsz;
kbuf.buffer = (void *) elf_info->buffer + phdr->p_offset;
kbuf.bufsz = size;
kbuf.bufsz = min(phdr->p_filesz, phdr->p_memsz);
kbuf.buf_align = phdr->p_align;
kbuf.mem = phdr->p_paddr - old_pbase + new_pbase;
kbuf.memsz = phdr->p_memsz;

View File

@@ -13,6 +13,7 @@
#include <linux/libfdt.h>
#include <linux/types.h>
#include <linux/memblock.h>
#include <linux/pfn.h>
#include <linux/vmalloc.h>
#include <asm/setup.h>
#include <asm/insn.h>
@@ -266,7 +267,7 @@ int load_extra_segments(struct kimage *image, unsigned long kernel_start,
kbuf.image = image;
kbuf.buf_min = kernel_start + kernel_len;
kbuf.buf_max = ULONG_MAX;
kbuf.buf_max = PFN_PHYS(max_low_pfn);
#ifdef CONFIG_CRASH_DUMP
/* Add elfcorehdr */

View File

@@ -56,17 +56,15 @@ unsigned long module_emit_plt_entry(struct module *mod, unsigned long val)
return (unsigned long)&plt[i];
}
#define cmp_3way(a, b) ((a) < (b) ? -1 : (a) > (b))
static int cmp_rela(const void *a, const void *b)
{
const Elf_Rela *x = a, *y = b;
int i;
/* sort by type, symbol index and addend */
i = cmp_3way(x->r_info, y->r_info);
i = cmp_int(x->r_info, y->r_info);
if (i == 0)
i = cmp_3way(x->r_addend, y->r_addend);
i = cmp_int(x->r_addend, y->r_addend);
return i;
}

View File

@@ -12,8 +12,8 @@ static char early_cmdline[COMMAND_LINE_SIZE];
static char *get_early_cmdline(uintptr_t dtb_pa)
{
const char *fdt_cmdline = NULL;
unsigned int fdt_cmdline_size = 0;
const char *fdt_cmdline;
ssize_t fdt_cmdline_size = 0;
int chosen_node;
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
@@ -22,18 +22,18 @@ static char *get_early_cmdline(uintptr_t dtb_pa)
fdt_cmdline = fdt_getprop((void *)dtb_pa, chosen_node,
"bootargs", NULL);
if (fdt_cmdline) {
fdt_cmdline_size = strlen(fdt_cmdline);
strscpy(early_cmdline, fdt_cmdline,
COMMAND_LINE_SIZE);
fdt_cmdline_size = strscpy(early_cmdline, fdt_cmdline);
if (fdt_cmdline_size < 0)
return early_cmdline;
}
}
}
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
fdt_cmdline_size == 0 /* CONFIG_CMDLINE_FALLBACK */) {
strlcat(early_cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
}
fdt_cmdline_size == 0 /* CONFIG_CMDLINE_FALLBACK */)
strscpy(early_cmdline + fdt_cmdline_size, CONFIG_CMDLINE,
COMMAND_LINE_SIZE - fdt_cmdline_size);
return early_cmdline;
}

View File

@@ -71,16 +71,13 @@ static struct resource *standard_resources;
static int __init add_resource(struct resource *parent,
struct resource *res)
{
int ret = 0;
int ret;
ret = insert_resource(parent, res);
if (ret < 0) {
pr_err("Failed to add a %s resource at %llx\n",
res->name, (unsigned long long) res->start);
return ret;
}
if (ret < 0)
pr_err("Failed to add resource %s %pR\n", res->name, res);
return 1;
return ret;
}
static int __init add_kernel_resources(void)

View File

@@ -87,7 +87,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
} else {
fp = READ_ONCE_TASK_STACK(task, frame->fp);
pc = READ_ONCE_TASK_STACK(task, frame->ra);
pc = ftrace_graph_ret_addr(current, &graph_idx, pc,
pc = ftrace_graph_ret_addr(task, &graph_idx, pc,
&frame->ra);
if (pc >= (unsigned long)handle_exception &&
pc < (unsigned long)&ret_from_exception_end) {
@@ -129,7 +129,7 @@ void notrace walk_stackframe(struct task_struct *task,
while (!kstack_end(ksp)) {
if (__kernel_text_address(pc) && unlikely(!fn(arg, pc)))
break;
pc = READ_ONCE_NOCHECK(*ksp++) - 0x4;
pc = READ_ONCE_NOCHECK(*ksp++);
}
}

View File

@@ -522,10 +522,10 @@ static bool unaligned_ctl __read_mostly;
static void check_unaligned_access_emulated(void *arg __always_unused)
{
int cpu = smp_processor_id();
long *mas_ptr = per_cpu_ptr(&misaligned_access_speed, cpu);
unsigned long tmp_var, tmp_val;
*mas_ptr = RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN;
if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN)
return;
__asm__ __volatile__ (
" "REG_L" %[tmp], 1(%[ptr])\n"

View File

@@ -27,8 +27,6 @@ DEFINE_PER_CPU(long, vector_misaligned_access) = RISCV_HWPROBE_MISALIGNED_VECTOR
static long unaligned_scalar_speed_param = RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN;
static long unaligned_vector_speed_param = RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN;
static cpumask_t fast_misaligned_access;
static u64 __maybe_unused
measure_cycles(void (*func)(void *dst, const void *src, size_t len),
void *dst, void *src, size_t len)
@@ -131,13 +129,10 @@ static int check_unaligned_access(struct page *page)
* Set the value of fast_misaligned_access of a CPU. These operations
* are atomic to avoid race conditions.
*/
if (ret) {
if (ret)
per_cpu(misaligned_access_speed, cpu) = RISCV_HWPROBE_MISALIGNED_SCALAR_FAST;
cpumask_set_cpu(cpu, &fast_misaligned_access);
} else {
else
per_cpu(misaligned_access_speed, cpu) = RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW;
cpumask_clear_cpu(cpu, &fast_misaligned_access);
}
return 0;
}
@@ -192,49 +187,24 @@ static void __init check_unaligned_access_speed_all_cpus(void)
DEFINE_STATIC_KEY_FALSE(fast_unaligned_access_speed_key);
static void modify_unaligned_access_branches(cpumask_t *mask, int weight)
static void modify_unaligned_access_branches(const cpumask_t *mask)
{
if (cpumask_weight(mask) == weight)
bool fast = true;
int cpu;
for_each_cpu(cpu, mask) {
if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_FAST) {
fast = false;
break;
}
}
if (fast)
static_branch_enable_cpuslocked(&fast_unaligned_access_speed_key);
else
static_branch_disable_cpuslocked(&fast_unaligned_access_speed_key);
}
static void set_unaligned_access_static_branches_except_cpu(int cpu)
{
/*
* Same as set_unaligned_access_static_branches, except excludes the
* given CPU from the result. When a CPU is hotplugged into an offline
* state, this function is called before the CPU is set to offline in
* the cpumask, and thus the CPU needs to be explicitly excluded.
*/
cpumask_t fast_except_me;
cpumask_and(&fast_except_me, &fast_misaligned_access, cpu_online_mask);
cpumask_clear_cpu(cpu, &fast_except_me);
modify_unaligned_access_branches(&fast_except_me, num_online_cpus() - 1);
}
static void set_unaligned_access_static_branches(void)
{
/*
* This will be called after check_unaligned_access_all_cpus so the
* result of unaligned access speed for all CPUs will be available.
*
* To avoid the number of online cpus changing between reading
* cpu_online_mask and calling num_online_cpus, cpus_read_lock must be
* held before calling this function.
*/
cpumask_t fast_and_online;
cpumask_and(&fast_and_online, &fast_misaligned_access, cpu_online_mask);
modify_unaligned_access_branches(&fast_and_online, num_online_cpus());
}
static int riscv_online_cpu(unsigned int cpu)
{
int ret = cpu_online_unaligned_access_init(cpu);
@@ -266,14 +236,19 @@ static int riscv_online_cpu(unsigned int cpu)
#endif
exit:
set_unaligned_access_static_branches();
modify_unaligned_access_branches(cpu_online_mask);
return 0;
}
static int riscv_offline_cpu(unsigned int cpu)
{
set_unaligned_access_static_branches_except_cpu(cpu);
cpumask_t mask;
cpumask_copy(&mask, cpu_online_mask);
cpumask_clear_cpu(cpu, &mask);
modify_unaligned_access_branches(&mask);
return 0;
}
@@ -430,7 +405,7 @@ static int __init check_unaligned_access_all_cpus(void)
riscv_online_cpu_vec, NULL);
cpus_read_lock();
set_unaligned_access_static_branches();
modify_unaligned_access_branches(cpu_online_mask);
cpus_read_unlock();
return 0;

View File

@@ -37,7 +37,7 @@
#include "../kernel/head.h"
u64 new_vmalloc[NR_CPUS / sizeof(u64) + 1];
DECLARE_BITMAP(new_valid_map_cpus, NR_CPUS);
struct kernel_mapping kernel_map __ro_after_init;
EXPORT_SYMBOL(kernel_map);

View File

@@ -7,6 +7,7 @@
#include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/ptdump.h>
#include <linux/pgtable.h>
@@ -213,21 +214,21 @@ static void dump_prot(struct pg_state *st)
val = st->current_prot & pte_bits[i].mask;
if (val) {
if (pte_bits[i].mask == _PAGE_SOFT)
sprintf(s, pte_bits[i].set, val >> 8);
snprintf(s, sizeof(s), pte_bits[i].set, val >> 8);
#ifdef CONFIG_64BIT
else if (pte_bits[i].mask == _PAGE_MTMASK_SVPBMT) {
if (val == _PAGE_NOCACHE_SVPBMT)
sprintf(s, pte_bits[i].set, "NC");
snprintf(s, sizeof(s), pte_bits[i].set, "NC");
else if (val == _PAGE_IO_SVPBMT)
sprintf(s, pte_bits[i].set, "IO");
snprintf(s, sizeof(s), pte_bits[i].set, "IO");
else
sprintf(s, pte_bits[i].set, "??");
snprintf(s, sizeof(s), pte_bits[i].set, "??");
}
#endif
else
sprintf(s, "%s", pte_bits[i].set);
strscpy(s, pte_bits[i].set);
} else {
sprintf(s, "%s", pte_bits[i].clear);
strscpy(s, pte_bits[i].clear);
}
pt_dump_seq_printf(st->seq, " %s", s);

View File

@@ -8,16 +8,16 @@
*
*/
#include <linux/purgatory.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <asm/purgatory.h>
#include <asm/string.h>
u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE] __section(".kexec-purgatory");
struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] __section(".kexec-purgatory");
static int verify_sha256_digest(void)
static bool verify_sha256_digest(void)
{
struct kexec_sha_region *ptr, *end;
struct sha256_ctx sctx;
@@ -26,19 +26,15 @@ static int verify_sha256_digest(void)
sha256_init(&sctx);
end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
for (ptr = purgatory_sha_regions; ptr < end; ptr++)
sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len);
sha256_update(&sctx, (const u8 *)(ptr->start), ptr->len);
sha256_final(&sctx, digest);
if (memcmp(digest, purgatory_sha256_digest, sizeof(digest)) != 0)
return 1;
return 0;
}
/* workaround for a warning with -Wmissing-prototypes */
void purgatory(void);
return memcmp(digest, purgatory_sha256_digest, sizeof(digest)) == 0;
}
void purgatory(void)
{
if (verify_sha256_digest())
if (!verify_sha256_digest())
for (;;)
/* loop forever */
;

View File

@@ -7,4 +7,4 @@ TEST_GEN_PROGS := pointer_masking
include ../../lib.mk
$(OUTPUT)/pointer_masking: pointer_masking.c
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
$(CC) -static -o $@ $(CFLAGS) $(LDFLAGS) $^

View File

@@ -16,7 +16,7 @@ ifeq ($(shell $(CC) $(CFLAGS) -nostdlib -xc /dev/null -o /dev/null > /dev/null 2
TEST_GEN_PROGS := cfitests
$(OUTPUT)/cfitests: cfitests.c shadowstack.c
$(CC) -o$@ $(CFLAGS) $(LDFLAGS) $^
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^
else
$(shell echo "Toolchain doesn't support CFI, skipping CFI kselftest." >&2)

View File

@@ -9,10 +9,10 @@ TEST_GEN_PROGS := hwprobe cbo which-cpus
include ../../lib.mk
$(OUTPUT)/hwprobe: hwprobe.c sys_hwprobe.S
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
$(CC) -static -o $@ $(CFLAGS) $(LDFLAGS) $^
$(OUTPUT)/cbo: cbo.c sys_hwprobe.S
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
$(CC) -static -o $@ $(CFLAGS) $(LDFLAGS) $^
$(OUTPUT)/which-cpus: which-cpus.c sys_hwprobe.S
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
$(CC) -static -o $@ $(CFLAGS) $(LDFLAGS) $^

View File

@@ -12,4 +12,4 @@ TEST_PROGS := run_mmap.sh
include ../../lib.mk
$(OUTPUT)/mm: mmap_default.c mmap_bottomup.c mmap_tests.h
$(CC) -o$@ $(CFLAGS) $(LDFLAGS) $^
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^

View File

@@ -9,4 +9,4 @@ TEST_GEN_PROGS := sigreturn
include ../../lib.mk
$(OUTPUT)/sigreturn: sigreturn.c
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
$(CC) -static -o $@ $(CFLAGS) $(LDFLAGS) $^

View File

@@ -11,29 +11,29 @@ include ../../lib.mk
TEST_GEN_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(TEST_GEN_LIBS))
$(OUTPUT)/sys_hwprobe.o: ../hwprobe/sys_hwprobe.S
$(CC) -static -c -o$@ $(CFLAGS) $^
$(CC) -static -c -o $@ $(CFLAGS) $^
$(OUTPUT)/v_helpers.o: v_helpers.c
$(CC) -static -c -o$@ $(CFLAGS) $^
$(CC) -static -c -o $@ $(CFLAGS) $^
$(OUTPUT)/vstate_prctl: vstate_prctl.c $(OUTPUT)/sys_hwprobe.o $(OUTPUT)/v_helpers.o
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
$(CC) -static -o $@ $(CFLAGS) $(LDFLAGS) $^
$(OUTPUT)/vstate_exec_nolibc: vstate_exec_nolibc.c
$(CC) -nostdlib -static -include ../../../../include/nolibc/nolibc.h \
-Wall $(CFLAGS) $(LDFLAGS) $^ -o $@ -lgcc
$(OUTPUT)/v_initval: v_initval.c $(OUTPUT)/sys_hwprobe.o $(OUTPUT)/v_helpers.o
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
$(CC) -static -o $@ $(CFLAGS) $(LDFLAGS) $^
$(OUTPUT)/v_exec_initval_nolibc: v_exec_initval_nolibc.c
$(CC) -nostdlib -static -include ../../../../include/nolibc/nolibc.h \
-Wall $(CFLAGS) $(LDFLAGS) $^ -o $@ -lgcc
$(OUTPUT)/vstate_ptrace: vstate_ptrace.c $(OUTPUT)/sys_hwprobe.o $(OUTPUT)/v_helpers.o
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
$(CC) -static -o $@ $(CFLAGS) $(LDFLAGS) $^
$(OUTPUT)/validate_v_ptrace: validate_v_ptrace.c $(OUTPUT)/sys_hwprobe.o $(OUTPUT)/v_helpers.o
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
$(CC) -static -o $@ $(CFLAGS) $(LDFLAGS) $^
EXTRA_CLEAN += $(TEST_GEN_OBJ)