diff options
Diffstat (limited to 'arch/powerpc/mm/slice.c')
-rw-r--r-- | arch/powerpc/mm/slice.c | 112 |
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 | |||
37 | static DEFINE_SPINLOCK(slice_convert_lock); | 42 | static DEFINE_SPINLOCK(slice_convert_lock); |
38 | 43 | ||
39 | 44 | ||
@@ -42,7 +47,7 @@ int _slice_debug = 1; | |||
42 | 47 | ||
43 | static void slice_print_mask(const char *label, struct slice_mask mask) | 48 | static 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 | ||
143 | static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize) | 148 | static 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 | ||
184 | static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize) | 194 | static 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 | ||
588 | unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr) | 604 | unsigned 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 | } |
603 | EXPORT_SYMBOL_GPL(get_slice_psize); | 620 | EXPORT_SYMBOL_GPL(get_slice_psize); |
604 | 621 | ||
@@ -618,7 +635,9 @@ EXPORT_SYMBOL_GPL(get_slice_psize); | |||
618 | */ | 635 | */ |
619 | void slice_set_user_psize(struct mm_struct *mm, unsigned int psize) | 636 | void 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) | |||
660 | void slice_set_psize(struct mm_struct *mm, unsigned long address, | 685 | void 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 |