Commit a0c2011a authored by David S. Miller's avatar David S. Miller

[SPARC]: First cut of hugetlb on sparc64, 4MB currently.

parent 4ec5e293
......@@ -25,6 +25,14 @@ CONFIG_SMP
If you don't know what to do here, say N.
CONFIG_HUGETLB_PAGE
This enables support for huge pages. User space applications
can make use of this support with the sys_alloc_hugepages and
sys_free_hugepages system calls. If your applications are
huge page aware, then say Y here.
Otherwise, say N.
CONFIG_PREEMPT
This option reduces the latency of the kernel when reacting to
real-time or interactive events by allowing a low priority process to
......
......@@ -15,6 +15,8 @@ define_bool CONFIG_VT y
define_bool CONFIG_VT_CONSOLE y
define_bool CONFIG_HW_CONSOLE y
bool 'SPARC64 Huge TLB Page Support' CONFIG_HUGETLB_PAGE
bool 'Symmetric multi-processing support' CONFIG_SMP
bool 'Preemptible Kernel' CONFIG_PREEMPT
......
......@@ -681,3 +681,100 @@ sys_perfctr(int opcode, unsigned long arg0, unsigned long arg1, unsigned long ar
};
return err;
}
#ifdef CONFIG_HUGETLB_PAGE
#define HPAGE_ALIGN(x) (((unsigned long)x + (HPAGE_SIZE -1)) & HPAGE_MASK)
extern long sys_munmap(unsigned long, size_t);
/* get_addr function gets the currently unused virtual range in
* the current process's address space. It returns the LARGE_PAGE_SIZE
* aligned address (in cases of success). Other kernel generic
* routines only could gurantee that allocated address is PAGE_SIZE aligned.
*/
static long get_addr(unsigned long addr, unsigned long len)
{
struct vm_area_struct *vma;
if (addr) {
addr = HPAGE_ALIGN(addr);
vma = find_vma(current->mm, addr);
if (((TASK_SIZE - len) >= addr) &&
(!vma || addr + len <= vma->vm_start))
goto found_addr;
}
addr = HPAGE_ALIGN(TASK_UNMAPPED_BASE);
for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
if (TASK_SIZE - len < addr)
return -ENOMEM;
if (!vma || ((addr + len) < vma->vm_start))
goto found_addr;
addr = vma->vm_end;
}
found_addr:
addr = HPAGE_ALIGN(addr);
return addr;
}
extern int alloc_hugetlb_pages(int, unsigned long, unsigned long, int, int);
asmlinkage long
sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag)
{
struct mm_struct *mm = current->mm;
unsigned long raddr;
int retval;
if (key < 0)
return -EINVAL;
if (len & (HPAGE_SIZE - 1))
return -EINVAL;
down_write(&mm->mmap_sem);
raddr = get_addr(addr, len);
retval = 0;
if (raddr == -ENOMEM) {
retval = -ENOMEM;
goto raddr_out;
}
retval = alloc_hugetlb_pages(key, raddr, len, prot, flag);
raddr_out:
up_write(&mm->mmap_sem);
if (retval < 0)
return (long) retval;
return raddr;
}
extern int free_hugepages(struct vm_area_struct *);
asmlinkage int
sys_free_hugepages(unsigned long addr)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
int retval;
vma = find_vma(current->mm, addr);
if ((!vma) || (!is_vm_hugetlb_page(vma)) || (vma->vm_start!=addr))
return -EINVAL;
down_write(&mm->mmap_sem);
spin_lock(&mm->page_table_lock);
retval = free_hugepages(vma);
spin_unlock(&mm->page_table_lock);
up_write(&mm->mmap_sem);
return retval;
}
#else
asmlinkage long
sys_alloc_hugepages(int key, unsigned long addr, size_t len, int prot, int flag)
{
return -ENOSYS;
}
asmlinkage int
sys_free_hugepages(unsigned long addr)
{
return -ENOSYS;
}
#endif
......@@ -65,8 +65,8 @@ sys_call_table32:
.word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
/*220*/ .word sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid
.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
/*230*/ .word sys32_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall
.word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
/*230*/ .word sys32_select, sys_time, sys_nis_syscall, sys_stime, sys_alloc_hugepages
.word sys_free_hugepages, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys32_nanosleep
/*250*/ .word sys32_mremap, sys32_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
......
......@@ -7,4 +7,6 @@ EXTRA_AFLAGS := -ansi
O_TARGET := mm.o
obj-y := ultra.o fault.o init.o generic.o extable.o modutil.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
include $(TOPDIR)/Rules.make
This diff is collapsed.
......@@ -1690,6 +1690,13 @@ static void __init taint_real_pages(void)
}
}
#ifdef CONFIG_HUGETLB_PAGE
long htlbpagemem = 0;
long htlbpage_max;
long htlbzone_pages;
extern struct list_head htlbpage_freelist;
#endif
void __init mem_init(void)
{
unsigned long codepages, datapages, initpages;
......@@ -1766,6 +1773,32 @@ void __init mem_init(void)
if (tlb_type == cheetah || tlb_type == cheetah_plus)
cheetah_ecache_flush_init();
#ifdef CONFIG_HUGETLB_PAGE
{
long i, j;
struct page *page, *map;
/* For now reserve quarter for hugetlb_pages. */
htlbzone_pages = (num_physpages >> ((HPAGE_SHIFT - PAGE_SHIFT) + 2)) ;
/* Will make this kernel command line. */
INIT_LIST_HEAD(&htlbpage_freelist);
for (i = 0; i < htlbzone_pages; i++) {
page = alloc_pages(GFP_ATOMIC, HUGETLB_PAGE_ORDER);
if (page == NULL)
break;
map = page;
for (j = 0; j < (HPAGE_SIZE / PAGE_SIZE); j++) {
SetPageReserved(map);
map++;
}
list_add(&page->list, &htlbpage_freelist);
}
printk("Total Huge_TLB_Page memory pages allocated %ld\n", i);
htlbzone_pages = htlbpagemem = i;
htlbpage_max = i;
}
#endif
}
void free_initmem (void)
......
......@@ -249,8 +249,8 @@
#define __NR_time 231 /* Linux Specific */
/* #define __NR_oldstat 232 Linux Specific */
#define __NR_stime 233 /* Linux Specific */
/* #define __NR_oldfstat 234 Linux Specific */
/* #define __NR_phys 235 Linux Specific */
#define __NR_alloc_hugepages 234 /* Linux Specific */
#define __NR_free_hugepages 235 /* Linux Specific */
#define __NR__llseek 236 /* Linux Specific */
#define __NR_mlock 237
#define __NR_munlock 238
......
......@@ -3,6 +3,8 @@
#ifndef _SPARC64_PAGE_H
#define _SPARC64_PAGE_H
#include <linux/config.h>
#define PAGE_SHIFT 13
#ifndef __ASSEMBLY__
/* I have my suspicions... -DaveM */
......@@ -99,6 +101,14 @@ typedef unsigned long iopgprot_t;
#endif /* (STRICT_MM_TYPECHECKS) */
#define HPAGE_SHIFT 22
#ifdef CONFIG_HUGETLB_PAGE
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1UL))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
#endif
#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \
(0x0000000070000000UL) : (PAGE_OFFSET))
......
......@@ -251,8 +251,8 @@
#endif
/* #define __NR_oldstat 232 Linux Specific */
#define __NR_stime 233 /* Linux Specific */
/* #define __NR_oldfstat 234 Linux Specific */
/* #define __NR_phys 235 Linux Specific */
#define __NR_alloc_hugepages 234 /* Linux Specific */
#define __NR_free_hugepages 235 /* Linux Specific */
#define __NR__llseek 236 /* Linux Specific */
#define __NR_mlock 237
#define __NR_munlock 238
......
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