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

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

Pull more RISC-V updates from Palmer Dabbelt:

- Support for handling misaligned accesses in S-mode

- Probing for misaligned access support is now properly cached and
handled in parallel

- PTDUMP now reflects the SW reserved bits, as well as the PBMT and
NAPOT extensions

- Performance improvements for TLB flushing

- Support for many new relocations in the module loader

- Various bug fixes and cleanups

* tag 'riscv-for-linus-6.7-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (51 commits)
riscv: Optimize bitops with Zbb extension
riscv: Rearrange hwcap.h and cpufeature.h
drivers: perf: Do not broadcast to other cpus when starting a counter
drivers: perf: Check find_first_bit() return value
of: property: Add fw_devlink support for msi-parent
RISC-V: Don't fail in riscv_of_parent_hartid() for disabled HARTs
riscv: Fix set_memory_XX() and set_direct_map_XX() by splitting huge linear mappings
riscv: Don't use PGD entries for the linear mapping
RISC-V: Probe misaligned access speed in parallel
RISC-V: Remove __init on unaligned_emulation_finish()
RISC-V: Show accurate per-hart isa in /proc/cpuinfo
RISC-V: Don't rely on positional structure initialization
riscv: Add tests for riscv module loading
riscv: Add remaining module relocations
riscv: Avoid unaligned access when relocating modules
riscv: split cache ops out of dma-noncoherent.c
riscv: Improve flush_tlb_kernel_range()
riscv: Make __flush_tlb_range() loop over pte instead of flushing the whole tlb
riscv: Improve flush_tlb_range() for hugetlb pages
riscv: Improve tlb_flush()
...

