diff options
author | Christophe Leroy <christophe.leroy@c-s.fr> | 2018-02-22 15:27:28 +0100 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2018-03-06 09:21:23 +1100 |
commit | 15472423ce47d6397d08d48daaae8590c9f9f242 (patch) | |
tree | 7f06b7bf75af5c3649a3c4f28144e4a50b3da72e /arch/powerpc/mm/slice.c | |
parent | aa0ab02ba992eb956934b21373e0138211486ddd (diff) | |
download | linux-stable-15472423ce47d6397d08d48daaae8590c9f9f242.tar.gz linux-stable-15472423ce47d6397d08d48daaae8590c9f9f242.tar.bz2 linux-stable-15472423ce47d6397d08d48daaae8590c9f9f242.zip |
powerpc/mm/slice: Allow up to 64 low slices
While the implementation of the "slices" address space allows
a significant amount of high slices, it limits the number of
low slices to 16 due to the use of a single u64 low_slices_psize
element in struct mm_context_t
On the 8xx, the minimum slice size is the size of the area
covered by a single PMD entry, ie 4M in 4K pages mode and 64M in
16K pages mode. This means we could have at least 64 slices.
In order to override this limitation, this patch switches the
handling of low_slices_psize to char array as done already for
high_slices_psize.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/mm/slice.c')
-rw-r--r-- | arch/powerpc/mm/slice.c | 57 |
1 files changed, 30 insertions, 27 deletions
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c index 0beca1ba2282..5e9e1e57d580 100644 --- a/arch/powerpc/mm/slice.c +++ b/arch/powerpc/mm/slice.c @@ -150,19 +150,21 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret, static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_mask *ret, unsigned long high_limit) { - unsigned char *hpsizes; + unsigned char *hpsizes, *lpsizes; int index, mask_index; unsigned long i; - u64 lpsizes; ret->low_slices = 0; if (SLICE_NUM_HIGH) bitmap_zero(ret->high_slices, SLICE_NUM_HIGH); lpsizes = mm->context.low_slices_psize; - for (i = 0; i < SLICE_NUM_LOW; i++) - if (((lpsizes >> (i * 4)) & 0xf) == psize) + for (i = 0; i < SLICE_NUM_LOW; i++) { + mask_index = i & 0x1; + index = i >> 1; + if (((lpsizes[index] >> (mask_index * 4)) & 0xf) == psize) ret->low_slices |= 1u << i; + } if (high_limit <= SLICE_LOW_TOP) return; @@ -218,8 +220,7 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz { int index, mask_index; /* Write the new slice psize bits */ - unsigned char *hpsizes; - u64 lpsizes; + unsigned char *hpsizes, *lpsizes; unsigned long i, flags; slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize); @@ -232,12 +233,13 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz lpsizes = mm->context.low_slices_psize; for (i = 0; i < SLICE_NUM_LOW; i++) - if (mask.low_slices & (1u << i)) - lpsizes = (lpsizes & ~(0xful << (i * 4))) | - (((unsigned long)psize) << (i * 4)); - - /* Assign the value back */ - mm->context.low_slices_psize = lpsizes; + if (mask.low_slices & (1u << i)) { + mask_index = i & 0x1; + index = i >> 1; + lpsizes[index] = (lpsizes[index] & + ~(0xf << (mask_index * 4))) | + (((unsigned long)psize) << (mask_index * 4)); + } hpsizes = mm->context.high_slices_psize; for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); i++) { @@ -644,7 +646,7 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr) { - unsigned char *hpsizes; + unsigned char *psizes; int index, mask_index; /* @@ -658,15 +660,14 @@ unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr) #endif } if (addr < SLICE_LOW_TOP) { - u64 lpsizes; - lpsizes = mm->context.low_slices_psize; + psizes = mm->context.low_slices_psize; index = GET_LOW_SLICE_INDEX(addr); - return (lpsizes >> (index * 4)) & 0xf; + } else { + psizes = mm->context.high_slices_psize; + index = GET_HIGH_SLICE_INDEX(addr); } - hpsizes = mm->context.high_slices_psize; - index = GET_HIGH_SLICE_INDEX(addr); mask_index = index & 0x1; - return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xf; + return (psizes[index >> 1] >> (mask_index * 4)) & 0xf; } EXPORT_SYMBOL_GPL(get_slice_psize); @@ -687,8 +688,8 @@ EXPORT_SYMBOL_GPL(get_slice_psize); void slice_set_user_psize(struct mm_struct *mm, unsigned int psize) { int index, mask_index; - unsigned char *hpsizes; - unsigned long flags, lpsizes; + unsigned char *hpsizes, *lpsizes; + unsigned long flags; unsigned int old_psize; int i; @@ -706,12 +707,14 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize) wmb(); lpsizes = mm->context.low_slices_psize; - for (i = 0; i < SLICE_NUM_LOW; i++) - if (((lpsizes >> (i * 4)) & 0xf) == old_psize) - lpsizes = (lpsizes & ~(0xful << (i * 4))) | - (((unsigned long)psize) << (i * 4)); - /* Assign the value back */ - mm->context.low_slices_psize = lpsizes; + for (i = 0; i < SLICE_NUM_LOW; i++) { + mask_index = i & 0x1; + index = i >> 1; + if (((lpsizes[index] >> (mask_index * 4)) & 0xf) == old_psize) + lpsizes[index] = (lpsizes[index] & + ~(0xf << (mask_index * 4))) | + (((unsigned long)psize) << (mask_index * 4)); + } hpsizes = mm->context.high_slices_psize; for (i = 0; i < SLICE_NUM_HIGH; i++) { |