diff options
author | Paul Mackerras <paulus@samba.org> | 2007-10-11 06:37:10 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-10-12 00:05:17 -0400 |
commit | 1189be6508d45183013ddb82b18f4934193de274 (patch) | |
tree | 58924481b4de56699e4a884dce8dc601e71cf7d1 /arch/powerpc/platforms | |
parent | 287e5d6fcccfa38b953cebe307e1ddfd32363355 (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.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/switch.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/htab.c | 34 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/htab.c | 13 | ||||
-rw-r--r-- | arch/powerpc/platforms/ps3/htab.c | 14 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 89 |
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) | |||
90 | static long beat_lpar_hpte_insert(unsigned long hpte_group, | 90 | static 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) | |||
184 | static long beat_lpar_hpte_updatepp(unsigned long slot, | 185 | static 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 | ||
252 | static void beat_lpar_hpte_updateboltedpp(unsigned long newpp, | 253 | static 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 | ||
272 | static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | 273 | static 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) | |||
310 | static long beat_lpar_hpte_insert_v3(unsigned long hpte_group, | 311 | static 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, | |||
363 | static long beat_lpar_hpte_updatepp_v3(unsigned long slot, | 365 | static 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 | ||
393 | static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va, | 395 | static 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 | */ |
144 | static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, | 145 | static 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 | */ |
207 | static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | 208 | static 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 | ||
224 | static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va, | 225 | static 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 | ||
62 | static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, | 62 | static 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 | ||
169 | static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, | 171 | static 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 | ||
207 | static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | 209 | static 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 | ||
213 | static void ps3_hpte_invalidate(unsigned long slot, unsigned long va, | 215 | static 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) | |||
284 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | 284 | static 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 | */ | ||
399 | static 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) | |||
400 | static long pSeries_lpar_hpte_updatepp(unsigned long slot, | 416 | static 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 | ||
447 | static long pSeries_lpar_hpte_find(unsigned long va, int psize) | 463 | static 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 | ||
478 | static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, | 487 | static 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 | ||
496 | static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | 505 | static 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, |