2019-10-23 09:31:21

by Mike Rapoport

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

From: Mike Rapoport <[email protected]>

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 <[email protected]>
---
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);
}
}
-
--
2.7.4


2019-10-24 19:55:30

by Greg Ungerer

[permalink] [raw]
Subject: Re: [PATCH 05/12] m68k: mm: use pgtable-nopXd instead of 4level-fixup

Hi Mike,

On 23/10/19 7:28 pm, Mike Rapoport wrote:
> From: Mike Rapoport <[email protected]>
>
> 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 <[email protected]>

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

Acked-by: Greg Ungerer <[email protected]>

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);
> }
> }
> -
>

2019-10-25 19:25:49

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 05/12] m68k: mm: use pgtable-nopXd instead of 4level-fixup

Hi Mike,

I love your patch! Yet something to improve:

[auto build test ERROR on mmotm/master]

url: https://github.com/0day-ci/linux/commits/Mike-Rapoport/mm-remove-__ARCH_HAS_4LEVEL_HACK/20191025-063009
base: git://git.cmpxchg.org/linux-mmotm.git master
config: m68k-multi_defconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 7.4.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.4.0 make.cross ARCH=m68k

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <[email protected]>

All errors (new ones prefixed by >>):

arch/m68k/sun3x/dvma.c: In function 'dvma_map_cpu':
>> arch/m68k/sun3x/dvma.c:98:33: error: passing argument 2 of 'pmd_alloc' from incompatible pointer type [-Werror=incompatible-pointer-types]
if((pmd = pmd_alloc(&init_mm, pgd, vaddr)) == NULL) {
^~~
In file included from arch/m68k/sun3x/dvma.c:17:0:
include/linux/mm.h:1917:22: note: expected 'pud_t * {aka struct <anonymous> *}' but argument is of type 'pgd_t * {aka struct <anonymous> *}'
static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
^~~~~~~~~
cc1: some warnings being treated as errors

vim +/pmd_alloc +98 arch/m68k/sun3x/dvma.c

^1da177e4c3f41 Linus Torvalds 2005-04-16 75
^1da177e4c3f41 Linus Torvalds 2005-04-16 76
^1da177e4c3f41 Linus Torvalds 2005-04-16 77 /* create a virtual mapping for a page assigned within the IOMMU
^1da177e4c3f41 Linus Torvalds 2005-04-16 78 so that the cpu can reach it easily */
^1da177e4c3f41 Linus Torvalds 2005-04-16 79 inline int dvma_map_cpu(unsigned long kaddr,
^1da177e4c3f41 Linus Torvalds 2005-04-16 80 unsigned long vaddr, int len)
^1da177e4c3f41 Linus Torvalds 2005-04-16 81 {
^1da177e4c3f41 Linus Torvalds 2005-04-16 82 pgd_t *pgd;
^1da177e4c3f41 Linus Torvalds 2005-04-16 83 unsigned long end;
^1da177e4c3f41 Linus Torvalds 2005-04-16 84 int ret = 0;
^1da177e4c3f41 Linus Torvalds 2005-04-16 85
^1da177e4c3f41 Linus Torvalds 2005-04-16 86 kaddr &= PAGE_MASK;
^1da177e4c3f41 Linus Torvalds 2005-04-16 87 vaddr &= PAGE_MASK;
^1da177e4c3f41 Linus Torvalds 2005-04-16 88
^1da177e4c3f41 Linus Torvalds 2005-04-16 89 end = PAGE_ALIGN(vaddr + len);
^1da177e4c3f41 Linus Torvalds 2005-04-16 90
4eee1e72ad06bd Geert Uytterhoeven 2016-12-06 91 pr_debug("dvma: mapping kern %08lx to virt %08lx\n", kaddr, vaddr);
^1da177e4c3f41 Linus Torvalds 2005-04-16 92 pgd = pgd_offset_k(vaddr);
^1da177e4c3f41 Linus Torvalds 2005-04-16 93
^1da177e4c3f41 Linus Torvalds 2005-04-16 94 do {
^1da177e4c3f41 Linus Torvalds 2005-04-16 95 pmd_t *pmd;
^1da177e4c3f41 Linus Torvalds 2005-04-16 96 unsigned long end2;
^1da177e4c3f41 Linus Torvalds 2005-04-16 97
^1da177e4c3f41 Linus Torvalds 2005-04-16 @98 if((pmd = pmd_alloc(&init_mm, pgd, vaddr)) == NULL) {
^1da177e4c3f41 Linus Torvalds 2005-04-16 99 ret = -ENOMEM;
^1da177e4c3f41 Linus Torvalds 2005-04-16 100 goto out;
^1da177e4c3f41 Linus Torvalds 2005-04-16 101 }
^1da177e4c3f41 Linus Torvalds 2005-04-16 102
^1da177e4c3f41 Linus Torvalds 2005-04-16 103 if((end & PGDIR_MASK) > (vaddr & PGDIR_MASK))
^1da177e4c3f41 Linus Torvalds 2005-04-16 104 end2 = (vaddr + (PGDIR_SIZE-1)) & PGDIR_MASK;
^1da177e4c3f41 Linus Torvalds 2005-04-16 105 else
^1da177e4c3f41 Linus Torvalds 2005-04-16 106 end2 = end;
^1da177e4c3f41 Linus Torvalds 2005-04-16 107
^1da177e4c3f41 Linus Torvalds 2005-04-16 108 do {
^1da177e4c3f41 Linus Torvalds 2005-04-16 109 pte_t *pte;
^1da177e4c3f41 Linus Torvalds 2005-04-16 110 unsigned long end3;
^1da177e4c3f41 Linus Torvalds 2005-04-16 111
872fec16d9a0ed Hugh Dickins 2005-10-29 112 if((pte = pte_alloc_kernel(pmd, vaddr)) == NULL) {
^1da177e4c3f41 Linus Torvalds 2005-04-16 113 ret = -ENOMEM;
^1da177e4c3f41 Linus Torvalds 2005-04-16 114 goto out;
^1da177e4c3f41 Linus Torvalds 2005-04-16 115 }
^1da177e4c3f41 Linus Torvalds 2005-04-16 116
^1da177e4c3f41 Linus Torvalds 2005-04-16 117 if((end2 & PMD_MASK) > (vaddr & PMD_MASK))
^1da177e4c3f41 Linus Torvalds 2005-04-16 118 end3 = (vaddr + (PMD_SIZE-1)) & PMD_MASK;
^1da177e4c3f41 Linus Torvalds 2005-04-16 119 else
^1da177e4c3f41 Linus Torvalds 2005-04-16 120 end3 = end2;
^1da177e4c3f41 Linus Torvalds 2005-04-16 121
^1da177e4c3f41 Linus Torvalds 2005-04-16 122 do {
4eee1e72ad06bd Geert Uytterhoeven 2016-12-06 123 pr_debug("mapping %08lx phys to %08lx\n",
^1da177e4c3f41 Linus Torvalds 2005-04-16 124 __pa(kaddr), vaddr);
^1da177e4c3f41 Linus Torvalds 2005-04-16 125 set_pte(pte, pfn_pte(virt_to_pfn(kaddr),
^1da177e4c3f41 Linus Torvalds 2005-04-16 126 PAGE_KERNEL));
^1da177e4c3f41 Linus Torvalds 2005-04-16 127 pte++;
^1da177e4c3f41 Linus Torvalds 2005-04-16 128 kaddr += PAGE_SIZE;
^1da177e4c3f41 Linus Torvalds 2005-04-16 129 vaddr += PAGE_SIZE;
^1da177e4c3f41 Linus Torvalds 2005-04-16 130 } while(vaddr < end3);
^1da177e4c3f41 Linus Torvalds 2005-04-16 131
^1da177e4c3f41 Linus Torvalds 2005-04-16 132 } while(vaddr < end2);
^1da177e4c3f41 Linus Torvalds 2005-04-16 133
^1da177e4c3f41 Linus Torvalds 2005-04-16 134 } while(vaddr < end);
^1da177e4c3f41 Linus Torvalds 2005-04-16 135
^1da177e4c3f41 Linus Torvalds 2005-04-16 136 flush_tlb_all();
^1da177e4c3f41 Linus Torvalds 2005-04-16 137
^1da177e4c3f41 Linus Torvalds 2005-04-16 138 out:
^1da177e4c3f41 Linus Torvalds 2005-04-16 139 return ret;
^1da177e4c3f41 Linus Torvalds 2005-04-16 140 }
^1da177e4c3f41 Linus Torvalds 2005-04-16 141

:::::: The code at line 98 was first introduced by commit
:::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2

:::::: TO: Linus Torvalds <[email protected]>
:::::: CC: Linus Torvalds <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (6.48 kB)
.config.gz (14.60 kB)
Download all attachments