1 /* SPDX-License-Identifier: GPL-2.0 */ 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* !! 2 #include <linux/linkage.h> 3 * relocate_kernel.S for kexec << 4 * << 5 * Copyright (C) 2022 Loongson Technology Corp << 6 */ << 7 << 8 #include <linux/kexec.h> << 9 << 10 #include <asm/asm.h> << 11 #include <asm/asmmacro.h> << 12 #include <asm/regdef.h> << 13 #include <asm/loongarch.h> << 14 #include <asm/stackframe.h> << 15 #include <asm/addrspace.h> << 16 << 17 SYM_CODE_START(relocate_new_kernel) << 18 UNWIND_HINT_UNDEFINED << 19 /* << 20 * a0: EFI boot flag for the new kerne << 21 * a1: Command line pointer for the ne << 22 * a2: System table pointer for the ne << 23 * a3: Start address to jump to after << 24 * a4: Pointer to the current indirect << 25 */ << 26 move s0, a4 << 27 << 28 /* << 29 * In case of a kdump/crash kernel, th << 30 * populated as the kernel is directly << 31 */ << 32 beqz s0, done << 33 << 34 process_entry: << 35 PTR_L s1, s0, 0 << 36 PTR_ADDI s0, s0, SZREG << 37 << 38 /* destination page */ << 39 andi s2, s1, IND_DESTINATIO << 40 beqz s2, 1f << 41 li.w t0, ~0x1 << 42 and s3, s1, t0 /* sto << 43 b process_entry << 44 3 45 1: !! 4 #include <asm/asm-offsets.h> 46 /* indirection page, update s0 */ !! 5 #include <asm/page.h> 47 andi s2, s1, IND_INDIRECTIO !! 6 #include <asm/setup.h> 48 beqz s2, 1f !! 7 49 li.w t0, ~0x2 !! 8 50 and s0, s1, t0 !! 9 #define MMU_BASE 8 /* MMU flags base in cpu_mmu_flags */ 51 b process_entry !! 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 52 92 53 1: 93 1: 54 /* done page */ !! 94 btst #0,%d0 /* entry & IND_DESTINATION? */ 55 andi s2, s1, IND_DONE !! 95 jeq 2f 56 beqz s2, 1f !! 96 andw %d2,%d0 57 b done !! 97 movel %d0,%a2 /* a2 = dst = entry & PAGE_MASK */ >> 98 jra .Lcopy >> 99 >> 100 2: >> 101 btst #3,%d0 /* entry & IND_SOURCE? */ >> 102 jeq .Lcopy >> 103 >> 104 andw %d2,%d0 >> 105 movel %d0,%a3 /* a3 = src = entry & PAGE_MASK */ >> 106 movew #PAGE_SIZE/32 - 1,%d0 /* d0 = PAGE_SIZE/32 - 1 */ >> 107 3: >> 108 movel %a3@+,%a2@+ /* *dst++ = *src++ */ >> 109 movel %a3@+,%a2@+ /* *dst++ = *src++ */ >> 110 movel %a3@+,%a2@+ /* *dst++ = *src++ */ >> 111 movel %a3@+,%a2@+ /* *dst++ = *src++ */ >> 112 movel %a3@+,%a2@+ /* *dst++ = *src++ */ >> 113 movel %a3@+,%a2@+ /* *dst++ = *src++ */ >> 114 movel %a3@+,%a2@+ /* *dst++ = *src++ */ >> 115 movel %a3@+,%a2@+ /* *dst++ = *src++ */ >> 116 dbf %d0, 3b >> 117 jra .Lcopy >> 118 >> 119 .Lflush: >> 120 /* Flush all caches */ >> 121 >> 122 btst #CPUB_68020,%d1 >> 123 jeq 2f >> 124 >> 125 1: /* 68020 or 68030 */ >> 126 .chip 68030 >> 127 movec %cacr,%d0 >> 128 orw #0x808,%d0 >> 129 movec %d0,%cacr >> 130 .chip 68k >> 131 jra .Lreincarnate >> 132 >> 133 2: >> 134 btst #CPUB_68030,%d1 >> 135 jne 1b >> 136 >> 137 btst #CPUB_68040,%d1 >> 138 jeq 4f >> 139 >> 140 3: /* 68040 or 68060 */ >> 141 .chip 68040 >> 142 nop >> 143 cpusha %bc >> 144 nop >> 145 cinva %bc >> 146 nop >> 147 .chip 68k >> 148 jra .Lreincarnate >> 149 >> 150 4: >> 151 btst #CPUB_68060,%d1 >> 152 jne 3b 58 153 59 1: !! 154 .Lreincarnate: 60 /* source page */ !! 155 jmp %a1@ 61 andi s2, s1, IND_SOURCE << 62 beqz s2, process_entry << 63 li.w t0, ~0x8 << 64 and s1, s1, t0 << 65 li.w s5, (1 << _PAGE_SHIFT) << 66 << 67 copy_word: << 68 /* copy page word by word */ << 69 REG_L s4, s1, 0 << 70 REG_S s4, s3, 0 << 71 PTR_ADDI s3, s3, SZREG << 72 PTR_ADDI s1, s1, SZREG << 73 LONG_ADDI s5, s5, -1 << 74 beqz s5, process_entry << 75 b copy_word << 76 << 77 done: << 78 ibar 0 << 79 dbar 0 << 80 << 81 /* << 82 * Jump to the new kernel, << 83 * make sure the values of a0, a1, a2 << 84 */ << 85 jr a3 << 86 SYM_CODE_END(relocate_new_kernel) << 87 << 88 #ifdef CONFIG_SMP << 89 /* << 90 * Other CPUs should wait until code is reloca << 91 * then start at the entry point from LOONGARC << 92 */ << 93 SYM_CODE_START(kexec_smp_wait) << 94 UNWIND_HINT_UNDEFINED << 95 1: li.w t0, 0x100 << 96 2: addi.w t0, t0, -1 << 97 bnez t0, 2b << 98 li.w t1, LOONGARCH_IOCSR_MB << 99 iocsrrd.w s0, t1 << 100 beqz s0, 1b << 101 iocsrrd.d s0, t1 << 102 << 103 li.d t0, CACHE_BASE << 104 or s0, s0, t0 << 105 jr s0 << 106 SYM_CODE_END(kexec_smp_wait) << 107 #endif << 108 156 109 relocate_new_kernel_end: 157 relocate_new_kernel_end: 110 158 111 .section ".data" !! 159 ENTRY(relocate_new_kernel_size) 112 SYM_DATA(relocate_new_kernel_size, .long reloc !! 160 .long relocate_new_kernel_end - relocate_new_kernel
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.