diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-09-05 12:56:57 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-05 12:56:57 -0400 |
commit | 616ad8c44281c0c6711a72b560e01ec335ff27e0 (patch) | |
tree | 0a20453ffedb09db6fb41a0c2208ccc2c7751d3a /arch/powerpc/platforms | |
parent | 99809963c99e1ed868d9ebeb4a5e7ee1cbe0309f (diff) | |
parent | b380b0d4f7dffcc235c0facefa537d4655619101 (diff) |
Merge branch 'linus' into x86/defconfig
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/run.c | 15 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/sched.c | 11 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/ps3/htab.c | 269 | ||||
-rw-r--r-- | arch/powerpc/platforms/ps3/setup.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/ps3/spu.c | 18 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/plpar_wrappers.h | 27 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 29 |
8 files changed, 169 insertions, 203 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index f7edba6cb795..c9bb7cfd3dca 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -206,11 +206,6 @@ static int spu_run_init(struct spu_context *ctx, u32 *npc) | |||
206 | (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); | 206 | (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); |
207 | if (runcntl == 0) | 207 | if (runcntl == 0) |
208 | runcntl = SPU_RUNCNTL_RUNNABLE; | 208 | runcntl = SPU_RUNCNTL_RUNNABLE; |
209 | } | ||
210 | |||
211 | if (ctx->flags & SPU_CREATE_NOSCHED) { | ||
212 | spuctx_switch_state(ctx, SPU_UTIL_USER); | ||
213 | ctx->ops->runcntl_write(ctx, runcntl); | ||
214 | } else { | 209 | } else { |
215 | unsigned long privcntl; | 210 | unsigned long privcntl; |
216 | 211 | ||
@@ -219,9 +214,15 @@ static int spu_run_init(struct spu_context *ctx, u32 *npc) | |||
219 | else | 214 | else |
220 | privcntl = SPU_PRIVCNTL_MODE_NORMAL; | 215 | privcntl = SPU_PRIVCNTL_MODE_NORMAL; |
221 | 216 | ||
222 | ctx->ops->npc_write(ctx, *npc); | ||
223 | ctx->ops->privcntl_write(ctx, privcntl); | 217 | ctx->ops->privcntl_write(ctx, privcntl); |
224 | ctx->ops->runcntl_write(ctx, runcntl); | 218 | ctx->ops->npc_write(ctx, *npc); |
219 | } | ||
220 | |||
221 | ctx->ops->runcntl_write(ctx, runcntl); | ||
222 | |||
223 | if (ctx->flags & SPU_CREATE_NOSCHED) { | ||
224 | spuctx_switch_state(ctx, SPU_UTIL_USER); | ||
225 | } else { | ||
225 | 226 | ||
226 | if (ctx->state == SPU_STATE_SAVED) { | 227 | if (ctx->state == SPU_STATE_SAVED) { |
227 | ret = spu_activate(ctx, 0); | 228 | ret = spu_activate(ctx, 0); |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 2deeeba7eccf..1c1b627ee843 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -641,8 +641,10 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
641 | 641 | ||
642 | if (tmp && tmp->prio > ctx->prio && | 642 | if (tmp && tmp->prio > ctx->prio && |
643 | !(tmp->flags & SPU_CREATE_NOSCHED) && | 643 | !(tmp->flags & SPU_CREATE_NOSCHED) && |
644 | (!victim || tmp->prio > victim->prio)) | 644 | (!victim || tmp->prio > victim->prio)) { |
645 | victim = spu->ctx; | 645 | victim = spu->ctx; |
646 | get_spu_context(victim); | ||
647 | } | ||
646 | } | 648 | } |
647 | mutex_unlock(&cbe_spu_info[node].list_mutex); | 649 | mutex_unlock(&cbe_spu_info[node].list_mutex); |
648 | 650 | ||
@@ -658,6 +660,7 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
658 | * look at another context or give up after X retries. | 660 | * look at another context or give up after X retries. |
659 | */ | 661 | */ |
660 | if (!mutex_trylock(&victim->state_mutex)) { | 662 | if (!mutex_trylock(&victim->state_mutex)) { |
663 | put_spu_context(victim); | ||
661 | victim = NULL; | 664 | victim = NULL; |
662 | goto restart; | 665 | goto restart; |
663 | } | 666 | } |
@@ -670,6 +673,7 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
670 | * restart the search. | 673 | * restart the search. |
671 | */ | 674 | */ |
672 | mutex_unlock(&victim->state_mutex); | 675 | mutex_unlock(&victim->state_mutex); |
676 | put_spu_context(victim); | ||
673 | victim = NULL; | 677 | victim = NULL; |
674 | goto restart; | 678 | goto restart; |
675 | } | 679 | } |
@@ -687,6 +691,7 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
687 | spu_add_to_rq(victim); | 691 | spu_add_to_rq(victim); |
688 | 692 | ||
689 | mutex_unlock(&victim->state_mutex); | 693 | mutex_unlock(&victim->state_mutex); |
694 | put_spu_context(victim); | ||
690 | 695 | ||
691 | return spu; | 696 | return spu; |
692 | } | 697 | } |
@@ -985,9 +990,11 @@ static int spusched_thread(void *unused) | |||
985 | struct spu_context *ctx = spu->ctx; | 990 | struct spu_context *ctx = spu->ctx; |
986 | 991 | ||
987 | if (ctx) { | 992 | if (ctx) { |
993 | get_spu_context(ctx); | ||
988 | mutex_unlock(mtx); | 994 | mutex_unlock(mtx); |
989 | spusched_tick(ctx); | 995 | spusched_tick(ctx); |
990 | mutex_lock(mtx); | 996 | mutex_lock(mtx); |
997 | put_spu_context(ctx); | ||
991 | } | 998 | } |
992 | } | 999 | } |
993 | mutex_unlock(mtx); | 1000 | mutex_unlock(mtx); |
@@ -1030,7 +1037,7 @@ void spuctx_switch_state(struct spu_context *ctx, | |||
1030 | node = spu->node; | 1037 | node = spu->node; |
1031 | if (old_state == SPU_UTIL_USER) | 1038 | if (old_state == SPU_UTIL_USER) |
1032 | atomic_dec(&cbe_spu_info[node].busy_spus); | 1039 | atomic_dec(&cbe_spu_info[node].busy_spus); |
1033 | if (new_state == SPU_UTIL_USER); | 1040 | if (new_state == SPU_UTIL_USER) |
1034 | atomic_inc(&cbe_spu_info[node].busy_spus); | 1041 | atomic_inc(&cbe_spu_info[node].busy_spus); |
1035 | } | 1042 | } |
1036 | } | 1043 | } |
diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile index 58ecdd72630f..be60d64be7ad 100644 --- a/arch/powerpc/platforms/powermac/Makefile +++ b/arch/powerpc/platforms/powermac/Makefile | |||
@@ -2,7 +2,7 @@ CFLAGS_bootx_init.o += -fPIC | |||
2 | 2 | ||
3 | ifdef CONFIG_FTRACE | 3 | ifdef CONFIG_FTRACE |
4 | # Do not trace early boot code | 4 | # Do not trace early boot code |
5 | CFLAGS_REMOVE_bootx_init.o = -pg | 5 | CFLAGS_REMOVE_bootx_init.o = -pg -mno-sched-epilog |
6 | endif | 6 | endif |
7 | 7 | ||
8 | obj-y += pic.o setup.o time.o feature.o pci.o \ | 8 | obj-y += pic.o setup.o time.o feature.o pci.o \ |
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index 1cf901fa9031..6eb1d4d182c9 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c | |||
@@ -29,138 +29,75 @@ | |||
29 | 29 | ||
30 | #include "platform.h" | 30 | #include "platform.h" |
31 | 31 | ||
32 | #if defined(DEBUG) | 32 | /** |
33 | #define DBG udbg_printf | 33 | * enum lpar_vas_id - id of LPAR virtual address space. |
34 | #else | 34 | * @lpar_vas_id_current: Current selected virtual address space |
35 | #define DBG pr_debug | 35 | * |
36 | #endif | 36 | * Identify the target LPAR address space. |
37 | 37 | */ | |
38 | static struct hash_pte *htab; | 38 | |
39 | static unsigned long htab_addr; | 39 | enum ps3_lpar_vas_id { |
40 | static unsigned char *bolttab; | 40 | PS3_LPAR_VAS_ID_CURRENT = 0, |
41 | static unsigned char *inusetab; | 41 | }; |
42 | 42 | ||
43 | static DEFINE_SPINLOCK(ps3_bolttab_lock); | 43 | |
44 | 44 | static DEFINE_SPINLOCK(ps3_htab_lock); | |
45 | #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \ | ||
46 | _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) | ||
47 | static void _debug_dump_hpte(unsigned long pa, unsigned long va, | ||
48 | unsigned long group, unsigned long bitmap, struct hash_pte lhpte, | ||
49 | int psize, unsigned long slot, const char* func, int line) | ||
50 | { | ||
51 | DBG("%s:%d: pa = %lxh\n", func, line, pa); | ||
52 | DBG("%s:%d: lpar = %lxh\n", func, line, | ||
53 | ps3_mm_phys_to_lpar(pa)); | ||
54 | DBG("%s:%d: va = %lxh\n", func, line, va); | ||
55 | DBG("%s:%d: group = %lxh\n", func, line, group); | ||
56 | DBG("%s:%d: bitmap = %lxh\n", func, line, bitmap); | ||
57 | DBG("%s:%d: hpte.v = %lxh\n", func, line, lhpte.v); | ||
58 | DBG("%s:%d: hpte.r = %lxh\n", func, line, lhpte.r); | ||
59 | DBG("%s:%d: psize = %xh\n", func, line, psize); | ||
60 | DBG("%s:%d: slot = %lxh\n", func, line, slot); | ||
61 | } | ||
62 | 45 | ||
63 | static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, | 46 | static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, |
64 | unsigned long pa, unsigned long rflags, unsigned long vflags, | 47 | unsigned long pa, unsigned long rflags, unsigned long vflags, |
65 | int psize, int ssize) | 48 | int psize, int ssize) |
66 | { | 49 | { |
67 | unsigned long slot; | 50 | int result; |
68 | struct hash_pte lhpte; | 51 | u64 hpte_v, hpte_r; |
69 | int secondary = 0; | 52 | u64 inserted_index; |
70 | unsigned long result; | 53 | u64 evicted_v, evicted_r; |
71 | unsigned long bitmap; | 54 | u64 hpte_v_array[4], hpte_rs; |
72 | unsigned long flags; | 55 | unsigned long flags; |
73 | unsigned long p_pteg, s_pteg, b_index, b_mask, cb, ci; | 56 | long ret = -1; |
74 | |||
75 | vflags &= ~HPTE_V_SECONDARY; /* this bit is ignored */ | ||
76 | |||
77 | lhpte.v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) | | ||
78 | vflags | HPTE_V_VALID; | ||
79 | lhpte.r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags; | ||
80 | |||
81 | p_pteg = hpte_group / HPTES_PER_GROUP; | ||
82 | s_pteg = ~p_pteg & htab_hash_mask; | ||
83 | |||
84 | spin_lock_irqsave(&ps3_bolttab_lock, flags); | ||
85 | |||
86 | BUG_ON(bolttab[p_pteg] == 0xff && bolttab[s_pteg] == 0xff); | ||
87 | 57 | ||
88 | bitmap = (inusetab[p_pteg] << 8) | inusetab[s_pteg]; | 58 | /* |
59 | * lv1_insert_htab_entry() will search for victim | ||
60 | * entry in both primary and secondary pte group | ||
61 | */ | ||
62 | vflags &= ~HPTE_V_SECONDARY; | ||
89 | 63 | ||
90 | if (bitmap == 0xffff) { | 64 | hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID; |
91 | /* | 65 | hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags; |
92 | * PTEG is full. Search for victim. | ||
93 | */ | ||
94 | bitmap &= ~((bolttab[p_pteg] << 8) | bolttab[s_pteg]); | ||
95 | do { | ||
96 | ci = mftb() & 15; | ||
97 | cb = 0x8000UL >> ci; | ||
98 | } while ((cb & bitmap) == 0); | ||
99 | } else { | ||
100 | /* | ||
101 | * search free slot in hardware order | ||
102 | * [primary] 0, 2, 4, 6, 1, 3, 5, 7 | ||
103 | * [secondary] 0, 2, 4, 6, 1, 3, 5, 7 | ||
104 | */ | ||
105 | for (ci = 0; ci < HPTES_PER_GROUP; ci += 2) { | ||
106 | cb = 0x8000UL >> ci; | ||
107 | if ((cb & bitmap) == 0) | ||
108 | goto found; | ||
109 | } | ||
110 | for (ci = 1; ci < HPTES_PER_GROUP; ci += 2) { | ||
111 | cb = 0x8000UL >> ci; | ||
112 | if ((cb & bitmap) == 0) | ||
113 | goto found; | ||
114 | } | ||
115 | for (ci = HPTES_PER_GROUP; ci < HPTES_PER_GROUP*2; ci += 2) { | ||
116 | cb = 0x8000UL >> ci; | ||
117 | if ((cb & bitmap) == 0) | ||
118 | goto found; | ||
119 | } | ||
120 | for (ci = HPTES_PER_GROUP+1; ci < HPTES_PER_GROUP*2; ci += 2) { | ||
121 | cb = 0x8000UL >> ci; | ||
122 | if ((cb & bitmap) == 0) | ||
123 | goto found; | ||
124 | } | ||
125 | } | ||
126 | 66 | ||
127 | found: | 67 | spin_lock_irqsave(&ps3_htab_lock, flags); |
128 | if (ci < HPTES_PER_GROUP) { | ||
129 | slot = p_pteg * HPTES_PER_GROUP + ci; | ||
130 | } else { | ||
131 | slot = s_pteg * HPTES_PER_GROUP + (ci & 7); | ||
132 | /* lhpte.dw0.dw0.h = 1; */ | ||
133 | vflags |= HPTE_V_SECONDARY; | ||
134 | lhpte.v |= HPTE_V_SECONDARY; | ||
135 | } | ||
136 | 68 | ||
137 | result = lv1_write_htab_entry(0, slot, lhpte.v, lhpte.r); | 69 | /* talk hvc to replace entries BOLTED == 0 */ |
70 | result = lv1_insert_htab_entry(PS3_LPAR_VAS_ID_CURRENT, hpte_group, | ||
71 | hpte_v, hpte_r, | ||
72 | HPTE_V_BOLTED, 0, | ||
73 | &inserted_index, | ||
74 | &evicted_v, &evicted_r); | ||
138 | 75 | ||
139 | if (result) { | 76 | if (result) { |
140 | debug_dump_hpte(pa, va, hpte_group, bitmap, lhpte, psize, slot); | 77 | /* all entries bolted !*/ |
78 | pr_info("%s:result=%d va=%lx pa=%lx ix=%lx v=%lx r=%lx\n", | ||
79 | __func__, result, va, pa, hpte_group, hpte_v, hpte_r); | ||
141 | BUG(); | 80 | BUG(); |
142 | } | 81 | } |
143 | 82 | ||
144 | /* | 83 | /* |
145 | * If used slot is not in primary HPTE group, | 84 | * see if the entry is inserted into secondary pteg |
146 | * the slot should be in secondary HPTE group. | ||
147 | */ | 85 | */ |
86 | result = lv1_read_htab_entries(PS3_LPAR_VAS_ID_CURRENT, | ||
87 | inserted_index & ~0x3UL, | ||
88 | &hpte_v_array[0], &hpte_v_array[1], | ||
89 | &hpte_v_array[2], &hpte_v_array[3], | ||
90 | &hpte_rs); | ||
91 | BUG_ON(result); | ||
148 | 92 | ||
149 | if ((hpte_group ^ slot) & ~(HPTES_PER_GROUP - 1)) { | 93 | if (hpte_v_array[inserted_index % 4] & HPTE_V_SECONDARY) |
150 | secondary = 1; | 94 | ret = (inserted_index & 7) | (1 << 3); |
151 | b_index = s_pteg; | 95 | else |
152 | } else { | 96 | ret = inserted_index & 7; |
153 | secondary = 0; | ||
154 | b_index = p_pteg; | ||
155 | } | ||
156 | 97 | ||
157 | b_mask = (lhpte.v & HPTE_V_BOLTED) ? 1 << 7 : 0 << 7; | 98 | spin_unlock_irqrestore(&ps3_htab_lock, flags); |
158 | bolttab[b_index] |= b_mask >> (slot & 7); | ||
159 | b_mask = 1 << 7; | ||
160 | inusetab[b_index] |= b_mask >> (slot & 7); | ||
161 | spin_unlock_irqrestore(&ps3_bolttab_lock, flags); | ||
162 | 99 | ||
163 | return (slot & 7) | (secondary << 3); | 100 | return ret; |
164 | } | 101 | } |
165 | 102 | ||
166 | static long ps3_hpte_remove(unsigned long hpte_group) | 103 | static long ps3_hpte_remove(unsigned long hpte_group) |
@@ -172,39 +109,48 @@ static long ps3_hpte_remove(unsigned long hpte_group) | |||
172 | static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, | 109 | static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, |
173 | unsigned long va, int psize, int ssize, int local) | 110 | unsigned long va, int psize, int ssize, int local) |
174 | { | 111 | { |
112 | int result; | ||
113 | u64 hpte_v, want_v, hpte_rs; | ||
114 | u64 hpte_v_array[4]; | ||
175 | unsigned long flags; | 115 | unsigned long flags; |
176 | unsigned long result; | 116 | long ret; |
177 | unsigned long pteg, bit; | ||
178 | unsigned long hpte_v, want_v; | ||
179 | 117 | ||
180 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); | 118 | want_v = hpte_encode_v(va, psize, ssize); |
181 | 119 | ||
182 | spin_lock_irqsave(&ps3_bolttab_lock, flags); | 120 | spin_lock_irqsave(&ps3_htab_lock, flags); |
183 | 121 | ||
184 | hpte_v = htab[slot].v; | 122 | result = lv1_read_htab_entries(PS3_LPAR_VAS_ID_CURRENT, slot & ~0x3UL, |
185 | if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { | 123 | &hpte_v_array[0], &hpte_v_array[1], |
186 | spin_unlock_irqrestore(&ps3_bolttab_lock, flags); | 124 | &hpte_v_array[2], &hpte_v_array[3], |
187 | 125 | &hpte_rs); | |
188 | /* ps3_hpte_insert() will be used to update PTE */ | ||
189 | return -1; | ||
190 | } | ||
191 | |||
192 | result = lv1_write_htab_entry(0, slot, 0, 0); | ||
193 | 126 | ||
194 | if (result) { | 127 | if (result) { |
195 | DBG("%s: va=%lx slot=%lx psize=%d result = %ld (0x%lx)\n", | 128 | pr_info("%s: res=%d read va=%lx slot=%lx psize=%d\n", |
196 | __func__, va, slot, psize, result, result); | 129 | __func__, result, va, slot, psize); |
197 | BUG(); | 130 | BUG(); |
198 | } | 131 | } |
199 | 132 | ||
200 | pteg = slot / HPTES_PER_GROUP; | 133 | hpte_v = hpte_v_array[slot % 4]; |
201 | bit = slot % HPTES_PER_GROUP; | ||
202 | inusetab[pteg] &= ~(0x80 >> bit); | ||
203 | 134 | ||
204 | spin_unlock_irqrestore(&ps3_bolttab_lock, flags); | 135 | /* |
136 | * As lv1_read_htab_entries() does not give us the RPN, we can | ||
137 | * not synthesize the new hpte_r value here, and therefore can | ||
138 | * not update the hpte with lv1_insert_htab_entry(), so we | ||
139 | * insted invalidate it and ask the caller to update it via | ||
140 | * ps3_hpte_insert() by returning a -1 value. | ||
141 | */ | ||
142 | if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { | ||
143 | /* not found */ | ||
144 | ret = -1; | ||
145 | } else { | ||
146 | /* entry found, just invalidate it */ | ||
147 | result = lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, | ||
148 | slot, 0, 0); | ||
149 | ret = -1; | ||
150 | } | ||
205 | 151 | ||
206 | /* ps3_hpte_insert() will be used to update PTE */ | 152 | spin_unlock_irqrestore(&ps3_htab_lock, flags); |
207 | return -1; | 153 | return ret; |
208 | } | 154 | } |
209 | 155 | ||
210 | static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | 156 | static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, |
@@ -217,45 +163,35 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long va, | |||
217 | int psize, int ssize, int local) | 163 | int psize, int ssize, int local) |
218 | { | 164 | { |
219 | unsigned long flags; | 165 | unsigned long flags; |
220 | unsigned long result; | 166 | int result; |
221 | unsigned long pteg, bit; | 167 | |
168 | spin_lock_irqsave(&ps3_htab_lock, flags); | ||
222 | 169 | ||
223 | spin_lock_irqsave(&ps3_bolttab_lock, flags); | 170 | result = lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, slot, 0, 0); |
224 | result = lv1_write_htab_entry(0, slot, 0, 0); | ||
225 | 171 | ||
226 | if (result) { | 172 | if (result) { |
227 | DBG("%s: va=%lx slot=%lx psize=%d result = %ld (0x%lx)\n", | 173 | pr_info("%s: res=%d va=%lx slot=%lx psize=%d\n", |
228 | __func__, va, slot, psize, result, result); | 174 | __func__, result, va, slot, psize); |
229 | BUG(); | 175 | BUG(); |
230 | } | 176 | } |
231 | 177 | ||
232 | pteg = slot / HPTES_PER_GROUP; | 178 | spin_unlock_irqrestore(&ps3_htab_lock, flags); |
233 | bit = slot % HPTES_PER_GROUP; | ||
234 | inusetab[pteg] &= ~(0x80 >> bit); | ||
235 | spin_unlock_irqrestore(&ps3_bolttab_lock, flags); | ||
236 | } | 179 | } |
237 | 180 | ||
238 | static void ps3_hpte_clear(void) | 181 | static void ps3_hpte_clear(void) |
239 | { | 182 | { |
240 | int result; | 183 | unsigned long hpte_count = (1UL << ppc64_pft_size) >> 4; |
241 | 184 | u64 i; | |
242 | DBG(" -> %s:%d\n", __func__, __LINE__); | ||
243 | 185 | ||
244 | result = lv1_unmap_htab(htab_addr); | 186 | for (i = 0; i < hpte_count; i++) |
245 | BUG_ON(result); | 187 | lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, i, 0, 0); |
246 | 188 | ||
247 | ps3_mm_shutdown(); | 189 | ps3_mm_shutdown(); |
248 | ps3_mm_vas_destroy(); | 190 | ps3_mm_vas_destroy(); |
249 | |||
250 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
251 | } | 191 | } |
252 | 192 | ||
253 | void __init ps3_hpte_init(unsigned long htab_size) | 193 | void __init ps3_hpte_init(unsigned long htab_size) |
254 | { | 194 | { |
255 | long bitmap_size; | ||
256 | |||
257 | DBG(" -> %s:%d\n", __func__, __LINE__); | ||
258 | |||
259 | ppc_md.hpte_invalidate = ps3_hpte_invalidate; | 195 | ppc_md.hpte_invalidate = ps3_hpte_invalidate; |
260 | ppc_md.hpte_updatepp = ps3_hpte_updatepp; | 196 | ppc_md.hpte_updatepp = ps3_hpte_updatepp; |
261 | ppc_md.hpte_updateboltedpp = ps3_hpte_updateboltedpp; | 197 | ppc_md.hpte_updateboltedpp = ps3_hpte_updateboltedpp; |
@@ -264,28 +200,5 @@ void __init ps3_hpte_init(unsigned long htab_size) | |||
264 | ppc_md.hpte_clear_all = ps3_hpte_clear; | 200 | ppc_md.hpte_clear_all = ps3_hpte_clear; |
265 | 201 | ||
266 | ppc64_pft_size = __ilog2(htab_size); | 202 | ppc64_pft_size = __ilog2(htab_size); |
267 | |||
268 | bitmap_size = htab_size / sizeof(struct hash_pte) / 8; | ||
269 | |||
270 | bolttab = __va(lmb_alloc(bitmap_size, 1)); | ||
271 | inusetab = __va(lmb_alloc(bitmap_size, 1)); | ||
272 | |||
273 | memset(bolttab, 0, bitmap_size); | ||
274 | memset(inusetab, 0, bitmap_size); | ||
275 | |||
276 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
277 | } | 203 | } |
278 | 204 | ||
279 | void __init ps3_map_htab(void) | ||
280 | { | ||
281 | long result; | ||
282 | unsigned long htab_size = (1UL << ppc64_pft_size); | ||
283 | |||
284 | result = lv1_map_htab(0, &htab_addr); | ||
285 | |||
286 | htab = (__force struct hash_pte *)ioremap_flags(htab_addr, htab_size, | ||
287 | pgprot_val(PAGE_READONLY_X)); | ||
288 | |||
289 | DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__, | ||
290 | htab_addr, (unsigned long)htab); | ||
291 | } | ||
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index a413abbd4123..77bc330263c4 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c | |||
@@ -201,7 +201,6 @@ static void __init ps3_setup_arch(void) | |||
201 | ps3_firmware_version.rev); | 201 | ps3_firmware_version.rev); |
202 | 202 | ||
203 | ps3_spu_set_platform(); | 203 | ps3_spu_set_platform(); |
204 | ps3_map_htab(); | ||
205 | 204 | ||
206 | #ifdef CONFIG_SMP | 205 | #ifdef CONFIG_SMP |
207 | smp_init_ps3(); | 206 | smp_init_ps3(); |
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c index d135cef9ed6a..ccae3d446b98 100644 --- a/arch/powerpc/platforms/ps3/spu.c +++ b/arch/powerpc/platforms/ps3/spu.c | |||
@@ -186,14 +186,24 @@ static void spu_unmap(struct spu *spu) | |||
186 | iounmap(spu_pdata(spu)->shadow); | 186 | iounmap(spu_pdata(spu)->shadow); |
187 | } | 187 | } |
188 | 188 | ||
189 | /** | ||
190 | * setup_areas - Map the spu regions into the address space. | ||
191 | * | ||
192 | * The current HV requires the spu shadow regs to be mapped with the | ||
193 | * PTE page protection bits set as read-only (PP=3). This implementation | ||
194 | * uses the low level __ioremap() to bypass the page protection settings | ||
195 | * inforced by ioremap_flags() to get the needed PTE bits set for the | ||
196 | * shadow regs. | ||
197 | */ | ||
198 | |||
189 | static int __init setup_areas(struct spu *spu) | 199 | static int __init setup_areas(struct spu *spu) |
190 | { | 200 | { |
191 | struct table {char* name; unsigned long addr; unsigned long size;}; | 201 | struct table {char* name; unsigned long addr; unsigned long size;}; |
202 | static const unsigned long shadow_flags = _PAGE_NO_CACHE | 3; | ||
192 | 203 | ||
193 | spu_pdata(spu)->shadow = ioremap_flags(spu_pdata(spu)->shadow_addr, | 204 | spu_pdata(spu)->shadow = __ioremap(spu_pdata(spu)->shadow_addr, |
194 | sizeof(struct spe_shadow), | 205 | sizeof(struct spe_shadow), |
195 | pgprot_val(PAGE_READONLY) | | 206 | shadow_flags); |
196 | _PAGE_NO_CACHE); | ||
197 | if (!spu_pdata(spu)->shadow) { | 207 | if (!spu_pdata(spu)->shadow) { |
198 | pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); | 208 | pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); |
199 | goto fail_ioremap; | 209 | goto fail_ioremap; |
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index a437267c6bf8..d967c1893ab5 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define _PSERIES_PLPAR_WRAPPERS_H | 2 | #define _PSERIES_PLPAR_WRAPPERS_H |
3 | 3 | ||
4 | #include <asm/hvcall.h> | 4 | #include <asm/hvcall.h> |
5 | #include <asm/page.h> | ||
5 | 6 | ||
6 | static inline long poll_pending(void) | 7 | static inline long poll_pending(void) |
7 | { | 8 | { |
@@ -44,12 +45,34 @@ static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa) | |||
44 | 45 | ||
45 | static inline long plpar_page_set_loaned(unsigned long vpa) | 46 | static inline long plpar_page_set_loaned(unsigned long vpa) |
46 | { | 47 | { |
47 | return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa, 0); | 48 | unsigned long cmo_page_sz = cmo_get_page_size(); |
49 | long rc = 0; | ||
50 | int i; | ||
51 | |||
52 | for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz) | ||
53 | rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa + i, 0); | ||
54 | |||
55 | for (i -= cmo_page_sz; rc && i != 0; i -= cmo_page_sz) | ||
56 | plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, | ||
57 | vpa + i - cmo_page_sz, 0); | ||
58 | |||
59 | return rc; | ||
48 | } | 60 | } |
49 | 61 | ||
50 | static inline long plpar_page_set_active(unsigned long vpa) | 62 | static inline long plpar_page_set_active(unsigned long vpa) |
51 | { | 63 | { |
52 | return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa, 0); | 64 | unsigned long cmo_page_sz = cmo_get_page_size(); |
65 | long rc = 0; | ||
66 | int i; | ||
67 | |||
68 | for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz) | ||
69 | rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa + i, 0); | ||
70 | |||
71 | for (i -= cmo_page_sz; rc && i != 0; i -= cmo_page_sz) | ||
72 | plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, | ||
73 | vpa + i - cmo_page_sz, 0); | ||
74 | |||
75 | return rc; | ||
53 | } | 76 | } |
54 | 77 | ||
55 | extern void vpa_init(int cpu); | 78 | extern void vpa_init(int cpu); |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 063a0d2fba30..7b01d67b4e48 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -68,6 +68,10 @@ | |||
68 | #include "plpar_wrappers.h" | 68 | #include "plpar_wrappers.h" |
69 | #include "pseries.h" | 69 | #include "pseries.h" |
70 | 70 | ||
71 | int CMO_PrPSP = -1; | ||
72 | int CMO_SecPSP = -1; | ||
73 | unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT); | ||
74 | EXPORT_SYMBOL(CMO_PageSize); | ||
71 | 75 | ||
72 | int fwnmi_active; /* TRUE if an FWNMI handler is present */ | 76 | int fwnmi_active; /* TRUE if an FWNMI handler is present */ |
73 | 77 | ||
@@ -325,8 +329,7 @@ void pSeries_cmo_feature_init(void) | |||
325 | { | 329 | { |
326 | char *ptr, *key, *value, *end; | 330 | char *ptr, *key, *value, *end; |
327 | int call_status; | 331 | int call_status; |
328 | int PrPSP = -1; | 332 | int page_order = IOMMU_PAGE_SHIFT; |
329 | int SecPSP = -1; | ||
330 | 333 | ||
331 | pr_debug(" -> fw_cmo_feature_init()\n"); | 334 | pr_debug(" -> fw_cmo_feature_init()\n"); |
332 | spin_lock(&rtas_data_buf_lock); | 335 | spin_lock(&rtas_data_buf_lock); |
@@ -365,21 +368,31 @@ void pSeries_cmo_feature_init(void) | |||
365 | break; | 368 | break; |
366 | } | 369 | } |
367 | 370 | ||
368 | if (0 == strcmp(key, "PrPSP")) | 371 | if (0 == strcmp(key, "CMOPageSize")) |
369 | PrPSP = simple_strtol(value, NULL, 10); | 372 | page_order = simple_strtol(value, NULL, 10); |
373 | else if (0 == strcmp(key, "PrPSP")) | ||
374 | CMO_PrPSP = simple_strtol(value, NULL, 10); | ||
370 | else if (0 == strcmp(key, "SecPSP")) | 375 | else if (0 == strcmp(key, "SecPSP")) |
371 | SecPSP = simple_strtol(value, NULL, 10); | 376 | CMO_SecPSP = simple_strtol(value, NULL, 10); |
372 | value = key = ptr + 1; | 377 | value = key = ptr + 1; |
373 | } | 378 | } |
374 | ptr++; | 379 | ptr++; |
375 | } | 380 | } |
376 | 381 | ||
377 | if (PrPSP != -1 || SecPSP != -1) { | 382 | /* Page size is returned as the power of 2 of the page size, |
383 | * convert to the page size in bytes before returning | ||
384 | */ | ||
385 | CMO_PageSize = 1 << page_order; | ||
386 | pr_debug("CMO_PageSize = %lu\n", CMO_PageSize); | ||
387 | |||
388 | if (CMO_PrPSP != -1 || CMO_SecPSP != -1) { | ||
378 | pr_info("CMO enabled\n"); | 389 | pr_info("CMO enabled\n"); |
379 | pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP); | 390 | pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", CMO_PrPSP, |
391 | CMO_SecPSP); | ||
380 | powerpc_firmware_features |= FW_FEATURE_CMO; | 392 | powerpc_firmware_features |= FW_FEATURE_CMO; |
381 | } else | 393 | } else |
382 | pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP); | 394 | pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", CMO_PrPSP, |
395 | CMO_SecPSP); | ||
383 | spin_unlock(&rtas_data_buf_lock); | 396 | spin_unlock(&rtas_data_buf_lock); |
384 | pr_debug(" <- fw_cmo_feature_init()\n"); | 397 | pr_debug(" <- fw_cmo_feature_init()\n"); |
385 | } | 398 | } |