1#include <linux/linkage.h>
2
3#include <asm/asm-offsets.h>
4#include <asm/page.h>
5#include <asm/setup.h>
6
7
8#define MMU_BASE	8		/* MMU flags base in cpu_mmu_flags */
9
10.text
11
12ENTRY(relocate_new_kernel)
13	movel %sp@(4),%a0		/* a0 = ptr */
14	movel %sp@(8),%a1		/* a1 = start */
15	movel %sp@(12),%d1		/* d1 = cpu_mmu_flags */
16	movew #PAGE_MASK,%d2		/* d2 = PAGE_MASK */
17
18	/* Disable MMU */
19
20	btst #MMU_BASE + MMUB_68851,%d1
21	jeq 3f
22
231:	/* 68851 or 68030 */
24
25	lea %pc@(.Lcopy),%a4
262:	addl #0x00000000,%a4		/* virt_to_phys() */
27
28	.section ".m68k_fixup","aw"
29	.long M68K_FIXUP_MEMOFFSET, 2b+2
30	.previous
31
32	.chip 68030
33	pmove %tc,%d0			/* Disable MMU */
34	bclr #7,%d0
35	pmove %d0,%tc
36	jmp %a4@			/* Jump to physical .Lcopy */
37	.chip 68k
38
393:
40	btst #MMU_BASE + MMUB_68030,%d1
41	jne 1b
42
43	btst #MMU_BASE + MMUB_68040,%d1
44	jeq 6f
45
464:	/* 68040 or 68060 */
47
48	lea %pc@(.Lcont040),%a4
495:	addl #0x00000000,%a4		/* virt_to_phys() */
50
51	.section ".m68k_fixup","aw"
52	.long M68K_FIXUP_MEMOFFSET, 5b+2
53	.previous
54
55	movel %a4,%d0
56	andl #0xff000000,%d0
57	orw #0xe020,%d0			/* Map 16 MiB, enable, cacheable */
58	.chip 68040
59	movec %d0,%itt0
60	movec %d0,%dtt0
61	.chip 68k
62	jmp %a4@			/* Jump to physical .Lcont040 */
63
64.Lcont040:
65	moveq #0,%d0
66	.chip 68040
67	movec %d0,%tc			/* Disable MMU */
68	movec %d0,%itt0
69	movec %d0,%itt1
70	movec %d0,%dtt0
71	movec %d0,%dtt1
72	.chip 68k
73	jra .Lcopy
74
756:
76	btst #MMU_BASE + MMUB_68060,%d1
77	jne 4b
78
79.Lcopy:
80	movel %a0@+,%d0			/* d0 = entry = *ptr */
81	jeq .Lflush
82
83	btst #2,%d0			/* entry & IND_DONE? */
84	jne .Lflush
85
86	btst #1,%d0			/* entry & IND_INDIRECTION? */
87	jeq 1f
88	andw %d2,%d0
89	movel %d0,%a0			/* ptr = entry & PAGE_MASK */
90	jra .Lcopy
91
921:
93	btst #0,%d0			/* entry & IND_DESTINATION? */
94	jeq 2f
95	andw %d2,%d0
96	movel %d0,%a2			/* a2 = dst = entry & PAGE_MASK */
97	jra .Lcopy
98
992:
100	btst #3,%d0			/* entry & IND_SOURCE? */
101	jeq .Lcopy
102
103	andw %d2,%d0
104	movel %d0,%a3			/* a3 = src = entry & PAGE_MASK */
105	movew #PAGE_SIZE/32 - 1,%d0	/* d0 = PAGE_SIZE/32 - 1 */
1063:
107	movel %a3@+,%a2@+		/* *dst++ = *src++ */
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	dbf %d0, 3b
116	jra .Lcopy
117
118.Lflush:
119	/* Flush all caches */
120
121	btst #CPUB_68020,%d1
122	jeq 2f
123
1241:	/* 68020 or 68030 */
125	.chip 68030
126	movec %cacr,%d0
127	orw #0x808,%d0
128	movec %d0,%cacr
129	.chip 68k
130	jra .Lreincarnate
131
1322:
133	btst #CPUB_68030,%d1
134	jne 1b
135
136	btst #CPUB_68040,%d1
137	jeq 4f
138
1393:	/* 68040 or 68060 */
140	.chip 68040
141	nop
142	cpusha %bc
143	nop
144	cinva %bc
145	nop
146	.chip 68k
147	jra .Lreincarnate
148
1494:
150	btst #CPUB_68060,%d1
151	jne 3b
152
153.Lreincarnate:
154	jmp %a1@
155
156relocate_new_kernel_end:
157
158ENTRY(relocate_new_kernel_size)
159	.long relocate_new_kernel_end - relocate_new_kernel
160