[PATCH] Move iSeries and common vectors into unused space in head.S

In the ppc64 kernel head.S there is currently quite a lot of unused
space between the naca (at fixed address 0x4000) and the fwnmi data
area (at fixed address 0x7000). This patch moves various exception
vectors and support code into this region to use the wasted space.

The functions load_up_fpu and load_up_altivec are moved down as well,
since they are essentially continuations of the fp_unavailable_common
and altivec_unavailable_common vectors, respectively.

Likewise, the fwnmi vectors themselves are moved down into this area,
because while the location of the fwnmi data area is fixed by the RPA,
the vectors themselves can be anywhere sufficiently low.

Signed-off-by: David Gibson <dwg@au1.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by

David Gibson and committed by
Paul Mackerras
ec465515 2e2446ea

+175 -180
+175 -180
arch/ppc64/kernel/head.S
··· 52 * We layout physical memory as follows: 53 * 0x0000 - 0x00ff : Secondary processor spin code 54 * 0x0100 - 0x2fff : pSeries Interrupt prologs 55 - * 0x3000 - 0x3fff : Interrupt support 56 - * 0x4000 - 0x4fff : NACA 57 - * 0x6000 : iSeries and common interrupt prologs 58 * 0x9000 - 0x9fff : Initial segment table 59 */ 60 ··· 500 STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) 501 STD_EXCEPTION_PSERIES(0x1700, altivec_assist) 502 503 - /* moved from 0xf00 */ 504 - STD_EXCEPTION_PSERIES(0x3000, performance_monitor) 505 506 - . = 0x3100 507 _GLOBAL(do_stab_bolted_pSeries) 508 mtcrf 0x80,r12 509 mfspr r12,SPRG2 510 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) 511 512 513 - . = 0x6100 514 515 #ifdef CONFIG_PPC_ISERIES 516 /*** ISeries-LPAR interrupt handlers ***/ ··· 673 ld r13,PACA_EXGEN+EX_R13(r13) 674 rfid 675 b . /* prevent speculative execution */ 676 - #endif 677 - 678 - /* 679 - * Data area reserved for FWNMI option. 680 - */ 681 - .= 0x7000 682 - .globl fwnmi_data_area 683 - fwnmi_data_area: 684 - 685 - #ifdef CONFIG_PPC_ISERIES 686 - . = LPARMAP_PHYS 687 - #include "lparmap.s" 688 #endif /* CONFIG_PPC_ISERIES */ 689 - 690 - /* 691 - * Vectors for the FWNMI option. Share common code. 692 - */ 693 - . = 0x8000 694 - .globl system_reset_fwnmi 695 - system_reset_fwnmi: 696 - HMT_MEDIUM 697 - mtspr SPRG1,r13 /* save r13 */ 698 - RUNLATCH_ON(r13) 699 - EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) 700 - .globl machine_check_fwnmi 701 - machine_check_fwnmi: 702 - HMT_MEDIUM 703 - mtspr SPRG1,r13 /* save r13 */ 704 - RUNLATCH_ON(r13) 705 - EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) 706 - 707 - /* 708 - * Space for the initial segment table 709 - * For LPAR, the hypervisor must fill in at least one entry 710 - * before we get control (with relocate on) 711 - */ 712 - . = STAB0_PHYS_ADDR 713 - .globl __start_stab 714 - __start_stab: 715 - 716 - . = (STAB0_PHYS_ADDR + PAGE_SIZE) 717 - .globl __end_stab 718 - __end_stab: 719 - 720 721 /*** Common interrupt handlers ***/ 722 ··· 865 bl .kernel_fp_unavailable_exception 866 BUG_OPCODE 867 868 .align 7 869 .globl altivec_unavailable_common 870 altivec_unavailable_common: ··· 935 ENABLE_INTS 936 bl .altivec_unavailable_exception 937 b .ret_from_except 938 939 /* 940 * Hash table stuff ··· 1256 bl .unrecoverable_exception 1257 b 1b 1258 1259 1260 /* 1261 * On pSeries, secondary processors spin in the following code. ··· 1541 copy_to_here: 1542 1543 /* 1544 - * load_up_fpu(unused, unused, tsk) 1545 - * Disable FP for the task which had the FPU previously, 1546 - * and save its floating-point registers in its thread_struct. 1547 - * Enables the FPU for use in the kernel on return. 1548 - * On SMP we know the fpu is free, since we give it up every 1549 - * switch (ie, no lazy save of the FP registers). 1550 - * On entry: r13 == 'current' && last_task_used_math != 'current' 1551 - */ 1552 - _STATIC(load_up_fpu) 1553 - mfmsr r5 /* grab the current MSR */ 1554 - ori r5,r5,MSR_FP 1555 - mtmsrd r5 /* enable use of fpu now */ 1556 - isync 1557 - /* 1558 - * For SMP, we don't do lazy FPU switching because it just gets too 1559 - * horrendously complex, especially when a task switches from one CPU 1560 - * to another. Instead we call giveup_fpu in switch_to. 1561 - * 1562 - */ 1563 - #ifndef CONFIG_SMP 1564 - ld r3,last_task_used_math@got(r2) 1565 - ld r4,0(r3) 1566 - cmpdi 0,r4,0 1567 - beq 1f 1568 - /* Save FP state to last_task_used_math's THREAD struct */ 1569 - addi r4,r4,THREAD 1570 - SAVE_32FPRS(0, r4) 1571 - mffs fr0 1572 - stfd fr0,THREAD_FPSCR(r4) 1573 - /* Disable FP for last_task_used_math */ 1574 - ld r5,PT_REGS(r4) 1575 - ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1576 - li r6,MSR_FP|MSR_FE0|MSR_FE1 1577 - andc r4,r4,r6 1578 - std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1579 - 1: 1580 - #endif /* CONFIG_SMP */ 1581 - /* enable use of FP after return */ 1582 - ld r4,PACACURRENT(r13) 1583 - addi r5,r4,THREAD /* Get THREAD */ 1584 - ld r4,THREAD_FPEXC_MODE(r5) 1585 - ori r12,r12,MSR_FP 1586 - or r12,r12,r4 1587 - std r12,_MSR(r1) 1588 - lfd fr0,THREAD_FPSCR(r5) 1589 - mtfsf 0xff,fr0 1590 - REST_32FPRS(0, r5) 1591 - #ifndef CONFIG_SMP 1592 - /* Update last_task_used_math to 'current' */ 1593 - subi r4,r5,THREAD /* Back to 'current' */ 1594 - std r4,0(r3) 1595 - #endif /* CONFIG_SMP */ 1596 - /* restore registers and return */ 1597 - b fast_exception_return 1598 - 1599 - /* 1600 * disable_kernel_fp() 1601 * Disable the FPU. 1602 */ ··· 1584 #endif /* CONFIG_SMP */ 1585 blr 1586 1587 - 1588 #ifdef CONFIG_ALTIVEC 1589 - 1590 - /* 1591 - * load_up_altivec(unused, unused, tsk) 1592 - * Disable VMX for the task which had it previously, 1593 - * and save its vector registers in its thread_struct. 1594 - * Enables the VMX for use in the kernel on return. 1595 - * On SMP we know the VMX is free, since we give it up every 1596 - * switch (ie, no lazy save of the vector registers). 1597 - * On entry: r13 == 'current' && last_task_used_altivec != 'current' 1598 - */ 1599 - _STATIC(load_up_altivec) 1600 - mfmsr r5 /* grab the current MSR */ 1601 - oris r5,r5,MSR_VEC@h 1602 - mtmsrd r5 /* enable use of VMX now */ 1603 - isync 1604 - 1605 - /* 1606 - * For SMP, we don't do lazy VMX switching because it just gets too 1607 - * horrendously complex, especially when a task switches from one CPU 1608 - * to another. Instead we call giveup_altvec in switch_to. 1609 - * VRSAVE isn't dealt with here, that is done in the normal context 1610 - * switch code. Note that we could rely on vrsave value to eventually 1611 - * avoid saving all of the VREGs here... 1612 - */ 1613 - #ifndef CONFIG_SMP 1614 - ld r3,last_task_used_altivec@got(r2) 1615 - ld r4,0(r3) 1616 - cmpdi 0,r4,0 1617 - beq 1f 1618 - /* Save VMX state to last_task_used_altivec's THREAD struct */ 1619 - addi r4,r4,THREAD 1620 - SAVE_32VRS(0,r5,r4) 1621 - mfvscr vr0 1622 - li r10,THREAD_VSCR 1623 - stvx vr0,r10,r4 1624 - /* Disable VMX for last_task_used_altivec */ 1625 - ld r5,PT_REGS(r4) 1626 - ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1627 - lis r6,MSR_VEC@h 1628 - andc r4,r4,r6 1629 - std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1630 - 1: 1631 - #endif /* CONFIG_SMP */ 1632 - /* Hack: if we get an altivec unavailable trap with VRSAVE 1633 - * set to all zeros, we assume this is a broken application 1634 - * that fails to set it properly, and thus we switch it to 1635 - * all 1's 1636 - */ 1637 - mfspr r4,SPRN_VRSAVE 1638 - cmpdi 0,r4,0 1639 - bne+ 1f 1640 - li r4,-1 1641 - mtspr SPRN_VRSAVE,r4 1642 - 1: 1643 - /* enable use of VMX after return */ 1644 - ld r4,PACACURRENT(r13) 1645 - addi r5,r4,THREAD /* Get THREAD */ 1646 - oris r12,r12,MSR_VEC@h 1647 - std r12,_MSR(r1) 1648 - li r4,1 1649 - li r10,THREAD_VSCR 1650 - stw r4,THREAD_USED_VR(r5) 1651 - lvx vr0,r10,r5 1652 - mtvscr vr0 1653 - REST_32VRS(0,r4,r5) 1654 - #ifndef CONFIG_SMP 1655 - /* Update last_task_used_math to 'current' */ 1656 - subi r4,r5,THREAD /* Back to 'current' */ 1657 - std r4,0(r3) 1658 - #endif /* CONFIG_SMP */ 1659 - /* restore registers and return */ 1660 - b fast_exception_return 1661 - 1662 /* 1663 * disable_kernel_altivec() 1664 * Disable the VMX.
··· 52 * We layout physical memory as follows: 53 * 0x0000 - 0x00ff : Secondary processor spin code 54 * 0x0100 - 0x2fff : pSeries Interrupt prologs 55 + * 0x3000 - 0x6fff : interrupt support, iSeries and common interrupt prologs 56 + * 0x7000 - 0x7fff : FWNMI data area 57 * 0x9000 - 0x9fff : Initial segment table 58 */ 59 ··· 501 STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) 502 STD_EXCEPTION_PSERIES(0x1700, altivec_assist) 503 504 + . = 0x3000 505 506 + /*** pSeries interrupt support ***/ 507 + 508 + /* moved from 0xf00 */ 509 + STD_EXCEPTION_PSERIES(., performance_monitor) 510 + 511 + .align 7 512 _GLOBAL(do_stab_bolted_pSeries) 513 mtcrf 0x80,r12 514 mfspr r12,SPRG2 515 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) 516 517 + /* 518 + * Vectors for the FWNMI option. Share common code. 519 + */ 520 + .globl system_reset_fwnmi 521 + system_reset_fwnmi: 522 + HMT_MEDIUM 523 + mtspr SPRG1,r13 /* save r13 */ 524 + RUNLATCH_ON(r13) 525 + EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) 526 527 + .globl machine_check_fwnmi 528 + machine_check_fwnmi: 529 + HMT_MEDIUM 530 + mtspr SPRG1,r13 /* save r13 */ 531 + RUNLATCH_ON(r13) 532 + EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) 533 534 #ifdef CONFIG_PPC_ISERIES 535 /*** ISeries-LPAR interrupt handlers ***/ ··· 656 ld r13,PACA_EXGEN+EX_R13(r13) 657 rfid 658 b . /* prevent speculative execution */ 659 #endif /* CONFIG_PPC_ISERIES */ 660 661 /*** Common interrupt handlers ***/ 662 ··· 891 bl .kernel_fp_unavailable_exception 892 BUG_OPCODE 893 894 + /* 895 + * load_up_fpu(unused, unused, tsk) 896 + * Disable FP for the task which had the FPU previously, 897 + * and save its floating-point registers in its thread_struct. 898 + * Enables the FPU for use in the kernel on return. 899 + * On SMP we know the fpu is free, since we give it up every 900 + * switch (ie, no lazy save of the FP registers). 901 + * On entry: r13 == 'current' && last_task_used_math != 'current' 902 + */ 903 + _STATIC(load_up_fpu) 904 + mfmsr r5 /* grab the current MSR */ 905 + ori r5,r5,MSR_FP 906 + mtmsrd r5 /* enable use of fpu now */ 907 + isync 908 + /* 909 + * For SMP, we don't do lazy FPU switching because it just gets too 910 + * horrendously complex, especially when a task switches from one CPU 911 + * to another. Instead we call giveup_fpu in switch_to. 912 + * 913 + */ 914 + #ifndef CONFIG_SMP 915 + ld r3,last_task_used_math@got(r2) 916 + ld r4,0(r3) 917 + cmpdi 0,r4,0 918 + beq 1f 919 + /* Save FP state to last_task_used_math's THREAD struct */ 920 + addi r4,r4,THREAD 921 + SAVE_32FPRS(0, r4) 922 + mffs fr0 923 + stfd fr0,THREAD_FPSCR(r4) 924 + /* Disable FP for last_task_used_math */ 925 + ld r5,PT_REGS(r4) 926 + ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) 927 + li r6,MSR_FP|MSR_FE0|MSR_FE1 928 + andc r4,r4,r6 929 + std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 930 + 1: 931 + #endif /* CONFIG_SMP */ 932 + /* enable use of FP after return */ 933 + ld r4,PACACURRENT(r13) 934 + addi r5,r4,THREAD /* Get THREAD */ 935 + ld r4,THREAD_FPEXC_MODE(r5) 936 + ori r12,r12,MSR_FP 937 + or r12,r12,r4 938 + std r12,_MSR(r1) 939 + lfd fr0,THREAD_FPSCR(r5) 940 + mtfsf 0xff,fr0 941 + REST_32FPRS(0, r5) 942 + #ifndef CONFIG_SMP 943 + /* Update last_task_used_math to 'current' */ 944 + subi r4,r5,THREAD /* Back to 'current' */ 945 + std r4,0(r3) 946 + #endif /* CONFIG_SMP */ 947 + /* restore registers and return */ 948 + b fast_exception_return 949 + 950 .align 7 951 .globl altivec_unavailable_common 952 altivec_unavailable_common: ··· 905 ENABLE_INTS 906 bl .altivec_unavailable_exception 907 b .ret_from_except 908 + 909 + #ifdef CONFIG_ALTIVEC 910 + /* 911 + * load_up_altivec(unused, unused, tsk) 912 + * Disable VMX for the task which had it previously, 913 + * and save its vector registers in its thread_struct. 914 + * Enables the VMX for use in the kernel on return. 915 + * On SMP we know the VMX is free, since we give it up every 916 + * switch (ie, no lazy save of the vector registers). 917 + * On entry: r13 == 'current' && last_task_used_altivec != 'current' 918 + */ 919 + _STATIC(load_up_altivec) 920 + mfmsr r5 /* grab the current MSR */ 921 + oris r5,r5,MSR_VEC@h 922 + mtmsrd r5 /* enable use of VMX now */ 923 + isync 924 + 925 + /* 926 + * For SMP, we don't do lazy VMX switching because it just gets too 927 + * horrendously complex, especially when a task switches from one CPU 928 + * to another. Instead we call giveup_altvec in switch_to. 929 + * VRSAVE isn't dealt with here, that is done in the normal context 930 + * switch code. Note that we could rely on vrsave value to eventually 931 + * avoid saving all of the VREGs here... 932 + */ 933 + #ifndef CONFIG_SMP 934 + ld r3,last_task_used_altivec@got(r2) 935 + ld r4,0(r3) 936 + cmpdi 0,r4,0 937 + beq 1f 938 + /* Save VMX state to last_task_used_altivec's THREAD struct */ 939 + addi r4,r4,THREAD 940 + SAVE_32VRS(0,r5,r4) 941 + mfvscr vr0 942 + li r10,THREAD_VSCR 943 + stvx vr0,r10,r4 944 + /* Disable VMX for last_task_used_altivec */ 945 + ld r5,PT_REGS(r4) 946 + ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) 947 + lis r6,MSR_VEC@h 948 + andc r4,r4,r6 949 + std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 950 + 1: 951 + #endif /* CONFIG_SMP */ 952 + /* Hack: if we get an altivec unavailable trap with VRSAVE 953 + * set to all zeros, we assume this is a broken application 954 + * that fails to set it properly, and thus we switch it to 955 + * all 1's 956 + */ 957 + mfspr r4,SPRN_VRSAVE 958 + cmpdi 0,r4,0 959 + bne+ 1f 960 + li r4,-1 961 + mtspr SPRN_VRSAVE,r4 962 + 1: 963 + /* enable use of VMX after return */ 964 + ld r4,PACACURRENT(r13) 965 + addi r5,r4,THREAD /* Get THREAD */ 966 + oris r12,r12,MSR_VEC@h 967 + std r12,_MSR(r1) 968 + li r4,1 969 + li r10,THREAD_VSCR 970 + stw r4,THREAD_USED_VR(r5) 971 + lvx vr0,r10,r5 972 + mtvscr vr0 973 + REST_32VRS(0,r4,r5) 974 + #ifndef CONFIG_SMP 975 + /* Update last_task_used_math to 'current' */ 976 + subi r4,r5,THREAD /* Back to 'current' */ 977 + std r4,0(r3) 978 + #endif /* CONFIG_SMP */ 979 + /* restore registers and return */ 980 + b fast_exception_return 981 + #endif /* CONFIG_ALTIVEC */ 982 983 /* 984 * Hash table stuff ··· 1152 bl .unrecoverable_exception 1153 b 1b 1154 1155 + /* 1156 + * Data area reserved for FWNMI option. 1157 + * This address (0x7000) is fixed by the RPA. 1158 + */ 1159 + .= 0x7000 1160 + .globl fwnmi_data_area 1161 + fwnmi_data_area: 1162 + .space PAGE_SIZE 1163 + 1164 + /* 1165 + * Space for the initial segment table 1166 + * For LPAR, the hypervisor must fill in at least one entry 1167 + * before we get control (with relocate on) 1168 + */ 1169 + . = STAB0_PHYS_ADDR 1170 + .globl __start_stab 1171 + __start_stab: 1172 + 1173 + . = (STAB0_PHYS_ADDR + PAGE_SIZE) 1174 + .globl __end_stab 1175 + __end_stab: 1176 1177 /* 1178 * On pSeries, secondary processors spin in the following code. ··· 1416 copy_to_here: 1417 1418 /* 1419 * disable_kernel_fp() 1420 * Disable the FPU. 1421 */ ··· 1515 #endif /* CONFIG_SMP */ 1516 blr 1517 1518 #ifdef CONFIG_ALTIVEC 1519 /* 1520 * disable_kernel_altivec() 1521 * Disable the VMX.