RISC-V Fixes for 5.8-rc2

This contains three fixes that I'd like to target for rc2:
 
 * 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.
 -----BEGIN PGP SIGNATURE-----
 
 iQJHBAABCgAxFiEEKzw3R0RoQ7JKlDp6LhMZ81+7GIkFAl7tRxkTHHBhbG1lckBk
 YWJiZWx0LmNvbQAKCRAuExnzX7sYiaJZD/9hzS6fxNlcLaLyBLLroWLlWnwGAi7r
 T3hTyNVo3EG/hHw0NGEWzqVuqjnuo0MAHDlTfkD7SuuBtj2PtZHVdX5JA9QsJF1j
 KF3hz14GbbGuzOWlt6m+6KMU4r9+qX+0L3aqu0ShXVZhsHjKyuYTSHlwIRLzCzlQ
 jcCVnrIQtq0pAcGylmL5s/9kVFGrpE6m1+Xm+mpPbgQCbqFMYCBVx8sb2EnEPv/X
 TzgCzS8sjRG0FYIrquwxuHtKg+AlgmmaQw96fWOq9R4mJtNvcDFbaTT5MEqQYP6B
 kljNf3DAdKG0QqKCtNC5BvgE+45BpQ67ZIUypG00Y0zViY2ZOjNGqGi7kzzIqOWG
 IwwB6Gcb6CJnOWRJ2OlkDDdOe1VOvrE/ap+WEYE8Fb/TRQhdOjcHMzd9d/0JXe9R
 XySr5gtpppKABJjBWmzGfqLRXby7qQFXR4BqnpPGuqR1Z0l5MaihN2mlpOZrDbMS
 Y0j1vQuINBkoBqXBfqxCZb5gvwxHI+5lwFNy8chw8JZTOuvLYJ0s5bK8AF9fAGk8
 7NCv+JCt2mrjMLRoZw7EFu4wqBTjjDXKP5AiiKHOCG9y4lokqLdATWirlWwScTt0
 TvikaMYsDdiuhRpg0D0YCKGzQ9Cl23XvGe9fm6Ajhhkn6lONJD0/V/1i0MfY0+Nm
 7TI46cNfvsUsWw==
 =ZAlD
 -----END PGP SIGNATURE-----

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

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
This commit is contained in:
Linus Torvalds 2020-06-20 12:14:29 -07:00
commit 7fdfbe08a2
3 changed files with 22 additions and 6 deletions

View file

@ -179,7 +179,7 @@
" bnez %1, 0b\n" \ " bnez %1, 0b\n" \
"1:\n" \ "1:\n" \
: "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
: "rJ" (__old), "rJ" (__new) \ : "rJ" ((long)__old), "rJ" (__new) \
: "memory"); \ : "memory"); \
break; \ break; \
case 8: \ case 8: \
@ -224,7 +224,7 @@
RISCV_ACQUIRE_BARRIER \ RISCV_ACQUIRE_BARRIER \
"1:\n" \ "1:\n" \
: "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
: "rJ" (__old), "rJ" (__new) \ : "rJ" ((long)__old), "rJ" (__new) \
: "memory"); \ : "memory"); \
break; \ break; \
case 8: \ case 8: \
@ -270,7 +270,7 @@
" bnez %1, 0b\n" \ " bnez %1, 0b\n" \
"1:\n" \ "1:\n" \
: "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
: "rJ" (__old), "rJ" (__new) \ : "rJ" ((long)__old), "rJ" (__new) \
: "memory"); \ : "memory"); \
break; \ break; \
case 8: \ case 8: \
@ -316,7 +316,7 @@
" fence rw, rw\n" \ " fence rw, rw\n" \
"1:\n" \ "1:\n" \
: "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \ : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
: "rJ" (__old), "rJ" (__new) \ : "rJ" ((long)__old), "rJ" (__new) \
: "memory"); \ : "memory"); \
break; \ break; \
case 8: \ case 8: \

View file

@ -8,6 +8,7 @@
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm-generic/mman-common.h>
static long riscv_sys_mmap(unsigned long addr, unsigned long len, static long riscv_sys_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long prot, unsigned long flags,
@ -16,6 +17,11 @@ static long riscv_sys_mmap(unsigned long addr, unsigned long len,
{ {
if (unlikely(offset & (~PAGE_MASK >> page_shift_offset))) if (unlikely(offset & (~PAGE_MASK >> page_shift_offset)))
return -EINVAL; return -EINVAL;
if ((prot & PROT_WRITE) && (prot & PROT_EXEC))
if (unlikely(!(prot & PROT_READ)))
return -EINVAL;
return ksys_mmap_pgoff(addr, len, prot, flags, fd, return ksys_mmap_pgoff(addr, len, prot, flags, fd,
offset >> (PAGE_SHIFT - page_shift_offset)); offset >> (PAGE_SHIFT - page_shift_offset));
} }

View file

@ -151,6 +151,7 @@ int set_memory_nx(unsigned long addr, int numpages)
int set_direct_map_invalid_noflush(struct page *page) int set_direct_map_invalid_noflush(struct page *page)
{ {
int ret;
unsigned long start = (unsigned long)page_address(page); unsigned long start = (unsigned long)page_address(page);
unsigned long end = start + PAGE_SIZE; unsigned long end = start + PAGE_SIZE;
struct pageattr_masks masks = { struct pageattr_masks masks = {
@ -158,11 +159,16 @@ int set_direct_map_invalid_noflush(struct page *page)
.clear_mask = __pgprot(_PAGE_PRESENT) .clear_mask = __pgprot(_PAGE_PRESENT)
}; };
return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks); mmap_read_lock(&init_mm);
ret = walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
mmap_read_unlock(&init_mm);
return ret;
} }
int set_direct_map_default_noflush(struct page *page) int set_direct_map_default_noflush(struct page *page)
{ {
int ret;
unsigned long start = (unsigned long)page_address(page); unsigned long start = (unsigned long)page_address(page);
unsigned long end = start + PAGE_SIZE; unsigned long end = start + PAGE_SIZE;
struct pageattr_masks masks = { struct pageattr_masks masks = {
@ -170,7 +176,11 @@ int set_direct_map_default_noflush(struct page *page)
.clear_mask = __pgprot(0) .clear_mask = __pgprot(0)
}; };
return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks); mmap_read_lock(&init_mm);
ret = walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
mmap_read_unlock(&init_mm);
return ret;
} }
void __kernel_map_pages(struct page *page, int numpages, int enable) void __kernel_map_pages(struct page *page, int numpages, int enable)