Commit 361739c8 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven
Browse files

Merge branch 'pgtable-layout-rewrite' into for-v5.7

Peter Zijlstra <peterz@infradead.org> wrote:

   "In order to facilitate Will's READ_ONCE() patches, we need to fix
    m68k/motorola to not have a giant pmd_t. These patches do so and are
    tested using ARAnyM/68040."
parents 98d54f81 de9e354e
Loading
Loading
Loading
Loading
+14 −17
Original line number Diff line number Diff line
@@ -28,21 +28,22 @@ extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
	return (pmd_t *) pgd;
}

#define pmd_populate(mm, pmd, page) (pmd_val(*pmd) = \
	(unsigned long)(page_address(page)))
#define pmd_populate(mm, pmd, pte) (pmd_val(*pmd) = (unsigned long)(pte))

#define pmd_populate_kernel(mm, pmd, pte) (pmd_val(*pmd) = (unsigned long)(pte))
#define pmd_populate_kernel pmd_populate

#define pmd_pgtable(pmd) pmd_page(pmd)
#define pmd_pgtable(pmd) pfn_to_virt(pmd_val(pmd) >> PAGE_SHIFT)

static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pgtable,
				  unsigned long address)
{
	struct page *page = virt_to_page(pgtable);

	pgtable_pte_page_dtor(page);
	__free_page(page);
}

static inline struct page *pte_alloc_one(struct mm_struct *mm)
static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
{
	struct page *page = alloc_pages(GFP_DMA, 0);
	pte_t *pte;
@@ -54,20 +55,16 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm)
		return NULL;
	}

	pte = kmap(page);
	if (pte) {
	pte = page_address(page);
	clear_page(pte);
		__flush_page_to_ram(pte);
		flush_tlb_kernel_page(pte);
		nocache_page(pte);
	}
	kunmap(page);

	return page;
	return pte;
}

static inline void pte_free(struct mm_struct *mm, struct page *page)
static inline void pte_free(struct mm_struct *mm, pgtable_t pgtable)
{
	struct page *page = virt_to_page(pgtable);

	pgtable_pte_page_dtor(page);
	__free_page(page);
}
@@ -90,7 +87,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
	new_pgd = (pgd_t *)__get_free_page(GFP_DMA | __GFP_NOWARN);
	if (!new_pgd)
		return NULL;
	memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE);
	memcpy(new_pgd, swapper_pg_dir, PTRS_PER_PGD * sizeof(pgd_t));
	memset(new_pgd, 0, PAGE_OFFSET >> PGDIR_SHIFT);
	return new_pgd;
}
+26 −48
Original line number Diff line number Diff line
@@ -5,93 +5,71 @@
#include <asm/tlb.h>
#include <asm/tlbflush.h>

extern pmd_t *get_pointer_table(void);
extern int free_pointer_table(pmd_t *);
extern void mmu_page_ctor(void *page);
extern void mmu_page_dtor(void *page);

static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
{
	pte_t *pte;
enum m68k_table_types {
	TABLE_PGD = 0,
	TABLE_PMD = 0, /* same size as PGD */
	TABLE_PTE = 1,
};

	pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
	if (pte) {
		__flush_page_to_ram(pte);
		flush_tlb_kernel_page(pte);
		nocache_page(pte);
	}
extern void init_pointer_table(void *table, int type);
extern void *get_pointer_table(int type);
extern int free_pointer_table(void *table, int type);

	return pte;
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
{
	return get_pointer_table(TABLE_PTE);
}

static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
	cache_page(pte);
	free_page((unsigned long) pte);
	free_pointer_table(pte, TABLE_PTE);
}

static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
{
	struct page *page;
	pte_t *pte;

	page = alloc_pages(GFP_KERNEL|__GFP_ZERO, 0);
	if(!page)
		return NULL;
	if (!pgtable_pte_page_ctor(page)) {
		__free_page(page);
		return NULL;
	}

	pte = kmap(page);
	__flush_page_to_ram(pte);
	flush_tlb_kernel_page(pte);
	nocache_page(pte);
	kunmap(page);
	return page;
	return get_pointer_table(TABLE_PTE);
}

static inline void pte_free(struct mm_struct *mm, pgtable_t page)
static inline void pte_free(struct mm_struct *mm, pgtable_t pgtable)
{
	pgtable_pte_page_dtor(page);
	cache_page(kmap(page));
	kunmap(page);
	__free_page(page);
	free_pointer_table(pgtable, TABLE_PTE);
}

static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pgtable,
				  unsigned long address)
{
	pgtable_pte_page_dtor(page);
	cache_page(kmap(page));
	kunmap(page);
	__free_page(page);
	free_pointer_table(pgtable, TABLE_PTE);
}


static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
{
	return get_pointer_table();
	return get_pointer_table(TABLE_PMD);
}

static inline int pmd_free(struct mm_struct *mm, pmd_t *pmd)
{
	return free_pointer_table(pmd);
	return free_pointer_table(pmd, TABLE_PMD);
}

