diff options
Diffstat (limited to 'arch/s390/mm/init.c')
-rw-r--r-- | arch/s390/mm/init.c | 60 |
1 files changed, 49 insertions, 11 deletions
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 30eb6d02ddb8..59b663109d90 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c | |||
@@ -38,19 +38,59 @@ | |||
38 | #include <asm/tlbflush.h> | 38 | #include <asm/tlbflush.h> |
39 | #include <asm/sections.h> | 39 | #include <asm/sections.h> |
40 | 40 | ||
41 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | ||
42 | |||
43 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); | 41 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); |
44 | 42 | ||
45 | char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); | 43 | unsigned long empty_zero_page, zero_page_mask; |
46 | EXPORT_SYMBOL(empty_zero_page); | 44 | EXPORT_SYMBOL(empty_zero_page); |
47 | 45 | ||
46 | static unsigned long setup_zero_pages(void) | ||
47 | { | ||
48 | struct cpuid cpu_id; | ||
49 | unsigned int order; | ||
50 | unsigned long size; | ||
51 | struct page *page; | ||
52 | int i; | ||
53 | |||
54 | get_cpu_id(&cpu_id); | ||
55 | switch (cpu_id.machine) { | ||
56 | case 0x9672: /* g5 */ | ||
57 | case 0x2064: /* z900 */ | ||
58 | case 0x2066: /* z900 */ | ||
59 | case 0x2084: /* z990 */ | ||
60 | case 0x2086: /* z990 */ | ||
61 | case 0x2094: /* z9-109 */ | ||
62 | case 0x2096: /* z9-109 */ | ||
63 | order = 0; | ||
64 | break; | ||
65 | case 0x2097: /* z10 */ | ||
66 | case 0x2098: /* z10 */ | ||
67 | default: | ||
68 | order = 2; | ||
69 | break; | ||
70 | } | ||
71 | |||
72 | empty_zero_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order); | ||
73 | if (!empty_zero_page) | ||
74 | panic("Out of memory in setup_zero_pages"); | ||
75 | |||
76 | page = virt_to_page((void *) empty_zero_page); | ||
77 | split_page(page, order); | ||
78 | for (i = 1 << order; i > 0; i--) { | ||
79 | SetPageReserved(page); | ||
80 | page++; | ||
81 | } | ||
82 | |||
83 | size = PAGE_SIZE << order; | ||
84 | zero_page_mask = (size - 1) & PAGE_MASK; | ||
85 | |||
86 | return 1UL << order; | ||
87 | } | ||
88 | |||
48 | /* | 89 | /* |
49 | * paging_init() sets up the page tables | 90 | * paging_init() sets up the page tables |
50 | */ | 91 | */ |
51 | void __init paging_init(void) | 92 | void __init paging_init(void) |
52 | { | 93 | { |
53 | static const int ssm_mask = 0x04000000L; | ||
54 | unsigned long max_zone_pfns[MAX_NR_ZONES]; | 94 | unsigned long max_zone_pfns[MAX_NR_ZONES]; |
55 | unsigned long pgd_type; | 95 | unsigned long pgd_type; |
56 | 96 | ||
@@ -72,18 +112,17 @@ void __init paging_init(void) | |||
72 | __ctl_load(S390_lowcore.kernel_asce, 1, 1); | 112 | __ctl_load(S390_lowcore.kernel_asce, 1, 1); |
73 | __ctl_load(S390_lowcore.kernel_asce, 7, 7); | 113 | __ctl_load(S390_lowcore.kernel_asce, 7, 7); |
74 | __ctl_load(S390_lowcore.kernel_asce, 13, 13); | 114 | __ctl_load(S390_lowcore.kernel_asce, 13, 13); |
75 | __raw_local_irq_ssm(ssm_mask); | 115 | arch_local_irq_restore(4UL << (BITS_PER_LONG - 8)); |
76 | 116 | ||
77 | atomic_set(&init_mm.context.attach_count, 1); | 117 | atomic_set(&init_mm.context.attach_count, 1); |
78 | 118 | ||
79 | sparse_memory_present_with_active_regions(MAX_NUMNODES); | 119 | sparse_memory_present_with_active_regions(MAX_NUMNODES); |
80 | sparse_init(); | 120 | sparse_init(); |
81 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); | 121 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); |
82 | #ifdef CONFIG_ZONE_DMA | ||
83 | max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS); | 122 | max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS); |
84 | #endif | ||
85 | max_zone_pfns[ZONE_NORMAL] = max_low_pfn; | 123 | max_zone_pfns[ZONE_NORMAL] = max_low_pfn; |
86 | free_area_init_nodes(max_zone_pfns); | 124 | free_area_init_nodes(max_zone_pfns); |
125 | fault_init(); | ||
87 | } | 126 | } |
88 | 127 | ||
89 | void __init mem_init(void) | 128 | void __init mem_init(void) |
@@ -93,14 +132,12 @@ void __init mem_init(void) | |||
93 | max_mapnr = num_physpages = max_low_pfn; | 132 | max_mapnr = num_physpages = max_low_pfn; |
94 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); | 133 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); |
95 | 134 | ||
96 | /* clear the zero-page */ | ||
97 | memset(empty_zero_page, 0, PAGE_SIZE); | ||
98 | |||
99 | /* Setup guest page hinting */ | 135 | /* Setup guest page hinting */ |
100 | cmma_init(); | 136 | cmma_init(); |
101 | 137 | ||
102 | /* this will put all low memory onto the freelists */ | 138 | /* this will put all low memory onto the freelists */ |
103 | totalram_pages += free_all_bootmem(); | 139 | totalram_pages += free_all_bootmem(); |
140 | totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */ | ||
104 | 141 | ||
105 | reservedpages = 0; | 142 | reservedpages = 0; |
106 | 143 | ||
@@ -136,7 +173,8 @@ void kernel_map_pages(struct page *page, int numpages, int enable) | |||
136 | pmd = pmd_offset(pud, address); | 173 | pmd = pmd_offset(pud, address); |
137 | pte = pte_offset_kernel(pmd, address); | 174 | pte = pte_offset_kernel(pmd, address); |
138 | if (!enable) { | 175 | if (!enable) { |
139 | ptep_invalidate(&init_mm, address, pte); | 176 | __ptep_ipte(address, pte); |
177 | pte_val(*pte) = _PAGE_TYPE_EMPTY; | ||
140 | continue; | 178 | continue; |
141 | } | 179 | } |
142 | *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW)); | 180 | *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW)); |