Commit a85729c9 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] convert i386 to generic nopud header

i386 works with 2 and 3 levels
Signed-off-by: default avatarAndi Kleen <ak@suse.de>

Converted to use pud_t by Nick Piggin
Signed-off-by: default avatarNick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f1b32486
...@@ -137,6 +137,7 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs) ...@@ -137,6 +137,7 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
static void mark_screen_rdonly(struct task_struct * tsk) static void mark_screen_rdonly(struct task_struct * tsk)
{ {
pgd_t *pgd; pgd_t *pgd;
pud_t *pud;
pmd_t *pmd; pmd_t *pmd;
pte_t *pte, *mapped; pte_t *pte, *mapped;
int i; int i;
...@@ -151,7 +152,15 @@ static void mark_screen_rdonly(struct task_struct * tsk) ...@@ -151,7 +152,15 @@ static void mark_screen_rdonly(struct task_struct * tsk)
pgd_clear(pgd); pgd_clear(pgd);
goto out; goto out;
} }
pmd = pmd_offset(pgd, 0xA0000); pud = pud_offset(pgd, 0xA0000);
if (pud_none(*pud))
goto out;
if (pud_bad(*pud)) {
pud_ERROR(*pud);
pud_clear(pud);
goto out;
}
pmd = pmd_offset(pud, 0xA0000);
if (pmd_none(*pmd)) if (pmd_none(*pmd))
goto out; goto out;
if (pmd_bad(*pmd)) { if (pmd_bad(*pmd)) {
......
...@@ -518,6 +518,7 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -518,6 +518,7 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
int index = pgd_index(address); int index = pgd_index(address);
unsigned long pgd_paddr; unsigned long pgd_paddr;
pgd_t *pgd, *pgd_k; pgd_t *pgd, *pgd_k;
pud_t *pud, *pud_k;
pmd_t *pmd, *pmd_k; pmd_t *pmd, *pmd_k;
pte_t *pte_k; pte_t *pte_k;
...@@ -530,11 +531,17 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -530,11 +531,17 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
/* /*
* set_pgd(pgd, *pgd_k); here would be useless on PAE * set_pgd(pgd, *pgd_k); here would be useless on PAE
* and redundant with the set_pmd() on non-PAE. * and redundant with the set_pmd() on non-PAE. As would
* set_pud.
*/ */
pmd = pmd_offset(pgd, address); pud = pud_offset(pgd, address);
pmd_k = pmd_offset(pgd_k, address); pud_k = pud_offset(pgd_k, address);
if (!pud_present(*pud_k))
goto no_context;
pmd = pmd_offset(pud, address);
pmd_k = pmd_offset(pud_k, address);
if (!pmd_present(*pmd_k)) if (!pmd_present(*pmd_k))
goto no_context; goto no_context;
set_pmd(pmd, *pmd_k); set_pmd(pmd, *pmd_k);
......
...@@ -21,20 +21,24 @@ ...@@ -21,20 +21,24 @@
static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{ {
pgd_t *pgd; pgd_t *pgd;
pud_t *pud;
pmd_t *pmd = NULL; pmd_t *pmd = NULL;
pgd = pgd_offset(mm, addr); pgd = pgd_offset(mm, addr);
pmd = pmd_alloc(mm, pgd, addr); pud = pud_alloc(mm, pgd, addr);
pmd = pmd_alloc(mm, pud, addr);
return (pte_t *) pmd; return (pte_t *) pmd;
} }
static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{ {
pgd_t *pgd; pgd_t *pgd;
pud_t *pud;
pmd_t *pmd = NULL; pmd_t *pmd = NULL;
pgd = pgd_offset(mm, addr); pgd = pgd_offset(mm, addr);
pmd = pmd_offset(pgd, addr); pud = pud_offset(pgd, addr);
pmd = pmd_offset(pud, addr);
return (pte_t *) pmd; return (pte_t *) pmd;
} }
......
...@@ -54,15 +54,18 @@ static int noinline do_test_wp_bit(void); ...@@ -54,15 +54,18 @@ static int noinline do_test_wp_bit(void);
*/ */
static pmd_t * __init one_md_table_init(pgd_t *pgd) static pmd_t * __init one_md_table_init(pgd_t *pgd)
{ {
pud_t *pud;
pmd_t *pmd_table; pmd_t *pmd_table;
#ifdef CONFIG_X86_PAE #ifdef CONFIG_X86_PAE
pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
if (pmd_table != pmd_offset(pgd, 0)) pud = pud_offset(pgd, 0);
if (pmd_table != pmd_offset(pud, 0))
BUG(); BUG();
#else #else
pmd_table = pmd_offset(pgd, 0); pud = pud_offset(pgd, 0);
pmd_table = pmd_offset(pud, 0);
#endif #endif
return pmd_table; return pmd_table;
...@@ -100,6 +103,7 @@ static pte_t * __init one_page_table_init(pmd_t *pmd) ...@@ -100,6 +103,7 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base) static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
{ {
pgd_t *pgd; pgd_t *pgd;
pud_t *pud;
pmd_t *pmd; pmd_t *pmd;
int pgd_idx, pmd_idx; int pgd_idx, pmd_idx;
unsigned long vaddr; unsigned long vaddr;
...@@ -112,8 +116,8 @@ static void __init page_table_range_init (unsigned long start, unsigned long end ...@@ -112,8 +116,8 @@ static void __init page_table_range_init (unsigned long start, unsigned long end
for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) { for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
if (pgd_none(*pgd)) if (pgd_none(*pgd))
one_md_table_init(pgd); one_md_table_init(pgd);
pud = pud_offset(pgd, vaddr);
pmd = pmd_offset(pgd, vaddr); pmd = pmd_offset(pud, vaddr);
for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) { for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
if (pmd_none(*pmd)) if (pmd_none(*pmd))
one_page_table_init(pmd); one_page_table_init(pmd);
...@@ -233,7 +237,7 @@ EXPORT_SYMBOL(kmap_prot); ...@@ -233,7 +237,7 @@ EXPORT_SYMBOL(kmap_prot);
EXPORT_SYMBOL(kmap_pte); EXPORT_SYMBOL(kmap_pte);
#define kmap_get_fixmap_pte(vaddr) \ #define kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr))
void __init kmap_init(void) void __init kmap_init(void)
{ {
...@@ -249,6 +253,7 @@ void __init kmap_init(void) ...@@ -249,6 +253,7 @@ void __init kmap_init(void)
void __init permanent_kmaps_init(pgd_t *pgd_base) void __init permanent_kmaps_init(pgd_t *pgd_base)
{ {
pgd_t *pgd; pgd_t *pgd;
pud_t *pud;
pmd_t *pmd; pmd_t *pmd;
pte_t *pte; pte_t *pte;
unsigned long vaddr; unsigned long vaddr;
...@@ -257,7 +262,8 @@ void __init permanent_kmaps_init(pgd_t *pgd_base) ...@@ -257,7 +262,8 @@ void __init permanent_kmaps_init(pgd_t *pgd_base)
page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
pgd = swapper_pg_dir + pgd_index(vaddr); pgd = swapper_pg_dir + pgd_index(vaddr);
pmd = pmd_offset(pgd, vaddr); pud = pud_offset(pgd, vaddr);
pmd = pmd_offset(pud, vaddr);
pte = pte_offset_kernel(pmd, vaddr); pte = pte_offset_kernel(pmd, vaddr);
pkmap_page_table = pte; pkmap_page_table = pte;
} }
......
...@@ -80,9 +80,14 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr, ...@@ -80,9 +80,14 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
BUG(); BUG();
spin_lock(&init_mm.page_table_lock); spin_lock(&init_mm.page_table_lock);
do { do {
pud_t *pud;
pmd_t *pmd; pmd_t *pmd;
pmd = pmd_alloc(&init_mm, dir, address);
error = -ENOMEM; error = -ENOMEM;
pud = pud_alloc(&init_mm, dir, address);
if (!pud)
break;
pmd = pmd_alloc(&init_mm, pud, address);
if (!pmd) if (!pmd)
break; break;
if (remap_area_pmd(pmd, address, end - address, if (remap_area_pmd(pmd, address, end - address,
......
...@@ -20,10 +20,14 @@ static struct list_head df_list = LIST_HEAD_INIT(df_list); ...@@ -20,10 +20,14 @@ static struct list_head df_list = LIST_HEAD_INIT(df_list);
pte_t *lookup_address(unsigned long address) pte_t *lookup_address(unsigned long address)
{ {
pgd_t *pgd = pgd_offset_k(address); pgd_t *pgd = pgd_offset_k(address);
pud_t *pud;
pmd_t *pmd; pmd_t *pmd;
if (pgd_none(*pgd)) if (pgd_none(*pgd))
return NULL; return NULL;
pmd = pmd_offset(pgd, address); pud = pud_offset(pgd, address);
if (pud_none(*pud))
return NULL;
pmd = pmd_offset(pud, address);
if (pmd_none(*pmd)) if (pmd_none(*pmd))
return NULL; return NULL;
if (pmd_large(*pmd)) if (pmd_large(*pmd))
...@@ -77,9 +81,11 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte) ...@@ -77,9 +81,11 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
spin_lock_irqsave(&pgd_lock, flags); spin_lock_irqsave(&pgd_lock, flags);
for (page = pgd_list; page; page = (struct page *)page->index) { for (page = pgd_list; page; page = (struct page *)page->index) {
pgd_t *pgd; pgd_t *pgd;
pud_t *pud;
pmd_t *pmd; pmd_t *pmd;
pgd = (pgd_t *)page_address(page) + pgd_index(address); pgd = (pgd_t *)page_address(page) + pgd_index(address);
pmd = pmd_offset(pgd, address); pud = pud_offset(pgd, address);
pmd = pmd_offset(pud, address);
set_pte_atomic((pte_t *)pmd, pte); set_pte_atomic((pte_t *)pmd, pte);
} }
spin_unlock_irqrestore(&pgd_lock, flags); spin_unlock_irqrestore(&pgd_lock, flags);
...@@ -92,7 +98,7 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte) ...@@ -92,7 +98,7 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
static inline void revert_page(struct page *kpte_page, unsigned long address) static inline void revert_page(struct page *kpte_page, unsigned long address)
{ {
pte_t *linear = (pte_t *) pte_t *linear = (pte_t *)
pmd_offset(pgd_offset(&init_mm, address), address); pmd_offset(pud_offset(pgd_offset_k(address), address), address);
set_pmd_pte(linear, address, set_pmd_pte(linear, address,
pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT, pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT,
PAGE_KERNEL_LARGE)); PAGE_KERNEL_LARGE));
......
...@@ -62,6 +62,7 @@ void show_mem(void) ...@@ -62,6 +62,7 @@ void show_mem(void)
static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
{ {
pgd_t *pgd; pgd_t *pgd;
pud_t *pud;
pmd_t *pmd; pmd_t *pmd;
pte_t *pte; pte_t *pte;
...@@ -70,7 +71,12 @@ static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) ...@@ -70,7 +71,12 @@ static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
BUG(); BUG();
return; return;
} }
pmd = pmd_offset(pgd, vaddr); pud = pud_offset(pgd, vaddr);
if (pud_none(*pud)) {
BUG();
return;
}
pmd = pmd_offset(pud, vaddr);
if (pmd_none(*pmd)) { if (pmd_none(*pmd)) {
BUG(); BUG();
return; return;
...@@ -95,6 +101,7 @@ static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) ...@@ -95,6 +101,7 @@ static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
{ {
pgd_t *pgd; pgd_t *pgd;
pud_t *pud;
pmd_t *pmd; pmd_t *pmd;
if (vaddr & (PMD_SIZE-1)) { /* vaddr is misaligned */ if (vaddr & (PMD_SIZE-1)) { /* vaddr is misaligned */
...@@ -110,7 +117,8 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) ...@@ -110,7 +117,8 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
printk ("set_pmd_pfn: pgd_none\n"); printk ("set_pmd_pfn: pgd_none\n");
return; /* BUG(); */ return; /* BUG(); */
} }
pmd = pmd_offset(pgd, vaddr); pud = pud_offset(pgd, vaddr);
pmd = pmd_offset(pud, vaddr);
set_pmd(pmd, pfn_pmd(pfn, flags)); set_pmd(pmd, pfn_pmd(pfn, flags));
/* /*
* It's enough to flush this one mapping. * It's enough to flush this one mapping.
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
/* /*
* Allocate and free page tables. * Allocate and free page tables.
*/ */
extern pgd_t *pgd_alloc(struct mm_struct *); extern pgd_t *pgd_alloc(struct mm_struct *);
extern void pgd_free(pgd_t *pgd); extern void pgd_free(pgd_t *pgd);
...@@ -44,7 +43,7 @@ static inline void pte_free(struct page *pte) ...@@ -44,7 +43,7 @@ static inline void pte_free(struct page *pte)
#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) #define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
#define pmd_free(x) do { } while (0) #define pmd_free(x) do { } while (0)
#define __pmd_free_tlb(tlb,x) do { } while (0) #define __pmd_free_tlb(tlb,x) do { } while (0)
#define pgd_populate(mm, pmd, pte) BUG() #define pud_populate(mm, pmd, pte) BUG()
#endif #endif
#define check_pgt_cache() do { } while (0) #define check_pgt_cache() do { } while (0)
......
#ifndef _I386_PGTABLE_3LEVEL_H #ifndef _I386_PGTABLE_3LEVEL_H
#define _I386_PGTABLE_3LEVEL_H #define _I386_PGTABLE_3LEVEL_H
#include <asm-generic/pgtable-nopud.h>
/* /*
* Intel Physical Address Extension (PAE) Mode - three-level page * Intel Physical Address Extension (PAE) Mode - three-level page
* tables on PPro+ CPUs. * tables on PPro+ CPUs.
...@@ -15,9 +17,9 @@ ...@@ -15,9 +17,9 @@
#define pgd_ERROR(e) \ #define pgd_ERROR(e) \
printk("%s:%d: bad pgd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pgd_val(e)) printk("%s:%d: bad pgd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
static inline int pgd_none(pgd_t pgd) { return 0; } #define pud_none(pud) 0
static inline int pgd_bad(pgd_t pgd) { return 0; } #define pud_bad(pud) 0
static inline int pgd_present(pgd_t pgd) { return 1; } #define pud_present(pud) 1
/* /*
* Is the pte executable? * Is the pte executable?
...@@ -59,8 +61,8 @@ static inline void set_pte(pte_t *ptep, pte_t pte) ...@@ -59,8 +61,8 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
set_64bit((unsigned long long *)(pteptr),pte_val(pteval)) set_64bit((unsigned long long *)(pteptr),pte_val(pteval))
#define set_pmd(pmdptr,pmdval) \ #define set_pmd(pmdptr,pmdval) \
set_64bit((unsigned long long *)(pmdptr),pmd_val(pmdval)) set_64bit((unsigned long long *)(pmdptr),pmd_val(pmdval))
#define set_pgd(pgdptr,pgdval) \ #define set_pud(pudptr,pudval) \
set_64bit((unsigned long long *)(pgdptr),pgd_val(pgdval)) set_64bit((unsigned long long *)(pudptr),pud_val(pudval))
/* /*
* Pentium-II erratum A13: in PAE mode we explicitly have to flush * Pentium-II erratum A13: in PAE mode we explicitly have to flush
...@@ -68,22 +70,22 @@ static inline void set_pte(pte_t *ptep, pte_t pte) ...@@ -68,22 +70,22 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
* We do not let the generic code free and clear pgd entries due to * We do not let the generic code free and clear pgd entries due to
* this erratum. * this erratum.
*/ */
static inline void pgd_clear (pgd_t * pgd) { } static inline void pud_clear (pud_t * pud) { }
#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
#define pmd_page_kernel(pmd) \ #define pmd_page_kernel(pmd) \
((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
#define pgd_page(pgd) \ #define pud_page(pud) \
((struct page *) __va(pgd_val(pgd) & PAGE_MASK)) ((struct page *) __va(pud_val(pud) & PAGE_MASK))
#define pgd_page_kernel(pgd) \ #define pud_page_kernel(pud) \
((unsigned long) __va(pgd_val(pgd) & PAGE_MASK)) ((unsigned long) __va(pud_val(pud) & PAGE_MASK))
/* Find an entry in the second-level page table.. */ /* Find an entry in the second-level page table.. */
#define pmd_offset(dir, address) ((pmd_t *) pgd_page(*(dir)) + \ #define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
pmd_index(address)) pmd_index(address))
static inline pte_t ptep_get_and_clear(pte_t *ptep) static inline pte_t ptep_get_and_clear(pte_t *ptep)
......
...@@ -303,6 +303,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) ...@@ -303,6 +303,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
* control the given virtual address * control the given virtual address
*/ */
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
#define pgd_index_k(addr) pgd_index(addr)
/* /*
* pgd_offset() returns a (pgd_t *) * pgd_offset() returns a (pgd_t *)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment