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

Commit 736d2169 authored by Helge Deller's avatar Helge Deller
Browse files

parisc: Add Huge Page and HUGETLBFS support



This patch adds huge page support to allow userspace to allocate huge
pages and to use hugetlbfs filesystem on 32- and 64-bit Linux kernels.
A later patch will add kernel support to map kernel text and data on
huge pages.

The only requirement is, that the kernel needs to be compiled for a
PA8X00 CPU (PA2.0 architecture). Older PA1.X CPUs do not support
variable page sizes. 64bit Kernels are compiled for PA2.0 by default.

Technically on parisc multiple physical huge pages may be needed to
emulate standard 2MB huge pages.

Signed-off-by: default avatarHelge Deller <deller@gmx.de>
parent 337685e5
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -108,6 +108,9 @@ config PGTABLE_LEVELS
	default 3 if 64BIT && PARISC_PAGE_SIZE_4KB
	default 2

config SYS_SUPPORTS_HUGETLBFS
	def_bool y if PA20

source "init/Kconfig"

source "kernel/Kconfig.freezer"
+85 −0
Original line number Diff line number Diff line
#ifndef _ASM_PARISC64_HUGETLB_H
#define _ASM_PARISC64_HUGETLB_H

#include <asm/page.h>
#include <asm-generic/hugetlb.h>


void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
		     pte_t *ptep, pte_t pte);

pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
			      pte_t *ptep);

static inline int is_hugepage_only_range(struct mm_struct *mm,
					 unsigned long addr,
					 unsigned long len) {
	return 0;
}

/*
 * If the arch doesn't supply something else, assume that hugepage
 * size aligned regions are ok without further preparation.
 */
static inline int prepare_hugepage_range(struct file *file,
			unsigned long addr, unsigned long len)
{
	if (len & ~HPAGE_MASK)
		return -EINVAL;
	if (addr & ~HPAGE_MASK)
		return -EINVAL;
	return 0;
}

static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
					  unsigned long addr, unsigned long end,
					  unsigned long floor,
					  unsigned long ceiling)
{
	free_pgd_range(tlb, addr, end, floor, ceiling);
}

static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
					 unsigned long addr, pte_t *ptep)
{
}

static inline int huge_pte_none(pte_t pte)
{
	return pte_none(pte);
}

static inline pte_t huge_pte_wrprotect(pte_t pte)
{
	return pte_wrprotect(pte);
}

static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
					   unsigned long addr, pte_t *ptep)
{
	pte_t old_pte = *ptep;
	set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
}

static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
					     unsigned long addr, pte_t *ptep,
					     pte_t pte, int dirty)
{
	int changed = !pte_same(*ptep, pte);
	if (changed) {
		set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
		flush_tlb_page(vma, addr);
	}
	return changed;
}

static inline pte_t huge_ptep_get(pte_t *ptep)
{
	return *ptep;
}

static inline void arch_clear_hugepage_flags(struct page *page)
{
}

#endif /* _ASM_PARISC64_HUGETLB_H */
+31 −14
Original line number Diff line number Diff line
@@ -502,21 +502,38 @@
	STREG		\pte,0(\ptp)
	.endm

	/* We have (depending on the page size):
	 * - 38 to 52-bit Physical Page Number
	 * - 12 to 26-bit page offset
	 */
	/* bitshift difference between a PFN (based on kernel's PAGE_SIZE)
	 * to a CPU TLB 4k PFN (4k => 12 bits to shift) */
	#define PAGE_ADD_SHIFT		(PAGE_SHIFT-12)
	#define PAGE_ADD_HUGE_SHIFT	(REAL_HPAGE_SHIFT-12)

	/* Drop prot bits and convert to page addr for iitlbt and idtlbt */
	.macro		convert_for_tlb_insert20 pte
	.macro		convert_for_tlb_insert20 pte,tmp
#ifdef CONFIG_HUGETLB_PAGE
	copy		\pte,\tmp
	extrd,u		\tmp,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
				64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte

	depdi		_PAGE_SIZE_ENCODING_DEFAULT,63,\
				(63-58)+PAGE_ADD_SHIFT,\pte
	extrd,u,*=	\tmp,_PAGE_HPAGE_BIT+32,1,%r0
	depdi		_HUGE_PAGE_SIZE_ENCODING_DEFAULT,63,\
				(63-58)+PAGE_ADD_HUGE_SHIFT,\pte
#else /* Huge pages disabled */
	extrd,u		\pte,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
				64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
	depdi		_PAGE_SIZE_ENCODING_DEFAULT,63,\
				(63-58)+PAGE_ADD_SHIFT,\pte
#endif
	.endm

	/* Convert the pte and prot to tlb insertion values.  How
	 * this happens is quite subtle, read below */
	.macro		make_insert_tlb	spc,pte,prot
	.macro		make_insert_tlb	spc,pte,prot,tmp
	space_to_prot   \spc \prot        /* create prot id from space */
	/* The following is the real subtlety.  This is depositing
	 * T <-> _PAGE_REFTRAP
@@ -553,7 +570,7 @@
	depdi		1,12,1,\prot

	/* Drop prot bits and convert to page addr for iitlbt and idtlbt */
	convert_for_tlb_insert20 \pte
	convert_for_tlb_insert20 \pte \tmp
	.endm

	/* Identical macro to make_insert_tlb above, except it
@@ -1142,7 +1159,7 @@ dtlb_miss_20w:
	tlb_lock	spc,ptp,pte,t0,t1,dtlb_check_alias_20w
	update_accessed	ptp,pte,t0,t1

	make_insert_tlb	spc,pte,prot
	make_insert_tlb	spc,pte,prot,t1
	
	idtlbt          pte,prot

@@ -1168,7 +1185,7 @@ nadtlb_miss_20w:
	tlb_lock	spc,ptp,pte,t0,t1,nadtlb_check_alias_20w
	update_accessed	ptp,pte,t0,t1

	make_insert_tlb	spc,pte,prot
	make_insert_tlb	spc,pte,prot,t1

	idtlbt          pte,prot

@@ -1262,7 +1279,7 @@ dtlb_miss_20:
	tlb_lock	spc,ptp,pte,t0,t1,dtlb_check_alias_20
	update_accessed	ptp,pte,t0,t1

	make_insert_tlb	spc,pte,prot
	make_insert_tlb	spc,pte,prot,t1

	f_extend	pte,t1

@@ -1290,7 +1307,7 @@ nadtlb_miss_20:
	tlb_lock	spc,ptp,pte,t0,t1,nadtlb_check_alias_20
	update_accessed	ptp,pte,t0,t1

	make_insert_tlb	spc,pte,prot
	make_insert_tlb	spc,pte,prot,t1

	f_extend	pte,t1
	
@@ -1399,7 +1416,7 @@ itlb_miss_20w:
	tlb_lock	spc,ptp,pte,t0,t1,itlb_fault
	update_accessed	ptp,pte,t0,t1

	make_insert_tlb	spc,pte,prot
	make_insert_tlb	spc,pte,prot,t1
	
	iitlbt          pte,prot

@@ -1423,7 +1440,7 @@ naitlb_miss_20w:
	tlb_lock	spc,ptp,pte,t0,t1,naitlb_check_alias_20w
	update_accessed	ptp,pte,t0,t1

	make_insert_tlb	spc,pte,prot
	make_insert_tlb	spc,pte,prot,t1

	iitlbt          pte,prot

@@ -1509,7 +1526,7 @@ itlb_miss_20:
	tlb_lock	spc,ptp,pte,t0,t1,itlb_fault
	update_accessed	ptp,pte,t0,t1

	make_insert_tlb	spc,pte,prot
	make_insert_tlb	spc,pte,prot,t1

	f_extend	pte,t1

@@ -1529,7 +1546,7 @@ naitlb_miss_20:
	tlb_lock	spc,ptp,pte,t0,t1,naitlb_check_alias_20
	update_accessed	ptp,pte,t0,t1

	make_insert_tlb	spc,pte,prot
	make_insert_tlb	spc,pte,prot,t1

	f_extend	pte,t1

@@ -1561,7 +1578,7 @@ dbit_trap_20w:
	tlb_lock	spc,ptp,pte,t0,t1,dbit_fault
	update_dirty	ptp,pte,t1

	make_insert_tlb	spc,pte,prot
	make_insert_tlb	spc,pte,prot,t1
		
	idtlbt          pte,prot

@@ -1605,7 +1622,7 @@ dbit_trap_20:
	tlb_lock	spc,ptp,pte,t0,t1,dbit_fault
	update_dirty	ptp,pte,t1

	make_insert_tlb	spc,pte,prot
	make_insert_tlb	spc,pte,prot,t1

	f_extend	pte,t1
	
+10 −1
Original line number Diff line number Diff line
@@ -130,7 +130,16 @@ void __init setup_arch(char **cmdline_p)
	printk(KERN_INFO "The 32-bit Kernel has started...\n");
#endif

	printk(KERN_INFO "Default page size is %dKB.\n", (int)(PAGE_SIZE / 1024));
	printk(KERN_INFO "Kernel default page size is %d KB. Huge pages ",
		(int)(PAGE_SIZE / 1024));
#ifdef CONFIG_HUGETLB_PAGE
	printk(KERN_CONT "enabled with %d MB physical and %d MB virtual size",
		 1 << (REAL_HPAGE_SHIFT - 20), 1 << (HPAGE_SHIFT - 20));
#else
	printk(KERN_CONT "disabled");
#endif
	printk(KERN_CONT ".\n");


	pdc_console_init();

+1 −0
Original line number Diff line number Diff line
@@ -3,3 +3,4 @@
#

obj-y	 := init.o fault.o ioremap.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
Loading