static inline int __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
				 unsigned long address)
{
	return free_pointer_table(pmd);
	return free_pointer_table(pmd, TABLE_PMD);
}


static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
	pmd_free(mm, (pmd_t *)pgd);
	free_pointer_table(pgd, TABLE_PGD);
}

static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
	return (pgd_t *)get_pointer_table();
	return get_pointer_table(TABLE_PGD);
}


@@ -102,9 +80,9 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *

static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page)
{
	pmd_set(pmd, page_address(page));
	pmd_set(pmd, page);
}
#define pmd_pgtable(pmd) pmd_page(pmd)
#define pmd_pgtable(pmd) ((pgtable_t)__pmd_page(pmd))

static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
{
+21 −15
Original line number Diff line number Diff line
@@ -23,7 +23,18 @@
#define _DESCTYPE_MASK	0x003

#define _CACHEMASK040	(~0x060)
#define _TABLE_MASK	(0xfffffe00)

/*
 * Currently set to the minimum alignment of table pointers (256 bytes).
 * The hardware only uses the low 4 bits for state:
 *
 *    3 - Used
 *    2 - Write Protected
 *  0,1 - Descriptor Type
 *
 * and has the rest of the bits reserved.
 */
#define _TABLE_MASK	(0xffffff00)

#define _PAGE_TABLE	(_PAGE_SHORT)
#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_NOCACHE)
@@ -108,13 +119,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)

static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
{
	unsigned long ptbl = virt_to_phys(ptep) | _PAGE_TABLE | _PAGE_ACCESSED;
	unsigned long *ptr = pmdp->pmd;
	short i = 16;
	while (--i >= 0) {
		*ptr++ = ptbl;
		ptbl += (sizeof(pte_t)*PTRS_PER_PTE/16);
	}
	pmd_val(*pmdp) = virt_to_phys(ptep) | _PAGE_TABLE | _PAGE_ACCESSED;
}

static inline void pud_set(pud_t *pudp, pmd_t *pmdp)
@@ -138,13 +143,14 @@ static inline void pud_set(pud_t *pudp, pmd_t *pmdp)
#define pmd_none(pmd)		(!pmd_val(pmd))
#define pmd_bad(pmd)		((pmd_val(pmd) & _DESCTYPE_MASK) != _PAGE_TABLE)
#define pmd_present(pmd)	(pmd_val(pmd) & _PAGE_TABLE)
#define pmd_clear(pmdp) ({			\
	unsigned long *__ptr = pmdp->pmd;	\
	short __i = 16;				\
	while (--__i >= 0)			\
		*__ptr++ = 0;			\
})
#define pmd_page(pmd)		virt_to_page(__va(pmd_val(pmd)))
#define pmd_clear(pmdp)		({ pmd_val(*pmdp) = 0; })

/*
 * m68k does not have huge pages (020/030 actually could), but generic code
 * expects pmd_page() to exists, only to then DCE it all. Provide a dummy to
 * make the compiler happy.
 */
#define pmd_page(pmd)		NULL


#define pud_none(pud)		(!pud_val(pud))
+13 −3
Original line number Diff line number Diff line
@@ -22,15 +22,25 @@
 * These are used to make use of C type-checking..
 */
#if !defined(CONFIG_MMU) || 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) }, })
typedef struct { unsigned long pmd; } pmd_t;
#define pmd_val(x)	((&x)->pmd)
#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;

#if defined(CONFIG_SUN3)
/*
 * Sun3 still uses the asm-generic/pgalloc.h code and thus needs this
 * definition. It would be possible to unify Sun3 and ColdFire pgalloc and have
 * all of m68k use the same type.
 */
typedef struct page *pgtable_t;
#else
typedef pte_t *pgtable_t;
#endif

#define pte_val(x)	((x).pte)
#define pgd_val(x)	((x).pgd)
+5 −5
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@

/* PMD_SHIFT determines the size of the area a second-level page table can map */
#if CONFIG_PGTABLE_LEVELS == 3
#define PMD_SHIFT	22
#define PMD_SHIFT	18
#endif
#define PMD_SIZE	(1UL << PMD_SHIFT)
#define PMD_MASK	(~(PMD_SIZE-1))
@@ -67,8 +67,8 @@
#define PTRS_PER_PMD	1
#define PTRS_PER_PGD	1024
#else
#define PTRS_PER_PTE	1024
#define PTRS_PER_PMD	8
#define PTRS_PER_PTE	64
#define PTRS_PER_PMD	128
#define PTRS_PER_PGD	128
#endif
#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
@@ -76,8 +76,8 @@

/* Virtual address region for use by kernel_map() */
#ifdef CONFIG_SUN3
#define KMAP_START     0x0DC00000
#define KMAP_END       0x0E000000
#define KMAP_START	0x0dc00000
#define KMAP_END	0x0e000000
#elif defined(CONFIG_COLDFIRE)
#define KMAP_START	0xe0000000
#define KMAP_END	0xf0000000
Loading