Pull RISC-V fixes from Palmer Dabbelt: - a workaround for a compiler surprise related to the "r" inline assembly that allows LLVM to boot. - a fix to avoid WX-only mappings, which the ISA does not allow. While this probably manifests in many ways, the bug was found in stress-ng. - a missing lock in set_direct_map_*(), which due to a recent lockdep change started asserting. * tag 'riscv-for-linus-5.8-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: RISC-V: Acquire mmap lock before invoking walk_page_range RISC-V: Don't allow write+exec only page mapping request in mmap riscv/atomic: Fix sign extension for RV64I
Unified · Split
| @@ -179,7 +179,7 @@ · 178 unmodified lines | |||
| 179 | " bnez %1, 0b\n" \ | 179 | " bnez %1, 0b\n" \ |
| 180 | "1:\n" \ | 180 | "1:\n" \ |
| 181 | : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ | 181 | : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ |
| 182 | : "rJ" (__old), "rJ" (__new) \ | 182 | : "rJ" ((long)__old), "rJ" (__new) \ |
| 183 | : "memory"); \ | 183 | : "memory"); \ |
| 184 | break; \ | 184 | break; \ |
| 185 | case 8: \ | 185 | case 8: \ |
| @@ -224,7 +224,7 @@ · 38 unmodified lines | |||
| 224 | RISCV_ACQUIRE_BARRIER \ | 224 | RISCV_ACQUIRE_BARRIER \ |
| 225 | "1:\n" \ | 225 | "1:\n" \ |
| 226 | : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ | 226 | : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ |
| 227 | : "rJ" (__old), "rJ" (__new) \ | 227 | : "rJ" ((long)__old), "rJ" (__new) \ |
| 228 | : "memory"); \ | 228 | : "memory"); \ |
| 229 | break; \ | 229 | break; \ |
| 230 | case 8: \ | 230 | case 8: \ |
| @@ -270,7 +270,7 @@ · 39 unmodified lines | |||
| 270 | " bnez %1, 0b\n" \ | 270 | " bnez %1, 0b\n" \ |
| 271 | "1:\n" \ | 271 | "1:\n" \ |
| 272 | : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ | 272 | : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ |
| 273 | : "rJ" (__old), "rJ" (__new) \ | 273 | : "rJ" ((long)__old), "rJ" (__new) \ |
| 274 | : "memory"); \ | 274 | : "memory"); \ |
| 275 | break; \ | 275 | break; \ |
| 276 | case 8: \ | 276 | case 8: \ |
| @@ -316,7 +316,7 @@ · 39 unmodified lines | |||
| 316 | " fence rw, rw\n" \ | 316 | " fence rw, rw\n" \ |
| 317 | "1:\n" \ | 317 | "1:\n" \ |
| 318 | : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ | 318 | : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ |
| 319 | : "rJ" (__old), "rJ" (__new) \ | 319 | : "rJ" ((long)__old), "rJ" (__new) \ |
| 320 | : "memory"); \ | 320 | : "memory"); \ |
| 321 | break; \ | 321 | break; \ |
| 322 | case 8: \ | 322 | case 8: \ |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | #include <linux/syscalls.h> | 8 | #include <linux/syscalls.h> |
| 9 | #include <asm/unistd.h> | 9 | #include <asm/unistd.h> |
| 10 | #include <asm/cacheflush.h> | 10 | #include <asm/cacheflush.h> |
| 11 | #include <asm-generic/mman-common.h> | ||
| 11 | 12 | ||
| 12 | static long riscv_sys_mmap(unsigned long addr, unsigned long len, | 13 | static long riscv_sys_mmap(unsigned long addr, unsigned long len, |
| 13 | unsigned long prot, unsigned long flags, | 14 | unsigned long prot, unsigned long flags, |
| @@ -16,6 +17,11 @@ static long riscv_sys_mmap(unsigned long addr, unsigned long len, · 2 unmodified lines | |||
| 16 | { | 17 | { |
| 17 | if (unlikely(offset & (~PAGE_MASK >> page_shift_offset))) | 18 | if (unlikely(offset & (~PAGE_MASK >> page_shift_offset))) |
| 18 | return -EINVAL; | 19 | return -EINVAL; |
| 20 | |||
| 21 | if ((prot & PROT_WRITE) && (prot & PROT_EXEC)) | ||
| 22 | if (unlikely(!(prot & PROT_READ))) | ||
| 23 | return -EINVAL; | ||
| 24 | |||
| 19 | return ksys_mmap_pgoff(addr, len, prot, flags, fd, | 25 | return ksys_mmap_pgoff(addr, len, prot, flags, fd, |
| 20 | offset >> (PAGE_SHIFT - page_shift_offset)); | 26 | offset >> (PAGE_SHIFT - page_shift_offset)); |
| 21 | } | 27 | } |
| @@ -151,6 +151,7 @@ int set_memory_nx(unsigned long addr, int numpages) · 150 unmodified lines | |||
| 151 | 151 | ||
| 152 | int set_direct_map_invalid_noflush(struct page *page) | 152 | int set_direct_map_invalid_noflush(struct page *page) |
| 153 | { | 153 | { |
| 154 | int ret; | ||
| 154 | unsigned long start = (unsigned long)page_address(page); | 155 | unsigned long start = (unsigned long)page_address(page); |
| 155 | unsigned long end = start + PAGE_SIZE; | 156 | unsigned long end = start + PAGE_SIZE; |
| 156 | struct pageattr_masks masks = { | 157 | struct pageattr_masks masks = { |
| @@ -158,11 +159,16 @@ int set_direct_map_invalid_noflush(struct page *page) · 1 unmodified line | |||
| 158 | .clear_mask = __pgprot(_PAGE_PRESENT) | 159 | .clear_mask = __pgprot(_PAGE_PRESENT) |
| 159 | }; | 160 | }; |
| 160 | 161 | ||
| 161 | return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks); | 162 | mmap_read_lock(&init_mm); |
| 163 | ret = walk_page_range(&init_mm, start, end, &pageattr_ops, &masks); | ||
| 164 | mmap_read_unlock(&init_mm); | ||
| 165 | |||
| 166 | return ret; | ||
| 162 | } | 167 | } |
| 163 | 168 | ||
| 164 | int set_direct_map_default_noflush(struct page *page) | 169 | int set_direct_map_default_noflush(struct page *page) |
| 165 | { | 170 | { |
| 171 | int ret; | ||
| 166 | unsigned long start = (unsigned long)page_address(page); | 172 | unsigned long start = (unsigned long)page_address(page); |
| 167 | unsigned long end = start + PAGE_SIZE; | 173 | unsigned long end = start + PAGE_SIZE; |
| 168 | struct pageattr_masks masks = { | 174 | struct pageattr_masks masks = { |
| @@ -170,7 +176,11 @@ int set_direct_map_default_noflush(struct page *page) · 1 unmodified line | |||
| 170 | .clear_mask = __pgprot(0) | 176 | .clear_mask = __pgprot(0) |
| 171 | }; | 177 | }; |
| 172 | 178 | ||
| 173 | return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks); | 179 | mmap_read_lock(&init_mm); |
| 180 | ret = walk_page_range(&init_mm, start, end, &pageattr_ops, &masks); | ||
| 181 | mmap_read_unlock(&init_mm); | ||
| 182 | |||
| 183 | return ret; | ||
| 174 | } | 184 | } |
| 175 | 185 | ||
| 176 | void __kernel_map_pages(struct page *page, int numpages, int enable) | 186 | void __kernel_map_pages(struct page *page, int numpages, int enable) |