diff options
Diffstat (limited to 'arch/powerpc')
| -rw-r--r-- | arch/powerpc/mm/slice.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c index 564fff06f5c1..23ec2c5e3b78 100644 --- a/arch/powerpc/mm/slice.c +++ b/arch/powerpc/mm/slice.c | |||
| @@ -122,7 +122,8 @@ static int slice_high_has_vma(struct mm_struct *mm, unsigned long slice) | |||
| 122 | return !slice_area_is_free(mm, start, end - start); | 122 | return !slice_area_is_free(mm, start, end - start); |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret) | 125 | static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret, |
| 126 | unsigned long high_limit) | ||
| 126 | { | 127 | { |
| 127 | unsigned long i; | 128 | unsigned long i; |
| 128 | 129 | ||
| @@ -133,15 +134,16 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret) | |||
| 133 | if (!slice_low_has_vma(mm, i)) | 134 | if (!slice_low_has_vma(mm, i)) |
| 134 | ret->low_slices |= 1u << i; | 135 | ret->low_slices |= 1u << i; |
| 135 | 136 | ||
| 136 | if (mm->context.slb_addr_limit <= SLICE_LOW_TOP) | 137 | if (high_limit <= SLICE_LOW_TOP) |
| 137 | return; | 138 | return; |
| 138 | 139 | ||
| 139 | for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); i++) | 140 | for (i = 0; i < GET_HIGH_SLICE_INDEX(high_limit); i++) |
| 140 | if (!slice_high_has_vma(mm, i)) | 141 | if (!slice_high_has_vma(mm, i)) |
| 141 | __set_bit(i, ret->high_slices); | 142 | __set_bit(i, ret->high_slices); |
| 142 | } | 143 | } |
| 143 | 144 | ||
| 144 | static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_mask *ret) | 145 | static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_mask *ret, |
| 146 | unsigned long high_limit) | ||
| 145 | { | 147 | { |
| 146 | unsigned char *hpsizes; | 148 | unsigned char *hpsizes; |
| 147 | int index, mask_index; | 149 | int index, mask_index; |
| @@ -156,8 +158,11 @@ static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_ma | |||
| 156 | if (((lpsizes >> (i * 4)) & 0xf) == psize) | 158 | if (((lpsizes >> (i * 4)) & 0xf) == psize) |
| 157 | ret->low_slices |= 1u << i; | 159 | ret->low_slices |= 1u << i; |
| 158 | 160 | ||
| 161 | if (high_limit <= SLICE_LOW_TOP) | ||
| 162 | return; | ||
| 163 | |||
| 159 | hpsizes = mm->context.high_slices_psize; | 164 | hpsizes = mm->context.high_slices_psize; |
| 160 | for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); i++) { | 165 | for (i = 0; i < GET_HIGH_SLICE_INDEX(high_limit); i++) { |
| 161 | mask_index = i & 0x1; | 166 | mask_index = i & 0x1; |
| 162 | index = i >> 1; | 167 | index = i >> 1; |
| 163 | if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize) | 168 | if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize) |
| @@ -169,6 +174,10 @@ static int slice_check_fit(struct mm_struct *mm, | |||
| 169 | struct slice_mask mask, struct slice_mask available) | 174 | struct slice_mask mask, struct slice_mask available) |
| 170 | { | 175 | { |
| 171 | DECLARE_BITMAP(result, SLICE_NUM_HIGH); | 176 | DECLARE_BITMAP(result, SLICE_NUM_HIGH); |
| 177 | /* | ||
| 178 | * Make sure we just do bit compare only to the max | ||
| 179 | * addr limit and not the full bit map size. | ||
| 180 | */ | ||
| 172 | unsigned long slice_count = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); | 181 | unsigned long slice_count = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); |
| 173 | 182 | ||
| 174 | bitmap_and(result, mask.high_slices, | 183 | bitmap_and(result, mask.high_slices, |
| @@ -472,7 +481,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, | |||
| 472 | /* First make up a "good" mask of slices that have the right size | 481 | /* First make up a "good" mask of slices that have the right size |
| 473 | * already | 482 | * already |
| 474 | */ | 483 | */ |
| 475 | slice_mask_for_size(mm, psize, &good_mask); | 484 | slice_mask_for_size(mm, psize, &good_mask, high_limit); |
| 476 | slice_print_mask(" good_mask", good_mask); | 485 | slice_print_mask(" good_mask", good_mask); |
| 477 | 486 | ||
| 478 | /* | 487 | /* |
| @@ -497,7 +506,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, | |||
| 497 | #ifdef CONFIG_PPC_64K_PAGES | 506 | #ifdef CONFIG_PPC_64K_PAGES |
| 498 | /* If we support combo pages, we can allow 64k pages in 4k slices */ | 507 | /* If we support combo pages, we can allow 64k pages in 4k slices */ |
| 499 | if (psize == MMU_PAGE_64K) { | 508 | if (psize == MMU_PAGE_64K) { |
| 500 | slice_mask_for_size(mm, MMU_PAGE_4K, &compat_mask); | 509 | slice_mask_for_size(mm, MMU_PAGE_4K, &compat_mask, high_limit); |
| 501 | if (fixed) | 510 | if (fixed) |
| 502 | slice_or_mask(&good_mask, &compat_mask); | 511 | slice_or_mask(&good_mask, &compat_mask); |
| 503 | } | 512 | } |
| @@ -530,11 +539,11 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, | |||
| 530 | return newaddr; | 539 | return newaddr; |
| 531 | } | 540 | } |
| 532 | } | 541 | } |
| 533 | 542 | /* | |
| 534 | /* We don't fit in the good mask, check what other slices are | 543 | * We don't fit in the good mask, check what other slices are |
| 535 | * empty and thus can be converted | 544 | * empty and thus can be converted |
| 536 | */ | 545 | */ |
| 537 | slice_mask_for_free(mm, &potential_mask); | 546 | slice_mask_for_free(mm, &potential_mask, high_limit); |
| 538 | slice_or_mask(&potential_mask, &good_mask); | 547 | slice_or_mask(&potential_mask, &good_mask); |
| 539 | slice_print_mask(" potential", potential_mask); | 548 | slice_print_mask(" potential", potential_mask); |
| 540 | 549 | ||
| @@ -744,17 +753,18 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, | |||
| 744 | { | 753 | { |
| 745 | struct slice_mask mask, available; | 754 | struct slice_mask mask, available; |
| 746 | unsigned int psize = mm->context.user_psize; | 755 | unsigned int psize = mm->context.user_psize; |
| 756 | unsigned long high_limit = mm->context.slb_addr_limit; | ||
| 747 | 757 | ||
| 748 | if (radix_enabled()) | 758 | if (radix_enabled()) |
| 749 | return 0; | 759 | return 0; |
| 750 | 760 | ||
| 751 | slice_range_to_mask(addr, len, &mask); | 761 | slice_range_to_mask(addr, len, &mask); |
| 752 | slice_mask_for_size(mm, psize, &available); | 762 | slice_mask_for_size(mm, psize, &available, high_limit); |
| 753 | #ifdef CONFIG_PPC_64K_PAGES | 763 | #ifdef CONFIG_PPC_64K_PAGES |
| 754 | /* We need to account for 4k slices too */ | 764 | /* We need to account for 4k slices too */ |
| 755 | if (psize == MMU_PAGE_64K) { | 765 | if (psize == MMU_PAGE_64K) { |
| 756 | struct slice_mask compat_mask; | 766 | struct slice_mask compat_mask; |
| 757 | slice_mask_for_size(mm, MMU_PAGE_4K, &compat_mask); | 767 | slice_mask_for_size(mm, MMU_PAGE_4K, &compat_mask, high_limit); |
| 758 | slice_or_mask(&available, &compat_mask); | 768 | slice_or_mask(&available, &compat_mask); |
| 759 | } | 769 | } |
| 760 | #endif | 770 | #endif |
