diff options
author | Linus Torvalds | 2019-05-14 13:17:19 -0700 |
---|---|---|
committer | Linus Torvalds | 2019-05-14 13:17:19 -0700 |
commit | b2c91128212a4c1a36bd3085191bff21a34324be (patch) | |
tree | 75d4a67a8fe15c947941f5a347189a8701eba76b /arch/parisc/mm | |
parent | ca4b40629f4edd3a961bedcd118e3ad05439ec71 (diff) | |
parent | 4e617c86ba9be5211643e53f5f69d1195c956d68 (diff) |
Merge branch 'parisc-5.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull more parisc updates from Helge Deller:
"Two small enhancements, which I didn't included in the last pull
request because I wanted to keep them a few more days in for-next
before sending upstream:
- Replace the ldcw barrier instruction by a nop instruction in the
CAS code on uniprocessor machines.
- Map variables read-only after init (enable ro_after_init feature)"
* 'parisc-5.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
parisc: Use __ro_after_init in init.c
parisc: Use __ro_after_init in unwind.c
parisc: Use __ro_after_init in time.c
parisc: Use __ro_after_init in processor.c
parisc: Use __ro_after_init in process.c
parisc: Use __ro_after_init in perf_images.h
parisc: Use __ro_after_init in pci.c
parisc: Use __ro_after_init in inventory.c
parisc: Use __ro_after_init in head.S
parisc: Use __ro_after_init in firmware.c
parisc: Use __ro_after_init in drivers.c
parisc: Use __ro_after_init in cache.c
parisc: Enable the ro_after_init feature
parisc: Drop LDCW barrier in CAS code when running UP
Diffstat (limited to 'arch/parisc/mm')
-rw-r--r-- | arch/parisc/mm/init.c | 75 |
1 files changed, 39 insertions, 36 deletions
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 11ec1f1221a6..ddca8287d43b 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -66,7 +66,7 @@ static struct resource pdcdata_resource = { .flags = IORESOURCE_BUSY | IORESOURCE_MEM, }; -static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __read_mostly; +static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __ro_after_init; /* The following array is initialized from the firmware specific * information retrieved in kernel/inventory.c. @@ -345,16 +345,7 @@ static void __init setup_bootmem(void) memblock_dump_all(); } -static int __init parisc_text_address(unsigned long vaddr) -{ - static unsigned long head_ptr __initdata; - - if (!head_ptr) - head_ptr = PAGE_MASK & (unsigned long) - dereference_function_descriptor(&parisc_kernel_start); - - return core_kernel_text(vaddr) || vaddr == head_ptr; -} +static bool kernel_set_to_readonly; static void __init map_pages(unsigned long start_vaddr, unsigned long start_paddr, unsigned long size, @@ -372,10 +363,11 @@ static void __init map_pages(unsigned long start_vaddr, unsigned long vaddr; unsigned long ro_start; unsigned long ro_end; - unsigned long kernel_end; + unsigned long kernel_start, kernel_end; ro_start = __pa((unsigned long)_text); ro_end = __pa((unsigned long)&data_start); + kernel_start = __pa((unsigned long)&__init_begin); kernel_end = __pa((unsigned long)&_end); end_paddr = start_paddr + size; @@ -438,26 +430,30 @@ static void __init map_pages(unsigned long start_vaddr, pg_table = (pte_t *) __va(pg_table) + start_pte; for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++, pg_table++) { pte_t pte; - - if (force) - pte = __mk_pte(address, pgprot); - else if (parisc_text_address(vaddr)) { - pte = __mk_pte(address, PAGE_KERNEL_EXEC); - if (address >= ro_start && address < kernel_end) - pte = pte_mkhuge(pte); + pgprot_t prot; + bool huge = false; + + if (force) { + prot = pgprot; + } else if (address < kernel_start || address >= kernel_end) { + /* outside kernel memory */ + prot = PAGE_KERNEL; + } else if (!kernel_set_to_readonly) { + /* still initializing, allow writing to RO memory */ + prot = PAGE_KERNEL_RWX; + huge = true; + } else if (address >= ro_start) { + /* Code (ro) and Data areas */ + prot = (address < ro_end) ? + PAGE_KERNEL_EXEC : PAGE_KERNEL; + huge = true; + } else { + prot = PAGE_KERNEL; } - else -#if defined(CONFIG_PARISC_PAGE_SIZE_4KB) - if (address >= ro_start && address < ro_end) { - pte = __mk_pte(address, PAGE_KERNEL_EXEC); + + pte = __mk_pte(address, prot); + if (huge) pte = pte_mkhuge(pte); - } else -#endif - { - pte = __mk_pte(address, pgprot); - if (address >= ro_start && address < kernel_end) - pte = pte_mkhuge(pte); - } if (address >= end_paddr) break; @@ -493,6 +489,12 @@ void __ref free_initmem(void) { unsigned long init_begin = (unsigned long)__init_begin; unsigned long init_end = (unsigned long)__init_end; + unsigned long kernel_end = (unsigned long)&_end; + + /* Remap kernel text and data, but do not touch init section yet. */ + kernel_set_to_readonly = true; + map_pages(init_end, __pa(init_end), kernel_end - init_end, + PAGE_KERNEL, 0); /* The init text pages are marked R-X. We have to * flush the icache and mark them RW- @@ -509,7 +511,7 @@ void __ref free_initmem(void) PAGE_KERNEL, 1); /* force the kernel to see the new TLB entries */ - __flush_tlb_range(0, init_begin, init_end); + __flush_tlb_range(0, init_begin, kernel_end); /* finally dump all the instructions which were cached, since the * pages are no-longer executable */ @@ -527,8 +529,9 @@ void mark_rodata_ro(void) { /* rodata memory was already mapped with KERNEL_RO access rights by pagetable_init() and map_pages(). No need to do additional stuff here */ - printk (KERN_INFO "Write protecting the kernel read-only data: %luk\n", - (unsigned long)(__end_rodata - __start_rodata) >> 10); + unsigned long roai_size = __end_ro_after_init - __start_ro_after_init; + + pr_info("Write protected read-only-after-init data: %luk\n", roai_size >> 10); } #endif @@ -554,11 +557,11 @@ void mark_rodata_ro(void) #define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \ & ~(VM_MAP_OFFSET-1))) -void *parisc_vmalloc_start __read_mostly; +void *parisc_vmalloc_start __ro_after_init; EXPORT_SYMBOL(parisc_vmalloc_start); #ifdef CONFIG_PA11 -unsigned long pcxl_dma_start __read_mostly; +unsigned long pcxl_dma_start __ro_after_init; #endif void __init mem_init(void) @@ -632,7 +635,7 @@ void __init mem_init(void) #endif } -unsigned long *empty_zero_page __read_mostly; +unsigned long *empty_zero_page __ro_after_init; EXPORT_SYMBOL(empty_zero_page); /* |