aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/slice.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/slice.c')
-rw-r--r--arch/powerpc/mm/slice.c112
1 files changed, 73 insertions, 39 deletions
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index 73709f7ce92c..5829d2a950d4 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -34,6 +34,11 @@
34#include <asm/mmu.h> 34#include <asm/mmu.h>
35#include <asm/spu.h> 35#include <asm/spu.h>
36 36
37/* some sanity checks */
38#if (PGTABLE_RANGE >> 43) > SLICE_MASK_SIZE
39#error PGTABLE_RANGE exceeds slice_mask high_slices size
40#endif
41
37static DEFINE_SPINLOCK(slice_convert_lock); 42static DEFINE_SPINLOCK(slice_convert_lock);
38 43
39 44
@@ -42,7 +47,7 @@ int _slice_debug = 1;
42 47
43static void slice_print_mask(const char *label, struct slice_mask mask) 48static void slice_print_mask(const char *label, struct slice_mask mask)
44{ 49{
45 char *p, buf[16 + 3 + 16 + 1]; 50 char *p, buf[16 + 3 + 64 + 1];
46 int i; 51 int i;
47 52
48 if (!_slice_debug) 53 if (!_slice_debug)
@@ -54,7 +59,7 @@ static void slice_print_mask(const char *label, struct slice_mask mask)
54 *(p++) = '-'; 59 *(p++) = '-';
55 *(p++) = ' '; 60 *(p++) = ' ';
56 for (i = 0; i < SLICE_NUM_HIGH; i++) 61 for (i = 0; i < SLICE_NUM_HIGH; i++)
57 *(p++) = (mask.high_slices & (1 << i)) ? '1' : '0'; 62 *(p++) = (mask.high_slices & (1ul << i)) ? '1' : '0';
58 *(p++) = 0; 63 *(p++) = 0;
59 64
60 printk(KERN_DEBUG "%s:%s\n", label, buf); 65 printk(KERN_DEBUG "%s:%s\n", label, buf);
@@ -84,8 +89,8 @@ static struct slice_mask slice_range_to_mask(unsigned long start,
84 } 89 }
85 90
86 if ((start + len) > SLICE_LOW_TOP) 91 if ((start + len) > SLICE_LOW_TOP)
87 ret.high_slices = (1u << (GET_HIGH_SLICE_INDEX(end) + 1)) 92 ret.high_slices = (1ul << (GET_HIGH_SLICE_INDEX(end) + 1))
88 - (1u << GET_HIGH_SLICE_INDEX(start)); 93 - (1ul << GET_HIGH_SLICE_INDEX(start));
89 94
90 return ret; 95 return ret;
91} 96}
@@ -135,26 +140,31 @@ static struct slice_mask slice_mask_for_free(struct mm_struct *mm)
135 140
136 for (i = 0; i < SLICE_NUM_HIGH; i++) 141 for (i = 0; i < SLICE_NUM_HIGH; i++)
137 if (!slice_high_has_vma(mm, i)) 142 if (!slice_high_has_vma(mm, i))
138 ret.high_slices |= 1u << i; 143 ret.high_slices |= 1ul << i;
139 144
140 return ret; 145 return ret;
141} 146}
142 147
143static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize) 148static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize)
144{ 149{
150 unsigned char *hpsizes;
151 int index, mask_index;
145 struct slice_mask ret = { 0, 0 }; 152 struct slice_mask ret = { 0, 0 };
146 unsigned long i; 153 unsigned long i;
147 u64 psizes; 154 u64 lpsizes;
148 155
149 psizes = mm->context.low_slices_psize; 156 lpsizes = mm->context.low_slices_psize;
150 for (i = 0; i < SLICE_NUM_LOW; i++) 157 for (i = 0; i < SLICE_NUM_LOW; i++)
151 if (((psizes >> (i * 4)) & 0xf) == psize) 158 if (((lpsizes >> (i * 4)) & 0xf) == psize)
152 ret.low_slices |= 1u << i; 159 ret.low_slices |= 1u << i;
153 160
154 psizes = mm->context.high_slices_psize; 161 hpsizes = mm->context.high_slices_psize;
155 for (i = 0; i < SLICE_NUM_HIGH; i++) 162 for (i = 0; i < SLICE_NUM_HIGH; i++) {
156 if (((psizes >> (i * 4)) & 0xf) == psize) 163 mask_index = i & 0x1;
157 ret.high_slices |= 1u << i; 164 index = i >> 1;
165 if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize)
166 ret.high_slices |= 1ul << i;
167 }
158 168
159 return ret; 169 return ret;
160} 170}
@@ -183,8 +193,10 @@ static void slice_flush_segments(void *parm)
183 193
184static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize) 194static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize)
185{ 195{
196 int index, mask_index;
186 /* Write the new slice psize bits */ 197 /* Write the new slice psize bits */
187 u64 lpsizes, hpsizes; 198 unsigned char *hpsizes;
199 u64 lpsizes;
188 unsigned long i, flags; 200 unsigned long i, flags;
189 201
190 slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize); 202 slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize);
@@ -201,14 +213,18 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
201 lpsizes = (lpsizes & ~(0xful << (i * 4))) | 213 lpsizes = (lpsizes & ~(0xful << (i * 4))) |
202 (((unsigned long)psize) << (i * 4)); 214 (((unsigned long)psize) << (i * 4));
203 215
204 hpsizes = mm->context.high_slices_psize; 216 /* 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; 217 mm->context.low_slices_psize = lpsizes;
211 mm->context.high_slices_psize = hpsizes; 218
219 hpsizes = mm->context.high_slices_psize;
220 for (i = 0; i < SLICE_NUM_HIGH; i++) {
221 mask_index = i & 0x1;
222 index = i >> 1;
223 if (mask.high_slices & (1ul << i))
224 hpsizes[index] = (hpsizes[index] &
225 ~(0xf << (mask_index * 4))) |
226 (((unsigned long)psize) << (mask_index * 4));
227 }
212 228
213 slice_dbg(" lsps=%lx, hsps=%lx\n", 229 slice_dbg(" lsps=%lx, hsps=%lx\n",
214 mm->context.low_slices_psize, 230 mm->context.low_slices_psize,
@@ -587,18 +603,19 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
587 603
588unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr) 604unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
589{ 605{
590 u64 psizes; 606 unsigned char *hpsizes;
591 int index; 607 int index, mask_index;
592 608
593 if (addr < SLICE_LOW_TOP) { 609 if (addr < SLICE_LOW_TOP) {
594 psizes = mm->context.low_slices_psize; 610 u64 lpsizes;
611 lpsizes = mm->context.low_slices_psize;
595 index = GET_LOW_SLICE_INDEX(addr); 612 index = GET_LOW_SLICE_INDEX(addr);
596 } else { 613 return (lpsizes >> (index * 4)) & 0xf;
597 psizes = mm->context.high_slices_psize;
598 index = GET_HIGH_SLICE_INDEX(addr);
599 } 614 }
600 615 hpsizes = mm->context.high_slices_psize;
601 return (psizes >> (index * 4)) & 0xf; 616 index = GET_HIGH_SLICE_INDEX(addr);
617 mask_index = index & 0x1;
618 return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xf;
602} 619}
603EXPORT_SYMBOL_GPL(get_slice_psize); 620EXPORT_SYMBOL_GPL(get_slice_psize);
604 621
@@ -618,7 +635,9 @@ EXPORT_SYMBOL_GPL(get_slice_psize);
618 */ 635 */
619void slice_set_user_psize(struct mm_struct *mm, unsigned int psize) 636void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
620{ 637{
621 unsigned long flags, lpsizes, hpsizes; 638 int index, mask_index;
639 unsigned char *hpsizes;
640 unsigned long flags, lpsizes;
622 unsigned int old_psize; 641 unsigned int old_psize;
623 int i; 642 int i;
624 643
@@ -639,15 +658,21 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
639 if (((lpsizes >> (i * 4)) & 0xf) == old_psize) 658 if (((lpsizes >> (i * 4)) & 0xf) == old_psize)
640 lpsizes = (lpsizes & ~(0xful << (i * 4))) | 659 lpsizes = (lpsizes & ~(0xful << (i * 4))) |
641 (((unsigned long)psize) << (i * 4)); 660 (((unsigned long)psize) << (i * 4));
661 /* Assign the value back */
662 mm->context.low_slices_psize = lpsizes;
642 663
643 hpsizes = mm->context.high_slices_psize; 664 hpsizes = mm->context.high_slices_psize;
644 for (i = 0; i < SLICE_NUM_HIGH; i++) 665 for (i = 0; i < SLICE_NUM_HIGH; i++) {
645 if (((hpsizes >> (i * 4)) & 0xf) == old_psize) 666 mask_index = i & 0x1;
646 hpsizes = (hpsizes & ~(0xful << (i * 4))) | 667 index = i >> 1;
647 (((unsigned long)psize) << (i * 4)); 668 if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == old_psize)
669 hpsizes[index] = (hpsizes[index] &
670 ~(0xf << (mask_index * 4))) |
671 (((unsigned long)psize) << (mask_index * 4));
672 }
673
674
648 675
649 mm->context.low_slices_psize = lpsizes;
650 mm->context.high_slices_psize = hpsizes;
651 676
652 slice_dbg(" lsps=%lx, hsps=%lx\n", 677 slice_dbg(" lsps=%lx, hsps=%lx\n",
653 mm->context.low_slices_psize, 678 mm->context.low_slices_psize,
@@ -660,18 +685,27 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
660void slice_set_psize(struct mm_struct *mm, unsigned long address, 685void slice_set_psize(struct mm_struct *mm, unsigned long address,
661 unsigned int psize) 686 unsigned int psize)
662{ 687{
688 unsigned char *hpsizes;
663 unsigned long i, flags; 689 unsigned long i, flags;
664 u64 *p; 690 u64 *lpsizes;
665 691
666 spin_lock_irqsave(&slice_convert_lock, flags); 692 spin_lock_irqsave(&slice_convert_lock, flags);
667 if (address < SLICE_LOW_TOP) { 693 if (address < SLICE_LOW_TOP) {
668 i = GET_LOW_SLICE_INDEX(address); 694 i = GET_LOW_SLICE_INDEX(address);
669 p = &mm->context.low_slices_psize; 695 lpsizes = &mm->context.low_slices_psize;
696 *lpsizes = (*lpsizes & ~(0xful << (i * 4))) |
697 ((unsigned long) psize << (i * 4));
670 } else { 698 } else {
699 int index, mask_index;
671 i = GET_HIGH_SLICE_INDEX(address); 700 i = GET_HIGH_SLICE_INDEX(address);
672 p = &mm->context.high_slices_psize; 701 hpsizes = mm->context.high_slices_psize;
702 mask_index = i & 0x1;
703 index = i >> 1;
704 hpsizes[index] = (hpsizes[index] &
705 ~(0xf << (mask_index * 4))) |
706 (((unsigned long)psize) << (mask_index * 4));
673 } 707 }
674 *p = (*p & ~(0xful << (i * 4))) | ((unsigned long) psize << (i * 4)); 708
675 spin_unlock_irqrestore(&slice_convert_lock, flags); 709 spin_unlock_irqrestore(&slice_convert_lock, flags);
676 710
677#ifdef CONFIG_SPU_BASE 711#ifdef CONFIG_SPU_BASE