Skip to content

Commit 063df71

Browse files
committed
Merge tag 'riscv-for-linus-5.15-mw0' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux
Pull RISC-V updates from Palmer Dabbelt: - support PC-relative instructions (auipc and branches) in kprobes - support for forced IRQ threading - support for the hlt/nohlt kernel command line options, via the generic idle loop - show the edge/level triggered behavior of interrupts in /proc/interrupts - a handful of cleanups to our address mapping mechanisms - support for allocating gigantic hugepages via CMA - support for the undefined behavior sanitizer (UBSAN) - a handful of cleanups to the VDSO that allow the kernel to build with LLD. - support for hugepage migration * tag 'riscv-for-linus-5.15-mw0' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (21 commits) riscv: add support for hugepage migration RISC-V: Fix VDSO build for !MMU riscv: use strscpy to replace strlcpy riscv: explicitly use symbol offsets for VDSO riscv: Enable Undefined Behavior Sanitizer UBSAN riscv: Keep the riscv Kconfig selects sorted riscv: Support allocating gigantic hugepages using CMA riscv: fix the global name pfn_base confliction error riscv: Move early fdt mapping creation in its own function riscv: Simplify BUILTIN_DTB device tree mapping handling riscv: Use __maybe_unused instead of #ifdefs around variable declarations riscv: Get rid of map_size parameter to create_kernel_page_table riscv: Introduce va_kernel_pa_offset for 32-bit kernel riscv: Optimize kernel virtual address conversion macro dt-bindings: riscv: add starfive jh7100 bindings riscv: Enable GENERIC_IRQ_SHOW_LEVEL riscv: Enable idle generic idle loop riscv: Allow forced irq threading riscv: Implement thread_struct whitelist for hardened usercopy riscv: kprobes: implement the branch instructions ...
2 parents 3fe617c + c24a196 commit 063df71

File tree

13 files changed

+256
-127
lines changed

13 files changed

+256
-127
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/riscv/starfive.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: StarFive SoC-based boards
8+
9+
maintainers:
10+
- Michael Zhu <[email protected]>
11+
- Drew Fustini <[email protected]>
12+
13+
description:
14+
StarFive SoC-based boards
15+
16+
properties:
17+
$nodename:
18+
const: '/'
19+
compatible:
20+
oneOf:
21+
- items:
22+
- const: beagle,beaglev-starlight-jh7100-r0
23+
- const: starfive,jh7100
24+
25+
additionalProperties: true
26+
27+
...

arch/riscv/Kconfig

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ config 32BIT
1313
config RISCV
1414
def_bool y
1515
select ARCH_CLOCKSOURCE_INIT
16-
select ARCH_SUPPORTS_ATOMIC_RMW
17-
select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU
18-
select ARCH_STACKWALK
16+
select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
1917
select ARCH_HAS_BINFMT_FLAT
2018
select ARCH_HAS_DEBUG_VM_PGTABLE
2119
select ARCH_HAS_DEBUG_VIRTUAL if MMU
@@ -31,8 +29,12 @@ config RISCV
3129
select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
3230
select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL
3331
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
32+
select ARCH_HAS_UBSAN_SANITIZE_ALL
3433
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
3534
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
35+
select ARCH_STACKWALK
36+
select ARCH_SUPPORTS_ATOMIC_RMW
37+
select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU
3638
select ARCH_SUPPORTS_HUGETLBFS if MMU
3739
select ARCH_USE_MEMTEST
3840
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
@@ -48,9 +50,11 @@ config RISCV
4850
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
4951
select GENERIC_EARLY_IOREMAP
5052
select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO
53+
select GENERIC_IDLE_POLL_SETUP
5154
select GENERIC_IOREMAP
5255
select GENERIC_IRQ_MULTI_HANDLER
5356
select GENERIC_IRQ_SHOW
57+
select GENERIC_IRQ_SHOW_LEVEL
5458
select GENERIC_LIB_DEVMEM_IS_ALLOWED
5559
select GENERIC_PCI_IOMAP
5660
select GENERIC_PTDUMP if MMU
@@ -70,6 +74,7 @@ config RISCV
7074
select HAVE_ARCH_SECCOMP_FILTER
7175
select HAVE_ARCH_TRACEHOOK
7276
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT && MMU
77+
select HAVE_ARCH_THREAD_STRUCT_WHITELIST
7378
select HAVE_ARCH_VMAP_STACK if MMU && 64BIT
7479
select HAVE_ASM_MODVERSIONS
7580
select HAVE_CONTEXT_TRACKING
@@ -95,6 +100,7 @@ config RISCV
95100
select HAVE_STACKPROTECTOR
96101
select HAVE_SYSCALL_TRACEPOINTS
97102
select IRQ_DOMAIN
103+
select IRQ_FORCED_THREADING
98104
select MODULES_USE_ELF_RELA if MODULES
99105
select MODULE_SECTIONS if MODULES
100106
select OF

