diff mbox series

[05/12] m68k: mm: use pgtable-nopXd instead of 4level-fixup

Message ID 1571822941-29776-6-git-send-email-rppt@kernel.org (mailing list archive)
State New, archived
Headers show
Series mm: remove __ARCH_HAS_4LEVEL_HACK | expand

Commit Message

Mike Rapoport Oct. 23, 2019, 9:28 a.m. UTC
From: Mike Rapoport <rppt@linux.ibm.com>

m68k has two or three levels of page tables and can use appropriate
pgtable-nopXd and folding of the upper layers.

Replace usage of include/asm-generic/4level-fixup.h and explicit
definitions of __PAGETABLE_PxD_FOLDED in m68k with
include/asm-generic/pgtable-nopmd.h for two-level configurations and with
include/asm-generic/pgtable-nopmd.h for three-lelve configurations and
adjust page table manipulation macros and functions accordingly.

Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
---
 arch/m68k/include/asm/mcf_pgalloc.h      |  7 -------
 arch/m68k/include/asm/mcf_pgtable.h      | 28 +++++++++----------------
 arch/m68k/include/asm/mmu_context.h      | 12 ++++++++++-
 arch/m68k/include/asm/motorola_pgalloc.h |  4 ++--
 arch/m68k/include/asm/motorola_pgtable.h | 32 +++++++++++++++++-----------
 arch/m68k/include/asm/page.h             |  9 +++++---
 arch/m68k/include/asm/pgtable_mm.h       | 11 ++++++----
 arch/m68k/include/asm/sun3_pgalloc.h     |  5 -----
 arch/m68k/include/asm/sun3_pgtable.h     | 18 ----------------
 arch/m68k/kernel/sys_m68k.c              | 10 ++++++++-
 arch/m68k/mm/init.c                      |  6 ++++--
 arch/m68k/mm/kmap.c                      | 36 ++++++++++++++++++++++++--------
 arch/m68k/mm/mcfmmu.c                    | 16 +++++++++++++-
 arch/m68k/mm/motorola.c                  | 17 +++++++++------
 14 files changed, 122 insertions(+), 89 deletions(-)

Comments

Greg Ungerer Oct. 24, 2019, 4:12 a.m. UTC | #1
Hi Mike,

On 23/10/19 7:28 pm, Mike Rapoport wrote:
> From: Mike Rapoport <rppt@linux.ibm.com>
> 
> m68k has two or three levels of page tables and can use appropriate
> pgtable-nopXd and folding of the upper layers.
> 
> Replace usage of include/asm-generic/4level-fixup.h and explicit
> definitions of __PAGETABLE_PxD_FOLDED in m68k with
> include/asm-generic/pgtable-nopmd.h for two-level configurations and with
> include/asm-generic/pgtable-nopmd.h for three-lelve configurations and
> adjust page table manipulation macros and functions accordingly.
> 
> Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>

Tested (on real hardware) for the ColdFire MMU m68k variants and working

Acked-by: Greg Ungerer <gerg@linux-m68k.org>

Regards
Greg


