From: Andi Kleen ppc32 works with 2 levels (thanks to hch, Mikael P. for testing) Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton --- 25-akpm/arch/ppc/kernel/asm-offsets.c | 2 +- 25-akpm/arch/ppc/kernel/dma-mapping.c | 3 ++- 25-akpm/arch/ppc/mm/4xx_mmu.c | 4 ++-- 25-akpm/arch/ppc/mm/fault.c | 8 +++++--- 25-akpm/arch/ppc/mm/init.c | 22 ++++++++++++++++------ 25-akpm/arch/ppc/mm/pgtable.c | 7 ++++--- 25-akpm/arch/ppc/mm/tlb.c | 5 +++-- 25-akpm/arch/ppc/platforms/apus_setup.c | 2 +- 25-akpm/arch/ppc/platforms/pmac_cpufreq.c | 2 +- 25-akpm/drivers/macintosh/via-pmu.c | 4 ++-- 25-akpm/include/asm-ppc/mmu_context.h | 4 ++-- 25-akpm/include/asm-ppc/page.h | 2 ++ 25-akpm/include/asm-ppc/pgalloc.h | 3 ++- 25-akpm/include/asm-ppc/pgtable.h | 7 +++---- 14 files changed, 46 insertions(+), 29 deletions(-) diff -puN arch/ppc/kernel/asm-offsets.c~4level-architecture-changes-for-ppc arch/ppc/kernel/asm-offsets.c --- 25/arch/ppc/kernel/asm-offsets.c~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.636450688 -0800 +++ 25-akpm/arch/ppc/kernel/asm-offsets.c 2004-11-30 01:08:20.658447344 -0800 @@ -120,7 +120,7 @@ main(void) DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); DEFINE(CLONE_VM, CLONE_VM); DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); - DEFINE(MM_PGD, offsetof(struct mm_struct, pgd)); + DEFINE(MM_PGD, offsetof(struct mm_struct, pml4)); /* About the CPU features table */ DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec)); diff -puN arch/ppc/kernel/dma-mapping.c~4level-architecture-changes-for-ppc arch/ppc/kernel/dma-mapping.c --- 25/arch/ppc/kernel/dma-mapping.c~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.637450536 -0800 +++ 25-akpm/arch/ppc/kernel/dma-mapping.c 2004-11-30 01:08:20.658447344 -0800 @@ -333,7 +333,8 @@ static int __init dma_alloc_init(void) spin_lock(&init_mm.page_table_lock); do { - pgd = pgd_offset(&init_mm, CONSISTENT_BASE); + pgd = pml4_pgd_offset(pml4_offset_k(CONSISTENT_BASE), + CONSISTENT_BASE); pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE); if (!pmd) { printk(KERN_ERR "%s: no pmd tables\n", __func__); diff -puN arch/ppc/mm/4xx_mmu.c~4level-architecture-changes-for-ppc arch/ppc/mm/4xx_mmu.c --- 25/arch/ppc/mm/4xx_mmu.c~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.639450232 -0800 +++ 25-akpm/arch/ppc/mm/4xx_mmu.c 2004-11-30 01:08:20.659447192 -0800 @@ -112,7 +112,7 @@ unsigned long __init mmu_mapin_ram(void) unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE; spin_lock(&init_mm.page_table_lock); - pmdp = pmd_offset(pgd_offset_k(v), v); + pmdp = pmd_offset(pml4_pgd_offset(pml4_offset_k(v), v), v); pmd_val(*pmdp++) = val; pmd_val(*pmdp++) = val; pmd_val(*pmdp++) = val; @@ -129,7 +129,7 @@ unsigned long __init mmu_mapin_ram(void) unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE; spin_lock(&init_mm.page_table_lock); - pmdp = pmd_offset(pgd_offset_k(v), v); + pmdp = pmd_offset(pml4_pgd_offset(pml4_offset_k(v), v), v); pmd_val(*pmdp) = val; spin_unlock(&init_mm.page_table_lock); diff -puN arch/ppc/mm/fault.c~4level-architecture-changes-for-ppc arch/ppc/mm/fault.c --- 25/arch/ppc/mm/fault.c~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.640450080 -0800 +++ 25-akpm/arch/ppc/mm/fault.c 2004-11-30 01:08:20.659447192 -0800 @@ -354,7 +354,7 @@ pte_t *va_to_pte(unsigned long address) if (address < TASK_SIZE) return NULL; - dir = pgd_offset(&init_mm, address); + dir = pml4_pgd_offset(pml4_offset_k(address), address); if (dir) { pmd = pmd_offset(dir, address & PAGE_MASK); if (pmd && pmd_present(*pmd)) { @@ -384,7 +384,8 @@ print_8xx_pte(struct mm_struct *mm, unsi pte_t * pte; printk(" pte @ 0x%8lx: ", addr); - pgd = pgd_offset(mm, addr & PAGE_MASK); + pgd = pml4_pgd_offset(pml4_offset(mm, addr & PAGE_MASK), + addr & PAGE_MASK); if (pgd) { pmd = pmd_offset(pgd, addr & PAGE_MASK); if (pmd && pmd_present(*pmd)) { @@ -425,7 +426,8 @@ get_8xx_pte(struct mm_struct *mm, unsign pte_t * pte; int retval = 0; - pgd = pgd_offset(mm, addr & PAGE_MASK); + pgd = pml4_pgd_offset(pml4_offset(mm, addr & PAGE_MASK), + addr & PAGE_MASK); if (pgd) { pmd = pmd_offset(pgd, addr & PAGE_MASK); if (pmd && pmd_present(*pmd)) { diff -puN arch/ppc/mm/init.c~4level-architecture-changes-for-ppc arch/ppc/mm/init.c --- 25/arch/ppc/mm/init.c~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.642449776 -0800 +++ 25-akpm/arch/ppc/mm/init.c 2004-11-30 01:08:20.660447040 -0800 @@ -378,12 +378,20 @@ void __init paging_init(void) unsigned long zones_size[MAX_NR_ZONES], i; #ifdef CONFIG_HIGHMEM + pml4_t *pml4; + pgd_t *pgd; + pmd_t *pmd; map_page(PKMAP_BASE, 0, 0); /* XXX gross */ - pkmap_page_table = pte_offset_kernel(pmd_offset(pgd_offset_k - (PKMAP_BASE), PKMAP_BASE), PKMAP_BASE); + + pml4 = pml4_offset_k(PKMAP_BASE); + pgd = pml4_pgd_offset(pml4, PKMAP_BASE); + pmd = pgd_offset(pgd, PKMAP_BASE); + pkmap_page_table = pte_offset_kernel(pmd, PKMAP_BASE); map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */ - kmap_pte = pte_offset_kernel(pmd_offset(pgd_offset_k - (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN); + pml4 = pml4_offset_k(KMAP_FIX_BEGIN); + pgd = pml4_pgd_offset(pml4, KMAP_FIX_BEGIN); + pmd = pmd_offset(pgd, KMAP_FIX_BEGIN); + kmap_pte = pte_offset_kernel(pmd, KMAP_FIX_BEGIN); kmap_prot = PAGE_KERNEL; #endif /* CONFIG_HIGHMEM */ @@ -494,7 +502,8 @@ void __init mem_init(void) and page->index set correctly. */ for (addr = KERNELBASE; addr != 0; addr += PGDIR_SIZE) { struct page *pg; - pmd_t *pmd = pmd_offset(pgd_offset_k(addr), addr); + pmd_t *pmd = pmd_offset(pml4_pgd_offset( + pml4_offset_k(addr), addr), addr); if (pmd_present(*pmd)) { pg = pmd_page(*pmd); pg->mapping = (void *) &init_mm; @@ -647,7 +656,8 @@ void update_mmu_cache(struct vm_area_str pmd_t *pmd; mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm; - pmd = pmd_offset(pgd_offset(mm, address), address); + pmd = pmd_offset(pml4_pgd_offset(pml4_offset(mm, address), + address), address); if (!pmd_none(*pmd)) add_hash_page(mm->context, address, pmd_val(*pmd)); } diff -puN arch/ppc/mm/pgtable.c~4level-architecture-changes-for-ppc arch/ppc/mm/pgtable.c --- 25/arch/ppc/mm/pgtable.c~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.643449624 -0800 +++ 25-akpm/arch/ppc/mm/pgtable.c 2004-11-30 01:08:20.661446888 -0800 @@ -81,7 +81,7 @@ extern unsigned long p_mapped_by_tlbcam( #define PGDIR_ORDER 0 #endif -pgd_t *pgd_alloc(struct mm_struct *mm) +pgd_t *__pgd_alloc(struct mm_struct *mm, pml4_t *pml4, unsigned long addr) { pgd_t *ret; @@ -293,7 +293,7 @@ map_page(unsigned long va, phys_addr_t p spin_lock(&init_mm.page_table_lock); /* Use upper 10 bits of VA to index the first level map */ - pd = pmd_offset(pgd_offset_k(va), va); + pd = pmd_offset(pml4_pgd_offset(pml4_offset_k(va), va), va); /* Use middle 10 bits of VA to index the second-level map */ pg = pte_alloc_kernel(&init_mm, pd, va); if (pg != 0) { @@ -388,7 +388,8 @@ get_pteptr(struct mm_struct *mm, unsigne pte_t *pte; int retval = 0; - pgd = pgd_offset(mm, addr & PAGE_MASK); + pgd = pml4_pgd_offset(pml4_offset(mm, addr & PAGE_MASK), + addr & PAGE_MASK); if (pgd) { pmd = pmd_offset(pgd, addr & PAGE_MASK); if (pmd_present(*pmd)) { diff -puN arch/ppc/mm/tlb.c~4level-architecture-changes-for-ppc arch/ppc/mm/tlb.c --- 25/arch/ppc/mm/tlb.c~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.645449320 -0800 +++ 25-akpm/arch/ppc/mm/tlb.c 2004-11-30 01:08:20.661446888 -0800 @@ -132,7 +132,7 @@ static void flush_range(struct mm_struct if (start >= end) return; end = (end - 1) | ~PAGE_MASK; - pmd = pmd_offset(pgd_offset(mm, start), start); + pmd = pmd_offset(pml4_pgd_offset(pml4_offset(mm, start), start),start); for (;;) { pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1; if (pmd_end > end) @@ -184,7 +184,8 @@ void flush_tlb_page(struct vm_area_struc return; } mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; - pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr); + pmd = pmd_offset(pml4_pgd_offset(pml4_offset(mm, vmaddr), vmaddr), + vmaddr); if (!pmd_none(*pmd)) flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1); FINISH_FLUSH; diff -puN arch/ppc/platforms/apus_setup.c~4level-architecture-changes-for-ppc arch/ppc/platforms/apus_setup.c --- 25/arch/ppc/platforms/apus_setup.c~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.646449168 -0800 +++ 25-akpm/arch/ppc/platforms/apus_setup.c 2004-11-30 01:08:20.662446736 -0800 @@ -329,7 +329,7 @@ static __inline__ pte_t *my_find_pte(str va &= PAGE_MASK; - dir = pgd_offset( mm, va ); + dir = pml4_pgd_offset(pml4_offset( mm, va ), va); if (dir) { pmd = pmd_offset(dir, va & PAGE_MASK); diff -puN arch/ppc/platforms/pmac_cpufreq.c~4level-architecture-changes-for-ppc arch/ppc/platforms/pmac_cpufreq.c --- 25/arch/ppc/platforms/pmac_cpufreq.c~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.647449016 -0800 +++ 25-akpm/arch/ppc/platforms/pmac_cpufreq.c 2004-11-30 01:08:20.663446584 -0800 @@ -260,7 +260,7 @@ static int __pmac pmu_set_cpu_speed(int _set_L3CR(save_l3cr); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context, (pgd_t *)current->active_mm->pml4); #ifdef DEBUG_FREQ printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); diff -puN drivers/macintosh/via-pmu.c~4level-architecture-changes-for-ppc drivers/macintosh/via-pmu.c --- 25/drivers/macintosh/via-pmu.c~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.649448712 -0800 +++ 25-akpm/drivers/macintosh/via-pmu.c 2004-11-30 01:08:20.665446280 -0800 @@ -2504,7 +2504,7 @@ powerbook_sleep_grackle(void) _set_L2CR(save_l2cr); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context, (pml4_t *)current->active_mm->pml4); /* Power things up */ pmu_unlock(); @@ -2604,7 +2604,7 @@ powerbook_sleep_Core99(void) _set_L3CR(save_l3cr); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context, (pgd_t *)current->active_mm->pml4); /* Tell PMU we are ready */ pmu_unlock(); diff -puN include/asm-ppc/mmu_context.h~4level-architecture-changes-for-ppc include/asm-ppc/mmu_context.h --- 25/include/asm-ppc/mmu_context.h~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.650448560 -0800 +++ 25-akpm/include/asm-ppc/mmu_context.h 2004-11-30 01:08:20.666446128 -0800 @@ -172,7 +172,7 @@ static inline void switch_mm(struct mm_s : : ); #endif /* CONFIG_ALTIVEC */ - tsk->thread.pgdir = next->pgd; + tsk->thread.pgdir = (pgd_t *)next->pml4; /* No need to flush userspace segments if the mm doesnt change */ if (prev == next) @@ -180,7 +180,7 @@ static inline void switch_mm(struct mm_s /* Setup new userspace context */ get_mmu_context(next); - set_context(next->context, next->pgd); + set_context(next->context, (pgd_t *)next->pml4); } #define deactivate_mm(tsk,mm) do { } while (0) diff -puN include/asm-ppc/page.h~4level-architecture-changes-for-ppc include/asm-ppc/page.h --- 25/include/asm-ppc/page.h~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.652448256 -0800 +++ 25-akpm/include/asm-ppc/page.h 2004-11-30 01:08:20.666446128 -0800 @@ -163,5 +163,7 @@ extern __inline__ int get_order(unsigned #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +#include + #endif /* __KERNEL__ */ #endif /* _PPC_PAGE_H */ diff -puN include/asm-ppc/pgalloc.h~4level-architecture-changes-for-ppc include/asm-ppc/pgalloc.h --- 25/include/asm-ppc/pgalloc.h~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.653448104 -0800 +++ 25-akpm/include/asm-ppc/pgalloc.h 2004-11-30 01:08:20.666446128 -0800 @@ -7,7 +7,6 @@ extern void __bad_pte(pmd_t *pmd); -extern pgd_t *pgd_alloc(struct mm_struct *mm); extern void pgd_free(pgd_t *pgd); /* @@ -40,5 +39,7 @@ extern void pte_free(struct page *pte); #define check_pgt_cache() do { } while (0) +#include + #endif /* _PPC_PGALLOC_H */ #endif /* __KERNEL__ */ diff -puN include/asm-ppc/pgtable.h~4level-architecture-changes-for-ppc include/asm-ppc/pgtable.h --- 25/include/asm-ppc/pgtable.h~4level-architecture-changes-for-ppc 2004-11-30 01:08:20.654447952 -0800 +++ 25-akpm/include/asm-ppc/pgtable.h 2004-11-30 01:08:20.667445976 -0800 @@ -625,12 +625,9 @@ static inline void __ptep_set_access_fla (mem_map + (__pa(pmd_val(pmd)) >> PAGE_SHIFT)) #endif -/* to find an entry in a kernel page-table-directory */ -#define pgd_offset_k(address) pgd_offset(&init_mm, address) - /* to find an entry in a page-table-directory */ #define pgd_index(address) ((address) >> PGDIR_SHIFT) -#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) +#define pgd_index_k(address) pgd_index(address) /* Find an entry in the second-level page table.. */ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) @@ -734,5 +731,7 @@ extern int get_pteptr(struct mm_struct * #define __HAVE_ARCH_PTE_SAME #include +#include + #endif /* _PPC_PGTABLE_H */ #endif /* __KERNEL__ */ _