diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2012-09-09 22:52:52 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-09-17 02:31:50 -0400 |
commit | 7aa0727f3302931e698b3a7979ae5b9a4600da4e (patch) | |
tree | e84d09c79e5be7fe03bbf339a42924d4fbe2095b /arch/powerpc/mm | |
parent | 67550080b8288ee9b61e132e8ebc87d563f9c516 (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.c | 15 | ||||
-rw-r--r-- | arch/powerpc/mm/slb_low.S | 30 | ||||
-rw-r--r-- | arch/powerpc/mm/slice.c | 107 |
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 |
804 | unsigned int get_paca_psize(unsigned long addr) | 804 | unsigned 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 | ||
121 | 5: /* Extract the psize and multiply to get an array offset */ | 126 | 5: |
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 | ||
133 | 6: | ||
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 | ||
43 | static void slice_print_mask(const char *label, struct slice_mask mask) | 43 | static 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 | ||
143 | static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize) | 143 | static 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 | ||
184 | static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize) | 189 | static 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 | ||
588 | unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr) | 599 | unsigned 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 | } |
603 | EXPORT_SYMBOL_GPL(get_slice_psize); | 615 | EXPORT_SYMBOL_GPL(get_slice_psize); |
604 | 616 | ||
@@ -618,7 +630,9 @@ EXPORT_SYMBOL_GPL(get_slice_psize); | |||
618 | */ | 630 | */ |
619 | void slice_set_user_psize(struct mm_struct *mm, unsigned int psize) | 631 | void 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) | |||
660 | void slice_set_psize(struct mm_struct *mm, unsigned long address, | 680 | void 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 |