Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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
...

+256 -127
+27
Documentation/devicetree/bindings/riscv/starfive.yaml
··· 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 <michael.zhu@starfivetech.com> 11 + - Drew Fustini <drew@beagleboard.org> 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 + ...
+9 -3
arch/riscv/Kconfig
··· 13 13 config RISCV 14 14 def_bool y 15 15 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 19 17 select ARCH_HAS_BINFMT_FLAT 20 18 select ARCH_HAS_DEBUG_VM_PGTABLE 21 19 select ARCH_HAS_DEBUG_VIRTUAL if MMU ··· 29 31 select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL 30 32 select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL 31 33 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST 34 + select ARCH_HAS_UBSAN_SANITIZE_ALL 32 35 select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX 33 36 select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT 37 + select ARCH_STACKWALK 38 + select ARCH_SUPPORTS_ATOMIC_RMW 39 + select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU 34 40 select ARCH_SUPPORTS_HUGETLBFS if MMU 35 41 select ARCH_USE_MEMTEST 36 42 select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU ··· 50 48 select GENERIC_CLOCKEVENTS_BROADCAST if SMP 51 49 select GENERIC_EARLY_IOREMAP 52 50 select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO 51 + select GENERIC_IDLE_POLL_SETUP 53 52 select GENERIC_IOREMAP 54 53 select GENERIC_IRQ_MULTI_HANDLER 55 54 select GENERIC_IRQ_SHOW 55 + select GENERIC_IRQ_SHOW_LEVEL 56 56 select GENERIC_LIB_DEVMEM_IS_ALLOWED 57 57 select GENERIC_PCI_IOMAP 58 58 select GENERIC_PTDUMP if MMU ··· 74 70 select HAVE_ARCH_SECCOMP_FILTER 75 71 select HAVE_ARCH_TRACEHOOK 76 72 select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT && MMU 73 + select HAVE_ARCH_THREAD_STRUCT_WHITELIST 77 74 select HAVE_ARCH_VMAP_STACK if MMU && 64BIT 78 75 select HAVE_ASM_MODVERSIONS 79 76 select HAVE_CONTEXT_TRACKING ··· 100 95 select HAVE_STACKPROTECTOR 101 96 select HAVE_SYSCALL_TRACEPOINTS 102 97 select IRQ_DOMAIN 98 + select IRQ_FORCED_THREADING 103 99 select MODULES_USE_ELF_RELA if MODULES 104 100 select MODULE_SECTIONS if MODULES 105 101 select OF
+6
arch/riscv/Makefile
··· 108 108 vdso_install: 109 109 $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@ 110 110 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 + 111 117 ifneq ($(CONFIG_XIP_KERNEL),y) 112 118 ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy) 113 119 KBUILD_IMAGE := $(boot)/loader.bin
+5 -16
arch/riscv/include/asm/page.h
··· 79 79 #endif 80 80 81 81 #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) 84 84 #else 85 85 #define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) 86 86 #endif /* CONFIG_MMU */ ··· 91 91 uintptr_t size; 92 92 /* Offset between linear mapping virtual address and kernel load address */ 93 93 unsigned long va_pa_offset; 94 - #ifdef CONFIG_64BIT 95 94 /* Offset between kernel mapping virtual address and kernel load address */ 96 95 unsigned long va_kernel_pa_offset; 97 - #endif 98 96 unsigned long va_kernel_xip_pa_offset; 99 97 #ifdef CONFIG_XIP_KERNEL 100 98 uintptr_t xiprom; ··· 103 105 extern struct kernel_mapping kernel_map; 104 106 extern phys_addr_t phys_ram_base; 105 107 106 - #ifdef CONFIG_64BIT 107 108 #define is_kernel_mapping(x) \ 108 109 ((x) >= kernel_map.virt_addr && (x) < (kernel_map.virt_addr + kernel_map.size)) 110 + 109 111 #define is_linear_mapping(x) \ 110 - ((x) >= PAGE_OFFSET && (x) < kernel_map.virt_addr) 112 + ((x) >= PAGE_OFFSET && (!IS_ENABLED(CONFIG_64BIT) || (x) < kernel_map.virt_addr)) 111 113 112 114 #define linear_mapping_pa_to_va(x) ((void *)((unsigned long)(x) + kernel_map.va_pa_offset)) 113 115 #define kernel_mapping_pa_to_va(y) ({ \ ··· 121 123 #define linear_mapping_va_to_pa(x) ((unsigned long)(x) - kernel_map.va_pa_offset) 122 124 #define kernel_mapping_va_to_pa(y) ({ \ 123 125 unsigned long _y = y; \ 124 - (_y < kernel_map.virt_addr + XIP_OFFSET) ? \ 126 + (IS_ENABLED(CONFIG_XIP_KERNEL) && _y < kernel_map.virt_addr + XIP_OFFSET) ? \ 125 127 ((unsigned long)(_y) - kernel_map.va_kernel_xip_pa_offset) : \ 126 128 ((unsigned long)(_y) - kernel_map.va_kernel_pa_offset - XIP_OFFSET); \ 127 129 }) ··· 131 133 is_linear_mapping(_x) ? \ 132 134 linear_mapping_va_to_pa(_x) : kernel_mapping_va_to_pa(_x); \ 133 135 }) 134 - #else 135 - #define is_kernel_mapping(x) \ 136 - ((x) >= kernel_map.virt_addr && (x) < (kernel_map.virt_addr + kernel_map.size)) 137 - #define is_linear_mapping(x) \ 138 - ((x) >= PAGE_OFFSET) 139 - 140 - #define __pa_to_va_nodebug(x) ((void *)((unsigned long) (x) + kernel_map.va_pa_offset)) 141 - #define __va_to_pa_nodebug(x) ((unsigned long)(x) - kernel_map.va_pa_offset) 142 - #endif /* CONFIG_64BIT */ 143 136 144 137 #ifdef CONFIG_DEBUG_VIRTUAL 145 138 extern phys_addr_t __virt_to_phys(unsigned long x);
+8
arch/riscv/include/asm/processor.h
··· 37 37 unsigned long bad_cause; 38 38 }; 39 39 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 + 40 48 #define INIT_THREAD { \ 41 49 .sp = sizeof(init_stack) + (long)&init_stack, \ 42 50 }
+11 -12
arch/riscv/include/asm/vdso.h
··· 8 8 #ifndef _ASM_RISCV_VDSO_H 9 9 #define _ASM_RISCV_VDSO_H 10 10 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 + 11 18 #include <linux/types.h> 19 + #include <generated/vdso-offsets.h> 12 20 13 21 #ifndef CONFIG_GENERIC_TIME_VSYSCALL 14 22 struct vdso_data { 15 23 }; 16 24 #endif 17 25 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 - */ 26 26 #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 */ 31 30 32 31 asmlinkage long sys_riscv_flush_icache(uintptr_t, uintptr_t, uintptr_t); 33 32
+2 -3
arch/riscv/kernel/probes/decode-insn.c
··· 38 38 RISCV_INSN_REJECTED(c_ebreak, insn); 39 39 #endif 40 40 41 - RISCV_INSN_REJECTED(auipc, insn); 42 - RISCV_INSN_REJECTED(branch, insn); 43 - 44 41 RISCV_INSN_SET_SIMULATE(jal, insn); 45 42 RISCV_INSN_SET_SIMULATE(jalr, insn); 43 + RISCV_INSN_SET_SIMULATE(auipc, insn); 44 + RISCV_INSN_SET_SIMULATE(branch, insn); 46 45 47 46 return INSN_GOOD; 48 47 }
+112
arch/riscv/kernel/probes/simulate-insn.c
··· 83 83 84 84 return ret; 85 85 } 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 + }
+1 -1
arch/riscv/kernel/setup.c
··· 255 255 256 256 pr_err("No DTB passed to the kernel\n"); 257 257 #ifdef CONFIG_CMDLINE_FORCE 258 - strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); 258 + strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); 259 259 pr_info("Forcing kernel command line to: %s\n", boot_command_line); 260 260 #endif 261 261 }
+12 -14
arch/riscv/kernel/vdso/Makefile
··· 23 23 endif 24 24 25 25 # Build rules 26 - targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-syms.S 26 + targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds 27 27 obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) 28 28 29 - obj-y += vdso.o vdso-syms.o 29 + obj-y += vdso.o 30 30 CPPFLAGS_vdso.lds += -P -C -U$(ARCH) 31 31 32 32 # Disable -pg to prevent insert call site ··· 36 36 GCOV_PROFILE := n 37 37 KCOV_INSTRUMENT := n 38 38 KASAN_SANITIZE := n 39 + UBSAN_SANITIZE := n 39 40 40 41 # Force dependency 41 42 $(obj)/vdso.o: $(obj)/vdso.so ··· 44 43 # link rule for the .so file, .lds has to be first 45 44 $(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE 46 45 $(call if_changed,vdsold) 47 - LDFLAGS_vdso.so.dbg = -shared -s -soname=linux-vdso.so.1 \ 46 + LDFLAGS_vdso.so.dbg = -shared -S -soname=linux-vdso.so.1 \ 48 47 --build-id=sha1 --hash-style=both --eh-frame-hdr 49 - 50 - # We also create a special relocatable object that should mirror the symbol 51 - # table and layout of the linked DSO. With ld --just-symbols we can then 52 - # refer to these symbols in the kernel code rather than hand-coded addresses. 53 - $(obj)/vdso-syms.S: $(obj)/vdso.so FORCE 54 - $(call if_changed,so2s) 55 48 56 49 # strip rule for the .so file 57 50 $(obj)/%.so: OBJCOPYFLAGS := -S 58 51 $(obj)/%.so: $(obj)/%.so.dbg FORCE 59 52 $(call if_changed,objcopy) 53 + 54 + # Generate VDSO offsets using helper script 55 + gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh 56 + quiet_cmd_vdsosym = VDSOSYM $@ 57 + cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ 58 + 59 + include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE 60 + $(call if_changed,vdsosym) 60 61 61 62 # actual build commands 62 63 # The DSO images are built using a special linker script ··· 67 64 cmd_vdsold = $(LD) $(ld_flags) -T $(filter-out FORCE,$^) -o $@.tmp && \ 68 65 $(OBJCOPY) $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \ 69 66 rm $@.tmp 70 - 71 - # Extracts symbol offsets from the VDSO, converting them into an assembly file 72 - # that contains the same symbols at the same offsets. 73 - quiet_cmd_so2s = SO2S $@ 74 - cmd_so2s = $(NM) -D $< | $(srctree)/$(src)/so2s.sh > $@ 75 67 76 68 # install commands for the unstripped file 77 69 quiet_cmd_vdso_install = INSTALL $@
+5
arch/riscv/kernel/vdso/gen_vdso_offsets.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + LC_ALL=C 5 + sed -n -e 's/^[0]\+\(0[0-9a-fA-F]*\) . \(__vdso_[a-zA-Z0-9_]*\)$/\#define \2_offset\t0x\1/p'
-6
arch/riscv/kernel/vdso/so2s.sh
··· 1 - #!/bin/sh 2 - # SPDX-License-Identifier: GPL-2.0+ 3 - # Copyright 2020 Palmer Dabbelt <palmerdabbelt@google.com> 4 - 5 - sed 's!\([0-9a-f]*\) T \([a-z0-9_]*\)\(@@LINUX_4.15\)*!.global \2\n.set \2,0x\1!' \ 6 - | grep '^\.'
+58 -72
arch/riscv/mm/init.c
··· 19 19 #include <linux/set_memory.h> 20 20 #include <linux/dma-map-ops.h> 21 21 #include <linux/crash_dump.h> 22 + #include <linux/hugetlb.h> 22 23 23 24 #include <asm/fixmap.h> 24 25 #include <asm/tlbflush.h> ··· 223 222 224 223 early_init_fdt_scan_reserved_mem(); 225 224 dma_contiguous_reserve(dma32_phys_limit); 225 + if (IS_ENABLED(CONFIG_64BIT)) 226 + hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT); 226 227 memblock_allow_resize(); 227 228 } 228 229 ··· 237 234 #define pt_ops _pt_ops 238 235 #endif 239 236 240 - unsigned long pfn_base __ro_after_init; 241 - EXPORT_SYMBOL(pfn_base); 237 + unsigned long riscv_pfn_base __ro_after_init; 238 + EXPORT_SYMBOL(riscv_pfn_base); 242 239 243 240 pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss; 244 241 pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss; 245 242 static pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss; 246 243 247 244 pgd_t early_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); 245 + static pmd_t __maybe_unused early_dtb_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE); 248 246 249 247 #ifdef CONFIG_XIP_KERNEL 250 248 #define trampoline_pg_dir ((pgd_t *)XIP_FIXUP(trampoline_pg_dir)) ··· 326 322 static pmd_t trampoline_pmd[PTRS_PER_PMD] __page_aligned_bss; 327 323 static pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bss; 328 324 static pmd_t early_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE); 329 - static pmd_t early_dtb_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE); 330 325 331 326 #ifdef CONFIG_XIP_KERNEL 332 327 #define trampoline_pmd ((pmd_t *)XIP_FIXUP(trampoline_pmd)) ··· 411 408 #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \ 412 409 create_pte_mapping(__nextp, __va, __pa, __sz, __prot) 413 410 #define fixmap_pgd_next fixmap_pte 411 + #define create_pmd_mapping(__pmdp, __va, __pa, __sz, __prot) 414 412 #endif 415 413 416 414 void __init create_pgd_mapping(pgd_t *pgdp, ··· 519 515 #endif 520 516 521 517 #ifdef CONFIG_XIP_KERNEL 522 - static void __init create_kernel_page_table(pgd_t *pgdir, uintptr_t map_size, 518 + static void __init create_kernel_page_table(pgd_t *pgdir, 523 519 __always_unused bool early) 524 520 { 525 521 uintptr_t va, end_va; 526 522 527 523 /* Map the flash resident part */ 528 524 end_va = kernel_map.virt_addr + kernel_map.xiprom_sz; 529 - for (va = kernel_map.virt_addr; va < end_va; va += map_size) 525 + for (va = kernel_map.virt_addr; va < end_va; va += PMD_SIZE) 530 526 create_pgd_mapping(pgdir, va, 531 527 kernel_map.xiprom + (va - kernel_map.virt_addr), 532 - map_size, PAGE_KERNEL_EXEC); 528 + PMD_SIZE, PAGE_KERNEL_EXEC); 533 529 534 530 /* Map the data in RAM */ 535 531 end_va = kernel_map.virt_addr + XIP_OFFSET + kernel_map.size; 536 - for (va = kernel_map.virt_addr + XIP_OFFSET; va < end_va; va += map_size) 532 + for (va = kernel_map.virt_addr + XIP_OFFSET; va < end_va; va += PMD_SIZE) 537 533 create_pgd_mapping(pgdir, va, 538 534 kernel_map.phys_addr + (va - (kernel_map.virt_addr + XIP_OFFSET)), 539 - map_size, PAGE_KERNEL); 535 + PMD_SIZE, PAGE_KERNEL); 540 536 } 541 537 #else 542 - static void __init create_kernel_page_table(pgd_t *pgdir, uintptr_t map_size, 543 - bool early) 538 + static void __init create_kernel_page_table(pgd_t *pgdir, bool early) 544 539 { 545 540 uintptr_t va, end_va; 546 541 547 542 end_va = kernel_map.virt_addr + kernel_map.size; 548 - for (va = kernel_map.virt_addr; va < end_va; va += map_size) 543 + for (va = kernel_map.virt_addr; va < end_va; va += PMD_SIZE) 549 544 create_pgd_mapping(pgdir, va, 550 545 kernel_map.phys_addr + (va - kernel_map.virt_addr), 551 - map_size, 546 + PMD_SIZE, 552 547 early ? 553 548 PAGE_KERNEL_EXEC : pgprot_from_va(va)); 554 549 } 555 550 #endif 556 551 552 + /* 553 + * Setup a 4MB mapping that encompasses the device tree: for 64-bit kernel, 554 + * this means 2 PMD entries whereas for 32-bit kernel, this is only 1 PGDIR 555 + * entry. 556 + */ 557 + static void __init create_fdt_early_page_table(pgd_t *pgdir, uintptr_t dtb_pa) 558 + { 559 + #ifndef CONFIG_BUILTIN_DTB 560 + uintptr_t pa = dtb_pa & ~(PMD_SIZE - 1); 561 + 562 + create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA, 563 + IS_ENABLED(CONFIG_64BIT) ? (uintptr_t)early_dtb_pmd : pa, 564 + PGDIR_SIZE, 565 + IS_ENABLED(CONFIG_64BIT) ? PAGE_TABLE : PAGE_KERNEL); 566 + 567 + if (IS_ENABLED(CONFIG_64BIT)) { 568 + create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA, 569 + pa, PMD_SIZE, PAGE_KERNEL); 570 + create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA + PMD_SIZE, 571 + pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL); 572 + } 573 + 574 + dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PMD_SIZE - 1)); 575 + #else 576 + /* 577 + * For 64-bit kernel, __va can't be used since it would return a linear 578 + * mapping address whereas dtb_early_va will be used before 579 + * setup_vm_final installs the linear mapping. For 32-bit kernel, as the 580 + * kernel is mapped in the linear mapping, that makes no difference. 581 + */ 582 + dtb_early_va = kernel_mapping_pa_to_va(XIP_FIXUP(dtb_pa)); 583 + #endif 584 + 585 + dtb_early_pa = dtb_pa; 586 + } 587 + 557 588 asmlinkage void __init setup_vm(uintptr_t dtb_pa) 558 589 { 559 - uintptr_t __maybe_unused pa; 560 - uintptr_t map_size; 561 - #ifndef __PAGETABLE_PMD_FOLDED 562 - pmd_t fix_bmap_spmd, fix_bmap_epmd; 563 - #endif 590 + pmd_t __maybe_unused fix_bmap_spmd, fix_bmap_epmd; 564 591 565 592 kernel_map.virt_addr = KERNEL_LINK_ADDR; 566 593 ··· 608 573 kernel_map.phys_addr = (uintptr_t)(&_start); 609 574 kernel_map.size = (uintptr_t)(&_end) - kernel_map.phys_addr; 610 575 #endif 611 - 612 576 kernel_map.va_pa_offset = PAGE_OFFSET - kernel_map.phys_addr; 613 - #ifdef CONFIG_64BIT 614 577 kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr; 615 - #endif 616 578 617 - pfn_base = PFN_DOWN(kernel_map.phys_addr); 618 - 619 - /* 620 - * Enforce boot alignment requirements of RV32 and 621 - * RV64 by only allowing PMD or PGD mappings. 622 - */ 623 - map_size = PMD_SIZE; 579 + riscv_pfn_base = PFN_DOWN(kernel_map.phys_addr); 624 580 625 581 /* Sanity check alignment and size */ 626 582 BUG_ON((PAGE_OFFSET % PGDIR_SIZE) != 0); 627 - BUG_ON((kernel_map.phys_addr % map_size) != 0); 583 + BUG_ON((kernel_map.phys_addr % PMD_SIZE) != 0); 628 584 629 585 #ifdef CONFIG_64BIT 630 586 /* ··· 660 634 * us to reach paging_init(). We map all memory banks later 661 635 * in setup_vm_final() below. 662 636 */ 663 - create_kernel_page_table(early_pg_dir, map_size, true); 637 + create_kernel_page_table(early_pg_dir, true); 664 638 665 - #ifndef __PAGETABLE_PMD_FOLDED 666 - /* Setup early PMD for DTB */ 667 - create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA, 668 - (uintptr_t)early_dtb_pmd, PGDIR_SIZE, PAGE_TABLE); 669 - #ifndef CONFIG_BUILTIN_DTB 670 - /* Create two consecutive PMD mappings for FDT early scan */ 671 - pa = dtb_pa & ~(PMD_SIZE - 1); 672 - create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA, 673 - pa, PMD_SIZE, PAGE_KERNEL); 674 - create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA + PMD_SIZE, 675 - pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL); 676 - dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PMD_SIZE - 1)); 677 - #else /* CONFIG_BUILTIN_DTB */ 678 - #ifdef CONFIG_64BIT 679 - /* 680 - * __va can't be used since it would return a linear mapping address 681 - * whereas dtb_early_va will be used before setup_vm_final installs 682 - * the linear mapping. 683 - */ 684 - dtb_early_va = kernel_mapping_pa_to_va(XIP_FIXUP(dtb_pa)); 685 - #else 686 - dtb_early_va = __va(dtb_pa); 687 - #endif /* CONFIG_64BIT */ 688 - #endif /* CONFIG_BUILTIN_DTB */ 689 - #else 690 - #ifndef CONFIG_BUILTIN_DTB 691 - /* Create two consecutive PGD mappings for FDT early scan */ 692 - pa = dtb_pa & ~(PGDIR_SIZE - 1); 693 - create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA, 694 - pa, PGDIR_SIZE, PAGE_KERNEL); 695 - create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA + PGDIR_SIZE, 696 - pa + PGDIR_SIZE, PGDIR_SIZE, PAGE_KERNEL); 697 - dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PGDIR_SIZE - 1)); 698 - #else /* CONFIG_BUILTIN_DTB */ 699 - #ifdef CONFIG_64BIT 700 - dtb_early_va = kernel_mapping_pa_to_va(XIP_FIXUP(dtb_pa)); 701 - #else 702 - dtb_early_va = __va(dtb_pa); 703 - #endif /* CONFIG_64BIT */ 704 - #endif /* CONFIG_BUILTIN_DTB */ 705 - #endif 706 - dtb_early_pa = dtb_pa; 639 + /* Setup early mapping for FDT early scan */ 640 + create_fdt_early_page_table(early_pg_dir, dtb_pa); 707 641 708 642 /* 709 643 * Bootime fixmap only can handle PMD_SIZE mapping. Thus, boot-ioremap ··· 738 752 739 753 #ifdef CONFIG_64BIT 740 754 /* Map the kernel */ 741 - create_kernel_page_table(swapper_pg_dir, PMD_SIZE, false); 755 + create_kernel_page_table(swapper_pg_dir, false); 742 756 #endif 743 757 744 758 /* Clear fixmap PTE and PMD mappings */