arch/riscv/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ PHONY += vdso_install
108108
vdso_install:
109109
$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
110110

111+
ifeq ($(CONFIG_MMU),y)
112+
prepare: vdso_prepare
113+
vdso_prepare: prepare0
114+
$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h
115+
endif
116+
111117
ifneq ($(CONFIG_XIP_KERNEL),y)
112118
ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy)
113119
KBUILD_IMAGE := $(boot)/loader.bin

arch/riscv/include/asm/page.h

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ typedef struct page *pgtable_t;
7979
#endif
8080

8181
#ifdef CONFIG_MMU
82-
extern unsigned long pfn_base;
83-
#define ARCH_PFN_OFFSET (pfn_base)
82+
extern unsigned long riscv_pfn_base;
83+
#define ARCH_PFN_OFFSET (riscv_pfn_base)
8484
#else
8585
#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
8686
#endif /* CONFIG_MMU */
@@ -91,10 +91,8 @@ struct kernel_mapping {
9191
uintptr_t size;
9292
/* Offset between linear mapping virtual address and kernel load address */
9393
unsigned long va_pa_offset;
94-
#ifdef CONFIG_64BIT
9594
/* Offset between kernel mapping virtual address and kernel load address */
9695
unsigned long va_kernel_pa_offset;
97-
#endif
9896
unsigned long va_kernel_xip_pa_offset;
9997
#ifdef CONFIG_XIP_KERNEL
10098
uintptr_t xiprom;
@@ -105,11 +103,11 @@ struct kernel_mapping {
105103
extern struct kernel_mapping kernel_map;
106104
extern phys_addr_t phys_ram_base;
107105

108-
#ifdef CONFIG_64BIT
109106
#define is_kernel_mapping(x) \
110107
((x) >= kernel_map.virt_addr && (x) < (kernel_map.virt_addr + kernel_map.size))
108+
111109
#define is_linear_mapping(x) \
112-
((x) >= PAGE_OFFSET && (x) < kernel_map.virt_addr)
110+
((x) >= PAGE_OFFSET && (!IS_ENABLED(CONFIG_64BIT) || (x) < kernel_map.virt_addr))
113111

114112
#define linear_mapping_pa_to_va(x) ((void *)((unsigned long)(x) + kernel_map.va_pa_offset))
115113
#define kernel_mapping_pa_to_va(y) ({ \
@@ -123,7 +121,7 @@ extern phys_addr_t phys_ram_base;
123121
#define linear_mapping_va_to_pa(x) ((unsigned long)(x) - kernel_map.va_pa_offset)
124122
#define kernel_mapping_va_to_pa(y) ({ \
125123
unsigned long _y = y; \
126-
(_y < kernel_map.virt_addr + XIP_OFFSET) ? \
124+
(IS_ENABLED(CONFIG_XIP_KERNEL) && _y < kernel_map.virt_addr + XIP_OFFSET) ? \
127125
((unsigned long)(_y) - kernel_map.va_kernel_xip_pa_offset) : \
128126
((unsigned long)(_y) - kernel_map.va_kernel_pa_offset - XIP_OFFSET); \
129127
})
@@ -133,15 +131,6 @@ extern phys_addr_t phys_ram_base;
133131
is_linear_mapping(_x) ? \
134132
linear_mapping_va_to_pa(_x) : kernel_mapping_va_to_pa(_x); \
135133
})
136-
#else
137-
#define is_kernel_mapping(x) \
138-
((x) >= kernel_map.virt_addr && (x) < (kernel_map.virt_addr + kernel_map.size))
139-
#define is_linear_mapping(x) \
140-
((x) >= PAGE_OFFSET)
141-
142-
#define __pa_to_va_nodebug(x) ((void *)((unsigned long) (x) + kernel_map.va_pa_offset))
143-
#define __va_to_pa_nodebug(x) ((unsigned long)(x) - kernel_map.va_pa_offset)
144-
#endif /* CONFIG_64BIT */
145134

