Skip to content

Commit

Permalink
parisc: Add Huge Page and HUGETLBFS support
Browse files Browse the repository at this point in the history
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: Helge Deller <deller@gmx.de>
  • Loading branch information
Helge Deller committed Nov 22, 2015
1 parent 337685e commit 736d216
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 15 deletions.
3 changes: 3 additions & 0 deletions arch/parisc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
85 changes: 85 additions & 0 deletions arch/parisc/include/asm/hugetlb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#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 */
45 changes: 31 additions & 14 deletions arch/parisc/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -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_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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
11 changes: 10 additions & 1 deletion arch/parisc/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
1 change: 1 addition & 0 deletions arch/parisc/mm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
#

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

0 comments on commit 736d216

Please sign in to comment.