diff options
Diffstat (limited to 'arch/ppc64')
-rw-r--r-- | arch/ppc64/Kconfig | 13 | ||||
-rw-r--r-- | arch/ppc64/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/ppc64/kernel/head.S | 300 | ||||
-rw-r--r-- | arch/ppc64/kernel/pacaData.c | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/prom.c | 94 |
5 files changed, 273 insertions, 139 deletions
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index b987164fca4c..2130cc315957 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig | |||
@@ -47,6 +47,10 @@ config ARCH_MAY_HAVE_PC_FDC | |||
47 | bool | 47 | bool |
48 | default y | 48 | default y |
49 | 49 | ||
50 | config PPC_STD_MMU | ||
51 | bool | ||
52 | default y | ||
53 | |||
50 | # We optimistically allocate largepages from the VM, so make the limit | 54 | # We optimistically allocate largepages from the VM, so make the limit |
51 | # large enough (16MB). This badly named config option is actually | 55 | # large enough (16MB). This badly named config option is actually |
52 | # max order + 1 | 56 | # max order + 1 |
@@ -294,6 +298,15 @@ config NODES_SPAN_OTHER_NODES | |||
294 | def_bool y | 298 | def_bool y |
295 | depends on NEED_MULTIPLE_NODES | 299 | depends on NEED_MULTIPLE_NODES |
296 | 300 | ||
301 | config PPC_64K_PAGES | ||
302 | bool "64k page size" | ||
303 | help | ||
304 | This option changes the kernel logical page size to 64k. On machines | ||
305 | without processor support for 64k pages, the kernel will simulate | ||
306 | them by loading each individual 4k page on demand transparently, | ||
307 | while on hardware with such support, it will be used to map | ||
308 | normal application pages. | ||
309 | |||
297 | config SCHED_SMT | 310 | config SCHED_SMT |
298 | bool "SMT (Hyperthreading) scheduler support" | 311 | bool "SMT (Hyperthreading) scheduler support" |
299 | depends on SMP | 312 | depends on SMP |
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c index 504dee836d29..bce9065da6cb 100644 --- a/arch/ppc64/kernel/asm-offsets.c +++ b/arch/ppc64/kernel/asm-offsets.c | |||
@@ -93,6 +93,9 @@ int main(void) | |||
93 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); | 93 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); |
94 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); | 94 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); |
95 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); | 95 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); |
96 | #ifdef CONFIG_PPC_64K_PAGES | ||
97 | DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir)); | ||
98 | #endif | ||
96 | #ifdef CONFIG_HUGETLB_PAGE | 99 | #ifdef CONFIG_HUGETLB_PAGE |
97 | DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); | 100 | DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); |
98 | DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); | 101 | DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); |
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index db1cf397be2d..9e8050ea1225 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S | |||
@@ -195,11 +195,11 @@ exception_marker: | |||
195 | #define EX_R12 24 | 195 | #define EX_R12 24 |
196 | #define EX_R13 32 | 196 | #define EX_R13 32 |
197 | #define EX_SRR0 40 | 197 | #define EX_SRR0 40 |
198 | #define EX_R3 40 /* SLB miss saves R3, but not SRR0 */ | ||
199 | #define EX_DAR 48 | 198 | #define EX_DAR 48 |
200 | #define EX_LR 48 /* SLB miss saves LR, but not DAR */ | ||
201 | #define EX_DSISR 56 | 199 | #define EX_DSISR 56 |
202 | #define EX_CCR 60 | 200 | #define EX_CCR 60 |
201 | #define EX_R3 64 | ||
202 | #define EX_LR 72 | ||
203 | 203 | ||
204 | #define EXCEPTION_PROLOG_PSERIES(area, label) \ | 204 | #define EXCEPTION_PROLOG_PSERIES(area, label) \ |
205 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | 205 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ |
@@ -419,17 +419,22 @@ data_access_slb_pSeries: | |||
419 | mtspr SPRN_SPRG1,r13 | 419 | mtspr SPRN_SPRG1,r13 |
420 | RUNLATCH_ON(r13) | 420 | RUNLATCH_ON(r13) |
421 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | 421 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ |
422 | std r3,PACA_EXSLB+EX_R3(r13) | ||
423 | mfspr r3,SPRN_DAR | ||
422 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ | 424 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ |
425 | mfcr r9 | ||
426 | #ifdef __DISABLED__ | ||
427 | /* Keep that around for when we re-implement dynamic VSIDs */ | ||
428 | cmpdi r3,0 | ||
429 | bge slb_miss_user_pseries | ||
430 | #endif /* __DISABLED__ */ | ||
423 | std r10,PACA_EXSLB+EX_R10(r13) | 431 | std r10,PACA_EXSLB+EX_R10(r13) |
424 | std r11,PACA_EXSLB+EX_R11(r13) | 432 | std r11,PACA_EXSLB+EX_R11(r13) |
425 | std r12,PACA_EXSLB+EX_R12(r13) | 433 | std r12,PACA_EXSLB+EX_R12(r13) |
426 | std r3,PACA_EXSLB+EX_R3(r13) | 434 | mfspr r10,SPRN_SPRG1 |
427 | mfspr r9,SPRN_SPRG1 | 435 | std r10,PACA_EXSLB+EX_R13(r13) |
428 | std r9,PACA_EXSLB+EX_R13(r13) | ||
429 | mfcr r9 | ||
430 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | 436 | mfspr r12,SPRN_SRR1 /* and SRR1 */ |
431 | mfspr r3,SPRN_DAR | 437 | b .slb_miss_realmode /* Rel. branch works in real mode */ |
432 | b .do_slb_miss /* Rel. branch works in real mode */ | ||
433 | 438 | ||
434 | STD_EXCEPTION_PSERIES(0x400, instruction_access) | 439 | STD_EXCEPTION_PSERIES(0x400, instruction_access) |
435 | 440 | ||
@@ -440,17 +445,22 @@ instruction_access_slb_pSeries: | |||
440 | mtspr SPRN_SPRG1,r13 | 445 | mtspr SPRN_SPRG1,r13 |
441 | RUNLATCH_ON(r13) | 446 | RUNLATCH_ON(r13) |
442 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | 447 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ |
448 | std r3,PACA_EXSLB+EX_R3(r13) | ||
449 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ | ||
443 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ | 450 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ |
451 | mfcr r9 | ||
452 | #ifdef __DISABLED__ | ||
453 | /* Keep that around for when we re-implement dynamic VSIDs */ | ||
454 | cmpdi r3,0 | ||
455 | bge slb_miss_user_pseries | ||
456 | #endif /* __DISABLED__ */ | ||
444 | std r10,PACA_EXSLB+EX_R10(r13) | 457 | std r10,PACA_EXSLB+EX_R10(r13) |
445 | std r11,PACA_EXSLB+EX_R11(r13) | 458 | std r11,PACA_EXSLB+EX_R11(r13) |
446 | std r12,PACA_EXSLB+EX_R12(r13) | 459 | std r12,PACA_EXSLB+EX_R12(r13) |
447 | std r3,PACA_EXSLB+EX_R3(r13) | 460 | mfspr r10,SPRN_SPRG1 |
448 | mfspr r9,SPRN_SPRG1 | 461 | std r10,PACA_EXSLB+EX_R13(r13) |
449 | std r9,PACA_EXSLB+EX_R13(r13) | ||
450 | mfcr r9 | ||
451 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | 462 | mfspr r12,SPRN_SRR1 /* and SRR1 */ |
452 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ | 463 | b .slb_miss_realmode /* Rel. branch works in real mode */ |
453 | b .do_slb_miss /* Rel. branch works in real mode */ | ||
454 | 464 | ||
455 | STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) | 465 | STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) |
456 | STD_EXCEPTION_PSERIES(0x600, alignment) | 466 | STD_EXCEPTION_PSERIES(0x600, alignment) |
@@ -509,6 +519,38 @@ _GLOBAL(do_stab_bolted_pSeries) | |||
509 | EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) | 519 | EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) |
510 | 520 | ||
511 | /* | 521 | /* |
522 | * We have some room here we use that to put | ||
523 | * the peries slb miss user trampoline code so it's reasonably | ||
524 | * away from slb_miss_user_common to avoid problems with rfid | ||
525 | * | ||
526 | * This is used for when the SLB miss handler has to go virtual, | ||
527 | * which doesn't happen for now anymore but will once we re-implement | ||
528 | * dynamic VSIDs for shared page tables | ||
529 | */ | ||
530 | #ifdef __DISABLED__ | ||
531 | slb_miss_user_pseries: | ||
532 | std r10,PACA_EXGEN+EX_R10(r13) | ||
533 | std r11,PACA_EXGEN+EX_R11(r13) | ||
534 | std r12,PACA_EXGEN+EX_R12(r13) | ||
535 | mfspr r10,SPRG1 | ||
536 | ld r11,PACA_EXSLB+EX_R9(r13) | ||
537 | ld r12,PACA_EXSLB+EX_R3(r13) | ||
538 | std r10,PACA_EXGEN+EX_R13(r13) | ||
539 | std r11,PACA_EXGEN+EX_R9(r13) | ||
540 | std r12,PACA_EXGEN+EX_R3(r13) | ||
541 | clrrdi r12,r13,32 | ||
542 | mfmsr r10 | ||
543 | mfspr r11,SRR0 /* save SRR0 */ | ||
544 | ori r12,r12,slb_miss_user_common@l /* virt addr of handler */ | ||
545 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI | ||
546 | mtspr SRR0,r12 | ||
547 | mfspr r12,SRR1 /* and SRR1 */ | ||
548 | mtspr SRR1,r10 | ||
549 | rfid | ||
550 | b . /* prevent spec. execution */ | ||
551 | #endif /* __DISABLED__ */ | ||
552 | |||
553 | /* | ||
512 | * Vectors for the FWNMI option. Share common code. | 554 | * Vectors for the FWNMI option. Share common code. |
513 | */ | 555 | */ |
514 | .globl system_reset_fwnmi | 556 | .globl system_reset_fwnmi |
@@ -559,22 +601,59 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | |||
559 | .globl data_access_slb_iSeries | 601 | .globl data_access_slb_iSeries |
560 | data_access_slb_iSeries: | 602 | data_access_slb_iSeries: |
561 | mtspr SPRN_SPRG1,r13 /* save r13 */ | 603 | mtspr SPRN_SPRG1,r13 /* save r13 */ |
562 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) | 604 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ |
563 | std r3,PACA_EXSLB+EX_R3(r13) | 605 | std r3,PACA_EXSLB+EX_R3(r13) |
564 | ld r12,PACALPPACA+LPPACASRR1(r13) | ||
565 | mfspr r3,SPRN_DAR | 606 | mfspr r3,SPRN_DAR |
566 | b .do_slb_miss | 607 | std r9,PACA_EXSLB+EX_R9(r13) |
608 | mfcr r9 | ||
609 | #ifdef __DISABLED__ | ||
610 | cmpdi r3,0 | ||
611 | bge slb_miss_user_iseries | ||
612 | #endif | ||
613 | std r10,PACA_EXSLB+EX_R10(r13) | ||
614 | std r11,PACA_EXSLB+EX_R11(r13) | ||
615 | std r12,PACA_EXSLB+EX_R12(r13) | ||
616 | mfspr r10,SPRN_SPRG1 | ||
617 | std r10,PACA_EXSLB+EX_R13(r13) | ||
618 | ld r12,PACALPPACA+LPPACASRR1(r13); | ||
619 | b .slb_miss_realmode | ||
567 | 620 | ||
568 | STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) | 621 | STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) |
569 | 622 | ||
570 | .globl instruction_access_slb_iSeries | 623 | .globl instruction_access_slb_iSeries |
571 | instruction_access_slb_iSeries: | 624 | instruction_access_slb_iSeries: |
572 | mtspr SPRN_SPRG1,r13 /* save r13 */ | 625 | mtspr SPRN_SPRG1,r13 /* save r13 */ |
573 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) | 626 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ |
574 | std r3,PACA_EXSLB+EX_R3(r13) | 627 | std r3,PACA_EXSLB+EX_R3(r13) |
575 | ld r12,PACALPPACA+LPPACASRR1(r13) | 628 | ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ |
576 | ld r3,PACALPPACA+LPPACASRR0(r13) | 629 | std r9,PACA_EXSLB+EX_R9(r13) |
577 | b .do_slb_miss | 630 | mfcr r9 |
631 | #ifdef __DISABLED__ | ||
632 | cmpdi r3,0 | ||
633 | bge .slb_miss_user_iseries | ||
634 | #endif | ||
635 | std r10,PACA_EXSLB+EX_R10(r13) | ||
636 | std r11,PACA_EXSLB+EX_R11(r13) | ||
637 | std r12,PACA_EXSLB+EX_R12(r13) | ||
638 | mfspr r10,SPRN_SPRG1 | ||
639 | std r10,PACA_EXSLB+EX_R13(r13) | ||
640 | ld r12,PACALPPACA+LPPACASRR1(r13); | ||
641 | b .slb_miss_realmode | ||
642 | |||
643 | #ifdef __DISABLED__ | ||
644 | slb_miss_user_iseries: | ||
645 | std r10,PACA_EXGEN+EX_R10(r13) | ||
646 | std r11,PACA_EXGEN+EX_R11(r13) | ||
647 | std r12,PACA_EXGEN+EX_R12(r13) | ||
648 | mfspr r10,SPRG1 | ||
649 | ld r11,PACA_EXSLB+EX_R9(r13) | ||
650 | ld r12,PACA_EXSLB+EX_R3(r13) | ||
651 | std r10,PACA_EXGEN+EX_R13(r13) | ||
652 | std r11,PACA_EXGEN+EX_R9(r13) | ||
653 | std r12,PACA_EXGEN+EX_R3(r13) | ||
654 | EXCEPTION_PROLOG_ISERIES_2 | ||
655 | b slb_miss_user_common | ||
656 | #endif | ||
578 | 657 | ||
579 | MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt) | 658 | MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt) |
580 | STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN) | 659 | STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN) |
@@ -809,6 +888,126 @@ instruction_access_common: | |||
809 | li r5,0x400 | 888 | li r5,0x400 |
810 | b .do_hash_page /* Try to handle as hpte fault */ | 889 | b .do_hash_page /* Try to handle as hpte fault */ |
811 | 890 | ||
891 | /* | ||
892 | * Here is the common SLB miss user that is used when going to virtual | ||
893 | * mode for SLB misses, that is currently not used | ||
894 | */ | ||
895 | #ifdef __DISABLED__ | ||
896 | .align 7 | ||
897 | .globl slb_miss_user_common | ||
898 | slb_miss_user_common: | ||
899 | mflr r10 | ||
900 | std r3,PACA_EXGEN+EX_DAR(r13) | ||
901 | stw r9,PACA_EXGEN+EX_CCR(r13) | ||
902 | std r10,PACA_EXGEN+EX_LR(r13) | ||
903 | std r11,PACA_EXGEN+EX_SRR0(r13) | ||
904 | bl .slb_allocate_user | ||
905 | |||
906 | ld r10,PACA_EXGEN+EX_LR(r13) | ||
907 | ld r3,PACA_EXGEN+EX_R3(r13) | ||
908 | lwz r9,PACA_EXGEN+EX_CCR(r13) | ||
909 | ld r11,PACA_EXGEN+EX_SRR0(r13) | ||
910 | mtlr r10 | ||
911 | beq- slb_miss_fault | ||
912 | |||
913 | andi. r10,r12,MSR_RI /* check for unrecoverable exception */ | ||
914 | beq- unrecov_user_slb | ||
915 | mfmsr r10 | ||
916 | |||
917 | .machine push | ||
918 | .machine "power4" | ||
919 | mtcrf 0x80,r9 | ||
920 | .machine pop | ||
921 | |||
922 | clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */ | ||
923 | mtmsrd r10,1 | ||
924 | |||
925 | mtspr SRR0,r11 | ||
926 | mtspr SRR1,r12 | ||
927 | |||
928 | ld r9,PACA_EXGEN+EX_R9(r13) | ||
929 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
930 | ld r11,PACA_EXGEN+EX_R11(r13) | ||
931 | ld r12,PACA_EXGEN+EX_R12(r13) | ||
932 | ld r13,PACA_EXGEN+EX_R13(r13) | ||
933 | rfid | ||
934 | b . | ||
935 | |||
936 | slb_miss_fault: | ||
937 | EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN) | ||
938 | ld r4,PACA_EXGEN+EX_DAR(r13) | ||
939 | li r5,0 | ||
940 | std r4,_DAR(r1) | ||
941 | std r5,_DSISR(r1) | ||
942 | b .handle_page_fault | ||
943 | |||
944 | unrecov_user_slb: | ||
945 | EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) | ||
946 | DISABLE_INTS | ||
947 | bl .save_nvgprs | ||
948 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
949 | bl .unrecoverable_exception | ||
950 | b 1b | ||
951 | |||
952 | #endif /* __DISABLED__ */ | ||
953 | |||
954 | |||
955 | /* | ||
956 | * r13 points to the PACA, r9 contains the saved CR, | ||
957 | * r12 contain the saved SRR1, SRR0 is still ready for return | ||
958 | * r3 has the faulting address | ||
959 | * r9 - r13 are saved in paca->exslb. | ||
960 | * r3 is saved in paca->slb_r3 | ||
961 | * We assume we aren't going to take any exceptions during this procedure. | ||
962 | */ | ||
963 | _GLOBAL(slb_miss_realmode) | ||
964 | mflr r10 | ||
965 | |||
966 | stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ | ||
967 | std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ | ||
968 | |||
969 | bl .slb_allocate_realmode | ||
970 | |||
971 | /* All done -- return from exception. */ | ||
972 | |||
973 | ld r10,PACA_EXSLB+EX_LR(r13) | ||
974 | ld r3,PACA_EXSLB+EX_R3(r13) | ||
975 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | ||
976 | #ifdef CONFIG_PPC_ISERIES | ||
977 | ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ | ||
978 | #endif /* CONFIG_PPC_ISERIES */ | ||
979 | |||
980 | mtlr r10 | ||
981 | |||
982 | andi. r10,r12,MSR_RI /* check for unrecoverable exception */ | ||
983 | beq- unrecov_slb | ||
984 | |||
985 | .machine push | ||
986 | .machine "power4" | ||
987 | mtcrf 0x80,r9 | ||
988 | mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ | ||
989 | .machine pop | ||
990 | |||
991 | #ifdef CONFIG_PPC_ISERIES | ||
992 | mtspr SPRN_SRR0,r11 | ||
993 | mtspr SPRN_SRR1,r12 | ||
994 | #endif /* CONFIG_PPC_ISERIES */ | ||
995 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
996 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
997 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
998 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
999 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
1000 | rfid | ||
1001 | b . /* prevent speculative execution */ | ||
1002 | |||
1003 | unrecov_slb: | ||
1004 | EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) | ||
1005 | DISABLE_INTS | ||
1006 | bl .save_nvgprs | ||
1007 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
1008 | bl .unrecoverable_exception | ||
1009 | b 1b | ||
1010 | |||
812 | .align 7 | 1011 | .align 7 |
813 | .globl hardware_interrupt_common | 1012 | .globl hardware_interrupt_common |
814 | .globl hardware_interrupt_entry | 1013 | .globl hardware_interrupt_entry |
@@ -1139,62 +1338,6 @@ _GLOBAL(do_stab_bolted) | |||
1139 | b . /* prevent speculative execution */ | 1338 | b . /* prevent speculative execution */ |
1140 | 1339 | ||
1141 | /* | 1340 | /* |
1142 | * r13 points to the PACA, r9 contains the saved CR, | ||
1143 | * r11 and r12 contain the saved SRR0 and SRR1. | ||
1144 | * r3 has the faulting address | ||
1145 | * r9 - r13 are saved in paca->exslb. | ||
1146 | * r3 is saved in paca->slb_r3 | ||
1147 | * We assume we aren't going to take any exceptions during this procedure. | ||
1148 | */ | ||
1149 | _GLOBAL(do_slb_miss) | ||
1150 | mflr r10 | ||
1151 | |||
1152 | stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ | ||
1153 | std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ | ||
1154 | |||
1155 | bl .slb_allocate /* handle it */ | ||
1156 | |||
1157 | /* All done -- return from exception. */ | ||
1158 | |||
1159 | ld r10,PACA_EXSLB+EX_LR(r13) | ||
1160 | ld r3,PACA_EXSLB+EX_R3(r13) | ||
1161 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | ||
1162 | #ifdef CONFIG_PPC_ISERIES | ||
1163 | ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ | ||
1164 | #endif /* CONFIG_PPC_ISERIES */ | ||
1165 | |||
1166 | mtlr r10 | ||
1167 | |||
1168 | andi. r10,r12,MSR_RI /* check for unrecoverable exception */ | ||
1169 | beq- unrecov_slb | ||
1170 | |||
1171 | .machine push | ||
1172 | .machine "power4" | ||
1173 | mtcrf 0x80,r9 | ||
1174 | mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ | ||
1175 | .machine pop | ||
1176 | |||
1177 | #ifdef CONFIG_PPC_ISERIES | ||
1178 | mtspr SPRN_SRR0,r11 | ||
1179 | mtspr SPRN_SRR1,r12 | ||
1180 | #endif /* CONFIG_PPC_ISERIES */ | ||
1181 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
1182 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
1183 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
1184 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
1185 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
1186 | rfid | ||
1187 | b . /* prevent speculative execution */ | ||
1188 | |||
1189 | unrecov_slb: | ||
1190 | EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) | ||
1191 | DISABLE_INTS | ||
1192 | bl .save_nvgprs | ||
1193 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
1194 | bl .unrecoverable_exception | ||
1195 | b 1b | ||
1196 | |||
1197 | /* | ||
1198 | * Space for CPU0's segment table. | 1341 | * Space for CPU0's segment table. |
1199 | * | 1342 | * |
1200 | * On iSeries, the hypervisor must fill in at least one entry before | 1343 | * On iSeries, the hypervisor must fill in at least one entry before |
@@ -1569,7 +1712,10 @@ _GLOBAL(__secondary_start) | |||
1569 | #endif | 1712 | #endif |
1570 | /* Initialize the first segment table (or SLB) entry */ | 1713 | /* Initialize the first segment table (or SLB) entry */ |
1571 | ld r3,PACASTABVIRT(r13) /* get addr of segment table */ | 1714 | ld r3,PACASTABVIRT(r13) /* get addr of segment table */ |
1715 | BEGIN_FTR_SECTION | ||
1572 | bl .stab_initialize | 1716 | bl .stab_initialize |
1717 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
1718 | bl .slb_initialize | ||
1573 | 1719 | ||
1574 | /* Initialize the kernel stack. Just a repeat for iSeries. */ | 1720 | /* Initialize the kernel stack. Just a repeat for iSeries. */ |
1575 | LOADADDR(r3,current_set) | 1721 | LOADADDR(r3,current_set) |
diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c index 5e27e5a6a35d..3133c72b28ec 100644 --- a/arch/ppc64/kernel/pacaData.c +++ b/arch/ppc64/kernel/pacaData.c | |||
@@ -23,7 +23,7 @@ | |||
23 | static union { | 23 | static union { |
24 | struct systemcfg data; | 24 | struct systemcfg data; |
25 | u8 page[PAGE_SIZE]; | 25 | u8 page[PAGE_SIZE]; |
26 | } systemcfg_store __page_aligned; | 26 | } systemcfg_store __attribute__((__section__(".data.page.aligned"))); |
27 | struct systemcfg *systemcfg = &systemcfg_store.data; | 27 | struct systemcfg *systemcfg = &systemcfg_store.data; |
28 | EXPORT_SYMBOL(systemcfg); | 28 | EXPORT_SYMBOL(systemcfg); |
29 | 29 | ||
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 97bfceb5353b..dece31e58bc4 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c | |||
@@ -635,10 +635,10 @@ static inline char *find_flat_dt_string(u32 offset) | |||
635 | * used to extract the memory informations at boot before we can | 635 | * used to extract the memory informations at boot before we can |
636 | * unflatten the tree | 636 | * unflatten the tree |
637 | */ | 637 | */ |
638 | static int __init scan_flat_dt(int (*it)(unsigned long node, | 638 | int __init of_scan_flat_dt(int (*it)(unsigned long node, |
639 | const char *uname, int depth, | 639 | const char *uname, int depth, |
640 | void *data), | 640 | void *data), |
641 | void *data) | 641 | void *data) |
642 | { | 642 | { |
643 | unsigned long p = ((unsigned long)initial_boot_params) + | 643 | unsigned long p = ((unsigned long)initial_boot_params) + |
644 | initial_boot_params->off_dt_struct; | 644 | initial_boot_params->off_dt_struct; |
@@ -695,8 +695,8 @@ static int __init scan_flat_dt(int (*it)(unsigned long node, | |||
695 | * This function can be used within scan_flattened_dt callback to get | 695 | * This function can be used within scan_flattened_dt callback to get |
696 | * access to properties | 696 | * access to properties |
697 | */ | 697 | */ |
698 | static void* __init get_flat_dt_prop(unsigned long node, const char *name, | 698 | void* __init of_get_flat_dt_prop(unsigned long node, const char *name, |
699 | unsigned long *size) | 699 | unsigned long *size) |
700 | { | 700 | { |
701 | unsigned long p = node; | 701 | unsigned long p = node; |
702 | 702 | ||
@@ -996,7 +996,7 @@ void __init unflatten_device_tree(void) | |||
996 | static int __init early_init_dt_scan_cpus(unsigned long node, | 996 | static int __init early_init_dt_scan_cpus(unsigned long node, |
997 | const char *uname, int depth, void *data) | 997 | const char *uname, int depth, void *data) |
998 | { | 998 | { |
999 | char *type = get_flat_dt_prop(node, "device_type", NULL); | 999 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
1000 | u32 *prop; | 1000 | u32 *prop; |
1001 | unsigned long size; | 1001 | unsigned long size; |
1002 | 1002 | ||
@@ -1004,17 +1004,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
1004 | if (type == NULL || strcmp(type, "cpu") != 0) | 1004 | if (type == NULL || strcmp(type, "cpu") != 0) |
1005 | return 0; | 1005 | return 0; |
1006 | 1006 | ||
1007 | /* On LPAR, look for the first ibm,pft-size property for the hash table size | ||
1008 | */ | ||
1009 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) { | ||
1010 | u32 *pft_size; | ||
1011 | pft_size = (u32 *)get_flat_dt_prop(node, "ibm,pft-size", NULL); | ||
1012 | if (pft_size != NULL) { | ||
1013 | /* pft_size[0] is the NUMA CEC cookie */ | ||
1014 | ppc64_pft_size = pft_size[1]; | ||
1015 | } | ||
1016 | } | ||
1017 | |||
1018 | if (initial_boot_params && initial_boot_params->version >= 2) { | 1007 | if (initial_boot_params && initial_boot_params->version >= 2) { |
1019 | /* version 2 of the kexec param format adds the phys cpuid | 1008 | /* version 2 of the kexec param format adds the phys cpuid |
1020 | * of booted proc. | 1009 | * of booted proc. |
@@ -1023,8 +1012,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
1023 | boot_cpuid = 0; | 1012 | boot_cpuid = 0; |
1024 | } else { | 1013 | } else { |
1025 | /* Check if it's the boot-cpu, set it's hw index in paca now */ | 1014 | /* Check if it's the boot-cpu, set it's hw index in paca now */ |
1026 | if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) { | 1015 | if (of_get_flat_dt_prop(node, "linux,boot-cpu", NULL) |
1027 | u32 *prop = get_flat_dt_prop(node, "reg", NULL); | 1016 | != NULL) { |
1017 | u32 *prop = of_get_flat_dt_prop(node, "reg", NULL); | ||
1028 | set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop); | 1018 | set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop); |
1029 | boot_cpuid_phys = get_hard_smp_processor_id(0); | 1019 | boot_cpuid_phys = get_hard_smp_processor_id(0); |
1030 | } | 1020 | } |
@@ -1032,14 +1022,14 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
1032 | 1022 | ||
1033 | #ifdef CONFIG_ALTIVEC | 1023 | #ifdef CONFIG_ALTIVEC |
1034 | /* Check if we have a VMX and eventually update CPU features */ | 1024 | /* Check if we have a VMX and eventually update CPU features */ |
1035 | prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", NULL); | 1025 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); |
1036 | if (prop && (*prop) > 0) { | 1026 | if (prop && (*prop) > 0) { |
1037 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | 1027 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; |
1038 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | 1028 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; |
1039 | } | 1029 | } |
1040 | 1030 | ||
1041 | /* Same goes for Apple's "altivec" property */ | 1031 | /* Same goes for Apple's "altivec" property */ |
1042 | prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL); | 1032 | prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); |
1043 | if (prop) { | 1033 | if (prop) { |
1044 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | 1034 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; |
1045 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | 1035 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; |
@@ -1051,7 +1041,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
1051 | * this by looking at the size of the ibm,ppc-interrupt-server#s | 1041 | * this by looking at the size of the ibm,ppc-interrupt-server#s |
1052 | * property | 1042 | * property |
1053 | */ | 1043 | */ |
1054 | prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", | 1044 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", |
1055 | &size); | 1045 | &size); |
1056 | cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; | 1046 | cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; |
1057 | if (prop && ((size / sizeof(u32)) > 1)) | 1047 | if (prop && ((size / sizeof(u32)) > 1)) |
@@ -1072,26 +1062,26 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1072 | return 0; | 1062 | return 0; |
1073 | 1063 | ||
1074 | /* get platform type */ | 1064 | /* get platform type */ |
1075 | prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL); | 1065 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); |
1076 | if (prop == NULL) | 1066 | if (prop == NULL) |
1077 | return 0; | 1067 | return 0; |
1078 | systemcfg->platform = *prop; | 1068 | systemcfg->platform = *prop; |
1079 | 1069 | ||
1080 | /* check if iommu is forced on or off */ | 1070 | /* check if iommu is forced on or off */ |
1081 | if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) | 1071 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) |
1082 | iommu_is_off = 1; | 1072 | iommu_is_off = 1; |
1083 | if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) | 1073 | if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) |
1084 | iommu_force_on = 1; | 1074 | iommu_force_on = 1; |
1085 | 1075 | ||
1086 | prop64 = (u64*)get_flat_dt_prop(node, "linux,memory-limit", NULL); | 1076 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,memory-limit", NULL); |
1087 | if (prop64) | 1077 | if (prop64) |
1088 | memory_limit = *prop64; | 1078 | memory_limit = *prop64; |
1089 | 1079 | ||
1090 | prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); | 1080 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-start",NULL); |
1091 | if (prop64) | 1081 | if (prop64) |
1092 | tce_alloc_start = *prop64; | 1082 | tce_alloc_start = *prop64; |
1093 | 1083 | ||
1094 | prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); | 1084 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); |
1095 | if (prop64) | 1085 | if (prop64) |
1096 | tce_alloc_end = *prop64; | 1086 | tce_alloc_end = *prop64; |
1097 | 1087 | ||
@@ -1102,9 +1092,12 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1102 | { | 1092 | { |
1103 | u64 *basep, *entryp; | 1093 | u64 *basep, *entryp; |
1104 | 1094 | ||
1105 | basep = (u64*)get_flat_dt_prop(node, "linux,rtas-base", NULL); | 1095 | basep = (u64*)of_get_flat_dt_prop(node, |
1106 | entryp = (u64*)get_flat_dt_prop(node, "linux,rtas-entry", NULL); | 1096 | "linux,rtas-base", NULL); |
1107 | prop = (u32*)get_flat_dt_prop(node, "linux,rtas-size", NULL); | 1097 | entryp = (u64*)of_get_flat_dt_prop(node, |
1098 | "linux,rtas-entry", NULL); | ||
1099 | prop = (u32*)of_get_flat_dt_prop(node, | ||
1100 | "linux,rtas-size", NULL); | ||
1108 | if (basep && entryp && prop) { | 1101 | if (basep && entryp && prop) { |
1109 | rtas.base = *basep; | 1102 | rtas.base = *basep; |
1110 | rtas.entry = *entryp; | 1103 | rtas.entry = *entryp; |
@@ -1125,11 +1118,11 @@ static int __init early_init_dt_scan_root(unsigned long node, | |||
1125 | if (depth != 0) | 1118 | if (depth != 0) |
1126 | return 0; | 1119 | return 0; |
1127 | 1120 | ||
1128 | prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL); | 1121 | prop = (u32 *)of_get_flat_dt_prop(node, "#size-cells", NULL); |
1129 | dt_root_size_cells = (prop == NULL) ? 1 : *prop; | 1122 | dt_root_size_cells = (prop == NULL) ? 1 : *prop; |
1130 | DBG("dt_root_size_cells = %x\n", dt_root_size_cells); | 1123 | DBG("dt_root_size_cells = %x\n", dt_root_size_cells); |
1131 | 1124 | ||
1132 | prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL); | 1125 | prop = (u32 *)of_get_flat_dt_prop(node, "#address-cells", NULL); |
1133 | dt_root_addr_cells = (prop == NULL) ? 2 : *prop; | 1126 | dt_root_addr_cells = (prop == NULL) ? 2 : *prop; |
1134 | DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); | 1127 | DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); |
1135 | 1128 | ||
@@ -1161,7 +1154,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp) | |||
1161 | static int __init early_init_dt_scan_memory(unsigned long node, | 1154 | static int __init early_init_dt_scan_memory(unsigned long node, |
1162 | const char *uname, int depth, void *data) | 1155 | const char *uname, int depth, void *data) |
1163 | { | 1156 | { |
1164 | char *type = get_flat_dt_prop(node, "device_type", NULL); | 1157 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
1165 | cell_t *reg, *endp; | 1158 | cell_t *reg, *endp; |
1166 | unsigned long l; | 1159 | unsigned long l; |
1167 | 1160 | ||
@@ -1169,7 +1162,7 @@ static int __init early_init_dt_scan_memory(unsigned long node, | |||
1169 | if (type == NULL || strcmp(type, "memory") != 0) | 1162 | if (type == NULL || strcmp(type, "memory") != 0) |
1170 | return 0; | 1163 | return 0; |
1171 | 1164 | ||
1172 | reg = (cell_t *)get_flat_dt_prop(node, "reg", &l); | 1165 | reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); |
1173 | if (reg == NULL) | 1166 | if (reg == NULL) |
1174 | return 0; | 1167 | return 0; |
1175 | 1168 | ||
@@ -1225,19 +1218,16 @@ void __init early_init_devtree(void *params) | |||
1225 | /* Setup flat device-tree pointer */ | 1218 | /* Setup flat device-tree pointer */ |
1226 | initial_boot_params = params; | 1219 | initial_boot_params = params; |
1227 | 1220 | ||
1228 | /* By default, hash size is not set */ | ||
1229 | ppc64_pft_size = 0; | ||
1230 | |||
1231 | /* Retreive various informations from the /chosen node of the | 1221 | /* Retreive various informations from the /chosen node of the |
1232 | * device-tree, including the platform type, initrd location and | 1222 | * device-tree, including the platform type, initrd location and |
1233 | * size, TCE reserve, and more ... | 1223 | * size, TCE reserve, and more ... |
1234 | */ | 1224 | */ |
1235 | scan_flat_dt(early_init_dt_scan_chosen, NULL); | 1225 | of_scan_flat_dt(early_init_dt_scan_chosen, NULL); |
1236 | 1226 | ||
1237 | /* Scan memory nodes and rebuild LMBs */ | 1227 | /* Scan memory nodes and rebuild LMBs */ |
1238 | lmb_init(); | 1228 | lmb_init(); |
1239 | scan_flat_dt(early_init_dt_scan_root, NULL); | 1229 | of_scan_flat_dt(early_init_dt_scan_root, NULL); |
1240 | scan_flat_dt(early_init_dt_scan_memory, NULL); | 1230 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); |
1241 | lmb_enforce_memory_limit(memory_limit); | 1231 | lmb_enforce_memory_limit(memory_limit); |
1242 | lmb_analyze(); | 1232 | lmb_analyze(); |
1243 | systemcfg->physicalMemorySize = lmb_phys_mem_size(); | 1233 | systemcfg->physicalMemorySize = lmb_phys_mem_size(); |
@@ -1253,26 +1243,8 @@ void __init early_init_devtree(void *params) | |||
1253 | /* Retreive hash table size from flattened tree plus other | 1243 | /* Retreive hash table size from flattened tree plus other |
1254 | * CPU related informations (altivec support, boot CPU ID, ...) | 1244 | * CPU related informations (altivec support, boot CPU ID, ...) |
1255 | */ | 1245 | */ |
1256 | scan_flat_dt(early_init_dt_scan_cpus, NULL); | 1246 | of_scan_flat_dt(early_init_dt_scan_cpus, NULL); |
1257 | |||
1258 | /* If hash size wasn't obtained above, we calculate it now based on | ||
1259 | * the total RAM size | ||
1260 | */ | ||
1261 | if (ppc64_pft_size == 0) { | ||
1262 | unsigned long rnd_mem_size, pteg_count; | ||
1263 | |||
1264 | /* round mem_size up to next power of 2 */ | ||
1265 | rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize); | ||
1266 | if (rnd_mem_size < systemcfg->physicalMemorySize) | ||
1267 | rnd_mem_size <<= 1; | ||
1268 | |||
1269 | /* # pages / 2 */ | ||
1270 | pteg_count = max(rnd_mem_size >> (12 + 1), 1UL << 11); | ||
1271 | |||
1272 | ppc64_pft_size = __ilog2(pteg_count << 7); | ||
1273 | } | ||
1274 | 1247 | ||
1275 | DBG("Hash pftSize: %x\n", (int)ppc64_pft_size); | ||
1276 | DBG(" <- early_init_devtree()\n"); | 1248 | DBG(" <- early_init_devtree()\n"); |
1277 | } | 1249 | } |
1278 | 1250 | ||