From Rohit Seth ia64 reserves virtual address region 4 (any address which starts with 0x4) for huge pages. Apparently, for hardware reasons, we do not wish to allow mappings with other page sizes to appear in that region. This patch prevents the user from being able to place regular MAP_FIXED mappings into region 4 on ia64. It is a no-op for ia32. include/asm-ia64/page.h | 10 ++++++++++ include/linux/hugetlb.h | 5 +++++ mm/mmap.c | 20 +++++++++++++++----- 3 files changed, 30 insertions(+), 5 deletions(-) diff -puN mm/mmap.c~hugetlb-valid-page-ranges mm/mmap.c --- 25/mm/mmap.c~hugetlb-valid-page-ranges 2003-02-26 16:07:22.000000000 -0800 +++ 25-akpm/mm/mmap.c 2003-02-26 16:07:22.000000000 -0800 @@ -798,17 +798,27 @@ get_unmapped_area(struct file *file, uns unsigned long pgoff, unsigned long flags) { if (flags & MAP_FIXED) { + unsigned long ret; + if (addr > TASK_SIZE - len) return -ENOMEM; if (addr & ~PAGE_MASK) return -EINVAL; - if (file && is_file_hugepages(file)) { - unsigned long ret; - + if (file && is_file_hugepages(file)) { + /* + * Make sure that addr and length are properly aligned. + */ ret = is_aligned_hugepage_range(addr, len); - if (ret) - return ret; + } else { + /* + * Ensure that a normal request is not falling in a + * reserved hugepage range. For some archs like IA-64, + * there is a separate region for hugepages. + */ + ret = check_valid_hugepage_range(addr, len); } + if (ret) + return ret; return addr; } diff -puN include/asm-ia64/page.h~hugetlb-valid-page-ranges include/asm-ia64/page.h --- 25/include/asm-ia64/page.h~hugetlb-valid-page-ranges 2003-02-26 16:07:22.000000000 -0800 +++ 25-akpm/include/asm-ia64/page.h 2003-02-26 16:07:22.000000000 -0800 @@ -57,6 +57,16 @@ # define REGION_SHIFT 61 # define HPAGE_SIZE (__IA64_UL_CONST(1) << HPAGE_SHIFT) # define HPAGE_MASK (~(HPAGE_SIZE - 1)) +static inline int +check_valid_hugepage_range(unsigned long addr, unsigned long len) +{ + if (REGION_NUMBER(addr) == REGION_HPAGE) + return -EINVAL; + if (REGION_NUMBER(addr+len) == REGION_HPAGE) + return -EINVAL; + return 0; +} +#define ARCH_HAS_VALID_HUGEPAGE_RANGE #endif /* CONFIG_HUGETLB_PAGE */ #ifdef __ASSEMBLY__ diff -puN include/linux/hugetlb.h~hugetlb-valid-page-ranges include/linux/hugetlb.h --- 25/include/linux/hugetlb.h~hugetlb-valid-page-ranges 2003-02-26 16:07:22.000000000 -0800 +++ 25-akpm/include/linux/hugetlb.h 2003-02-26 16:07:22.000000000 -0800 @@ -37,6 +37,10 @@ mark_mm_hugetlb(struct mm_struct *mm, st mm->used_hugetlb = 1; } +#ifndef ARCH_HAS_VALID_HUGEPAGE_RANGE +#define check_valid_hugepage_range(addr, len) 0 +#endif + #else /* !CONFIG_HUGETLB_PAGE */ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma) @@ -58,6 +62,7 @@ static inline int is_vm_hugetlb_page(str #define follow_huge_pmd(mm, addr, pmd, write) 0 #define is_aligned_hugepage_range(addr, len) 0 #define pmd_huge(x) 0 +#define check_valid_hugepage_range(addr, len) 0 #ifndef HPAGE_MASK #define HPAGE_MASK 0 /* Keep the compiler happy */ _