diff options
-rw-r--r-- | arch/ppc64/kernel/head.S | 353 |
1 files changed, 174 insertions, 179 deletions
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 13c03648a602..eb54f0548b01 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S | |||
@@ -52,9 +52,8 @@ | |||
52 | * We layout physical memory as follows: | 52 | * We layout physical memory as follows: |
53 | * 0x0000 - 0x00ff : Secondary processor spin code | 53 | * 0x0000 - 0x00ff : Secondary processor spin code |
54 | * 0x0100 - 0x2fff : pSeries Interrupt prologs | 54 | * 0x0100 - 0x2fff : pSeries Interrupt prologs |
55 | * 0x3000 - 0x3fff : Interrupt support | 55 | * 0x3000 - 0x6fff : interrupt support, iSeries and common interrupt prologs |
56 | * 0x4000 - 0x4fff : NACA | 56 | * 0x7000 - 0x7fff : FWNMI data area |
57 | * 0x6000 : iSeries and common interrupt prologs | ||
58 | * 0x9000 - 0x9fff : Initial segment table | 57 | * 0x9000 - 0x9fff : Initial segment table |
59 | */ | 58 | */ |
60 | 59 | ||
@@ -501,17 +500,35 @@ system_call_pSeries: | |||
501 | STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) | 500 | STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) |
502 | STD_EXCEPTION_PSERIES(0x1700, altivec_assist) | 501 | STD_EXCEPTION_PSERIES(0x1700, altivec_assist) |
503 | 502 | ||
503 | . = 0x3000 | ||
504 | |||
505 | /*** pSeries interrupt support ***/ | ||
506 | |||
504 | /* moved from 0xf00 */ | 507 | /* moved from 0xf00 */ |
505 | STD_EXCEPTION_PSERIES(0x3000, performance_monitor) | 508 | STD_EXCEPTION_PSERIES(., performance_monitor) |
506 | 509 | ||
507 | . = 0x3100 | 510 | .align 7 |
508 | _GLOBAL(do_stab_bolted_pSeries) | 511 | _GLOBAL(do_stab_bolted_pSeries) |
509 | mtcrf 0x80,r12 | 512 | mtcrf 0x80,r12 |
510 | mfspr r12,SPRG2 | 513 | mfspr r12,SPRG2 |
511 | EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) | 514 | EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) |
512 | 515 | ||
516 | /* | ||
517 | * Vectors for the FWNMI option. Share common code. | ||
518 | */ | ||
519 | .globl system_reset_fwnmi | ||
520 | system_reset_fwnmi: | ||
521 | HMT_MEDIUM | ||
522 | mtspr SPRG1,r13 /* save r13 */ | ||
523 | RUNLATCH_ON(r13) | ||
524 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) | ||
513 | 525 | ||
514 | . = 0x6100 | 526 | .globl machine_check_fwnmi |
527 | machine_check_fwnmi: | ||
528 | HMT_MEDIUM | ||
529 | mtspr SPRG1,r13 /* save r13 */ | ||
530 | RUNLATCH_ON(r13) | ||
531 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | ||
515 | 532 | ||
516 | #ifdef CONFIG_PPC_ISERIES | 533 | #ifdef CONFIG_PPC_ISERIES |
517 | /*** ISeries-LPAR interrupt handlers ***/ | 534 | /*** ISeries-LPAR interrupt handlers ***/ |
@@ -656,51 +673,8 @@ hardware_interrupt_iSeries_masked: | |||
656 | ld r13,PACA_EXGEN+EX_R13(r13) | 673 | ld r13,PACA_EXGEN+EX_R13(r13) |
657 | rfid | 674 | rfid |
658 | b . /* prevent speculative execution */ | 675 | b . /* prevent speculative execution */ |
659 | #endif | ||
660 | |||
661 | /* | ||
662 | * Data area reserved for FWNMI option. | ||
663 | */ | ||
664 | .= 0x7000 | ||
665 | .globl fwnmi_data_area | ||
666 | fwnmi_data_area: | ||
667 | |||
668 | #ifdef CONFIG_PPC_ISERIES | ||
669 | . = LPARMAP_PHYS | ||
670 | #include "lparmap.s" | ||
671 | #endif /* CONFIG_PPC_ISERIES */ | 676 | #endif /* CONFIG_PPC_ISERIES */ |
672 | 677 | ||
673 | /* | ||
674 | * Vectors for the FWNMI option. Share common code. | ||
675 | */ | ||
676 | . = 0x8000 | ||
677 | .globl system_reset_fwnmi | ||
678 | system_reset_fwnmi: | ||
679 | HMT_MEDIUM | ||
680 | mtspr SPRG1,r13 /* save r13 */ | ||
681 | RUNLATCH_ON(r13) | ||
682 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) | ||
683 | .globl machine_check_fwnmi | ||
684 | machine_check_fwnmi: | ||
685 | HMT_MEDIUM | ||
686 | mtspr SPRG1,r13 /* save r13 */ | ||
687 | RUNLATCH_ON(r13) | ||
688 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | ||
689 | |||
690 | /* | ||
691 | * Space for the initial segment table | ||
692 | * For LPAR, the hypervisor must fill in at least one entry | ||
693 | * before we get control (with relocate on) | ||
694 | */ | ||
695 | . = STAB0_PHYS_ADDR | ||
696 | .globl __start_stab | ||
697 | __start_stab: | ||
698 | |||
699 | . = (STAB0_PHYS_ADDR + PAGE_SIZE) | ||
700 | .globl __end_stab | ||
701 | __end_stab: | ||
702 | |||
703 | |||
704 | /*** Common interrupt handlers ***/ | 678 | /*** Common interrupt handlers ***/ |
705 | 679 | ||
706 | STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception) | 680 | STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception) |
@@ -891,6 +865,62 @@ fp_unavailable_common: | |||
891 | bl .kernel_fp_unavailable_exception | 865 | bl .kernel_fp_unavailable_exception |
892 | BUG_OPCODE | 866 | BUG_OPCODE |
893 | 867 | ||
868 | /* | ||
869 | * load_up_fpu(unused, unused, tsk) | ||
870 | * Disable FP for the task which had the FPU previously, | ||
871 | * and save its floating-point registers in its thread_struct. | ||
872 | * Enables the FPU for use in the kernel on return. | ||
873 | * On SMP we know the fpu is free, since we give it up every | ||
874 | * switch (ie, no lazy save of the FP registers). | ||
875 | * On entry: r13 == 'current' && last_task_used_math != 'current' | ||
876 | */ | ||
877 | _STATIC(load_up_fpu) | ||
878 | mfmsr r5 /* grab the current MSR */ | ||
879 | ori r5,r5,MSR_FP | ||
880 | mtmsrd r5 /* enable use of fpu now */ | ||
881 | isync | ||
882 | /* | ||
883 | * For SMP, we don't do lazy FPU switching because it just gets too | ||
884 | * horrendously complex, especially when a task switches from one CPU | ||
885 | * to another. Instead we call giveup_fpu in switch_to. | ||
886 | * | ||
887 | */ | ||
888 | #ifndef CONFIG_SMP | ||
889 | ld r3,last_task_used_math@got(r2) | ||
890 | ld r4,0(r3) | ||
891 | cmpdi 0,r4,0 | ||
892 | beq 1f | ||
893 | /* Save FP state to last_task_used_math's THREAD struct */ | ||
894 | addi r4,r4,THREAD | ||
895 | SAVE_32FPRS(0, r4) | ||
896 | mffs fr0 | ||
897 | stfd fr0,THREAD_FPSCR(r4) | ||
898 | /* Disable FP for last_task_used_math */ | ||
899 | ld r5,PT_REGS(r4) | ||
900 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
901 | li r6,MSR_FP|MSR_FE0|MSR_FE1 | ||
902 | andc r4,r4,r6 | ||
903 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
904 | 1: | ||
905 | #endif /* CONFIG_SMP */ | ||
906 | /* enable use of FP after return */ | ||
907 | ld r4,PACACURRENT(r13) | ||
908 | addi r5,r4,THREAD /* Get THREAD */ | ||
909 | ld r4,THREAD_FPEXC_MODE(r5) | ||
910 | ori r12,r12,MSR_FP | ||
911 | or r12,r12,r4 | ||
912 | std r12,_MSR(r1) | ||
913 | lfd fr0,THREAD_FPSCR(r5) | ||
914 | mtfsf 0xff,fr0 | ||
915 | REST_32FPRS(0, r5) | ||
916 | #ifndef CONFIG_SMP | ||
917 | /* Update last_task_used_math to 'current' */ | ||
918 | subi r4,r5,THREAD /* Back to 'current' */ | ||
919 | std r4,0(r3) | ||
920 | #endif /* CONFIG_SMP */ | ||
921 | /* restore registers and return */ | ||
922 | b fast_exception_return | ||
923 | |||
894 | .align 7 | 924 | .align 7 |
895 | .globl altivec_unavailable_common | 925 | .globl altivec_unavailable_common |
896 | altivec_unavailable_common: | 926 | altivec_unavailable_common: |
@@ -906,6 +936,80 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
906 | bl .altivec_unavailable_exception | 936 | bl .altivec_unavailable_exception |
907 | b .ret_from_except | 937 | b .ret_from_except |
908 | 938 | ||
939 | #ifdef CONFIG_ALTIVEC | ||
940 | /* | ||
941 | * load_up_altivec(unused, unused, tsk) | ||
942 | * Disable VMX for the task which had it previously, | ||
943 | * and save its vector registers in its thread_struct. | ||
944 | * Enables the VMX for use in the kernel on return. | ||
945 | * On SMP we know the VMX is free, since we give it up every | ||
946 | * switch (ie, no lazy save of the vector registers). | ||
947 | * On entry: r13 == 'current' && last_task_used_altivec != 'current' | ||
948 | */ | ||
949 | _STATIC(load_up_altivec) | ||
950 | mfmsr r5 /* grab the current MSR */ | ||
951 | oris r5,r5,MSR_VEC@h | ||
952 | mtmsrd r5 /* enable use of VMX now */ | ||
953 | isync | ||
954 | |||
955 | /* | ||
956 | * For SMP, we don't do lazy VMX switching because it just gets too | ||
957 | * horrendously complex, especially when a task switches from one CPU | ||
958 | * to another. Instead we call giveup_altvec in switch_to. | ||
959 | * VRSAVE isn't dealt with here, that is done in the normal context | ||
960 | * switch code. Note that we could rely on vrsave value to eventually | ||
961 | * avoid saving all of the VREGs here... | ||
962 | */ | ||
963 | #ifndef CONFIG_SMP | ||
964 | ld r3,last_task_used_altivec@got(r2) | ||
965 | ld r4,0(r3) | ||
966 | cmpdi 0,r4,0 | ||
967 | beq 1f | ||
968 | /* Save VMX state to last_task_used_altivec's THREAD struct */ | ||
969 | addi r4,r4,THREAD | ||
970 | SAVE_32VRS(0,r5,r4) | ||
971 | mfvscr vr0 | ||
972 | li r10,THREAD_VSCR | ||
973 | stvx vr0,r10,r4 | ||
974 | /* Disable VMX for last_task_used_altivec */ | ||
975 | ld r5,PT_REGS(r4) | ||
976 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
977 | lis r6,MSR_VEC@h | ||
978 | andc r4,r4,r6 | ||
979 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
980 | 1: | ||
981 | #endif /* CONFIG_SMP */ | ||
982 | /* Hack: if we get an altivec unavailable trap with VRSAVE | ||
983 | * set to all zeros, we assume this is a broken application | ||
984 | * that fails to set it properly, and thus we switch it to | ||
985 | * all 1's | ||
986 | */ | ||
987 | mfspr r4,SPRN_VRSAVE | ||
988 | cmpdi 0,r4,0 | ||
989 | bne+ 1f | ||
990 | li r4,-1 | ||
991 | mtspr SPRN_VRSAVE,r4 | ||
992 | 1: | ||
993 | /* enable use of VMX after return */ | ||
994 | ld r4,PACACURRENT(r13) | ||
995 | addi r5,r4,THREAD /* Get THREAD */ | ||
996 | oris r12,r12,MSR_VEC@h | ||
997 | std r12,_MSR(r1) | ||
998 | li r4,1 | ||
999 | li r10,THREAD_VSCR | ||
1000 | stw r4,THREAD_USED_VR(r5) | ||
1001 | lvx vr0,r10,r5 | ||
1002 | mtvscr vr0 | ||
1003 | REST_32VRS(0,r4,r5) | ||
1004 | #ifndef CONFIG_SMP | ||
1005 | /* Update last_task_used_math to 'current' */ | ||
1006 | subi r4,r5,THREAD /* Back to 'current' */ | ||
1007 | std r4,0(r3) | ||
1008 | #endif /* CONFIG_SMP */ | ||
1009 | /* restore registers and return */ | ||
1010 | b fast_exception_return | ||
1011 | #endif /* CONFIG_ALTIVEC */ | ||
1012 | |||
909 | /* | 1013 | /* |
910 | * Hash table stuff | 1014 | * Hash table stuff |
911 | */ | 1015 | */ |
@@ -1152,6 +1256,27 @@ unrecov_slb: | |||
1152 | bl .unrecoverable_exception | 1256 | bl .unrecoverable_exception |
1153 | b 1b | 1257 | b 1b |
1154 | 1258 | ||
1259 | /* | ||
1260 | * Data area reserved for FWNMI option. | ||
1261 | * This address (0x7000) is fixed by the RPA. | ||
1262 | */ | ||
1263 | .= 0x7000 | ||
1264 | .globl fwnmi_data_area | ||
1265 | fwnmi_data_area: | ||
1266 | .space PAGE_SIZE | ||
1267 | |||
1268 | /* | ||
1269 | * Space for the initial segment table | ||
1270 | * For LPAR, the hypervisor must fill in at least one entry | ||
1271 | * before we get control (with relocate on) | ||
1272 | */ | ||
1273 | . = STAB0_PHYS_ADDR | ||
1274 | .globl __start_stab | ||
1275 | __start_stab: | ||
1276 | |||
1277 | . = (STAB0_PHYS_ADDR + PAGE_SIZE) | ||
1278 | .globl __end_stab | ||
1279 | __end_stab: | ||
1155 | 1280 | ||
1156 | /* | 1281 | /* |
1157 | * On pSeries, secondary processors spin in the following code. | 1282 | * On pSeries, secondary processors spin in the following code. |
@@ -1416,62 +1541,6 @@ _GLOBAL(copy_and_flush) | |||
1416 | copy_to_here: | 1541 | copy_to_here: |
1417 | 1542 | ||
1418 | /* | 1543 | /* |
1419 | * load_up_fpu(unused, unused, tsk) | ||
1420 | * Disable FP for the task which had the FPU previously, | ||
1421 | * and save its floating-point registers in its thread_struct. | ||
1422 | * Enables the FPU for use in the kernel on return. | ||
1423 | * On SMP we know the fpu is free, since we give it up every | ||
1424 | * switch (ie, no lazy save of the FP registers). | ||
1425 | * On entry: r13 == 'current' && last_task_used_math != 'current' | ||
1426 | */ | ||
1427 | _STATIC(load_up_fpu) | ||
1428 | mfmsr r5 /* grab the current MSR */ | ||
1429 | ori r5,r5,MSR_FP | ||
1430 | mtmsrd r5 /* enable use of fpu now */ | ||
1431 | isync | ||
1432 | /* | ||
1433 | * For SMP, we don't do lazy FPU switching because it just gets too | ||
1434 | * horrendously complex, especially when a task switches from one CPU | ||
1435 | * to another. Instead we call giveup_fpu in switch_to. | ||
1436 | * | ||
1437 | */ | ||
1438 | #ifndef CONFIG_SMP | ||
1439 | ld r3,last_task_used_math@got(r2) | ||
1440 | ld r4,0(r3) | ||
1441 | cmpdi 0,r4,0 | ||
1442 | beq 1f | ||
1443 | /* Save FP state to last_task_used_math's THREAD struct */ | ||
1444 | addi r4,r4,THREAD | ||
1445 | SAVE_32FPRS(0, r4) | ||
1446 | mffs fr0 | ||
1447 | stfd fr0,THREAD_FPSCR(r4) | ||
1448 | /* Disable FP for last_task_used_math */ | ||
1449 | ld r5,PT_REGS(r4) | ||
1450 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1451 | li r6,MSR_FP|MSR_FE0|MSR_FE1 | ||
1452 | andc r4,r4,r6 | ||
1453 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1454 | 1: | ||
1455 | #endif /* CONFIG_SMP */ | ||
1456 | /* enable use of FP after return */ | ||
1457 | ld r4,PACACURRENT(r13) | ||
1458 | addi r5,r4,THREAD /* Get THREAD */ | ||
1459 | ld r4,THREAD_FPEXC_MODE(r5) | ||
1460 | ori r12,r12,MSR_FP | ||
1461 | or r12,r12,r4 | ||
1462 | std r12,_MSR(r1) | ||
1463 | lfd fr0,THREAD_FPSCR(r5) | ||
1464 | mtfsf 0xff,fr0 | ||
1465 | REST_32FPRS(0, r5) | ||
1466 | #ifndef CONFIG_SMP | ||
1467 | /* Update last_task_used_math to 'current' */ | ||
1468 | subi r4,r5,THREAD /* Back to 'current' */ | ||
1469 | std r4,0(r3) | ||
1470 | #endif /* CONFIG_SMP */ | ||
1471 | /* restore registers and return */ | ||
1472 | b fast_exception_return | ||
1473 | |||
1474 | /* | ||
1475 | * disable_kernel_fp() | 1544 | * disable_kernel_fp() |
1476 | * Disable the FPU. | 1545 | * Disable the FPU. |
1477 | */ | 1546 | */ |
@@ -1515,81 +1584,7 @@ _GLOBAL(giveup_fpu) | |||
1515 | #endif /* CONFIG_SMP */ | 1584 | #endif /* CONFIG_SMP */ |
1516 | blr | 1585 | blr |
1517 | 1586 | ||
1518 | |||
1519 | #ifdef CONFIG_ALTIVEC | 1587 | #ifdef CONFIG_ALTIVEC |
1520 | |||
1521 | /* | ||
1522 | * load_up_altivec(unused, unused, tsk) | ||
1523 | * Disable VMX for the task which had it previously, | ||
1524 | * and save its vector registers in its thread_struct. | ||
1525 | * Enables the VMX for use in the kernel on return. | ||
1526 | * On SMP we know the VMX is free, since we give it up every | ||
1527 | * switch (ie, no lazy save of the vector registers). | ||
1528 | * On entry: r13 == 'current' && last_task_used_altivec != 'current' | ||
1529 | */ | ||
1530 | _STATIC(load_up_altivec) | ||
1531 | mfmsr r5 /* grab the current MSR */ | ||
1532 | oris r5,r5,MSR_VEC@h | ||
1533 | mtmsrd r5 /* enable use of VMX now */ | ||
1534 | isync | ||
1535 | |||
1536 | /* | ||
1537 | * For SMP, we don't do lazy VMX switching because it just gets too | ||
1538 | * horrendously complex, especially when a task switches from one CPU | ||
1539 | * to another. Instead we call giveup_altvec in switch_to. | ||
1540 | * VRSAVE isn't dealt with here, that is done in the normal context | ||
1541 | * switch code. Note that we could rely on vrsave value to eventually | ||
1542 | * avoid saving all of the VREGs here... | ||
1543 | */ | ||
1544 | #ifndef CONFIG_SMP | ||
1545 | ld r3,last_task_used_altivec@got(r2) | ||
1546 | ld r4,0(r3) | ||
1547 | cmpdi 0,r4,0 | ||
1548 | beq 1f | ||
1549 | /* Save VMX state to last_task_used_altivec's THREAD struct */ | ||
1550 | addi r4,r4,THREAD | ||
1551 | SAVE_32VRS(0,r5,r4) | ||
1552 | mfvscr vr0 | ||
1553 | li r10,THREAD_VSCR | ||
1554 | stvx vr0,r10,r4 | ||
1555 | /* Disable VMX for last_task_used_altivec */ | ||
1556 | ld r5,PT_REGS(r4) | ||
1557 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1558 | lis r6,MSR_VEC@h | ||
1559 | andc r4,r4,r6 | ||
1560 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1561 | 1: | ||
1562 | #endif /* CONFIG_SMP */ | ||
1563 | /* Hack: if we get an altivec unavailable trap with VRSAVE | ||
1564 | * set to all zeros, we assume this is a broken application | ||
1565 | * that fails to set it properly, and thus we switch it to | ||
1566 | * all 1's | ||
1567 | */ | ||
1568 | mfspr r4,SPRN_VRSAVE | ||
1569 | cmpdi 0,r4,0 | ||
1570 | bne+ 1f | ||
1571 | li r4,-1 | ||
1572 | mtspr SPRN_VRSAVE,r4 | ||
1573 | 1: | ||
1574 | /* enable use of VMX after return */ | ||
1575 | ld r4,PACACURRENT(r13) | ||
1576 | addi r5,r4,THREAD /* Get THREAD */ | ||
1577 | oris r12,r12,MSR_VEC@h | ||
1578 | std r12,_MSR(r1) | ||
1579 | li r4,1 | ||
1580 | li r10,THREAD_VSCR | ||
1581 | stw r4,THREAD_USED_VR(r5) | ||
1582 | lvx vr0,r10,r5 | ||
1583 | mtvscr vr0 | ||
1584 | REST_32VRS(0,r4,r5) | ||
1585 | #ifndef CONFIG_SMP | ||
1586 | /* Update last_task_used_math to 'current' */ | ||
1587 | subi r4,r5,THREAD /* Back to 'current' */ | ||
1588 | std r4,0(r3) | ||
1589 | #endif /* CONFIG_SMP */ | ||
1590 | /* restore registers and return */ | ||
1591 | b fast_exception_return | ||
1592 | |||
1593 | /* | 1588 | /* |
1594 | * disable_kernel_altivec() | 1589 | * disable_kernel_altivec() |
1595 | * Disable the VMX. | 1590 | * Disable the VMX. |