Commit 5a588e5b authored by Kenneth W. Chen's avatar Kenneth W. Chen Committed by David Mosberger

[PATCH] ia64: make hugetlbfs page size a boot-time option

This patch makes it possible to select the hugetlbfs page size at boot-time,
rather than at compile-time.  We believe we have resolved all the remaining
issues.  All critical speed path has been taken care of, i.e., vhpt handler
and context switch.  There should be no performance penalty with this dynamic
hugetlb page size feature.

We would like to thank Jack Steiner for his initiative on this feature
and his initial cool working patch.
parent 83f56aef
...@@ -288,39 +288,6 @@ config FORCE_MAX_ZONEORDER ...@@ -288,39 +288,6 @@ config FORCE_MAX_ZONEORDER
int int
default "18" default "18"
choice
prompt "Huge TLB page size"
depends on HUGETLB_PAGE
default HUGETLB_PAGE_SIZE_16MB
config HUGETLB_PAGE_SIZE_4GB
depends on MCKINLEY
bool "4GB"
config HUGETLB_PAGE_SIZE_1GB
depends on MCKINLEY
bool "1GB"
config HUGETLB_PAGE_SIZE_256MB
bool "256MB"
config HUGETLB_PAGE_SIZE_64MB
bool "64MB"
config HUGETLB_PAGE_SIZE_16MB
bool "16MB"
config HUGETLB_PAGE_SIZE_4MB
bool "4MB"
config HUGETLB_PAGE_SIZE_1MB
bool "1MB"
config HUGETLB_PAGE_SIZE_256KB
bool "256KB"
endchoice
config IA64_PAL_IDLE config IA64_PAL_IDLE
bool "Use PAL_HALT_LIGHT in idle loop" bool "Use PAL_HALT_LIGHT in idle loop"
help help
......
...@@ -118,10 +118,11 @@ ENTRY(vhpt_miss) ...@@ -118,10 +118,11 @@ ENTRY(vhpt_miss)
#ifdef CONFIG_HUGETLB_PAGE #ifdef CONFIG_HUGETLB_PAGE
extr.u r26=r25,2,6 extr.u r26=r25,2,6
;; ;;
cmp.eq p8,p0=HPAGE_SHIFT,r26 cmp.ne p8,p0=r18,r26
sub r27=r26,r18
;; ;;
(p8) dep r25=r18,r25,2,6 (p8) dep r25=r18,r25,2,6
(p8) shr r22=r22,HPAGE_SHIFT-PAGE_SHIFT (p8) shr r22=r22,r27
#endif #endif
;; ;;
cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
......
/* /*
* IA-64 Huge TLB Page Support for Kernel. * IA-64 Huge TLB Page Support for Kernel.
* *
* Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com> * Copyright (C) 2002-2004 Rohit Seth <rohit.seth@intel.com>
* Copyright (C) 2003-2004 Ken Chen <kenneth.w.chen@intel.com>
*
* Sep, 2003: add numa support
* Feb, 2004: dynamic hugetlb page size via boot parameter
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -18,11 +22,10 @@ ...@@ -18,11 +22,10 @@
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT)
static long htlbpagemem; static long htlbpagemem;
int htlbpage_max; int htlbpage_max;
static long htlbzone_pages; static long htlbzone_pages;
unsigned int hpage_shift=HPAGE_SHIFT_DEFAULT;
static struct list_head hugepage_freelists[MAX_NUMNODES]; static struct list_head hugepage_freelists[MAX_NUMNODES];
static spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED; static spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED;
...@@ -407,7 +410,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u ...@@ -407,7 +410,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u
return -EINVAL; return -EINVAL;
/* This code assumes that REGION_HPAGE != 0. */ /* This code assumes that REGION_HPAGE != 0. */
if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1))) if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1)))
addr = TASK_HPAGE_BASE; addr = HPAGE_REGION_BASE;
else else
addr = ALIGN(addr, HPAGE_SIZE); addr = ALIGN(addr, HPAGE_SIZE);
for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
...@@ -520,6 +523,35 @@ static int __init hugetlb_setup(char *s) ...@@ -520,6 +523,35 @@ static int __init hugetlb_setup(char *s)
} }
__setup("hugepages=", hugetlb_setup); __setup("hugepages=", hugetlb_setup);
static int __init hugetlb_setup_sz(char *str)
{
u64 tr_pages;
unsigned long long size;
if (ia64_pal_vm_page_size(&tr_pages, NULL) != 0)
/*
* shouldn't happen, but just in case.
*/
tr_pages = 0x15557000UL;
size = memparse(str, &str);
if (*str || (size & (size-1)) || !(tr_pages & size) ||
size <= PAGE_SIZE ||
size >= (1UL << PAGE_SHIFT << MAX_ORDER)) {
printk(KERN_WARNING "Invalid huge page size specified\n");
return 1;
}
hpage_shift = __ffs(size);
/*
* boot cpu already executed ia64_mmu_init, and has HPAGE_SHIFT_DEFAULT
* override here with new page shift.
*/
ia64_set_rr(HPAGE_REGION_BASE, hpage_shift << 2);
return 1;
}
__setup("hugepagesz=", hugetlb_setup_sz);
static int __init hugetlb_init(void) static int __init hugetlb_init(void)
{ {
int i; int i;
...@@ -540,7 +572,7 @@ static int __init hugetlb_init(void) ...@@ -540,7 +572,7 @@ static int __init hugetlb_init(void)
printk("Total HugeTLB memory allocated, %ld\n", htlbpagemem); printk("Total HugeTLB memory allocated, %ld\n", htlbpagemem);
return 0; return 0;
} }
module_init(hugetlb_init); __initcall(hugetlb_init);
int hugetlb_report_meminfo(char *buf) int hugetlb_report_meminfo(char *buf)
{ {
......
...@@ -342,6 +342,10 @@ ia64_mmu_init (void *my_cpu_data) ...@@ -342,6 +342,10 @@ ia64_mmu_init (void *my_cpu_data)
ia64_tlb_init(); ia64_tlb_init();
#ifdef CONFIG_HUGETLB_PAGE
ia64_set_rr(HPAGE_REGION_BASE, HPAGE_SHIFT << 2);
#endif
#ifdef CONFIG_IA64_MCA #ifdef CONFIG_IA64_MCA
cpu = smp_processor_id(); cpu = smp_processor_id();
......
...@@ -140,8 +140,9 @@ reload_context (mm_context_t context) ...@@ -140,8 +140,9 @@ reload_context (mm_context_t context)
{ {
unsigned long rid; unsigned long rid;
unsigned long rid_incr = 0; unsigned long rid_incr = 0;
unsigned long rr0, rr1, rr2, rr3, rr4; unsigned long rr0, rr1, rr2, rr3, rr4, old_rr4;
old_rr4 = ia64_get_rr(0x8000000000000000);
rid = context << 3; /* make space for encoding the region number */ rid = context << 3; /* make space for encoding the region number */
rid_incr = 1 << 8; rid_incr = 1 << 8;
...@@ -152,7 +153,7 @@ reload_context (mm_context_t context) ...@@ -152,7 +153,7 @@ reload_context (mm_context_t context)
rr3 = rr0 + 3*rid_incr; rr3 = rr0 + 3*rid_incr;
rr4 = rr0 + 4*rid_incr; rr4 = rr0 + 4*rid_incr;
#ifdef CONFIG_HUGETLB_PAGE #ifdef CONFIG_HUGETLB_PAGE
rr4 = (rr4 & (~(0xfcUL))) | (HPAGE_SHIFT << 2); rr4 = (rr4 & (~(0xfcUL))) | (old_rr4 & 0xfc);
#endif #endif
ia64_set_rr(0x0000000000000000, rr0); ia64_set_rr(0x0000000000000000, rr0);
......
...@@ -37,31 +37,14 @@ ...@@ -37,31 +37,14 @@
#define RGN_MAP_LIMIT ((1UL << (4*PAGE_SHIFT - 12)) - PAGE_SIZE) /* per region addr limit */ #define RGN_MAP_LIMIT ((1UL << (4*PAGE_SHIFT - 12)) - PAGE_SIZE) /* per region addr limit */
#ifdef CONFIG_HUGETLB_PAGE #ifdef CONFIG_HUGETLB_PAGE
# define REGION_HPAGE (4UL) /* note: this is hardcoded in reload_context()!*/
# define REGION_SHIFT 61
# define HPAGE_REGION_BASE (REGION_HPAGE << REGION_SHIFT)
# define HPAGE_SHIFT hpage_shift
# define HPAGE_SHIFT_DEFAULT 28 /* check ia64 SDM for architecture supported size */
# define HPAGE_SIZE (__IA64_UL_CONST(1) << HPAGE_SHIFT)
# define HPAGE_MASK (~(HPAGE_SIZE - 1))
# if defined(CONFIG_HUGETLB_PAGE_SIZE_4GB)
# define HPAGE_SHIFT 32
# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1GB)
# define HPAGE_SHIFT 30
# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256MB)
# define HPAGE_SHIFT 28
# elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB)
# define HPAGE_SHIFT 26
# elif defined(CONFIG_HUGETLB_PAGE_SIZE_16MB)
# define HPAGE_SHIFT 24
# elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
# define HPAGE_SHIFT 22
# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB)
# define HPAGE_SHIFT 20
# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256KB)
# define HPAGE_SHIFT 18
# else
# error Unsupported IA-64 HugeTLB Page Size!
# endif
# define REGION_HPAGE (4UL) /* note: this is hardcoded in mmu_context.h:reload_context()!*/
# define REGION_SHIFT 61
# define HPAGE_SIZE (__IA64_UL_CONST(1) << HPAGE_SHIFT)
# define HPAGE_MASK (~(HPAGE_SIZE - 1))
# define HAVE_ARCH_HUGETLB_UNMAPPED_AREA # define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
# define ARCH_HAS_HUGEPAGE_ONLY_RANGE # define ARCH_HAS_HUGEPAGE_ONLY_RANGE
#endif /* CONFIG_HUGETLB_PAGE */ #endif /* CONFIG_HUGETLB_PAGE */
...@@ -140,6 +123,7 @@ typedef union ia64_va { ...@@ -140,6 +123,7 @@ typedef union ia64_va {
# define is_hugepage_only_range(addr, len) \ # define is_hugepage_only_range(addr, len) \
(REGION_NUMBER(addr) == REGION_HPAGE && \ (REGION_NUMBER(addr) == REGION_HPAGE && \
REGION_NUMBER((addr)+(len)) == REGION_HPAGE) REGION_NUMBER((addr)+(len)) == REGION_HPAGE)
extern unsigned int hpage_shift;
#endif #endif
static __inline__ int static __inline__ int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment