x86: construct 32-bit boot time page tables in native format.
Specifically the boot time page tables in a CONFIG_X86_PAE=y enabled kernel are in PAE format. early_ioremap is updated to use the standard page table accessors. Clear any mappings beyond max_low_pfn from the boot page tables in native_pagetable_setup_start because the initial mappings can extend beyond the range of physical memory and into the vmalloc area. Derived from patches by Eric Biederman and H. Peter Anvin. [ jeremy@goop.org: PAE swapper_pg_dir needs to be page-sized fix ] Signed-off-by: Ian Campbell <ijc@hellion.org.uk> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Mika Penttilä <mika.penttila@kolumbus.fi> Cc: Jeremy Fitzhardinge <jeremy@goop.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
committed by
Thomas Gleixner
parent
185c045c24
commit
551889a6e2
@@ -260,41 +260,46 @@ static int __init early_ioremap_debug_setup(char *str)
|
||||
early_param("early_ioremap_debug", early_ioremap_debug_setup);
|
||||
|
||||
static __initdata int after_paging_init;
|
||||
static __initdata unsigned long bm_pte[1024]
|
||||
static __initdata pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)]
|
||||
__attribute__((aligned(PAGE_SIZE)));
|
||||
|
||||
static inline unsigned long * __init early_ioremap_pgd(unsigned long addr)
|
||||
static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
|
||||
{
|
||||
return (unsigned long *)swapper_pg_dir + ((addr >> 22) & 1023);
|
||||
pgd_t *pgd = &swapper_pg_dir[pgd_index(addr)];
|
||||
pud_t *pud = pud_offset(pgd, addr);
|
||||
pmd_t *pmd = pmd_offset(pud, addr);
|
||||
|
||||
return pmd;
|
||||
}
|
||||
|
||||
static inline unsigned long * __init early_ioremap_pte(unsigned long addr)
|
||||
static inline pte_t * __init early_ioremap_pte(unsigned long addr)
|
||||
{
|
||||
return bm_pte + ((addr >> PAGE_SHIFT) & 1023);
|
||||
return &bm_pte[pte_index(addr)];
|
||||
}
|
||||
|
||||
void __init early_ioremap_init(void)
|
||||
{
|
||||
unsigned long *pgd;
|
||||
pmd_t *pmd;
|
||||
|
||||
if (early_ioremap_debug)
|
||||
printk(KERN_INFO "early_ioremap_init()\n");
|
||||
|
||||
pgd = early_ioremap_pgd(fix_to_virt(FIX_BTMAP_BEGIN));
|
||||
*pgd = __pa(bm_pte) | _PAGE_TABLE;
|
||||
pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
|
||||
memset(bm_pte, 0, sizeof(bm_pte));
|
||||
set_pmd(pmd, __pmd(__pa(bm_pte) | _PAGE_TABLE));
|
||||
|
||||
/*
|
||||
* The boot-ioremap range spans multiple pgds, for which
|
||||
* The boot-ioremap range spans multiple pmds, for which
|
||||
* we are not prepared:
|
||||
*/
|
||||
if (pgd != early_ioremap_pgd(fix_to_virt(FIX_BTMAP_END))) {
|
||||
if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
|
||||
WARN_ON(1);
|
||||
printk(KERN_WARNING "pgd %p != %p\n",
|
||||
pgd, early_ioremap_pgd(fix_to_virt(FIX_BTMAP_END)));
|
||||
printk(KERN_WARNING "pmd %p != %p\n",
|
||||
pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
|
||||
printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
|
||||
fix_to_virt(FIX_BTMAP_BEGIN));
|
||||
fix_to_virt(FIX_BTMAP_BEGIN));
|
||||
printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_END): %08lx\n",
|
||||
fix_to_virt(FIX_BTMAP_END));
|
||||
fix_to_virt(FIX_BTMAP_END));
|
||||
|
||||
printk(KERN_WARNING "FIX_BTMAP_END: %d\n", FIX_BTMAP_END);
|
||||
printk(KERN_WARNING "FIX_BTMAP_BEGIN: %d\n",
|
||||
@@ -304,28 +309,29 @@ void __init early_ioremap_init(void)
|
||||
|
||||
void __init early_ioremap_clear(void)
|
||||
{
|
||||
unsigned long *pgd;
|
||||
pmd_t *pmd;
|
||||
|
||||
if (early_ioremap_debug)
|
||||
printk(KERN_INFO "early_ioremap_clear()\n");
|
||||
|
||||
pgd = early_ioremap_pgd(fix_to_virt(FIX_BTMAP_BEGIN));
|
||||
*pgd = 0;
|
||||
paravirt_release_pt(__pa(pgd) >> PAGE_SHIFT);
|
||||
pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
|
||||
pmd_clear(pmd);
|
||||
paravirt_release_pt(__pa(pmd) >> PAGE_SHIFT);
|
||||
__flush_tlb_all();
|
||||
}
|
||||
|
||||
void __init early_ioremap_reset(void)
|
||||
{
|
||||
enum fixed_addresses idx;
|
||||
unsigned long *pte, phys, addr;
|
||||
unsigned long addr, phys;
|
||||
pte_t *pte;
|
||||
|
||||
after_paging_init = 1;
|
||||
for (idx = FIX_BTMAP_BEGIN; idx >= FIX_BTMAP_END; idx--) {
|
||||
addr = fix_to_virt(idx);
|
||||
pte = early_ioremap_pte(addr);
|
||||
if (*pte & _PAGE_PRESENT) {
|
||||
phys = *pte & PAGE_MASK;
|
||||
if (pte_present(*pte)) {
|
||||
phys = pte_val(*pte) & PAGE_MASK;
|
||||
set_fixmap(idx, phys);
|
||||
}
|
||||
}
|
||||
@@ -334,7 +340,8 @@ void __init early_ioremap_reset(void)
|
||||
static void __init __early_set_fixmap(enum fixed_addresses idx,
|
||||
unsigned long phys, pgprot_t flags)
|
||||
{
|
||||
unsigned long *pte, addr = __fix_to_virt(idx);
|
||||
unsigned long addr = __fix_to_virt(idx);
|
||||
pte_t *pte;
|
||||
|
||||
if (idx >= __end_of_fixed_addresses) {
|
||||
BUG();
|
||||
@@ -342,9 +349,9 @@ static void __init __early_set_fixmap(enum fixed_addresses idx,
|
||||
}
|
||||
pte = early_ioremap_pte(addr);
|
||||
if (pgprot_val(flags))
|
||||
*pte = (phys & PAGE_MASK) | pgprot_val(flags);
|
||||
set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
|
||||
else
|
||||
*pte = 0;
|
||||
pte_clear(NULL, addr, pte);
|
||||
__flush_tlb_one(addr);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user