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

RISC-V: mm: Restrict address space for sv39,sv48,sv57

Make sv48 the default address space for mmap as some applications
currently depend on this assumption. A hint address passed to mmap will
cause the largest address space that fits entirely into the hint to be
used. If the hint is less than or equal to 1<<38, an sv39 address will
be used. An exception is that if the hint address is 0, then a sv48
address will be used. After an address space is completely full, the next
smallest address space will be used.

Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
Link: https://lore.kernel.org/r/20230809232218.849726-2-charlie@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>

authored by

Charlie Jenkins and committed by
Palmer Dabbelt
add2cc6b 06c2afb8

+70 -9
+1 -1
arch/riscv/include/asm/elf.h
··· 49 49 * the loader. We need to make sure that it is out of the way of the program 50 50 * that it will "exec", and that there is sufficient room for the brk. 51 51 */ 52 - #define ELF_ET_DYN_BASE ((TASK_SIZE / 3) * 2) 52 + #define ELF_ET_DYN_BASE ((DEFAULT_MAP_WINDOW / 3) * 2) 53 53 54 54 #ifdef CONFIG_64BIT 55 55 #ifdef CONFIG_COMPAT
+23 -2
arch/riscv/include/asm/pgtable.h
··· 62 62 * struct pages to map half the virtual address space. Then 63 63 * position vmemmap directly below the VMALLOC region. 64 64 */ 65 + #define VA_BITS_SV32 32 65 66 #ifdef CONFIG_64BIT 67 + #define VA_BITS_SV39 39 68 + #define VA_BITS_SV48 48 69 + #define VA_BITS_SV57 57 70 + 66 71 #define VA_BITS (pgtable_l5_enabled ? \ 67 - 57 : (pgtable_l4_enabled ? 48 : 39)) 72 + VA_BITS_SV57 : (pgtable_l4_enabled ? VA_BITS_SV48 : VA_BITS_SV39)) 68 73 #else 69 - #define VA_BITS 32 74 + #define VA_BITS VA_BITS_SV32 70 75 #endif 71 76 72 77 #define VMEMMAP_SHIFT \ ··· 116 111 #include <asm/page.h> 117 112 #include <asm/tlbflush.h> 118 113 #include <linux/mm_types.h> 114 + #include <asm/compat.h> 119 115 120 116 #define __page_val_to_pfn(_val) (((_val) & _PAGE_PFN_MASK) >> _PAGE_PFN_SHIFT) 121 117 122 118 #ifdef CONFIG_64BIT 123 119 #include <asm/pgtable-64.h> 120 + 121 + #define VA_USER_SV39 (UL(1) << (VA_BITS_SV39 - 1)) 122 + #define VA_USER_SV48 (UL(1) << (VA_BITS_SV48 - 1)) 123 + #define VA_USER_SV57 (UL(1) << (VA_BITS_SV57 - 1)) 124 + 125 + #ifdef CONFIG_COMPAT 126 + #define MMAP_VA_BITS_64 ((VA_BITS >= VA_BITS_SV48) ? VA_BITS_SV48 : VA_BITS) 127 + #define MMAP_MIN_VA_BITS_64 (VA_BITS_SV39) 128 + #define MMAP_VA_BITS (is_compat_task() ? VA_BITS_SV32 : MMAP_VA_BITS_64) 129 + #define MMAP_MIN_VA_BITS (is_compat_task() ? VA_BITS_SV32 : MMAP_MIN_VA_BITS_64) 130 + #else 131 + #define MMAP_VA_BITS ((VA_BITS >= VA_BITS_SV48) ? VA_BITS_SV48 : VA_BITS) 132 + #define MMAP_MIN_VA_BITS (VA_BITS_SV39) 133 + #endif /* CONFIG_COMPAT */ 134 + 124 135 #else 125 136 #include <asm/pgtable-32.h> 126 137 #endif /* CONFIG_64BIT */
+46 -6
arch/riscv/include/asm/processor.h
··· 13 13 14 14 #include <asm/ptrace.h> 15 15 16 + #ifdef CONFIG_64BIT 17 + #define DEFAULT_MAP_WINDOW (UL(1) << (MMAP_VA_BITS - 1)) 18 + #define STACK_TOP_MAX TASK_SIZE_64 19 + 20 + #define arch_get_mmap_end(addr, len, flags) \ 21 + ({ \ 22 + unsigned long mmap_end; \ 23 + typeof(addr) _addr = (addr); \ 24 + if ((_addr) == 0 || (IS_ENABLED(CONFIG_COMPAT) && is_compat_task())) \ 25 + mmap_end = STACK_TOP_MAX; \ 26 + else if ((_addr) >= VA_USER_SV57) \ 27 + mmap_end = STACK_TOP_MAX; \ 28 + else if ((((_addr) >= VA_USER_SV48)) && (VA_BITS >= VA_BITS_SV48)) \ 29 + mmap_end = VA_USER_SV48; \ 30 + else \ 31 + mmap_end = VA_USER_SV39; \ 32 + mmap_end; \ 33 + }) 34 + 35 + #define arch_get_mmap_base(addr, base) \ 36 + ({ \ 37 + unsigned long mmap_base; \ 38 + typeof(addr) _addr = (addr); \ 39 + typeof(base) _base = (base); \ 40 + unsigned long rnd_gap = DEFAULT_MAP_WINDOW - (_base); \ 41 + if ((_addr) == 0 || (IS_ENABLED(CONFIG_COMPAT) && is_compat_task())) \ 42 + mmap_base = (_base); \ 43 + else if (((_addr) >= VA_USER_SV57) && (VA_BITS >= VA_BITS_SV57)) \ 44 + mmap_base = VA_USER_SV57 - rnd_gap; \ 45 + else if ((((_addr) >= VA_USER_SV48)) && (VA_BITS >= VA_BITS_SV48)) \ 46 + mmap_base = VA_USER_SV48 - rnd_gap; \ 47 + else \ 48 + mmap_base = VA_USER_SV39 - rnd_gap; \ 49 + mmap_base; \ 50 + }) 51 + 52 + #else 53 + #define DEFAULT_MAP_WINDOW TASK_SIZE 54 + #define STACK_TOP_MAX TASK_SIZE 55 + #endif 56 + #define STACK_ALIGN 16 57 + 58 + #define STACK_TOP DEFAULT_MAP_WINDOW 59 + 16 60 /* 17 61 * This decides where the kernel will search for a free chunk of vm 18 62 * space during mmap's. 19 63 */ 20 - #define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3) 21 - 22 - #define STACK_TOP TASK_SIZE 23 64 #ifdef CONFIG_64BIT 24 - #define STACK_TOP_MAX TASK_SIZE_64 65 + #define TASK_UNMAPPED_BASE PAGE_ALIGN((UL(1) << MMAP_MIN_VA_BITS) / 3) 25 66 #else 26 - #define STACK_TOP_MAX TASK_SIZE 67 + #define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3) 27 68 #endif 28 - #define STACK_ALIGN 16 29 69 30 70 #ifndef __ASSEMBLY__ 31 71