Unverified Commit 9195c294 authored by Palmer Dabbelt's avatar Palmer Dabbelt
Browse files

RISC-V: Add Sv57 page table support

This implements Sv57 support at runtime. The kernel will try to boot
with 5-level page table firstly , and will fallback to 4-level if the HW
does not support it. And it will finally fallback to 3-level if the HW
alse does not support sv48.

* riscv-sv57:
  riscv: mm: Support kasan for sv57
  riscv: mm: Set sv57 on defaultly
  riscv: mm: Prepare pt_ops helper functions for sv57
  riscv: mm: Control p4d's folding by pgtable_l5_enabled
parents 67ff2f26 8fbdccd2
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ config PAGE_OFFSET
	hex
	default 0xC0000000 if 32BIT
	default 0x80000000 if 64BIT && !MMU
	default 0xffffaf8000000000 if 64BIT
	default 0xff60000000000000 if 64BIT

config KASAN_SHADOW_OFFSET
	hex
@@ -202,7 +202,7 @@ config FIX_EARLYCON_MEM

config PGTABLE_LEVELS
	int
	default 4 if 64BIT
	default 5 if 64BIT
	default 2

config LOCKDEP_SUPPORT
+1 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@
#define SATP_PPN	_AC(0x00000FFFFFFFFFFF, UL)
#define SATP_MODE_39	_AC(0x8000000000000000, UL)
#define SATP_MODE_48	_AC(0x9000000000000000, UL)
#define SATP_MODE_57	_AC(0xa000000000000000, UL)
#define SATP_ASID_BITS	16
#define SATP_ASID_SHIFT	44
#define SATP_ASID_MASK	_AC(0xFFFF, UL)
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ enum fixed_addresses {
	FIX_PTE,
	FIX_PMD,
	FIX_PUD,
	FIX_P4D,
	FIX_TEXT_POKE1,
	FIX_TEXT_POKE0,
	FIX_EARLYCON_MEM_BASE,
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
 * By default, CONFIG_PAGE_OFFSET value corresponds to SV48 address space so
 * define the PAGE_OFFSET value for SV39.
 */
#define PAGE_OFFSET_L4		_AC(0xffffaf8000000000, UL)
#define PAGE_OFFSET_L3		_AC(0xffffffd800000000, UL)
#else
#define PAGE_OFFSET		_AC(CONFIG_PAGE_OFFSET, UL)
+49 −0
Original line number Diff line number Diff line
@@ -59,6 +59,26 @@ static inline void p4d_populate_safe(struct mm_struct *mm, p4d_t *p4d,
	}
}

static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, p4d_t *p4d)
{
	if (pgtable_l5_enabled) {
		unsigned long pfn = virt_to_pfn(p4d);

		set_pgd(pgd, __pgd((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
	}
}

static inline void pgd_populate_safe(struct mm_struct *mm, pgd_t *pgd,
				     p4d_t *p4d)
{
	if (pgtable_l5_enabled) {
		unsigned long pfn = virt_to_pfn(p4d);

		set_pgd_safe(pgd,
			     __pgd((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE));
	}
}

#define pud_alloc_one pud_alloc_one
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
{
@@ -76,6 +96,35 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)
}

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

#define p4d_alloc_one p4d_alloc_one
static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long addr)
{
	if (pgtable_l5_enabled) {
		gfp_t gfp = GFP_PGTABLE_USER;

		if (mm == &init_mm)
			gfp = GFP_PGTABLE_KERNEL;
		return (p4d_t *)get_zeroed_page(gfp);
	}

	return NULL;
}

static inline void __p4d_free(struct mm_struct *mm, p4d_t *p4d)
{
	BUG_ON((unsigned long)p4d & (PAGE_SIZE-1));
	free_page((unsigned long)p4d);
}

#define p4d_free p4d_free
static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
{
	if (pgtable_l5_enabled)
		__p4d_free(mm, p4d);
}

#define __p4d_free_tlb(tlb, p4d, addr)  p4d_free((tlb)->mm, p4d)
#endif /* __PAGETABLE_PMD_FOLDED */

static inline pgd_t *pgd_alloc(struct mm_struct *mm)
Loading