diff options
Diffstat (limited to 'arch/s390/mm/init.c')
-rw-r--r-- | arch/s390/mm/init.c | 119 |
1 files changed, 53 insertions, 66 deletions
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index a055894f3bd..127044e1707 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -9,7 +9,6 @@ * Copyright (C) 1995 Linus Torvalds */ -#include <linux/config.h> #include <linux/signal.h> #include <linux/sched.h> #include <linux/kernel.h> @@ -24,6 +23,7 @@ #include <linux/init.h> #include <linux/pagemap.h> #include <linux/bootmem.h> +#include <linux/pfn.h> #include <asm/processor.h> #include <asm/system.h> @@ -34,6 +34,7 @@ #include <asm/lowcore.h> #include <asm/tlb.h> #include <asm/tlbflush.h> +#include <asm/sections.h> DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -44,26 +45,17 @@ void diag10(unsigned long addr) { if (addr >= 0x7ff00000) return; + asm volatile( #ifdef CONFIG_64BIT - asm volatile ( - " sam31\n" - " diag %0,%0,0x10\n" - "0: sam64\n" - ".section __ex_table,\"a\"\n" - " .align 8\n" - " .quad 0b, 0b\n" - ".previous\n" - : : "a" (addr)); + " sam31\n" + " diag %0,%0,0x10\n" + "0: sam64\n" #else - asm volatile ( - " diag %0,%0,0x10\n" + " diag %0,%0,0x10\n" "0:\n" - ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 0b, 0b\n" - ".previous\n" - : : "a" (addr)); #endif + EX_TABLE(0b,0b) + : : "a" (addr)); } void show_mem(void) @@ -90,17 +82,6 @@ void show_mem(void) printk("%d pages swap cached\n",cached); } -/* References to section boundaries */ - -extern unsigned long _text; -extern unsigned long _etext; -extern unsigned long _edata; -extern unsigned long __bss_start; -extern unsigned long _end; - -extern unsigned long __init_begin; -extern unsigned long __init_end; - extern unsigned long __initdata zholes_size[]; /* * paging_init() sets up the page tables @@ -117,13 +98,24 @@ void __init paging_init(void) unsigned long pfn = 0; unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; static const int ssm_mask = 0x04000000L; + unsigned long ro_start_pfn, ro_end_pfn; + unsigned long zones_size[MAX_NR_ZONES]; + + ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata); + ro_end_pfn = PFN_UP((unsigned long)&__end_rodata); + + memset(zones_size, 0, sizeof(zones_size)); + zones_size[ZONE_DMA] = max_low_pfn; + free_area_init_node(0, &contig_page_data, zones_size, + __pa(PAGE_OFFSET) >> PAGE_SHIFT, + zholes_size); /* unmap whole virtual address space */ pg_dir = swapper_pg_dir; - for (i=0;i<KERNEL_PGD_PTRS;i++) - pmd_clear((pmd_t*)pg_dir++); + for (i = 0; i < PTRS_PER_PGD; i++) + pmd_clear((pmd_t *) pg_dir++); /* * map whole physical memory to virtual memory (identity mapping) @@ -135,19 +127,19 @@ void __init paging_init(void) /* * pg_table is physical at this point */ - pg_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); + pg_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); - pg_dir->pgd0 = (_PAGE_TABLE | __pa(pg_table)); - pg_dir->pgd1 = (_PAGE_TABLE | (__pa(pg_table)+1024)); - pg_dir->pgd2 = (_PAGE_TABLE | (__pa(pg_table)+2048)); - pg_dir->pgd3 = (_PAGE_TABLE | (__pa(pg_table)+3072)); + pmd_populate_kernel(&init_mm, (pmd_t *) pg_dir, pg_table); pg_dir++; for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) { - pte = pfn_pte(pfn, PAGE_KERNEL); + if (pfn >= ro_start_pfn && pfn < ro_end_pfn) + pte = pfn_pte(pfn, __pgprot(_PAGE_RO)); + else + pte = pfn_pte(pfn, PAGE_KERNEL); if (pfn >= max_low_pfn) - pte_clear(&init_mm, 0, &pte); - set_pte(pg_table, pte); + pte_val(pte) = _PAGE_TYPE_EMPTY; + set_pte(pg_table, pte); pfn++; } } @@ -155,27 +147,17 @@ void __init paging_init(void) S390_lowcore.kernel_asce = pgdir_k; /* enable virtual mapping in kernel mode */ - __asm__ __volatile__(" LCTL 1,1,%0\n" - " LCTL 7,7,%0\n" - " LCTL 13,13,%0\n" - " SSM %1" - : : "m" (pgdir_k), "m" (ssm_mask)); + __ctl_load(pgdir_k, 1, 1); + __ctl_load(pgdir_k, 7, 7); + __ctl_load(pgdir_k, 13, 13); + __raw_local_irq_ssm(ssm_mask); local_flush_tlb(); - - { - unsigned long zones_size[MAX_NR_ZONES]; - - memset(zones_size, 0, sizeof(zones_size)); - zones_size[ZONE_DMA] = max_low_pfn; - free_area_init_node(0, &contig_page_data, zones_size, - __pa(PAGE_OFFSET) >> PAGE_SHIFT, - zholes_size); - } return; } #else /* CONFIG_64BIT */ + void __init paging_init(void) { pgd_t * pg_dir; @@ -187,13 +169,15 @@ void __init paging_init(void) unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERN_REGION_TABLE; static const int ssm_mask = 0x04000000L; - unsigned long zones_size[MAX_NR_ZONES]; unsigned long dma_pfn, high_pfn; + unsigned long ro_start_pfn, ro_end_pfn; memset(zones_size, 0, sizeof(zones_size)); dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT; high_pfn = max_low_pfn; + ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata); + ro_end_pfn = PFN_UP((unsigned long)&__end_rodata); if (dma_pfn > high_pfn) zones_size[ZONE_DMA] = high_pfn; @@ -219,7 +203,7 @@ void __init paging_init(void) continue; } - pm_dir = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE*4); + pm_dir = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE * 4); pgd_populate(&init_mm, pg_dir, pm_dir); for (j = 0 ; j < PTRS_PER_PMD ; j++,pm_dir++) { @@ -228,15 +212,16 @@ void __init paging_init(void) continue; } - pt_dir = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); + pt_dir = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); pmd_populate_kernel(&init_mm, pm_dir, pt_dir); for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) { - pte = pfn_pte(pfn, PAGE_KERNEL); - if (pfn >= max_low_pfn) { - pte_clear(&init_mm, 0, &pte); - continue; - } + if (pfn >= ro_start_pfn && pfn < ro_end_pfn) + pte = pfn_pte(pfn, __pgprot(_PAGE_RO)); + else + pte = pfn_pte(pfn, PAGE_KERNEL); + if (pfn >= max_low_pfn) + pte_val(pte) = _PAGE_TYPE_EMPTY; set_pte(pt_dir, pte); pfn++; } @@ -246,11 +231,10 @@ void __init paging_init(void) S390_lowcore.kernel_asce = pgdir_k; /* enable virtual mapping in kernel mode */ - __asm__ __volatile__("lctlg 1,1,%0\n\t" - "lctlg 7,7,%0\n\t" - "lctlg 13,13,%0\n\t" - "ssm %1" - : :"m" (pgdir_k), "m" (ssm_mask)); + __ctl_load(pgdir_k, 1, 1); + __ctl_load(pgdir_k, 7, 7); + __ctl_load(pgdir_k, 13, 13); + __raw_local_irq_ssm(ssm_mask); local_flush_tlb(); @@ -283,6 +267,9 @@ void __init mem_init(void) reservedpages << (PAGE_SHIFT-10), datasize >>10, initsize >> 10); + printk("Write protected kernel read-only data: %#lx - %#lx\n", + (unsigned long)&__start_rodata, + PFN_ALIGN((unsigned long)&__end_rodata) - 1); } void free_initmem(void) |