| /* 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 |