[PATCH] powerpc: More hugepage boundary case fixes

Blah. The patch [0] I recently sent fixing errors with
in_hugepage_area() and prepare_hugepage_range() for powerpc itself has
an off-by-one bug. Furthermore, the related functions
touches_hugepage_*_range() and within_hugepage_*_range() are also
buggy. Some of the bugs, like those addressed in [0] originated with
commit 7d24f0b8a53261709938ffabe3e00f88f6498df9 where we tweaked the
semantics of where hugepages are allowed. Other bugs have been there
essentially forever, and are due to the undefined behaviour of '<<'
with shift counts greater than the type width (LOW_ESID_MASK could
return non-zero for high ranges with the right congruences).

The good news is that I now have a testsuite which should pick up
things like this if they creep in again.

[0] "powerpc-fix-for-hugepage-areas-straddling-4gb-boundary"

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by David Gibson and committed by Paul Mackerras 9a94c579 26925c59

+12 -7
+1 -1
arch/powerpc/mm/hugetlbpage.c
··· 295 295 if (addr < 0x100000000UL) 296 296 err = open_low_hpage_areas(current->mm, 297 297 LOW_ESID_MASK(addr, len)); 298 - if ((addr + len) >= 0x100000000UL) 298 + if ((addr + len) > 0x100000000UL) 299 299 err = open_high_hpage_areas(current->mm, 300 300 HTLB_AREA_MASK(addr, len)); 301 301 if (err) {
+11 -6
include/asm-powerpc/page_64.h
··· 103 103 #define HTLB_AREA_SIZE (1UL << HTLB_AREA_SHIFT) 104 104 #define GET_HTLB_AREA(x) ((x) >> HTLB_AREA_SHIFT) 105 105 106 - #define LOW_ESID_MASK(addr, len) (((1U << (GET_ESID(addr+len-1)+1)) \ 107 - - (1U << GET_ESID(addr))) & 0xffff) 106 + #define LOW_ESID_MASK(addr, len) \ 107 + (((1U << (GET_ESID(min((addr)+(len)-1, 0x100000000UL))+1)) \ 108 + - (1U << GET_ESID(min((addr), 0x100000000UL)))) & 0xffff) 108 109 #define HTLB_AREA_MASK(addr, len) (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \ 109 110 - (1U << GET_HTLB_AREA(addr))) & 0xffff) 110 111 ··· 114 113 #define ARCH_HAS_SETCLEAR_HUGE_PTE 115 114 116 115 #define touches_hugepage_low_range(mm, addr, len) \ 117 - (LOW_ESID_MASK((addr), (len)) & (mm)->context.low_htlb_areas) 116 + (((addr) < 0x100000000UL) \ 117 + && (LOW_ESID_MASK((addr), (len)) & (mm)->context.low_htlb_areas)) 118 118 #define touches_hugepage_high_range(mm, addr, len) \ 119 - (HTLB_AREA_MASK((addr), (len)) & (mm)->context.high_htlb_areas) 119 + ((((addr) + (len)) > 0x100000000UL) \ 120 + && (HTLB_AREA_MASK((addr), (len)) & (mm)->context.high_htlb_areas)) 120 121 121 122 #define __within_hugepage_low_range(addr, len, segmask) \ 122 - ((LOW_ESID_MASK((addr), (len)) | (segmask)) == (segmask)) 123 + ( (((addr)+(len)) <= 0x100000000UL) \ 124 + && ((LOW_ESID_MASK((addr), (len)) | (segmask)) == (segmask))) 123 125 #define within_hugepage_low_range(addr, len) \ 124 126 __within_hugepage_low_range((addr), (len), \ 125 127 current->mm->context.low_htlb_areas) 126 128 #define __within_hugepage_high_range(addr, len, zonemask) \ 127 - ((HTLB_AREA_MASK((addr), (len)) | (zonemask)) == (zonemask)) 129 + ( ((addr) >= 0x100000000UL) \ 130 + && ((HTLB_AREA_MASK((addr), (len)) | (zonemask)) == (zonemask))) 128 131 #define within_hugepage_high_range(addr, len) \ 129 132 __within_hugepage_high_range((addr), (len), \ 130 133 current->mm->context.high_htlb_areas)