diff options
| -rw-r--r-- | arch/s390/include/asm/pgtable.h | 21 | ||||
| -rw-r--r-- | arch/s390/kernel/module.c | 11 | ||||
| -rw-r--r-- | arch/s390/kernel/setup.c | 13 | ||||
| -rw-r--r-- | arch/s390/mm/dump_pagetables.c | 13 |
4 files changed, 46 insertions, 12 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 75b91bb772bd..dd647c919a66 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
| @@ -119,13 +119,12 @@ static inline int is_zero_pfn(unsigned long pfn) | |||
| 119 | 119 | ||
| 120 | #ifndef __ASSEMBLY__ | 120 | #ifndef __ASSEMBLY__ |
| 121 | /* | 121 | /* |
| 122 | * The vmalloc area will always be on the topmost area of the kernel | 122 | * The vmalloc and module area will always be on the topmost area of the kernel |
| 123 | * mapping. We reserve 96MB (31bit) / 128GB (64bit) for vmalloc, | 123 | * mapping. We reserve 96MB (31bit) / 128GB (64bit) for vmalloc and modules. |
| 124 | * which should be enough for any sane case. | 124 | * On 64 bit kernels we have a 2GB area at the top of the vmalloc area where |
| 125 | * By putting vmalloc at the top, we maximise the gap between physical | 125 | * modules will reside. That makes sure that inter module branches always |
| 126 | * memory and vmalloc to catch misplaced memory accesses. As a side | 126 | * happen without trampolines and in addition the placement within a 2GB frame |
| 127 | * effect, this also makes sure that 64 bit module code cannot be used | 127 | * is branch prediction unit friendly. |
| 128 | * as system call address. | ||
| 129 | */ | 128 | */ |
| 130 | extern unsigned long VMALLOC_START; | 129 | extern unsigned long VMALLOC_START; |
| 131 | extern unsigned long VMALLOC_END; | 130 | extern unsigned long VMALLOC_END; |
| @@ -133,6 +132,14 @@ extern struct page *vmemmap; | |||
| 133 | 132 | ||
| 134 | #define VMEM_MAX_PHYS ((unsigned long) vmemmap) | 133 | #define VMEM_MAX_PHYS ((unsigned long) vmemmap) |
| 135 | 134 | ||
| 135 | #ifdef CONFIG_64BIT | ||
| 136 | extern unsigned long MODULES_VADDR; | ||
| 137 | extern unsigned long MODULES_END; | ||
| 138 | #define MODULES_VADDR MODULES_VADDR | ||
| 139 | #define MODULES_END MODULES_END | ||
| 140 | #define MODULES_LEN (1UL << 31) | ||
| 141 | #endif | ||
| 142 | |||
| 136 | /* | 143 | /* |
| 137 | * A 31 bit pagetable entry of S390 has following format: | 144 | * A 31 bit pagetable entry of S390 has following format: |
| 138 | * | PFRA | | OS | | 145 | * | PFRA | | OS | |
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 46412b1d7e1e..4610deafd953 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c | |||
| @@ -44,6 +44,17 @@ | |||
| 44 | #define PLT_ENTRY_SIZE 20 | 44 | #define PLT_ENTRY_SIZE 20 |
| 45 | #endif /* CONFIG_64BIT */ | 45 | #endif /* CONFIG_64BIT */ |
| 46 | 46 | ||
| 47 | #ifdef CONFIG_64BIT | ||
| 48 | void *module_alloc(unsigned long size) | ||
| 49 | { | ||
| 50 | if (PAGE_ALIGN(size) > MODULES_LEN) | ||
| 51 | return NULL; | ||
| 52 | return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, | ||
| 53 | GFP_KERNEL, PAGE_KERNEL, -1, | ||
| 54 | __builtin_return_address(0)); | ||
| 55 | } | ||
| 56 | #endif | ||
| 57 | |||
| 47 | /* Free memory returned from module_alloc */ | 58 | /* Free memory returned from module_alloc */ |
| 48 | void module_free(struct module *mod, void *module_region) | 59 | void module_free(struct module *mod, void *module_region) |
| 49 | { | 60 | { |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index bfb48f18169c..b1f2be9aaaad 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
| @@ -105,6 +105,11 @@ EXPORT_SYMBOL(VMALLOC_END); | |||
| 105 | struct page *vmemmap; | 105 | struct page *vmemmap; |
| 106 | EXPORT_SYMBOL(vmemmap); | 106 | EXPORT_SYMBOL(vmemmap); |
| 107 | 107 | ||
| 108 | #ifdef CONFIG_64BIT | ||
| 109 | unsigned long MODULES_VADDR; | ||
| 110 | unsigned long MODULES_END; | ||
| 111 | #endif | ||
| 112 | |||
| 108 | /* An array with a pointer to the lowcore of every CPU. */ | 113 | /* An array with a pointer to the lowcore of every CPU. */ |
| 109 | struct _lowcore *lowcore_ptr[NR_CPUS]; | 114 | struct _lowcore *lowcore_ptr[NR_CPUS]; |
| 110 | EXPORT_SYMBOL(lowcore_ptr); | 115 | EXPORT_SYMBOL(lowcore_ptr); |
| @@ -544,19 +549,23 @@ static void __init setup_memory_end(void) | |||
| 544 | 549 | ||
| 545 | /* Choose kernel address space layout: 2, 3, or 4 levels. */ | 550 | /* Choose kernel address space layout: 2, 3, or 4 levels. */ |
| 546 | #ifdef CONFIG_64BIT | 551 | #ifdef CONFIG_64BIT |
| 547 | vmalloc_size = VMALLOC_END ?: 128UL << 30; | 552 | vmalloc_size = VMALLOC_END ?: (128UL << 30) - MODULES_LEN; |
| 548 | tmp = (memory_end ?: real_memory_size) / PAGE_SIZE; | 553 | tmp = (memory_end ?: real_memory_size) / PAGE_SIZE; |
| 549 | tmp = tmp * (sizeof(struct page) + PAGE_SIZE) + vmalloc_size; | 554 | tmp = tmp * (sizeof(struct page) + PAGE_SIZE) + vmalloc_size; |
| 550 | if (tmp <= (1UL << 42)) | 555 | if (tmp <= (1UL << 42)) |
| 551 | vmax = 1UL << 42; /* 3-level kernel page table */ | 556 | vmax = 1UL << 42; /* 3-level kernel page table */ |
| 552 | else | 557 | else |
| 553 | vmax = 1UL << 53; /* 4-level kernel page table */ | 558 | vmax = 1UL << 53; /* 4-level kernel page table */ |
| 559 | /* module area is at the end of the kernel address space. */ | ||
| 560 | MODULES_END = vmax; | ||
| 561 | MODULES_VADDR = MODULES_END - MODULES_LEN; | ||
| 562 | VMALLOC_END = MODULES_VADDR; | ||
| 554 | #else | 563 | #else |
| 555 | vmalloc_size = VMALLOC_END ?: 96UL << 20; | 564 | vmalloc_size = VMALLOC_END ?: 96UL << 20; |
| 556 | vmax = 1UL << 31; /* 2-level kernel page table */ | 565 | vmax = 1UL << 31; /* 2-level kernel page table */ |
| 557 | #endif | ||
| 558 | /* vmalloc area is at the end of the kernel address space. */ | 566 | /* vmalloc area is at the end of the kernel address space. */ |
| 559 | VMALLOC_END = vmax; | 567 | VMALLOC_END = vmax; |
| 568 | #endif | ||
| 560 | VMALLOC_START = vmax - vmalloc_size; | 569 | VMALLOC_START = vmax - vmalloc_size; |
| 561 | 570 | ||
| 562 | /* Split remaining virtual space between 1:1 mapping & vmemmap array */ | 571 | /* Split remaining virtual space between 1:1 mapping & vmemmap array */ |
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c index cd1c62d160ed..cbc6668acb85 100644 --- a/arch/s390/mm/dump_pagetables.c +++ b/arch/s390/mm/dump_pagetables.c | |||
| @@ -18,6 +18,9 @@ enum address_markers_idx { | |||
| 18 | KERNEL_END_NR, | 18 | KERNEL_END_NR, |
| 19 | VMEMMAP_NR, | 19 | VMEMMAP_NR, |
| 20 | VMALLOC_NR, | 20 | VMALLOC_NR, |
| 21 | #ifdef CONFIG_64BIT | ||
| 22 | MODULES_NR, | ||
| 23 | #endif | ||
| 21 | }; | 24 | }; |
| 22 | 25 | ||
| 23 | static struct addr_marker address_markers[] = { | 26 | static struct addr_marker address_markers[] = { |
| @@ -26,6 +29,9 @@ static struct addr_marker address_markers[] = { | |||
| 26 | [KERNEL_END_NR] = {(unsigned long)&_end, "Kernel Image End"}, | 29 | [KERNEL_END_NR] = {(unsigned long)&_end, "Kernel Image End"}, |
| 27 | [VMEMMAP_NR] = {0, "vmemmap Area"}, | 30 | [VMEMMAP_NR] = {0, "vmemmap Area"}, |
| 28 | [VMALLOC_NR] = {0, "vmalloc Area"}, | 31 | [VMALLOC_NR] = {0, "vmalloc Area"}, |
| 32 | #ifdef CONFIG_64BIT | ||
| 33 | [MODULES_NR] = {0, "Modules Area"}, | ||
| 34 | #endif | ||
| 29 | { -1, NULL } | 35 | { -1, NULL } |
| 30 | }; | 36 | }; |
| 31 | 37 | ||
| @@ -205,11 +211,12 @@ static int pt_dump_init(void) | |||
| 205 | * kernel ASCE. We need this to keep the page table walker functions | 211 | * kernel ASCE. We need this to keep the page table walker functions |
| 206 | * from accessing non-existent entries. | 212 | * from accessing non-existent entries. |
| 207 | */ | 213 | */ |
| 208 | #ifdef CONFIG_64BIT | 214 | #ifdef CONFIG_32BIT |
| 215 | max_addr = 1UL << 31; | ||
| 216 | #else | ||
| 209 | max_addr = (S390_lowcore.kernel_asce & _REGION_ENTRY_TYPE_MASK) >> 2; | 217 | max_addr = (S390_lowcore.kernel_asce & _REGION_ENTRY_TYPE_MASK) >> 2; |
| 210 | max_addr = 1UL << (max_addr * 11 + 31); | 218 | max_addr = 1UL << (max_addr * 11 + 31); |
| 211 | #else | 219 | address_markers[MODULES_NR].start_address = MODULES_VADDR; |
| 212 | max_addr = 1UL << 31; | ||
| 213 | #endif | 220 | #endif |
| 214 | address_markers[VMEMMAP_NR].start_address = (unsigned long) vmemmap; | 221 | address_markers[VMEMMAP_NR].start_address = (unsigned long) vmemmap; |
| 215 | address_markers[VMALLOC_NR].start_address = VMALLOC_START; | 222 | address_markers[VMALLOC_NR].start_address = VMALLOC_START; |
