diff options
Diffstat (limited to 'arch/s390/mm/init.c')
| -rw-r--r-- | arch/s390/mm/init.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 81dce185f836..eb6ebfef134a 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/pagemap.h> | 24 | #include <linux/pagemap.h> |
| 25 | #include <linux/bootmem.h> | 25 | #include <linux/bootmem.h> |
| 26 | #include <linux/pfn.h> | ||
| 26 | 27 | ||
| 27 | #include <asm/processor.h> | 28 | #include <asm/processor.h> |
| 28 | #include <asm/system.h> | 29 | #include <asm/system.h> |
| @@ -33,6 +34,7 @@ | |||
| 33 | #include <asm/lowcore.h> | 34 | #include <asm/lowcore.h> |
| 34 | #include <asm/tlb.h> | 35 | #include <asm/tlb.h> |
| 35 | #include <asm/tlbflush.h> | 36 | #include <asm/tlbflush.h> |
| 37 | #include <asm/sections.h> | ||
| 36 | 38 | ||
| 37 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 39 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
| 38 | 40 | ||
| @@ -89,17 +91,6 @@ void show_mem(void) | |||
| 89 | printk("%d pages swap cached\n",cached); | 91 | printk("%d pages swap cached\n",cached); |
| 90 | } | 92 | } |
| 91 | 93 | ||
| 92 | /* References to section boundaries */ | ||
| 93 | |||
| 94 | extern unsigned long _text; | ||
| 95 | extern unsigned long _etext; | ||
| 96 | extern unsigned long _edata; | ||
| 97 | extern unsigned long __bss_start; | ||
| 98 | extern unsigned long _end; | ||
| 99 | |||
| 100 | extern unsigned long __init_begin; | ||
| 101 | extern unsigned long __init_end; | ||
| 102 | |||
| 103 | extern unsigned long __initdata zholes_size[]; | 94 | extern unsigned long __initdata zholes_size[]; |
| 104 | /* | 95 | /* |
| 105 | * paging_init() sets up the page tables | 96 | * paging_init() sets up the page tables |
| @@ -116,6 +107,10 @@ void __init paging_init(void) | |||
| 116 | unsigned long pfn = 0; | 107 | unsigned long pfn = 0; |
| 117 | unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; | 108 | unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; |
| 118 | static const int ssm_mask = 0x04000000L; | 109 | static const int ssm_mask = 0x04000000L; |
| 110 | unsigned long ro_start_pfn, ro_end_pfn; | ||
| 111 | |||
| 112 | ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata); | ||
| 113 | ro_end_pfn = PFN_UP((unsigned long)&__end_rodata); | ||
| 119 | 114 | ||
| 120 | /* unmap whole virtual address space */ | 115 | /* unmap whole virtual address space */ |
| 121 | 116 | ||
| @@ -143,7 +138,10 @@ void __init paging_init(void) | |||
| 143 | pg_dir++; | 138 | pg_dir++; |
| 144 | 139 | ||
| 145 | for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) { | 140 | for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) { |
| 146 | pte = pfn_pte(pfn, PAGE_KERNEL); | 141 | if (pfn >= ro_start_pfn && pfn < ro_end_pfn) |
| 142 | pte = pfn_pte(pfn, __pgprot(_PAGE_RO)); | ||
| 143 | else | ||
| 144 | pte = pfn_pte(pfn, PAGE_KERNEL); | ||
| 147 | if (pfn >= max_low_pfn) | 145 | if (pfn >= max_low_pfn) |
| 148 | pte_clear(&init_mm, 0, &pte); | 146 | pte_clear(&init_mm, 0, &pte); |
| 149 | set_pte(pg_table, pte); | 147 | set_pte(pg_table, pte); |
| @@ -175,6 +173,7 @@ void __init paging_init(void) | |||
| 175 | } | 173 | } |
| 176 | 174 | ||
| 177 | #else /* CONFIG_64BIT */ | 175 | #else /* CONFIG_64BIT */ |
| 176 | |||
| 178 | void __init paging_init(void) | 177 | void __init paging_init(void) |
| 179 | { | 178 | { |
| 180 | pgd_t * pg_dir; | 179 | pgd_t * pg_dir; |
| @@ -186,13 +185,15 @@ void __init paging_init(void) | |||
| 186 | unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | | 185 | unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | |
| 187 | _KERN_REGION_TABLE; | 186 | _KERN_REGION_TABLE; |
| 188 | static const int ssm_mask = 0x04000000L; | 187 | static const int ssm_mask = 0x04000000L; |
| 189 | |||
| 190 | unsigned long zones_size[MAX_NR_ZONES]; | 188 | unsigned long zones_size[MAX_NR_ZONES]; |
| 191 | unsigned long dma_pfn, high_pfn; | 189 | unsigned long dma_pfn, high_pfn; |
| 190 | unsigned long ro_start_pfn, ro_end_pfn; | ||
| 192 | 191 | ||
| 193 | memset(zones_size, 0, sizeof(zones_size)); | 192 | memset(zones_size, 0, sizeof(zones_size)); |
| 194 | dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT; | 193 | dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT; |
| 195 | high_pfn = max_low_pfn; | 194 | high_pfn = max_low_pfn; |
| 195 | ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata); | ||
| 196 | ro_end_pfn = PFN_UP((unsigned long)&__end_rodata); | ||
| 196 | 197 | ||
| 197 | if (dma_pfn > high_pfn) | 198 | if (dma_pfn > high_pfn) |
| 198 | zones_size[ZONE_DMA] = high_pfn; | 199 | zones_size[ZONE_DMA] = high_pfn; |
| @@ -231,7 +232,10 @@ void __init paging_init(void) | |||
| 231 | pmd_populate_kernel(&init_mm, pm_dir, pt_dir); | 232 | pmd_populate_kernel(&init_mm, pm_dir, pt_dir); |
| 232 | 233 | ||
| 233 | for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) { | 234 | for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) { |
| 234 | pte = pfn_pte(pfn, PAGE_KERNEL); | 235 | if (pfn >= ro_start_pfn && pfn < ro_end_pfn) |
| 236 | pte = pfn_pte(pfn, __pgprot(_PAGE_RO)); | ||
| 237 | else | ||
| 238 | pte = pfn_pte(pfn, PAGE_KERNEL); | ||
| 235 | if (pfn >= max_low_pfn) { | 239 | if (pfn >= max_low_pfn) { |
| 236 | pte_clear(&init_mm, 0, &pte); | 240 | pte_clear(&init_mm, 0, &pte); |
| 237 | continue; | 241 | continue; |
| @@ -282,6 +286,9 @@ void __init mem_init(void) | |||
| 282 | reservedpages << (PAGE_SHIFT-10), | 286 | reservedpages << (PAGE_SHIFT-10), |
| 283 | datasize >>10, | 287 | datasize >>10, |
| 284 | initsize >> 10); | 288 | initsize >> 10); |
| 289 | printk("Write protected kernel read-only data: %#lx - %#lx\n", | ||
| 290 | (unsigned long)&__start_rodata, | ||
| 291 | PFN_ALIGN((unsigned long)&__end_rodata) - 1); | ||
| 285 | } | 292 | } |
| 286 | 293 | ||
| 287 | void free_initmem(void) | 294 | void free_initmem(void) |
