/* SPDX-License-Identifier: GPL-2.0 */ #include <linux/linkage.h> #include <asm/asm-offsets.h> #include <asm/page.h> #include <asm/setup.h> #define MMU_BASE 8 /* MMU flags base in cpu_mmu_flags */ .text ENTRY(relocate_new_kernel) movel %sp@(4),%a0 /* a0 = ptr */ movel %sp@(8),%a1 /* a1 = start */ movel %sp@(12),%d1 /* d1 = cpu_mmu_flags */ movew #PAGE_MASK,%d2 /* d2 = PAGE_MASK */ /* Disable MMU */ btst #MMU_BASE + MMUB_68851,%d1 jeq 3f 1: /* 68851 or 68030 */ lea %pc@(.Lcopy),%a4 2: addl #0x00000000,%a4 /* virt_to_phys() */ .section .m68k_fixup,"aw" .long M68K_FIXUP_MEMOFFSET, 2b+2 .previous .chip 68030 pmove %tc,%d0 /* Disable MMU */ bclr #7,%d0 pmove %d0,%tc jmp %a4@ /* Jump to physical .Lcopy */ .chip 68k 3: btst #MMU_BASE + MMUB_68030,%d1 jne 1b btst #MMU_BASE + MMUB_68040,%d1 jeq 6f 4: /* 68040 or 68060 */ lea %pc@(.Lcont040),%a4 5: addl #0x00000000,%a4 /* virt_to_phys() */ .section .m68k_fixup,"aw" .long M68K_FIXUP_MEMOFFSET, 5b+2 .previous movel %a4,%d0 andl #0xff000000,%d0 orw #0xe020,%d0 /* Map 16 MiB, enable, cacheable */ .chip 68040 movec %d0,%itt0 movec %d0,%dtt0 .chip 68k jmp %a4@ /* Jump to physical .Lcont040 */ .Lcont040: moveq #0,%d0 .chip 68040 movec %d0,%tc /* Disable MMU */ movec %d0,%itt0 movec %d0,%itt1 movec %d0,%dtt0 movec %d0,%dtt1 .chip 68k jra .Lcopy 6: btst #MMU_BASE + MMUB_68060,%d1 jne 4b .Lcopy: movel %a0@+,%d0 /* d0 = entry = *ptr */ jeq .Lflush btst #2,%d0 /* entry & IND_DONE? */ jne .Lflush btst #1,%d0 /* entry & IND_INDIRECTION? */ jeq 1f andw %d2,%d0 movel %d0,%a0 /* ptr = entry & PAGE_MASK */ jra .Lcopy 1: btst #0,%d0 /* entry & IND_DESTINATION? */ jeq 2f andw %d2,%d0 movel %d0,%a2 /* a2 = dst = entry & PAGE_MASK */ jra .Lcopy 2: btst #3,%d0 /* entry & IND_SOURCE? */ jeq .Lcopy andw %d2,%d0 movel %d0,%a3 /* a3 = src = entry & PAGE_MASK */ movew #PAGE_SIZE/32 - 1,%d0 /* d0 = PAGE_SIZE/32 - 1 */ 3: movel %a3@+,%a2@+ /* *dst++ = *src++ */ movel %a3@+,%a2@+ /* *dst++ = *src++ */ movel %a3@+,%a2@+ /* *dst++ = *src++ */ movel %a3@+,%a2@+ /* *dst++ = *src++ */ movel %a3@+,%a2@+ /* *dst++ = *src++ */ movel %a3@+,%a2@+ /* *dst++ = *src++ */ movel %a3@+,%a2@+ /* *dst++ = *src++ */ movel %a3@+,%a2@+ /* *dst++ = *src++ */ dbf %d0, 3b jra .Lcopy .Lflush: /* Flush all caches */ btst #CPUB_68020,%d1 jeq 2f 1: /* 68020 or 68030 */ .chip 68030 movec %cacr,%d0 orw #0x808,%d0 movec %d0,%cacr .chip 68k jra .Lreincarnate 2: btst #CPUB_68030,%d1 jne 1b btst #CPUB_68040,%d1 jeq 4f 3: /* 68040 or 68060 */ .chip 68040 nop cpusha %bc nop cinva %bc nop .chip 68k jra .Lreincarnate 4: btst #CPUB_68060,%d1 jne 3b .Lreincarnate: jmp %a1@ relocate_new_kernel_end: ENTRY(relocate_new_kernel_size) .long relocate_new_kernel_end - relocate_new_kernel