aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2007-10-11 06:37:10 -0400
committerPaul Mackerras <paulus@samba.org>2007-10-12 00:05:17 -0400
commit1189be6508d45183013ddb82b18f4934193de274 (patch)
tree58924481b4de56699e4a884dce8dc601e71cf7d1 /arch/powerpc/platforms
parent287e5d6fcccfa38b953cebe307e1ddfd32363355 (diff)
[POWERPC] Use 1TB segments
This makes the kernel use 1TB segments for all kernel mappings and for user addresses of 1TB and above, on machines which support them (currently POWER5+, POWER6 and PA6T). We detect that the machine supports 1TB segments by looking at the ibm,processor-segment-sizes property in the device tree. We don't currently use 1TB segments for user addresses < 1T, since that would effectively prevent 32-bit processes from using huge pages unless we also had a way to revert to using 256MB segments. That would be possible but would involve extra complications (such as keeping track of which segment size was used when HPTEs were inserted) and is not addressed here. Parts of this patch were originally written by Ben Herrenschmidt. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c6
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c2
-rw-r--r--arch/powerpc/platforms/celleb/htab.c34
-rw-r--r--arch/powerpc/platforms/iseries/htab.c13
-rw-r--r--arch/powerpc/platforms/ps3/htab.c14
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c89
6 files changed, 86 insertions, 72 deletions
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index b5a21177bb32..c83c3e3f5178 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -168,7 +168,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
168#else 168#else
169 psize = mm->context.user_psize; 169 psize = mm->context.user_psize;
170#endif 170#endif
171 vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | 171 vsid = (get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
172 SLB_VSID_USER; 172 SLB_VSID_USER;
173 break; 173 break;
174 case VMALLOC_REGION_ID: 174 case VMALLOC_REGION_ID:
@@ -176,12 +176,12 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
176 psize = mmu_vmalloc_psize; 176 psize = mmu_vmalloc_psize;
177 else 177 else
178 psize = mmu_io_psize; 178 psize = mmu_io_psize;
179 vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | 179 vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
180 SLB_VSID_KERNEL; 180 SLB_VSID_KERNEL;
181 break; 181 break;
182 case KERNEL_REGION_ID: 182 case KERNEL_REGION_ID:
183 psize = mmu_linear_psize; 183 psize = mmu_linear_psize;
184 vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | 184 vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
185 SLB_VSID_KERNEL; 185 SLB_VSID_KERNEL;
186 break; 186 break;
187 default: 187 default:
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index de7e5ee451d2..3d64c81cc6e2 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -699,7 +699,7 @@ static inline void get_kernel_slb(u64 ea, u64 slb[2])
699 llp = mmu_psize_defs[mmu_linear_psize].sllp; 699 llp = mmu_psize_defs[mmu_linear_psize].sllp;
700 else 700 else
701 llp = mmu_psize_defs[mmu_virtual_psize].sllp; 701 llp = mmu_psize_defs[mmu_virtual_psize].sllp;
702 slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | 702 slb[0] = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
703 SLB_VSID_KERNEL | llp; 703 SLB_VSID_KERNEL | llp;
704 slb[1] = (ea & ESID_MASK) | SLB_ESID_V; 704 slb[1] = (ea & ESID_MASK) | SLB_ESID_V;
705} 705}
diff --git a/arch/powerpc/platforms/celleb/htab.c b/arch/powerpc/platforms/celleb/htab.c
index 5e75c77ea8f3..fbf27c74ebda 100644
--- a/arch/powerpc/platforms/celleb/htab.c
+++ b/arch/powerpc/platforms/celleb/htab.c
@@ -90,7 +90,7 @@ static inline unsigned int beat_read_mask(unsigned hpte_group)
90static long beat_lpar_hpte_insert(unsigned long hpte_group, 90static long beat_lpar_hpte_insert(unsigned long hpte_group,
91 unsigned long va, unsigned long pa, 91 unsigned long va, unsigned long pa,
92 unsigned long rflags, unsigned long vflags, 92 unsigned long rflags, unsigned long vflags,
93 int psize) 93 int psize, int ssize)
94{ 94{
95 unsigned long lpar_rc; 95 unsigned long lpar_rc;
96 unsigned long slot; 96 unsigned long slot;
@@ -105,7 +105,8 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group,
105 "rflags=%lx, vflags=%lx, psize=%d)\n", 105 "rflags=%lx, vflags=%lx, psize=%d)\n",
106 hpte_group, va, pa, rflags, vflags, psize); 106 hpte_group, va, pa, rflags, vflags, psize);
107 107
108 hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; 108 hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
109 vflags | HPTE_V_VALID;
109 hpte_r = hpte_encode_r(pa, psize) | rflags; 110 hpte_r = hpte_encode_r(pa, psize) | rflags;
110 111
111 if (!(vflags & HPTE_V_BOLTED)) 112 if (!(vflags & HPTE_V_BOLTED))
@@ -184,12 +185,12 @@ static void beat_lpar_hptab_clear(void)
184static long beat_lpar_hpte_updatepp(unsigned long slot, 185static long beat_lpar_hpte_updatepp(unsigned long slot,
185 unsigned long newpp, 186 unsigned long newpp,
186 unsigned long va, 187 unsigned long va,
187 int psize, int local) 188 int psize, int ssize, int local)
188{ 189{
189 unsigned long lpar_rc; 190 unsigned long lpar_rc;
190 unsigned long dummy0, dummy1, want_v; 191 unsigned long dummy0, dummy1, want_v;
191 192
192 want_v = hpte_encode_v(va, psize); 193 want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
193 194
194 DBG_LOW(" update: " 195 DBG_LOW(" update: "
195 "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ", 196 "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
@@ -225,8 +226,8 @@ static long beat_lpar_hpte_find(unsigned long va, int psize)
225 long slot; 226 long slot;
226 unsigned long want_v, hpte_v; 227 unsigned long want_v, hpte_v;
227 228
228 hash = hpt_hash(va, mmu_psize_defs[psize].shift); 229 hash = hpt_hash(va, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M);
229 want_v = hpte_encode_v(va, psize); 230 want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
230 231
231 for (j = 0; j < 2; j++) { 232 for (j = 0; j < 2; j++) {
232 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; 233 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
@@ -251,11 +252,11 @@ static long beat_lpar_hpte_find(unsigned long va, int psize)
251 252
252static void beat_lpar_hpte_updateboltedpp(unsigned long newpp, 253static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
253 unsigned long ea, 254 unsigned long ea,
254 int psize) 255 int psize, int ssize)
255{ 256{
256 unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1; 257 unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1;
257 258
258 vsid = get_kernel_vsid(ea); 259 vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
259 va = (vsid << 28) | (ea & 0x0fffffff); 260 va = (vsid << 28) | (ea & 0x0fffffff);
260 261
261 spin_lock(&beat_htab_lock); 262 spin_lock(&beat_htab_lock);
@@ -270,7 +271,7 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
270} 271}
271 272
272static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va, 273static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
273 int psize, int local) 274 int psize, int ssize, int local)
274{ 275{
275 unsigned long want_v; 276 unsigned long want_v;
276 unsigned long lpar_rc; 277 unsigned long lpar_rc;
@@ -279,7 +280,7 @@ static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
279 280
280 DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", 281 DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
281 slot, va, psize, local); 282 slot, va, psize, local);
282 want_v = hpte_encode_v(va, psize); 283 want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
283 284
284 spin_lock_irqsave(&beat_htab_lock, flags); 285 spin_lock_irqsave(&beat_htab_lock, flags);
285 dummy1 = beat_lpar_hpte_getword0(slot); 286 dummy1 = beat_lpar_hpte_getword0(slot);
@@ -310,7 +311,7 @@ void __init hpte_init_beat(void)
310static long beat_lpar_hpte_insert_v3(unsigned long hpte_group, 311static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
311 unsigned long va, unsigned long pa, 312 unsigned long va, unsigned long pa,
312 unsigned long rflags, unsigned long vflags, 313 unsigned long rflags, unsigned long vflags,
313 int psize) 314 int psize, int ssize)
314{ 315{
315 unsigned long lpar_rc; 316 unsigned long lpar_rc;
316 unsigned long slot; 317 unsigned long slot;
@@ -325,7 +326,8 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
325 "rflags=%lx, vflags=%lx, psize=%d)\n", 326 "rflags=%lx, vflags=%lx, psize=%d)\n",
326 hpte_group, va, pa, rflags, vflags, psize); 327 hpte_group, va, pa, rflags, vflags, psize);
327 328
328 hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; 329 hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
330 vflags | HPTE_V_VALID;
329 hpte_r = hpte_encode_r(pa, psize) | rflags; 331 hpte_r = hpte_encode_r(pa, psize) | rflags;
330 332
331 if (!(vflags & HPTE_V_BOLTED)) 333 if (!(vflags & HPTE_V_BOLTED))
@@ -363,13 +365,13 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
363static long beat_lpar_hpte_updatepp_v3(unsigned long slot, 365static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
364 unsigned long newpp, 366 unsigned long newpp,
365 unsigned long va, 367 unsigned long va,
366 int psize, int local) 368 int psize, int ssize, int local)
367{ 369{
368 unsigned long lpar_rc; 370 unsigned long lpar_rc;
369 unsigned long want_v; 371 unsigned long want_v;
370 unsigned long pss; 372 unsigned long pss;
371 373
372 want_v = hpte_encode_v(va, psize); 374 want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
373 pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc; 375 pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
374 376
375 DBG_LOW(" update: " 377 DBG_LOW(" update: "
@@ -391,7 +393,7 @@ static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
391} 393}
392 394
393static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va, 395static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
394 int psize, int local) 396 int psize, int ssize, int local)
395{ 397{
396 unsigned long want_v; 398 unsigned long want_v;
397 unsigned long lpar_rc; 399 unsigned long lpar_rc;
@@ -399,7 +401,7 @@ static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
399 401
400 DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", 402 DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
401 slot, va, psize, local); 403 slot, va, psize, local);
402 want_v = hpte_encode_v(va, psize); 404 want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
403 pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc; 405 pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
404 406
405 lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss); 407 lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss);
diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c
index b4e2c7a038e1..15a7097e5dd7 100644
--- a/arch/powerpc/platforms/iseries/htab.c
+++ b/arch/powerpc/platforms/iseries/htab.c
@@ -86,7 +86,8 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
86 } 86 }
87 87
88 88
89 lhpte.v = hpte_encode_v(va, MMU_PAGE_4K) | vflags | HPTE_V_VALID; 89 lhpte.v = hpte_encode_v(va, MMU_PAGE_4K, MMU_SEGSIZE_256M) |
90 vflags | HPTE_V_VALID;
90 lhpte.r = hpte_encode_r(phys_to_abs(pa), MMU_PAGE_4K) | rflags; 91 lhpte.r = hpte_encode_r(phys_to_abs(pa), MMU_PAGE_4K) | rflags;
91 92
92 /* Now fill in the actual HPTE */ 93 /* Now fill in the actual HPTE */
@@ -142,7 +143,7 @@ static long iSeries_hpte_remove(unsigned long hpte_group)
142 * bits 61..63 : PP2,PP1,PP0 143 * bits 61..63 : PP2,PP1,PP0
143 */ 144 */
144static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, 145static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
145 unsigned long va, int psize, int local) 146 unsigned long va, int psize, int ssize, int local)
146{ 147{
147 struct hash_pte hpte; 148 struct hash_pte hpte;
148 unsigned long want_v; 149 unsigned long want_v;
@@ -150,7 +151,7 @@ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
150 iSeries_hlock(slot); 151 iSeries_hlock(slot);
151 152
152 HvCallHpt_get(&hpte, slot); 153 HvCallHpt_get(&hpte, slot);
153 want_v = hpte_encode_v(va, MMU_PAGE_4K); 154 want_v = hpte_encode_v(va, MMU_PAGE_4K, MMU_SEGSIZE_256M);
154 155
155 if (HPTE_V_COMPARE(hpte.v, want_v) && (hpte.v & HPTE_V_VALID)) { 156 if (HPTE_V_COMPARE(hpte.v, want_v) && (hpte.v & HPTE_V_VALID)) {
156 /* 157 /*
@@ -205,14 +206,14 @@ static long iSeries_hpte_find(unsigned long vpn)
205 * No need to lock here because we should be the only user. 206 * No need to lock here because we should be the only user.
206 */ 207 */
207static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, 208static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
208 int psize) 209 int psize, int ssize)
209{ 210{
210 unsigned long vsid,va,vpn; 211 unsigned long vsid,va,vpn;
211 long slot; 212 long slot;
212 213
213 BUG_ON(psize != MMU_PAGE_4K); 214 BUG_ON(psize != MMU_PAGE_4K);
214 215
215 vsid = get_kernel_vsid(ea); 216 vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
216 va = (vsid << 28) | (ea & 0x0fffffff); 217 va = (vsid << 28) | (ea & 0x0fffffff);
217 vpn = va >> HW_PAGE_SHIFT; 218 vpn = va >> HW_PAGE_SHIFT;
218 slot = iSeries_hpte_find(vpn); 219 slot = iSeries_hpte_find(vpn);
@@ -222,7 +223,7 @@ static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
222} 223}
223 224
224static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va, 225static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va,
225 int psize, int local) 226 int psize, int ssize, int local)
226{ 227{
227 unsigned long hpte_v; 228 unsigned long hpte_v;
228 unsigned long avpn = va >> 23; 229 unsigned long avpn = va >> 23;
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index 5d2e176a1b18..7382f195c4f8 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -60,7 +60,8 @@ static void _debug_dump_hpte(unsigned long pa, unsigned long va,
60} 60}
61 61
62static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, 62static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
63 unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) 63 unsigned long pa, unsigned long rflags, unsigned long vflags,
64 int psize, int ssize)
64{ 65{
65 unsigned long slot; 66 unsigned long slot;
66 struct hash_pte lhpte; 67 struct hash_pte lhpte;
@@ -72,7 +73,8 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
72 73
73 vflags &= ~HPTE_V_SECONDARY; /* this bit is ignored */ 74 vflags &= ~HPTE_V_SECONDARY; /* this bit is ignored */
74 75
75 lhpte.v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; 76 lhpte.v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
77 vflags | HPTE_V_VALID;
76 lhpte.r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags; 78 lhpte.r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags;
77 79
78 p_pteg = hpte_group / HPTES_PER_GROUP; 80 p_pteg = hpte_group / HPTES_PER_GROUP;
@@ -167,14 +169,14 @@ static long ps3_hpte_remove(unsigned long hpte_group)
167} 169}
168 170
169static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, 171static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
170 unsigned long va, int psize, int local) 172 unsigned long va, int psize, int ssize, int local)
171{ 173{
172 unsigned long flags; 174 unsigned long flags;
173 unsigned long result; 175 unsigned long result;
174 unsigned long pteg, bit; 176 unsigned long pteg, bit;
175 unsigned long hpte_v, want_v; 177 unsigned long hpte_v, want_v;
176 178
177 want_v = hpte_encode_v(va, psize); 179 want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
178 180
179 spin_lock_irqsave(&ps3_bolttab_lock, flags); 181 spin_lock_irqsave(&ps3_bolttab_lock, flags);
180 182
@@ -205,13 +207,13 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
205} 207}
206 208
207static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, 209static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
208 int psize) 210 int psize, int ssize)
209{ 211{
210 panic("ps3_hpte_updateboltedpp() not implemented"); 212 panic("ps3_hpte_updateboltedpp() not implemented");
211} 213}
212 214
213static void ps3_hpte_invalidate(unsigned long slot, unsigned long va, 215static void ps3_hpte_invalidate(unsigned long slot, unsigned long va,
214 int psize, int local) 216 int psize, int ssize, int local)
215{ 217{
216 unsigned long flags; 218 unsigned long flags;
217 unsigned long result; 219 unsigned long result;
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index ea327ca345c6..9a455d46379d 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -284,7 +284,7 @@ void vpa_init(int cpu)
284static long pSeries_lpar_hpte_insert(unsigned long hpte_group, 284static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
285 unsigned long va, unsigned long pa, 285 unsigned long va, unsigned long pa,
286 unsigned long rflags, unsigned long vflags, 286 unsigned long rflags, unsigned long vflags,
287 int psize) 287 int psize, int ssize)
288{ 288{
289 unsigned long lpar_rc; 289 unsigned long lpar_rc;
290 unsigned long flags; 290 unsigned long flags;
@@ -296,7 +296,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
296 "rflags=%lx, vflags=%lx, psize=%d)\n", 296 "rflags=%lx, vflags=%lx, psize=%d)\n",
297 hpte_group, va, pa, rflags, vflags, psize); 297 hpte_group, va, pa, rflags, vflags, psize);
298 298
299 hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; 299 hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
300 hpte_r = hpte_encode_r(pa, psize) | rflags; 300 hpte_r = hpte_encode_r(pa, psize) | rflags;
301 301
302 if (!(vflags & HPTE_V_BOLTED)) 302 if (!(vflags & HPTE_V_BOLTED))
@@ -392,6 +392,22 @@ static void pSeries_lpar_hptab_clear(void)
392} 392}
393 393
394/* 394/*
395 * This computes the AVPN and B fields of the first dword of a HPTE,
396 * for use when we want to match an existing PTE. The bottom 7 bits
397 * of the returned value are zero.
398 */
399static inline unsigned long hpte_encode_avpn(unsigned long va, int psize,
400 int ssize)
401{
402 unsigned long v;
403
404 v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
405 v <<= HPTE_V_AVPN_SHIFT;
406 v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
407 return v;
408}
409
410/*
395 * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and 411 * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
396 * the low 3 bits of flags happen to line up. So no transform is needed. 412 * the low 3 bits of flags happen to line up. So no transform is needed.
397 * We can probably optimize here and assume the high bits of newpp are 413 * We can probably optimize here and assume the high bits of newpp are
@@ -400,18 +416,18 @@ static void pSeries_lpar_hptab_clear(void)
400static long pSeries_lpar_hpte_updatepp(unsigned long slot, 416static long pSeries_lpar_hpte_updatepp(unsigned long slot,
401 unsigned long newpp, 417 unsigned long newpp,
402 unsigned long va, 418 unsigned long va,
403 int psize, int local) 419 int psize, int ssize, int local)
404{ 420{
405 unsigned long lpar_rc; 421 unsigned long lpar_rc;
406 unsigned long flags = (newpp & 7) | H_AVPN; 422 unsigned long flags = (newpp & 7) | H_AVPN;
407 unsigned long want_v; 423 unsigned long want_v;
408 424
409 want_v = hpte_encode_v(va, psize); 425 want_v = hpte_encode_avpn(va, psize, ssize);
410 426
411 DBG_LOW(" update: avpnv=%016lx, hash=%016lx, f=%x, psize: %d ... ", 427 DBG_LOW(" update: avpnv=%016lx, hash=%016lx, f=%x, psize: %d ... ",
412 want_v & HPTE_V_AVPN, slot, flags, psize); 428 want_v, slot, flags, psize);
413 429
414 lpar_rc = plpar_pte_protect(flags, slot, want_v & HPTE_V_AVPN); 430 lpar_rc = plpar_pte_protect(flags, slot, want_v);
415 431
416 if (lpar_rc == H_NOT_FOUND) { 432 if (lpar_rc == H_NOT_FOUND) {
417 DBG_LOW("not found !\n"); 433 DBG_LOW("not found !\n");
@@ -444,32 +460,25 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
444 return dword0; 460 return dword0;
445} 461}
446 462
447static long pSeries_lpar_hpte_find(unsigned long va, int psize) 463static long pSeries_lpar_hpte_find(unsigned long va, int psize, int ssize)
448{ 464{
449 unsigned long hash; 465 unsigned long hash;
450 unsigned long i, j; 466 unsigned long i;
451 long slot; 467 long slot;
452 unsigned long want_v, hpte_v; 468 unsigned long want_v, hpte_v;
453 469
454 hash = hpt_hash(va, mmu_psize_defs[psize].shift); 470 hash = hpt_hash(va, mmu_psize_defs[psize].shift, ssize);
455 want_v = hpte_encode_v(va, psize); 471 want_v = hpte_encode_avpn(va, psize, ssize);
456 472
457 for (j = 0; j < 2; j++) { 473 /* Bolted entries are always in the primary group */
458 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; 474 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
459 for (i = 0; i < HPTES_PER_GROUP; i++) { 475 for (i = 0; i < HPTES_PER_GROUP; i++) {
460 hpte_v = pSeries_lpar_hpte_getword0(slot); 476 hpte_v = pSeries_lpar_hpte_getword0(slot);
461 477
462 if (HPTE_V_COMPARE(hpte_v, want_v) 478 if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID))
463 && (hpte_v & HPTE_V_VALID) 479 /* HPTE matches */
464 && (!!(hpte_v & HPTE_V_SECONDARY) == j)) { 480 return slot;
465 /* HPTE matches */ 481 ++slot;
466 if (j)
467 slot = -slot;
468 return slot;
469 }
470 ++slot;
471 }
472 hash = ~hash;
473 } 482 }
474 483
475 return -1; 484 return -1;
@@ -477,14 +486,14 @@ static long pSeries_lpar_hpte_find(unsigned long va, int psize)
477 486
478static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, 487static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
479 unsigned long ea, 488 unsigned long ea,
480 int psize) 489 int psize, int ssize)
481{ 490{
482 unsigned long lpar_rc, slot, vsid, va, flags; 491 unsigned long lpar_rc, slot, vsid, va, flags;
483 492
484 vsid = get_kernel_vsid(ea); 493 vsid = get_kernel_vsid(ea, ssize);
485 va = (vsid << 28) | (ea & 0x0fffffff); 494 va = hpt_va(ea, vsid, ssize);
486 495
487 slot = pSeries_lpar_hpte_find(va, psize); 496 slot = pSeries_lpar_hpte_find(va, psize, ssize);
488 BUG_ON(slot == -1); 497 BUG_ON(slot == -1);
489 498
490 flags = newpp & 7; 499 flags = newpp & 7;
@@ -494,7 +503,7 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
494} 503}
495 504
496static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, 505static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
497 int psize, int local) 506 int psize, int ssize, int local)
498{ 507{
499 unsigned long want_v; 508 unsigned long want_v;
500 unsigned long lpar_rc; 509 unsigned long lpar_rc;
@@ -503,9 +512,8 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
503 DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d", 512 DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d",
504 slot, va, psize, local); 513 slot, va, psize, local);
505 514
506 want_v = hpte_encode_v(va, psize); 515 want_v = hpte_encode_avpn(va, psize, ssize);
507 lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v & HPTE_V_AVPN, 516 lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
508 &dummy1, &dummy2);
509 if (lpar_rc == H_NOT_FOUND) 517 if (lpar_rc == H_NOT_FOUND)
510 return; 518 return;
511 519
@@ -533,18 +541,19 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
533 unsigned long va; 541 unsigned long va;
534 unsigned long hash, index, shift, hidx, slot; 542 unsigned long hash, index, shift, hidx, slot;
535 real_pte_t pte; 543 real_pte_t pte;
536 int psize; 544 int psize, ssize;
537 545
538 if (lock_tlbie) 546 if (lock_tlbie)
539 spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); 547 spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
540 548
541 psize = batch->psize; 549 psize = batch->psize;
550 ssize = batch->ssize;
542 pix = 0; 551 pix = 0;
543 for (i = 0; i < number; i++) { 552 for (i = 0; i < number; i++) {
544 va = batch->vaddr[i]; 553 va = batch->vaddr[i];
545 pte = batch->pte[i]; 554 pte = batch->pte[i];
546 pte_iterate_hashed_subpages(pte, psize, va, index, shift) { 555 pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
547 hash = hpt_hash(va, shift); 556 hash = hpt_hash(va, shift, ssize);
548 hidx = __rpte_to_hidx(pte, index); 557 hidx = __rpte_to_hidx(pte, index);
549 if (hidx & _PTEIDX_SECONDARY) 558 if (hidx & _PTEIDX_SECONDARY)
550 hash = ~hash; 559 hash = ~hash;
@@ -552,11 +561,11 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
552 slot += hidx & _PTEIDX_GROUP_IX; 561 slot += hidx & _PTEIDX_GROUP_IX;
553 if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) { 562 if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) {
554 pSeries_lpar_hpte_invalidate(slot, va, psize, 563 pSeries_lpar_hpte_invalidate(slot, va, psize,
555 local); 564 ssize, local);
556 } else { 565 } else {
557 param[pix] = HBR_REQUEST | HBR_AVPN | slot; 566 param[pix] = HBR_REQUEST | HBR_AVPN | slot;
558 param[pix+1] = hpte_encode_v(va, psize) & 567 param[pix+1] = hpte_encode_avpn(va, psize,
559 HPTE_V_AVPN; 568 ssize);
560 pix += 2; 569 pix += 2;
561 if (pix == 8) { 570 if (pix == 8) {
562 rc = plpar_hcall9(H_BULK_REMOVE, param, 571 rc = plpar_hcall9(H_BULK_REMOVE, param,