> ---
>   arch/m68k/include/asm/mcf_pgalloc.h      |  7 -------
>   arch/m68k/include/asm/mcf_pgtable.h      | 28 +++++++++----------------
>   arch/m68k/include/asm/mmu_context.h      | 12 ++++++++++-
>   arch/m68k/include/asm/motorola_pgalloc.h |  4 ++--
>   arch/m68k/include/asm/motorola_pgtable.h | 32 +++++++++++++++++-----------
>   arch/m68k/include/asm/page.h             |  9 +++++---
>   arch/m68k/include/asm/pgtable_mm.h       | 11 ++++++----
>   arch/m68k/include/asm/sun3_pgalloc.h     |  5 -----
>   arch/m68k/include/asm/sun3_pgtable.h     | 18 ----------------
>   arch/m68k/kernel/sys_m68k.c              | 10 ++++++++-
>   arch/m68k/mm/init.c                      |  6 ++++--
>   arch/m68k/mm/kmap.c                      | 36 ++++++++++++++++++++++++--------
>   arch/m68k/mm/mcfmmu.c                    | 16 +++++++++++++-
>   arch/m68k/mm/motorola.c                  | 17 +++++++++------
>   14 files changed, 122 insertions(+), 89 deletions(-)
> 
> diff --git a/arch/m68k/include/asm/mcf_pgalloc.h b/arch/m68k/include/asm/mcf_pgalloc.h
> index b34d44d..82ec54c 100644
> --- a/arch/m68k/include/asm/mcf_pgalloc.h
> +++ b/arch/m68k/include/asm/mcf_pgalloc.h
> @@ -28,9 +28,6 @@ extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
>   	return (pmd_t *) pgd;
>   }
>   
> -#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); })
> -#define pmd_alloc_one(mm, address)      ({ BUG(); ((pmd_t *)2); })
> -
>   #define pmd_populate(mm, pmd, page) (pmd_val(*pmd) = \
>   	(unsigned long)(page_address(page)))
>   
> @@ -45,8 +42,6 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
>   	__free_page(page);
>   }
>   
> -#define __pmd_free_tlb(tlb, pmd, address) do { } while (0)
> -
>   static inline struct page *pte_alloc_one(struct mm_struct *mm)
>   {
>   	struct page *page = alloc_pages(GFP_DMA, 0);
> @@ -100,6 +95,4 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
>   	return new_pgd;
>   }
>   
> -#define pgd_populate(mm, pmd, pte) BUG()
> -
>   #endif /* M68K_MCF_PGALLOC_H */
> diff --git a/arch/m68k/include/asm/mcf_pgtable.h b/arch/m68k/include/asm/mcf_pgtable.h
> index 5d5502c..b9f45ae 100644
> --- a/arch/m68k/include/asm/mcf_pgtable.h
> +++ b/arch/m68k/include/asm/mcf_pgtable.h
> @@ -198,17 +198,9 @@ static inline int pmd_bad2(pmd_t *pmd) { return 0; }
>   #define pmd_present(pmd) (!pmd_none2(&(pmd)))
>   static inline void pmd_clear(pmd_t *pmdp) { pmd_val(*pmdp) = 0; }
>   
> -static inline int pgd_none(pgd_t pgd) { return 0; }
> -static inline int pgd_bad(pgd_t pgd) { return 0; }
> -static inline int pgd_present(pgd_t pgd) { return 1; }
> -static inline void pgd_clear(pgd_t *pgdp) {}
> -
>   #define pte_ERROR(e) \
>   	printk(KERN_ERR "%s:%d: bad pte %08lx.\n",	\
>   	__FILE__, __LINE__, pte_val(e))
> -#define pmd_ERROR(e) \
> -	printk(KERN_ERR "%s:%d: bad pmd %08lx.\n",	\
> -	__FILE__, __LINE__, pmd_val(e))
>   #define pgd_ERROR(e) \
>   	printk(KERN_ERR "%s:%d: bad pgd %08lx.\n",	\
>   	__FILE__, __LINE__, pgd_val(e))
> @@ -340,14 +332,6 @@ extern pgd_t kernel_pg_dir[PTRS_PER_PGD];
>   #define pgd_offset_k(address)	pgd_offset(&init_mm, address)
>   
>   /*
> - * Find an entry in the second-level pagetable.
> - */
> -static inline pmd_t *pmd_offset(pgd_t *pgd, unsigned long address)
> -{
> -	return (pmd_t *) pgd;
> -}
> -
> -/*
>    * Find an entry in the third-level pagetable.
>    */
>   #define __pte_offset(address)	((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
> @@ -360,12 +344,16 @@ static inline pmd_t *pmd_offset(pgd_t *pgd, unsigned long address)
>   static inline void nocache_page(void *vaddr)
>   {
>   	pgd_t *dir;
> +	p4d_t *p4dp;
> +	pud_t *pudp;
>   	pmd_t *pmdp;
>   	pte_t *ptep;
>   	unsigned long addr = (unsigned long) vaddr;
>   
>   	dir = pgd_offset_k(addr);
> -	pmdp = pmd_offset(dir, addr);
> +	p4dp = p4d_offset(dir, addr);
> +	pudp = pud_offset(p4dp, addr);
> +	pmdp = pmd_offset(pudp, addr);
>   	ptep = pte_offset_kernel(pmdp, addr);
>   	*ptep = pte_mknocache(*ptep);
>   }
> @@ -376,12 +364,16 @@ static inline void nocache_page(void *vaddr)
>   static inline void cache_page(void *vaddr)
>   {
>   	pgd_t *dir;
> +	p4d_t *p4dp;
> +	pud_t *pudp;
>   	pmd_t *pmdp;
>   	pte_t *ptep;
>   	unsigned long addr = (unsigned long) vaddr;
>   
>   	dir = pgd_offset_k(addr);
> -	pmdp = pmd_offset(dir, addr);
> +	p4dp = p4d_offset(dir, addr);
> +	pudp = pud_offset(p4dp, addr);
> +	pmdp = pmd_offset(pudp, addr);
>   	ptep = pte_offset_kernel(pmdp, addr);
>   	*ptep = pte_mkcache(*ptep);
>   }
> diff --git a/arch/m68k/include/asm/mmu_context.h b/arch/m68k/include/asm/mmu_context.h
> index f5b1852..cac9f28 100644
> --- a/arch/m68k/include/asm/mmu_context.h
> +++ b/arch/m68k/include/asm/mmu_context.h
> @@ -100,6 +100,8 @@ static inline void load_ksp_mmu(struct task_struct *task)
>   	struct mm_struct *mm;
>   	int asid;
>   	pgd_t *pgd;
> +	p4d_t *p4d;
> +	pud_t *pud;
>   	pmd_t *pmd;
>   	pte_t *pte;
>   	unsigned long mmuar;
> @@ -127,7 +129,15 @@ static inline void load_ksp_mmu(struct task_struct *task)
>   	if (pgd_none(*pgd))
>   		goto bug;
>   
> -	pmd = pmd_offset(pgd, mmuar);
> +	p4d = p4d_offset(pgd, mmuar);
> +	if (p4d_none(*p4d))
> +		goto bug;
> +
> +	pud = pud_offset(p4d, mmuar);
> +	if (pud_none(*pud))
> +		goto bug;
> +
> +	pmd = pmd_offset(pud, mmuar);
>   	if (pmd_none(*pmd))
>   		goto bug;
>   
> diff --git a/arch/m68k/include/asm/motorola_pgalloc.h b/arch/m68k/include/asm/motorola_pgalloc.h
> index acab315..ff9cc40 100644
> --- a/arch/m68k/include/asm/motorola_pgalloc.h
> +++ b/arch/m68k/include/asm/motorola_pgalloc.h
> @@ -106,9 +106,9 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page
>   }
>   #define pmd_pgtable(pmd) pmd_page(pmd)
>   
> -static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
> +static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
>   {
> -	pgd_set(pgd, pmd);
> +	pud_set(pud, pmd);
>   }
>   
>   #endif /* _MOTOROLA_PGALLOC_H */
> diff --git a/arch/m68k/include/asm/motorola_pgtable.h b/arch/m68k/include/asm/motorola_pgtable.h
> index 7f66a7b..62bedc6 100644
> --- a/arch/m68k/include/asm/motorola_pgtable.h
> +++ b/arch/m68k/include/asm/motorola_pgtable.h
> @@ -117,14 +117,14 @@ static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
>   	}
>   }
>   
> -static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
> +static inline void pud_set(pud_t *pudp, pmd_t *pmdp)
>   {
> -	pgd_val(*pgdp) = _PAGE_TABLE | _PAGE_ACCESSED | __pa(pmdp);
> +	pud_val(*pudp) = _PAGE_TABLE | _PAGE_ACCESSED | __pa(pmdp);
>   }
>   
>   #define __pte_page(pte) ((unsigned long)__va(pte_val(pte) & PAGE_MASK))
>   #define __pmd_page(pmd) ((unsigned long)__va(pmd_val(pmd) & _TABLE_MASK))
> -#define __pgd_page(pgd) ((unsigned long)__va(pgd_val(pgd) & _TABLE_MASK))
> +#define pud_page_vaddr(pud) ((unsigned long)__va(pud_val(pud) & _TABLE_MASK))
>   
>   
>   #define pte_none(pte)		(!pte_val(pte))
> @@ -147,11 +147,11 @@ static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
>   #define pmd_page(pmd)		virt_to_page(__va(pmd_val(pmd)))
>   
>   
> -#define pgd_none(pgd)		(!pgd_val(pgd))
> -#define pgd_bad(pgd)		((pgd_val(pgd) & _DESCTYPE_MASK) != _PAGE_TABLE)
> -#define pgd_present(pgd)	(pgd_val(pgd) & _PAGE_TABLE)
> -#define pgd_clear(pgdp)		({ pgd_val(*pgdp) = 0; })
> -#define pgd_page(pgd)		(mem_map + ((unsigned long)(__va(pgd_val(pgd)) - PAGE_OFFSET) >> PAGE_SHIFT))
> +#define pud_none(pud)		(!pud_val(pud))
> +#define pud_bad(pud)		((pud_val(pud) & _DESCTYPE_MASK) != _PAGE_TABLE)
> +#define pud_present(pud)	(pud_val(pud) & _PAGE_TABLE)
> +#define pud_clear(pudp)		({ pud_val(*pudp) = 0; })
> +#define pud_page(pud)		(mem_map + ((unsigned long)(__va(pud_val(pud)) - PAGE_OFFSET) >> PAGE_SHIFT))
>   
>   #define pte_ERROR(e) \
>   	printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
> @@ -209,9 +209,9 @@ static inline pgd_t *pgd_offset_k(unsigned long address)
>   
>   
>   /* Find an entry in the second-level page table.. */
> -static inline pmd_t *pmd_offset(pgd_t *dir, unsigned long address)
> +static inline pmd_t *pmd_offset(pud_t *dir, unsigned long address)
>   {
> -	return (pmd_t *)__pgd_page(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PMD-1));
> +	return (pmd_t *)pud_page_vaddr(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PMD-1));
>   }
>   
>   /* Find an entry in the third-level page table.. */
> @@ -239,11 +239,15 @@ static inline void nocache_page(void *vaddr)
>   
>   	if (CPU_IS_040_OR_060) {
>   		pgd_t *dir;
> +		p4d_t *p4dp;
> +		pud_t *pudp;
>   		pmd_t *pmdp;
>   		pte_t *ptep;
>   
>   		dir = pgd_offset_k(addr);
> -		pmdp = pmd_offset(dir, addr);
> +		p4dp = p4d_offset(dir, addr);
> +		pudp = pud_offset(p4dp, addr);
> +		pmdp = pmd_offset(pudp, addr);
>   		ptep = pte_offset_kernel(pmdp, addr);
>   		*ptep = pte_mknocache(*ptep);
>   	}
> @@ -255,11 +259,15 @@ static inline void cache_page(void *vaddr)
>   
>   	if (CPU_IS_040_OR_060) {
>   		pgd_t *dir;
> +		p4d_t *p4dp;
> +		pud_t *pudp;
>   		pmd_t *pmdp;
>   		pte_t *ptep;
>   
>   		dir = pgd_offset_k(addr);
> -		pmdp = pmd_offset(dir, addr);
> +		p4dp = p4d_offset(dir, addr);
> +		pudp = pud_offset(p4dp, addr);
> +		pmdp = pmd_offset(pudp, addr);
>   		ptep = pte_offset_kernel(pmdp, addr);
>   		*ptep = pte_mkcache(*ptep);
>   	}
> diff --git a/arch/m68k/include/asm/page.h b/arch/m68k/include/asm/page.h
> index 700d819..c00b67a 100644
> --- a/arch/m68k/include/asm/page.h
> +++ b/arch/m68k/include/asm/page.h
> @@ -21,19 +21,22 @@
>   /*
>    * These are used to make use of C type-checking..
>    */
> -typedef struct { unsigned long pte; } pte_t;
> +#if CONFIG_PGTABLE_LEVELS == 3
>   typedef struct { unsigned long pmd[16]; } pmd_t;
> +#define pmd_val(x)	((&x)->pmd[0])
> +#define __pmd(x)	((pmd_t) { { (x) }, })
> +#endif
> +
> +typedef struct { unsigned long pte; } pte_t;
>   typedef struct { unsigned long pgd; } pgd_t;
>   typedef struct { unsigned long pgprot; } pgprot_t;
>   typedef struct page *pgtable_t;
>   
>   #define pte_val(x)	((x).pte)
> -#define pmd_val(x)	((&x)->pmd[0])
>   #define pgd_val(x)	((x).pgd)
>   #define pgprot_val(x)	((x).pgprot)
>   
>   #define __pte(x)	((pte_t) { (x) } )
> -#define __pmd(x)	((pmd_t) { { (x) }, })
>   #define __pgd(x)	((pgd_t) { (x) } )
>   #define __pgprot(x)	((pgprot_t) { (x) } )
>   
> diff --git a/arch/m68k/include/asm/pgtable_mm.h b/arch/m68k/include/asm/pgtable_mm.h
> index 646c174f..2bf5c35 100644
> --- a/arch/m68k/include/asm/pgtable_mm.h
> +++ b/arch/m68k/include/asm/pgtable_mm.h
> @@ -2,7 +2,12 @@
>   #ifndef _M68K_PGTABLE_H
>   #define _M68K_PGTABLE_H
>   
> -#include <asm-generic/4level-fixup.h>
> +
> +#if defined(CONFIG_SUN3) || defined(CONFIG_COLDFIRE)
> +#include <asm-generic/pgtable-nopmd.h>
> +#else
> +#include <asm-generic/pgtable-nopud.h>
> +#endif
>   
>   #include <asm/setup.h>
>   
> @@ -30,9 +35,7 @@
>   
>   
>   /* PMD_SHIFT determines the size of the area a second-level page table can map */
> -#ifdef CONFIG_SUN3
> -#define PMD_SHIFT       17
> -#else
> +#if CONFIG_PGTABLE_LEVELS == 3
>   #define PMD_SHIFT	22
>   #endif
>   #define PMD_SIZE	(1UL << PMD_SHIFT)
> diff --git a/arch/m68k/include/asm/sun3_pgalloc.h b/arch/m68k/include/asm/sun3_pgalloc.h
> index 8561211..11b95da 100644
> --- a/arch/m68k/include/asm/sun3_pgalloc.h
> +++ b/arch/m68k/include/asm/sun3_pgalloc.h
> @@ -17,8 +17,6 @@
>   
>   extern const char bad_pmd_string[];
>   
> -#define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); })
> -
>   #define __pte_free_tlb(tlb,pte,addr)			\
>   do {							\
>   	pgtable_pte_page_dtor(pte);			\
> @@ -41,7 +39,6 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page
>    * inside the pgd, so has no extra memory associated with it.
>    */
>   #define pmd_free(mm, x)			do { } while (0)
> -#define __pmd_free_tlb(tlb, x, addr)	do { } while (0)
>   
>   static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
>   {
> @@ -58,6 +55,4 @@ static inline pgd_t * pgd_alloc(struct mm_struct *mm)
>        return new_pgd;
>   }
>   
> -#define pgd_populate(mm, pmd, pte) BUG()
> -
>   #endif /* SUN3_PGALLOC_H */
> diff --git a/arch/m68k/include/asm/sun3_pgtable.h b/arch/m68k/include/asm/sun3_pgtable.h
> index c987d50..bc41552 100644
> --- a/arch/m68k/include/asm/sun3_pgtable.h
> +++ b/arch/m68k/include/asm/sun3_pgtable.h
> @@ -110,11 +110,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
>   
>   #define pmd_set(pmdp,ptep) do {} while (0)
>   
> -static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
> -{
> -	pgd_val(*pgdp) = virt_to_phys(pmdp);
> -}
> -
>   #define __pte_page(pte) \
>   ((unsigned long) __va ((pte_val (pte) & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT))
>   #define __pmd_page(pmd) \
> @@ -145,16 +140,9 @@ static inline int pmd_present2 (pmd_t *pmd) { return pmd_val (*pmd) & SUN3_PMD_V
>   #define pmd_present(pmd) (!pmd_none2(&(pmd)))
>   static inline void pmd_clear (pmd_t *pmdp) { pmd_val (*pmdp) = 0; }
>   
> -static inline int pgd_none (pgd_t pgd) { return 0; }
> -static inline int pgd_bad (pgd_t pgd) { return 0; }
> -static inline int pgd_present (pgd_t pgd) { return 1; }
> -static inline void pgd_clear (pgd_t *pgdp) {}
> -
>   
>   #define pte_ERROR(e) \
>   	pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
> -#define pmd_ERROR(e) \
> -	pr_err("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
>   #define pgd_ERROR(e) \
>   	pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
>   
> @@ -194,12 +182,6 @@ extern pgd_t kernel_pg_dir[PTRS_PER_PGD];
>   /* Find an entry in a kernel pagetable directory. */
>   #define pgd_offset_k(address) pgd_offset(&init_mm, address)
>   
> -/* Find an entry in the second-level pagetable. */
> -static inline pmd_t *pmd_offset (pgd_t *pgd, unsigned long address)
> -{
> -	return (pmd_t *) pgd;
> -}
> -
>   /* Find an entry in the third-level pagetable. */
>   #define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
>   #define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address))
> diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
> index 6363ec8..18a4de7 100644
> --- a/arch/m68k/kernel/sys_m68k.c
> +++ b/arch/m68k/kernel/sys_m68k.c
> @@ -465,6 +465,8 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
>   	for (;;) {
>   		struct mm_struct *mm = current->mm;
>   		pgd_t *pgd;
> +		p4d_t *p4d;
> +		pud_t *pud;
>   		pmd_t *pmd;
>   		pte_t *pte;
>   		spinlock_t *ptl;
> @@ -474,7 +476,13 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
>   		pgd = pgd_offset(mm, (unsigned long)mem);
>   		if (!pgd_present(*pgd))
>   			goto bad_access;
> -		pmd = pmd_offset(pgd, (unsigned long)mem);
> +		p4d = p4d_offset(pgd, (unsigned long)mem);
> +		if (!p4d_present(*p4d))
> +			goto bad_access;
> +		pud = pud_offset(p4d, (unsigned long)mem);
> +		if (!pud_present(*pud))
> +			goto bad_access;
> +		pmd = pmd_offset(pud, (unsigned long)mem);
>   		if (!pmd_present(*pmd))
>   			goto bad_access;
>   		pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl);
> diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
> index 778cacb..27c453f 100644
> --- a/arch/m68k/mm/init.c
> +++ b/arch/m68k/mm/init.c
> @@ -130,8 +130,10 @@ static inline void init_pointer_tables(void)
>   	/* insert pointer tables allocated so far into the tablelist */
>   	init_pointer_table((unsigned long)kernel_pg_dir);
>   	for (i = 0; i < PTRS_PER_PGD; i++) {
> -		if (pgd_present(kernel_pg_dir[i]))
> -			init_pointer_table(__pgd_page(kernel_pg_dir[i]));
> +		pud_t *pud = (pud_t *)(&kernel_pg_dir[i]);
> +
> +		if (pud_present(*pud))
> +			init_pointer_table(pgd_page_vaddr(kernel_pg_dir[i]));
>   	}
>   
>   	/* insert also pointer table that we used to unmap the zero page */
> diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
> index 40a3b32..9f687da 100644
> --- a/arch/m68k/mm/kmap.c
> +++ b/arch/m68k/mm/kmap.c
> @@ -110,6 +110,8 @@ void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cachefla
>   	unsigned long virtaddr, retaddr;
>   	long offset;
>   	pgd_t *pgd_dir;
> +	p4d_t *p4d_dir;
> +	pud_t *pud_dir;
>   	pmd_t *pmd_dir;
>   	pte_t *pte_dir;
>   
> @@ -196,17 +198,21 @@ void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cachefla
>   			printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
>   #endif
>   		pgd_dir = pgd_offset_k(virtaddr);
> -		pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
> +		p4d_dir = p4d_offset(pgd_dir, virtaddr);
> +		pud_dir = pud_offset(p4d_dir, virtaddr);
> +		pmd_dir = pmd_alloc(&init_mm, pud_dir, virtaddr);
>   		if (!pmd_dir) {
>   			printk("ioremap: no mem for pmd_dir\n");
>   			return NULL;
>   		}
>   
>   		if (CPU_IS_020_OR_030) {
> +#if CONFIG_PGTABLE_LEVELS == 3
>   			pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
>   			physaddr += PTRTREESIZE;
>   			virtaddr += PTRTREESIZE;
>   			size -= PTRTREESIZE;
> +#endif
>   		} else {
>   			pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
>   			if (!pte_dir) {
> @@ -258,19 +264,24 @@ void __iounmap(void *addr, unsigned long size)
>   {
>   	unsigned long virtaddr = (unsigned long)addr;
>   	pgd_t *pgd_dir;
> +	p4d_t *p4d_dir;
> +	pud_t *pud_dir;
>   	pmd_t *pmd_dir;
>   	pte_t *pte_dir;
>   
>   	while ((long)size > 0) {
>   		pgd_dir = pgd_offset_k(virtaddr);
> -		if (pgd_bad(*pgd_dir)) {
> -			printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
> -			pgd_clear(pgd_dir);
> +		p4d_dir = p4d_offset(pgd_dir, virtaddr);
> +		pud_dir = pud_offset(p4d_dir, virtaddr);
> +		if (pud_bad(*pud_dir)) {
> +			printk("iounmap: bad pgd(%08lx)\n", pud_val(*pud_dir));
> +			pud_clear(pud_dir);
>   			return;
>   		}
> -		pmd_dir = pmd_offset(pgd_dir, virtaddr);
> +		pmd_dir = pmd_offset(pud_dir, virtaddr);
>   
>   		if (CPU_IS_020_OR_030) {
> +#if CONFIG_PGTABLE_LEVELS == 3
>   			int pmd_off = (virtaddr/PTRTREESIZE) & 15;
>   			int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
>   
> @@ -281,6 +292,7 @@ void __iounmap(void *addr, unsigned long size)
>   				continue;
>   			} else if (pmd_type == 0)
>   				continue;
> +#endif
>   		}
>   
>   		if (pmd_bad(*pmd_dir)) {
> @@ -307,6 +319,8 @@ void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
>   {
>   	unsigned long virtaddr = (unsigned long)addr;
>   	pgd_t *pgd_dir;
> +	p4d_t *p4d_dir;
> +	pud_t *pud_dir;
>   	pmd_t *pmd_dir;
>   	pte_t *pte_dir;
>   
> @@ -341,14 +355,17 @@ void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
>   
>   	while ((long)size > 0) {
>   		pgd_dir = pgd_offset_k(virtaddr);
> -		if (pgd_bad(*pgd_dir)) {
> -			printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
> -			pgd_clear(pgd_dir);
> +		p4d_dir = p4d_offset(pgd_dir, virtaddr);
> +		pud_dir = pud_offset(p4d_dir, virtaddr);
> +		if (pud_bad(*pud_dir)) {
> +			printk("iocachemode: bad pud(%08lx)\n", pud_val(*pud_dir));
> +			pud_clear(pud_dir);
>   			return;
>   		}
> -		pmd_dir = pmd_offset(pgd_dir, virtaddr);
> +		pmd_dir = pmd_offset(pud_dir, virtaddr);
>   
>   		if (CPU_IS_020_OR_030) {
> +#if CONFIG_PGTABLE_LEVELS == 3
>   			int pmd_off = (virtaddr/PTRTREESIZE) & 15;
>   
>   			if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
> @@ -358,6 +375,7 @@ void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
>   				size -= PTRTREESIZE;
>   				continue;
>   			}
> +#endif
>   		}
>   
>   		if (pmd_bad(*pmd_dir)) {
> diff --git a/arch/m68k/mm/mcfmmu.c b/arch/m68k/mm/mcfmmu.c
> index 6cb1e41..0ea3756 100644
> --- a/arch/m68k/mm/mcfmmu.c
> +++ b/arch/m68k/mm/mcfmmu.c
> @@ -92,6 +92,8 @@ int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
>   	unsigned long flags, mmuar, mmutr;
>   	struct mm_struct *mm;
>   	pgd_t *pgd;
> +	p4d_t *p4d;
> +	pud_t *pud;
>   	pmd_t *pmd;
>   	pte_t *pte;
>   	int asid;
> @@ -113,7 +115,19 @@ int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
>   		return -1;
>   	}
>   
> -	pmd = pmd_offset(pgd, mmuar);
> +	p4d = p4d_offset(pgd, mmuar);
> +	if (p4d_none(*p4d)) {
> +		local_irq_restore(flags);
> +		return -1;
> +	}
> +
> +	pud = pud_offset(p4d, mmuar);
> +	if (pud_none(*pud)) {
> +		local_irq_restore(flags);
> +		return -1;
> +	}
> +
> +	pmd = pmd_offset(pud, mmuar);
>   	if (pmd_none(*pmd)) {
>   		local_irq_restore(flags);
>   		return -1;
> diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
> index 356601b..4857985 100644
> --- a/arch/m68k/mm/motorola.c
> +++ b/arch/m68k/mm/motorola.c
> @@ -82,9 +82,11 @@ static pmd_t * __init kernel_ptr_table(void)
>   		 */
>   		last = (unsigned long)kernel_pg_dir;
>   		for (i = 0; i < PTRS_PER_PGD; i++) {
> -			if (!pgd_present(kernel_pg_dir[i]))
> +			pud_t *pud = (pud_t *)(&kernel_pg_dir[i]);
> +
> +			if (!pud_present(*pud))
>   				continue;
> -			pmd = __pgd_page(kernel_pg_dir[i]);
> +			pmd = pgd_page_vaddr(kernel_pg_dir[i]);
>   			if (pmd > last)
>   				last = pmd;
>   		}
> @@ -118,6 +120,8 @@ static void __init map_node(int node)
>   #define ROOTTREESIZE (32*1024*1024)
>   	unsigned long physaddr, virtaddr, size;
>   	pgd_t *pgd_dir;
> +	p4d_t *p4d_dir;
> +	pud_t *pud_dir;
>   	pmd_t *pmd_dir;
>   	pte_t *pte_dir;
>   
> @@ -149,14 +153,16 @@ static void __init map_node(int node)
>   				continue;
>   			}
>   		}
> -		if (!pgd_present(*pgd_dir)) {
> +		p4d_dir = p4d_offset(pgd_dir, virtaddr);
> +		pud_dir = pud_offset(p4d_dir, virtaddr);
> +		if (!pud_present(*pud_dir)) {
>   			pmd_dir = kernel_ptr_table();
>   #ifdef DEBUG
>   			printk ("[new pointer %p]", pmd_dir);
>   #endif
> -			pgd_set(pgd_dir, pmd_dir);
> +			pud_set(pud_dir, pmd_dir);
>   		} else
> -			pmd_dir = pmd_offset(pgd_dir, virtaddr);
> +			pmd_dir = pmd_offset(pud_dir, virtaddr);
>   
>   		if (CPU_IS_020_OR_030) {
>   			if (virtaddr) {
> @@ -304,4 +310,3 @@ void __init paging_init(void)
>   			node_set_state(i, N_NORMAL_MEMORY);
>   	}
>   }
> -
>
diff mbox series

Patch

diff --git a/arch/m68k/include/asm/mcf_pgalloc.h b/arch/m68k/include/asm/mcf_pgalloc.h
index b34d44d..82ec54c 100644
--- a/arch/m68k/include/asm/mcf_pgalloc.h
+++ b/arch/m68k/include/asm/mcf_pgalloc.h
@@ -28,9 +28,6 @@  extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
 	return (pmd_t *) pgd;
 }
 
-#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); })
-#define pmd_alloc_one(mm, address)      ({ BUG(); ((pmd_t *)2); })
-
 #define pmd_populate(mm, pmd, page) (pmd_val(*pmd) = \
 	(unsigned long)(page_address(page)))
 
@@ -45,8 +42,6 @@  static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
 	__free_page(page);
 }
 
-#define __pmd_free_tlb(tlb, pmd, address) do { } while (0)
-
 static inline struct page *pte_alloc_one(struct mm_struct *mm)
 {
 	struct page *page = alloc_pages(GFP_DMA, 0);
@@ -100,6 +95,4 @@  static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 	return new_pgd;
 }
 
-#define pgd_populate(mm, pmd, pte) BUG()
-
 #endif /* M68K_MCF_PGALLOC_H */
diff --git a/arch/m68k/include/asm/mcf_pgtable.h b/arch/m68k/include/asm/mcf_pgtable.h
index 5d5502c..b9f45ae 100644
--- a/arch/m68k/include/asm/mcf_pgtable.h
+++ b/arch/m68k/include/asm/mcf_pgtable.h
@@ -198,17 +198,9 @@  static inline int pmd_bad2(pmd_t *pmd) { return 0; }
 #define pmd_present(pmd) (!pmd_none2(&(pmd)))
 static inline void pmd_clear(pmd_t *pmdp) { pmd_val(*pmdp) = 0; }
 
-static inline int pgd_none(pgd_t pgd) { return 0; }
-static inline int pgd_bad(pgd_t pgd) { return 0; }
-static inline int pgd_present(pgd_t pgd) { return 1; }
-static inline void pgd_clear(pgd_t *pgdp) {}
-
 #define pte_ERROR(e) \
 	printk(KERN_ERR "%s:%d: bad pte %08lx.\n",	\
 	__FILE__, __LINE__, pte_val(e))
-#define pmd_ERROR(e) \
-	printk(KERN_ERR "%s:%d: bad pmd %08lx.\n",	\
-	__FILE__, __LINE__, pmd_val(e))
 #define pgd_ERROR(e) \
 	printk(KERN_ERR "%s:%d: bad pgd %08lx.\n",	\
 	__FILE__, __LINE__, pgd_val(e))
@@ -340,14 +332,6 @@  extern pgd_t kernel_pg_dir[PTRS_PER_PGD];
 #define pgd_offset_k(address)	pgd_offset(&init_mm, address)
 
 /*
- * Find an entry in the second-level pagetable.
- */
-static inline pmd_t *pmd_offset(pgd_t *pgd, unsigned long address)
-{
-	return (pmd_t *) pgd;
-}
-
-/*
  * Find an entry in the third-level pagetable.
  */
 #define __pte_offset(address)	((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
@@ -360,12 +344,16 @@  static inline pmd_t *pmd_offset(pgd_t *pgd, unsigned long address)
 static inline void nocache_page(void *vaddr)
 {
 	pgd_t *dir;
+	p4d_t *p4dp;
+	pud_t *pudp;
 	pmd_t *pmdp;
 	pte_t *ptep;
 	unsigned long addr = (unsigned long) vaddr;
 
 	dir = pgd_offset_k(addr);
-	pmdp = pmd_offset(dir, addr);
+	p4dp = p4d_offset(dir, addr);
+	pudp = pud_offset(p4dp, addr);
+	pmdp = pmd_offset(pudp, addr);
 	ptep = pte_offset_kernel(pmdp, addr);
 	*ptep = pte_mknocache(*ptep);
 }
@@ -376,12 +364,16 @@  static inline void nocache_page(void *vaddr)
 static inline void cache_page(void *vaddr)
 {
 	pgd_t *dir;
+	p4d_t *p4dp;
+	pud_t *pudp;
 	pmd_t *pmdp;
 	pte_t *ptep;
 	unsigned long addr = (unsigned long) vaddr;
 
 	dir = pgd_offset_k(addr);
-	pmdp = pmd_offset(dir, addr);
+	p4dp = p4d_offset(dir, addr);
+	pudp = pud_offset(p4dp, addr);
+	pmdp = pmd_offset(pudp, addr);
 	ptep = pte_offset_kernel(pmdp, addr);
 	*ptep = pte_mkcache(*ptep);
 }
diff --git a/arch/m68k/include/asm/mmu_context.h b/arch/m68k/include/asm/mmu_context.h
index f5b1852..cac9f28 100644
--- a/arch/m68k/include/asm/mmu_context.h
+++ b/arch/m68k/include/asm/mmu_context.h
@@ -100,6 +100,8 @@  static inline void load_ksp_mmu(struct task_struct *task)
 	struct mm_struct *mm;
 	int asid;
 	pgd_t *pgd;
+	p4d_t *p4d;
+	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
 	unsigned long mmuar;
@@ -127,7 +129,15 @@  static inline void load_ksp_mmu(struct task_struct *task)
 	if (pgd_none(*pgd))
 		goto bug;
 
-	pmd = pmd_offset(pgd, mmuar);
+	p4d = p4d_offset(pgd, mmuar);
+	if (p4d_none(*p4d))
+		goto bug;
+
+	pud = pud_offset(p4d, mmuar);
+	if (pud_none(*pud))
+		goto bug;
+
+	pmd = pmd_offset(pud, mmuar);
 	if (pmd_none(*pmd))
 		goto bug;
 
diff --git a/arch/m68k/include/asm/motorola_pgalloc.h b/arch/m68k/include/asm/motorola_pgalloc.h
index acab315..ff9cc40 100644
--- a/arch/m68k/include/asm/motorola_pgalloc.h
+++ b/arch/m68k/include/asm/motorola_pgalloc.h
@@ -106,9 +106,9 @@  static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page
 }
 #define pmd_pgtable(pmd) pmd_page(pmd)
 
-static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
+static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
 {
-	pgd_set(pgd, pmd);
+	pud_set(pud, pmd);
 }
 
 #endif /* _MOTOROLA_PGALLOC_H */
diff --git a/arch/m68k/include/asm/motorola_pgtable.h b/arch/m68k/include/asm/motorola_pgtable.h
index 7f66a7b..62bedc6 100644
--- a/arch/m68k/include/asm/motorola_pgtable.h
+++ b/arch/m68k/include/asm/motorola_pgtable.h
@@ -117,14 +117,14 @@  static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
 	}
 }
 
-static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
+static inline void pud_set(pud_t *pudp, pmd_t *pmdp)
 {
-	pgd_val(*pgdp) = _PAGE_TABLE | _PAGE_ACCESSED | __pa(pmdp);
+	pud_val(*pudp) = _PAGE_TABLE | _PAGE_ACCESSED | __pa(pmdp);
 }
 
 #define __pte_page(pte) ((unsigned long)__va(pte_val(pte) & PAGE_MASK))
 #define __pmd_page(pmd) ((unsigned long)__va(pmd_val(pmd) & _TABLE_MASK))
-#define __pgd_page(pgd) ((unsigned long)__va(pgd_val(pgd) & _TABLE_MASK))
+#define pud_page_vaddr(pud) ((unsigned long)__va(pud_val(pud) & _TABLE_MASK))
 
 
 #define pte_none(pte)		(!pte_val(pte))
@@ -147,11 +147,11 @@  static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
 #define pmd_page(pmd)		virt_to_page(__va(pmd_val(pmd)))
 
 
-#define pgd_none(pgd)		(!pgd_val(pgd))
-#define pgd_bad(pgd)		((pgd_val(pgd) & _DESCTYPE_MASK) != _PAGE_TABLE)
-#define pgd_present(pgd)	(pgd_val(pgd) & _PAGE_TABLE)
-#define pgd_clear(pgdp)		({ pgd_val(*pgdp) = 0; })
-#define pgd_page(pgd)		(mem_map + ((unsigned long)(__va(pgd_val(pgd)) - PAGE_OFFSET) >> PAGE_SHIFT))
+#define pud_none(pud)		(!pud_val(pud))
+#define pud_bad(pud)		((pud_val(pud) & _DESCTYPE_MASK) != _PAGE_TABLE)
+#define pud_present(pud)	(pud_val(pud) & _PAGE_TABLE)
+#define pud_clear(pudp)		({ pud_val(*pudp) = 0; })
+#define pud_page(pud)		(mem_map + ((unsigned long)(__va(pud_val(pud)) - PAGE_OFFSET) >> PAGE_SHIFT))
 
 #define pte_ERROR(e) \
 	printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
@@ -209,9 +209,9 @@  static inline pgd_t *pgd_offset_k(unsigned long address)
 
 
 /* Find an entry in the second-level page table.. */
-static inline pmd_t *pmd_offset(pgd_t *dir, unsigned long address)
+static inline pmd_t *pmd_offset(pud_t *dir, unsigned long address)
 {
-	return (pmd_t *)__pgd_page(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PMD-1));
+	return (pmd_t *)pud_page_vaddr(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PMD-1));
 }
 
 /* Find an entry in the third-level page table.. */
@@ -239,11 +239,15 @@  static inline void nocache_page(void *vaddr)
 
 	if (CPU_IS_040_OR_060) {
 		pgd_t *dir;
+		p4d_t *p4dp;
+		pud_t *pudp;
 		pmd_t *pmdp;
 		pte_t *ptep;
 
 		dir = pgd_offset_k(addr);
-		pmdp = pmd_offset(dir, addr);
+		p4dp = p4d_offset(dir, addr);
+		pudp = pud_offset(p4dp, addr);
+		pmdp = pmd_offset(pudp, addr);
 		ptep = pte_offset_kernel(pmdp, addr);
 		*ptep = pte_mknocache(*ptep);
 	}
@@ -255,11 +259,15 @@  static inline void cache_page(void *vaddr)
 
 	if (CPU_IS_040_OR_060) {
 		pgd_t *dir;
+		p4d_t *p4dp;
+		pud_t *pudp;
 		pmd_t *pmdp;
 		pte_t *ptep;
 
 		dir = pgd_offset_k(addr);
-		pmdp = pmd_offset(dir, addr);
+		p4dp = p4d_offset(dir, addr);
+		pudp = pud_offset(p4dp, addr);
+		pmdp = pmd_offset(pudp, addr);
 		ptep = pte_offset_kernel(pmdp, addr);
 		*ptep = pte_mkcache(*ptep);
 	}
diff --git a/arch/m68k/include/asm/page.h b/arch/m68k/include/asm/page.h
index 700d819..c00b67a 100644
--- a/arch/m68k/include/asm/page.h
+++ b/arch/m68k/include/asm/page.h
@@ -21,19 +21,22 @@ 
 /*
  * These are used to make use of C type-checking..
  */
-typedef struct { unsigned long pte; } pte_t;
+#if CONFIG_PGTABLE_LEVELS == 3
 typedef struct { unsigned long pmd[16]; } pmd_t;
+#define pmd_val(x)	((&x)->pmd[0])
+#define __pmd(x)	((pmd_t) { { (x) }, })
+#endif
+
+typedef struct { unsigned long pte; } pte_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
 typedef struct page *pgtable_t;
 
 #define pte_val(x)	((x).pte)
-#define pmd_val(x)	((&x)->pmd[0])
 #define pgd_val(x)	((x).pgd)
 #define pgprot_val(x)	((x).pgprot)
 
 #define __pte(x)	((pte_t) { (x) } )
-#define __pmd(x)	((pmd_t) { { (x) }, })
 #define __pgd(x)	((pgd_t) { (x) } )
 #define __pgprot(x)	((pgprot_t) { (x) } )
 
diff --git a/arch/m68k/include/asm/pgtable_mm.h b/arch/m68k/include/asm/pgtable_mm.h
index 646c174f..2bf5c35 100644
--- a/arch/m68k/include/asm/pgtable_mm.h
+++ b/arch/m68k/include/asm/pgtable_mm.h
@@ -2,7 +2,12 @@ 
 #ifndef _M68K_PGTABLE_H
 #define _M68K_PGTABLE_H
 
-#include <asm-generic/4level-fixup.h>
+
+#if defined(CONFIG_SUN3) || defined(CONFIG_COLDFIRE)
+#include <asm-generic/pgtable-nopmd.h>
+#else
+#include <asm-generic/pgtable-nopud.h>
+#endif
 
 #include <asm/setup.h>
 
@@ -30,9 +35,7 @@ 
 
 
 /* PMD_SHIFT determines the size of the area a second-level page table can map */
-#ifdef CONFIG_SUN3
-#define PMD_SHIFT       17
-#else
+#if CONFIG_PGTABLE_LEVELS == 3
 #define PMD_SHIFT	22
 #endif
 #define PMD_SIZE	(1UL << PMD_SHIFT)
diff --git a/arch/m68k/include/asm/sun3_pgalloc.h b/arch/m68k/include/asm/sun3_pgalloc.h
index 8561211..11b95da 100644
--- a/arch/m68k/include/asm/sun3_pgalloc.h
+++ b/arch/m68k/include/asm/sun3_pgalloc.h
@@ -17,8 +17,6 @@ 
 
 extern const char bad_pmd_string[];
 
-#define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); })
-
 #define __pte_free_tlb(tlb,pte,addr)			\
 do {							\
 	pgtable_pte_page_dtor(pte);			\
@@ -41,7 +39,6 @@  static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page
  * inside the pgd, so has no extra memory associated with it.
  */
 #define pmd_free(mm, x)			do { } while (0)
-#define __pmd_free_tlb(tlb, x, addr)	do { } while (0)
 
 static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 {
@@ -58,6 +55,4 @@  static inline pgd_t * pgd_alloc(struct mm_struct *mm)
      return new_pgd;
 }
 
-#define pgd_populate(mm, pmd, pte) BUG()
-
 #endif /* SUN3_PGALLOC_H */
diff --git a/arch/m68k/include/asm/sun3_pgtable.h b/arch/m68k/include/asm/sun3_pgtable.h
index c987d50..bc41552 100644
--- a/arch/m68k/include/asm/sun3_pgtable.h
+++ b/arch/m68k/include/asm/sun3_pgtable.h
@@ -110,11 +110,6 @@  static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 
 #define pmd_set(pmdp,ptep) do {} while (0)
 
-static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
-{
-	pgd_val(*pgdp) = virt_to_phys(pmdp);
-}
-
 #define __pte_page(pte) \
 ((unsigned long) __va ((pte_val (pte) & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT))
 #define __pmd_page(pmd) \
@@ -145,16 +140,9 @@  static inline int pmd_present2 (pmd_t *pmd) { return pmd_val (*pmd) & SUN3_PMD_V
 #define pmd_present(pmd) (!pmd_none2(&(pmd)))
 static inline void pmd_clear (pmd_t *pmdp) { pmd_val (*pmdp) = 0; }
 
-static inline int pgd_none (pgd_t pgd) { return 0; }
-static inline int pgd_bad (pgd_t pgd) { return 0; }
-static inline int pgd_present (pgd_t pgd) { return 1; }
-static inline void pgd_clear (pgd_t *pgdp) {}
-
 
 #define pte_ERROR(e) \
 	pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
-#define pmd_ERROR(e) \
-	pr_err("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
 #define pgd_ERROR(e) \
 	pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
@@ -194,12 +182,6 @@  extern pgd_t kernel_pg_dir[PTRS_PER_PGD];
 /* Find an entry in a kernel pagetable directory. */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
-/* Find an entry in the second-level pagetable. */
-static inline pmd_t *pmd_offset (pgd_t *pgd, unsigned long address)
-{
-	return (pmd_t *) pgd;
-}
-
 /* Find an entry in the third-level pagetable. */
 #define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
 #define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address))
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 6363ec8..18a4de7 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -465,6 +465,8 @@  sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
 	for (;;) {
 		struct mm_struct *mm = current->mm;
 		pgd_t *pgd;
+		p4d_t *p4d;
+		pud_t *pud;
 		pmd_t *pmd;
 		pte_t *pte;
 		spinlock_t *ptl;
@@ -474,7 +476,13 @@  sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
 		pgd = pgd_offset(mm, (unsigned long)mem);
 		if (!pgd_present(*pgd))
 			goto bad_access;
-		pmd = pmd_offset(pgd, (unsigned long)mem);
+		p4d = p4d_offset(pgd, (unsigned long)mem);
+		if (!p4d_present(*p4d))
+			goto bad_access;
+		pud = pud_offset(p4d, (unsigned long)mem);
+		if (!pud_present(*pud))
+			goto bad_access;
+		pmd = pmd_offset(pud, (unsigned long)mem);
 		if (!pmd_present(*pmd))
 			goto bad_access;
 		pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl);
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index 778cacb..27c453f 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -130,8 +130,10 @@  static inline void init_pointer_tables(void)
 	/* insert pointer tables allocated so far into the tablelist */
 	init_pointer_table((unsigned long)kernel_pg_dir);
 	for (i = 0; i < PTRS_PER_PGD; i++) {
-		if (pgd_present(kernel_pg_dir[i]))
-			init_pointer_table(__pgd_page(kernel_pg_dir[i]));
+		pud_t *pud = (pud_t *)(&kernel_pg_dir[i]);
+
+		if (pud_present(*pud))
+			init_pointer_table(pgd_page_vaddr(kernel_pg_dir[i]));
 	}
 
 	/* insert also pointer table that we used to unmap the zero page */
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index 40a3b32..9f687da 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -110,6 +110,8 @@  void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cachefla
 	unsigned long virtaddr, retaddr;
 	long offset;
 	pgd_t *pgd_dir;
+	p4d_t *p4d_dir;
+	pud_t *pud_dir;
 	pmd_t *pmd_dir;
 	pte_t *pte_dir;
 
@@ -196,17 +198,21 @@  void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cachefla
 			printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
 #endif
 		pgd_dir = pgd_offset_k(virtaddr);
-		pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
+		p4d_dir = p4d_offset(pgd_dir, virtaddr);
+		pud_dir = pud_offset(p4d_dir, virtaddr);
+		pmd_dir = pmd_alloc(&init_mm, pud_dir, virtaddr);
 		if (!pmd_dir) {
 			printk("ioremap: no mem for pmd_dir\n");
 			return NULL;
 		}
 
 		if (CPU_IS_020_OR_030) {
+#if CONFIG_PGTABLE_LEVELS == 3
 			pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
 			physaddr += PTRTREESIZE;
 			virtaddr += PTRTREESIZE;
 			size -= PTRTREESIZE;
+#endif
 		} else {
 			pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
 			if (!pte_dir) {
@@ -258,19 +264,24 @@  void __iounmap(void *addr, unsigned long size)
 {
 	unsigned long virtaddr = (unsigned long)addr;
 	pgd_t *pgd_dir;
+	p4d_t *p4d_dir;
+	pud_t *pud_dir;
 	pmd_t *pmd_dir;
 	pte_t *pte_dir;
 
 	while ((long)size > 0) {
 		pgd_dir = pgd_offset_k(virtaddr);
-		if (pgd_bad(*pgd_dir)) {
-			printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
-			pgd_clear(pgd_dir);
+		p4d_dir = p4d_offset(pgd_dir, virtaddr);
+		pud_dir = pud_offset(p4d_dir, virtaddr);
+		if (pud_bad(*pud_dir)) {
+			printk("iounmap: bad pgd(%08lx)\n", pud_val(*pud_dir));
+			pud_clear(pud_dir);
 			return;
 		}
-		pmd_dir = pmd_offset(pgd_dir, virtaddr);
+		pmd_dir = pmd_offset(pud_dir, virtaddr);
 
 		if (CPU_IS_020_OR_030) {
+#if CONFIG_PGTABLE_LEVELS == 3
 			int pmd_off = (virtaddr/PTRTREESIZE) & 15;
 			int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
 
@@ -281,6 +292,7 @@  void __iounmap(void *addr, unsigned long size)
 				continue;
 			} else if (pmd_type == 0)
 				continue;
+#endif
 		}
 
 		if (pmd_bad(*pmd_dir)) {
@@ -307,6 +319,8 @@  void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
 {
 	unsigned long virtaddr = (unsigned long)addr;
 	pgd_t *pgd_dir;
+	p4d_t *p4d_dir;
+	pud_t *pud_dir;
 	pmd_t *pmd_dir;
 	pte_t *pte_dir;
 
@@ -341,14 +355,17 @@  void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
 
 	while ((long)size > 0) {
 		pgd_dir = pgd_offset_k(virtaddr);
-		if (pgd_bad(*pgd_dir)) {
-			printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
-			pgd_clear(pgd_dir);
+		p4d_dir = p4d_offset(pgd_dir, virtaddr);
+		pud_dir = pud_offset(p4d_dir, virtaddr);
+		if (pud_bad(*pud_dir)) {
+			printk("iocachemode: bad pud(%08lx)\n", pud_val(*pud_dir));
+			pud_clear(pud_dir);
 			return;
 		}
-		pmd_dir = pmd_offset(pgd_dir, virtaddr);
+		pmd_dir = pmd_offset(pud_dir, virtaddr);
 
 		if (CPU_IS_020_OR_030) {
+#if CONFIG_PGTABLE_LEVELS == 3
 			int pmd_off = (virtaddr/PTRTREESIZE) & 15;
 
 			if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
@@ -358,6 +375,7 @@  void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
 				size -= PTRTREESIZE;
 				continue;
 			}
+#endif
 		}
 
 		if (pmd_bad(*pmd_dir)) {
diff --git a/arch/m68k/mm/mcfmmu.c b/arch/m68k/mm/mcfmmu.c
index 6cb1e41..0ea3756 100644
--- a/arch/m68k/mm/mcfmmu.c
+++ b/arch/m68k/mm/mcfmmu.c
@@ -92,6 +92,8 @@  int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
 	unsigned long flags, mmuar, mmutr;
 	struct mm_struct *mm;
 	pgd_t *pgd;
+	p4d_t *p4d;
+	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
 	int asid;
@@ -113,7 +115,19 @@  int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
 		return -1;
 	}
 
-	pmd = pmd_offset(pgd, mmuar);
+	p4d = p4d_offset(pgd, mmuar);
+	if (p4d_none(*p4d)) {
+		local_irq_restore(flags);
+		return -1;
+	}
+
+	pud = pud_offset(p4d, mmuar);
+	if (pud_none(*pud)) {
+		local_irq_restore(flags);
+		return -1;
+	}
+
+	pmd = pmd_offset(pud, mmuar);
 	if (pmd_none(*pmd)) {
 		local_irq_restore(flags);
 		return -1;
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index 356601b..4857985 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -82,9 +82,11 @@  static pmd_t * __init kernel_ptr_table(void)
 		 */
 		last = (unsigned long)kernel_pg_dir;
 		for (i = 0; i < PTRS_PER_PGD; i++) {
-			if (!pgd_present(kernel_pg_dir[i]))
+			pud_t *pud = (pud_t *)(&kernel_pg_dir[i]);
+
+			if (!pud_present(*pud))
 				continue;
-			pmd = __pgd_page(kernel_pg_dir[i]);
+			pmd = pgd_page_vaddr(kernel_pg_dir[i]);
 			if (pmd > last)
 				last = pmd;
 		}
@@ -118,6 +120,8 @@  static void __init map_node(int node)
 #define ROOTTREESIZE (32*1024*1024)
 	unsigned long physaddr, virtaddr, size;
 	pgd_t *pgd_dir;
+	p4d_t *p4d_dir;
+	pud_t *pud_dir;
 	pmd_t *pmd_dir;
 	pte_t *pte_dir;
 
@@ -149,14 +153,16 @@  static void __init map_node(int node)
 				continue;
 			}
 		}
-		if (!pgd_present(*pgd_dir)) {
+		p4d_dir = p4d_offset(pgd_dir, virtaddr);
+		pud_dir = pud_offset(p4d_dir, virtaddr);
+		if (!pud_present(*pud_dir)) {
 			pmd_dir = kernel_ptr_table();
 #ifdef DEBUG
 			printk ("[new pointer %p]", pmd_dir);
 #endif
-			pgd_set(pgd_dir, pmd_dir);
+			pud_set(pud_dir, pmd_dir);
 		} else
-			pmd_dir = pmd_offset(pgd_dir, virtaddr);
+			pmd_dir = pmd_offset(pud_dir, virtaddr);
 
 		if (CPU_IS_020_OR_030) {
 			if (virtaddr) {
@@ -304,4 +310,3 @@  void __init paging_init(void)
 			node_set_state(i, N_NORMAL_MEMORY);
 	}
 }
-