Commit 8747ff70 authored by Vineet Gupta's avatar Vineet Gupta
Browse files

ARC: mm: support 4 levels of page tables

parent 2dde02ab
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -41,6 +41,17 @@ typedef struct {
#define pgd_val(x)	((x).pgd)
#define __pgd(x)	((pgd_t) { (x) })

#if CONFIG_PGTABLE_LEVELS > 3

typedef struct {
	unsigned long pud;
} pud_t;

#define pud_val(x)      	((x).pud)
#define __pud(x)        	((pud_t) { (x) })

#endif

#if CONFIG_PGTABLE_LEVELS > 2

typedef struct {
+11 −0
Original line number Diff line number Diff line
@@ -70,6 +70,17 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
	return ret;
}

#if CONFIG_PGTABLE_LEVELS > 3

static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4dp, pud_t *pudp)
{
	set_p4d(p4dp, __p4d((unsigned long)pudp));
}

#define __pud_free_tlb(tlb, pmd, addr)  pud_free((tlb)->mm, pmd)

#endif

#if CONFIG_PGTABLE_LEVELS > 2

static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmdp)
+40 −5
Original line number Diff line number Diff line
@@ -54,8 +54,13 @@
/*
 * A default 3 level paging testing setup in software walked MMU
 *   MMUv4 (8K page): <4> : <7> : <8> : <13>
 * A default 4 level paging testing setup in software walked MMU
 *   MMUv4 (8K page): <4> : <3> : <4> : <8> : <13>
 */
#define PGDIR_SHIFT		28
#if CONFIG_PGTABLE_LEVELS > 3
#define PUD_SHIFT		25
#endif
#if CONFIG_PGTABLE_LEVELS > 2
#define PMD_SHIFT		21
#endif
@@ -66,17 +71,25 @@
#define PGDIR_MASK		(~(PGDIR_SIZE - 1))
#define PTRS_PER_PGD		BIT(32 - PGDIR_SHIFT)

#if CONFIG_PGTABLE_LEVELS > 3
#define PUD_SIZE		BIT(PUD_SHIFT)
#define PUD_MASK		(~(PUD_SIZE - 1))
#define PTRS_PER_PUD		BIT(PGDIR_SHIFT - PUD_SHIFT)
#endif

#if CONFIG_PGTABLE_LEVELS > 2
#define PMD_SIZE		BIT(PMD_SHIFT)
#define PMD_MASK		(~(PMD_SIZE - 1))
#define PTRS_PER_PMD		BIT(PGDIR_SHIFT - PMD_SHIFT)
#define PTRS_PER_PMD		BIT(PUD_SHIFT - PMD_SHIFT)
#endif

#define PTRS_PER_PTE		BIT(PMD_SHIFT - PAGE_SHIFT)

#ifndef __ASSEMBLY__

#if CONFIG_PGTABLE_LEVELS > 2
#if CONFIG_PGTABLE_LEVELS > 3
#include <asm-generic/pgtable-nop4d.h>
#elif CONFIG_PGTABLE_LEVELS > 2
#include <asm-generic/pgtable-nopud.h>
#else
#include <asm-generic/pgtable-nopmd.h>
@@ -91,9 +104,31 @@
#define pgd_ERROR(e) \
	pr_crit("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))

#if CONFIG_PGTABLE_LEVELS > 3

/* In 4 level paging, p4d_* macros work on pgd */
#define p4d_none(x)		(!p4d_val(x))
#define p4d_bad(x)		((p4d_val(x) & ~PAGE_MASK))
#define p4d_present(x)		(p4d_val(x))
#define p4d_clear(xp)		do { p4d_val(*(xp)) = 0; } while (0)
#define p4d_pgtable(p4d)	((pud_t *)(p4d_val(p4d) & PAGE_MASK))
#define p4d_page(p4d)		virt_to_page(p4d_pgtable(p4d))
#define set_p4d(p4dp, p4d)	(*(p4dp) = p4d)

/*
 * 2nd level paging: pud
 */
#define pud_ERROR(e) \
	pr_crit("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e))

#endif

#if CONFIG_PGTABLE_LEVELS > 2

/* In 3 level paging, pud_* macros work on pgd */
/*
 * In 3 level paging, pud_* macros work on pgd
 * In 4 level paging, pud_* macros work on pud
 */
#define pud_none(x)		(!pud_val(x))
#define pud_bad(x)		((pud_val(x) & ~PAGE_MASK))
#define pud_present(x)		(pud_val(x))
@@ -103,7 +138,7 @@
#define set_pud(pudp, pud)	(*(pudp) = pud)

/*
 * 2nd level paging: pmd
 * 3rd level paging: pmd
 */
#define pmd_ERROR(e) \
	pr_crit("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
@@ -131,7 +166,7 @@
#define pmd_pgtable(pmd)	((pgtable_t) pmd_page_vaddr(pmd))

/*
 * 3rd level paging: pte
 * 4th level paging: pte
 */
#define pte_ERROR(e) \
	pr_crit("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+2 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ noinline static int handle_kernel_vaddr_fault(unsigned long address)
	if (!p4d_present(*p4d_k))
		goto bad_area;

	set_p4d(p4d, *p4d_k);

	pud = pud_offset(p4d, address);
	pud_k = pud_offset(p4d_k, address);
	if (!pud_present(*pud_k))
+1 −0
Original line number Diff line number Diff line
@@ -191,6 +191,7 @@ void __init mem_init(void)
	highmem_init();

	BUILD_BUG_ON((PTRS_PER_PGD * sizeof(pgd_t)) > PAGE_SIZE);
	BUILD_BUG_ON((PTRS_PER_PUD * sizeof(pud_t)) > PAGE_SIZE);
	BUILD_BUG_ON((PTRS_PER_PMD * sizeof(pmd_t)) > PAGE_SIZE);
	BUILD_BUG_ON((PTRS_PER_PTE * sizeof(pte_t)) > PAGE_SIZE);
}
Loading