diff options
Diffstat (limited to 'arch/sh/mm/init.c')
-rw-r--r-- | arch/sh/mm/init.c | 68 |
1 files changed, 53 insertions, 15 deletions
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index d5e160da64b2..2918c6b14659 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c | |||
@@ -23,9 +23,7 @@ | |||
23 | 23 | ||
24 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 24 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
25 | pgd_t swapper_pg_dir[PTRS_PER_PGD]; | 25 | pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
26 | 26 | unsigned long cached_to_uncached = 0; | |
27 | void (*copy_page)(void *from, void *to); | ||
28 | void (*clear_page)(void *to); | ||
29 | 27 | ||
30 | void show_mem(void) | 28 | void show_mem(void) |
31 | { | 29 | { |
@@ -102,7 +100,8 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot) | |||
102 | 100 | ||
103 | set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot)); | 101 | set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot)); |
104 | 102 | ||
105 | flush_tlb_one(get_asid(), addr); | 103 | if (cached_to_uncached) |
104 | flush_tlb_one(get_asid(), addr); | ||
106 | } | 105 | } |
107 | 106 | ||
108 | /* | 107 | /* |
@@ -131,6 +130,37 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) | |||
131 | 130 | ||
132 | set_pte_phys(address, phys, prot); | 131 | set_pte_phys(address, phys, prot); |
133 | } | 132 | } |
133 | |||
134 | void __init page_table_range_init(unsigned long start, unsigned long end, | ||
135 | pgd_t *pgd_base) | ||
136 | { | ||
137 | pgd_t *pgd; | ||
138 | pud_t *pud; | ||
139 | pmd_t *pmd; | ||
140 | int pgd_idx; | ||
141 | unsigned long vaddr; | ||
142 | |||
143 | vaddr = start & PMD_MASK; | ||
144 | end = (end + PMD_SIZE - 1) & PMD_MASK; | ||
145 | pgd_idx = pgd_index(vaddr); | ||
146 | pgd = pgd_base + pgd_idx; | ||
147 | |||
148 | for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) { | ||
149 | BUG_ON(pgd_none(*pgd)); | ||
150 | pud = pud_offset(pgd, 0); | ||
151 | BUG_ON(pud_none(*pud)); | ||
152 | pmd = pmd_offset(pud, 0); | ||
153 | |||
154 | if (!pmd_present(*pmd)) { | ||
155 | pte_t *pte_table; | ||
156 | pte_table = (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE); | ||
157 | memset(pte_table, 0, PAGE_SIZE); | ||
158 | pmd_populate_kernel(&init_mm, pmd, pte_table); | ||
159 | } | ||
160 | |||
161 | vaddr += PMD_SIZE; | ||
162 | } | ||
163 | } | ||
134 | #endif /* CONFIG_MMU */ | 164 | #endif /* CONFIG_MMU */ |
135 | 165 | ||
136 | /* | 166 | /* |
@@ -150,6 +180,11 @@ void __init paging_init(void) | |||
150 | * check for a null value. */ | 180 | * check for a null value. */ |
151 | set_TTB(swapper_pg_dir); | 181 | set_TTB(swapper_pg_dir); |
152 | 182 | ||
183 | /* Populate the relevant portions of swapper_pg_dir so that | ||
184 | * we can use the fixmap entries without calling kmalloc. | ||
185 | * pte's will be filled in by __set_fixmap(). */ | ||
186 | page_table_range_init(FIXADDR_START, FIXADDR_TOP, swapper_pg_dir); | ||
187 | |||
153 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); | 188 | memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); |
154 | 189 | ||
155 | for_each_online_node(nid) { | 190 | for_each_online_node(nid) { |
@@ -167,9 +202,22 @@ void __init paging_init(void) | |||
167 | } | 202 | } |
168 | 203 | ||
169 | free_area_init_nodes(max_zone_pfns); | 204 | free_area_init_nodes(max_zone_pfns); |
205 | |||
206 | /* Set up the uncached fixmap */ | ||
207 | set_fixmap_nocache(FIX_UNCACHED, __pa(&__uncached_start)); | ||
208 | |||
209 | #ifdef CONFIG_29BIT | ||
210 | /* | ||
211 | * Handle trivial transitions between cached and uncached | ||
212 | * segments, making use of the 1:1 mapping relationship in | ||
213 | * 512MB lowmem. | ||
214 | */ | ||
215 | cached_to_uncached = P2SEG - P1SEG; | ||
216 | #endif | ||
170 | } | 217 | } |
171 | 218 | ||
172 | static struct kcore_list kcore_mem, kcore_vmalloc; | 219 | static struct kcore_list kcore_mem, kcore_vmalloc; |
220 | int after_bootmem = 0; | ||
173 | 221 | ||
174 | void __init mem_init(void) | 222 | void __init mem_init(void) |
175 | { | 223 | { |
@@ -202,17 +250,7 @@ void __init mem_init(void) | |||
202 | memset(empty_zero_page, 0, PAGE_SIZE); | 250 | memset(empty_zero_page, 0, PAGE_SIZE); |
203 | __flush_wback_region(empty_zero_page, PAGE_SIZE); | 251 | __flush_wback_region(empty_zero_page, PAGE_SIZE); |
204 | 252 | ||
205 | /* | 253 | after_bootmem = 1; |
206 | * Setup wrappers for copy/clear_page(), these will get overridden | ||
207 | * later in the boot process if a better method is available. | ||
208 | */ | ||
209 | #ifdef CONFIG_MMU | ||
210 | copy_page = copy_page_slow; | ||
211 | clear_page = clear_page_slow; | ||
212 | #else | ||
213 | copy_page = copy_page_nommu; | ||
214 | clear_page = clear_page_nommu; | ||
215 | #endif | ||
216 | 254 | ||
217 | codesize = (unsigned long) &_etext - (unsigned long) &_text; | 255 | codesize = (unsigned long) &_etext - (unsigned long) &_text; |
218 | datasize = (unsigned long) &_edata - (unsigned long) &_etext; | 256 | datasize = (unsigned long) &_edata - (unsigned long) &_etext; |