From: Jeff Dike This adds pud_t support to UML. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton --- 25-akpm/arch/um/kernel/mem.c | 3 +- 25-akpm/arch/um/kernel/process_kern.c | 12 ++++++++++- 25-akpm/arch/um/kernel/skas/tlb.c | 7 ++++-- 25-akpm/arch/um/kernel/tlb.c | 16 +++++++++++---- 25-akpm/arch/um/kernel/trap_kern.c | 7 ++++-- 25-akpm/arch/um/kernel/tt/tlb.c | 12 ++++++++--- 25-akpm/include/asm-um/pgalloc.h | 14 +++++++------ 25-akpm/include/asm-um/pgtable.h | 35 ++++++++++++++++++++-------------- 8 files changed, 73 insertions(+), 33 deletions(-) diff -puN arch/um/kernel/mem.c~uml-add-some-pudding arch/um/kernel/mem.c --- 25/arch/um/kernel/mem.c~uml-add-some-pudding 2005-01-09 23:44:00.119145376 -0800 +++ 25-akpm/arch/um/kernel/mem.c 2005-01-09 23:44:00.132143400 -0800 @@ -135,7 +135,8 @@ pte_t *kmap_pte; pgprot_t kmap_prot; #define kmap_get_fixmap_pte(vaddr) \ - pte_offset(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) { diff -puN arch/um/kernel/process_kern.c~uml-add-some-pudding arch/um/kernel/process_kern.c --- 25/arch/um/kernel/process_kern.c~uml-add-some-pudding 2005-01-09 23:44:00.120145224 -0800 +++ 25-akpm/arch/um/kernel/process_kern.c 2005-01-09 23:44:00.133143248 -0800 @@ -235,18 +235,28 @@ void *um_virt_to_phys(struct task_struct pte_t *pte_out) { pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; if(task->mm == NULL) return(ERR_PTR(-EINVAL)); pgd = pgd_offset(task->mm, addr); - pmd = pmd_offset(pgd, addr); + if(!pgd_present(*pgd)) + return(ERR_PTR(-EINVAL)); + + pud = pud_offset(pgd, addr); + if(!pud_present(*pud)) + return(ERR_PTR(-EINVAL)); + + pmd = pmd_offset(pud, addr); if(!pmd_present(*pmd)) return(ERR_PTR(-EINVAL)); + pte = pte_offset_kernel(pmd, addr); if(!pte_present(*pte)) return(ERR_PTR(-EINVAL)); + if(pte_out != NULL) *pte_out = *pte; return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK)); diff -puN arch/um/kernel/skas/tlb.c~uml-add-some-pudding arch/um/kernel/skas/tlb.c --- 25/arch/um/kernel/skas/tlb.c~uml-add-some-pudding 2005-01-09 23:44:00.122144920 -0800 +++ 25-akpm/arch/um/kernel/skas/tlb.c 2005-01-09 23:44:00.133143248 -0800 @@ -18,6 +18,7 @@ static void fix_range(struct mm_struct * unsigned long end_addr, int force) { pgd_t *npgd; + pmd_t *npud; pmd_t *npmd; pte_t *npte; unsigned long addr; @@ -27,7 +28,8 @@ static void fix_range(struct mm_struct * fd = mm->context.skas.mm_fd; for(addr = start_addr; addr < end_addr;){ npgd = pgd_offset(mm, addr); - npmd = pmd_offset(npgd, addr); + npud = pud_offset(npgd, addr); + npmd = pmd_offset(npud, addr); if(pmd_present(*npmd)){ npte = pte_offset_kernel(npmd, addr); r = pte_read(*npte); @@ -79,7 +81,8 @@ void flush_tlb_kernel_range_skas(unsigne mm = &init_mm; for(addr = start; addr < end;){ pgd = pgd_offset(mm, addr); - pmd = pmd_offset(pgd, addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); if(pmd_present(*pmd)){ pte = pte_offset_kernel(pmd, addr); if(!pte_present(*pte) || pte_newpage(*pte)){ diff -puN arch/um/kernel/tlb.c~uml-add-some-pudding arch/um/kernel/tlb.c --- 25/arch/um/kernel/tlb.c~uml-add-some-pudding 2005-01-09 23:44:00.123144768 -0800 +++ 25-akpm/arch/um/kernel/tlb.c 2005-01-09 23:44:00.134143096 -0800 @@ -59,9 +59,14 @@ pgd_t *pgd_offset_proc(struct mm_struct return(pgd_offset(mm, address)); } -pmd_t *pmd_offset_proc(pgd_t *pgd, unsigned long address) +pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) { - return(pmd_offset(pgd, address)); + return(pud_offset(pgd, address)); +} + +pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) +{ + return(pmd_offset(pud, address)); } pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) @@ -71,8 +76,11 @@ pte_t *pte_offset_proc(pmd_t *pmd, unsig pte_t *addr_pte(struct task_struct *task, unsigned long addr) { - return(pte_offset_kernel(pmd_offset(pgd_offset(task->mm, addr), addr), - addr)); + pgd_t *pgd = pgd_offset(task->mm, addr); + pud_t *pud = pud_offset(pgd, addr); + pmd_t *pmd = pmd_offset(pud, addr); + + return(pte_offset_map(pmd, addr)); } /* diff -puN arch/um/kernel/trap_kern.c~uml-add-some-pudding arch/um/kernel/trap_kern.c --- 25/arch/um/kernel/trap_kern.c~uml-add-some-pudding 2005-01-09 23:44:00.125144464 -0800 +++ 25-akpm/arch/um/kernel/trap_kern.c 2005-01-09 23:44:00.135142944 -0800 @@ -13,6 +13,7 @@ #include "linux/ptrace.h" #include "asm/semaphore.h" #include "asm/pgtable.h" +#include "asm/pgalloc.h" #include "asm/tlbflush.h" #include "asm/a.out.h" #include "asm/current.h" @@ -32,6 +33,7 @@ int handle_page_fault(unsigned long addr struct mm_struct *mm = current->mm; struct vm_area_struct *vma; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; unsigned long page; @@ -54,8 +56,9 @@ int handle_page_fault(unsigned long addr if(is_write && !(vma->vm_flags & VM_WRITE)) goto out; page = address & PAGE_MASK; - pgd = pgd_offset(mm, page); - pmd = pmd_offset(pgd, page); + pgd = pgd_offset(mm); + pud = pud_offset(pgd, page); + pmd = pmd_offset(pud, page); do { survive: switch (handle_mm_fault(mm, vma, address, is_write)){ diff -puN arch/um/kernel/tt/tlb.c~uml-add-some-pudding arch/um/kernel/tt/tlb.c --- 25/arch/um/kernel/tt/tlb.c~uml-add-some-pudding 2005-01-09 23:44:00.126144312 -0800 +++ 25-akpm/arch/um/kernel/tt/tlb.c 2005-01-09 23:44:00.135142944 -0800 @@ -19,6 +19,7 @@ static void fix_range(struct mm_struct * unsigned long end_addr, int force) { pgd_t *npgd; + pud_t *npud; pmd_t *npmd; pte_t *npte; unsigned long addr; @@ -42,7 +43,8 @@ static void fix_range(struct mm_struct * continue; } npgd = pgd_offset(mm, addr); - npmd = pmd_offset(npgd, addr); + npud = pud_offset(npgd, addr); + npmd = pmd_offset(npud, addr); if(pmd_present(*npmd)){ npte = pte_offset_kernel(npmd, addr); r = pte_read(*npte); @@ -90,6 +92,7 @@ static void flush_kernel_vm_range(unsign { struct mm_struct *mm; pgd_t *pgd; + pud_t *pmd; pmd_t *pmd; pte_t *pte; unsigned long addr; @@ -98,7 +101,8 @@ static void flush_kernel_vm_range(unsign mm = &init_mm; for(addr = start; addr < end;){ pgd = pgd_offset(mm, addr); - pmd = pmd_offset(pgd, addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); if(pmd_present(*pmd)){ pte = pte_offset_kernel(pmd, addr); if(!pte_present(*pte) || pte_newpage(*pte)){ @@ -155,6 +159,7 @@ void mprotect_kernel_vm(int w) { struct mm_struct *mm; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; unsigned long addr; @@ -162,7 +167,8 @@ void mprotect_kernel_vm(int w) mm = &init_mm; for(addr = start_vm; addr < end_vm;){ pgd = pgd_offset(mm, addr); - pmd = pmd_offset(pgd, addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); if(pmd_present(*pmd)){ pte = pte_offset_kernel(pmd, addr); if(pte_present(*pte)) protect_vm_page(addr, w, 0); diff -puN include/asm-um/pgalloc.h~uml-add-some-pudding include/asm-um/pgalloc.h --- 25/include/asm-um/pgalloc.h~uml-add-some-pudding 2005-01-09 23:44:00.127144160 -0800 +++ 25-akpm/include/asm-um/pgalloc.h 2005-01-09 23:44:00.136142792 -0800 @@ -13,12 +13,14 @@ #define pmd_populate_kernel(mm, pmd, pte) \ set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte))) -static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, - struct page *pte) -{ - set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte))); -} +#define pmd_populate(mm, pmd, pte) \ + set_pmd(pmd, __pmd(_PAGE_TABLE + \ + ((unsigned long long)page_to_pfn(pte) << \ + (unsigned long long) PAGE_SHIFT))) +/* + * Allocate and free page tables. + */ extern pgd_t *pgd_alloc(struct mm_struct *); extern void pgd_free(pgd_t *pgd); @@ -45,7 +47,7 @@ static inline void pte_free(struct page #define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) #define pmd_free(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() #define check_pgt_cache() do { } while (0) diff -puN include/asm-um/pgtable.h~uml-add-some-pudding include/asm-um/pgtable.h --- 25/include/asm-um/pgtable.h~uml-add-some-pudding 2005-01-09 23:44:00.129143856 -0800 +++ 25-akpm/include/asm-um/pgtable.h 2005-01-09 23:44:00.137142640 -0800 @@ -7,8 +7,6 @@ #ifndef __UM_PGTABLE_H #define __UM_PGTABLE_H -#include - #include "linux/sched.h" #include "asm/processor.h" #include "asm/page.h" @@ -23,7 +21,6 @@ extern unsigned long *empty_zero_page; #define pgtable_cache_init() do ; while (0) /* PMD_SHIFT determines the size of the area a second-level page table can map */ -#define PMD_SHIFT 22 #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) @@ -39,7 +36,6 @@ extern unsigned long *empty_zero_page; #define PTRS_PER_PTE 1024 #define PTRS_PER_PMD 1 #define PTRS_PER_PGD 1024 -#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) #define FIRST_USER_PGD_NR 0 #define pte_ERROR(e) \ @@ -176,6 +172,15 @@ extern pte_t * __bad_pagetable(void); #define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE) #define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE) +#define pud_newpage(x) (pud_val(x) & _PAGE_NEWPAGE) +#define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEWPAGE) + +static inline pud_t *__pud_alloc(struct mm_struct *mm, pgd_t *pgd, + unsigned long addr) +{ + BUG(); +} + /* * The "pgd_xxx()" functions here are trivial for a folded two-level * setup: the pgd is never bad, and a pmd always exists (as it's folded @@ -374,15 +379,15 @@ static inline pte_t pte_modify(pte_t pte * this macro returns the index of the entry in the pgd page which would * 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_index() is used get the offset into the pgd page's array of pgd_t's; */ -#define pgd_offset(mm, address) \ -((mm)->pgd + ((address) >> PGDIR_SHIFT)) - +#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) /* * a shortcut which implies the use of the kernel's pgd, instead @@ -390,15 +395,15 @@ static inline pte_t pte_modify(pte_t pte */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) +/* + * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD] + * + * this macro returns the index of the entry in the pmd page which would + * control the given virtual address + */ #define pmd_index(address) \ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) -/* Find an entry in the second-level page table.. */ -static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) -{ - return (pmd_t *) dir; -} - /* * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] * @@ -430,6 +435,8 @@ static inline pmd_t * pmd_offset(pgd_t * #include +#include + #endif #endif _