Commit b4e0dd09 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: Fix bug in hugepage support

From: David Gibson <david@gibson.dropbear.id.au>

The PPC64 version of is_aligned_hugepage_range() is buggy.  It is supposed to
test not only that the given range is hugepage aligned, but that it lies
within the address space allowed for hugepages.  We were checking only that
the given range intersected the hugepage range, not that it lay entirely
within it.  This patch fixes the problem and changes the name of some macros
to make it less likely to make that misunderstanding again.
parent 5c57dda8
...@@ -230,7 +230,8 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len) ...@@ -230,7 +230,8 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
return -EINVAL; return -EINVAL;
if (addr & ~HPAGE_MASK) if (addr & ~HPAGE_MASK)
return -EINVAL; return -EINVAL;
if (! is_hugepage_only_range(addr, len)) if (! (within_hugepage_low_range(addr, len)
|| within_hugepage_high_range(addr, len)) )
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
...@@ -300,9 +301,9 @@ static int open_32bit_htlbpage_range(struct mm_struct *mm) ...@@ -300,9 +301,9 @@ static int open_32bit_htlbpage_range(struct mm_struct *mm)
int prepare_hugepage_range(unsigned long addr, unsigned long len) int prepare_hugepage_range(unsigned long addr, unsigned long len)
{ {
if (is_hugepage_high_range(addr, len)) if (within_hugepage_high_range(addr, len))
return 0; return 0;
else if (is_hugepage_low_range(addr, len)) else if (within_hugepage_low_range(addr, len))
return open_32bit_htlbpage_range(current->mm); return open_32bit_htlbpage_range(current->mm);
return -EINVAL; return -EINVAL;
......
...@@ -40,15 +40,19 @@ ...@@ -40,15 +40,19 @@
#define ARCH_HAS_HUGEPAGE_ONLY_RANGE #define ARCH_HAS_HUGEPAGE_ONLY_RANGE
#define ARCH_HAS_PREPARE_HUGEPAGE_RANGE #define ARCH_HAS_PREPARE_HUGEPAGE_RANGE
#define is_hugepage_low_range(addr, len) \ #define touches_hugepage_low_range(addr, len) \
(((addr) > (TASK_HPAGE_BASE_32-(len))) && ((addr) < TASK_HPAGE_END_32)) (((addr) > (TASK_HPAGE_BASE_32-(len))) && ((addr) < TASK_HPAGE_END_32))
#define is_hugepage_high_range(addr, len) \ #define touches_hugepage_high_range(addr, len) \
(((addr) > (TASK_HPAGE_BASE-(len))) && ((addr) < TASK_HPAGE_END)) (((addr) > (TASK_HPAGE_BASE-(len))) && ((addr) < TASK_HPAGE_END))
#define within_hugepage_low_range(addr, len) (((addr) >= TASK_HPAGE_BASE_32) \
&& ((addr)+(len) <= TASK_HPAGE_END_32) && ((addr)+(len) >= (addr)))
#define within_hugepage_high_range(addr, len) (((addr) >= TASK_HPAGE_BASE) \
&& ((addr)+(len) <= TASK_HPAGE_END) && ((addr)+(len) >= (addr)))
#define is_hugepage_only_range(addr, len) \ #define is_hugepage_only_range(addr, len) \
(is_hugepage_high_range((addr), (len)) || \ (touches_hugepage_high_range((addr), (len)) || \
(current->mm->context.low_hpages \ (current->mm->context.low_hpages \
&& is_hugepage_low_range((addr), (len)))) && touches_hugepage_low_range((addr), (len))))
#define hugetlb_free_pgtables free_pgtables #define hugetlb_free_pgtables free_pgtables
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
......
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