+2558 -707
+20
Documentation/arch/riscv/uabi.rst
··· 42 42 43 43 rv64imadc_zifoo_zigoo_zafoo_sbar_scar_zxmbaz_xqux_xrux 44 44 45 + "isa" and "hart isa" lines in /proc/cpuinfo 46 + ------------------------------------------- 47 + 48 + The "isa" line in /proc/cpuinfo describes the lowest common denominator of 49 + RISC-V ISA extensions recognized by the kernel and implemented on all harts. The 50 + "hart isa" line, in contrast, describes the set of extensions recognized by the 51 + kernel on the particular hart being described, even if those extensions may not 52 + be present on all harts in the system. 53 + 54 + In both lines, the presence of an extension guarantees only that the hardware 55 + has the described capability. Additional kernel support or policy changes may be 56 + required before an extension's capability is fully usable by userspace programs. 57 + Similarly, for S-mode extensions, presence in one of these lines does not 58 + guarantee that the kernel is taking advantage of the extension, or that the 59 + feature will be visible in guest VMs managed by this kernel. 60 + 61 + Inversely, the absence of an extension in these lines does not necessarily mean 62 + the hardware does not support that feature. The running kernel may not recognize 63 + the extension, or may have deliberately removed it from the listing. 64 + 45 65 Misaligned accesses 46 66 ------------------- 47 67
+12
arch/riscv/Kconfig
··· 642 642 Specify the Pages of thread stack size (from 4KB to 64KB), which also 643 643 affects irq stack size, which is equal to thread stack size. 644 644 645 + config RISCV_MISALIGNED 646 + bool "Support misaligned load/store traps for kernel and userspace" 647 + select SYSCTL_ARCH_UNALIGN_ALLOW 648 + default y 649 + help 650 + Say Y here if you want the kernel to embed support for misaligned 651 + load/store for both kernel and userspace. When disable, misaligned 652 + accesses will generate SIGBUS in userspace and panic in kernel. 653 + 645 654 endmenu # "Platform type" 646 655 647 656 menu "Kernel features" ··· 917 908 select EFI 918 909 select MMU 919 910 select OF 911 + 912 + config ARCH_PROC_KCORE_TEXT 913 + def_bool y 920 914 921 915 menu "Power management options" 922 916
+1
arch/riscv/Kconfig.debug
··· 1 + source "arch/riscv/kernel/tests/Kconfig.debug"
+1
arch/riscv/boot/Makefile
··· 17 17 KCOV_INSTRUMENT := n 18 18 19 19 OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S 20 + OBJCOPYFLAGS_loader.bin :=-O binary 20 21 OBJCOPYFLAGS_xipImage :=-O binary -R .note -R .note.gnu.build-id -R .comment -S 21 22 22 23 targets := Image Image.* loader loader.o loader.lds loader.bin
+2
arch/riscv/configs/defconfig
··· 215 215 CONFIG_MMC_SDHCI_PLTFM=y 216 216 CONFIG_MMC_SDHCI_CADENCE=y 217 217 CONFIG_MMC_SPI=y 218 + CONFIG_MMC_DW=y 219 + CONFIG_MMC_DW_STARFIVE=y 218 220 CONFIG_MMC_SDHI=y 219 221 CONFIG_MMC_SUNXI=y 220 222 CONFIG_RTC_CLASS=y
+251 -3
arch/riscv/include/asm/bitops.h
··· 15 15 #include <asm/barrier.h> 16 16 #include <asm/bitsperlong.h> 17 17 18 + #if !defined(CONFIG_RISCV_ISA_ZBB) || defined(NO_ALTERNATIVE) 18 19 #include <asm-generic/bitops/__ffs.h> 19 - #include <asm-generic/bitops/ffz.h> 20 - #include <asm-generic/bitops/fls.h> 21 20 #include <asm-generic/bitops/__fls.h> 21 + #include <asm-generic/bitops/ffs.h> 22 + #include <asm-generic/bitops/fls.h> 23 + 24 + #else 25 + #include <asm/alternative-macros.h> 26 + #include <asm/hwcap.h> 27 + 28 + #if (BITS_PER_LONG == 64) 29 + #define CTZW "ctzw " 30 + #define CLZW "clzw " 31 + #elif (BITS_PER_LONG == 32) 32 + #define CTZW "ctz " 33 + #define CLZW "clz " 34 + #else 35 + #error "Unexpected BITS_PER_LONG" 36 + #endif 37 + 38 + static __always_inline unsigned long variable__ffs(unsigned long word) 39 + { 40 + int num; 41 + 42 + asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 43 + RISCV_ISA_EXT_ZBB, 1) 44 + : : : : legacy); 45 + 46 + asm volatile (".option push\n" 47 + ".option arch,+zbb\n" 48 + "ctz %0, %1\n" 49 + ".option pop\n" 50 + : "=r" (word) : "r" (word) :); 51 + 52 + return word; 53 + 54 + legacy: 55 + num = 0; 56 + #if BITS_PER_LONG == 64 57 + if ((word & 0xffffffff) == 0) { 58 + num += 32; 59 + word >>= 32; 60 + } 61 + #endif 62 + if ((word & 0xffff) == 0) { 63 + num += 16; 64 + word >>= 16; 65 + } 66 + if ((word & 0xff) == 0) { 67 + num += 8; 68 + word >>= 8; 69 + } 70 + if ((word & 0xf) == 0) { 71 + num += 4; 72 + word >>= 4; 73 + } 74 + if ((word & 0x3) == 0) { 75 + num += 2; 76 + word >>= 2; 77 + } 78 + if ((word & 0x1) == 0) 79 + num += 1; 80 + return num; 81 + } 82 + 83 + /** 84 + * __ffs - find first set bit in a long word 85 + * @word: The word to search 86 + * 87 + * Undefined if no set bit exists, so code should check against 0 first. 88 + */ 89 + #define __ffs(word) \ 90 + (__builtin_constant_p(word) ? \ 91 + (unsigned long)__builtin_ctzl(word) : \ 92 + variable__ffs(word)) 93 + 94 + static __always_inline unsigned long variable__fls(unsigned long word) 95 + { 96 + int num; 97 + 98 + asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 99 + RISCV_ISA_EXT_ZBB, 1) 100 + : : : : legacy); 101 + 102 + asm volatile (".option push\n" 103 + ".option arch,+zbb\n" 104 + "clz %0, %1\n" 105 + ".option pop\n" 106 + : "=r" (word) : "r" (word) :); 107 + 108 + return BITS_PER_LONG - 1 - word; 109 + 110 + legacy: 111 + num = BITS_PER_LONG - 1; 112 + #if BITS_PER_LONG == 64 113 + if (!(word & (~0ul << 32))) { 114 + num -= 32; 115 + word <<= 32; 116 + } 117 + #endif 118 + if (!(word & (~0ul << (BITS_PER_LONG - 16)))) { 119 + num -= 16; 120 + word <<= 16; 121 + } 122 + if (!(word & (~0ul << (BITS_PER_LONG - 8)))) { 123 + num -= 8; 124 + word <<= 8; 125 + } 126 + if (!(word & (~0ul << (BITS_PER_LONG - 4)))) { 127 + num -= 4; 128 + word <<= 4; 129 + } 130 + if (!(word & (~0ul << (BITS_PER_LONG - 2)))) { 131 + num -= 2; 132 + word <<= 2; 133 + } 134 + if (!(word & (~0ul << (BITS_PER_LONG - 1)))) 135 + num -= 1; 136 + return num; 137 + } 138 + 139 + /** 140 + * __fls - find last set bit in a long word 141 + * @word: the word to search 142 + * 143 + * Undefined if no set bit exists, so code should check against 0 first. 144 + */ 145 + #define __fls(word) \ 146 + (__builtin_constant_p(word) ? \ 147 + (unsigned long)(BITS_PER_LONG - 1 - __builtin_clzl(word)) : \ 148 + variable__fls(word)) 149 + 150 + static __always_inline int variable_ffs(int x) 151 + { 152 + int r; 153 + 154 + if (!x) 155 + return 0; 156 + 157 + asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 158 + RISCV_ISA_EXT_ZBB, 1) 159 + : : : : legacy); 160 + 161 + asm volatile (".option push\n" 162 + ".option arch,+zbb\n" 163 + CTZW "%0, %1\n" 164 + ".option pop\n" 165 + : "=r" (r) : "r" (x) :); 166 + 167 + return r + 1; 168 + 169 + legacy: 170 + r = 1; 171 + if (!(x & 0xffff)) { 172 + x >>= 16; 173 + r += 16; 174 + } 175 + if (!(x & 0xff)) { 176 + x >>= 8; 177 + r += 8; 178 + } 179 + if (!(x & 0xf)) { 180 + x >>= 4; 181 + r += 4; 182 + } 183 + if (!(x & 3)) { 184 + x >>= 2; 185 + r += 2; 186 + } 187 + if (!(x & 1)) { 188 + x >>= 1; 189 + r += 1; 190 + } 191 + return r; 192 + } 193 + 194 + /** 195 + * ffs - find first set bit in a word 196 + * @x: the word to search 197 + * 198 + * This is defined the same way as the libc and compiler builtin ffs routines. 199 + * 200 + * ffs(value) returns 0 if value is 0 or the position of the first set bit if 201 + * value is nonzero. The first (least significant) bit is at position 1. 202 + */ 203 + #define ffs(x) (__builtin_constant_p(x) ? __builtin_ffs(x) : variable_ffs(x)) 204 + 205 + static __always_inline int variable_fls(unsigned int x) 206 + { 207 + int r; 208 + 209 + if (!x) 210 + return 0; 211 + 212 + asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 213 + RISCV_ISA_EXT_ZBB, 1) 214 + : : : : legacy); 215 + 216 + asm volatile (".option push\n" 217 + ".option arch,+zbb\n" 218 + CLZW "%0, %1\n" 219 + ".option pop\n" 220 + : "=r" (r) : "r" (x) :); 221 + 222 + return 32 - r; 223 + 224 + legacy: 225 + r = 32; 226 + if (!(x & 0xffff0000u)) { 227 + x <<= 16; 228 + r -= 16; 229 + } 230 + if (!(x & 0xff000000u)) { 231 + x <<= 8; 232 + r -= 8; 233 + } 234 + if (!(x & 0xf0000000u)) { 235 + x <<= 4; 236 + r -= 4; 237 + } 238 + if (!(x & 0xc0000000u)) { 239 + x <<= 2; 240 + r -= 2; 241 + } 242 + if (!(x & 0x80000000u)) { 243 + x <<= 1; 244 + r -= 1; 245 + } 246 + return r; 247 + } 248 + 249 + /** 250 + * fls - find last set bit in a word 251 + * @x: the word to search 252 + * 253 + * This is defined in a similar way as ffs, but returns the position of the most 254 + * significant set bit. 255 + * 256 + * fls(value) returns 0 if value is 0 or the position of the last set bit if 257 + * value is nonzero. The last (most significant) bit is at position 32. 258 + */ 259 + #define fls(x) \ 260 + ({ \ 261 + typeof(x) x_ = (x); \ 262 + __builtin_constant_p(x_) ? \ 263 + (int)((x_ != 0) ? (32 - __builtin_clz(x_)) : 0) \ 264 + : \ 265 + variable_fls(x_); \ 266 + }) 267 + 268 + #endif /* !defined(CONFIG_RISCV_ISA_ZBB) || defined(NO_ALTERNATIVE) */ 269 + 270 + #include <asm-generic/bitops/ffz.h> 22 271 #include <asm-generic/bitops/fls64.h> 23 272 #include <asm-generic/bitops/sched.h> 24 - #include <asm-generic/bitops/ffs.h> 25 273 26 274 #include <asm-generic/bitops/hweight.h> 27 275
+101 -1
arch/riscv/include/asm/cpufeature.h
··· 7 7 #define _ASM_CPUFEATURE_H 8 8 9 9 #include <linux/bitmap.h> 10 + #include <linux/jump_label.h> 10 11 #include <asm/hwcap.h> 12 + #include <asm/alternative-macros.h> 13 + #include <asm/errno.h> 11 14 12 15 /* 13 16 * These are probed via a device_initcall(), via either the SBI or directly ··· 33 30 /* Per-cpu ISA extensions. */ 34 31 extern struct riscv_isainfo hart_isa[NR_CPUS]; 35 32 36 - void check_unaligned_access(int cpu); 37 33 void riscv_user_isa_enable(void); 34 + 35 + #ifdef CONFIG_RISCV_MISALIGNED 36 + bool unaligned_ctl_available(void); 37 + bool check_unaligned_access_emulated(int cpu); 38 + void unaligned_emulation_finish(void); 39 + #else 40 + static inline bool unaligned_ctl_available(void) 41 + { 42 + return false; 43 + } 44 + 45 + static inline bool check_unaligned_access_emulated(int cpu) 46 + { 47 + return false; 48 + } 49 + 50 + static inline void unaligned_emulation_finish(void) {} 51 + #endif 52 + 53 + unsigned long riscv_get_elf_hwcap(void); 54 + 55 + struct riscv_isa_ext_data { 56 + const unsigned int id; 57 + const char *name; 58 + const char *property; 59 + }; 60 + 61 + extern const struct riscv_isa_ext_data riscv_isa_ext[]; 62 + extern const size_t riscv_isa_ext_count; 63 + extern bool riscv_isa_fallback; 64 + 65 + unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap); 66 + 67 + bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit); 68 + #define riscv_isa_extension_available(isa_bitmap, ext) \ 69 + __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext) 70 + 71 + static __always_inline bool 72 + riscv_has_extension_likely(const unsigned long ext) 73 + { 74 + compiletime_assert(ext < RISCV_ISA_EXT_MAX, 75 + "ext must be < RISCV_ISA_EXT_MAX"); 76 + 77 + if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) { 78 + asm_volatile_goto( 79 + ALTERNATIVE("j %l[l_no]", "nop", 0, %[ext], 1) 80 + : 81 + : [ext] "i" (ext) 82 + : 83 + : l_no); 84 + } else { 85 + if (!__riscv_isa_extension_available(NULL, ext)) 86 + goto l_no; 87 + } 88 + 89 + return true; 90 + l_no: 91 + return false; 92 + } 93 + 94 + static __always_inline bool 95 + riscv_has_extension_unlikely(const unsigned long ext) 96 + { 97 + compiletime_assert(ext < RISCV_ISA_EXT_MAX, 98 + "ext must be < RISCV_ISA_EXT_MAX"); 99 + 100 + if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) { 101 + asm_volatile_goto( 102 + ALTERNATIVE("nop", "j %l[l_yes]", 0, %[ext], 1) 103 + : 104 + : [ext] "i" (ext) 105 + : 106 + : l_yes); 107 + } else { 108 + if (__riscv_isa_extension_available(NULL, ext)) 109 + goto l_yes; 110 + } 111 + 112 + return false; 113 + l_yes: 114 + return true; 115 + } 116 + 117 + static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext) 118 + { 119 + if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_likely(ext)) 120 + return true; 121 + 122 + return __riscv_isa_extension_available(hart_isa[cpu].isa, ext); 123 + } 124 + 125 + static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsigned long ext) 126 + { 127 + if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_unlikely(ext)) 128 + return true; 129 + 130 + return __riscv_isa_extension_available(hart_isa[cpu].isa, ext); 131 + } 38 132 39 133 #endif
+1 -1
arch/riscv/include/asm/elf.h
··· 14 14 #include <asm/auxvec.h> 15 15 #include <asm/byteorder.h> 16 16 #include <asm/cacheinfo.h> 17 - #include <asm/hwcap.h> 17 + #include <asm/cpufeature.h> 18 18 19 19 /* 20 20 * These are used to set parameters in the core dumps.
+14
arch/riscv/include/asm/entry-common.h
··· 8 8 void handle_page_fault(struct pt_regs *regs); 9 9 void handle_break(struct pt_regs *regs); 10 10 11 + #ifdef CONFIG_RISCV_MISALIGNED 12 + int handle_misaligned_load(struct pt_regs *regs); 13 + int handle_misaligned_store(struct pt_regs *regs); 14 + #else 15 + static inline int handle_misaligned_load(struct pt_regs *regs) 16 + { 17 + return -1; 18 + } 19 + static inline int handle_misaligned_store(struct pt_regs *regs) 20 + { 21 + return -1; 22 + } 23 + #endif 24 + 11 25 #endif /* _ASM_RISCV_ENTRY_COMMON_H */
+3 -3
arch/riscv/include/asm/errata_list.h
··· 117 117 * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | 118 118 * 0000000 11001 00000 000 00000 0001011 119 119 */ 120 - #define THEAD_inval_A0 ".long 0x0265000b" 121 - #define THEAD_clean_A0 ".long 0x0255000b" 122 - #define THEAD_flush_A0 ".long 0x0275000b" 120 + #define THEAD_INVAL_A0 ".long 0x0265000b" 121 + #define THEAD_CLEAN_A0 ".long 0x0255000b" 122 + #define THEAD_FLUSH_A0 ".long 0x0275000b" 123 123 #define THEAD_SYNC_S ".long 0x0190000b" 124 124 125 125 #define ALT_CMO_OP(_op, _start, _size, _cachesize) \
-91
arch/riscv/include/asm/hwcap.h
··· 8 8 #ifndef _ASM_RISCV_HWCAP_H 9 9 #define _ASM_RISCV_HWCAP_H 10 10 11 - #include <asm/alternative-macros.h> 12 - #include <asm/errno.h> 13 - #include <linux/bits.h> 14 11 #include <uapi/asm/hwcap.h> 15 12 16 13 #define RISCV_ISA_EXT_a ('a' - 'a') ··· 64 67 #define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SMAIA 65 68 #else 66 69 #define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SSAIA 67 - #endif 68 - 69 - #ifndef __ASSEMBLY__ 70 - 71 - #include <linux/jump_label.h> 72 - #include <asm/cpufeature.h> 73 - 74 - unsigned long riscv_get_elf_hwcap(void); 75 - 76 - struct riscv_isa_ext_data { 77 - const unsigned int id; 78 - const char *name; 79 - const char *property; 80 - }; 81 - 82 - extern const struct riscv_isa_ext_data riscv_isa_ext[]; 83 - extern const size_t riscv_isa_ext_count; 84 - extern bool riscv_isa_fallback; 85 - 86 - unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap); 87 - 88 - #define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext) 89 - 90 - bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit); 91 - #define riscv_isa_extension_available(isa_bitmap, ext) \ 92 - __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext) 93 - 94 - static __always_inline bool 95 - riscv_has_extension_likely(const unsigned long ext) 96 - { 97 - compiletime_assert(ext < RISCV_ISA_EXT_MAX, 98 - "ext must be < RISCV_ISA_EXT_MAX"); 99 - 100 - if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) { 101 - asm_volatile_goto( 102 - ALTERNATIVE("j %l[l_no]", "nop", 0, %[ext], 1) 103 - : 104 - : [ext] "i" (ext) 105 - : 106 - : l_no); 107 - } else { 108 - if (!__riscv_isa_extension_available(NULL, ext)) 109 - goto l_no; 110 - } 111 - 112 - return true; 113 - l_no: 114 - return false; 115 - } 116 - 117 - static __always_inline bool 118 - riscv_has_extension_unlikely(const unsigned long ext) 119 - { 120 - compiletime_assert(ext < RISCV_ISA_EXT_MAX, 121 - "ext must be < RISCV_ISA_EXT_MAX"); 122 - 123 - if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) { 124 - asm_volatile_goto( 125 - ALTERNATIVE("nop", "j %l[l_yes]", 0, %[ext], 1) 126 - : 127 - : [ext] "i" (ext) 128 - : 129 - : l_yes); 130 - } else { 131 - if (__riscv_isa_extension_available(NULL, ext)) 132 - goto l_yes; 133 - } 134 - 135 - return false; 136 - l_yes: 137 - return true; 138 - } 139 - 140 - static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext) 141 - { 142 - if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_likely(ext)) 143 - return true; 144 - 145 - return __riscv_isa_extension_available(hart_isa[cpu].isa, ext); 146 - } 147 - 148 - static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsigned long ext) 149 - { 150 - if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_unlikely(ext)) 151 - return true; 152 - 153 - return __riscv_isa_extension_available(hart_isa[cpu].isa, ext); 154 - } 155 70 #endif 156 71 157 72 #endif /* _ASM_RISCV_HWCAP_H */
+4 -4
arch/riscv/include/asm/insn-def.h
··· 180 180 INSN_R(OPCODE_SYSTEM, FUNC3(0), FUNC7(51), \ 181 181 __RD(0), RS1(gaddr), RS2(vmid)) 182 182 183 - #define CBO_inval(base) \ 183 + #define CBO_INVAL(base) \ 184 184 INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \ 185 185 RS1(base), SIMM12(0)) 186 186 187 - #define CBO_clean(base) \ 187 + #define CBO_CLEAN(base) \ 188 188 INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \ 189 189 RS1(base), SIMM12(1)) 190 190 191 - #define CBO_flush(base) \ 191 + #define CBO_FLUSH(base) \ 192 192 INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \ 193 193 RS1(base), SIMM12(2)) 194 194 195 - #define CBO_zero(base) \ 195 + #define CBO_ZERO(base) \ 196 196 INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \ 197 197 RS1(base), SIMM12(4)) 198 198
+9 -5
arch/riscv/include/asm/pgtable-64.h
··· 126 126 127 127 /* 128 128 * [63:59] T-Head Memory Type definitions: 129 - * 130 - * 00000 - NC Weakly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable 129 + * bit[63] SO - Strong Order 130 + * bit[62] C - Cacheable 131 + * bit[61] B - Bufferable 132 + * bit[60] SH - Shareable 133 + * bit[59] Sec - Trustable 134 + * 00110 - NC Weakly-ordered, Non-cacheable, Bufferable, Shareable, Non-trustable 131 135 * 01110 - PMA Weakly-ordered, Cacheable, Bufferable, Shareable, Non-trustable 132 - * 10000 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable 136 + * 10010 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Shareable, Non-trustable 133 137 */ 134 138 #define _PAGE_PMA_THEAD ((1UL << 62) | (1UL << 61) | (1UL << 60)) 135 - #define _PAGE_NOCACHE_THEAD 0UL 136 - #define _PAGE_IO_THEAD (1UL << 63) 139 + #define _PAGE_NOCACHE_THEAD ((1UL < 61) | (1UL << 60)) 140 + #define _PAGE_IO_THEAD ((1UL << 63) | (1UL << 60)) 137 141 #define _PAGE_MTMASK_THEAD (_PAGE_PMA_THEAD | _PAGE_IO_THEAD | (1UL << 59)) 138 142 139 143 static inline u64 riscv_page_mtmask(void)
+2 -2
arch/riscv/include/asm/pgtable-bits.h
··· 16 16 #define _PAGE_GLOBAL (1 << 5) /* Global */ 17 17 #define _PAGE_ACCESSED (1 << 6) /* Set by hardware on any access */ 18 18 #define _PAGE_DIRTY (1 << 7) /* Set by hardware on any write */ 19 - #define _PAGE_SOFT (1 << 8) /* Reserved for software */ 19 + #define _PAGE_SOFT (3 << 8) /* Reserved for software */ 20 20 21 - #define _PAGE_SPECIAL _PAGE_SOFT 21 + #define _PAGE_SPECIAL (1 << 8) /* RSW: 0x1 */ 22 22 #define _PAGE_TABLE _PAGE_PRESENT 23 23 24 24 /*
+1
arch/riscv/include/asm/pgtable.h
··· 291 291 } 292 292 293 293 #ifdef CONFIG_RISCV_ISA_SVNAPOT 294 + #include <asm/cpufeature.h> 294 295 295 296 static __always_inline bool has_svnapot(void) 296 297 {
+9
arch/riscv/include/asm/processor.h
··· 8 8 9 9 #include <linux/const.h> 10 10 #include <linux/cache.h> 11 + #include <linux/prctl.h> 11 12 12 13 #include <vdso/processor.h> 13 14 ··· 83 82 unsigned long bad_cause; 84 83 unsigned long vstate_ctrl; 85 84 struct __riscv_v_ext_state vstate; 85 + unsigned long align_ctl; 86 86 }; 87 87 88 88 /* Whitelist the fstate from the task_struct for hardened usercopy */ ··· 96 94 97 95 #define INIT_THREAD { \ 98 96 .sp = sizeof(init_stack) + (long)&init_stack, \ 97 + .align_ctl = PR_UNALIGN_NOPRINT, \ 99 98 } 100 99 101 100 #define task_pt_regs(tsk) \ ··· 138 135 extern long riscv_v_vstate_ctrl_set_current(unsigned long arg); 139 136 extern long riscv_v_vstate_ctrl_get_current(void); 140 137 #endif /* CONFIG_RISCV_ISA_V */ 138 + 139 + extern int get_unalign_ctl(struct task_struct *tsk, unsigned long addr); 140 + extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val); 141 + 142 + #define GET_UNALIGN_CTL(tsk, addr) get_unalign_ctl((tsk), (addr)) 143 + #define SET_UNALIGN_CTL(tsk, val) set_unalign_ctl((tsk), (val)) 141 144 142 145 #endif /* __ASSEMBLY__ */ 143 146
-3
arch/riscv/include/asm/sbi.h
··· 280 280 void sbi_shutdown(void); 281 281 void sbi_send_ipi(unsigned int cpu); 282 282 int sbi_remote_fence_i(const struct cpumask *cpu_mask); 283 - int sbi_remote_sfence_vma(const struct cpumask *cpu_mask, 284 - unsigned long start, 285 - unsigned long size); 286 283 287 284 int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask, 288 285 unsigned long start,
+1 -1
arch/riscv/include/asm/switch_to.h
··· 9 9 #include <linux/jump_label.h> 10 10 #include <linux/sched/task_stack.h> 11 11 #include <asm/vector.h> 12 - #include <asm/hwcap.h> 12 + #include <asm/cpufeature.h> 13 13 #include <asm/processor.h> 14 14 #include <asm/ptrace.h> 15 15 #include <asm/csr.h>
+7 -1
arch/riscv/include/asm/tlb.h
··· 15 15 16 16 static inline void tlb_flush(struct mmu_gather *tlb) 17 17 { 18 - flush_tlb_mm(tlb->mm); 18 + #ifdef CONFIG_MMU 19 + if (tlb->fullmm || tlb->need_flush_all) 20 + flush_tlb_mm(tlb->mm); 21 + else 22 + flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end, 23 + tlb_get_unmap_size(tlb)); 24 + #endif 19 25 } 20 26 21 27 #endif /* _ASM_RISCV_TLB_H */
+11 -4
arch/riscv/include/asm/tlbflush.h
··· 11 11 #include <asm/smp.h> 12 12 #include <asm/errata_list.h> 13 13 14 + #define FLUSH_TLB_MAX_SIZE ((unsigned long)-1) 15 + #define FLUSH_TLB_NO_ASID ((unsigned long)-1) 16 + 14 17 #ifdef CONFIG_MMU 15 18 extern unsigned long asid_mask; 16 19 ··· 35 32 #if defined(CONFIG_SMP) && defined(CONFIG_MMU) 36 33 void flush_tlb_all(void); 37 34 void flush_tlb_mm(struct mm_struct *mm); 35 + void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, 36 + unsigned long end, unsigned int page_size); 38 37 void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr); 39 38 void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 40 39 unsigned long end); 40 + void flush_tlb_kernel_range(unsigned long start, unsigned long end); 41 41 #ifdef CONFIG_TRANSPARENT_HUGEPAGE 42 42 #define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE 43 43 void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, ··· 57 51 local_flush_tlb_all(); 58 52 } 59 53 60 - #define flush_tlb_mm(mm) flush_tlb_all() 61 - #endif /* !CONFIG_SMP || !CONFIG_MMU */ 62 - 63 54 /* Flush a range of kernel pages */ 64 55 static inline void flush_tlb_kernel_range(unsigned long start, 65 56 unsigned long end) 66 57 { 67 - flush_tlb_all(); 58 + local_flush_tlb_all(); 68 59 } 60 + 61 + #define flush_tlb_mm(mm) flush_tlb_all() 62 + #define flush_tlb_mm_range(mm, start, end, page_size) flush_tlb_all() 63 + #endif /* !CONFIG_SMP || !CONFIG_MMU */ 69 64 70 65 #endif /* _ASM_RISCV_TLBFLUSH_H */
+1 -1
arch/riscv/include/asm/vector.h
··· 15 15 #include <linux/sched.h> 16 16 #include <linux/sched/task_stack.h> 17 17 #include <asm/ptrace.h> 18 - #include <asm/hwcap.h> 18 + #include <asm/cpufeature.h> 19 19 #include <asm/csr.h> 20 20 #include <asm/asm.h> 21 21
+4 -1
arch/riscv/include/uapi/asm/elf.h
··· 49 49 #define R_RISCV_TLS_DTPREL64 9 50 50 #define R_RISCV_TLS_TPREL32 10 51 51 #define R_RISCV_TLS_TPREL64 11 52 + #define R_RISCV_IRELATIVE 58 52 53 53 54 /* Relocation types not used by the dynamic linker */ 54 55 #define R_RISCV_BRANCH 16 ··· 82 81 #define R_RISCV_ALIGN 43 83 82 #define R_RISCV_RVC_BRANCH 44 84 83 #define R_RISCV_RVC_JUMP 45 85 - #define R_RISCV_LUI 46 86 84 #define R_RISCV_GPREL_I 47 87 85 #define R_RISCV_GPREL_S 48 88 86 #define R_RISCV_TPREL_I 49 ··· 93 93 #define R_RISCV_SET16 55 94 94 #define R_RISCV_SET32 56 95 95 #define R_RISCV_32_PCREL 57 96 + #define R_RISCV_PLT32 59 97 + #define R_RISCV_SET_ULEB128 60 98 + #define R_RISCV_SUB_ULEB128 61 96 99 97 100 98 101 #endif /* _UAPI_ASM_RISCV_ELF_H */
+2 -1
arch/riscv/kernel/Makefile
··· 57 57 obj-y += cacheinfo.o 58 58 obj-y += patch.o 59 59 obj-y += probes/ 60 + obj-y += tests/ 60 61 obj-$(CONFIG_MMU) += vdso.o vdso/ 61 62 62 - obj-$(CONFIG_RISCV_M_MODE) += traps_misaligned.o 63 + obj-$(CONFIG_RISCV_MISALIGNED) += traps_misaligned.o 63 64 obj-$(CONFIG_FPU) += fpu.o 64 65 obj-$(CONFIG_RISCV_ISA_V) += vector.o 65 66 obj-$(CONFIG_SMP) += smpboot.o
+4 -4
arch/riscv/kernel/copy-unaligned.S
··· 9 9 /* void __riscv_copy_words_unaligned(void *, const void *, size_t) */ 10 10 /* Performs a memcpy without aligning buffers, using word loads and stores. */ 11 11 /* Note: The size is truncated to a multiple of 8 * SZREG */ 12 - ENTRY(__riscv_copy_words_unaligned) 12 + SYM_FUNC_START(__riscv_copy_words_unaligned) 13 13 andi a4, a2, ~((8*SZREG)-1) 14 14 beqz a4, 2f 15 15 add a3, a1, a4 ··· 36 36 37 37 2: 38 38 ret 39 - END(__riscv_copy_words_unaligned) 39 + SYM_FUNC_END(__riscv_copy_words_unaligned) 40 40 41 41 /* void __riscv_copy_bytes_unaligned(void *, const void *, size_t) */ 42 42 /* Performs a memcpy without aligning buffers, using only byte accesses. */ 43 43 /* Note: The size is truncated to a multiple of 8 */ 44 - ENTRY(__riscv_copy_bytes_unaligned) 44 + SYM_FUNC_START(__riscv_copy_bytes_unaligned) 45 45 andi a4, a2, ~(8-1) 46 46 beqz a4, 2f 47 47 add a3, a1, a4 ··· 68 68 69 69 2: 70 70 ret 71 - END(__riscv_copy_bytes_unaligned) 71 + SYM_FUNC_END(__riscv_copy_bytes_unaligned)
+24 -9
arch/riscv/kernel/cpu.c
··· 125 125 */ 126 126 int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid) 127 127 { 128 - int rc; 129 - 130 128 for (; node; node = node->parent) { 131 129 if (of_device_is_compatible(node, "riscv")) { 132 - rc = riscv_of_processor_hartid(node, hartid); 133 - if (!rc) 134 - return 0; 130 + *hartid = (unsigned long)of_get_cpu_hwid(node, 0); 131 + if (*hartid == ~0UL) { 132 + pr_warn("Found CPU without hart ID\n"); 133 + return -ENODEV; 134 + } 135 + return 0; 135 136 } 136 137 } 137 138 ··· 203 202 204 203 #ifdef CONFIG_PROC_FS 205 204 206 - static void print_isa(struct seq_file *f) 205 + static void print_isa(struct seq_file *f, const unsigned long *isa_bitmap) 207 206 { 208 - seq_puts(f, "isa\t\t: "); 209 207 210 208 if (IS_ENABLED(CONFIG_32BIT)) 211 209 seq_write(f, "rv32", 4); ··· 212 212 seq_write(f, "rv64", 4); 213 213 214 214 for (int i = 0; i < riscv_isa_ext_count; i++) { 215 - if (!__riscv_isa_extension_available(NULL, riscv_isa_ext[i].id)) 215 + if (!__riscv_isa_extension_available(isa_bitmap, riscv_isa_ext[i].id)) 216 216 continue; 217 217 218 218 /* Only multi-letter extensions are split by underscores */ ··· 276 276 277 277 seq_printf(m, "processor\t: %lu\n", cpu_id); 278 278 seq_printf(m, "hart\t\t: %lu\n", cpuid_to_hartid_map(cpu_id)); 279 - print_isa(m); 279 + 280 + /* 281 + * For historical raisins, the isa: line is limited to the lowest common 282 + * denominator of extensions supported across all harts. A true list of 283 + * extensions supported on this hart is printed later in the hart isa: 284 + * line. 285 + */ 286 + seq_puts(m, "isa\t\t: "); 287 + print_isa(m, NULL); 280 288 print_mmu(m); 281 289 282 290 if (acpi_disabled) { ··· 300 292 seq_printf(m, "mvendorid\t: 0x%lx\n", ci->mvendorid); 301 293 seq_printf(m, "marchid\t\t: 0x%lx\n", ci->marchid); 302 294 seq_printf(m, "mimpid\t\t: 0x%lx\n", ci->mimpid); 295 + 296 + /* 297 + * Print the ISA extensions specific to this hart, which may show 298 + * additional extensions not present across all harts. 299 + */ 300 + seq_puts(m, "hart isa\t: "); 301 + print_isa(m, hart_isa[cpu_id].isa); 303 302 seq_puts(m, "\n"); 304 303 305 304 return 0;
+83 -17
arch/riscv/kernel/cpufeature.c
··· 8 8 9 9 #include <linux/acpi.h> 10 10 #include <linux/bitmap.h> 11 + #include <linux/cpuhotplug.h> 11 12 #include <linux/ctype.h> 12 13 #include <linux/log2.h> 13 14 #include <linux/memory.h> ··· 30 29 31 30 #define MISALIGNED_ACCESS_JIFFIES_LG2 1 32 31 #define MISALIGNED_BUFFER_SIZE 0x4000 32 + #define MISALIGNED_BUFFER_ORDER get_order(MISALIGNED_BUFFER_SIZE) 33 33 #define MISALIGNED_COPY_SIZE ((MISALIGNED_BUFFER_SIZE / 2) - 0x80) 34 34 35 35 unsigned long elf_hwcap __read_mostly; ··· 561 559 return hwcap; 562 560 } 563 561 564 - void check_unaligned_access(int cpu) 562 + static int check_unaligned_access(void *param) 565 563 { 564 + int cpu = smp_processor_id(); 566 565 u64 start_cycles, end_cycles; 567 566 u64 word_cycles; 568 567 u64 byte_cycles; 569 568 int ratio; 570 569 unsigned long start_jiffies, now; 571 - struct page *page; 570 + struct page *page = param; 572 571 void *dst; 573 572 void *src; 574 573 long speed = RISCV_HWPROBE_MISALIGNED_SLOW; 575 574 576 - page = alloc_pages(GFP_NOWAIT, get_order(MISALIGNED_BUFFER_SIZE)); 577 - if (!page) { 578 - pr_warn("Can't alloc pages to measure memcpy performance"); 579 - return; 580 - } 575 + if (check_unaligned_access_emulated(cpu)) 576 + return 0; 581 577 582 578 /* Make an unaligned destination buffer. */ 583 579 dst = (void *)((unsigned long)page_address(page) | 0x1); ··· 629 629 pr_warn("cpu%d: rdtime lacks granularity needed to measure unaligned access speed\n", 630 630 cpu); 631 631 632 - goto out; 632 + return 0; 633 633 } 634 634 635 635 if (word_cycles < byte_cycles) ··· 643 643 (speed == RISCV_HWPROBE_MISALIGNED_FAST) ? "fast" : "slow"); 644 644 645 645 per_cpu(misaligned_access_speed, cpu) = speed; 646 - 647 - out: 648 - __free_pages(page, get_order(MISALIGNED_BUFFER_SIZE)); 649 - } 650 - 651 - static int check_unaligned_access_boot_cpu(void) 652 - { 653 - check_unaligned_access(0); 654 646 return 0; 655 647 } 656 648 657 - arch_initcall(check_unaligned_access_boot_cpu); 649 + static void check_unaligned_access_nonboot_cpu(void *param) 650 + { 651 + unsigned int cpu = smp_processor_id(); 652 + struct page **pages = param; 653 + 654 + if (smp_processor_id() != 0) 655 + check_unaligned_access(pages[cpu]); 656 + } 657 + 658 + static int riscv_online_cpu(unsigned int cpu) 659 + { 660 + static struct page *buf; 661 + 662 + /* We are already set since the last check */ 663 + if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_UNKNOWN) 664 + return 0; 665 + 666 + buf = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER); 667 + if (!buf) { 668 + pr_warn("Allocation failure, not measuring misaligned performance\n"); 669 + return -ENOMEM; 670 + } 671 + 672 + check_unaligned_access(buf); 673 + __free_pages(buf, MISALIGNED_BUFFER_ORDER); 674 + return 0; 675 + } 676 + 677 + /* Measure unaligned access on all CPUs present at boot in parallel. */ 678 + static int check_unaligned_access_all_cpus(void) 679 + { 680 + unsigned int cpu; 681 + unsigned int cpu_count = num_possible_cpus(); 682 + struct page **bufs = kzalloc(cpu_count * sizeof(struct page *), 683 + GFP_KERNEL); 684 + 685 + if (!bufs) { 686 + pr_warn("Allocation failure, not measuring misaligned performance\n"); 687 + return 0; 688 + } 689 + 690 + /* 691 + * Allocate separate buffers for each CPU so there's no fighting over 692 + * cache lines. 693 + */ 694 + for_each_cpu(cpu, cpu_online_mask) { 695 + bufs[cpu] = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER); 696 + if (!bufs[cpu]) { 697 + pr_warn("Allocation failure, not measuring misaligned performance\n"); 698 + goto out; 699 + } 700 + } 701 + 702 + /* Check everybody except 0, who stays behind to tend jiffies. */ 703 + on_each_cpu(check_unaligned_access_nonboot_cpu, bufs, 1); 704 + 705 + /* Check core 0. */ 706 + smp_call_on_cpu(0, check_unaligned_access, bufs[0], true); 707 + 708 + /* Setup hotplug callback for any new CPUs that come online. */ 709 + cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online", 710 + riscv_online_cpu, NULL); 711 + 712 + out: 713 + unaligned_emulation_finish(); 714 + for_each_cpu(cpu, cpu_online_mask) { 715 + if (bufs[cpu]) 716 + __free_pages(bufs[cpu], MISALIGNED_BUFFER_ORDER); 717 + } 718 + 719 + kfree(bufs); 720 + return 0; 721 + } 722 + 723 + arch_initcall(check_unaligned_access_all_cpus); 658 724 659 725 void riscv_user_isa_enable(void) 660 726 {
+7 -8
arch/riscv/kernel/entry.S
··· 26 26 * register will contain 0, and we should continue on the current TP. 27 27 */ 28 28 csrrw tp, CSR_SCRATCH, tp 29 - bnez tp, _save_context 29 + bnez tp, .Lsave_context 30 30 31 - _restore_kernel_tpsp: 31 + .Lrestore_kernel_tpsp: 32 32 csrr tp, CSR_SCRATCH 33 33 REG_S sp, TASK_TI_KERNEL_SP(tp) 34 34 ··· 40 40 REG_L sp, TASK_TI_KERNEL_SP(tp) 41 41 #endif 42 42 43 - _save_context: 43 + .Lsave_context: 44 44 REG_S sp, TASK_TI_USER_SP(tp) 45 45 REG_L sp, TASK_TI_KERNEL_SP(tp) 46 46 addi sp, sp, -(PT_SIZE_ON_STACK) ··· 322 322 .section ".rodata" 323 323 .align LGREG 324 324 /* Exception vector table */ 325 - SYM_CODE_START(excp_vect_table) 325 + SYM_DATA_START_LOCAL(excp_vect_table) 326 326 RISCV_PTR do_trap_insn_misaligned 327 327 ALT_INSN_FAULT(RISCV_PTR do_trap_insn_fault) 328 328 RISCV_PTR do_trap_insn_illegal ··· 340 340 RISCV_PTR do_page_fault /* load page fault */ 341 341 RISCV_PTR do_trap_unknown 342 342 RISCV_PTR do_page_fault /* store page fault */ 343 - excp_vect_table_end: 344 - SYM_CODE_END(excp_vect_table) 343 + SYM_DATA_END_LABEL(excp_vect_table, SYM_L_LOCAL, excp_vect_table_end) 345 344 346 345 #ifndef CONFIG_MMU 347 - SYM_CODE_START(__user_rt_sigreturn) 346 + SYM_DATA_START(__user_rt_sigreturn) 348 347 li a7, __NR_rt_sigreturn 349 348 ecall 350 - SYM_CODE_END(__user_rt_sigreturn) 349 + SYM_DATA_END(__user_rt_sigreturn) 351 350 #endif
+125 -4
arch/riscv/kernel/fpu.S
··· 19 19 #include <asm/csr.h> 20 20 #include <asm/asm-offsets.h> 21 21 22 - ENTRY(__fstate_save) 22 + SYM_FUNC_START(__fstate_save) 23 23 li a2, TASK_THREAD_F0 24 24 add a0, a0, a2 25 25 li t1, SR_FS ··· 60 60 sw t0, TASK_THREAD_FCSR_F0(a0) 61 61 csrc CSR_STATUS, t1 62 62 ret 63 - ENDPROC(__fstate_save) 63 + SYM_FUNC_END(__fstate_save) 64 64 65 - ENTRY(__fstate_restore) 65 + SYM_FUNC_START(__fstate_restore) 66 66 li a2, TASK_THREAD_F0 67 67 add a0, a0, a2 68 68 li t1, SR_FS ··· 103 103 fscsr t0 104 104 csrc CSR_STATUS, t1 105 105 ret 106 - ENDPROC(__fstate_restore) 106 + SYM_FUNC_END(__fstate_restore) 107 + 108 + #define get_f32(which) fmv.x.s a0, which; j 2f 109 + #define put_f32(which) fmv.s.x which, a1; j 2f 110 + #if __riscv_xlen == 64 111 + # define get_f64(which) fmv.x.d a0, which; j 2f 112 + # define put_f64(which) fmv.d.x which, a1; j 2f 113 + #else 114 + # define get_f64(which) fsd which, 0(a1); j 2f 115 + # define put_f64(which) fld which, 0(a1); j 2f 116 + #endif 117 + 118 + .macro fp_access_prologue 119 + /* 120 + * Compute jump offset to store the correct FP register since we don't 121 + * have indirect FP register access 122 + */ 123 + sll t0, a0, 3 124 + la t2, 1f 125 + add t0, t0, t2 126 + li t1, SR_FS 127 + csrs CSR_STATUS, t1 128 + jr t0 129 + 1: 130 + .endm 131 + 132 + .macro fp_access_epilogue 133 + 2: 134 + csrc CSR_STATUS, t1 135 + ret 136 + .endm 137 + 138 + #define fp_access_body(__access_func) \ 139 + __access_func(f0); \ 140 + __access_func(f1); \ 141 + __access_func(f2); \ 142 + __access_func(f3); \ 143 + __access_func(f4); \ 144 + __access_func(f5); \ 145 + __access_func(f6); \ 146 + __access_func(f7); \ 147 + __access_func(f8); \ 148 + __access_func(f9); \ 149 + __access_func(f10); \ 150 + __access_func(f11); \ 151 + __access_func(f12); \ 152 + __access_func(f13); \ 153 + __access_func(f14); \ 154 + __access_func(f15); \ 155 + __access_func(f16); \ 156 + __access_func(f17); \ 157 + __access_func(f18); \ 158 + __access_func(f19); \ 159 + __access_func(f20); \ 160 + __access_func(f21); \ 161 + __access_func(f22); \ 162 + __access_func(f23); \ 163 + __access_func(f24); \ 164 + __access_func(f25); \ 165 + __access_func(f26); \ 166 + __access_func(f27); \ 167 + __access_func(f28); \ 168 + __access_func(f29); \ 169 + __access_func(f30); \ 170 + __access_func(f31) 171 + 172 + 173 + #ifdef CONFIG_RISCV_MISALIGNED 174 + 175 + /* 176 + * Disable compressed instructions set to keep a constant offset between FP 177 + * load/store/move instructions 178 + */ 179 + .option norvc 180 + /* 181 + * put_f32_reg - Set a FP register from a register containing the value 182 + * a0 = FP register index to be set 183 + * a1 = value to be loaded in the FP register 184 + */ 185 + SYM_FUNC_START(put_f32_reg) 186 + fp_access_prologue 187 + fp_access_body(put_f32) 188 + fp_access_epilogue 189 + SYM_FUNC_END(put_f32_reg) 190 + 191 + /* 192 + * get_f32_reg - Get a FP register value and return it 193 + * a0 = FP register index to be retrieved 194 + */ 195 + SYM_FUNC_START(get_f32_reg) 196 + fp_access_prologue 197 + fp_access_body(get_f32) 198 + fp_access_epilogue 199 + SYM_FUNC_END(get_f32_reg) 200 + 201 + /* 202 + * put_f64_reg - Set a 64 bits FP register from a value or a pointer. 203 + * a0 = FP register index to be set 204 + * a1 = value/pointer to be loaded in the FP register (when xlen == 32 bits, we 205 + * load the value to a pointer). 206 + */ 207 + SYM_FUNC_START(put_f64_reg) 208 + fp_access_prologue 209 + fp_access_body(put_f64) 210 + fp_access_epilogue 211 + SYM_FUNC_END(put_f64_reg) 212 + 213 + /* 214 + * put_f64_reg - Get a 64 bits FP register value and returned it or store it to 215 + * a pointer. 216 + * a0 = FP register index to be retrieved 217 + * a1 = If xlen == 32, pointer which should be loaded with the FP register value 218 + * or unused if xlen == 64. In which case the FP register value is returned 219 + * through a0 220 + */ 221 + SYM_FUNC_START(get_f64_reg) 222 + fp_access_prologue 223 + fp_access_body(get_f64) 224 + fp_access_epilogue 225 + SYM_FUNC_END(get_f64_reg) 226 + 227 + #endif /* CONFIG_RISCV_MISALIGNED */
+15 -15
arch/riscv/kernel/head.S
··· 19 19 #include "efi-header.S" 20 20 21 21 __HEAD 22 - ENTRY(_start) 22 + SYM_CODE_START(_start) 23 23 /* 24 24 * Image header expected by Linux boot-loaders. The image header data 25 25 * structure is described in asm/image.h. ··· 164 164 XIP_FIXUP_OFFSET a0 165 165 call relocate_enable_mmu 166 166 #endif 167 - call setup_trap_vector 167 + call .Lsetup_trap_vector 168 168 tail smp_callin 169 169 #endif /* CONFIG_SMP */ 170 170 171 171 .align 2 172 - setup_trap_vector: 172 + .Lsetup_trap_vector: 173 173 /* Set trap vector to exception handler */ 174 174 la a0, handle_exception 175 175 csrw CSR_TVEC, a0 ··· 187 187 wfi 188 188 j .Lsecondary_park 189 189 190 - END(_start) 190 + SYM_CODE_END(_start) 191 191 192 - ENTRY(_start_kernel) 192 + SYM_CODE_START(_start_kernel) 193 193 /* Mask all interrupts */ 194 194 csrw CSR_IE, zero 195 195 csrw CSR_IP, zero ··· 206 206 * not implement PMPs, so we set up a quick trap handler to just skip 207 207 * touching the PMPs on any trap. 208 208 */ 209 - la a0, pmp_done 209 + la a0, .Lpmp_done 210 210 csrw CSR_TVEC, a0 211 211 212 212 li a0, -1 ··· 214 214 li a0, (PMP_A_NAPOT | PMP_R | PMP_W | PMP_X) 215 215 csrw CSR_PMPCFG0, a0 216 216 .align 2 217 - pmp_done: 217 + .Lpmp_done: 218 218 219 219 /* 220 220 * The hartid in a0 is expected later on, and we have no firmware ··· 275 275 /* Clear BSS for flat non-ELF images */ 276 276 la a3, __bss_start 277 277 la a4, __bss_stop 278 - ble a4, a3, clear_bss_done 279 - clear_bss: 278 + ble a4, a3, .Lclear_bss_done 279 + .Lclear_bss: 280 280 REG_S zero, (a3) 281 281 add a3, a3, RISCV_SZPTR 282 - blt a3, a4, clear_bss 283 - clear_bss_done: 282 + blt a3, a4, .Lclear_bss 283 + .Lclear_bss_done: 284 284 #endif 285 285 la a2, boot_cpu_hartid 286 286 XIP_FIXUP_OFFSET a2 ··· 305 305 call relocate_enable_mmu 306 306 #endif /* CONFIG_MMU */ 307 307 308 - call setup_trap_vector 308 + call .Lsetup_trap_vector 309 309 /* Restore C environment */ 310 310 la tp, init_task 311 311 la sp, init_thread_union + THREAD_SIZE ··· 348 348 tail .Lsecondary_start_common 349 349 #endif /* CONFIG_RISCV_BOOT_SPINWAIT */ 350 350 351 - END(_start_kernel) 351 + SYM_CODE_END(_start_kernel) 352 352 353 353 #ifdef CONFIG_RISCV_M_MODE 354 - ENTRY(reset_regs) 354 + SYM_CODE_START_LOCAL(reset_regs) 355 355 li sp, 0 356 356 li gp, 0 357 357 li tp, 0 ··· 449 449 .Lreset_regs_done_vector: 450 450 #endif /* CONFIG_RISCV_ISA_V */ 451 451 ret 452 - END(reset_regs) 452 + SYM_CODE_END(reset_regs) 453 453 #endif /* CONFIG_RISCV_M_MODE */
+6 -6
arch/riscv/kernel/hibernate-asm.S
··· 21 21 * 22 22 * Always returns 0 23 23 */ 24 - ENTRY(__hibernate_cpu_resume) 24 + SYM_FUNC_START(__hibernate_cpu_resume) 25 25 /* switch to hibernated image's page table. */ 26 26 csrw CSR_SATP, s0 27 27 sfence.vma ··· 34 34 mv a0, zero 35 35 36 36 ret 37 - END(__hibernate_cpu_resume) 37 + SYM_FUNC_END(__hibernate_cpu_resume) 38 38 39 39 /* 40 40 * Prepare to restore the image. ··· 42 42 * a1: satp of temporary page tables. 43 43 * a2: cpu_resume. 44 44 */ 45 - ENTRY(hibernate_restore_image) 45 + SYM_FUNC_START(hibernate_restore_image) 46 46 mv s0, a0 47 47 mv s1, a1 48 48 mv s2, a2 ··· 50 50 REG_L a1, relocated_restore_code 51 51 52 52 jr a1 53 - END(hibernate_restore_image) 53 + SYM_FUNC_END(hibernate_restore_image) 54 54 55 55 /* 56 56 * The below code will be executed from a 'safe' page. ··· 58 58 * back to the original memory location. Finally, it jumps to __hibernate_cpu_resume() 59 59 * to restore the CPU context. 60 60 */ 61 - ENTRY(hibernate_core_restore_code) 61 + SYM_FUNC_START(hibernate_core_restore_code) 62 62 /* switch to temp page table. */ 63 63 csrw satp, s1 64 64 sfence.vma ··· 73 73 bnez s4, .Lcopy 74 74 75 75 jr s2 76 - END(hibernate_core_restore_code) 76 + SYM_FUNC_END(hibernate_core_restore_code)
+8 -12
arch/riscv/kernel/mcount-dyn.S
··· 82 82 .endm 83 83 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ 84 84 85 - ENTRY(ftrace_caller) 85 + SYM_FUNC_START(ftrace_caller) 86 86 SAVE_ABI 87 87 88 88 addi a0, t0, -FENTRY_RA_OFFSET ··· 91 91 mv a1, ra 92 92 mv a3, sp 93 93 94 - ftrace_call: 95 - .global ftrace_call 94 + SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) 96 95 call ftrace_stub 97 96 98 97 #ifdef CONFIG_FUNCTION_GRAPH_TRACER ··· 101 102 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST 102 103 mv a2, s0 103 104 #endif 104 - ftrace_graph_call: 105 - .global ftrace_graph_call 105 + SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL) 106 106 call ftrace_stub 107 107 #endif 108 108 RESTORE_ABI 109 109 jr t0 110 - ENDPROC(ftrace_caller) 110 + SYM_FUNC_END(ftrace_caller) 111 111 112 112 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS 113 - ENTRY(ftrace_regs_caller) 113 + SYM_FUNC_START(ftrace_regs_caller) 114 114 SAVE_ALL 115 115 116 116 addi a0, t0, -FENTRY_RA_OFFSET ··· 118 120 mv a1, ra 119 121 mv a3, sp 120 122 121 - ftrace_regs_call: 122 - .global ftrace_regs_call 123 + SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL) 123 124 call ftrace_stub 124 125 125 126 #ifdef CONFIG_FUNCTION_GRAPH_TRACER ··· 128 131 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST 129 132 mv a2, s0 130 133 #endif 131 - ftrace_graph_regs_call: 132 - .global ftrace_graph_regs_call 134 + SYM_INNER_LABEL(ftrace_graph_regs_call, SYM_L_GLOBAL) 133 135 call ftrace_stub 134 136 #endif 135 137 136 138 RESTORE_ALL 137 139 jr t0 138 - ENDPROC(ftrace_regs_caller) 140 + SYM_FUNC_END(ftrace_regs_caller) 139 141 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
+9 -9
arch/riscv/kernel/mcount.S
··· 61 61 ret 62 62 SYM_FUNC_END(ftrace_stub_graph) 63 63 64 - ENTRY(return_to_handler) 64 + SYM_FUNC_START(return_to_handler) 65 65 /* 66 66 * On implementing the frame point test, the ideal way is to compare the 67 67 * s0 (frame pointer, if enabled) on entry and the sp (stack pointer) on return. ··· 76 76 mv a2, a0 77 77 RESTORE_RET_ABI_STATE 78 78 jalr a2 79 - ENDPROC(return_to_handler) 79 + SYM_FUNC_END(return_to_handler) 80 80 #endif 81 81 82 82 #ifndef CONFIG_DYNAMIC_FTRACE 83 - ENTRY(MCOUNT_NAME) 83 + SYM_FUNC_START(MCOUNT_NAME) 84 84 la t4, ftrace_stub 85 85 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 86 86 la t0, ftrace_graph_return 87 87 REG_L t1, 0(t0) 88 - bne t1, t4, do_ftrace_graph_caller 88 + bne t1, t4, .Ldo_ftrace_graph_caller 89 89 90 90 la t3, ftrace_graph_entry 91 91 REG_L t2, 0(t3) 92 92 la t6, ftrace_graph_entry_stub 93 - bne t2, t6, do_ftrace_graph_caller 93 + bne t2, t6, .Ldo_ftrace_graph_caller 94 94 #endif 95 95 la t3, ftrace_trace_function 96 96 REG_L t5, 0(t3) 97 - bne t5, t4, do_trace 97 + bne t5, t4, .Ldo_trace 98 98 ret 99 99 100 100 #ifdef CONFIG_FUNCTION_GRAPH_TRACER ··· 102 102 * A pseudo representation for the function graph tracer: 103 103 * prepare_to_return(&ra_to_caller_of_caller, ra_to_caller) 104 104 */ 105 - do_ftrace_graph_caller: 105 + .Ldo_ftrace_graph_caller: 106 106 addi a0, s0, -SZREG 107 107 mv a1, ra 108 108 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST ··· 118 118 * A pseudo representation for the function tracer: 119 119 * (*ftrace_trace_function)(ra_to_caller, ra_to_caller_of_caller) 120 120 */ 121 - do_trace: 121 + .Ldo_trace: 122 122 REG_L a1, -SZREG(s0) 123 123 mv a0, ra 124 124 ··· 126 126 jalr t5 127 127 RESTORE_ABI_STATE 128 128 ret 129 - ENDPROC(MCOUNT_NAME) 129 + SYM_FUNC_END(MCOUNT_NAME) 130 130 #endif 131 131 EXPORT_SYMBOL(MCOUNT_NAME)
+504 -104
arch/riscv/kernel/module.c
··· 7 7 #include <linux/elf.h> 8 8 #include <linux/err.h> 9 9 #include <linux/errno.h> 10 + #include <linux/hashtable.h> 11 + #include <linux/kernel.h> 12 + #include <linux/log2.h> 10 13 #include <linux/moduleloader.h> 11 14 #include <linux/vmalloc.h> 12 15 #include <linux/sizes.h> 13 16 #include <linux/pgtable.h> 14 17 #include <asm/alternative.h> 15 18 #include <asm/sections.h> 19 + 20 + struct used_bucket { 21 + struct list_head head; 22 + struct hlist_head *bucket; 23 + }; 24 + 25 + struct relocation_head { 26 + struct hlist_node node; 27 + struct list_head *rel_entry; 28 + void *location; 29 + }; 30 + 31 + struct relocation_entry { 32 + struct list_head head; 33 + Elf_Addr value; 34 + unsigned int type; 35 + }; 36 + 37 + struct relocation_handlers { 38 + int (*reloc_handler)(struct module *me, void *location, Elf_Addr v); 39 + int (*accumulate_handler)(struct module *me, void *location, 40 + long buffer); 41 + }; 42 + 43 + unsigned int initialize_relocation_hashtable(unsigned int num_relocations); 44 + void process_accumulated_relocations(struct module *me); 45 + int add_relocation_to_accumulate(struct module *me, int type, void *location, 46 + unsigned int hashtable_bits, Elf_Addr v); 47 + 48 + struct hlist_head *relocation_hashtable; 49 + 50 + struct list_head used_buckets_list; 16 51 17 52 /* 18 53 * The auipc+jalr instruction pair can reach any PC-relative offset ··· 62 27 #endif 63 28 } 64 29 65 - static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v) 30 + static int riscv_insn_rmw(void *location, u32 keep, u32 set) 31 + { 32 + u16 *parcel = location; 33 + u32 insn = (u32)le16_to_cpu(parcel[0]) | (u32)le16_to_cpu(parcel[1]) << 16; 34 + 35 + insn &= keep; 36 + insn |= set; 37 + 38 + parcel[0] = cpu_to_le16(insn); 39 + parcel[1] = cpu_to_le16(insn >> 16); 40 + return 0; 41 + } 42 + 43 + static int riscv_insn_rvc_rmw(void *location, u16 keep, u16 set) 44 + { 45 + u16 *parcel = location; 46 + u16 insn = le16_to_cpu(*parcel); 47 + 48 + insn &= keep; 49 + insn |= set; 50 + 51 + *parcel = cpu_to_le16(insn); 52 + return 0; 53 + } 54 + 55 + static int apply_r_riscv_32_rela(struct module *me, void *location, Elf_Addr v) 66 56 { 67 57 if (v != (u32)v) { 68 58 pr_err("%s: value %016llx out of range for 32-bit field\n", 69 59 me->name, (long long)v); 70 60 return -EINVAL; 71 61 } 72 - *location = v; 62 + *(u32 *)location = v; 73 63 return 0; 74 64 } 75 65 76 - static int apply_r_riscv_64_rela(struct module *me, u32 *location, Elf_Addr v) 66 + static int apply_r_riscv_64_rela(struct module *me, void *location, Elf_Addr v) 77 67 { 78 68 *(u64 *)location = v; 79 69 return 0; 80 70 } 81 71 82 - static int apply_r_riscv_branch_rela(struct module *me, u32 *location, 72 + static int apply_r_riscv_branch_rela(struct module *me, void *location, 83 73 Elf_Addr v) 84 74 { 85 - ptrdiff_t offset = (void *)v - (void *)location; 75 + ptrdiff_t offset = (void *)v - location; 86 76 u32 imm12 = (offset & 0x1000) << (31 - 12); 87 77 u32 imm11 = (offset & 0x800) >> (11 - 7); 88 78 u32 imm10_5 = (offset & 0x7e0) << (30 - 10); 89 79 u32 imm4_1 = (offset & 0x1e) << (11 - 4); 90 80 91 - *location = (*location & 0x1fff07f) | imm12 | imm11 | imm10_5 | imm4_1; 92 - return 0; 81 + return riscv_insn_rmw(location, 0x1fff07f, imm12 | imm11 | imm10_5 | imm4_1); 93 82 } 94 83 95 - static int apply_r_riscv_jal_rela(struct module *me, u32 *location, 84 + static int apply_r_riscv_jal_rela(struct module *me, void *location, 96 85 Elf_Addr v) 97 86 { 98 - ptrdiff_t offset = (void *)v - (void *)location; 87 + ptrdiff_t offset = (void *)v - location; 99 88 u32 imm20 = (offset & 0x100000) << (31 - 20); 100 89 u32 imm19_12 = (offset & 0xff000); 101 90 u32 imm11 = (offset & 0x800) << (20 - 11); 102 91 u32 imm10_1 = (offset & 0x7fe) << (30 - 10); 103 92 104 - *location = (*location & 0xfff) | imm20 | imm19_12 | imm11 | imm10_1; 105 - return 0; 93 + return riscv_insn_rmw(location, 0xfff, imm20 | imm19_12 | imm11 | imm10_1); 106 94 } 107 95 108 - static int apply_r_riscv_rvc_branch_rela(struct module *me, u32 *location, 96 + static int apply_r_riscv_rvc_branch_rela(struct module *me, void *location, 109 97 Elf_Addr v) 110 98 { 111 - ptrdiff_t offset = (void *)v - (void *)location; 99 + ptrdiff_t offset = (void *)v - location; 112 100 u16 imm8 = (offset & 0x100) << (12 - 8); 113 101 u16 imm7_6 = (offset & 0xc0) >> (6 - 5); 114 102 u16 imm5 = (offset & 0x20) >> (5 - 2); 115 103 u16 imm4_3 = (offset & 0x18) << (12 - 5); 116 104 u16 imm2_1 = (offset & 0x6) << (12 - 10); 117 105 118 - *(u16 *)location = (*(u16 *)location & 0xe383) | 119 - imm8 | imm7_6 | imm5 | imm4_3 | imm2_1; 120 - return 0; 106 + return riscv_insn_rvc_rmw(location, 0xe383, 107 + imm8 | imm7_6 | imm5 | imm4_3 | imm2_1); 121 108 } 122 109 123 - static int apply_r_riscv_rvc_jump_rela(struct module *me, u32 *location, 110 + static int apply_r_riscv_rvc_jump_rela(struct module *me, void *location, 124 111 Elf_Addr v) 125 112 { 126 - ptrdiff_t offset = (void *)v - (void *)location; 113 + ptrdiff_t offset = (void *)v - location; 127 114 u16 imm11 = (offset & 0x800) << (12 - 11); 128 115 u16 imm10 = (offset & 0x400) >> (10 - 8); 129 116 u16 imm9_8 = (offset & 0x300) << (12 - 11); ··· 155 98 u16 imm4 = (offset & 0x10) << (12 - 5); 156 99 u16 imm3_1 = (offset & 0xe) << (12 - 10); 157 100 158 - *(u16 *)location = (*(u16 *)location & 0xe003) | 159 - imm11 | imm10 | imm9_8 | imm7 | imm6 | imm5 | imm4 | imm3_1; 160 - return 0; 101 + return riscv_insn_rvc_rmw(location, 0xe003, 102 + imm11 | imm10 | imm9_8 | imm7 | imm6 | imm5 | imm4 | imm3_1); 161 103 } 162 104 163 - static int apply_r_riscv_pcrel_hi20_rela(struct module *me, u32 *location, 105 + static int apply_r_riscv_pcrel_hi20_rela(struct module *me, void *location, 164 106 Elf_Addr v) 165 107 { 166 - ptrdiff_t offset = (void *)v - (void *)location; 167 - s32 hi20; 108 + ptrdiff_t offset = (void *)v - location; 168 109 169 110 if (!riscv_insn_valid_32bit_offset(offset)) { 170 111 pr_err( ··· 171 116 return -EINVAL; 172 117 } 173 118 174 - hi20 = (offset + 0x800) & 0xfffff000; 175 - *location = (*location & 0xfff) | hi20; 176 - return 0; 119 + return riscv_insn_rmw(location, 0xfff, (offset + 0x800) & 0xfffff000); 177 120 } 178 121 179 - static int apply_r_riscv_pcrel_lo12_i_rela(struct module *me, u32 *location, 122 + static int apply_r_riscv_pcrel_lo12_i_rela(struct module *me, void *location, 180 123 Elf_Addr v) 181 124 { 182 125 /* 183 126 * v is the lo12 value to fill. It is calculated before calling this 184 127 * handler. 185 128 */ 186 - *location = (*location & 0xfffff) | ((v & 0xfff) << 20); 187 - return 0; 129 + return riscv_insn_rmw(location, 0xfffff, (v & 0xfff) << 20); 188 130 } 189 131 190 - static int apply_r_riscv_pcrel_lo12_s_rela(struct module *me, u32 *location, 132 + static int apply_r_riscv_pcrel_lo12_s_rela(struct module *me, void *location, 191 133 Elf_Addr v) 192 134 { 193 135 /* ··· 194 142 u32 imm11_5 = (v & 0xfe0) << (31 - 11); 195 143 u32 imm4_0 = (v & 0x1f) << (11 - 4); 196 144 197 - *location = (*location & 0x1fff07f) | imm11_5 | imm4_0; 198 - return 0; 145 + return riscv_insn_rmw(location, 0x1fff07f, imm11_5 | imm4_0); 199 146 } 200 147 201 - static int apply_r_riscv_hi20_rela(struct module *me, u32 *location, 148 + static int apply_r_riscv_hi20_rela(struct module *me, void *location, 202 149 Elf_Addr v) 203 150 { 204 - s32 hi20; 205 - 206 151 if (IS_ENABLED(CONFIG_CMODEL_MEDLOW)) { 207 152 pr_err( 208 153 "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n", ··· 207 158 return -EINVAL; 208 159 } 209 160 210 - hi20 = ((s32)v + 0x800) & 0xfffff000; 211 - *location = (*location & 0xfff) | hi20; 212 - return 0; 161 + return riscv_insn_rmw(location, 0xfff, ((s32)v + 0x800) & 0xfffff000); 213 162 } 214 163 215 - static int apply_r_riscv_lo12_i_rela(struct module *me, u32 *location, 164 + static int apply_r_riscv_lo12_i_rela(struct module *me, void *location, 216 165 Elf_Addr v) 217 166 { 218 167 /* Skip medlow checking because of filtering by HI20 already */ 219 168 s32 hi20 = ((s32)v + 0x800) & 0xfffff000; 220 169 s32 lo12 = ((s32)v - hi20); 221 - *location = (*location & 0xfffff) | ((lo12 & 0xfff) << 20); 222 - return 0; 170 + 171 + return riscv_insn_rmw(location, 0xfffff, (lo12 & 0xfff) << 20); 223 172 } 224 173 225 - static int apply_r_riscv_lo12_s_rela(struct module *me, u32 *location, 174 + static int apply_r_riscv_lo12_s_rela(struct module *me, void *location, 226 175 Elf_Addr v) 227 176 { 228 177 /* Skip medlow checking because of filtering by HI20 already */ ··· 228 181 s32 lo12 = ((s32)v - hi20); 229 182 u32 imm11_5 = (lo12 & 0xfe0) << (31 - 11); 230 183 u32 imm4_0 = (lo12 & 0x1f) << (11 - 4); 231 - *location = (*location & 0x1fff07f) | imm11_5 | imm4_0; 232 - return 0; 184 + 185 + return riscv_insn_rmw(location, 0x1fff07f, imm11_5 | imm4_0); 233 186 } 234 187 235 - static int apply_r_riscv_got_hi20_rela(struct module *me, u32 *location, 188 + static int apply_r_riscv_got_hi20_rela(struct module *me, void *location, 236 189 Elf_Addr v) 237 190 { 238 - ptrdiff_t offset = (void *)v - (void *)location; 239 - s32 hi20; 191 + ptrdiff_t offset = (void *)v - location; 240 192 241 193 /* Always emit the got entry */ 242 194 if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) { 243 - offset = module_emit_got_entry(me, v); 244 - offset = (void *)offset - (void *)location; 195 + offset = (void *)module_emit_got_entry(me, v) - location; 245 196 } else { 246 197 pr_err( 247 198 "%s: can not generate the GOT entry for symbol = %016llx from PC = %p\n", ··· 247 202 return -EINVAL; 248 203 } 249 204 250 - hi20 = (offset + 0x800) & 0xfffff000; 251 - *location = (*location & 0xfff) | hi20; 252 - return 0; 205 + return riscv_insn_rmw(location, 0xfff, (offset + 0x800) & 0xfffff000); 253 206 } 254 207 255 - static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location, 208 + static int apply_r_riscv_call_plt_rela(struct module *me, void *location, 256 209 Elf_Addr v) 257 210 { 258 - ptrdiff_t offset = (void *)v - (void *)location; 211 + ptrdiff_t offset = (void *)v - location; 259 212 u32 hi20, lo12; 260 213 261 214 if (!riscv_insn_valid_32bit_offset(offset)) { 262 215 /* Only emit the plt entry if offset over 32-bit range */ 263 216 if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) { 264 - offset = module_emit_plt_entry(me, v); 265 - offset = (void *)offset - (void *)location; 217 + offset = (void *)module_emit_plt_entry(me, v) - location; 266 218 } else { 267 219 pr_err( 268 220 "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n", ··· 270 228 271 229 hi20 = (offset + 0x800) & 0xfffff000; 272 230 lo12 = (offset - hi20) & 0xfff; 273 - *location = (*location & 0xfff) | hi20; 274 - *(location + 1) = (*(location + 1) & 0xfffff) | (lo12 << 20); 275 - return 0; 231 + riscv_insn_rmw(location, 0xfff, hi20); 232 + return riscv_insn_rmw(location + 4, 0xfffff, lo12 << 20); 276 233 } 277 234 278 - static int apply_r_riscv_call_rela(struct module *me, u32 *location, 235 + static int apply_r_riscv_call_rela(struct module *me, void *location, 279 236 Elf_Addr v) 280 237 { 281 - ptrdiff_t offset = (void *)v - (void *)location; 238 + ptrdiff_t offset = (void *)v - location; 282 239 u32 hi20, lo12; 283 240 284 241 if (!riscv_insn_valid_32bit_offset(offset)) { ··· 289 248 290 249 hi20 = (offset + 0x800) & 0xfffff000; 291 250 lo12 = (offset - hi20) & 0xfff; 292 - *location = (*location & 0xfff) | hi20; 293 - *(location + 1) = (*(location + 1) & 0xfffff) | (lo12 << 20); 294 - return 0; 251 + riscv_insn_rmw(location, 0xfff, hi20); 252 + return riscv_insn_rmw(location + 4, 0xfffff, lo12 << 20); 295 253 } 296 254 297 - static int apply_r_riscv_relax_rela(struct module *me, u32 *location, 255 + static int apply_r_riscv_relax_rela(struct module *me, void *location, 298 256 Elf_Addr v) 299 257 { 300 258 return 0; 301 259 } 302 260 303 - static int apply_r_riscv_align_rela(struct module *me, u32 *location, 261 + static int apply_r_riscv_align_rela(struct module *me, void *location, 304 262 Elf_Addr v) 305 263 { 306 264 pr_err( ··· 308 268 return -EINVAL; 309 269 } 310 270 311 - static int apply_r_riscv_add16_rela(struct module *me, u32 *location, 271 + static int apply_r_riscv_add8_rela(struct module *me, void *location, Elf_Addr v) 272 + { 273 + *(u8 *)location += (u8)v; 274 + return 0; 275 + } 276 + 277 + static int apply_r_riscv_add16_rela(struct module *me, void *location, 312 278 Elf_Addr v) 313 279 { 314 280 *(u16 *)location += (u16)v; 315 281 return 0; 316 282 } 317 283 318 - static int apply_r_riscv_add32_rela(struct module *me, u32 *location, 284 + static int apply_r_riscv_add32_rela(struct module *me, void *location, 319 285 Elf_Addr v) 320 286 { 321 287 *(u32 *)location += (u32)v; 322 288 return 0; 323 289 } 324 290 325 - static int apply_r_riscv_add64_rela(struct module *me, u32 *location, 291 + static int apply_r_riscv_add64_rela(struct module *me, void *location, 326 292 Elf_Addr v) 327 293 { 328 294 *(u64 *)location += (u64)v; 329 295 return 0; 330 296 } 331 297 332 - static int apply_r_riscv_sub16_rela(struct module *me, u32 *location, 298 + static int apply_r_riscv_sub8_rela(struct module *me, void *location, Elf_Addr v) 299 + { 300 + *(u8 *)location -= (u8)v; 301 + return 0; 302 + } 303 + 304 + static int apply_r_riscv_sub16_rela(struct module *me, void *location, 333 305 Elf_Addr v) 334 306 { 335 307 *(u16 *)location -= (u16)v; 336 308 return 0; 337 309 } 338 310 339 - static int apply_r_riscv_sub32_rela(struct module *me, u32 *location, 311 + static int apply_r_riscv_sub32_rela(struct module *me, void *location, 340 312 Elf_Addr v) 341 313 { 342 314 *(u32 *)location -= (u32)v; 343 315 return 0; 344 316 } 345 317 346 - static int apply_r_riscv_sub64_rela(struct module *me, u32 *location, 318 + static int apply_r_riscv_sub64_rela(struct module *me, void *location, 347 319 Elf_Addr v) 348 320 { 349 321 *(u64 *)location -= (u64)v; 350 322 return 0; 351 323 } 352 324 353 - static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, 354 - Elf_Addr v) = { 355 - [R_RISCV_32] = apply_r_riscv_32_rela, 356 - [R_RISCV_64] = apply_r_riscv_64_rela, 357 - [R_RISCV_BRANCH] = apply_r_riscv_branch_rela, 358 - [R_RISCV_JAL] = apply_r_riscv_jal_rela, 359 - [R_RISCV_RVC_BRANCH] = apply_r_riscv_rvc_branch_rela, 360 - [R_RISCV_RVC_JUMP] = apply_r_riscv_rvc_jump_rela, 361 - [R_RISCV_PCREL_HI20] = apply_r_riscv_pcrel_hi20_rela, 362 - [R_RISCV_PCREL_LO12_I] = apply_r_riscv_pcrel_lo12_i_rela, 363 - [R_RISCV_PCREL_LO12_S] = apply_r_riscv_pcrel_lo12_s_rela, 364 - [R_RISCV_HI20] = apply_r_riscv_hi20_rela, 365 - [R_RISCV_LO12_I] = apply_r_riscv_lo12_i_rela, 366 - [R_RISCV_LO12_S] = apply_r_riscv_lo12_s_rela, 367 - [R_RISCV_GOT_HI20] = apply_r_riscv_got_hi20_rela, 368 - [R_RISCV_CALL_PLT] = apply_r_riscv_call_plt_rela, 369 - [R_RISCV_CALL] = apply_r_riscv_call_rela, 370 - [R_RISCV_RELAX] = apply_r_riscv_relax_rela, 371 - [R_RISCV_ALIGN] = apply_r_riscv_align_rela, 372 - [R_RISCV_ADD16] = apply_r_riscv_add16_rela, 373 - [R_RISCV_ADD32] = apply_r_riscv_add32_rela, 374 - [R_RISCV_ADD64] = apply_r_riscv_add64_rela, 375 - [R_RISCV_SUB16] = apply_r_riscv_sub16_rela, 376 - [R_RISCV_SUB32] = apply_r_riscv_sub32_rela, 377 - [R_RISCV_SUB64] = apply_r_riscv_sub64_rela, 325 + static int dynamic_linking_not_supported(struct module *me, void *location, 326 + Elf_Addr v) 327 + { 328 + pr_err("%s: Dynamic linking not supported in kernel modules PC = %p\n", 329 + me->name, location); 330 + return -EINVAL; 331 + } 332 + 333 + static int tls_not_supported(struct module *me, void *location, Elf_Addr v) 334 + { 335 + pr_err("%s: Thread local storage not supported in kernel modules PC = %p\n", 336 + me->name, location); 337 + return -EINVAL; 338 + } 339 + 340 + static int apply_r_riscv_sub6_rela(struct module *me, void *location, Elf_Addr v) 341 + { 342 + u8 *byte = location; 343 + u8 value = v; 344 + 345 + *byte = (*byte - (value & 0x3f)) & 0x3f; 346 + return 0; 347 + } 348 + 349 + static int apply_r_riscv_set6_rela(struct module *me, void *location, Elf_Addr v) 350 + { 351 + u8 *byte = location; 352 + u8 value = v; 353 + 354 + *byte = (*byte & 0xc0) | (value & 0x3f); 355 + return 0; 356 + } 357 + 358 + static int apply_r_riscv_set8_rela(struct module *me, void *location, Elf_Addr v) 359 + { 360 + *(u8 *)location = (u8)v; 361 + return 0; 362 + } 363 + 364 + static int apply_r_riscv_set16_rela(struct module *me, void *location, 365 + Elf_Addr v) 366 + { 367 + *(u16 *)location = (u16)v; 368 + return 0; 369 + } 370 + 371 + static int apply_r_riscv_set32_rela(struct module *me, void *location, 372 + Elf_Addr v) 373 + { 374 + *(u32 *)location = (u32)v; 375 + return 0; 376 + } 377 + 378 + static int apply_r_riscv_32_pcrel_rela(struct module *me, void *location, 379 + Elf_Addr v) 380 + { 381 + *(u32 *)location = v - (uintptr_t)location; 382 + return 0; 383 + } 384 + 385 + static int apply_r_riscv_plt32_rela(struct module *me, void *location, 386 + Elf_Addr v) 387 + { 388 + ptrdiff_t offset = (void *)v - location; 389 + 390 + if (!riscv_insn_valid_32bit_offset(offset)) { 391 + /* Only emit the plt entry if offset over 32-bit range */ 392 + if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) { 393 + offset = (void *)module_emit_plt_entry(me, v) - location; 394 + } else { 395 + pr_err("%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n", 396 + me->name, (long long)v, location); 397 + return -EINVAL; 398 + } 399 + } 400 + 401 + *(u32 *)location = (u32)offset; 402 + return 0; 403 + } 404 + 405 + static int apply_r_riscv_set_uleb128(struct module *me, void *location, Elf_Addr v) 406 + { 407 + *(long *)location = v; 408 + return 0; 409 + } 410 + 411 + static int apply_r_riscv_sub_uleb128(struct module *me, void *location, Elf_Addr v) 412 + { 413 + *(long *)location -= v; 414 + return 0; 415 + } 416 + 417 + static int apply_6_bit_accumulation(struct module *me, void *location, long buffer) 418 + { 419 + u8 *byte = location; 420 + u8 value = buffer; 421 + 422 + if (buffer > 0x3f) { 423 + pr_err("%s: value %ld out of range for 6-bit relocation.\n", 424 + me->name, buffer); 425 + return -EINVAL; 426 + } 427 + 428 + *byte = (*byte & 0xc0) | (value & 0x3f); 429 + return 0; 430 + } 431 + 432 + static int apply_8_bit_accumulation(struct module *me, void *location, long buffer) 433 + { 434 + if (buffer > U8_MAX) { 435 + pr_err("%s: value %ld out of range for 8-bit relocation.\n", 436 + me->name, buffer); 437 + return -EINVAL; 438 + } 439 + *(u8 *)location = (u8)buffer; 440 + return 0; 441 + } 442 + 443 + static int apply_16_bit_accumulation(struct module *me, void *location, long buffer) 444 + { 445 + if (buffer > U16_MAX) { 446 + pr_err("%s: value %ld out of range for 16-bit relocation.\n", 447 + me->name, buffer); 448 + return -EINVAL; 449 + } 450 + *(u16 *)location = (u16)buffer; 451 + return 0; 452 + } 453 + 454 + static int apply_32_bit_accumulation(struct module *me, void *location, long buffer) 455 + { 456 + if (buffer > U32_MAX) { 457 + pr_err("%s: value %ld out of range for 32-bit relocation.\n", 458 + me->name, buffer); 459 + return -EINVAL; 460 + } 461 + *(u32 *)location = (u32)buffer; 462 + return 0; 463 + } 464 + 465 + static int apply_64_bit_accumulation(struct module *me, void *location, long buffer) 466 + { 467 + *(u64 *)location = (u64)buffer; 468 + return 0; 469 + } 470 + 471 + static int apply_uleb128_accumulation(struct module *me, void *location, long buffer) 472 + { 473 + /* 474 + * ULEB128 is a variable length encoding. Encode the buffer into 475 + * the ULEB128 data format. 476 + */ 477 + u8 *p = location; 478 + 479 + while (buffer != 0) { 480 + u8 value = buffer & 0x7f; 481 + 482 + buffer >>= 7; 483 + value |= (!!buffer) << 7; 484 + 485 + *p++ = value; 486 + } 487 + return 0; 488 + } 489 + 490 + /* 491 + * Relocations defined in the riscv-elf-psabi-doc. 492 + * This handles static linking only. 493 + */ 494 + static const struct relocation_handlers reloc_handlers[] = { 495 + [R_RISCV_32] = { .reloc_handler = apply_r_riscv_32_rela }, 496 + [R_RISCV_64] = { .reloc_handler = apply_r_riscv_64_rela }, 497 + [R_RISCV_RELATIVE] = { .reloc_handler = dynamic_linking_not_supported }, 498 + [R_RISCV_COPY] = { .reloc_handler = dynamic_linking_not_supported }, 499 + [R_RISCV_JUMP_SLOT] = { .reloc_handler = dynamic_linking_not_supported }, 500 + [R_RISCV_TLS_DTPMOD32] = { .reloc_handler = dynamic_linking_not_supported }, 501 + [R_RISCV_TLS_DTPMOD64] = { .reloc_handler = dynamic_linking_not_supported }, 502 + [R_RISCV_TLS_DTPREL32] = { .reloc_handler = dynamic_linking_not_supported }, 503 + [R_RISCV_TLS_DTPREL64] = { .reloc_handler = dynamic_linking_not_supported }, 504 + [R_RISCV_TLS_TPREL32] = { .reloc_handler = dynamic_linking_not_supported }, 505 + [R_RISCV_TLS_TPREL64] = { .reloc_handler = dynamic_linking_not_supported }, 506 + /* 12-15 undefined */ 507 + [R_RISCV_BRANCH] = { .reloc_handler = apply_r_riscv_branch_rela }, 508 + [R_RISCV_JAL] = { .reloc_handler = apply_r_riscv_jal_rela }, 509 + [R_RISCV_CALL] = { .reloc_handler = apply_r_riscv_call_rela }, 510 + [R_RISCV_CALL_PLT] = { .reloc_handler = apply_r_riscv_call_plt_rela }, 511 + [R_RISCV_GOT_HI20] = { .reloc_handler = apply_r_riscv_got_hi20_rela }, 512 + [R_RISCV_TLS_GOT_HI20] = { .reloc_handler = tls_not_supported }, 513 + [R_RISCV_TLS_GD_HI20] = { .reloc_handler = tls_not_supported }, 514 + [R_RISCV_PCREL_HI20] = { .reloc_handler = apply_r_riscv_pcrel_hi20_rela }, 515 + [R_RISCV_PCREL_LO12_I] = { .reloc_handler = apply_r_riscv_pcrel_lo12_i_rela }, 516 + [R_RISCV_PCREL_LO12_S] = { .reloc_handler = apply_r_riscv_pcrel_lo12_s_rela }, 517 + [R_RISCV_HI20] = { .reloc_handler = apply_r_riscv_hi20_rela }, 518 + [R_RISCV_LO12_I] = { .reloc_handler = apply_r_riscv_lo12_i_rela }, 519 + [R_RISCV_LO12_S] = { .reloc_handler = apply_r_riscv_lo12_s_rela }, 520 + [R_RISCV_TPREL_HI20] = { .reloc_handler = tls_not_supported }, 521 + [R_RISCV_TPREL_LO12_I] = { .reloc_handler = tls_not_supported }, 522 + [R_RISCV_TPREL_LO12_S] = { .reloc_handler = tls_not_supported }, 523 + [R_RISCV_TPREL_ADD] = { .reloc_handler = tls_not_supported }, 524 + [R_RISCV_ADD8] = { .reloc_handler = apply_r_riscv_add8_rela, 525 + .accumulate_handler = apply_8_bit_accumulation }, 526 + [R_RISCV_ADD16] = { .reloc_handler = apply_r_riscv_add16_rela, 527 + .accumulate_handler = apply_16_bit_accumulation }, 528 + [R_RISCV_ADD32] = { .reloc_handler = apply_r_riscv_add32_rela, 529 + .accumulate_handler = apply_32_bit_accumulation }, 530 + [R_RISCV_ADD64] = { .reloc_handler = apply_r_riscv_add64_rela, 531 + .accumulate_handler = apply_64_bit_accumulation }, 532 + [R_RISCV_SUB8] = { .reloc_handler = apply_r_riscv_sub8_rela, 533 + .accumulate_handler = apply_8_bit_accumulation }, 534 + [R_RISCV_SUB16] = { .reloc_handler = apply_r_riscv_sub16_rela, 535 + .accumulate_handler = apply_16_bit_accumulation }, 536 + [R_RISCV_SUB32] = { .reloc_handler = apply_r_riscv_sub32_rela, 537 + .accumulate_handler = apply_32_bit_accumulation }, 538 + [R_RISCV_SUB64] = { .reloc_handler = apply_r_riscv_sub64_rela, 539 + .accumulate_handler = apply_64_bit_accumulation }, 540 + /* 41-42 reserved for future standard use */ 541 + [R_RISCV_ALIGN] = { .reloc_handler = apply_r_riscv_align_rela }, 542 + [R_RISCV_RVC_BRANCH] = { .reloc_handler = apply_r_riscv_rvc_branch_rela }, 543 + [R_RISCV_RVC_JUMP] = { .reloc_handler = apply_r_riscv_rvc_jump_rela }, 544 + /* 46-50 reserved for future standard use */ 545 + [R_RISCV_RELAX] = { .reloc_handler = apply_r_riscv_relax_rela }, 546 + [R_RISCV_SUB6] = { .reloc_handler = apply_r_riscv_sub6_rela, 547 + .accumulate_handler = apply_6_bit_accumulation }, 548 + [R_RISCV_SET6] = { .reloc_handler = apply_r_riscv_set6_rela, 549 + .accumulate_handler = apply_6_bit_accumulation }, 550 + [R_RISCV_SET8] = { .reloc_handler = apply_r_riscv_set8_rela, 551 + .accumulate_handler = apply_8_bit_accumulation }, 552 + [R_RISCV_SET16] = { .reloc_handler = apply_r_riscv_set16_rela, 553 + .accumulate_handler = apply_16_bit_accumulation }, 554 + [R_RISCV_SET32] = { .reloc_handler = apply_r_riscv_set32_rela, 555 + .accumulate_handler = apply_32_bit_accumulation }, 556 + [R_RISCV_32_PCREL] = { .reloc_handler = apply_r_riscv_32_pcrel_rela }, 557 + [R_RISCV_IRELATIVE] = { .reloc_handler = dynamic_linking_not_supported }, 558 + [R_RISCV_PLT32] = { .reloc_handler = apply_r_riscv_plt32_rela }, 559 + [R_RISCV_SET_ULEB128] = { .reloc_handler = apply_r_riscv_set_uleb128, 560 + .accumulate_handler = apply_uleb128_accumulation }, 561 + [R_RISCV_SUB_ULEB128] = { .reloc_handler = apply_r_riscv_sub_uleb128, 562 + .accumulate_handler = apply_uleb128_accumulation }, 563 + /* 62-191 reserved for future standard use */ 564 + /* 192-255 nonstandard ABI extensions */ 378 565 }; 566 + 567 + void process_accumulated_relocations(struct module *me) 568 + { 569 + /* 570 + * Only ADD/SUB/SET/ULEB128 should end up here. 571 + * 572 + * Each bucket may have more than one relocation location. All 573 + * relocations for a location are stored in a list in a bucket. 574 + * 575 + * Relocations are applied to a temp variable before being stored to the 576 + * provided location to check for overflow. This also allows ULEB128 to 577 + * properly decide how many entries are needed before storing to 578 + * location. The final value is stored into location using the handler 579 + * for the last relocation to an address. 580 + * 581 + * Three layers of indexing: 582 + * - Each of the buckets in use 583 + * - Groups of relocations in each bucket by location address 584 + * - Each relocation entry for a location address 585 + */ 586 + struct used_bucket *bucket_iter; 587 + struct relocation_head *rel_head_iter; 588 + struct relocation_entry *rel_entry_iter; 589 + int curr_type; 590 + void *location; 591 + long buffer; 592 + 593 + list_for_each_entry(bucket_iter, &used_buckets_list, head) { 594 + hlist_for_each_entry(rel_head_iter, bucket_iter->bucket, node) { 595 + buffer = 0; 596 + location = rel_head_iter->location; 597 + list_for_each_entry(rel_entry_iter, 598 + rel_head_iter->rel_entry, head) { 599 + curr_type = rel_entry_iter->type; 600 + reloc_handlers[curr_type].reloc_handler( 601 + me, &buffer, rel_entry_iter->value); 602 + kfree(rel_entry_iter); 603 + } 604 + reloc_handlers[curr_type].accumulate_handler( 605 + me, location, buffer); 606 + kfree(rel_head_iter); 607 + } 608 + kfree(bucket_iter); 609 + } 610 + 611 + kfree(relocation_hashtable); 612 + } 613 + 614 + int add_relocation_to_accumulate(struct module *me, int type, void *location, 615 + unsigned int hashtable_bits, Elf_Addr v) 616 + { 617 + struct relocation_entry *entry; 618 + struct relocation_head *rel_head; 619 + struct hlist_head *current_head; 620 + struct used_bucket *bucket; 621 + unsigned long hash; 622 + 623 + entry = kmalloc(sizeof(*entry), GFP_KERNEL); 624 + INIT_LIST_HEAD(&entry->head); 625 + entry->type = type; 626 + entry->value = v; 627 + 628 + hash = hash_min((uintptr_t)location, hashtable_bits); 629 + 630 + current_head = &relocation_hashtable[hash]; 631 + 632 + /* Find matching location (if any) */ 633 + bool found = false; 634 + struct relocation_head *rel_head_iter; 635 + 636 + hlist_for_each_entry(rel_head_iter, current_head, node) { 637 + if (rel_head_iter->location == location) { 638 + found = true; 639 + rel_head = rel_head_iter; 640 + break; 641 + } 642 + } 643 + 644 + if (!found) { 645 + rel_head = kmalloc(sizeof(*rel_head), GFP_KERNEL); 646 + rel_head->rel_entry = 647 + kmalloc(sizeof(struct list_head), GFP_KERNEL); 648 + INIT_LIST_HEAD(rel_head->rel_entry); 649 + rel_head->location = location; 650 + INIT_HLIST_NODE(&rel_head->node); 651 + if (!current_head->first) { 652 + bucket = 653 + kmalloc(sizeof(struct used_bucket), GFP_KERNEL); 654 + INIT_LIST_HEAD(&bucket->head); 655 + bucket->bucket = current_head; 656 + list_add(&bucket->head, &used_buckets_list); 657 + } 658 + hlist_add_head(&rel_head->node, current_head); 659 + } 660 + 661 + /* Add relocation to head of discovered rel_head */ 662 + list_add_tail(&entry->head, rel_head->rel_entry); 663 + 664 + return 0; 665 + } 666 + 667 + unsigned int initialize_relocation_hashtable(unsigned int num_relocations) 668 + { 669 + /* Can safely assume that bits is not greater than sizeof(long) */ 670 + unsigned long hashtable_size = roundup_pow_of_two(num_relocations); 671 + unsigned int hashtable_bits = ilog2(hashtable_size); 672 + 673 + /* 674 + * Double size of hashtable if num_relocations * 1.25 is greater than 675 + * hashtable_size. 676 + */ 677 + int should_double_size = ((num_relocations + (num_relocations >> 2)) > (hashtable_size)); 678 + 679 + hashtable_bits += should_double_size; 680 + 681 + hashtable_size <<= should_double_size; 682 + 683 + relocation_hashtable = kmalloc_array(hashtable_size, 684 + sizeof(*relocation_hashtable), 685 + GFP_KERNEL); 686 + __hash_init(relocation_hashtable, hashtable_size); 687 + 688 + INIT_LIST_HEAD(&used_buckets_list); 689 + 690 + return hashtable_bits; 691 + } 379 692 380 693 int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, 381 694 unsigned int symindex, unsigned int relsec, 382 695 struct module *me) 383 696 { 384 697 Elf_Rela *rel = (void *) sechdrs[relsec].sh_addr; 385 - int (*handler)(struct module *me, u32 *location, Elf_Addr v); 698 + int (*handler)(struct module *me, void *location, Elf_Addr v); 386 699 Elf_Sym *sym; 387 - u32 *location; 700 + void *location; 388 701 unsigned int i, type; 389 702 Elf_Addr v; 390 703 int res; 704 + unsigned int num_relocations = sechdrs[relsec].sh_size / sizeof(*rel); 705 + unsigned int hashtable_bits = initialize_relocation_hashtable(num_relocations); 391 706 392 707 pr_debug("Applying relocate section %u to %u\n", relsec, 393 708 sechdrs[relsec].sh_info); 394 709 395 - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 710 + for (i = 0; i < num_relocations; i++) { 396 711 /* This is where to make the change */ 397 712 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 398 713 + rel[i].r_offset; ··· 765 370 766 371 type = ELF_RISCV_R_TYPE(rel[i].r_info); 767 372 768 - if (type < ARRAY_SIZE(reloc_handlers_rela)) 769 - handler = reloc_handlers_rela[type]; 373 + if (type < ARRAY_SIZE(reloc_handlers)) 374 + handler = reloc_handlers[type].reloc_handler; 770 375 else 771 376 handler = NULL; 772 377 ··· 822 427 } 823 428 } 824 429 825 - res = handler(me, location, v); 430 + if (reloc_handlers[type].accumulate_handler) 431 + res = add_relocation_to_accumulate(me, type, location, hashtable_bits, v); 432 + else 433 + res = handler(me, location, v); 826 434 if (res) 827 435 return res; 828 436 } 437 + 438 + process_accumulated_relocations(me); 829 439 830 440 return 0; 831 441 }
+2 -2
arch/riscv/kernel/probes/rethook_trampoline.S
··· 75 75 REG_L x31, PT_T6(sp) 76 76 .endm 77 77 78 - ENTRY(arch_rethook_trampoline) 78 + SYM_CODE_START(arch_rethook_trampoline) 79 79 addi sp, sp, -(PT_SIZE_ON_STACK) 80 80 save_all_base_regs 81 81 ··· 90 90 addi sp, sp, PT_SIZE_ON_STACK 91 91 92 92 ret 93 - ENDPROC(arch_rethook_trampoline) 93 + SYM_CODE_END(arch_rethook_trampoline)
+1 -1
arch/riscv/kernel/probes/simulate-insn.c
··· 24 24 unsigned long val) 25 25 { 26 26 if (index == 0) 27 - return false; 27 + return true; 28 28 else if (index <= 31) 29 29 *((unsigned long *)regs + index) = val; 30 30 else
+6
arch/riscv/kernel/probes/uprobes.c
··· 3 3 #include <linux/highmem.h> 4 4 #include <linux/ptrace.h> 5 5 #include <linux/uprobes.h> 6 + #include <asm/insn.h> 6 7 7 8 #include "decode-insn.h" 8 9 ··· 16 15 #else 17 16 return *insn == UPROBE_SWBP_INSN; 18 17 #endif 18 + } 19 + 20 + bool is_trap_insn(uprobe_opcode_t *insn) 21 + { 22 + return riscv_insn_is_ebreak(*insn) || riscv_insn_is_c_ebreak(*insn); 19 23 } 20 24 21 25 unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
+18
arch/riscv/kernel/process.c
··· 25 25 #include <asm/thread_info.h> 26 26 #include <asm/cpuidle.h> 27 27 #include <asm/vector.h> 28 + #include <asm/cpufeature.h> 28 29 29 30 register unsigned long gp_in_global __asm__("gp"); 30 31 ··· 40 39 void arch_cpu_idle(void) 41 40 { 42 41 cpu_do_idle(); 42 + } 43 + 44 + int set_unalign_ctl(struct task_struct *tsk, unsigned int val) 45 + { 46 + if (!unaligned_ctl_available()) 47 + return -EINVAL; 48 + 49 + tsk->thread.align_ctl = val; 50 + return 0; 51 + } 52 + 53 + int get_unalign_ctl(struct task_struct *tsk, unsigned long adr) 54 + { 55 + if (!unaligned_ctl_available()) 56 + return -EINVAL; 57 + 58 + return put_user(tsk->thread.align_ctl, (unsigned long __user *)adr); 43 59 } 44 60 45 61 void __show_regs(struct pt_regs *regs)
+10 -22
arch/riscv/kernel/sbi.c
··· 11 11 #include <linux/reboot.h> 12 12 #include <asm/sbi.h> 13 13 #include <asm/smp.h> 14 + #include <asm/tlbflush.h> 14 15 15 16 /* default SBI version is 0.1 */ 16 17 unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT; ··· 378 377 EXPORT_SYMBOL(sbi_remote_fence_i); 379 378 380 379 /** 381 - * sbi_remote_sfence_vma() - Execute SFENCE.VMA instructions on given remote 382 - * harts for the specified virtual address range. 383 - * @cpu_mask: A cpu mask containing all the target harts. 384 - * @start: Start of the virtual address 385 - * @size: Total size of the virtual address range. 386 - * 387 - * Return: 0 on success, appropriate linux error code otherwise. 388 - */ 389 - int sbi_remote_sfence_vma(const struct cpumask *cpu_mask, 390 - unsigned long start, 391 - unsigned long size) 392 - { 393 - return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA, 394 - cpu_mask, start, size, 0, 0); 395 - } 396 - EXPORT_SYMBOL(sbi_remote_sfence_vma); 397 - 398 - /** 399 380 * sbi_remote_sfence_vma_asid() - Execute SFENCE.VMA instructions on given 400 - * remote harts for a virtual address range belonging to a specific ASID. 381 + * remote harts for a virtual address range belonging to a specific ASID or not. 401 382 * 402 383 * @cpu_mask: A cpu mask containing all the target harts. 403 384 * @start: Start of the virtual address 404 385 * @size: Total size of the virtual address range. 405 - * @asid: The value of address space identifier (ASID). 386 + * @asid: The value of address space identifier (ASID), or FLUSH_TLB_NO_ASID 387 + * for flushing all address spaces. 406 388 * 407 389 * Return: 0 on success, appropriate linux error code otherwise. 408 390 */ ··· 394 410 unsigned long size, 395 411 unsigned long asid) 396 412 { 397 - return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID, 398 - cpu_mask, start, size, asid, 0); 413 + if (asid == FLUSH_TLB_NO_ASID) 414 + return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA, 415 + cpu_mask, start, size, 0, 0); 416 + else 417 + return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID, 418 + cpu_mask, start, size, asid, 0); 399 419 } 400 420 EXPORT_SYMBOL(sbi_remote_sfence_vma_asid); 401 421
+51 -44
arch/riscv/kernel/signal.c
··· 384 384 sigset_t *oldset = sigmask_to_save(); 385 385 int ret; 386 386 387 - /* Are we from a system call? */ 388 - if (regs->cause == EXC_SYSCALL) { 389 - /* Avoid additional syscall restarting via ret_from_exception */ 390 - regs->cause = -1UL; 391 - /* If so, check system call restarting.. */ 392 - switch (regs->a0) { 393 - case -ERESTART_RESTARTBLOCK: 394 - case -ERESTARTNOHAND: 395 - regs->a0 = -EINTR; 396 - break; 397 - 398 - case -ERESTARTSYS: 399 - if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { 400 - regs->a0 = -EINTR; 401 - break; 402 - } 403 - fallthrough; 404 - case -ERESTARTNOINTR: 405 - regs->a0 = regs->orig_a0; 406 - regs->epc -= 0x4; 407 - break; 408 - } 409 - } 410 - 411 387 rseq_signal_deliver(ksig, regs); 412 388 413 389 /* Set up the stack frame */ ··· 397 421 398 422 void arch_do_signal_or_restart(struct pt_regs *regs) 399 423 { 424 + unsigned long continue_addr = 0, restart_addr = 0; 425 + int retval = 0; 400 426 struct ksignal ksig; 427 + bool syscall = (regs->cause == EXC_SYSCALL); 401 428 429 + /* If we were from a system call, check for system call restarting */ 430 + if (syscall) { 431 + continue_addr = regs->epc; 432 + restart_addr = continue_addr - 4; 433 + retval = regs->a0; 434 + 435 + /* Avoid additional syscall restarting via ret_from_exception */ 436 + regs->cause = -1UL; 437 + 438 + /* 439 + * Prepare for system call restart. We do this here so that a 440 + * debugger will see the already changed PC. 441 + */ 442 + switch (retval) { 443 + case -ERESTARTNOHAND: 444 + case -ERESTARTSYS: 445 + case -ERESTARTNOINTR: 446 + case -ERESTART_RESTARTBLOCK: 447 + regs->a0 = regs->orig_a0; 448 + regs->epc = restart_addr; 449 + break; 450 + } 451 + } 452 + 453 + /* 454 + * Get the signal to deliver. When running under ptrace, at this point 455 + * the debugger may change all of our registers. 456 + */ 402 457 if (get_signal(&ksig)) { 458 + /* 459 + * Depending on the signal settings, we may need to revert the 460 + * decision to restart the system call, but skip this if a 461 + * debugger has chosen to restart at a different PC. 462 + */ 463 + if (regs->epc == restart_addr && 464 + (retval == -ERESTARTNOHAND || 465 + retval == -ERESTART_RESTARTBLOCK || 466 + (retval == -ERESTARTSYS && 467 + !(ksig.ka.sa.sa_flags & SA_RESTART)))) { 468 + regs->a0 = -EINTR; 469 + regs->epc = continue_addr; 470 + } 471 + 403 472 /* Actually deliver the signal */ 404 473 handle_signal(&ksig, regs); 405 474 return; 406 475 } 407 476 408 - /* Did we come from a system call? */ 409 - if (regs->cause == EXC_SYSCALL) { 410 - /* Avoid additional syscall restarting via ret_from_exception */ 411 - regs->cause = -1UL; 412 - 413 - /* Restart the system call - no handlers present */ 414 - switch (regs->a0) { 415 - case -ERESTARTNOHAND: 416 - case -ERESTARTSYS: 417 - case -ERESTARTNOINTR: 418 - regs->a0 = regs->orig_a0; 419 - regs->epc -= 0x4; 420 - break; 421 - case -ERESTART_RESTARTBLOCK: 422 - regs->a0 = regs->orig_a0; 423 - regs->a7 = __NR_restart_syscall; 424 - regs->epc -= 0x4; 425 - break; 426 - } 427 - } 477 + /* 478 + * Handle restarting a different system call. As above, if a debugger 479 + * has chosen to restart at a different PC, ignore the restart. 480 + */ 481 + if (syscall && regs->epc == restart_addr && retval == -ERESTART_RESTARTBLOCK) 482 + regs->a7 = __NR_restart_syscall; 428 483 429 484 /* 430 485 * If there is no signal to deliver, we just put the saved
-1
arch/riscv/kernel/smpboot.c
··· 248 248 249 249 numa_add_cpu(curr_cpuid); 250 250 set_cpu_online(curr_cpuid, 1); 251 - check_unaligned_access(curr_cpuid); 252 251 253 252 if (has_vector()) { 254 253 if (riscv_v_setup_vsize())
+2 -2
arch/riscv/kernel/suspend_entry.S
··· 16 16 .altmacro 17 17 .option norelax 18 18 19 - ENTRY(__cpu_suspend_enter) 19 + SYM_FUNC_START(__cpu_suspend_enter) 20 20 /* Save registers (except A0 and T0-T6) */ 21 21 REG_S ra, (SUSPEND_CONTEXT_REGS + PT_RA)(a0) 22 22 REG_S sp, (SUSPEND_CONTEXT_REGS + PT_SP)(a0) ··· 57 57 58 58 /* Return to C code */ 59 59 ret 60 - END(__cpu_suspend_enter) 60 + SYM_FUNC_END(__cpu_suspend_enter) 61 61 62 62 SYM_TYPED_FUNC_START(__cpu_resume_enter) 63 63 /* Load the global pointer */
+35
arch/riscv/kernel/tests/Kconfig.debug
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + menu "arch/riscv/kernel Testing and Coverage" 3 + 4 + config AS_HAS_ULEB128 5 + def_bool $(as-instr,.reloc label$(comma) R_RISCV_SET_ULEB128$(comma) 127\n.reloc label$(comma) R_RISCV_SUB_ULEB128$(comma) 127\nlabel:\n.word 0) 6 + 7 + menuconfig RUNTIME_KERNEL_TESTING_MENU 8 + bool "arch/riscv/kernel runtime Testing" 9 + def_bool y 10 + help 11 + Enable riscv kernel runtime testing. 12 + 13 + if RUNTIME_KERNEL_TESTING_MENU 14 + 15 + config RISCV_MODULE_LINKING_KUNIT 16 + bool "KUnit test riscv module linking at runtime" if !KUNIT_ALL_TESTS 17 + depends on KUNIT 18 + default KUNIT_ALL_TESTS 19 + help 20 + Enable this option to test riscv module linking at boot. This will 21 + enable a module called "test_module_linking". 22 + 23 + KUnit tests run during boot and output the results to the debug log 24 + in TAP format (http://testanything.org/). Only useful for kernel devs 25 + running the KUnit test harness, and not intended for inclusion into a 26 + production build. 27 + 28 + For more information on KUnit and unit tests in general please refer 29 + to the KUnit documentation in Documentation/dev-tools/kunit/. 30 + 31 + If unsure, say N. 32 + 33 + endif # RUNTIME_TESTING_MENU 34 + 35 + endmenu # "arch/riscv/kernel runtime Testing"
+1
arch/riscv/kernel/tests/Makefile
··· 1 + obj-$(CONFIG_RISCV_MODULE_LINKING_KUNIT) += module_test/
+15
arch/riscv/kernel/tests/module_test/Makefile
··· 1 + obj-m += test_module_linking.o 2 + 3 + test_sub := test_sub6.o test_sub8.o test_sub16.o test_sub32.o test_sub64.o 4 + 5 + test_set := test_set6.o test_set8.o test_set16.o test_set32.o 6 + 7 + test_module_linking-objs += $(test_sub) 8 + 9 + test_module_linking-objs += $(test_set) 10 + 11 + ifeq ($(CONFIG_AS_HAS_ULEB128),y) 12 + test_module_linking-objs += test_uleb128.o 13 + endif 14 + 15 + test_module_linking-objs += test_module_linking_main.o
+88
arch/riscv/kernel/tests/module_test/test_module_linking_main.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2023 Rivos Inc. 4 + */ 5 + 6 + #include <linux/module.h> 7 + #include <linux/kernel.h> 8 + #include <linux/init.h> 9 + #include <kunit/test.h> 10 + 11 + MODULE_LICENSE("GPL"); 12 + MODULE_DESCRIPTION("Test module linking"); 13 + 14 + extern int test_set32(void); 15 + extern int test_set16(void); 16 + extern int test_set8(void); 17 + extern int test_set6(void); 18 + extern long test_sub64(void); 19 + extern int test_sub32(void); 20 + extern int test_sub16(void); 21 + extern int test_sub8(void); 22 + extern int test_sub6(void); 23 + 24 + #ifdef CONFIG_AS_HAS_ULEB128 25 + extern int test_uleb_basic(void); 26 + extern int test_uleb_large(void); 27 + #endif 28 + 29 + #define CHECK_EQ(lhs, rhs) KUNIT_ASSERT_EQ(test, lhs, rhs) 30 + 31 + void run_test_set(struct kunit *test); 32 + void run_test_sub(struct kunit *test); 33 + void run_test_uleb(struct kunit *test); 34 + 35 + void run_test_set(struct kunit *test) 36 + { 37 + int val32 = test_set32(); 38 + int val16 = test_set16(); 39 + int val8 = test_set8(); 40 + int val6 = test_set6(); 41 + 42 + CHECK_EQ(val32, 0); 43 + CHECK_EQ(val16, 0); 44 + CHECK_EQ(val8, 0); 45 + CHECK_EQ(val6, 0); 46 + } 47 + 48 + void run_test_sub(struct kunit *test) 49 + { 50 + int val64 = test_sub64(); 51 + int val32 = test_sub32(); 52 + int val16 = test_sub16(); 53 + int val8 = test_sub8(); 54 + int val6 = test_sub6(); 55 + 56 + CHECK_EQ(val64, 0); 57 + CHECK_EQ(val32, 0); 58 + CHECK_EQ(val16, 0); 59 + CHECK_EQ(val8, 0); 60 + CHECK_EQ(val6, 0); 61 + } 62 + 63 + #ifdef CONFIG_AS_HAS_ULEB128 64 + void run_test_uleb(struct kunit *test) 65 + { 66 + int val_uleb = test_uleb_basic(); 67 + int val_uleb2 = test_uleb_large(); 68 + 69 + CHECK_EQ(val_uleb, 0); 70 + CHECK_EQ(val_uleb2, 0); 71 + } 72 + #endif 73 + 74 + static struct kunit_case __refdata riscv_module_linking_test_cases[] = { 75 + KUNIT_CASE(run_test_set), 76 + KUNIT_CASE(run_test_sub), 77 + #ifdef CONFIG_AS_HAS_ULEB128 78 + KUNIT_CASE(run_test_uleb), 79 + #endif 80 + {} 81 + }; 82 + 83 + static struct kunit_suite riscv_module_linking_test_suite = { 84 + .name = "riscv_checksum", 85 + .test_cases = riscv_module_linking_test_cases, 86 + }; 87 + 88 + kunit_test_suites(&riscv_module_linking_test_suite);
+23
arch/riscv/kernel/tests/module_test/test_set16.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Rivos Inc. 4 + */ 5 + 6 + .text 7 + .global test_set16 8 + test_set16: 9 + lw a0, set16 10 + la t0, set16 11 + #ifdef CONFIG_32BIT 12 + slli t0, t0, 16 13 + srli t0, t0, 16 14 + #else 15 + slli t0, t0, 48 16 + srli t0, t0, 48 17 + #endif 18 + sub a0, a0, t0 19 + ret 20 + .data 21 + set16: 22 + .reloc set16, R_RISCV_SET16, set16 23 + .word 0
+20
arch/riscv/kernel/tests/module_test/test_set32.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Rivos Inc. 4 + */ 5 + 6 + .text 7 + .global test_set32 8 + test_set32: 9 + lw a0, set32 10 + la t0, set32 11 + #ifndef CONFIG_32BIT 12 + slli t0, t0, 32 13 + srli t0, t0, 32 14 + #endif 15 + sub a0, a0, t0 16 + ret 17 + .data 18 + set32: 19 + .reloc set32, R_RISCV_SET32, set32 20 + .word 0
+23
arch/riscv/kernel/tests/module_test/test_set6.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Rivos Inc. 4 + */ 5 + 6 + .text 7 + .global test_set6 8 + test_set6: 9 + lw a0, set6 10 + la t0, set6 11 + #ifdef CONFIG_32BIT 12 + slli t0, t0, 26 13 + srli t0, t0, 26 14 + #else 15 + slli t0, t0, 58 16 + srli t0, t0, 58 17 + #endif 18 + sub a0, a0, t0 19 + ret 20 + .data 21 + set6: 22 + .reloc set6, R_RISCV_SET6, set6 23 + .word 0
+23
arch/riscv/kernel/tests/module_test/test_set8.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Rivos Inc. 4 + */ 5 + 6 + .text 7 + .global test_set8 8 + test_set8: 9 + lw a0, set8 10 + la t0, set8 11 + #ifdef CONFIG_32BIT 12 + slli t0, t0, 24 13 + srli t0, t0, 24 14 + #else 15 + slli t0, t0, 56 16 + srli t0, t0, 56 17 + #endif 18 + sub a0, a0, t0 19 + ret 20 + .data 21 + set8: 22 + .reloc set8, R_RISCV_SET8, set8 23 + .word 0
+20
arch/riscv/kernel/tests/module_test/test_sub16.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Rivos Inc. 4 + */ 5 + 6 + .text 7 + .global test_sub16 8 + test_sub16: 9 + lh a0, sub16 10 + addi a0, a0, -32 11 + ret 12 + first: 13 + .space 32 14 + second: 15 + 16 + .data 17 + sub16: 18 + .reloc sub16, R_RISCV_ADD16, second 19 + .reloc sub16, R_RISCV_SUB16, first 20 + .half 0
+20
arch/riscv/kernel/tests/module_test/test_sub32.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Rivos Inc. 4 + */ 5 + 6 + .text 7 + .global test_sub32 8 + test_sub32: 9 + lw a0, sub32 10 + addi a0, a0, -32 11 + ret 12 + first: 13 + .space 32 14 + second: 15 + 16 + .data 17 + sub32: 18 + .reloc sub32, R_RISCV_ADD32, second 19 + .reloc sub32, R_RISCV_SUB32, first 20 + .word 0
+20
arch/riscv/kernel/tests/module_test/test_sub6.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Rivos Inc. 4 + */ 5 + 6 + .text 7 + .global test_sub6 8 + test_sub6: 9 + lb a0, sub6 10 + addi a0, a0, -32 11 + ret 12 + first: 13 + .space 32 14 + second: 15 + 16 + .data 17 + sub6: 18 + .reloc sub6, R_RISCV_SET6, second 19 + .reloc sub6, R_RISCV_SUB6, first 20 + .byte 0
+25
arch/riscv/kernel/tests/module_test/test_sub64.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Rivos Inc. 4 + */ 5 + 6 + .text 7 + .global test_sub64 8 + test_sub64: 9 + #ifdef CONFIG_32BIT 10 + lw a0, sub64 11 + #else 12 + ld a0, sub64 13 + #endif 14 + addi a0, a0, -32 15 + ret 16 + first: 17 + .space 32 18 + second: 19 + 20 + .data 21 + sub64: 22 + .reloc sub64, R_RISCV_ADD64, second 23 + .reloc sub64, R_RISCV_SUB64, first 24 + .word 0 25 + .word 0
+20
arch/riscv/kernel/tests/module_test/test_sub8.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Rivos Inc. 4 + */ 5 + 6 + .text 7 + .global test_sub8 8 + test_sub8: 9 + lb a0, sub8 10 + addi a0, a0, -32 11 + ret 12 + first: 13 + .space 32 14 + second: 15 + 16 + .data 17 + sub8: 18 + .reloc sub8, R_RISCV_ADD8, second 19 + .reloc sub8, R_RISCV_SUB8, first 20 + .byte 0
+31
arch/riscv/kernel/tests/module_test/test_uleb128.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2023 Rivos Inc. 4 + */ 5 + 6 + .text 7 + .global test_uleb_basic 8 + test_uleb_basic: 9 + ld a0, second 10 + addi a0, a0, -127 11 + ret 12 + 13 + .global test_uleb_large 14 + test_uleb_large: 15 + ld a0, fourth 16 + addi a0, a0, -0x07e8 17 + ret 18 + 19 + .data 20 + first: 21 + .space 127 22 + second: 23 + .reloc second, R_RISCV_SET_ULEB128, second 24 + .reloc second, R_RISCV_SUB_ULEB128, first 25 + .dword 0 26 + third: 27 + .space 1000 28 + fourth: 29 + .reloc fourth, R_RISCV_SET_ULEB128, fourth 30 + .reloc fourth, R_RISCV_SUB_ULEB128, third 31 + .dword 0
+18 -12
arch/riscv/kernel/traps.c
··· 36 36 37 37 static DEFINE_SPINLOCK(die_lock); 38 38 39 - static void dump_kernel_instr(const char *loglvl, struct pt_regs *regs) 39 + static int copy_code(struct pt_regs *regs, u16 *val, const u16 *insns) 40 + { 41 + const void __user *uaddr = (__force const void __user *)insns; 42 + 43 + if (!user_mode(regs)) 44 + return get_kernel_nofault(*val, insns); 45 + 46 + /* The user space code from other tasks cannot be accessed. */ 47 + if (regs != task_pt_regs(current)) 48 + return -EPERM; 49 + 50 + return copy_from_user_nofault(val, uaddr, sizeof(*val)); 51 + } 52 + 53 + static void dump_instr(const char *loglvl, struct pt_regs *regs) 40 54 { 41 55 char str[sizeof("0000 ") * 12 + 2 + 1], *p = str; 42 56 const u16 *insns = (u16 *)instruction_pointer(regs); ··· 59 45 int i; 60 46 61 47 for (i = -10; i < 2; i++) { 62 - bad = get_kernel_nofault(val, &insns[i]); 48 + bad = copy_code(regs, &val, &insns[i]); 63 49 if (!bad) { 64 50 p += sprintf(p, i == 0 ? "(%04hx) " : "%04hx ", val); 65 51 } else { ··· 88 74 print_modules(); 89 75 if (regs) { 90 76 show_regs(regs); 91 - dump_kernel_instr(KERN_EMERG, regs); 77 + dump_instr(KERN_EMERG, regs); 92 78 } 93 79 94 80 cause = regs ? regs->cause : -1; ··· 121 107 print_vma_addr(KERN_CONT " in ", instruction_pointer(regs)); 122 108 pr_cont("\n"); 123 109 __show_regs(regs); 110 + dump_instr(KERN_EMERG, regs); 124 111 } 125 112 126 113 force_sig_fault(signo, code, (void __user *)addr); ··· 196 181 197 182 DO_ERROR_INFO(do_trap_load_fault, 198 183 SIGSEGV, SEGV_ACCERR, "load access fault"); 199 - #ifndef CONFIG_RISCV_M_MODE 200 - DO_ERROR_INFO(do_trap_load_misaligned, 201 - SIGBUS, BUS_ADRALN, "Oops - load address misaligned"); 202 - DO_ERROR_INFO(do_trap_store_misaligned, 203 - SIGBUS, BUS_ADRALN, "Oops - store (or AMO) address misaligned"); 204 - #else 205 - int handle_misaligned_load(struct pt_regs *regs); 206 - int handle_misaligned_store(struct pt_regs *regs); 207 184 208 185 asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs) 209 186 { ··· 238 231 irqentry_nmi_exit(regs, state); 239 232 } 240 233 } 241 - #endif 242 234 DO_ERROR_INFO(do_trap_store_fault, 243 235 SIGSEGV, SEGV_ACCERR, "store (or AMO) access fault"); 244 236 DO_ERROR_INFO(do_trap_ecall_s,
+331 -50
arch/riscv/kernel/traps_misaligned.c
··· 6 6 #include <linux/init.h> 7 7 #include <linux/mm.h> 8 8 #include <linux/module.h> 9 + #include <linux/perf_event.h> 9 10 #include <linux/irq.h> 10 11 #include <linux/stringify.h> 11 12 12 13 #include <asm/processor.h> 13 14 #include <asm/ptrace.h> 14 15 #include <asm/csr.h> 16 + #include <asm/entry-common.h> 17 + #include <asm/hwprobe.h> 18 + #include <asm/cpufeature.h> 15 19 16 20 #define INSN_MATCH_LB 0x3 17 21 #define INSN_MASK_LB 0x707f ··· 155 151 #define PRECISION_S 0 156 152 #define PRECISION_D 1 157 153 158 - #define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type, insn) \ 159 - static inline type load_##type(const type *addr) \ 160 - { \ 161 - type val; \ 162 - asm (#insn " %0, %1" \ 163 - : "=&r" (val) : "m" (*addr)); \ 164 - return val; \ 154 + #ifdef CONFIG_FPU 155 + 156 + #define FP_GET_RD(insn) (insn >> 7 & 0x1F) 157 + 158 + extern void put_f32_reg(unsigned long fp_reg, unsigned long value); 159 + 160 + static int set_f32_rd(unsigned long insn, struct pt_regs *regs, 161 + unsigned long val) 162 + { 163 + unsigned long fp_reg = FP_GET_RD(insn); 164 + 165 + put_f32_reg(fp_reg, val); 166 + regs->status |= SR_FS_DIRTY; 167 + 168 + return 0; 165 169 } 166 170 167 - #define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type, insn) \ 168 - static inline void store_##type(type *addr, type val) \ 169 - { \ 170 - asm volatile (#insn " %0, %1\n" \ 171 - : : "r" (val), "m" (*addr)); \ 172 - } 171 + extern void put_f64_reg(unsigned long fp_reg, unsigned long value); 173 172 174 - DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u8, lbu) 175 - DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u16, lhu) 176 - DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s8, lb) 177 - DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s16, lh) 178 - DECLARE_UNPRIVILEGED_LOAD_FUNCTION(s32, lw) 179 - DECLARE_UNPRIVILEGED_STORE_FUNCTION(u8, sb) 180 - DECLARE_UNPRIVILEGED_STORE_FUNCTION(u16, sh) 181 - DECLARE_UNPRIVILEGED_STORE_FUNCTION(u32, sw) 182 - #if defined(CONFIG_64BIT) 183 - DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u32, lwu) 184 - DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u64, ld) 185 - DECLARE_UNPRIVILEGED_STORE_FUNCTION(u64, sd) 186 - DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong, ld) 173 + static int set_f64_rd(unsigned long insn, struct pt_regs *regs, u64 val) 174 + { 175 + unsigned long fp_reg = FP_GET_RD(insn); 176 + unsigned long value; 177 + 178 + #if __riscv_xlen == 32 179 + value = (unsigned long) &val; 187 180 #else 188 - DECLARE_UNPRIVILEGED_LOAD_FUNCTION(u32, lw) 189 - DECLARE_UNPRIVILEGED_LOAD_FUNCTION(ulong, lw) 181 + value = val; 182 + #endif 183 + put_f64_reg(fp_reg, value); 184 + regs->status |= SR_FS_DIRTY; 190 185 191 - static inline u64 load_u64(const u64 *addr) 192 - { 193 - return load_u32((u32 *)addr) 194 - + ((u64)load_u32((u32 *)addr + 1) << 32); 186 + return 0; 195 187 } 196 188 197 - static inline void store_u64(u64 *addr, u64 val) 189 + #if __riscv_xlen == 32 190 + extern void get_f64_reg(unsigned long fp_reg, u64 *value); 191 + 192 + static u64 get_f64_rs(unsigned long insn, u8 fp_reg_offset, 193 + struct pt_regs *regs) 198 194 { 199 - store_u32((u32 *)addr, val); 200 - store_u32((u32 *)addr + 1, val >> 32); 195 + unsigned long fp_reg = (insn >> fp_reg_offset) & 0x1F; 196 + u64 val; 197 + 198 + get_f64_reg(fp_reg, &val); 199 + regs->status |= SR_FS_DIRTY; 200 + 201 + return val; 201 202 } 203 + #else 204 + 205 + extern unsigned long get_f64_reg(unsigned long fp_reg); 206 + 207 + static unsigned long get_f64_rs(unsigned long insn, u8 fp_reg_offset, 208 + struct pt_regs *regs) 209 + { 210 + unsigned long fp_reg = (insn >> fp_reg_offset) & 0x1F; 211 + unsigned long val; 212 + 213 + val = get_f64_reg(fp_reg); 214 + regs->status |= SR_FS_DIRTY; 215 + 216 + return val; 217 + } 218 + 202 219 #endif 203 220 204 - static inline ulong get_insn(ulong mepc) 221 + extern unsigned long get_f32_reg(unsigned long fp_reg); 222 + 223 + static unsigned long get_f32_rs(unsigned long insn, u8 fp_reg_offset, 224 + struct pt_regs *regs) 225 + { 226 + unsigned long fp_reg = (insn >> fp_reg_offset) & 0x1F; 227 + unsigned long val; 228 + 229 + val = get_f32_reg(fp_reg); 230 + regs->status |= SR_FS_DIRTY; 231 + 232 + return val; 233 + } 234 + 235 + #else /* CONFIG_FPU */ 236 + static void set_f32_rd(unsigned long insn, struct pt_regs *regs, 237 + unsigned long val) {} 238 + 239 + static void set_f64_rd(unsigned long insn, struct pt_regs *regs, u64 val) {} 240 + 241 + static unsigned long get_f64_rs(unsigned long insn, u8 fp_reg_offset, 242 + struct pt_regs *regs) 243 + { 244 + return 0; 245 + } 246 + 247 + static unsigned long get_f32_rs(unsigned long insn, u8 fp_reg_offset, 248 + struct pt_regs *regs) 249 + { 250 + return 0; 251 + } 252 + 253 + #endif 254 + 255 + #define GET_F64_RS2(insn, regs) (get_f64_rs(insn, 20, regs)) 256 + #define GET_F64_RS2C(insn, regs) (get_f64_rs(insn, 2, regs)) 257 + #define GET_F64_RS2S(insn, regs) (get_f64_rs(RVC_RS2S(insn), 0, regs)) 258 + 259 + #define GET_F32_RS2(insn, regs) (get_f32_rs(insn, 20, regs)) 260 + #define GET_F32_RS2C(insn, regs) (get_f32_rs(insn, 2, regs)) 261 + #define GET_F32_RS2S(insn, regs) (get_f32_rs(RVC_RS2S(insn), 0, regs)) 262 + 263 + #ifdef CONFIG_RISCV_M_MODE 264 + static inline int load_u8(struct pt_regs *regs, const u8 *addr, u8 *r_val) 265 + { 266 + u8 val; 267 + 268 + asm volatile("lbu %0, %1" : "=&r" (val) : "m" (*addr)); 269 + *r_val = val; 270 + 271 + return 0; 272 + } 273 + 274 + static inline int store_u8(struct pt_regs *regs, u8 *addr, u8 val) 275 + { 276 + asm volatile ("sb %0, %1\n" : : "r" (val), "m" (*addr)); 277 + 278 + return 0; 279 + } 280 + 281 + static inline int get_insn(struct pt_regs *regs, ulong mepc, ulong *r_insn) 205 282 { 206 283 register ulong __mepc asm ("a2") = mepc; 207 284 ulong val, rvc_mask = 3, tmp; ··· 311 226 : [addr] "r" (__mepc), [rvc_mask] "r" (rvc_mask), 312 227 [xlen_minus_16] "i" (XLEN_MINUS_16)); 313 228 314 - return val; 229 + *r_insn = val; 230 + 231 + return 0; 315 232 } 233 + #else 234 + static inline int load_u8(struct pt_regs *regs, const u8 *addr, u8 *r_val) 235 + { 236 + if (user_mode(regs)) { 237 + return __get_user(*r_val, addr); 238 + } else { 239 + *r_val = *addr; 240 + return 0; 241 + } 242 + } 243 + 244 + static inline int store_u8(struct pt_regs *regs, u8 *addr, u8 val) 245 + { 246 + if (user_mode(regs)) { 247 + return __put_user(val, addr); 248 + } else { 249 + *addr = val; 250 + return 0; 251 + } 252 + } 253 + 254 + #define __read_insn(regs, insn, insn_addr) \ 255 + ({ \ 256 + int __ret; \ 257 + \ 258 + if (user_mode(regs)) { \ 259 + __ret = __get_user(insn, insn_addr); \ 260 + } else { \ 261 + insn = *insn_addr; \ 262 + __ret = 0; \ 263 + } \ 264 + \ 265 + __ret; \ 266 + }) 267 + 268 + static inline int get_insn(struct pt_regs *regs, ulong epc, ulong *r_insn) 269 + { 270 + ulong insn = 0; 271 + 272 + if (epc & 0x2) { 273 + ulong tmp = 0; 274 + u16 __user *insn_addr = (u16 __user *)epc; 275 + 276 + if (__read_insn(regs, insn, insn_addr)) 277 + return -EFAULT; 278 + /* __get_user() uses regular "lw" which sign extend the loaded 279 + * value make sure to clear higher order bits in case we "or" it 280 + * below with the upper 16 bits half. 281 + */ 282 + insn &= GENMASK(15, 0); 283 + if ((insn & __INSN_LENGTH_MASK) != __INSN_LENGTH_32) { 284 + *r_insn = insn; 285 + return 0; 286 + } 287 + insn_addr++; 288 + if (__read_insn(regs, tmp, insn_addr)) 289 + return -EFAULT; 290 + *r_insn = (tmp << 16) | insn; 291 + 292 + return 0; 293 + } else { 294 + u32 __user *insn_addr = (u32 __user *)epc; 295 + 296 + if (__read_insn(regs, insn, insn_addr)) 297 + return -EFAULT; 298 + if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) { 299 + *r_insn = insn; 300 + return 0; 301 + } 302 + insn &= GENMASK(15, 0); 303 + *r_insn = insn; 304 + 305 + return 0; 306 + } 307 + } 308 + #endif 316 309 317 310 union reg_data { 318 311 u8 data_bytes[8]; ··· 398 235 u64 data_u64; 399 236 }; 400 237 238 + static bool unaligned_ctl __read_mostly; 239 + 240 + /* sysctl hooks */ 241 + int unaligned_enabled __read_mostly = 1; /* Enabled by default */ 242 + 401 243 int handle_misaligned_load(struct pt_regs *regs) 402 244 { 403 245 union reg_data val; 404 246 unsigned long epc = regs->epc; 405 - unsigned long insn = get_insn(epc); 406 - unsigned long addr = csr_read(mtval); 247 + unsigned long insn; 248 + unsigned long addr = regs->badaddr; 407 249 int i, fp = 0, shift = 0, len = 0; 250 + 251 + perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr); 252 + 253 + *this_cpu_ptr(&misaligned_access_speed) = RISCV_HWPROBE_MISALIGNED_EMULATED; 254 + 255 + if (!unaligned_enabled) 256 + return -1; 257 + 258 + if (user_mode(regs) && (current->thread.align_ctl & PR_UNALIGN_SIGBUS)) 259 + return -1; 260 + 261 + if (get_insn(regs, epc, &insn)) 262 + return -1; 408 263 409 264 regs->epc = 0; 410 265 ··· 486 305 return -1; 487 306 } 488 307 489 - val.data_u64 = 0; 490 - for (i = 0; i < len; i++) 491 - val.data_bytes[i] = load_u8((void *)(addr + i)); 308 + if (!IS_ENABLED(CONFIG_FPU) && fp) 309 + return -EOPNOTSUPP; 492 310 493 - if (fp) 494 - return -1; 495 - SET_RD(insn, regs, val.data_ulong << shift >> shift); 311 + val.data_u64 = 0; 312 + for (i = 0; i < len; i++) { 313 + if (load_u8(regs, (void *)(addr + i), &val.data_bytes[i])) 314 + return -1; 315 + } 316 + 317 + if (!fp) 318 + SET_RD(insn, regs, val.data_ulong << shift >> shift); 319 + else if (len == 8) 320 + set_f64_rd(insn, regs, val.data_u64); 321 + else 322 + set_f32_rd(insn, regs, val.data_ulong); 496 323 497 324 regs->epc = epc + INSN_LEN(insn); 498 325 ··· 511 322 { 512 323 union reg_data val; 513 324 unsigned long epc = regs->epc; 514 - unsigned long insn = get_insn(epc); 515 - unsigned long addr = csr_read(mtval); 516 - int i, len = 0; 325 + unsigned long insn; 326 + unsigned long addr = regs->badaddr; 327 + int i, len = 0, fp = 0; 328 + 329 + perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr); 330 + 331 + if (!unaligned_enabled) 332 + return -1; 333 + 334 + if (user_mode(regs) && (current->thread.align_ctl & PR_UNALIGN_SIGBUS)) 335 + return -1; 336 + 337 + if (get_insn(regs, epc, &insn)) 338 + return -1; 517 339 518 340 regs->epc = 0; 519 341 ··· 536 336 } else if ((insn & INSN_MASK_SD) == INSN_MATCH_SD) { 537 337 len = 8; 538 338 #endif 339 + } else if ((insn & INSN_MASK_FSD) == INSN_MATCH_FSD) { 340 + fp = 1; 341 + len = 8; 342 + val.data_u64 = GET_F64_RS2(insn, regs); 343 + } else if ((insn & INSN_MASK_FSW) == INSN_MATCH_FSW) { 344 + fp = 1; 345 + len = 4; 346 + val.data_ulong = GET_F32_RS2(insn, regs); 539 347 } else if ((insn & INSN_MASK_SH) == INSN_MATCH_SH) { 540 348 len = 2; 541 349 #if defined(CONFIG_64BIT) ··· 562 354 ((insn >> SH_RD) & 0x1f)) { 563 355 len = 4; 564 356 val.data_ulong = GET_RS2C(insn, regs); 357 + } else if ((insn & INSN_MASK_C_FSD) == INSN_MATCH_C_FSD) { 358 + fp = 1; 359 + len = 8; 360 + val.data_u64 = GET_F64_RS2S(insn, regs); 361 + } else if ((insn & INSN_MASK_C_FSDSP) == INSN_MATCH_C_FSDSP) { 362 + fp = 1; 363 + len = 8; 364 + val.data_u64 = GET_F64_RS2C(insn, regs); 365 + #if !defined(CONFIG_64BIT) 366 + } else if ((insn & INSN_MASK_C_FSW) == INSN_MATCH_C_FSW) { 367 + fp = 1; 368 + len = 4; 369 + val.data_ulong = GET_F32_RS2S(insn, regs); 370 + } else if ((insn & INSN_MASK_C_FSWSP) == INSN_MATCH_C_FSWSP) { 371 + fp = 1; 372 + len = 4; 373 + val.data_ulong = GET_F32_RS2C(insn, regs); 374 + #endif 565 375 } else { 566 376 regs->epc = epc; 567 377 return -1; 568 378 } 569 379 570 - for (i = 0; i < len; i++) 571 - store_u8((void *)(addr + i), val.data_bytes[i]); 380 + if (!IS_ENABLED(CONFIG_FPU) && fp) 381 + return -EOPNOTSUPP; 382 + 383 + for (i = 0; i < len; i++) { 384 + if (store_u8(regs, (void *)(addr + i), val.data_bytes[i])) 385 + return -1; 386 + } 572 387 573 388 regs->epc = epc + INSN_LEN(insn); 574 389 575 390 return 0; 391 + } 392 + 393 + bool check_unaligned_access_emulated(int cpu) 394 + { 395 + long *mas_ptr = per_cpu_ptr(&misaligned_access_speed, cpu); 396 + unsigned long tmp_var, tmp_val; 397 + bool misaligned_emu_detected; 398 + 399 + *mas_ptr = RISCV_HWPROBE_MISALIGNED_UNKNOWN; 400 + 401 + __asm__ __volatile__ ( 402 + " "REG_L" %[tmp], 1(%[ptr])\n" 403 + : [tmp] "=r" (tmp_val) : [ptr] "r" (&tmp_var) : "memory"); 404 + 405 + misaligned_emu_detected = (*mas_ptr == RISCV_HWPROBE_MISALIGNED_EMULATED); 406 + /* 407 + * If unaligned_ctl is already set, this means that we detected that all 408 + * CPUS uses emulated misaligned access at boot time. If that changed 409 + * when hotplugging the new cpu, this is something we don't handle. 410 + */ 411 + if (unlikely(unaligned_ctl && !misaligned_emu_detected)) { 412 + pr_crit("CPU misaligned accesses non homogeneous (expected all emulated)\n"); 413 + while (true) 414 + cpu_relax(); 415 + } 416 + 417 + return misaligned_emu_detected; 418 + } 419 + 420 + void unaligned_emulation_finish(void) 421 + { 422 + int cpu; 423 + 424 + /* 425 + * We can only support PR_UNALIGN controls if all CPUs have misaligned 426 + * accesses emulated since tasks requesting such control can run on any 427 + * CPU. 428 + */ 429 + for_each_present_cpu(cpu) { 430 + if (per_cpu(misaligned_access_speed, cpu) != 431 + RISCV_HWPROBE_MISALIGNED_EMULATED) { 432 + return; 433 + } 434 + } 435 + unaligned_ctl = true; 436 + } 437 + 438 + bool unaligned_ctl_available(void) 439 + { 440 + return unaligned_ctl; 576 441 }
+2 -2
arch/riscv/kernel/vdso/flush_icache.S
··· 8 8 9 9 .text 10 10 /* int __vdso_flush_icache(void *start, void *end, unsigned long flags); */ 11 - ENTRY(__vdso_flush_icache) 11 + SYM_FUNC_START(__vdso_flush_icache) 12 12 .cfi_startproc 13 13 #ifdef CONFIG_SMP 14 14 li a7, __NR_riscv_flush_icache ··· 19 19 #endif 20 20 ret 21 21 .cfi_endproc 22 - ENDPROC(__vdso_flush_icache) 22 + SYM_FUNC_END(__vdso_flush_icache)
+2 -2
arch/riscv/kernel/vdso/getcpu.S
··· 8 8 9 9 .text 10 10 /* int __vdso_getcpu(unsigned *cpu, unsigned *node, void *unused); */ 11 - ENTRY(__vdso_getcpu) 11 + SYM_FUNC_START(__vdso_getcpu) 12 12 .cfi_startproc 13 13 /* For now, just do the syscall. */ 14 14 li a7, __NR_getcpu 15 15 ecall 16 16 ret 17 17 .cfi_endproc 18 - ENDPROC(__vdso_getcpu) 18 + SYM_FUNC_END(__vdso_getcpu)
+2 -2
arch/riscv/kernel/vdso/rt_sigreturn.S
··· 7 7 #include <asm/unistd.h> 8 8 9 9 .text 10 - ENTRY(__vdso_rt_sigreturn) 10 + SYM_FUNC_START(__vdso_rt_sigreturn) 11 11 .cfi_startproc 12 12 .cfi_signal_frame 13 13 li a7, __NR_rt_sigreturn 14 14 ecall 15 15 .cfi_endproc 16 - ENDPROC(__vdso_rt_sigreturn) 16 + SYM_FUNC_END(__vdso_rt_sigreturn)
+2 -2
arch/riscv/kernel/vdso/sys_hwprobe.S
··· 5 5 #include <asm/unistd.h> 6 6 7 7 .text 8 - ENTRY(riscv_hwprobe) 8 + SYM_FUNC_START(riscv_hwprobe) 9 9 .cfi_startproc 10 10 li a7, __NR_riscv_hwprobe 11 11 ecall 12 12 ret 13 13 14 14 .cfi_endproc 15 - ENDPROC(riscv_hwprobe) 15 + SYM_FUNC_END(riscv_hwprobe)
+19 -23
arch/riscv/kernel/vdso/vdso.lds.S
··· 23 23 .gnu.version_d : { *(.gnu.version_d) } 24 24 .gnu.version_r : { *(.gnu.version_r) } 25 25 26 - .note : { *(.note.*) } :text :note 27 26 .dynamic : { *(.dynamic) } :text :dynamic 28 27 29 - .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr 30 - .eh_frame : { KEEP (*(.eh_frame)) } :text 31 - 32 - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } 33 - 34 - /* 35 - * This linker script is used both with -r and with -shared. 36 - * For the layouts to match, we need to skip more than enough 37 - * space for the dynamic symbol table, etc. If this amount is 38 - * insufficient, ld -shared will error; simply increase it here. 39 - */ 40 - . = 0x800; 41 - .text : { *(.text .text.*) } :text 42 - 43 - . = ALIGN(4); 44 - .alternative : { 45 - __alt_start = .; 46 - *(.alternative) 47 - __alt_end = .; 48 - } 49 - 50 - .data : { 28 + .rodata : { 29 + *(.rodata .rodata.* .gnu.linkonce.r.*) 51 30 *(.got.plt) *(.got) 52 31 *(.data .data.* .gnu.linkonce.d.*) 53 32 *(.dynbss) 54 33 *(.bss .bss.* .gnu.linkonce.b.*) 34 + } 35 + 36 + .note : { *(.note.*) } :text :note 37 + 38 + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr 39 + .eh_frame : { KEEP (*(.eh_frame)) } :text 40 + 41 + /* 42 + * Text is well-separated from actual data: there's plenty of 43 + * stuff that isn't used at runtime in between. 44 + */ 45 + . = ALIGN(16); 46 + .text : { *(.text .text.*) } :text 47 + 48 + . = ALIGN(4); 49 + .alternative : { 50 + *(.alternative) 55 51 } 56 52 } 57 53
+1 -1
arch/riscv/kvm/aia.c
··· 14 14 #include <linux/kvm_host.h> 15 15 #include <linux/percpu.h> 16 16 #include <linux/spinlock.h> 17 - #include <asm/hwcap.h> 17 + #include <asm/cpufeature.h> 18 18 #include <asm/kvm_aia_imsic.h> 19 19 20 20 struct aia_hgei_control {
+1 -1
arch/riscv/kvm/main.c
··· 11 11 #include <linux/module.h> 12 12 #include <linux/kvm_host.h> 13 13 #include <asm/csr.h> 14 - #include <asm/hwcap.h> 14 + #include <asm/cpufeature.h> 15 15 #include <asm/sbi.h> 16 16 17 17 long kvm_arch_dev_ioctl(struct file *filp,
+1 -1
arch/riscv/kvm/tlb.c
··· 12 12 #include <linux/kvm_host.h> 13 13 #include <asm/cacheflush.h> 14 14 #include <asm/csr.h> 15 - #include <asm/hwcap.h> 15 + #include <asm/cpufeature.h> 16 16 #include <asm/insn-def.h> 17 17 18 18 #define has_svinval() riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)
+1 -1
arch/riscv/kvm/vcpu_fp.c
··· 11 11 #include <linux/err.h> 12 12 #include <linux/kvm_host.h> 13 13 #include <linux/uaccess.h> 14 - #include <asm/hwcap.h> 14 + #include <asm/cpufeature.h> 15 15 16 16 #ifdef CONFIG_FPU 17 17 void kvm_riscv_vcpu_fp_reset(struct kvm_vcpu *vcpu)
+1 -1
arch/riscv/kvm/vcpu_onereg.c
··· 13 13 #include <linux/uaccess.h> 14 14 #include <linux/kvm_host.h> 15 15 #include <asm/cacheflush.h> 16 - #include <asm/hwcap.h> 16 + #include <asm/cpufeature.h> 17 17 #include <asm/kvm_vcpu_vector.h> 18 18 #include <asm/vector.h> 19 19
+1 -1
arch/riscv/kvm/vcpu_vector.c
··· 11 11 #include <linux/err.h> 12 12 #include <linux/kvm_host.h> 13 13 #include <linux/uaccess.h> 14 - #include <asm/hwcap.h> 14 + #include <asm/cpufeature.h> 15 15 #include <asm/kvm_vcpu_vector.h> 16 16 #include <asm/vector.h> 17 17
+16 -16
arch/riscv/lib/clear_page.S
··· 29 29 lw a1, riscv_cboz_block_size 30 30 add a2, a0, a2 31 31 .Lzero_loop: 32 - CBO_zero(a0) 32 + CBO_ZERO(a0) 33 33 add a0, a0, a1 34 34 CBOZ_ALT(11, "bltu a0, a2, .Lzero_loop; ret", "nop; nop") 35 - CBO_zero(a0) 35 + CBO_ZERO(a0) 36 36 add a0, a0, a1 37 37 CBOZ_ALT(10, "bltu a0, a2, .Lzero_loop; ret", "nop; nop") 38 - CBO_zero(a0) 38 + CBO_ZERO(a0) 39 39 add a0, a0, a1 40 - CBO_zero(a0) 40 + CBO_ZERO(a0) 41 41 add a0, a0, a1 42 42 CBOZ_ALT(9, "bltu a0, a2, .Lzero_loop; ret", "nop; nop") 43 - CBO_zero(a0) 43 + CBO_ZERO(a0) 44 44 add a0, a0, a1 45 - CBO_zero(a0) 45 + CBO_ZERO(a0) 46 46 add a0, a0, a1 47 - CBO_zero(a0) 47 + CBO_ZERO(a0) 48 48 add a0, a0, a1 49 - CBO_zero(a0) 49 + CBO_ZERO(a0) 50 50 add a0, a0, a1 51 51 CBOZ_ALT(8, "bltu a0, a2, .Lzero_loop; ret", "nop; nop") 52 - CBO_zero(a0) 52 + CBO_ZERO(a0) 53 53 add a0, a0, a1 54 - CBO_zero(a0) 54 + CBO_ZERO(a0) 55 55 add a0, a0, a1 56 - CBO_zero(a0) 56 + CBO_ZERO(a0) 57 57 add a0, a0, a1 58 - CBO_zero(a0) 58 + CBO_ZERO(a0) 59 59 add a0, a0, a1 60 - CBO_zero(a0) 60 + CBO_ZERO(a0) 61 61 add a0, a0, a1 62 - CBO_zero(a0) 62 + CBO_ZERO(a0) 63 63 add a0, a0, a1 64 - CBO_zero(a0) 64 + CBO_ZERO(a0) 65 65 add a0, a0, a1 66 - CBO_zero(a0) 66 + CBO_ZERO(a0) 67 67 add a0, a0, a1 68 68 bltu a0, a2, .Lzero_loop 69 69 ret
+3 -3
arch/riscv/lib/memcpy.S
··· 7 7 #include <asm/asm.h> 8 8 9 9 /* void *memcpy(void *, const void *, size_t) */ 10 - ENTRY(__memcpy) 11 - WEAK(memcpy) 10 + SYM_FUNC_START(__memcpy) 12 11 move t6, a0 /* Preserve return value */ 13 12 14 13 /* Defer to byte-oriented copy for small sizes */ ··· 104 105 bltu a1, a3, 5b 105 106 6: 106 107 ret 107 - END(__memcpy) 108 + SYM_FUNC_END(__memcpy) 109 + SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy) 108 110 SYM_FUNC_ALIAS(__pi_memcpy, __memcpy) 109 111 SYM_FUNC_ALIAS(__pi___memcpy, __memcpy)
+28 -29
arch/riscv/lib/memmove.S
··· 7 7 #include <asm/asm.h> 8 8 9 9 SYM_FUNC_START(__memmove) 10 - SYM_FUNC_START_WEAK(memmove) 11 10 /* 12 11 * Returns 13 12 * a0 - dest ··· 25 26 */ 26 27 27 28 /* Return if nothing to do */ 28 - beq a0, a1, return_from_memmove 29 - beqz a2, return_from_memmove 29 + beq a0, a1, .Lreturn_from_memmove 30 + beqz a2, .Lreturn_from_memmove 30 31 31 32 /* 32 33 * Register Uses ··· 59 60 * small enough not to bother. 60 61 */ 61 62 andi t0, a2, -(2 * SZREG) 62 - beqz t0, byte_copy 63 + beqz t0, .Lbyte_copy 63 64 64 65 /* 65 66 * Now solve for t5 and t6. ··· 86 87 */ 87 88 xor t0, a0, a1 88 89 andi t1, t0, (SZREG - 1) 89 - beqz t1, coaligned_copy 90 + beqz t1, .Lcoaligned_copy 90 91 /* Fall through to misaligned fixup copy */ 91 92 92 - misaligned_fixup_copy: 93 - bltu a1, a0, misaligned_fixup_copy_reverse 93 + .Lmisaligned_fixup_copy: 94 + bltu a1, a0, .Lmisaligned_fixup_copy_reverse 94 95 95 - misaligned_fixup_copy_forward: 96 - jal t0, byte_copy_until_aligned_forward 96 + .Lmisaligned_fixup_copy_forward: 97 + jal t0, .Lbyte_copy_until_aligned_forward 97 98 98 99 andi a5, a1, (SZREG - 1) /* Find the alignment offset of src (a1) */ 99 100 slli a6, a5, 3 /* Multiply by 8 to convert that to bits to shift */ ··· 152 153 mv t3, t6 /* Fix the dest pointer in case the loop was broken */ 153 154 154 155 add a1, t3, a5 /* Restore the src pointer */ 155 - j byte_copy_forward /* Copy any remaining bytes */ 156 + j .Lbyte_copy_forward /* Copy any remaining bytes */ 156 157 157 - misaligned_fixup_copy_reverse: 158 - jal t0, byte_copy_until_aligned_reverse 158 + .Lmisaligned_fixup_copy_reverse: 159 + jal t0, .Lbyte_copy_until_aligned_reverse 159 160 160 161 andi a5, a4, (SZREG - 1) /* Find the alignment offset of src (a4) */ 161 162 slli a6, a5, 3 /* Multiply by 8 to convert that to bits to shift */ ··· 214 215 mv t4, t5 /* Fix the dest pointer in case the loop was broken */ 215 216 216 217 add a4, t4, a5 /* Restore the src pointer */ 217 - j byte_copy_reverse /* Copy any remaining bytes */ 218 + j .Lbyte_copy_reverse /* Copy any remaining bytes */ 218 219 219 220 /* 220 221 * Simple copy loops for SZREG co-aligned memory locations. 221 222 * These also make calls to do byte copies for any unaligned 222 223 * data at their terminations. 223 224 */ 224 - coaligned_copy: 225 - bltu a1, a0, coaligned_copy_reverse 225 + .Lcoaligned_copy: 226 + bltu a1, a0, .Lcoaligned_copy_reverse 226 227 227 - coaligned_copy_forward: 228 - jal t0, byte_copy_until_aligned_forward 228 + .Lcoaligned_copy_forward: 229 + jal t0, .Lbyte_copy_until_aligned_forward 229 230 230 231 1: 231 232 REG_L t1, ( 0 * SZREG)(a1) ··· 234 235 REG_S t1, (-1 * SZREG)(t3) 235 236 bne t3, t6, 1b 236 237 237 - j byte_copy_forward /* Copy any remaining bytes */ 238 + j .Lbyte_copy_forward /* Copy any remaining bytes */ 238 239 239 - coaligned_copy_reverse: 240 - jal t0, byte_copy_until_aligned_reverse 240 + .Lcoaligned_copy_reverse: 241 + jal t0, .Lbyte_copy_until_aligned_reverse 241 242 242 243 1: 243 244 REG_L t1, (-1 * SZREG)(a4) ··· 246 247 REG_S t1, ( 0 * SZREG)(t4) 247 248 bne t4, t5, 1b 248 249 249 - j byte_copy_reverse /* Copy any remaining bytes */ 250 + j .Lbyte_copy_reverse /* Copy any remaining bytes */ 250 251 251 252 /* 252 253 * These are basically sub-functions within the function. They ··· 257 258 * up from where they were left and we avoid code duplication 258 259 * without any overhead except the call in and return jumps. 259 260 */ 260 - byte_copy_until_aligned_forward: 261 + .Lbyte_copy_until_aligned_forward: 261 262 beq t3, t5, 2f 262 263 1: 263 264 lb t1, 0(a1) ··· 268 269 2: 269 270 jalr zero, 0x0(t0) /* Return to multibyte copy loop */ 270 271 271 - byte_copy_until_aligned_reverse: 272 + .Lbyte_copy_until_aligned_reverse: 272 273 beq t4, t6, 2f 273 274 1: 274 275 lb t1, -1(a4) ··· 284 285 * These will byte copy until they reach the end of data to copy. 285 286 * At that point, they will call to return from memmove. 286 287 */ 287 - byte_copy: 288 - bltu a1, a0, byte_copy_reverse 288 + .Lbyte_copy: 289 + bltu a1, a0, .Lbyte_copy_reverse 289 290 290 - byte_copy_forward: 291 + .Lbyte_copy_forward: 291 292 beq t3, t4, 2f 292 293 1: 293 294 lb t1, 0(a1) ··· 298 299 2: 299 300 ret 300 301 301 - byte_copy_reverse: 302 + .Lbyte_copy_reverse: 302 303 beq t4, t3, 2f 303 304 1: 304 305 lb t1, -1(a4) ··· 308 309 bne t4, t3, 1b 309 310 2: 310 311 311 - return_from_memmove: 312 + .Lreturn_from_memmove: 312 313 ret 313 314 314 - SYM_FUNC_END(memmove) 315 315 SYM_FUNC_END(__memmove) 316 + SYM_FUNC_ALIAS_WEAK(memmove, __memmove) 316 317 SYM_FUNC_ALIAS(__pi_memmove, __memmove) 317 318 SYM_FUNC_ALIAS(__pi___memmove, __memmove)
+3 -3
arch/riscv/lib/memset.S
··· 8 8 #include <asm/asm.h> 9 9 10 10 /* void *memset(void *, int, size_t) */ 11 - ENTRY(__memset) 12 - WEAK(memset) 11 + SYM_FUNC_START(__memset) 13 12 move t0, a0 /* Preserve return value */ 14 13 15 14 /* Defer to byte-oriented fill for small sizes */ ··· 109 110 bltu t0, a3, 5b 110 111 6: 111 112 ret 112 - END(__memset) 113 + SYM_FUNC_END(__memset) 114 + SYM_FUNC_ALIAS_WEAK(memset, __memset)
+5 -6
arch/riscv/lib/uaccess.S
··· 10 10 _asm_extable 100b, \lbl 11 11 .endm 12 12 13 - ENTRY(__asm_copy_to_user) 14 - ENTRY(__asm_copy_from_user) 13 + SYM_FUNC_START(__asm_copy_to_user) 15 14 16 15 /* Enable access to user memory */ 17 16 li t6, SR_SUM ··· 180 181 csrc CSR_STATUS, t6 181 182 sub a0, t5, a0 182 183 ret 183 - ENDPROC(__asm_copy_to_user) 184 - ENDPROC(__asm_copy_from_user) 184 + SYM_FUNC_END(__asm_copy_to_user) 185 185 EXPORT_SYMBOL(__asm_copy_to_user) 186 + SYM_FUNC_ALIAS(__asm_copy_from_user, __asm_copy_to_user) 186 187 EXPORT_SYMBOL(__asm_copy_from_user) 187 188 188 189 189 - ENTRY(__clear_user) 190 + SYM_FUNC_START(__clear_user) 190 191 191 192 /* Enable access to user memory */ 192 193 li t6, SR_SUM ··· 232 233 csrc CSR_STATUS, t6 233 234 sub a0, a3, a0 234 235 ret 235 - ENDPROC(__clear_user) 236 + SYM_FUNC_END(__clear_user) 236 237 EXPORT_SYMBOL(__clear_user)
+1
arch/riscv/mm/Makefile
··· 36 36 37 37 obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o 38 38 obj-$(CONFIG_RISCV_DMA_NONCOHERENT) += dma-noncoherent.o 39 + obj-$(CONFIG_RISCV_NONSTANDARD_CACHE_OPS) += cache-ops.o
+17
arch/riscv/mm/cache-ops.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2021 Western Digital Corporation or its affiliates. 4 + */ 5 + 6 + #include <asm/dma-noncoherent.h> 7 + 8 + struct riscv_nonstd_cache_ops noncoherent_cache_ops __ro_after_init; 9 + 10 + void 11 + riscv_noncoherent_register_cache_ops(const struct riscv_nonstd_cache_ops *ops) 12 + { 13 + if (!ops) 14 + return; 15 + noncoherent_cache_ops = *ops; 16 + } 17 + EXPORT_SYMBOL_GPL(riscv_noncoherent_register_cache_ops);
+4 -19
arch/riscv/mm/dma-noncoherent.c
··· 15 15 int dma_cache_alignment __ro_after_init = ARCH_DMA_MINALIGN; 16 16 EXPORT_SYMBOL_GPL(dma_cache_alignment); 17 17 18 - struct riscv_nonstd_cache_ops noncoherent_cache_ops __ro_after_init = { 19 - .wback = NULL, 20 - .inv = NULL, 21 - .wback_inv = NULL, 22 - }; 23 - 24 18 static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size) 25 19 { 26 20 void *vaddr = phys_to_virt(paddr); ··· 25 31 return; 26 32 } 27 33 #endif 28 - ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size); 34 + ALT_CMO_OP(CLEAN, vaddr, size, riscv_cbom_block_size); 29 35 } 30 36 31 37 static inline void arch_dma_cache_inv(phys_addr_t paddr, size_t size) ··· 39 45 } 40 46 #endif 41 47 42 - ALT_CMO_OP(inval, vaddr, size, riscv_cbom_block_size); 48 + ALT_CMO_OP(INVAL, vaddr, size, riscv_cbom_block_size); 43 49 } 44 50 45 51 static inline void arch_dma_cache_wback_inv(phys_addr_t paddr, size_t size) ··· 53 59 } 54 60 #endif 55 61 56 - ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size); 62 + ALT_CMO_OP(FLUSH, vaddr, size, riscv_cbom_block_size); 57 63 } 58 64 59 65 static inline bool arch_sync_dma_clean_before_fromdevice(void) ··· 125 131 } 126 132 #endif 127 133 128 - ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size); 134 + ALT_CMO_OP(FLUSH, flush_addr, size, riscv_cbom_block_size); 129 135 } 130 136 131 137 void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, ··· 156 162 if (!noncoherent_supported) 157 163 dma_cache_alignment = 1; 158 164 } 159 - 160 - void riscv_noncoherent_register_cache_ops(const struct riscv_nonstd_cache_ops *ops) 161 - { 162 - if (!ops) 163 - return; 164 - 165 - noncoherent_cache_ops = *ops; 166 - } 167 - EXPORT_SYMBOL_GPL(riscv_noncoherent_register_cache_ops);
+6 -6
arch/riscv/mm/init.c
··· 666 666 static uintptr_t __init best_map_size(phys_addr_t pa, uintptr_t va, 667 667 phys_addr_t size) 668 668 { 669 - if (!(pa & (PGDIR_SIZE - 1)) && !(va & (PGDIR_SIZE - 1)) && size >= PGDIR_SIZE) 670 - return PGDIR_SIZE; 671 - 672 - if (!(pa & (P4D_SIZE - 1)) && !(va & (P4D_SIZE - 1)) && size >= P4D_SIZE) 669 + if (pgtable_l5_enabled && 670 + !(pa & (P4D_SIZE - 1)) && !(va & (P4D_SIZE - 1)) && size >= P4D_SIZE) 673 671 return P4D_SIZE; 674 672 675 - if (!(pa & (PUD_SIZE - 1)) && !(va & (PUD_SIZE - 1)) && size >= PUD_SIZE) 673 + if (pgtable_l4_enabled && 674 + !(pa & (PUD_SIZE - 1)) && !(va & (PUD_SIZE - 1)) && size >= PUD_SIZE) 676 675 return PUD_SIZE; 677 676 678 - if (!(pa & (PMD_SIZE - 1)) && !(va & (PMD_SIZE - 1)) && size >= PMD_SIZE) 677 + if (IS_ENABLED(CONFIG_64BIT) && 678 + !(pa & (PMD_SIZE - 1)) && !(va & (PMD_SIZE - 1)) && size >= PMD_SIZE) 679 679 return PMD_SIZE; 680 680 681 681 return PAGE_SIZE;
+230 -40
arch/riscv/mm/pageattr.c
··· 5 5 6 6 #include <linux/pagewalk.h> 7 7 #include <linux/pgtable.h> 8 + #include <linux/vmalloc.h> 8 9 #include <asm/tlbflush.h> 9 10 #include <asm/bitops.h> 10 11 #include <asm/set_memory.h> ··· 24 23 new_val |= (pgprot_val(masks->set_mask)); 25 24 26 25 return new_val; 27 - } 28 - 29 - static int pageattr_pgd_entry(pgd_t *pgd, unsigned long addr, 30 - unsigned long next, struct mm_walk *walk) 31 - { 32 - pgd_t val = READ_ONCE(*pgd); 33 - 34 - if (pgd_leaf(val)) { 35 - val = __pgd(set_pageattr_masks(pgd_val(val), walk)); 36 - set_pgd(pgd, val); 37 - } 38 - 39 - return 0; 40 26 } 41 27 42 28 static int pageattr_p4d_entry(p4d_t *p4d, unsigned long addr, ··· 84 96 } 85 97 86 98 static const struct mm_walk_ops pageattr_ops = { 87 - .pgd_entry = pageattr_pgd_entry, 88 99 .p4d_entry = pageattr_p4d_entry, 89 100 .pud_entry = pageattr_pud_entry, 90 101 .pmd_entry = pageattr_pmd_entry, ··· 92 105 .walk_lock = PGWALK_RDLOCK, 93 106 }; 94 107 108 + #ifdef CONFIG_64BIT 109 + static int __split_linear_mapping_pmd(pud_t *pudp, 110 + unsigned long vaddr, unsigned long end) 111 + { 112 + pmd_t *pmdp; 113 + unsigned long next; 114 + 115 + pmdp = pmd_offset(pudp, vaddr); 116 + 117 + do { 118 + next = pmd_addr_end(vaddr, end); 119 + 120 + if (next - vaddr >= PMD_SIZE && 121 + vaddr <= (vaddr & PMD_MASK) && end >= next) 122 + continue; 123 + 124 + if (pmd_leaf(*pmdp)) { 125 + struct page *pte_page; 126 + unsigned long pfn = _pmd_pfn(*pmdp); 127 + pgprot_t prot = __pgprot(pmd_val(*pmdp) & ~_PAGE_PFN_MASK); 128 + pte_t *ptep_new; 129 + int i; 130 + 131 + pte_page = alloc_page(GFP_KERNEL); 132 + if (!pte_page) 133 + return -ENOMEM; 134 + 135 + ptep_new = (pte_t *)page_address(pte_page); 136 + for (i = 0; i < PTRS_PER_PTE; ++i, ++ptep_new) 137 + set_pte(ptep_new, pfn_pte(pfn + i, prot)); 138 + 139 + smp_wmb(); 140 + 141 + set_pmd(pmdp, pfn_pmd(page_to_pfn(pte_page), PAGE_TABLE)); 142 + } 143 + } while (pmdp++, vaddr = next, vaddr != end); 144 + 145 + return 0; 146 + } 147 + 148 + static int __split_linear_mapping_pud(p4d_t *p4dp, 149 + unsigned long vaddr, unsigned long end) 150 + { 151 + pud_t *pudp; 152 + unsigned long next; 153 + int ret; 154 + 155 + pudp = pud_offset(p4dp, vaddr); 156 + 157 + do { 158 + next = pud_addr_end(vaddr, end); 159 + 160 + if (next - vaddr >= PUD_SIZE && 161 + vaddr <= (vaddr & PUD_MASK) && end >= next) 162 + continue; 163 + 164 + if (pud_leaf(*pudp)) { 165 + struct page *pmd_page; 166 + unsigned long pfn = _pud_pfn(*pudp); 167 + pgprot_t prot = __pgprot(pud_val(*pudp) & ~_PAGE_PFN_MASK); 168 + pmd_t *pmdp_new; 169 + int i; 170 + 171 + pmd_page = alloc_page(GFP_KERNEL); 172 + if (!pmd_page) 173 + return -ENOMEM; 174 + 175 + pmdp_new = (pmd_t *)page_address(pmd_page); 176 + for (i = 0; i < PTRS_PER_PMD; ++i, ++pmdp_new) 177 + set_pmd(pmdp_new, 178 + pfn_pmd(pfn + ((i * PMD_SIZE) >> PAGE_SHIFT), prot)); 179 + 180 + smp_wmb(); 181 + 182 + set_pud(pudp, pfn_pud(page_to_pfn(pmd_page), PAGE_TABLE)); 183 + } 184 + 185 + ret = __split_linear_mapping_pmd(pudp, vaddr, next); 186 + if (ret) 187 + return ret; 188 + } while (pudp++, vaddr = next, vaddr != end); 189 + 190 + return 0; 191 + } 192 + 193 + static int __split_linear_mapping_p4d(pgd_t *pgdp, 194 + unsigned long vaddr, unsigned long end) 195 + { 196 + p4d_t *p4dp; 197 + unsigned long next; 198 + int ret; 199 + 200 + p4dp = p4d_offset(pgdp, vaddr); 201 + 202 + do { 203 + next = p4d_addr_end(vaddr, end); 204 + 205 + /* 206 + * If [vaddr; end] contains [vaddr & P4D_MASK; next], we don't 207 + * need to split, we'll change the protections on the whole P4D. 208 + */ 209 + if (next - vaddr >= P4D_SIZE && 210 + vaddr <= (vaddr & P4D_MASK) && end >= next) 211 + continue; 212 + 213 + if (p4d_leaf(*p4dp)) { 214 + struct page *pud_page; 215 + unsigned long pfn = _p4d_pfn(*p4dp); 216 + pgprot_t prot = __pgprot(p4d_val(*p4dp) & ~_PAGE_PFN_MASK); 217 + pud_t *pudp_new; 218 + int i; 219 + 220 + pud_page = alloc_page(GFP_KERNEL); 221 + if (!pud_page) 222 + return -ENOMEM; 223 + 224 + /* 225 + * Fill the pud level with leaf puds that have the same 226 + * protections as the leaf p4d. 227 + */ 228 + pudp_new = (pud_t *)page_address(pud_page); 229 + for (i = 0; i < PTRS_PER_PUD; ++i, ++pudp_new) 230 + set_pud(pudp_new, 231 + pfn_pud(pfn + ((i * PUD_SIZE) >> PAGE_SHIFT), prot)); 232 + 233 + /* 234 + * Make sure the pud filling is not reordered with the 235 + * p4d store which could result in seeing a partially 236 + * filled pud level. 237 + */ 238 + smp_wmb(); 239 + 240 + set_p4d(p4dp, pfn_p4d(page_to_pfn(pud_page), PAGE_TABLE)); 241 + } 242 + 243 + ret = __split_linear_mapping_pud(p4dp, vaddr, next); 244 + if (ret) 245 + return ret; 246 + } while (p4dp++, vaddr = next, vaddr != end); 247 + 248 + return 0; 249 + } 250 + 251 + static int __split_linear_mapping_pgd(pgd_t *pgdp, 252 + unsigned long vaddr, 253 + unsigned long end) 254 + { 255 + unsigned long next; 256 + int ret; 257 + 258 + do { 259 + next = pgd_addr_end(vaddr, end); 260 + /* We never use PGD mappings for the linear mapping */ 261 + ret = __split_linear_mapping_p4d(pgdp, vaddr, next); 262 + if (ret) 263 + return ret; 264 + } while (pgdp++, vaddr = next, vaddr != end); 265 + 266 + return 0; 267 + } 268 + 269 + static int split_linear_mapping(unsigned long start, unsigned long end) 270 + { 271 + return __split_linear_mapping_pgd(pgd_offset_k(start), start, end); 272 + } 273 + #endif /* CONFIG_64BIT */ 274 + 95 275 static int __set_memory(unsigned long addr, int numpages, pgprot_t set_mask, 96 276 pgprot_t clear_mask) 97 277 { 98 278 int ret; 99 279 unsigned long start = addr; 100 280 unsigned long end = start + PAGE_SIZE * numpages; 281 + unsigned long __maybe_unused lm_start; 282 + unsigned long __maybe_unused lm_end; 101 283 struct pageattr_masks masks = { 102 284 .set_mask = set_mask, 103 285 .clear_mask = clear_mask ··· 276 120 return 0; 277 121 278 122 mmap_write_lock(&init_mm); 123 + 124 + #ifdef CONFIG_64BIT 125 + /* 126 + * We are about to change the permissions of a kernel mapping, we must 127 + * apply the same changes to its linear mapping alias, which may imply 128 + * splitting a huge mapping. 129 + */ 130 + 131 + if (is_vmalloc_or_module_addr((void *)start)) { 132 + struct vm_struct *area = NULL; 133 + int i, page_start; 134 + 135 + area = find_vm_area((void *)start); 136 + page_start = (start - (unsigned long)area->addr) >> PAGE_SHIFT; 137 + 138 + for (i = page_start; i < page_start + numpages; ++i) { 139 + lm_start = (unsigned long)page_address(area->pages[i]); 140 + lm_end = lm_start + PAGE_SIZE; 141 + 142 + ret = split_linear_mapping(lm_start, lm_end); 143 + if (ret) 144 + goto unlock; 145 + 146 + ret = walk_page_range_novma(&init_mm, lm_start, lm_end, 147 + &pageattr_ops, NULL, &masks); 148 + if (ret) 149 + goto unlock; 150 + } 151 + } else if (is_kernel_mapping(start) || is_linear_mapping(start)) { 152 + lm_start = (unsigned long)lm_alias(start); 153 + lm_end = (unsigned long)lm_alias(end); 154 + 155 + ret = split_linear_mapping(lm_start, lm_end); 156 + if (ret) 157 + goto unlock; 158 + 159 + ret = walk_page_range_novma(&init_mm, lm_start, lm_end, 160 + &pageattr_ops, NULL, &masks); 161 + if (ret) 162 + goto unlock; 163 + } 164 + 279 165 ret = walk_page_range_novma(&init_mm, start, end, &pageattr_ops, NULL, 280 166 &masks); 167 + 168 + unlock: 169 + mmap_write_unlock(&init_mm); 170 + 171 + /* 172 + * We can't use flush_tlb_kernel_range() here as we may have split a 173 + * hugepage that is larger than that, so let's flush everything. 174 + */ 175 + flush_tlb_all(); 176 + #else 177 + ret = walk_page_range_novma(&init_mm, start, end, &pageattr_ops, NULL, 178 + &masks); 179 + 281 180 mmap_write_unlock(&init_mm); 282 181 283 182 flush_tlb_kernel_range(start, end); 183 + #endif 284 184 285 185 return ret; 286 186 } ··· 371 159 372 160 int set_direct_map_invalid_noflush(struct page *page) 373 161 { 374 - int ret; 375 - unsigned long start = (unsigned long)page_address(page); 376 - unsigned long end = start + PAGE_SIZE; 377 - struct pageattr_masks masks = { 378 - .set_mask = __pgprot(0), 379 - .clear_mask = __pgprot(_PAGE_PRESENT) 380 - }; 381 - 382 - mmap_read_lock(&init_mm); 383 - ret = walk_page_range(&init_mm, start, end, &pageattr_ops, &masks); 384 - mmap_read_unlock(&init_mm); 385 - 386 - return ret; 162 + return __set_memory((unsigned long)page_address(page), 1, 163 + __pgprot(0), __pgprot(_PAGE_PRESENT)); 387 164 } 388 165 389 166 int set_direct_map_default_noflush(struct page *page) 390 167 { 391 - int ret; 392 - unsigned long start = (unsigned long)page_address(page); 393 - unsigned long end = start + PAGE_SIZE; 394 - struct pageattr_masks masks = { 395 - .set_mask = PAGE_KERNEL, 396 - .clear_mask = __pgprot(0) 397 - }; 398 - 399 - mmap_read_lock(&init_mm); 400 - ret = walk_page_range(&init_mm, start, end, &pageattr_ops, &masks); 401 - mmap_read_unlock(&init_mm); 402 - 403 - return ret; 168 + return __set_memory((unsigned long)page_address(page), 1, 169 + PAGE_KERNEL, __pgprot(0)); 404 170 } 405 171 406 172 #ifdef CONFIG_DEBUG_PAGEALLOC
+2 -2
arch/riscv/mm/pmem.c
··· 17 17 return; 18 18 } 19 19 #endif 20 - ALT_CMO_OP(clean, addr, size, riscv_cbom_block_size); 20 + ALT_CMO_OP(CLEAN, addr, size, riscv_cbom_block_size); 21 21 } 22 22 EXPORT_SYMBOL_GPL(arch_wb_cache_pmem); 23 23 ··· 29 29 return; 30 30 } 31 31 #endif 32 - ALT_CMO_OP(inval, addr, size, riscv_cbom_block_size); 32 + ALT_CMO_OP(INVAL, addr, size, riscv_cbom_block_size); 33 33 } 34 34 EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
+34 -19
arch/riscv/mm/ptdump.c
··· 129 129 /* Page Table Entry */ 130 130 struct prot_bits { 131 131 u64 mask; 132 - u64 val; 133 132 const char *set; 134 133 const char *clear; 135 134 }; 136 135 137 136 static const struct prot_bits pte_bits[] = { 138 137 { 138 + #ifdef CONFIG_64BIT 139 + .mask = _PAGE_NAPOT, 140 + .set = "N", 141 + .clear = ".", 142 + }, { 143 + .mask = _PAGE_MTMASK_SVPBMT, 144 + .set = "MT(%s)", 145 + .clear = " .. ", 146 + }, { 147 + #endif 139 148 .mask = _PAGE_SOFT, 140 - .val = _PAGE_SOFT, 141 - .set = "RSW", 142 - .clear = " ", 149 + .set = "RSW(%d)", 150 + .clear = " .. ", 143 151 }, { 144 152 .mask = _PAGE_DIRTY, 145 - .val = _PAGE_DIRTY, 146 153 .set = "D", 147 154 .clear = ".", 148 155 }, { 149 156 .mask = _PAGE_ACCESSED, 150 - .val = _PAGE_ACCESSED, 151 157 .set = "A", 152 158 .clear = ".", 153 159 }, { 154 160 .mask = _PAGE_GLOBAL, 155 - .val = _PAGE_GLOBAL, 156 161 .set = "G", 157 162 .clear = ".", 158 163 }, { 159 164 .mask = _PAGE_USER, 160 - .val = _PAGE_USER, 161 165 .set = "U", 162 166 .clear = ".", 163 167 }, { 164 168 .mask = _PAGE_EXEC, 165 - .val = _PAGE_EXEC, 166 169 .set = "X", 167 170 .clear = ".", 168 171 }, { 169 172 .mask = _PAGE_WRITE, 170 - .val = _PAGE_WRITE, 171 173 .set = "W", 172 174 .clear = ".", 173 175 }, { 174 176 .mask = _PAGE_READ, 175 - .val = _PAGE_READ, 176 177 .set = "R", 177 178 .clear = ".", 178 179 }, { 179 180 .mask = _PAGE_PRESENT, 180 - .val = _PAGE_PRESENT, 181 181 .set = "V", 182 182 .clear = ".", 183 183 } ··· 208 208 unsigned int i; 209 209 210 210 for (i = 0; i < ARRAY_SIZE(pte_bits); i++) { 211 - const char *s; 211 + char s[7]; 212 + unsigned long val; 212 213 213 - if ((st->current_prot & pte_bits[i].mask) == pte_bits[i].val) 214 - s = pte_bits[i].set; 215 - else 216 - s = pte_bits[i].clear; 214 + val = st->current_prot & pte_bits[i].mask; 215 + if (val) { 216 + if (pte_bits[i].mask == _PAGE_SOFT) 217 + sprintf(s, pte_bits[i].set, val >> 8); 218 + #ifdef CONFIG_64BIT 219 + else if (pte_bits[i].mask == _PAGE_MTMASK_SVPBMT) { 220 + if (val == _PAGE_NOCACHE_SVPBMT) 221 + sprintf(s, pte_bits[i].set, "NC"); 222 + else if (val == _PAGE_IO_SVPBMT) 223 + sprintf(s, pte_bits[i].set, "IO"); 224 + else 225 + sprintf(s, pte_bits[i].set, "??"); 226 + } 227 + #endif 228 + else 229 + sprintf(s, "%s", pte_bits[i].set); 230 + } else { 231 + sprintf(s, "%s", pte_bits[i].clear); 232 + } 217 233 218 - if (s) 219 - pt_dump_seq_printf(st->seq, " %s", s); 234 + pt_dump_seq_printf(st->seq, " %s", s); 220 235 } 221 236 } 222 237
+115 -64
arch/riscv/mm/tlbflush.c
··· 3 3 #include <linux/mm.h> 4 4 #include <linux/smp.h> 5 5 #include <linux/sched.h> 6 + #include <linux/hugetlb.h> 6 7 #include <asm/sbi.h> 7 8 #include <asm/mmu_context.h> 8 9 9 10 static inline void local_flush_tlb_all_asid(unsigned long asid) 10 11 { 11 - __asm__ __volatile__ ("sfence.vma x0, %0" 12 - : 13 - : "r" (asid) 14 - : "memory"); 12 + if (asid != FLUSH_TLB_NO_ASID) 13 + __asm__ __volatile__ ("sfence.vma x0, %0" 14 + : 15 + : "r" (asid) 16 + : "memory"); 17 + else 18 + local_flush_tlb_all(); 15 19 } 16 20 17 21 static inline void local_flush_tlb_page_asid(unsigned long addr, 18 22 unsigned long asid) 19 23 { 20 - __asm__ __volatile__ ("sfence.vma %0, %1" 21 - : 22 - : "r" (addr), "r" (asid) 23 - : "memory"); 24 + if (asid != FLUSH_TLB_NO_ASID) 25 + __asm__ __volatile__ ("sfence.vma %0, %1" 26 + : 27 + : "r" (addr), "r" (asid) 28 + : "memory"); 29 + else 30 + local_flush_tlb_page(addr); 24 31 } 25 32 26 - static inline void local_flush_tlb_range(unsigned long start, 27 - unsigned long size, unsigned long stride) 33 + /* 34 + * Flush entire TLB if number of entries to be flushed is greater 35 + * than the threshold below. 36 + */ 37 + static unsigned long tlb_flush_all_threshold __read_mostly = 64; 38 + 39 + static void local_flush_tlb_range_threshold_asid(unsigned long start, 40 + unsigned long size, 41 + unsigned long stride, 42 + unsigned long asid) 28 43 { 29 - if (size <= stride) 30 - local_flush_tlb_page(start); 31 - else 32 - local_flush_tlb_all(); 44 + unsigned long nr_ptes_in_range = DIV_ROUND_UP(size, stride); 45 + int i; 46 + 47 + if (nr_ptes_in_range > tlb_flush_all_threshold) { 48 + local_flush_tlb_all_asid(asid); 49 + return; 50 + } 51 + 52 + for (i = 0; i < nr_ptes_in_range; ++i) { 53 + local_flush_tlb_page_asid(start, asid); 54 + start += stride; 55 + } 33 56 } 34 57 35 58 static inline void local_flush_tlb_range_asid(unsigned long start, ··· 60 37 { 61 38 if (size <= stride) 62 39 local_flush_tlb_page_asid(start, asid); 63 - else 40 + else if (size == FLUSH_TLB_MAX_SIZE) 64 41 local_flush_tlb_all_asid(asid); 42 + else 43 + local_flush_tlb_range_threshold_asid(start, size, stride, asid); 65 44 } 66 45 67 46 static void __ipi_flush_tlb_all(void *info) ··· 76 51 if (riscv_use_ipi_for_rfence()) 77 52 on_each_cpu(__ipi_flush_tlb_all, NULL, 1); 78 53 else 79 - sbi_remote_sfence_vma(NULL, 0, -1); 54 + sbi_remote_sfence_vma_asid(NULL, 0, FLUSH_TLB_MAX_SIZE, FLUSH_TLB_NO_ASID); 80 55 } 81 56 82 57 struct flush_tlb_range_data { ··· 93 68 local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid); 94 69 } 95 70 96 - static void __ipi_flush_tlb_range(void *info) 97 - { 98 - struct flush_tlb_range_data *d = info; 99 - 100 - local_flush_tlb_range(d->start, d->size, d->stride); 101 - } 102 - 103 71 static void __flush_tlb_range(struct mm_struct *mm, unsigned long start, 104 72 unsigned long size, unsigned long stride) 105 73 { 106 74 struct flush_tlb_range_data ftd; 107 - struct cpumask *cmask = mm_cpumask(mm); 108 - unsigned int cpuid; 75 + const struct cpumask *cmask; 76 + unsigned long asid = FLUSH_TLB_NO_ASID; 109 77 bool broadcast; 110 78 111 - if (cpumask_empty(cmask)) 112 - return; 79 + if (mm) { 80 + unsigned int cpuid; 113 81 114 - cpuid = get_cpu(); 115 - /* check if the tlbflush needs to be sent to other CPUs */ 116 - broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids; 117 - if (static_branch_unlikely(&use_asid_allocator)) { 118 - unsigned long asid = atomic_long_read(&mm->context.id) & asid_mask; 82 + cmask = mm_cpumask(mm); 83 + if (cpumask_empty(cmask)) 84 + return; 119 85 120 - if (broadcast) { 121 - if (riscv_use_ipi_for_rfence()) { 122 - ftd.asid = asid; 123 - ftd.start = start; 124 - ftd.size = size; 125 - ftd.stride = stride; 126 - on_each_cpu_mask(cmask, 127 - __ipi_flush_tlb_range_asid, 128 - &ftd, 1); 129 - } else 130 - sbi_remote_sfence_vma_asid(cmask, 131 - start, size, asid); 132 - } else { 133 - local_flush_tlb_range_asid(start, size, stride, asid); 134 - } 86 + cpuid = get_cpu(); 87 + /* check if the tlbflush needs to be sent to other CPUs */ 88 + broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids; 89 + 90 + if (static_branch_unlikely(&use_asid_allocator)) 91 + asid = atomic_long_read(&mm->context.id) & asid_mask; 135 92 } else { 136 - if (broadcast) { 137 - if (riscv_use_ipi_for_rfence()) { 138 - ftd.asid = 0; 139 - ftd.start = start; 140 - ftd.size = size; 141 - ftd.stride = stride; 142 - on_each_cpu_mask(cmask, 143 - __ipi_flush_tlb_range, 144 - &ftd, 1); 145 - } else 146 - sbi_remote_sfence_vma(cmask, start, size); 147 - } else { 148 - local_flush_tlb_range(start, size, stride); 149 - } 93 + cmask = cpu_online_mask; 94 + broadcast = true; 150 95 } 151 96 152 - put_cpu(); 97 + if (broadcast) { 98 + if (riscv_use_ipi_for_rfence()) { 99 + ftd.asid = asid; 100 + ftd.start = start; 101 + ftd.size = size; 102 + ftd.stride = stride; 103 + on_each_cpu_mask(cmask, 104 + __ipi_flush_tlb_range_asid, 105 + &ftd, 1); 106 + } else 107 + sbi_remote_sfence_vma_asid(cmask, 108 + start, size, asid); 109 + } else { 110 + local_flush_tlb_range_asid(start, size, stride, asid); 111 + } 112 + 113 + if (mm) 114 + put_cpu(); 153 115 } 154 116 155 117 void flush_tlb_mm(struct mm_struct *mm) 156 118 { 157 - __flush_tlb_range(mm, 0, -1, PAGE_SIZE); 119 + __flush_tlb_range(mm, 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE); 120 + } 121 + 122 + void flush_tlb_mm_range(struct mm_struct *mm, 123 + unsigned long start, unsigned long end, 124 + unsigned int page_size) 125 + { 126 + __flush_tlb_range(mm, start, end - start, page_size); 158 127 } 159 128 160 129 void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) ··· 159 140 void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 160 141 unsigned long end) 161 142 { 162 - __flush_tlb_range(vma->vm_mm, start, end - start, PAGE_SIZE); 143 + unsigned long stride_size; 144 + 145 + if (!is_vm_hugetlb_page(vma)) { 146 + stride_size = PAGE_SIZE; 147 + } else { 148 + stride_size = huge_page_size(hstate_vma(vma)); 149 + 150 + /* 151 + * As stated in the privileged specification, every PTE in a 152 + * NAPOT region must be invalidated, so reset the stride in that 153 + * case. 154 + */ 155 + if (has_svnapot()) { 156 + if (stride_size >= PGDIR_SIZE) 157 + stride_size = PGDIR_SIZE; 158 + else if (stride_size >= P4D_SIZE) 159 + stride_size = P4D_SIZE; 160 + else if (stride_size >= PUD_SIZE) 161 + stride_size = PUD_SIZE; 162 + else if (stride_size >= PMD_SIZE) 163 + stride_size = PMD_SIZE; 164 + else 165 + stride_size = PAGE_SIZE; 166 + } 167 + } 168 + 169 + __flush_tlb_range(vma->vm_mm, start, end - start, stride_size); 163 170 } 171 + 172 + void flush_tlb_kernel_range(unsigned long start, unsigned long end) 173 + { 174 + __flush_tlb_range(NULL, start, end - start, PAGE_SIZE); 175 + } 176 + 164 177 #ifdef CONFIG_TRANSPARENT_HUGEPAGE 165 178 void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, 166 179 unsigned long end)
+4 -12
arch/riscv/purgatory/entry.S
··· 7 7 * Author: Li Zhengyu (lizhengyu3@huawei.com) 8 8 * 9 9 */ 10 - 11 - .macro size, sym:req 12 - .size \sym, . - \sym 13 - .endm 10 + #include <linux/linkage.h> 14 11 15 12 .text 16 13 17 - .globl purgatory_start 18 - purgatory_start: 14 + SYM_CODE_START(purgatory_start) 19 15 20 16 lla sp, .Lstack 21 17 mv s0, a0 /* The hartid of the current hart */ ··· 24 28 mv a1, s1 25 29 ld a2, riscv_kernel_entry 26 30 jr a2 27 - 28 - size purgatory_start 31 + SYM_CODE_END(purgatory_start) 29 32 30 33 .align 4 31 34 .rept 256 ··· 34 39 35 40 .data 36 41 37 - .globl riscv_kernel_entry 38 - riscv_kernel_entry: 39 - .quad 0 40 - size riscv_kernel_entry 42 + SYM_DATA(riscv_kernel_entry, .quad 0) 41 43 42 44 .end
+1 -1
drivers/clocksource/timer-riscv.c
··· 25 25 #include <linux/limits.h> 26 26 #include <clocksource/timer-riscv.h> 27 27 #include <asm/smp.h> 28 - #include <asm/hwcap.h> 28 + #include <asm/cpufeature.h> 29 29 #include <asm/sbi.h> 30 30 #include <asm/timex.h> 31 31
+1 -1
drivers/firmware/efi/libstub/Makefile
··· 28 28 -DEFI_HAVE_MEMCHR -DEFI_HAVE_STRRCHR \ 29 29 -DEFI_HAVE_STRCMP -fno-builtin -fpic \ 30 30 $(call cc-option,-mno-single-pic-base) 31 - cflags-$(CONFIG_RISCV) += -fpic 31 + cflags-$(CONFIG_RISCV) += -fpic -DNO_ALTERNATIVE 32 32 cflags-$(CONFIG_LOONGARCH) += -fpie 33 33 34 34 cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt
+2
drivers/of/property.c
··· 1267 1267 DEFINE_SIMPLE_PROP(leds, "leds", NULL) 1268 1268 DEFINE_SIMPLE_PROP(backlight, "backlight", NULL) 1269 1269 DEFINE_SIMPLE_PROP(panel, "panel", NULL) 1270 + DEFINE_SIMPLE_PROP(msi_parent, "msi-parent", "#msi-cells") 1270 1271 DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) 1271 1272 DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") 1272 1273 ··· 1357 1356 { .parse_prop = parse_leds, }, 1358 1357 { .parse_prop = parse_backlight, }, 1359 1358 { .parse_prop = parse_panel, }, 1359 + { .parse_prop = parse_msi_parent, }, 1360 1360 { .parse_prop = parse_gpio_compat, }, 1361 1361 { .parse_prop = parse_interrupts, }, 1362 1362 { .parse_prop = parse_regulators, },
+8 -5
drivers/perf/riscv_pmu_sbi.c
··· 22 22 23 23 #include <asm/errata_list.h> 24 24 #include <asm/sbi.h> 25 - #include <asm/hwcap.h> 25 + #include <asm/cpufeature.h> 26 26 27 27 #define SYSCTL_NO_USER_ACCESS 0 28 28 #define SYSCTL_USER_ACCESS 1 ··· 543 543 544 544 if ((hwc->flags & PERF_EVENT_FLAG_USER_ACCESS) && 545 545 (hwc->flags & PERF_EVENT_FLAG_USER_READ_CNT)) 546 - on_each_cpu_mask(mm_cpumask(event->owner->mm), 547 - pmu_sbi_set_scounteren, (void *)event, 1); 546 + pmu_sbi_set_scounteren((void *)event); 548 547 } 549 548 550 549 static void pmu_sbi_ctr_stop(struct perf_event *event, unsigned long flag) ··· 553 554 554 555 if ((hwc->flags & PERF_EVENT_FLAG_USER_ACCESS) && 555 556 (hwc->flags & PERF_EVENT_FLAG_USER_READ_CNT)) 556 - on_each_cpu_mask(mm_cpumask(event->owner->mm), 557 - pmu_sbi_reset_scounteren, (void *)event, 1); 557 + pmu_sbi_reset_scounteren((void *)event); 558 558 559 559 ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, hwc->idx, 1, flag, 0, 0, 0); 560 560 if (ret.error && (ret.error != SBI_ERR_ALREADY_STOPPED) && ··· 687 689 688 690 /* Firmware counter don't support overflow yet */ 689 691 fidx = find_first_bit(cpu_hw_evt->used_hw_ctrs, RISCV_MAX_COUNTERS); 692 + if (fidx == RISCV_MAX_COUNTERS) { 693 + csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num)); 694 + return IRQ_NONE; 695 + } 696 + 690 697 event = cpu_hw_evt->events[fidx]; 691 698 if (!event) { 692 699 csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num));