Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 41151e77 authored by Becky Bruce's avatar Becky Bruce Committed by Benjamin Herrenschmidt
Browse files

powerpc: Hugetlb for BookE



Enable hugepages on Freescale BookE processors.  This allows the kernel to
use huge TLB entries to map pages, which can greatly reduce the number of
TLB misses and the amount of TLB thrashing experienced by applications with
large memory footprints.  Care should be taken when using this on FSL
processors, as the number of large TLB entries supported by the core is low
(16-64) on current processors.

The supported set of hugepage sizes include 4m, 16m, 64m, 256m, and 1g.
Page sizes larger than the max zone size are called "gigantic" pages and
must be allocated on the command line (and cannot be deallocated).

This is currently only fully implemented for Freescale 32-bit BookE
processors, but there is some infrastructure in the code for
64-bit BooKE.

Signed-off-by: default avatarBecky Bruce <beckyb@kernel.crashing.org>
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 7df5659e
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -429,8 +429,7 @@ config ARCH_POPULATES_NODE_MAP
	def_bool y

config SYS_SUPPORTS_HUGETLBFS
       def_bool y
       depends on PPC_BOOK3S_64
	bool

source "mm/Kconfig"

+61 −2
Original line number Diff line number Diff line
#ifndef _ASM_POWERPC_HUGETLB_H
#define _ASM_POWERPC_HUGETLB_H

#ifdef CONFIG_HUGETLB_PAGE
#include <asm/page.h>

extern struct kmem_cache *hugepte_cache;
extern void __init reserve_hugetlb_gpages(void);

static inline pte_t *hugepd_page(hugepd_t hpd)
{
	BUG_ON(!hugepd_ok(hpd));
	return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | PD_HUGE);
}

static inline unsigned int hugepd_shift(hugepd_t hpd)
{
	return hpd.pd & HUGEPD_SHIFT_MASK;
}

static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr,
				    unsigned pdshift)
{
	/*
	 * On 32-bit, we have multiple higher-level table entries that point to
	 * the same hugepte.  Just use the first one since they're all
	 * identical.  So for that case, idx=0.
	 */
	unsigned long idx = 0;

	pte_t *dir = hugepd_page(*hpdp);
#ifdef CONFIG_PPC64
	idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp);
#endif

	return dir + idx;
}

pte_t *huge_pte_offset_and_shift(struct mm_struct *mm,
				 unsigned long addr, unsigned *shift);

void flush_dcache_icache_hugepage(struct page *page);

#if defined(CONFIG_PPC_MM_SLICES) || defined(CONFIG_PPC_SUBPAGE_PROT)
int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
			   unsigned long len);
#else
static inline int is_hugepage_only_range(struct mm_struct *mm,
					 unsigned long addr,
					 unsigned long len)
{
	return 0;
}
#endif

void book3e_hugetlb_preload(struct mm_struct *mm, unsigned long ea, pte_t pte);
void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);

void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
			    unsigned long end, unsigned long floor,
@@ -50,8 +95,11 @@ static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
					    unsigned long addr, pte_t *ptep)
{
	unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1);
	return __pte(old);
#ifdef CONFIG_PPC64
	return __pte(pte_update(mm, addr, ptep, ~0UL, 1));
#else
	return __pte(pte_update(ptep, ~0UL, 0));
#endif
}

static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
@@ -93,4 +141,15 @@ static inline void arch_release_hugepage(struct page *page)
{
}

#else /* ! CONFIG_HUGETLB_PAGE */
static inline void reserve_hugetlb_gpages(void)
{
	pr_err("Cannot reserve gpages without hugetlb enabled\n");
}
static inline void flush_hugetlb_page(struct vm_area_struct *vma,
				      unsigned long vmaddr)
{
}
#endif

#endif /* _ASM_POWERPC_HUGETLB_H */
+7 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@
#define MAS2_M			0x00000004
#define MAS2_G			0x00000002
#define MAS2_E			0x00000001
#define MAS2_WIMGE_MASK		0x0000001f
#define MAS2_EPN_MASK(size)		(~0 << (size + 10))
#define MAS2_VAL(addr, size, flags)	((addr) & MAS2_EPN_MASK(size) | (flags))

@@ -80,6 +81,7 @@
#define MAS3_SW			0x00000004
#define MAS3_UR			0x00000002
#define MAS3_SR			0x00000001
#define MAS3_BAP_MASK		0x0000003f
#define MAS3_SPSIZE		0x0000003e
#define MAS3_SPSIZE_SHIFT	1

@@ -212,6 +214,11 @@ typedef struct {
	unsigned int	id;
	unsigned int	active;
	unsigned long	vdso_base;
#ifdef CONFIG_PPC_MM_SLICES
	u64 low_slices_psize;   /* SLB page size encodings */
	u64 high_slices_psize;  /* 4 bits per slice for now */
	u16 user_psize;         /* page size index */
#endif
} mm_context_t;

/* Page size definitions, common between 32 and 64-bit
+1 −2
Original line number Diff line number Diff line
@@ -262,8 +262,7 @@ extern void hash_failure_debug(unsigned long ea, unsigned long access,
extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
			     unsigned long pstart, unsigned long prot,
			     int psize, int ssize);
extern void add_gpage(unsigned long addr, unsigned long page_size,
			  unsigned long number_of_pages);
extern void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages);
extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);

extern void hpte_init_native(void);
+10 −8
Original line number Diff line number Diff line
@@ -175,14 +175,16 @@ extern u64 ppc64_rma_size;
#define MMU_PAGE_64K_AP	3	/* "Admixed pages" (hash64 only) */
#define MMU_PAGE_256K	4
#define MMU_PAGE_1M	5
#define MMU_PAGE_8M	6
#define MMU_PAGE_16M	7
#define MMU_PAGE_256M	8
#define MMU_PAGE_1G	9
#define MMU_PAGE_16G	10
#define MMU_PAGE_64G	11
#define MMU_PAGE_COUNT	12

#define MMU_PAGE_4M	6
#define MMU_PAGE_8M	7
#define MMU_PAGE_16M	8
#define MMU_PAGE_64M	9
#define MMU_PAGE_256M	10
#define MMU_PAGE_1G	11
#define MMU_PAGE_16G	12
#define MMU_PAGE_64G	13

#define MMU_PAGE_COUNT	14

#if defined(CONFIG_PPC_STD_MMU_64)
/* 64-bit classic hash table MMU */
Loading