aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/mm/hugetlbpage.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 54131b877da3..f6fe3eaf87a3 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -549,6 +549,17 @@ fail:
549 return addr; 549 return addr;
550} 550}
551 551
552static int htlb_check_hinted_area(unsigned long addr, unsigned long len)
553{
554 struct vm_area_struct *vma;
555
556 vma = find_vma(current->mm, addr);
557 if (!vma || ((addr + len) <= vma->vm_start))
558 return 0;
559
560 return -ENOMEM;
561}
562
552static unsigned long htlb_get_low_area(unsigned long len, u16 segmask) 563static unsigned long htlb_get_low_area(unsigned long len, u16 segmask)
553{ 564{
554 unsigned long addr = 0; 565 unsigned long addr = 0;
@@ -609,6 +620,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
609{ 620{
610 int lastshift; 621 int lastshift;
611 u16 areamask, curareas; 622 u16 areamask, curareas;
623 struct vm_area_struct *vma;
612 624
613 if (HPAGE_SHIFT == 0) 625 if (HPAGE_SHIFT == 0)
614 return -EINVAL; 626 return -EINVAL;
@@ -618,15 +630,28 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
618 if (!cpu_has_feature(CPU_FTR_16M_PAGE)) 630 if (!cpu_has_feature(CPU_FTR_16M_PAGE))
619 return -EINVAL; 631 return -EINVAL;
620 632
633 /* Paranoia, caller should have dealt with this */
634 BUG_ON((addr + len) < addr);
635
621 if (test_thread_flag(TIF_32BIT)) { 636 if (test_thread_flag(TIF_32BIT)) {
637 /* Paranoia, caller should have dealt with this */
638 BUG_ON((addr + len) > 0x100000000UL);
639
622 curareas = current->mm->context.low_htlb_areas; 640 curareas = current->mm->context.low_htlb_areas;
623 641
624 /* First see if we can do the mapping in the existing 642 /* First see if we can use the hint address */
625 * low areas */ 643 if (addr && (htlb_check_hinted_area(addr, len) == 0)) {
644 areamask = LOW_ESID_MASK(addr, len);
645 if (open_low_hpage_areas(current->mm, areamask) == 0)
646 return addr;
647 }
648
649 /* Next see if we can map in the existing low areas */
626 addr = htlb_get_low_area(len, curareas); 650 addr = htlb_get_low_area(len, curareas);
627 if (addr != -ENOMEM) 651 if (addr != -ENOMEM)
628 return addr; 652 return addr;
629 653
654 /* Finally go looking for areas to open */
630 lastshift = 0; 655 lastshift = 0;
631 for (areamask = LOW_ESID_MASK(0x100000000UL-len, len); 656 for (areamask = LOW_ESID_MASK(0x100000000UL-len, len);
632 ! lastshift; areamask >>=1) { 657 ! lastshift; areamask >>=1) {
@@ -641,12 +666,22 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
641 } else { 666 } else {
642 curareas = current->mm->context.high_htlb_areas; 667 curareas = current->mm->context.high_htlb_areas;
643 668
644 /* First see if we can do the mapping in the existing 669 /* First see if we can use the hint address */
645 * high areas */ 670 /* We discourage 64-bit processes from doing hugepage
671 * mappings below 4GB (must use MAP_FIXED) */
672 if ((addr >= 0x100000000UL)
673 && (htlb_check_hinted_area(addr, len) == 0)) {
674 areamask = HTLB_AREA_MASK(addr, len);
675 if (open_high_hpage_areas(current->mm, areamask) == 0)
676 return addr;
677 }
678
679 /* Next see if we can map in the existing high areas */
646 addr = htlb_get_high_area(len, curareas); 680 addr = htlb_get_high_area(len, curareas);
647 if (addr != -ENOMEM) 681 if (addr != -ENOMEM)
648 return addr; 682 return addr;
649 683
684 /* Finally go looking for areas to open */
650 lastshift = 0; 685 lastshift = 0;
651 for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len); 686 for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len);
652 ! lastshift; areamask >>=1) { 687 ! lastshift; areamask >>=1) {