aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2012-09-09 22:52:52 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-09-17 02:31:50 -0400
commit7aa0727f3302931e698b3a7979ae5b9a4600da4e (patch)
treee84d09c79e5be7fe03bbf339a42924d4fbe2095b /arch/powerpc/mm
parent67550080b8288ee9b61e132e8ebc87d563f9c516 (diff)
powerpc/mm: Increase the slice range to 64TB
This patch makes the high psizes mask as an unsigned char array so that we can have more than 16TB. Currently we support upto 64TB Reviewed-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r--arch/powerpc/mm/hash_utils_64.c15
-rw-r--r--arch/powerpc/mm/slb_low.S30
-rw-r--r--arch/powerpc/mm/slice.c107
3 files changed, 99 insertions, 53 deletions
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 7d4ffd79cc82..3a292be2e079 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -803,16 +803,19 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
803#ifdef CONFIG_PPC_MM_SLICES 803#ifdef CONFIG_PPC_MM_SLICES
804unsigned int get_paca_psize(unsigned long addr) 804unsigned int get_paca_psize(unsigned long addr)
805{ 805{
806 unsigned long index, slices; 806 u64 lpsizes;
807 unsigned char *hpsizes;
808 unsigned long index, mask_index;
807 809
808 if (addr < SLICE_LOW_TOP) { 810 if (addr < SLICE_LOW_TOP) {
809 slices = get_paca()->context.low_slices_psize; 811 lpsizes = get_paca()->context.low_slices_psize;
810 index = GET_LOW_SLICE_INDEX(addr); 812 index = GET_LOW_SLICE_INDEX(addr);
811 } else { 813 return (lpsizes >> (index * 4)) & 0xF;
812 slices = get_paca()->context.high_slices_psize;
813 index = GET_HIGH_SLICE_INDEX(addr);
814 } 814 }
815 return (slices >> (index * 4)) & 0xF; 815 hpsizes = get_paca()->context.high_slices_psize;
816 index = GET_HIGH_SLICE_INDEX(addr);
817 mask_index = index & 0x1;
818 return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xF;
816} 819}
817 820
818#else 821#else
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index b9ee79ce2200..e132dc6ed1a9 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -108,17 +108,31 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
108 * between 4k and 64k standard page size 108 * between 4k and 64k standard page size
109 */ 109 */
110#ifdef CONFIG_PPC_MM_SLICES 110#ifdef CONFIG_PPC_MM_SLICES
111 /* r10 have esid */
111 cmpldi r10,16 112 cmpldi r10,16
112 113 /* below SLICE_LOW_TOP */
113 /* Get the slice index * 4 in r11 and matching slice size mask in r9 */
114 ld r9,PACALOWSLICESPSIZE(r13)
115 sldi r11,r10,2
116 blt 5f 114 blt 5f
117 ld r9,PACAHIGHSLICEPSIZE(r13) 115 /*
118 srdi r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT - 2) 116 * Handle hpsizes,
119 andi. r11,r11,0x3c 117 * r9 is get_paca()->context.high_slices_psize[index], r11 is mask_index
118 */
119 srdi r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT + 1) /* index */
120 addi r9,r11,PACAHIGHSLICEPSIZE
121 lbzx r9,r13,r9 /* r9 is hpsizes[r11] */
122 /* r11 = (r10 >> (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)) & 0x1 */
123 rldicl r11,r10,(64 - (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)),63
124 b 6f
120 125
1215: /* Extract the psize and multiply to get an array offset */ 1265:
127 /*
128 * Handle lpsizes
129 * r9 is get_paca()->context.low_slices_psize, r11 is index
130 */
131 ld r9,PACALOWSLICESPSIZE(r13)
132 mr r11,r10
1336:
134 sldi r11,r11,2 /* index * 4 */
135 /* Extract the psize and multiply to get an array offset */
122 srd r9,r9,r11 136 srd r9,r9,r11
123 andi. r9,r9,0xf 137 andi. r9,r9,0xf
124 mulli r9,r9,MMUPSIZEDEFSIZE 138 mulli r9,r9,MMUPSIZEDEFSIZE
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index 73709f7ce92c..b4e996a398bd 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -42,7 +42,7 @@ int _slice_debug = 1;
42 42
43static void slice_print_mask(const char *label, struct slice_mask mask) 43static void slice_print_mask(const char *label, struct slice_mask mask)
44{ 44{
45 char *p, buf[16 + 3 + 16 + 1]; 45 char *p, buf[16 + 3 + 64 + 1];
46 int i; 46 int i;
47 47
48 if (!_slice_debug) 48 if (!_slice_debug)
@@ -54,7 +54,7 @@ static void slice_print_mask(const char *label, struct slice_mask mask)
54 *(p++) = '-'; 54 *(p++) = '-';
55 *(p++) = ' '; 55 *(p++) = ' ';
56 for (i = 0; i < SLICE_NUM_HIGH; i++) 56 for (i = 0; i < SLICE_NUM_HIGH; i++)
57 *(p++) = (mask.high_slices & (1 << i)) ? '1' : '0'; 57 *(p++) = (mask.high_slices & (1ul << i)) ? '1' : '0';
58 *(p++) = 0; 58 *(p++) = 0;
59 59
60 printk(KERN_DEBUG "%s:%s\n", label, buf); 60 printk(KERN_DEBUG "%s:%s\n", label, buf);
@@ -84,8 +84,8 @@ static struct slice_mask slice_range_to_mask(unsigned long start,
84 } 84 }
85 85
86 if ((start + len) > SLICE_LOW_TOP) 86 if ((start + len) > SLICE_LOW_TOP)
87 ret.high_slices = (1u << (GET_HIGH_SLICE_INDEX(end) + 1)) 87 ret.high_slices = (1ul << (GET_HIGH_SLICE_INDEX(end) + 1))
88 - (1u << GET_HIGH_SLICE_INDEX(start)); 88 - (1ul << GET_HIGH_SLICE_INDEX(start));
89 89
90 return ret; 90 return ret;
91} 91}
@@ -135,26 +135,31 @@ static struct slice_mask slice_mask_for_free(struct mm_struct *mm)
135 135
136 for (i = 0; i < SLICE_NUM_HIGH; i++) 136 for (i = 0; i < SLICE_NUM_HIGH; i++)
137 if (!slice_high_has_vma(mm, i)) 137 if (!slice_high_has_vma(mm, i))
138 ret.high_slices |= 1u << i; 138 ret.high_slices |= 1ul << i;
139 139
140 return ret; 140 return ret;
141} 141}
142 142
143static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize) 143static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize)
144{ 144{
145 unsigned char *hpsizes;
146 int index, mask_index;
145 struct slice_mask ret = { 0, 0 }; 147 struct slice_mask ret = { 0, 0 };
146 unsigned long i; 148 unsigned long i;
147 u64 psizes; 149 u64 lpsizes;
148 150
149 psizes = mm->context.low_slices_psize; 151 lpsizes = mm->context.low_slices_psize;
150 for (i = 0; i < SLICE_NUM_LOW; i++) 152 for (i = 0; i < SLICE_NUM_LOW; i++)
151 if (((psizes >> (i * 4)) & 0xf) == psize) 153 if (((lpsizes >> (i * 4)) & 0xf) == psize)
152 ret.low_slices |= 1u << i; 154 ret.low_slices |= 1u << i;
153 155
154 psizes = mm->context.high_slices_psize; 156 hpsizes = mm->context.high_slices_psize;
155 for (i = 0; i < SLICE_NUM_HIGH; i++) 157 for (i = 0; i < SLICE_NUM_HIGH; i++) {
156 if (((psizes >> (i * 4)) & 0xf) == psize) 158 mask_index = i & 0x1;
157 ret.high_slices |= 1u << i; 159 index = i >> 1;
160 if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize)
161 ret.high_slices |= 1ul << i;
162 }
158 163
159 return ret; 164 return ret;
160} 165}
@@ -183,8 +188,10 @@ static void slice_flush_segments(void *parm)
183 188
184static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize) 189static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize)
185{ 190{
191 int index, mask_index;
186 /* Write the new slice psize bits */ 192 /* Write the new slice psize bits */
187 u64 lpsizes, hpsizes; 193 unsigned char *hpsizes;
194 u64 lpsizes;
188 unsigned long i, flags; 195 unsigned long i, flags;
189 196
190 slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize); 197 slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize);
@@ -201,14 +208,18 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
201 lpsizes = (lpsizes & ~(0xful << (i * 4))) | 208 lpsizes = (lpsizes & ~(0xful << (i * 4))) |
202 (((unsigned long)psize) << (i * 4)); 209 (((unsigned long)psize) << (i * 4));
203 210
204 hpsizes = mm->context.high_slices_psize; 211 /* Assign the value back */
205 for (i = 0; i < SLICE_NUM_HIGH; i++)
206 if (mask.high_slices & (1u << i))
207 hpsizes = (hpsizes & ~(0xful << (i * 4))) |
208 (((unsigned long)psize) << (i * 4));
209
210 mm->context.low_slices_psize = lpsizes; 212 mm->context.low_slices_psize = lpsizes;
211 mm->context.high_slices_psize = hpsizes; 213
214 hpsizes = mm->context.high_slices_psize;
215 for (i = 0; i < SLICE_NUM_HIGH; i++) {
216 mask_index = i & 0x1;
217 index = i >> 1;
218 if (mask.high_slices & (1ul << i))
219 hpsizes[index] = (hpsizes[index] &
220 ~(0xf << (mask_index * 4))) |
221 (((unsigned long)psize) << (mask_index * 4));
222 }
212 223
213 slice_dbg(" lsps=%lx, hsps=%lx\n", 224 slice_dbg(" lsps=%lx, hsps=%lx\n",
214 mm->context.low_slices_psize, 225 mm->context.low_slices_psize,
@@ -587,18 +598,19 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
587 598
588unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr) 599unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
589{ 600{
590 u64 psizes; 601 unsigned char *hpsizes;
591 int index; 602 int index, mask_index;
592 603
593 if (addr < SLICE_LOW_TOP) { 604 if (addr < SLICE_LOW_TOP) {
594 psizes = mm->context.low_slices_psize; 605 u64 lpsizes;
606 lpsizes = mm->context.low_slices_psize;
595 index = GET_LOW_SLICE_INDEX(addr); 607 index = GET_LOW_SLICE_INDEX(addr);
596 } else { 608 return (lpsizes >> (index * 4)) & 0xf;
597 psizes = mm->context.high_slices_psize;
598 index = GET_HIGH_SLICE_INDEX(addr);
599 } 609 }
600 610 hpsizes = mm->context.high_slices_psize;
601 return (psizes >> (index * 4)) & 0xf; 611 index = GET_HIGH_SLICE_INDEX(addr);
612 mask_index = index & 0x1;
613 return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xf;
602} 614}
603EXPORT_SYMBOL_GPL(get_slice_psize); 615EXPORT_SYMBOL_GPL(get_slice_psize);
604 616
@@ -618,7 +630,9 @@ EXPORT_SYMBOL_GPL(get_slice_psize);
618 */ 630 */
619void slice_set_user_psize(struct mm_struct *mm, unsigned int psize) 631void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
620{ 632{
621 unsigned long flags, lpsizes, hpsizes; 633 int index, mask_index;
634 unsigned char *hpsizes;
635 unsigned long flags, lpsizes;
622 unsigned int old_psize; 636 unsigned int old_psize;
623 int i; 637 int i;
624 638
@@ -639,15 +653,21 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
639 if (((lpsizes >> (i * 4)) & 0xf) == old_psize) 653 if (((lpsizes >> (i * 4)) & 0xf) == old_psize)
640 lpsizes = (lpsizes & ~(0xful << (i * 4))) | 654 lpsizes = (lpsizes & ~(0xful << (i * 4))) |
641 (((unsigned long)psize) << (i * 4)); 655 (((unsigned long)psize) << (i * 4));
656 /* Assign the value back */
657 mm->context.low_slices_psize = lpsizes;
642 658
643 hpsizes = mm->context.high_slices_psize; 659 hpsizes = mm->context.high_slices_psize;
644 for (i = 0; i < SLICE_NUM_HIGH; i++) 660 for (i = 0; i < SLICE_NUM_HIGH; i++) {
645 if (((hpsizes >> (i * 4)) & 0xf) == old_psize) 661 mask_index = i & 0x1;
646 hpsizes = (hpsizes & ~(0xful << (i * 4))) | 662 index = i >> 1;
647 (((unsigned long)psize) << (i * 4)); 663 if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == old_psize)
664 hpsizes[index] = (hpsizes[index] &
665 ~(0xf << (mask_index * 4))) |
666 (((unsigned long)psize) << (mask_index * 4));
667 }
668
669
648 670
649 mm->context.low_slices_psize = lpsizes;
650 mm->context.high_slices_psize = hpsizes;
651 671
652 slice_dbg(" lsps=%lx, hsps=%lx\n", 672 slice_dbg(" lsps=%lx, hsps=%lx\n",
653 mm->context.low_slices_psize, 673 mm->context.low_slices_psize,
@@ -660,18 +680,27 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
660void slice_set_psize(struct mm_struct *mm, unsigned long address, 680void slice_set_psize(struct mm_struct *mm, unsigned long address,
661 unsigned int psize) 681 unsigned int psize)
662{ 682{
683 unsigned char *hpsizes;
663 unsigned long i, flags; 684 unsigned long i, flags;
664 u64 *p; 685 u64 *lpsizes;
665 686
666 spin_lock_irqsave(&slice_convert_lock, flags); 687 spin_lock_irqsave(&slice_convert_lock, flags);
667 if (address < SLICE_LOW_TOP) { 688 if (address < SLICE_LOW_TOP) {
668 i = GET_LOW_SLICE_INDEX(address); 689 i = GET_LOW_SLICE_INDEX(address);
669 p = &mm->context.low_slices_psize; 690 lpsizes = &mm->context.low_slices_psize;
691 *lpsizes = (*lpsizes & ~(0xful << (i * 4))) |
692 ((unsigned long) psize << (i * 4));
670 } else { 693 } else {
694 int index, mask_index;
671 i = GET_HIGH_SLICE_INDEX(address); 695 i = GET_HIGH_SLICE_INDEX(address);
672 p = &mm->context.high_slices_psize; 696 hpsizes = mm->context.high_slices_psize;
697 mask_index = i & 0x1;
698 index = i >> 1;
699 hpsizes[index] = (hpsizes[index] &
700 ~(0xf << (mask_index * 4))) |
701 (((unsigned long)psize) << (mask_index * 4));
673 } 702 }
674 *p = (*p & ~(0xful << (i * 4))) | ((unsigned long) psize << (i * 4)); 703
675 spin_unlock_irqrestore(&slice_convert_lock, flags); 704 spin_unlock_irqrestore(&slice_convert_lock, flags);
676 705
677#ifdef CONFIG_SPU_BASE 706#ifdef CONFIG_SPU_BASE