aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/mmu-hash64.h6
-rw-r--r--arch/powerpc/include/asm/page_64.h6
-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
5 files changed, 109 insertions, 55 deletions
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index 6aeb4986a373..7cbd541f915f 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -460,7 +460,11 @@ typedef struct {
460 460
461#ifdef CONFIG_PPC_MM_SLICES 461#ifdef CONFIG_PPC_MM_SLICES
462 u64 low_slices_psize; /* SLB page size encodings */ 462 u64 low_slices_psize; /* SLB page size encodings */
463 u64 high_slices_psize; /* 4 bits per slice for now */ 463 /*
464 * Right now we support 64TB and 4 bits for each
465 * 1TB slice we need 32 bytes for 64TB.
466 */
467 unsigned char high_slices_psize[32]; /* 4 bits per slice for now */
464#else 468#else
465 u16 sllp; /* SLB page size encoding */ 469 u16 sllp; /* SLB page size encoding */
466#endif 470#endif
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h
index fed85e6290e1..6c9bef4cb6a0 100644
--- a/arch/powerpc/include/asm/page_64.h
+++ b/arch/powerpc/include/asm/page_64.h
@@ -82,7 +82,11 @@ extern u64 ppc64_pft_size;
82 82
83struct slice_mask { 83struct slice_mask {
84 u16 low_slices; 84 u16 low_slices;
85 u16 high_slices; 85 /*
86 * This should be derived out of PGTABLE_RANGE. For the current
87 * max 64TB, u64 should be ok.
88 */
89 u64 high_slices;
86}; 90};
87 91
88struct mm_struct; 92struct mm_struct;
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