1/* SPDX-License-Identifier: GPL-2.0 */
2#include <linux/linkage.h>
3
4#include <asm/asm-offsets.h>
5#include <asm/page.h>
6#include <asm/setup.h>
7
8
9#define MMU_BASE 8 /* MMU flags base in cpu_mmu_flags */
10
11.text
12
13ENTRY(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
241: /* 68851 or 68030 */
25
26 lea %pc@(.Lcopy),%a4
272: 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
403:
41 btst #MMU_BASE + MMUB_68030,%d1
42 jne 1b
43
44 btst #MMU_BASE + MMUB_68040,%d1
45 jeq 6f
46
474: /* 68040 or 68060 */
48
49 lea %pc@(.Lcont040),%a4
505: 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
766:
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
92
931:
94 btst #0,%d0 /* entry & IND_DESTINATION? */
95 jeq 2f
96 andw %d2,%d0
97 movel %d0,%a2 /* a2 = dst = entry & PAGE_MASK */
98 jra .Lcopy
99
1002:
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 */
1073:
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
1251: /* 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
1332:
134 btst #CPUB_68030,%d1
135 jne 1b
136
137 btst #CPUB_68040,%d1
138 jeq 4f
139
1403: /* 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
1504:
151 btst #CPUB_68060,%d1
152 jne 3b
153
154.Lreincarnate:
155 jmp %a1@
156
157relocate_new_kernel_end:
158
159ENTRY(relocate_new_kernel_size)
160 .long relocate_new_kernel_end - relocate_new_kernel
161

source code of linux/arch/m68k/kernel/relocate_kernel.S