aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2017-03-21 23:36:58 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2017-04-01 06:12:20 -0400
commit957b778a166e32e242a33fdab693ffb256a19cbd (patch)
treee4ffce7347a62e55ac2cd99b3efdb2e62c7cf070
parentf6eedbba7a26fdaee9ea8121336dc86236c136c7 (diff)
powerpc/mm: Add addr_limit to mm_context and use it to derive max slice index
In the followup patch, we will increase the slice array size to handle 512TB range, but will limit the max addr to 128TB. Avoid doing unnecessary computation and avoid doing slice mask related operation above address limit. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/include/asm/book3s/64/mmu-hash.h3
-rw-r--r--arch/powerpc/include/asm/book3s/64/mmu.h1
-rw-r--r--arch/powerpc/kernel/paca.c3
-rw-r--r--arch/powerpc/kernel/setup-common.c9
-rw-r--r--arch/powerpc/mm/mmu_context_book3s64.c7
-rw-r--r--arch/powerpc/mm/slice.c20
6 files changed, 32 insertions, 11 deletions
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
index c93450bf306f..5961b0d65a79 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
@@ -597,7 +597,8 @@ extern void slb_set_size(u16 size);
597#define USER_VSID_RANGE (1UL << (ESID_BITS + SID_SHIFT)) 597#define USER_VSID_RANGE (1UL << (ESID_BITS + SID_SHIFT))
598 598
599/* 4 bits per slice and we have one slice per 1TB */ 599/* 4 bits per slice and we have one slice per 1TB */
600#define SLICE_ARRAY_SIZE (H_PGTABLE_RANGE >> 41) 600#define SLICE_ARRAY_SIZE (H_PGTABLE_RANGE >> 41)
601#define TASK_SLICE_ARRAY_SZ(x) ((x)->context.addr_limit >> 41)
601 602
602#ifndef __ASSEMBLY__ 603#ifndef __ASSEMBLY__
603 604
diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
index cce434e7de06..c4b865112d24 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu.h
@@ -82,6 +82,7 @@ typedef struct {
82#ifdef CONFIG_PPC_MM_SLICES 82#ifdef CONFIG_PPC_MM_SLICES
83 u64 low_slices_psize; /* SLB page size encodings */ 83 u64 low_slices_psize; /* SLB page size encodings */
84 unsigned char high_slices_psize[SLICE_ARRAY_SIZE]; 84 unsigned char high_slices_psize[SLICE_ARRAY_SIZE];
85 unsigned long addr_limit;
85#else 86#else
86 u16 sllp; /* SLB page size encoding */ 87 u16 sllp; /* SLB page size encoding */
87#endif 88#endif
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index e2cf745a4b94..a2c7a6456ee6 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -253,9 +253,10 @@ void copy_mm_to_paca(struct mm_struct *mm)
253 253
254 get_paca()->mm_ctx_id = context->id; 254 get_paca()->mm_ctx_id = context->id;
255#ifdef CONFIG_PPC_MM_SLICES 255#ifdef CONFIG_PPC_MM_SLICES
256 VM_BUG_ON(!mm->context.addr_limit);
256 get_paca()->mm_ctx_low_slices_psize = context->low_slices_psize; 257 get_paca()->mm_ctx_low_slices_psize = context->low_slices_psize;
257 memcpy(&get_paca()->mm_ctx_high_slices_psize, 258 memcpy(&get_paca()->mm_ctx_high_slices_psize,
258 &context->high_slices_psize, SLICE_ARRAY_SIZE); 259 &context->high_slices_psize, TASK_SLICE_ARRAY_SZ(mm));
259#else /* CONFIG_PPC_MM_SLICES */ 260#else /* CONFIG_PPC_MM_SLICES */
260 get_paca()->mm_ctx_user_psize = context->user_psize; 261 get_paca()->mm_ctx_user_psize = context->user_psize;
261 get_paca()->mm_ctx_sllp = context->sllp; 262 get_paca()->mm_ctx_sllp = context->sllp;
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 4697da895133..a79db6b63466 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -920,6 +920,15 @@ void __init setup_arch(char **cmdline_p)
920 init_mm.end_code = (unsigned long) _etext; 920 init_mm.end_code = (unsigned long) _etext;
921 init_mm.end_data = (unsigned long) _edata; 921 init_mm.end_data = (unsigned long) _edata;
922 init_mm.brk = klimit; 922 init_mm.brk = klimit;
923
924#ifdef CONFIG_PPC_MM_SLICES
925#ifdef CONFIG_PPC64
926 init_mm.context.addr_limit = TASK_SIZE_USER64;
927#else
928#error "context.addr_limit not initialized."
929#endif
930#endif
931
923#ifdef CONFIG_PPC_64K_PAGES 932#ifdef CONFIG_PPC_64K_PAGES
924 init_mm.context.pte_frag = NULL; 933 init_mm.context.pte_frag = NULL;
925#endif 934#endif
diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c
index e5fde156e11d..fd0bc6db2dcd 100644
--- a/arch/powerpc/mm/mmu_context_book3s64.c
+++ b/arch/powerpc/mm/mmu_context_book3s64.c
@@ -79,6 +79,13 @@ static int hash__init_new_context(struct mm_struct *mm)
79 return index; 79 return index;
80 80
81 /* 81 /*
82 * We do switch_slb() early in fork, even before we setup the
83 * mm->context.addr_limit. Default to max task size so that we copy the
84 * default values to paca which will help us to handle slb miss early.
85 */
86 mm->context.addr_limit = TASK_SIZE_USER64;
87
88 /*
82 * The old code would re-promote on fork, we don't do that when using 89 * The old code would re-promote on fork, we don't do that when using
83 * slices as it could cause problem promoting slices that have been 90 * slices as it could cause problem promoting slices that have been
84 * forced down to 4K. 91 * forced down to 4K.
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index 95e5a20b1b6a..ded96edac817 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -136,7 +136,7 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret)
136 if (mm->task_size <= SLICE_LOW_TOP) 136 if (mm->task_size <= SLICE_LOW_TOP)
137 return; 137 return;
138 138
139 for (i = 0; i < SLICE_NUM_HIGH; i++) 139 for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.addr_limit); i++)
140 if (!slice_high_has_vma(mm, i)) 140 if (!slice_high_has_vma(mm, i))
141 __set_bit(i, ret->high_slices); 141 __set_bit(i, ret->high_slices);
142} 142}
@@ -157,7 +157,7 @@ static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_ma
157 ret->low_slices |= 1u << i; 157 ret->low_slices |= 1u << i;
158 158
159 hpsizes = mm->context.high_slices_psize; 159 hpsizes = mm->context.high_slices_psize;
160 for (i = 0; i < SLICE_NUM_HIGH; i++) { 160 for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.addr_limit); i++) {
161 mask_index = i & 0x1; 161 mask_index = i & 0x1;
162 index = i >> 1; 162 index = i >> 1;
163 if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize) 163 if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize)
@@ -165,15 +165,17 @@ static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_ma
165 } 165 }
166} 166}
167 167
168static int slice_check_fit(struct slice_mask mask, struct slice_mask available) 168static int slice_check_fit(struct mm_struct *mm,
169 struct slice_mask mask, struct slice_mask available)
169{ 170{
170 DECLARE_BITMAP(result, SLICE_NUM_HIGH); 171 DECLARE_BITMAP(result, SLICE_NUM_HIGH);
172 unsigned long slice_count = GET_HIGH_SLICE_INDEX(mm->context.addr_limit);
171 173
172 bitmap_and(result, mask.high_slices, 174 bitmap_and(result, mask.high_slices,
173 available.high_slices, SLICE_NUM_HIGH); 175 available.high_slices, slice_count);
174 176
175 return (mask.low_slices & available.low_slices) == mask.low_slices && 177 return (mask.low_slices & available.low_slices) == mask.low_slices &&
176 bitmap_equal(result, mask.high_slices, SLICE_NUM_HIGH); 178 bitmap_equal(result, mask.high_slices, slice_count);
177} 179}
178 180
179static void slice_flush_segments(void *parm) 181static void slice_flush_segments(void *parm)
@@ -217,7 +219,7 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
217 mm->context.low_slices_psize = lpsizes; 219 mm->context.low_slices_psize = lpsizes;
218 220
219 hpsizes = mm->context.high_slices_psize; 221 hpsizes = mm->context.high_slices_psize;
220 for (i = 0; i < SLICE_NUM_HIGH; i++) { 222 for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.addr_limit); i++) {
221 mask_index = i & 0x1; 223 mask_index = i & 0x1;
222 index = i >> 1; 224 index = i >> 1;
223 if (test_bit(i, mask.high_slices)) 225 if (test_bit(i, mask.high_slices))
@@ -484,7 +486,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
484 /* Check if we fit in the good mask. If we do, we just return, 486 /* Check if we fit in the good mask. If we do, we just return,
485 * nothing else to do 487 * nothing else to do
486 */ 488 */
487 if (slice_check_fit(mask, good_mask)) { 489 if (slice_check_fit(mm, mask, good_mask)) {
488 slice_dbg(" fits good !\n"); 490 slice_dbg(" fits good !\n");
489 return addr; 491 return addr;
490 } 492 }
@@ -509,7 +511,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
509 slice_or_mask(&potential_mask, &good_mask); 511 slice_or_mask(&potential_mask, &good_mask);
510 slice_print_mask(" potential", potential_mask); 512 slice_print_mask(" potential", potential_mask);
511 513
512 if ((addr != 0 || fixed) && slice_check_fit(mask, potential_mask)) { 514 if ((addr != 0 || fixed) && slice_check_fit(mm, mask, potential_mask)) {
513 slice_dbg(" fits potential !\n"); 515 slice_dbg(" fits potential !\n");
514 goto convert; 516 goto convert;
515 } 517 }
@@ -734,6 +736,6 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
734 slice_print_mask(" mask", mask); 736 slice_print_mask(" mask", mask);
735 slice_print_mask(" available", available); 737 slice_print_mask(" available", available);
736#endif 738#endif
737 return !slice_check_fit(mask, available); 739 return !slice_check_fit(mm, mask, available);
738} 740}
739#endif 741#endif