146135
#ifdef CONFIG_DEBUG_VIRTUAL
147136
extern phys_addr_t __virt_to_phys(unsigned long x);

arch/riscv/include/asm/processor.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ struct thread_struct {
3737
unsigned long bad_cause;
3838
};
3939

40+
/* Whitelist the fstate from the task_struct for hardened usercopy */
41+
static inline void arch_thread_struct_whitelist(unsigned long *offset,
42+
unsigned long *size)
43+
{
44+
*offset = offsetof(struct thread_struct, fstate);
45+
*size = sizeof_field(struct thread_struct, fstate);
46+
}
47+
4048
#define INIT_THREAD { \
4149
.sp = sizeof(init_stack) + (long)&init_stack, \
4250
}

arch/riscv/include/asm/vdso.h

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,25 @@
88
#ifndef _ASM_RISCV_VDSO_H
99
#define _ASM_RISCV_VDSO_H
1010

11+
12+
/*
13+
* All systems with an MMU have a VDSO, but systems without an MMU don't
14+
* support shared libraries and therefor don't have one.
15+
*/
16+
#ifdef CONFIG_MMU
17+
1118
#include <linux/types.h>
19+
#include <generated/vdso-offsets.h>
1220

1321
#ifndef CONFIG_GENERIC_TIME_VSYSCALL
1422
struct vdso_data {
1523
};
1624
#endif
1725

