1 /* SPDX-License-Identifier: GPL-2.0-only */ !! 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* !! 2 #include <linux/linkage.h> 3 * relocate_kernel.S for kexec << 4 * Created by <nschichan@corp.free.fr> on Thu O << 5 */ << 6 << 7 #include <asm/asm.h> << 8 #include <asm/asmmacro.h> << 9 #include <asm/regdef.h> << 10 #include <asm/mipsregs.h> << 11 #include <asm/stackframe.h> << 12 #include <asm/addrspace.h> << 13 << 14 #include <kernel-entry-init.h> << 15 << 16 LEAF(relocate_new_kernel) << 17 PTR_L a0, arg0 << 18 PTR_L a1, arg1 << 19 PTR_L a2, arg2 << 20 PTR_L a3, arg3 << 21 << 22 PTR_L s0, kexec_indirection_ << 23 PTR_L s1, kexec_start_addres << 24 << 25 process_entry: << 26 PTR_L s2, (s0) << 27 PTR_ADDIU s0, s0, SZREG << 28 << 29 /* << 30 * In case of a kdump/crash kernel, th << 31 * populated as the kernel is directly << 32 */ << 33 beqz s2, done << 34 << 35 /* destination page */ << 36 and s3, s2, 0x1 << 37 beq s3, zero, 1f << 38 and s4, s2, ~0x1 /* sto << 39 b process_entry << 40 3 41 1: !! 4 #include <asm/asm-offsets.h> 42 /* indirection page, update s0 */ !! 5 #include <asm/page.h> 43 and s3, s2, 0x2 !! 6 #include <asm/setup.h> 44 beq s3, zero, 1f !! 7 45 and s0, s2, ~0x2 !! 8 46 b process_entry !! 9 #define MMU_BASE 8 /* MMU flags base in cpu_mmu_flags */ >> 10 >> 11 .text >> 12 >> 13 ENTRY(relocate_new_kernel) >> 14 movel %sp@(4),%a0 /* a0 = ptr */ >> 15 movel %sp@(8),%a1 /* a1 = start */ >> 16 movel %sp@(12),%d1 /* d1 = cpu_mmu_flags */ >> 17 movew #PAGE_MASK,%d2 /* d2 = PAGE_MASK */ >> 18 >> 19 /* Disable MMU */ >> 20 >> 21 btst #MMU_BASE + MMUB_68851,%d1 >> 22 jeq 3f >> 23 >> 24 1: /* 68851 or 68030 */ >> 25 >> 26 lea %pc@(.Lcopy),%a4 >> 27 2: addl #0x00000000,%a4 /* virt_to_phys() */ >> 28 >> 29 .section .m68k_fixup,"aw" >> 30 .long M68K_FIXUP_MEMOFFSET, 2b+2 >> 31 .previous >> 32 >> 33 .chip 68030 >> 34 pmove %tc,%d0 /* Disable MMU */ >> 35 bclr #7,%d0 >> 36 pmove %d0,%tc >> 37 jmp %a4@ /* Jump to physical .Lcopy */ >> 38 .chip 68k >> 39 >> 40 3: >> 41 btst #MMU_BASE + MMUB_68030,%d1 >> 42 jne 1b >> 43 >> 44 btst #MMU_BASE + MMUB_68040,%d1 >> 45 jeq 6f >> 46 >> 47 4: /* 68040 or 68060 */ >> 48 >> 49 lea %pc@(.Lcont040),%a4 >> 50 5: addl #0x00000000,%a4 /* virt_to_phys() */ >> 51 >> 52 .section .m68k_fixup,"aw" >> 53 .long M68K_FIXUP_MEMOFFSET, 5b+2 >> 54 .previous >> 55 >> 56 movel %a4,%d0 >> 57 andl #0xff000000,%d0 >> 58 orw #0xe020,%d0 /* Map 16 MiB, enable, cacheable */ >> 59 .chip 68040 >> 60 movec %d0,%itt0 >> 61 movec %d0,%dtt0 >> 62 .chip 68k >> 63 jmp %a4@ /* Jump to physical .Lcont040 */ >> 64 >> 65 .Lcont040: >> 66 moveq #0,%d0 >> 67 .chip 68040 >> 68 movec %d0,%tc /* Disable MMU */ >> 69 movec %d0,%itt0 >> 70 movec %d0,%itt1 >> 71 movec %d0,%dtt0 >> 72 movec %d0,%dtt1 >> 73 .chip 68k >> 74 jra .Lcopy >> 75 >> 76 6: >> 77 btst #MMU_BASE + MMUB_68060,%d1 >> 78 jne 4b >> 79 >> 80 .Lcopy: >> 81 movel %a0@+,%d0 /* d0 = entry = *ptr */ >> 82 jeq .Lflush >> 83 >> 84 btst #2,%d0 /* entry & IND_DONE? */ >> 85 jne .Lflush >> 86 >> 87 btst #1,%d0 /* entry & IND_INDIRECTION? */ >> 88 jeq 1f >> 89 andw %d2,%d0 >> 90 movel %d0,%a0 /* ptr = entry & PAGE_MASK */ >> 91 jra .Lcopy 47 92 48 1: 93 1: 49 /* done page */ !! 94 btst #0,%d0 /* entry & IND_DESTINATION? */ 50 and s3, s2, 0x4 !! 95 jeq 2f 51 beq s3, zero, 1f !! 96 andw %d2,%d0 52 b done !! 97 movel %d0,%a2 /* a2 = dst = entry & PAGE_MASK */ 53 1: !! 98 jra .Lcopy 54 /* source page */ !! 99 55 and s3, s2, 0x8 !! 100 2: 56 beq s3, zero, process_entr !! 101 btst #3,%d0 /* entry & IND_SOURCE? */ 57 and s2, s2, ~0x8 !! 102 jeq .Lcopy 58 li s6, (1 << _PAGE_SHIFT) !! 103 59 !! 104 andw %d2,%d0 60 copy_word: !! 105 movel %d0,%a3 /* a3 = src = entry & PAGE_MASK */ 61 /* copy page word by word */ !! 106 movew #PAGE_SIZE/32 - 1,%d0 /* d0 = PAGE_SIZE/32 - 1 */ 62 REG_L s5, (s2) !! 107 3: 63 REG_S s5, (s4) !! 108 movel %a3@+,%a2@+ /* *dst++ = *src++ */ 64 PTR_ADDIU s4, s4, SZREG !! 109 movel %a3@+,%a2@+ /* *dst++ = *src++ */ 65 PTR_ADDIU s2, s2, SZREG !! 110 movel %a3@+,%a2@+ /* *dst++ = *src++ */ 66 LONG_ADDIU s6, s6, -1 !! 111 movel %a3@+,%a2@+ /* *dst++ = *src++ */ 67 beq s6, zero, process_entr !! 112 movel %a3@+,%a2@+ /* *dst++ = *src++ */ 68 b copy_word !! 113 movel %a3@+,%a2@+ /* *dst++ = *src++ */ 69 !! 114 movel %a3@+,%a2@+ /* *dst++ = *src++ */ 70 done: !! 115 movel %a3@+,%a2@+ /* *dst++ = *src++ */ 71 #ifdef CONFIG_SMP !! 116 dbf %d0, 3b 72 /* kexec_flag reset is signal to other !! 117 jra .Lcopy 73 was moved to its location. Note - w !! 118 74 of kexec_flag. */ !! 119 .Lflush: 75 !! 120 /* Flush all caches */ 76 bal 1f !! 121 77 1: move t1,ra; !! 122 btst #CPUB_68020,%d1 78 PTR_LA t2,1b !! 123 jeq 2f 79 PTR_LA t0,kexec_flag !! 124 80 PTR_SUB t0,t0,t2; !! 125 1: /* 68020 or 68030 */ 81 PTR_ADD t0,t1,t0; !! 126 .chip 68030 82 LONG_S zero,(t0) !! 127 movec %cacr,%d0 83 #endif !! 128 orw #0x808,%d0 84 !! 129 movec %d0,%cacr 85 #ifdef CONFIG_CPU_CAVIUM_OCTEON !! 130 .chip 68k 86 /* We need to flush I-cache before jum !! 131 jra .Lreincarnate 87 * Unfortunately, this code is cpu-spe !! 132 88 */ !! 133 2: 89 .set push !! 134 btst #CPUB_68030,%d1 90 .set noreorder !! 135 jne 1b 91 syncw !! 136 92 syncw !! 137 btst #CPUB_68040,%d1 93 synci 0($0) !! 138 jeq 4f 94 .set pop !! 139 95 #else !! 140 3: /* 68040 or 68060 */ 96 sync !! 141 .chip 68040 97 #endif !! 142 nop 98 /* jump to kexec_start_address */ !! 143 cpusha %bc 99 j s1 !! 144 nop 100 END(relocate_new_kernel) !! 145 cinva %bc 101 !! 146 nop 102 #ifdef CONFIG_SMP !! 147 .chip 68k 103 /* !! 148 jra .Lreincarnate 104 * Other CPUs should wait until code is reloca !! 149 105 * then start at entry (?) point. !! 150 4: 106 */ !! 151 btst #CPUB_68060,%d1 107 LEAF(kexec_smp_wait) !! 152 jne 3b 108 PTR_L a0, s_arg0 !! 153 109 PTR_L a1, s_arg1 !! 154 .Lreincarnate: 110 PTR_L a2, s_arg2 !! 155 jmp %a1@ 111 PTR_L a3, s_arg3 << 112 PTR_L s1, kexec_start_addres << 113 << 114 /* Non-relocated address works for arg << 115 * kernel is not overwritten). But we << 116 * kexec_flag. << 117 */ << 118 << 119 bal 1f << 120 1: move t1,ra; << 121 PTR_LA t2,1b << 122 PTR_LA t0,kexec_flag << 123 PTR_SUB t0,t0,t2; << 124 PTR_ADD t0,t1,t0; << 125 << 126 1: LONG_L s0, (t0) << 127 bne s0, zero,1b << 128 << 129 #ifdef USE_KEXEC_SMP_WAIT_FINAL << 130 kexec_smp_wait_final << 131 #else << 132 sync << 133 #endif << 134 j s1 << 135 END(kexec_smp_wait) << 136 #endif << 137 << 138 #ifdef __mips64 << 139 /* all PTR's must be aligned to 8 byte << 140 .align 3 << 141 #endif << 142 << 143 /* All parameters to new kernel are passed in << 144 * kexec_args[0..3] are used to prepare regist << 145 */ << 146 << 147 EXPORT(kexec_args) << 148 arg0: PTR_WD 0x0 << 149 arg1: PTR_WD 0x0 << 150 arg2: PTR_WD 0x0 << 151 arg3: PTR_WD 0x0 << 152 .size kexec_args,PTRSIZE*4 << 153 << 154 #ifdef CONFIG_SMP << 155 /* << 156 * Secondary CPUs may have different kernel pa << 157 * their registers a0-a3. secondary_kexec_args << 158 * to prepare register values. << 159 */ << 160 EXPORT(secondary_kexec_args) << 161 s_arg0: PTR_WD 0x0 << 162 s_arg1: PTR_WD 0x0 << 163 s_arg2: PTR_WD 0x0 << 164 s_arg3: PTR_WD 0x0 << 165 .size secondary_kexec_args,PTRSIZE*4 << 166 kexec_flag: << 167 LONG 0x1 << 168 << 169 #endif << 170 << 171 EXPORT(kexec_start_address) << 172 PTR_WD 0x0 << 173 .size kexec_start_address, P << 174 << 175 EXPORT(kexec_indirection_page) << 176 PTR_WD 0 << 177 .size kexec_indirection_page << 178 156 179 relocate_new_kernel_end: 157 relocate_new_kernel_end: 180 158 181 EXPORT(relocate_new_kernel_size) !! 159 ENTRY(relocate_new_kernel_size) 182 PTR_WD relocate_new_kernel_en !! 160 .long relocate_new_kernel_end - relocate_new_kernel 183 .size relocate_new_kernel_si <<
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.