]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] ppc64: allow MAP_FIXED hugepage mappings
authorAndrew Morton <akpm@osdl.org>
Thu, 1 Apr 2004 05:50:36 +0000 (21:50 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 1 Apr 2004 05:50:36 +0000 (21:50 -0800)
From: David Gibson <david@gibson.dropbear.id.au>

On PowerPC64 the "low" hugepage range (at 2-3G for use by 32-bit processes)
needs to be activated before it can be used.  hugetlb_get_unmapped_area()
automatically activates the range for hugepage mappings in 32-bit processes
which are not MAP_FIXED.  However for MAP_FIXED mmap()s, even at a suitable
address will fail if the region is not already activated, because there is
no suitable callback from the generic MAP_FIXED code path into the arch
code.

This patch corrects this problem and allows PPC64 to do MAP_FIXED hugepage
mappings in the low hugepage range.

arch/ppc64/mm/hugetlbpage.c
include/asm-ppc64/page.h
include/linux/hugetlb.h
mm/mmap.c

index 1f620734b3045b17f28200b5654766b19a42c8c2..3a50af4962dd27c3cf1cbe3e3ede72b7700ac448 100644 (file)
@@ -295,6 +295,16 @@ static int open_32bit_htlbpage_range(struct mm_struct *mm)
        return 0;
 }
 
+int prepare_hugepage_range(unsigned long addr, unsigned long len)
+{
+       if (is_hugepage_high_range(addr, len))
+               return 0;
+       else if (is_hugepage_low_range(addr, len))
+               return open_32bit_htlbpage_range(current->mm);
+
+       return -EINVAL;
+}
+
 int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
                        struct vm_area_struct *vma)
 {
index 6e32a197dba4dfa5945e2434f079a437b4f20098..fd707bb57da5cd11401bc497fe22b859c9cdd178 100644 (file)
 #define TASK_HPAGE_END_32      (0xc0000000UL)
 
 #define ARCH_HAS_HUGEPAGE_ONLY_RANGE
+#define ARCH_HAS_PREPARE_HUGEPAGE_RANGE
+
+#define is_hugepage_low_range(addr, len) \
+       (((addr) > (TASK_HPAGE_BASE_32-(len))) && ((addr) < TASK_HPAGE_END_32))
+#define is_hugepage_high_range(addr, len) \
+       (((addr) > (TASK_HPAGE_BASE-(len))) && ((addr) < TASK_HPAGE_END))
+
 #define is_hugepage_only_range(addr, len) \
-       ( ((addr > (TASK_HPAGE_BASE-len)) && (addr < TASK_HPAGE_END)) || \
-         (current->mm->context.low_hpages && \
-          (addr > (TASK_HPAGE_BASE_32-len)) && (addr < TASK_HPAGE_END_32)) )
+       (is_hugepage_high_range((addr), (len)) || \
+        (current->mm->context.low_hpages \
+         && is_hugepage_low_range((addr), (len))))
 #define hugetlb_free_pgtables free_pgtables
 #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 
index a88f16ccdc5a039f37c888e6ea530856a48f274b..5075a90bcd65b4e7653499bfe89cd8253c5b4829 100644 (file)
@@ -42,6 +42,13 @@ mark_mm_hugetlb(struct mm_struct *mm, struct vm_area_struct *vma)
 #define hugetlb_free_pgtables(tlb, prev, start, end) do { } while (0)
 #endif
 
+#ifndef ARCH_HAS_PREPARE_HUGEPAGE_RANGE
+#define prepare_hugepage_range(addr, len)      \
+       is_aligned_hugepage_range(addr, len)
+#else
+int prepare_hugepage_range(unsigned long addr, unsigned long len);
+#endif
+
 #else /* !CONFIG_HUGETLB_PAGE */
 
 static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
@@ -62,6 +69,7 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
 #define mark_mm_hugetlb(mm, vma)               do { } while (0)
 #define follow_huge_pmd(mm, addr, pmd, write)  0
 #define is_aligned_hugepage_range(addr, len)   0
+#define prepare_hugepage_range(addr, len)      (-EINVAL)
 #define pmd_huge(x)    0
 #define is_hugepage_only_range(addr, len)      0
 #define hugetlb_free_pgtables(tlb, prev, start, end) do { } while (0)
index 416817625cd3e6ad6ee6a2d00a5b968fb0b901e7..31520c7698549adf44fd22b96037127524fb085a 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -807,9 +807,10 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
                        return -EINVAL;
                if (file && is_file_hugepages(file))  {
                        /*
-                        * Make sure that addr and length are properly aligned.
+                        * Check if the given range is hugepage aligned, and
+                        * can be made suitable for hugepages.
                         */
-                       ret = is_aligned_hugepage_range(addr, len);
+                       ret = prepare_hugepage_range(addr, len);
                } else {
                        /*
                         * Ensure that a normal request is not falling in a