18-
/*
19-
* The VDSO symbols are mapped into Linux so we can just use regular symbol
20-
* addressing to get their offsets in userspace. The symbols are mapped at an
21-
* offset of 0, but since the linker must support setting weak undefined
22-
* symbols to the absolute address 0 it also happens to support other low
23-
* addresses even when the code model suggests those low addresses would not
24-
* otherwise be availiable.
25-
*/
2626
#define VDSO_SYMBOL(base, name) \
27-
({ \
28-
extern const char __vdso_##name[]; \
29-
(void __user *)((unsigned long)(base) + __vdso_##name); \
30-
})
27+
(void __user *)((unsigned long)(base) + __vdso_##name##_offset)
28+
29+
#endif /* CONFIG_MMU */
3130

3231
asmlinkage long sys_riscv_flush_icache(uintptr_t, uintptr_t, uintptr_t);
3332

arch/riscv/kernel/probes/decode-insn.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,10 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
3838
RISCV_INSN_REJECTED(c_ebreak, insn);
3939
#endif
4040

41-
RISCV_INSN_REJECTED(auipc, insn);
42-
RISCV_INSN_REJECTED(branch, insn);
43-
4441
RISCV_INSN_SET_SIMULATE(jal, insn);
4542
RISCV_INSN_SET_SIMULATE(jalr, insn);
43+
RISCV_INSN_SET_SIMULATE(auipc, insn);
44+
RISCV_INSN_SET_SIMULATE(branch, insn);
4645

4746
return INSN_GOOD;
4847
}

arch/riscv/kernel/probes/simulate-insn.c

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,115 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg
8383

8484
return ret;
8585
}
86+
87+
#define auipc_rd_idx(opcode) \
88+
((opcode >> 7) & 0x1f)
89+
90+
#define auipc_imm(opcode) \
91+
((((opcode) >> 12) & 0xfffff) << 12)
92+
93+
#if __riscv_xlen == 64
94+
#define auipc_offset(opcode) sign_extend64(auipc_imm(opcode), 31)
95+
#elif __riscv_xlen == 32
96+
#define auipc_offset(opcode) auipc_imm(opcode)
97+
#else
98+
#error "Unexpected __riscv_xlen"
99+
#endif
100+
101+
bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *regs)
102+
{
103+
/*
104+
* auipc instruction:
105+
* 31 12 11 7 6 0
106+
* | imm[31:12] | rd | opcode |
107+
* 20 5 7
108+
*/
109+
110+
u32 rd_idx = auipc_rd_idx(opcode);
111+
unsigned long rd_val = addr + auipc_offset(opcode);
112+
113+
if (!rv_insn_reg_set_val(regs, rd_idx, rd_val))
114+
return false;
115+
116+
instruction_pointer_set(regs, addr + 4);
117+
118+
return true;
119+
}
120+
121+
#define branch_rs1_idx(opcode) \
122+
(((opcode) >> 15) & 0x1f)
123+
124+
#define branch_rs2_idx(opcode) \
125+
(((opcode) >> 20) & 0x1f)
126+
127+
#define branch_funct3(opcode) \
128+
(((opcode) >> 12) & 0x7)
129+
130+
#define branch_imm(opcode) \
131+
(((((opcode) >> 8) & 0xf ) << 1) | \
132+
((((opcode) >> 25) & 0x3f) << 5) | \
133+
((((opcode) >> 7) & 0x1 ) << 11) | \
134+
((((opcode) >> 31) & 0x1 ) << 12))
135+
136+
#define branch_offset(opcode) \
137+
sign_extend32((branch_imm(opcode)), 12)
138+
139+
#define BRANCH_BEQ 0x0
140+
#define BRANCH_BNE 0x1
141+
#define BRANCH_BLT 0x4
142+
#define BRANCH_BGE 0x5
143+
#define BRANCH_BLTU 0x6
144+
#define BRANCH_BGEU 0x7
145+
146+
bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs)
147+
{
148+
/*
149+
* branch instructions:
150+
* 31 30 25 24 20 19 15 14 12 11 8 7 6 0
151+
* | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode |
152+
* 1 6 5 5 3 4 1 7
153+
* imm[12|10:5] rs2 rs1 000 imm[4:1|11] 1100011 BEQ
154+
* imm[12|10:5] rs2 rs1 001 imm[4:1|11] 1100011 BNE
155+
* imm[12|10:5] rs2 rs1 100 imm[4:1|11] 1100011 BLT
156+
* imm[12|10:5] rs2 rs1 101 imm[4:1|11] 1100011 BGE
157+
* imm[12|10:5] rs2 rs1 110 imm[4:1|11] 1100011 BLTU
158+
* imm[12|10:5] rs2 rs1 111 imm[4:1|11] 1100011 BGEU
159+
*/
160+
161+
s32 offset;
162+
s32 offset_tmp;
163+
unsigned long rs1_val;
164+
unsigned long rs2_val;
165+
166+
if (!rv_insn_reg_get_val(regs, branch_rs1_idx(opcode), &rs1_val) ||
167+
!rv_insn_reg_get_val(regs, branch_rs2_idx(opcode), &rs2_val))
168+
return false;
169+
170+
offset_tmp = branch_offset(opcode);
171+
switch (branch_funct3(opcode)) {
172+
case BRANCH_BEQ:
173+
offset = (rs1_val == rs2_val) ? offset_tmp : 4;
174+
break;
175+
case BRANCH_BNE:
176+
offset = (rs1_val != rs2_val) ? offset_tmp : 4;
177+
break;
178+
case BRANCH_BLT:
179+
offset = ((long)rs1_val < (long)rs2_val) ? offset_tmp : 4;
180+
break;
181+
case BRANCH_BGE:
182+
offset = ((long)rs1_val >= (long)rs2_val) ? offset_tmp : 4;
183+
break;
184+
case BRANCH_BLTU:
185+
offset = (rs1_val < rs2_val) ? offset_tmp : 4;
186+
break;
187+
case BRANCH_BGEU:
188+
offset = (rs1_val >= rs2_val) ? offset_tmp : 4;
189+
break;
190+
default:
191+
return false;
192+
}
193+
194+
instruction_pointer_set(regs, addr + offset);
195+
196+
return true;
197+
}

arch/riscv/kernel/setup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ static void __init parse_dtb(void)
255255

256256
pr_err("No DTB passed to the kernel\n");
257257
#ifdef CONFIG_CMDLINE_FORCE
258-
strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
258+
strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
259259
pr_info("Forcing kernel command line to: %s\n", boot_command_line);
260260
#endif
261261
}

0 commit comments

Comments
 (0)