aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2013-09-22 22:04:36 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-10-11 01:48:26 -0400
commit12f04f2be80dd8d9da24534828f3ab3189ca5af2 (patch)
tree0cdc5e766e3c3406286f808721ccd4ab9b134a20 /arch/powerpc
parent32ee1e188eadd7c997837649a107fd1c50feef7a (diff)
powerpc: Book 3S MMU little endian support
Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/mmu-hash64.h4
-rw-r--r--arch/powerpc/mm/hash_native_64.c46
-rw-r--r--arch/powerpc/mm/hash_utils_64.c38
3 files changed, 46 insertions, 42 deletions
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index c4cf01197273..807014dde821 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -135,8 +135,8 @@ extern char initial_stab[];
135#ifndef __ASSEMBLY__ 135#ifndef __ASSEMBLY__
136 136
137struct hash_pte { 137struct hash_pte {
138 unsigned long v; 138 __be64 v;
139 unsigned long r; 139 __be64 r;
140}; 140};
141 141
142extern struct hash_pte *htab_address; 142extern struct hash_pte *htab_address;
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index c33d939120c9..3ea26c25590b 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -35,7 +35,11 @@
35#define DBG_LOW(fmt...) 35#define DBG_LOW(fmt...)
36#endif 36#endif
37 37
38#ifdef __BIG_ENDIAN__
38#define HPTE_LOCK_BIT 3 39#define HPTE_LOCK_BIT 3
40#else
41#define HPTE_LOCK_BIT (56+3)
42#endif
39 43
40DEFINE_RAW_SPINLOCK(native_tlbie_lock); 44DEFINE_RAW_SPINLOCK(native_tlbie_lock);
41 45
@@ -172,7 +176,7 @@ static inline void tlbie(unsigned long vpn, int psize, int apsize,
172 176
173static inline void native_lock_hpte(struct hash_pte *hptep) 177static inline void native_lock_hpte(struct hash_pte *hptep)
174{ 178{
175 unsigned long *word = &hptep->v; 179 unsigned long *word = (unsigned long *)&hptep->v;
176 180
177 while (1) { 181 while (1) {
178 if (!test_and_set_bit_lock(HPTE_LOCK_BIT, word)) 182 if (!test_and_set_bit_lock(HPTE_LOCK_BIT, word))
@@ -184,7 +188,7 @@ static inline void native_lock_hpte(struct hash_pte *hptep)
184 188
185static inline void native_unlock_hpte(struct hash_pte *hptep) 189static inline void native_unlock_hpte(struct hash_pte *hptep)
186{ 190{
187 unsigned long *word = &hptep->v; 191 unsigned long *word = (unsigned long *)&hptep->v;
188 192
189 clear_bit_unlock(HPTE_LOCK_BIT, word); 193 clear_bit_unlock(HPTE_LOCK_BIT, word);
190} 194}
@@ -204,10 +208,10 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
204 } 208 }
205 209
206 for (i = 0; i < HPTES_PER_GROUP; i++) { 210 for (i = 0; i < HPTES_PER_GROUP; i++) {
207 if (! (hptep->v & HPTE_V_VALID)) { 211 if (! (be64_to_cpu(hptep->v) & HPTE_V_VALID)) {
208 /* retry with lock held */ 212 /* retry with lock held */
209 native_lock_hpte(hptep); 213 native_lock_hpte(hptep);
210 if (! (hptep->v & HPTE_V_VALID)) 214 if (! (be64_to_cpu(hptep->v) & HPTE_V_VALID))
211 break; 215 break;
212 native_unlock_hpte(hptep); 216 native_unlock_hpte(hptep);
213 } 217 }
@@ -226,14 +230,14 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
226 i, hpte_v, hpte_r); 230 i, hpte_v, hpte_r);
227 } 231 }
228 232
229 hptep->r = hpte_r; 233 hptep->r = cpu_to_be64(hpte_r);
230 /* Guarantee the second dword is visible before the valid bit */ 234 /* Guarantee the second dword is visible before the valid bit */
231 eieio(); 235 eieio();
232 /* 236 /*
233 * Now set the first dword including the valid bit 237 * Now set the first dword including the valid bit
234 * NOTE: this also unlocks the hpte 238 * NOTE: this also unlocks the hpte
235 */ 239 */
236 hptep->v = hpte_v; 240 hptep->v = cpu_to_be64(hpte_v);
237 241
238 __asm__ __volatile__ ("ptesync" : : : "memory"); 242 __asm__ __volatile__ ("ptesync" : : : "memory");
239 243
@@ -254,12 +258,12 @@ static long native_hpte_remove(unsigned long hpte_group)
254 258
255 for (i = 0; i < HPTES_PER_GROUP; i++) { 259 for (i = 0; i < HPTES_PER_GROUP; i++) {
256 hptep = htab_address + hpte_group + slot_offset; 260 hptep = htab_address + hpte_group + slot_offset;
257 hpte_v = hptep->v; 261 hpte_v = be64_to_cpu(hptep->v);
258 262
259 if ((hpte_v & HPTE_V_VALID) && !(hpte_v & HPTE_V_BOLTED)) { 263 if ((hpte_v & HPTE_V_VALID) && !(hpte_v & HPTE_V_BOLTED)) {
260 /* retry with lock held */ 264 /* retry with lock held */
261 native_lock_hpte(hptep); 265 native_lock_hpte(hptep);
262 hpte_v = hptep->v; 266 hpte_v = be64_to_cpu(hptep->v);
263 if ((hpte_v & HPTE_V_VALID) 267 if ((hpte_v & HPTE_V_VALID)
264 && !(hpte_v & HPTE_V_BOLTED)) 268 && !(hpte_v & HPTE_V_BOLTED))
265 break; 269 break;
@@ -294,7 +298,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
294 298
295 native_lock_hpte(hptep); 299 native_lock_hpte(hptep);
296 300
297 hpte_v = hptep->v; 301 hpte_v = be64_to_cpu(hptep->v);
298 /* 302 /*
299 * We need to invalidate the TLB always because hpte_remove doesn't do 303 * We need to invalidate the TLB always because hpte_remove doesn't do
300 * a tlb invalidate. If a hash bucket gets full, we "evict" a more/less 304 * a tlb invalidate. If a hash bucket gets full, we "evict" a more/less
@@ -308,8 +312,8 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
308 } else { 312 } else {
309 DBG_LOW(" -> hit\n"); 313 DBG_LOW(" -> hit\n");
310 /* Update the HPTE */ 314 /* Update the HPTE */
311 hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | 315 hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & ~(HPTE_R_PP | HPTE_R_N)) |
312 (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); 316 (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)));
313 } 317 }
314 native_unlock_hpte(hptep); 318 native_unlock_hpte(hptep);
315 319
@@ -334,7 +338,7 @@ static long native_hpte_find(unsigned long vpn, int psize, int ssize)
334 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; 338 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
335 for (i = 0; i < HPTES_PER_GROUP; i++) { 339 for (i = 0; i < HPTES_PER_GROUP; i++) {
336 hptep = htab_address + slot; 340 hptep = htab_address + slot;
337 hpte_v = hptep->v; 341 hpte_v = be64_to_cpu(hptep->v);
338 342
339 if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID)) 343 if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID))
340 /* HPTE matches */ 344 /* HPTE matches */
@@ -369,8 +373,9 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
369 hptep = htab_address + slot; 373 hptep = htab_address + slot;
370 374
371 /* Update the HPTE */ 375 /* Update the HPTE */
372 hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | 376 hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) &
373 (newpp & (HPTE_R_PP | HPTE_R_N)); 377 ~(HPTE_R_PP | HPTE_R_N)) |
378 (newpp & (HPTE_R_PP | HPTE_R_N)));
374 /* 379 /*
375 * Ensure it is out of the tlb too. Bolted entries base and 380 * Ensure it is out of the tlb too. Bolted entries base and
376 * actual page size will be same. 381 * actual page size will be same.
@@ -392,7 +397,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long vpn,
392 397
393 want_v = hpte_encode_avpn(vpn, bpsize, ssize); 398 want_v = hpte_encode_avpn(vpn, bpsize, ssize);
394 native_lock_hpte(hptep); 399 native_lock_hpte(hptep);
395 hpte_v = hptep->v; 400 hpte_v = be64_to_cpu(hptep->v);
396 401
397 /* 402 /*
398 * We need to invalidate the TLB always because hpte_remove doesn't do 403 * We need to invalidate the TLB always because hpte_remove doesn't do
@@ -458,7 +463,7 @@ static void native_hugepage_invalidate(struct mm_struct *mm,
458 hptep = htab_address + slot; 463 hptep = htab_address + slot;
459 want_v = hpte_encode_avpn(vpn, psize, ssize); 464 want_v = hpte_encode_avpn(vpn, psize, ssize);
460 native_lock_hpte(hptep); 465 native_lock_hpte(hptep);
461 hpte_v = hptep->v; 466 hpte_v = be64_to_cpu(hptep->v);
462 467
463 /* Even if we miss, we need to invalidate the TLB */ 468 /* Even if we miss, we need to invalidate the TLB */
464 if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) 469 if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID))
@@ -519,11 +524,12 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
519 int *psize, int *apsize, int *ssize, unsigned long *vpn) 524 int *psize, int *apsize, int *ssize, unsigned long *vpn)
520{ 525{
521 unsigned long avpn, pteg, vpi; 526 unsigned long avpn, pteg, vpi;
522 unsigned long hpte_v = hpte->v; 527 unsigned long hpte_v = be64_to_cpu(hpte->v);
528 unsigned long hpte_r = be64_to_cpu(hpte->r);
523 unsigned long vsid, seg_off; 529 unsigned long vsid, seg_off;
524 int size, a_size, shift; 530 int size, a_size, shift;
525 /* Look at the 8 bit LP value */ 531 /* Look at the 8 bit LP value */
526 unsigned int lp = (hpte->r >> LP_SHIFT) & ((1 << LP_BITS) - 1); 532 unsigned int lp = (hpte_r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
527 533
528 if (!(hpte_v & HPTE_V_LARGE)) { 534 if (!(hpte_v & HPTE_V_LARGE)) {
529 size = MMU_PAGE_4K; 535 size = MMU_PAGE_4K;
@@ -612,7 +618,7 @@ static void native_hpte_clear(void)
612 * running, right? and for crash dump, we probably 618 * running, right? and for crash dump, we probably
613 * don't want to wait for a maybe bad cpu. 619 * don't want to wait for a maybe bad cpu.
614 */ 620 */
615 hpte_v = hptep->v; 621 hpte_v = be64_to_cpu(hptep->v);
616 622
617 /* 623 /*
618 * Call __tlbie() here rather than tlbie() since we 624 * Call __tlbie() here rather than tlbie() since we
@@ -664,7 +670,7 @@ static void native_flush_hash_range(unsigned long number, int local)
664 hptep = htab_address + slot; 670 hptep = htab_address + slot;
665 want_v = hpte_encode_avpn(vpn, psize, ssize); 671 want_v = hpte_encode_avpn(vpn, psize, ssize);
666 native_lock_hpte(hptep); 672 native_lock_hpte(hptep);
667 hpte_v = hptep->v; 673 hpte_v = be64_to_cpu(hptep->v);
668 if (!HPTE_V_COMPARE(hpte_v, want_v) || 674 if (!HPTE_V_COMPARE(hpte_v, want_v) ||
669 !(hpte_v & HPTE_V_VALID)) 675 !(hpte_v & HPTE_V_VALID))
670 native_unlock_hpte(hptep); 676 native_unlock_hpte(hptep);
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index bde8b5589755..6176b3cdf579 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -251,19 +251,18 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node,
251 void *data) 251 void *data)
252{ 252{
253 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 253 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
254 u32 *prop; 254 __be32 *prop;
255 unsigned long size = 0; 255 unsigned long size = 0;
256 256
257 /* We are scanning "cpu" nodes only */ 257 /* We are scanning "cpu" nodes only */
258 if (type == NULL || strcmp(type, "cpu") != 0) 258 if (type == NULL || strcmp(type, "cpu") != 0)
259 return 0; 259 return 0;
260 260
261 prop = (u32 *)of_get_flat_dt_prop(node, "ibm,processor-segment-sizes", 261 prop = of_get_flat_dt_prop(node, "ibm,processor-segment-sizes", &size);
262 &size);
263 if (prop == NULL) 262 if (prop == NULL)
264 return 0; 263 return 0;
265 for (; size >= 4; size -= 4, ++prop) { 264 for (; size >= 4; size -= 4, ++prop) {
266 if (prop[0] == 40) { 265 if (be32_to_cpu(prop[0]) == 40) {
267 DBG("1T segment support detected\n"); 266 DBG("1T segment support detected\n");
268 cur_cpu_spec->mmu_features |= MMU_FTR_1T_SEGMENT; 267 cur_cpu_spec->mmu_features |= MMU_FTR_1T_SEGMENT;
269 return 1; 268 return 1;
@@ -307,23 +306,22 @@ static int __init htab_dt_scan_page_sizes(unsigned long node,
307 void *data) 306 void *data)
308{ 307{
309 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 308 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
310 u32 *prop; 309 __be32 *prop;
311 unsigned long size = 0; 310 unsigned long size = 0;
312 311
313 /* We are scanning "cpu" nodes only */ 312 /* We are scanning "cpu" nodes only */
314 if (type == NULL || strcmp(type, "cpu") != 0) 313 if (type == NULL || strcmp(type, "cpu") != 0)
315 return 0; 314 return 0;
316 315
317 prop = (u32 *)of_get_flat_dt_prop(node, 316 prop = of_get_flat_dt_prop(node, "ibm,segment-page-sizes", &size);
318 "ibm,segment-page-sizes", &size);
319 if (prop != NULL) { 317 if (prop != NULL) {
320 pr_info("Page sizes from device-tree:\n"); 318 pr_info("Page sizes from device-tree:\n");
321 size /= 4; 319 size /= 4;
322 cur_cpu_spec->mmu_features &= ~(MMU_FTR_16M_PAGE); 320 cur_cpu_spec->mmu_features &= ~(MMU_FTR_16M_PAGE);
323 while(size > 0) { 321 while(size > 0) {
324 unsigned int base_shift = prop[0]; 322 unsigned int base_shift = be32_to_cpu(prop[0]);
325 unsigned int slbenc = prop[1]; 323 unsigned int slbenc = be32_to_cpu(prop[1]);
326 unsigned int lpnum = prop[2]; 324 unsigned int lpnum = be32_to_cpu(prop[2]);
327 struct mmu_psize_def *def; 325 struct mmu_psize_def *def;
328 int idx, base_idx; 326 int idx, base_idx;
329 327
@@ -356,8 +354,8 @@ static int __init htab_dt_scan_page_sizes(unsigned long node,
356 def->tlbiel = 0; 354 def->tlbiel = 0;
357 355
358 while (size > 0 && lpnum) { 356 while (size > 0 && lpnum) {
359 unsigned int shift = prop[0]; 357 unsigned int shift = be32_to_cpu(prop[0]);
360 int penc = prop[1]; 358 int penc = be32_to_cpu(prop[1]);
361 359
362 prop += 2; size -= 2; 360 prop += 2; size -= 2;
363 lpnum--; 361 lpnum--;
@@ -390,8 +388,8 @@ static int __init htab_dt_scan_hugepage_blocks(unsigned long node,
390 const char *uname, int depth, 388 const char *uname, int depth,
391 void *data) { 389 void *data) {
392 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 390 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
393 unsigned long *addr_prop; 391 __be64 *addr_prop;
394 u32 *page_count_prop; 392 __be32 *page_count_prop;
395 unsigned int expected_pages; 393 unsigned int expected_pages;
396 long unsigned int phys_addr; 394 long unsigned int phys_addr;
397 long unsigned int block_size; 395 long unsigned int block_size;
@@ -405,12 +403,12 @@ static int __init htab_dt_scan_hugepage_blocks(unsigned long node,
405 page_count_prop = of_get_flat_dt_prop(node, "ibm,expected#pages", NULL); 403 page_count_prop = of_get_flat_dt_prop(node, "ibm,expected#pages", NULL);
406 if (page_count_prop == NULL) 404 if (page_count_prop == NULL)
407 return 0; 405 return 0;
408 expected_pages = (1 << page_count_prop[0]); 406 expected_pages = (1 << be32_to_cpu(page_count_prop[0]));
409 addr_prop = of_get_flat_dt_prop(node, "reg", NULL); 407 addr_prop = of_get_flat_dt_prop(node, "reg", NULL);
410 if (addr_prop == NULL) 408 if (addr_prop == NULL)
411 return 0; 409 return 0;
412 phys_addr = addr_prop[0]; 410 phys_addr = be64_to_cpu(addr_prop[0]);
413 block_size = addr_prop[1]; 411 block_size = be64_to_cpu(addr_prop[1]);
414 if (block_size != (16 * GB)) 412 if (block_size != (16 * GB))
415 return 0; 413 return 0;
416 printk(KERN_INFO "Huge page(16GB) memory: " 414 printk(KERN_INFO "Huge page(16GB) memory: "
@@ -534,16 +532,16 @@ static int __init htab_dt_scan_pftsize(unsigned long node,
534 void *data) 532 void *data)
535{ 533{
536 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 534 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
537 u32 *prop; 535 __be32 *prop;
538 536
539 /* We are scanning "cpu" nodes only */ 537 /* We are scanning "cpu" nodes only */
540 if (type == NULL || strcmp(type, "cpu") != 0) 538 if (type == NULL || strcmp(type, "cpu") != 0)
541 return 0; 539 return 0;
542 540
543 prop = (u32 *)of_get_flat_dt_prop(node, "ibm,pft-size", NULL); 541 prop = of_get_flat_dt_prop(node, "ibm,pft-size", NULL);
544 if (prop != NULL) { 542 if (prop != NULL) {
545 /* pft_size[0] is the NUMA CEC cookie */ 543 /* pft_size[0] is the NUMA CEC cookie */
546 ppc64_pft_size = prop[1]; 544 ppc64_pft_size = be32_to_cpu(prop[1]);
547 return 1; 545 return 1;
548 } 546 }
549 return 0; 547 return 0;