Skip to content

Commit 736d216

Browse files
committed
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: Helge Deller <[email protected]>
1 parent 337685e commit 736d216

File tree

6 files changed

+291
-15
lines changed

6 files changed

+291
-15
lines changed

arch/parisc/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ config PGTABLE_LEVELS
108108
default 3 if 64BIT && PARISC_PAGE_SIZE_4KB
109109
default 2
110110

111+
config SYS_SUPPORTS_HUGETLBFS
112+
def_bool y if PA20
113+
111114
source "init/Kconfig"
112115

113116
source "kernel/Kconfig.freezer"

arch/parisc/include/asm/hugetlb.h

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#ifndef _ASM_PARISC64_HUGETLB_H
2+
#define _ASM_PARISC64_HUGETLB_H
3+
4+
#include <asm/page.h>
5+
#include <asm-generic/hugetlb.h>
6+
7+
8+
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
9+
pte_t *ptep, pte_t pte);
10+
11+
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
12+
pte_t *ptep);
13+
14+
static inline int is_hugepage_only_range(struct mm_struct *mm,
15+
unsigned long addr,
16+
unsigned long len) {
17+
return 0;
18+
}
19+
20+
/*
21+
* If the arch doesn't supply something else, assume that hugepage
22+
* size aligned regions are ok without further preparation.
23+
*/
24+
static inline int prepare_hugepage_range(struct file *file,
25+
unsigned long addr, unsigned long len)
26+
{
27+
if (len & ~HPAGE_MASK)
28+
return -EINVAL;
29+
if (addr & ~HPAGE_MASK)
30+
return -EINVAL;
31+
return 0;
32+
}
33+
34+
static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
35+
unsigned long addr, unsigned long end,
36+
unsigned long floor,
37+
unsigned long ceiling)
38+
{
39+
free_pgd_range(tlb, addr, end, floor, ceiling);
40+
}
41+
42+
static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
43+
unsigned long addr, pte_t *ptep)
44+
{
45+
}
46+
47+
static inline int huge_pte_none(pte_t pte)
48+
{
49+
return pte_none(pte);
50+
}
51+
52+
static inline pte_t huge_pte_wrprotect(pte_t pte)
53+
{
54+
return pte_wrprotect(pte);
55+
}
56+
57+
static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
58+
unsigned long addr, pte_t *ptep)
59+
{
60+
pte_t old_pte = *ptep;
61+
set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
62+
}
63+
64+
static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
65+
unsigned long addr, pte_t *ptep,
66+
pte_t pte, int dirty)
67+
{
68+
int changed = !pte_same(*ptep, pte);
69+
if (changed) {
70+
set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
71+
flush_tlb_page(vma, addr);
72+
}
73+
return changed;
74+
}
75+
76+
static inline pte_t huge_ptep_get(pte_t *ptep)
77+
{
78+
return *ptep;
79+
}
80+
81+
static inline void arch_clear_hugepage_flags(struct page *page)
82+
{
83+
}
84+
85+
#endif /* _ASM_PARISC64_HUGETLB_H */

arch/parisc/kernel/entry.S

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -502,21 +502,38 @@
502502
STREG \pte,0(\ptp)
503503
.endm
504504

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

509514
/* Drop prot bits and convert to page addr for iitlbt and idtlbt */
510-
.macro convert_for_tlb_insert20 pte
515+
.macro convert_for_tlb_insert20 pte,tmp
516+
#ifdef CONFIG_HUGETLB_PAGE
517+
copy \pte,\tmp
518+
extrd,u \tmp,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
519+
64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
520+
521+
depdi _PAGE_SIZE_ENCODING_DEFAULT,63,\
522+
(63-58)+PAGE_ADD_SHIFT,\pte
523+
extrd,u,*= \tmp,_PAGE_HPAGE_BIT+32,1,%r0
524+
depdi _HUGE_PAGE_SIZE_ENCODING_DEFAULT,63,\
525+
(63-58)+PAGE_ADD_HUGE_SHIFT,\pte
526+
#else /* Huge pages disabled */
511527
extrd,u \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
512528
64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
513529
depdi _PAGE_SIZE_ENCODING_DEFAULT,63,\
514530
(63-58)+PAGE_ADD_SHIFT,\pte
531+
#endif
515532
.endm
516533

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

555572
/* Drop prot bits and convert to page addr for iitlbt and idtlbt */
556-
convert_for_tlb_insert20 \pte
573+
convert_for_tlb_insert20 \pte \tmp
557574
.endm
558575

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

1145-
make_insert_tlb spc,pte,prot
1162+
make_insert_tlb spc,pte,prot,t1
11461163

11471164
idtlbt pte,prot
11481165

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

1171-
make_insert_tlb spc,pte,prot
1188+
make_insert_tlb spc,pte,prot,t1
11721189

11731190
idtlbt pte,prot
11741191

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

1265-
make_insert_tlb spc,pte,prot
1282+
make_insert_tlb spc,pte,prot,t1
12661283

12671284
f_extend pte,t1
12681285

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

1293-
make_insert_tlb spc,pte,prot
1310+
make_insert_tlb spc,pte,prot,t1
12941311

12951312
f_extend pte,t1
12961313

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

1402-
make_insert_tlb spc,pte,prot
1419+
make_insert_tlb spc,pte,prot,t1
14031420

14041421
iitlbt pte,prot
14051422

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

1426-
make_insert_tlb spc,pte,prot
1443+
make_insert_tlb spc,pte,prot,t1
14271444

14281445
iitlbt pte,prot
14291446

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

1512-
make_insert_tlb spc,pte,prot
1529+
make_insert_tlb spc,pte,prot,t1
15131530

15141531
f_extend pte,t1
15151532

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

1532-
make_insert_tlb spc,pte,prot
1549+
make_insert_tlb spc,pte,prot,t1
15331550

15341551
f_extend pte,t1
15351552

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

1564-
make_insert_tlb spc,pte,prot
1581+
make_insert_tlb spc,pte,prot,t1
15651582

15661583
idtlbt pte,prot
15671584

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

1608-
make_insert_tlb spc,pte,prot
1625+
make_insert_tlb spc,pte,prot,t1
16091626

16101627
f_extend pte,t1
16111628

arch/parisc/kernel/setup.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,16 @@ void __init setup_arch(char **cmdline_p)
130130
printk(KERN_INFO "The 32-bit Kernel has started...\n");
131131
#endif
132132

133-
printk(KERN_INFO "Default page size is %dKB.\n", (int)(PAGE_SIZE / 1024));
133+
printk(KERN_INFO "Kernel default page size is %d KB. Huge pages ",
134+
(int)(PAGE_SIZE / 1024));
135+
#ifdef CONFIG_HUGETLB_PAGE
136+
printk(KERN_CONT "enabled with %d MB physical and %d MB virtual size",
137+
1 << (REAL_HPAGE_SHIFT - 20), 1 << (HPAGE_SHIFT - 20));
138+
#else
139+
printk(KERN_CONT "disabled");
140+
#endif
141+
printk(KERN_CONT ".\n");
142+
134143

135144
pdc_console_init();
136145

arch/parisc/mm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
#
44

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

0 commit comments

Comments
 (0)