diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/setup_32.c | 1 | ||||
-rw-r--r-- | arch/x86/mm/init_32.c | 2 | ||||
-rw-r--r-- | arch/x86/mm/ioremap_32.c | 87 |
3 files changed, 88 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) memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); pre_setup_arch_hook(); early_cpu_init(); + bt_ioremap_init(); #ifdef CONFIG_EFI 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) * Fixed mappings, only the page table structure has to be * created - mappings will be set by set_fixmap(): */ + bt_ioremap_clear(); vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK; page_table_range_init(vaddr, end, pgd_base); + bt_ioremap_reset(); permanent_kmaps_init(pgd_base); 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) } EXPORT_SYMBOL(iounmap); +static __initdata int after_paging_init; +static __initdata unsigned long bm_pte[1024] + __attribute__((aligned(PAGE_SIZE))); + +static inline unsigned long * __init bt_ioremap_pgd(unsigned long addr) +{ + return (unsigned long *)swapper_pg_dir + ((addr >> 22) & 1023); +} + +static inline unsigned long * __init bt_ioremap_pte(unsigned long addr) +{ + return bm_pte + ((addr >> PAGE_SHIFT) & 1023); +} + +void __init bt_ioremap_init(void) +{ + unsigned long *pgd; + + pgd = bt_ioremap_pgd(fix_to_virt(FIX_BTMAP_BEGIN)); + *pgd = __pa(bm_pte) | _PAGE_TABLE; + memset(bm_pte, 0, sizeof(bm_pte)); + BUG_ON(pgd != bt_ioremap_pgd(fix_to_virt(FIX_BTMAP_END))); +} + +void __init bt_ioremap_clear(void) +{ + unsigned long *pgd; + + pgd = bt_ioremap_pgd(fix_to_virt(FIX_BTMAP_BEGIN)); + *pgd = 0; + __flush_tlb_all(); +} + +void __init bt_ioremap_reset(void) +{ + enum fixed_addresses idx; + unsigned long *pte, phys, addr; + + after_paging_init = 1; + for (idx = FIX_BTMAP_BEGIN; idx <= FIX_BTMAP_END; idx--) { + addr = fix_to_virt(idx); + pte = bt_ioremap_pte(addr); + if (!*pte & _PAGE_PRESENT) { + phys = *pte & PAGE_MASK; + set_fixmap(idx, phys); + } + } +} + +static void __init __bt_set_fixmap(enum fixed_addresses idx, + unsigned long phys, pgprot_t flags) +{ + unsigned long *pte, addr = __fix_to_virt(idx); + + if (idx >= __end_of_fixed_addresses) { + BUG(); + return; + } + pte = bt_ioremap_pte(addr); + if (pgprot_val(flags)) + *pte = (phys & PAGE_MASK) | pgprot_val(flags); + else + *pte = 0; + __flush_tlb_one(addr); +} + +static inline void __init bt_set_fixmap(enum fixed_addresses idx, + unsigned long phys) +{ + if (after_paging_init) + set_fixmap(idx, phys); + else + __bt_set_fixmap(idx, phys, PAGE_KERNEL); +} + +static inline void __init bt_clear_fixmap(enum fixed_addresses idx) +{ + if (after_paging_init) + clear_fixmap(idx); + else + __bt_set_fixmap(idx, 0, __pgprot(0)); +} + void __init *bt_ioremap(unsigned long phys_addr, unsigned long size) { unsigned long offset, last_addr; @@ -244,7 +327,7 @@ void __init *bt_ioremap(unsigned long phys_addr, unsigned long size) */ idx = FIX_BTMAP_BEGIN; while (nrpages > 0) { - set_fixmap(idx, phys_addr); + bt_set_fixmap(idx, phys_addr); phys_addr += PAGE_SIZE; --idx; --nrpages; @@ -267,7 +350,7 @@ void __init bt_iounmap(void *addr, unsigned long size) idx = FIX_BTMAP_BEGIN; while (nrpages > 0) { - clear_fixmap(idx); + bt_clear_fixmap(idx); --idx; --nrpages; } |