aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/setup_32.c1
-rw-r--r--arch/x86/mm/init_32.c2
-rw-r--r--arch/x86/mm/ioremap_32.c87
-rw-r--r--include/asm-x86/io_32.h3
4 files changed, 91 insertions, 2 deletions
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index 83ba3ca5f43..35db426de30 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -697,6 +697,7 @@ void __init setup_arch(char **cmdline_p)
697 memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); 697 memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
698 pre_setup_arch_hook(); 698 pre_setup_arch_hook();
699 early_cpu_init(); 699 early_cpu_init();
700 bt_ioremap_init();
700 701
701#ifdef CONFIG_EFI 702#ifdef CONFIG_EFI
702 if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, 703 if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 206e3f6800b..f4e1894367a 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -429,9 +429,11 @@ static void __init pagetable_init (void)
429 * Fixed mappings, only the page table structure has to be 429 * Fixed mappings, only the page table structure has to be
430 * created - mappings will be set by set_fixmap(): 430 * created - mappings will be set by set_fixmap():
431 */ 431 */
432 bt_ioremap_clear();
432 vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; 433 vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
433 end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK; 434 end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK;
434 page_table_range_init(vaddr, end, pgd_base); 435 page_table_range_init(vaddr, end, pgd_base);
436 bt_ioremap_reset();
435 437
436 permanent_kmaps_init(pgd_base); 438 permanent_kmaps_init(pgd_base);
437 439
diff --git a/arch/x86/mm/ioremap_32.c b/arch/x86/mm/ioremap_32.c
index ef0f6a452ee..fd1f5b6cfa2 100644
--- a/arch/x86/mm/ioremap_32.c
+++ b/arch/x86/mm/ioremap_32.c
@@ -208,6 +208,89 @@ void iounmap(volatile void __iomem *addr)
208} 208}
209EXPORT_SYMBOL(iounmap); 209EXPORT_SYMBOL(iounmap);
210 210
211static __initdata int after_paging_init;
212static __initdata unsigned long bm_pte[1024]
213 __attribute__((aligned(PAGE_SIZE)));
214
215static inline unsigned long * __init bt_ioremap_pgd(unsigned long addr)
216{
217 return (unsigned long *)swapper_pg_dir + ((addr >> 22) & 1023);
218}
219
220static inline unsigned long * __init bt_ioremap_pte(unsigned long addr)
221{
222 return bm_pte + ((addr >> PAGE_SHIFT) & 1023);
223}
224
225void __init bt_ioremap_init(void)
226{
227 unsigned long *pgd;
228
229 pgd = bt_ioremap_pgd(fix_to_virt(FIX_BTMAP_BEGIN));
230 *pgd = __pa(bm_pte) | _PAGE_TABLE;
231 memset(bm_pte, 0, sizeof(bm_pte));
232 BUG_ON(pgd != bt_ioremap_pgd(fix_to_virt(FIX_BTMAP_END)));
233}
234
235void __init bt_ioremap_clear(void)
236{
237 unsigned long *pgd;
238
239 pgd = bt_ioremap_pgd(fix_to_virt(FIX_BTMAP_BEGIN));
240 *pgd = 0;
241 __flush_tlb_all();
242}
243
244void __init bt_ioremap_reset(void)
245{
246 enum fixed_addresses idx;
247 unsigned long *pte, phys, addr;
248
249 after_paging_init = 1;
250 for (idx = FIX_BTMAP_BEGIN; idx <= FIX_BTMAP_END; idx--) {
251 addr = fix_to_virt(idx);
252 pte = bt_ioremap_pte(addr);
253 if (!*pte & _PAGE_PRESENT) {
254 phys = *pte & PAGE_MASK;
255 set_fixmap(idx, phys);
256 }
257 }
258}
259
260static void __init __bt_set_fixmap(enum fixed_addresses idx,
261 unsigned long phys, pgprot_t flags)
262{
263 unsigned long *pte, addr = __fix_to_virt(idx);
264
265 if (idx >= __end_of_fixed_addresses) {
266 BUG();
267 return;
268 }
269 pte = bt_ioremap_pte(addr);
270 if (pgprot_val(flags))
271 *pte = (phys & PAGE_MASK) | pgprot_val(flags);
272 else
273 *pte = 0;
274 __flush_tlb_one(addr);
275}
276
277static inline void __init bt_set_fixmap(enum fixed_addresses idx,
278 unsigned long phys)
279{
280 if (after_paging_init)
281 set_fixmap(idx, phys);
282 else
283 __bt_set_fixmap(idx, phys, PAGE_KERNEL);
284}
285
286static inline void __init bt_clear_fixmap(enum fixed_addresses idx)
287{
288 if (after_paging_init)
289 clear_fixmap(idx);
290 else
291 __bt_set_fixmap(idx, 0, __pgprot(0));
292}
293
211void __init *bt_ioremap(unsigned long phys_addr, unsigned long size) 294void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
212{ 295{
213 unsigned long offset, last_addr; 296 unsigned long offset, last_addr;
@@ -244,7 +327,7 @@ void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
244 */ 327 */
245 idx = FIX_BTMAP_BEGIN; 328 idx = FIX_BTMAP_BEGIN;
246 while (nrpages > 0) { 329 while (nrpages > 0) {
247 set_fixmap(idx, phys_addr); 330 bt_set_fixmap(idx, phys_addr);
248 phys_addr += PAGE_SIZE; 331 phys_addr += PAGE_SIZE;
249 --idx; 332 --idx;
250 --nrpages; 333 --nrpages;
@@ -267,7 +350,7 @@ void __init bt_iounmap(void *addr, unsigned long size)
267 350
268 idx = FIX_BTMAP_BEGIN; 351 idx = FIX_BTMAP_BEGIN;
269 while (nrpages > 0) { 352 while (nrpages > 0) {
270 clear_fixmap(idx); 353 bt_clear_fixmap(idx);
271 --idx; 354 --idx;
272 --nrpages; 355 --nrpages;
273 } 356 }
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index db397884637..f7b733d9ace 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -139,6 +139,9 @@ extern void iounmap(volatile void __iomem *addr);
139 * mappings, before the real ioremap() is functional. 139 * mappings, before the real ioremap() is functional.
140 * A boot-time mapping is currently limited to at most 16 pages. 140 * A boot-time mapping is currently limited to at most 16 pages.
141 */ 141 */
142extern void bt_ioremap_init(void);
143extern void bt_ioremap_clear(void);
144extern void bt_ioremap_reset(void);
142extern void *bt_ioremap(unsigned long offset, unsigned long size); 145extern void *bt_ioremap(unsigned long offset, unsigned long size);
143extern void bt_iounmap(void *addr, unsigned long size); 146extern void bt_iounmap(void *addr, unsigned long size);
144extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); 147extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);