diff options
Diffstat (limited to 'arch/powerpc/kernel/misc_32.S')
-rw-r--r-- | arch/powerpc/kernel/misc_32.S | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 998a1002860..f7d760ab5ca 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -8,6 +8,8 @@ | |||
8 | * kexec bits: | 8 | * kexec bits: |
9 | * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com> | 9 | * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com> |
10 | * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz | 10 | * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz |
11 | * PPC44x port. Copyright (C) 2011, IBM Corporation | ||
12 | * Author: Suzuki Poulose <suzuki@in.ibm.com> | ||
11 | * | 13 | * |
12 | * This program is free software; you can redistribute it and/or | 14 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 15 | * modify it under the terms of the GNU General Public License |
@@ -736,6 +738,175 @@ relocate_new_kernel: | |||
736 | mr r5, r31 | 738 | mr r5, r31 |
737 | 739 | ||
738 | li r0, 0 | 740 | li r0, 0 |
741 | #elif defined(CONFIG_44x) && !defined(CONFIG_47x) | ||
742 | |||
743 | /* | ||
744 | * Code for setting up 1:1 mapping for PPC440x for KEXEC | ||
745 | * | ||
746 | * We cannot switch off the MMU on PPC44x. | ||
747 | * So we: | ||
748 | * 1) Invalidate all the mappings except the one we are running from. | ||
749 | * 2) Create a tmp mapping for our code in the other address space(TS) and | ||
750 | * jump to it. Invalidate the entry we started in. | ||
751 | * 3) Create a 1:1 mapping for 0-2GiB in chunks of 256M in original TS. | ||
752 | * 4) Jump to the 1:1 mapping in original TS. | ||
753 | * 5) Invalidate the tmp mapping. | ||
754 | * | ||
755 | * - Based on the kexec support code for FSL BookE | ||
756 | * - Doesn't support 47x yet. | ||
757 | * | ||
758 | */ | ||
759 | /* Save our parameters */ | ||
760 | mr r29, r3 | ||
761 | mr r30, r4 | ||
762 | mr r31, r5 | ||
763 | |||
764 | /* Load our MSR_IS and TID to MMUCR for TLB search */ | ||
765 | mfspr r3,SPRN_PID | ||
766 | mfmsr r4 | ||
767 | andi. r4,r4,MSR_IS@l | ||
768 | beq wmmucr | ||
769 | oris r3,r3,PPC44x_MMUCR_STS@h | ||
770 | wmmucr: | ||
771 | mtspr SPRN_MMUCR,r3 | ||
772 | sync | ||
773 | |||
774 | /* | ||
775 | * Invalidate all the TLB entries except the current entry | ||
776 | * where we are running from | ||
777 | */ | ||
778 | bl 0f /* Find our address */ | ||
779 | 0: mflr r5 /* Make it accessible */ | ||
780 | tlbsx r23,0,r5 /* Find entry we are in */ | ||
781 | li r4,0 /* Start at TLB entry 0 */ | ||
782 | li r3,0 /* Set PAGEID inval value */ | ||
783 | 1: cmpw r23,r4 /* Is this our entry? */ | ||
784 | beq skip /* If so, skip the inval */ | ||
785 | tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */ | ||
786 | skip: | ||
787 | addi r4,r4,1 /* Increment */ | ||
788 | cmpwi r4,64 /* Are we done? */ | ||
789 | bne 1b /* If not, repeat */ | ||
790 | isync | ||
791 | |||
792 | /* Create a temp mapping and jump to it */ | ||
793 | andi. r6, r23, 1 /* Find the index to use */ | ||
794 | addi r24, r6, 1 /* r24 will contain 1 or 2 */ | ||
795 | |||
796 | mfmsr r9 /* get the MSR */ | ||
797 | rlwinm r5, r9, 27, 31, 31 /* Extract the MSR[IS] */ | ||
798 | xori r7, r5, 1 /* Use the other address space */ | ||
799 | |||
800 | /* Read the current mapping entries */ | ||
801 | tlbre r3, r23, PPC44x_TLB_PAGEID | ||
802 | tlbre r4, r23, PPC44x_TLB_XLAT | ||
803 | tlbre r5, r23, PPC44x_TLB_ATTRIB | ||
804 | |||
805 | /* Save our current XLAT entry */ | ||
806 | mr r25, r4 | ||
807 | |||
808 | /* Extract the TLB PageSize */ | ||
809 | li r10, 1 /* r10 will hold PageSize */ | ||
810 | rlwinm r11, r3, 0, 24, 27 /* bits 24-27 */ | ||
811 | |||
812 | /* XXX: As of now we use 256M, 4K pages */ | ||
813 | cmpwi r11, PPC44x_TLB_256M | ||
814 | bne tlb_4k | ||
815 | rotlwi r10, r10, 28 /* r10 = 256M */ | ||
816 | b write_out | ||
817 | tlb_4k: | ||
818 | cmpwi r11, PPC44x_TLB_4K | ||
819 | bne default | ||
820 | rotlwi r10, r10, 12 /* r10 = 4K */ | ||
821 | b write_out | ||
822 | default: | ||
823 | rotlwi r10, r10, 10 /* r10 = 1K */ | ||
824 | |||
825 | write_out: | ||
826 | /* | ||
827 | * Write out the tmp 1:1 mapping for this code in other address space | ||
828 | * Fixup EPN = RPN , TS=other address space | ||
829 | */ | ||
830 | insrwi r3, r7, 1, 23 /* Bit 23 is TS for PAGEID field */ | ||
831 | |||
832 | /* Write out the tmp mapping entries */ | ||
833 | tlbwe r3, r24, PPC44x_TLB_PAGEID | ||
834 | tlbwe r4, r24, PPC44x_TLB_XLAT | ||
835 | tlbwe r5, r24, PPC44x_TLB_ATTRIB | ||
836 | |||
837 | subi r11, r10, 1 /* PageOffset Mask = PageSize - 1 */ | ||
838 | not r10, r11 /* Mask for PageNum */ | ||
839 | |||
840 | /* Switch to other address space in MSR */ | ||
841 | insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */ | ||
842 | |||
843 | bl 1f | ||
844 | 1: mflr r8 | ||
845 | addi r8, r8, (2f-1b) /* Find the target offset */ | ||
846 | |||
847 | /* Jump to the tmp mapping */ | ||
848 | mtspr SPRN_SRR0, r8 | ||
849 | mtspr SPRN_SRR1, r9 | ||
850 | rfi | ||
851 | |||
852 | 2: | ||
853 | /* Invalidate the entry we were executing from */ | ||
854 | li r3, 0 | ||
855 | tlbwe r3, r23, PPC44x_TLB_PAGEID | ||
856 | |||
857 | /* attribute fields. rwx for SUPERVISOR mode */ | ||
858 | li r5, 0 | ||
859 | ori r5, r5, (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G) | ||
860 | |||
861 | /* Create 1:1 mapping in 256M pages */ | ||
862 | xori r7, r7, 1 /* Revert back to Original TS */ | ||
863 | |||
864 | li r8, 0 /* PageNumber */ | ||
865 | li r6, 3 /* TLB Index, start at 3 */ | ||
866 | |||
867 | next_tlb: | ||
868 | rotlwi r3, r8, 28 /* Create EPN (bits 0-3) */ | ||
869 | mr r4, r3 /* RPN = EPN */ | ||
870 | ori r3, r3, (PPC44x_TLB_VALID | PPC44x_TLB_256M) /* SIZE = 256M, Valid */ | ||
871 | insrwi r3, r7, 1, 23 /* Set TS from r7 */ | ||
872 | |||
873 | tlbwe r3, r6, PPC44x_TLB_PAGEID /* PageID field : EPN, V, SIZE */ | ||
874 | tlbwe r4, r6, PPC44x_TLB_XLAT /* Address translation : RPN */ | ||
875 | tlbwe r5, r6, PPC44x_TLB_ATTRIB /* Attributes */ | ||
876 | |||
877 | addi r8, r8, 1 /* Increment PN */ | ||
878 | addi r6, r6, 1 /* Increment TLB Index */ | ||
879 | cmpwi r8, 8 /* Are we done ? */ | ||
880 | bne next_tlb | ||
881 | isync | ||
882 | |||
883 | /* Jump to the new mapping 1:1 */ | ||
884 | li r9,0 | ||
885 | insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */ | ||
886 | |||
887 | bl 1f | ||
888 | 1: mflr r8 | ||
889 | and r8, r8, r11 /* Get our offset within page */ | ||
890 | addi r8, r8, (2f-1b) | ||
891 | |||
892 | and r5, r25, r10 /* Get our target PageNum */ | ||
893 | or r8, r8, r5 /* Target jump address */ | ||
894 | |||
895 | mtspr SPRN_SRR0, r8 | ||
896 | mtspr SPRN_SRR1, r9 | ||
897 | rfi | ||
898 | 2: | ||
899 | /* Invalidate the tmp entry we used */ | ||
900 | li r3, 0 | ||
901 | tlbwe r3, r24, PPC44x_TLB_PAGEID | ||
902 | sync | ||
903 | |||
904 | /* Restore the parameters */ | ||
905 | mr r3, r29 | ||
906 | mr r4, r30 | ||
907 | mr r5, r31 | ||
908 | |||
909 | li r0, 0 | ||
739 | #else | 910 | #else |
740 | li r0, 0 | 911 | li r0, 0 |
741 | 912 | ||