xref: /plan9-contrib/sys/src/9/vt5/rebootcode.s (revision 1c9d674cbfa2c1924558af05e99c43e5c5cd4845)
1*1c9d674cSDavid du Colombier/* virtex5 ppc440x5 reboot code */
2*1c9d674cSDavid du Colombier#include "mem.h"
3*1c9d674cSDavid du Colombier
4*1c9d674cSDavid du Colombier#define SPR_SRR0	26		/* Save/Restore Register 0 */
5*1c9d674cSDavid du Colombier#define SPR_SRR1	27		/* Save/Restore Register 1 */
6*1c9d674cSDavid du Colombier#define SPR_DBCR0	0x134		/* Debug Control Register 0 */
7*1c9d674cSDavid du Colombier#define SPR_DBCR1	0x135		/* Debug Control Register 1 */
8*1c9d674cSDavid du Colombier#define SPR_DBCR2	0x136		/* Debug Control Register 1 */
9*1c9d674cSDavid du Colombier#define SPR_DBSR	0x130		/* Debug Status Register */
10*1c9d674cSDavid du Colombier
11*1c9d674cSDavid du Colombier/* special instruction definitions */
12*1c9d674cSDavid du Colombier#define	BDNZ	BC	16,0,
13*1c9d674cSDavid du Colombier#define	BDNE	BC	0,2,
14*1c9d674cSDavid du Colombier
15*1c9d674cSDavid du Colombier#define	ICCCI(a,b)	WORD	$((31<<26)|((a)<<16)|((b)<<11)|(966<<1))
16*1c9d674cSDavid du Colombier#define	DCCCI(a,b)	WORD	$((31<<26)|((a)<<16)|((b)<<11)|(454<<1))
17*1c9d674cSDavid du Colombier
18*1c9d674cSDavid du Colombier/*
19*1c9d674cSDavid du Colombier * on the 400 series, the prefetcher madly fetches across RFI, sys call,
20*1c9d674cSDavid du Colombier * and others; use BR 0(PC) to stop.
21*1c9d674cSDavid du Colombier */
22*1c9d674cSDavid du Colombier#define	RFI	WORD	$((19<<26)|(50<<1)); BR 0(PC)
23*1c9d674cSDavid du Colombier#define	RFCI	WORD	$((19<<26)|(51<<1)); BR 0(PC)
24*1c9d674cSDavid du Colombier
25*1c9d674cSDavid du Colombier/* print progress character.  steps on R7 and R8, needs SB set. */
26*1c9d674cSDavid du Colombier#define PROG(c)	MOVW $(Uartlite+4), R7; MOVW $(c), R8; MOVW	R8, 0(R7); SYNC
27*1c9d674cSDavid du Colombier
28*1c9d674cSDavid du Colombier/*
29*1c9d674cSDavid du Colombier * copied to REBOOTADDR and executed there.
30*1c9d674cSDavid du Colombier * since it copies the new kernel over the old one, it is
31*1c9d674cSDavid du Colombier * self-contained and does not call any other kernel code.
32*1c9d674cSDavid du Colombier *
33*1c9d674cSDavid du Colombier * Turn off interrupts, then copy the new kernel to its correct location
34*1c9d674cSDavid du Colombier * in physical memory.  Then jump to the start of the kernel.
35*1c9d674cSDavid du Colombier * destination and source arguments are virtual addresses.
36*1c9d674cSDavid du Colombier */
37*1c9d674cSDavid du Colombier
38*1c9d674cSDavid du Colombier	NOSCHED
39*1c9d674cSDavid du Colombier
40*1c9d674cSDavid du ColombierTEXT	main(SB),1,$-4
41*1c9d674cSDavid du Colombier	MOVW	$setSB(SB), R2
42*1c9d674cSDavid du Colombier
43*1c9d674cSDavid du Colombier	MOVW	R3, p1+0(FP)		/* destination, passed in R3 */
44*1c9d674cSDavid du Colombier	MOVW	R3, R6			/* entry point */
45*1c9d674cSDavid du Colombier	MOVW	p2+4(FP), R4		/* source */
46*1c9d674cSDavid du Colombier	MOVW	n+8(FP), R5		/* byte count */
47*1c9d674cSDavid du Colombier
48*1c9d674cSDavid du Colombier	/* make it safe to copy over the old kernel */
49*1c9d674cSDavid du ColombierPROG('R')
50*1c9d674cSDavid du Colombier	BL	introff(SB)
51*1c9d674cSDavid du Colombier//	MOVW	$setSB(SB), R2
52*1c9d674cSDavid du Colombier
53*1c9d674cSDavid du ColombierPROG('e')
54*1c9d674cSDavid du Colombier//	BL	resetcaches(SB)
55*1c9d674cSDavid du Colombier
56*1c9d674cSDavid du Colombier	/* disable debug facilities */
57*1c9d674cSDavid du Colombier	ISYNC
58*1c9d674cSDavid du Colombier	MOVW	R0, SPR(SPR_DBCR0)
59*1c9d674cSDavid du Colombier	MOVW	R0, SPR(SPR_DBCR1)
60*1c9d674cSDavid du Colombier	MOVW	R0, SPR(SPR_DBCR2)
61*1c9d674cSDavid du Colombier	ISYNC
62*1c9d674cSDavid du Colombier	MOVW	$~0, R7
63*1c9d674cSDavid du Colombier	MOVW	R7, SPR(SPR_DBSR)
64*1c9d674cSDavid du Colombier	ISYNC
65*1c9d674cSDavid du Colombier
66*1c9d674cSDavid du Colombier	MOVW	R3, R1			/* tiny trampoline stack before dest */
67*1c9d674cSDavid du Colombier	SUB	$0x20, R1		/* bypass a.out header */
68*1c9d674cSDavid du Colombier
69*1c9d674cSDavid du Colombier	/* copy new kernel over the old */
70*1c9d674cSDavid du Colombier	MOVWU	R0, -48(R1)		/* allocate stack frame */
71*1c9d674cSDavid du Colombier	MOVW	R3, 44(R1)		/* save dest */
72*1c9d674cSDavid du Colombier	MOVW	R5, 40(R1)		/* save count */
73*1c9d674cSDavid du Colombier	MOVW	R3, 0(R1)
74*1c9d674cSDavid du Colombier	MOVW	R3, 4(R1)		/* push dest */
75*1c9d674cSDavid du Colombier	MOVW	R4, 8(R1)		/* push src */
76*1c9d674cSDavid du Colombier	MOVW	R5, 12(R1)		/* push size */
77*1c9d674cSDavid du ColombierPROG('s')
78*1c9d674cSDavid du Colombier	BL	memmove(SB)
79*1c9d674cSDavid du Colombier	SYNC
80*1c9d674cSDavid du Colombier	MOVW	44(R1), R6		/* restore dest */
81*1c9d674cSDavid du Colombier	MOVW	p2+4(FP), R4		/* restore source */
82*1c9d674cSDavid du Colombier	MOVW	40(R1), R5		/* restore count */
83*1c9d674cSDavid du Colombier
84*1c9d674cSDavid du Colombier	/* verify that we copied it correctly */
85*1c9d674cSDavid du ColombierPROG('t')
86*1c9d674cSDavid du Colombier	MOVW	R4, R10
87*1c9d674cSDavid du Colombier	MOVW	R6, R11
88*1c9d674cSDavid du Colombier	MOVW	R5, R12
89*1c9d674cSDavid du Colombier	SUB	$4, R10
90*1c9d674cSDavid du Colombier	SUB	$4, R11
91*1c9d674cSDavid du Colombiercmploop:
92*1c9d674cSDavid du Colombier	MOVWU	4(R10), R13
93*1c9d674cSDavid du Colombier	MOVWU	4(R11), R14
94*1c9d674cSDavid du Colombier	CMP	R13, R14
95*1c9d674cSDavid du Colombier	BNE	buggered
96*1c9d674cSDavid du Colombier	SUB	$4, R12
97*1c9d674cSDavid du Colombier	CMP	R12, R0
98*1c9d674cSDavid du Colombier	BGT	cmploop
99*1c9d674cSDavid du Colombier
100*1c9d674cSDavid du ColombierPROG('a')
101*1c9d674cSDavid du Colombier	ANDCC	$~KZERO, R6, R3		/* physical entry addr */
102*1c9d674cSDavid du Colombier
103*1c9d674cSDavid du Colombier	MOVW	R0, R4
104*1c9d674cSDavid du Colombier	SUB	$(4*2), R4		/* r4 is now points to bootstart */
105*1c9d674cSDavid du Colombier	MOVW	R3, 0(R4)		/* entry addr into bootstart */
106*1c9d674cSDavid du Colombier	SYNC
107*1c9d674cSDavid du Colombier	ISYNC
108*1c9d674cSDavid du Colombier
109*1c9d674cSDavid du ColombierPROG('r')
110*1c9d674cSDavid du Colombier	/*
111*1c9d674cSDavid du Colombier	 * flush data cache
112*1c9d674cSDavid du Colombier	 */
113*1c9d674cSDavid du Colombier	MOVW	R6, R3			/* virtaddr */
114*1c9d674cSDavid du Colombier	MOVW	R5, R4			/* count */
115*1c9d674cSDavid du Colombier	RLWNM	$0, R3, $~(DCACHELINESZ-1), R5
116*1c9d674cSDavid du Colombier	CMP	R4, R0
117*1c9d674cSDavid du Colombier	BLE	dcf1
118*1c9d674cSDavid du Colombier	SUB	R5, R3
119*1c9d674cSDavid du Colombier	ADD	R3, R4
120*1c9d674cSDavid du Colombier	ADD	$(DCACHELINESZ-1), R4
121*1c9d674cSDavid du Colombier	SRAW	$DCACHELINELOG, R4
122*1c9d674cSDavid du Colombier	MOVW	R4, CTR
123*1c9d674cSDavid du Colombierdcf0:	DCBF	(R5)
124*1c9d674cSDavid du Colombier	ADD	$DCACHELINESZ, R5
125*1c9d674cSDavid du Colombier	BDNZ	dcf0
126*1c9d674cSDavid du Colombierdcf1:
127*1c9d674cSDavid du Colombier	SYNC
128*1c9d674cSDavid du Colombier	ISYNC
129*1c9d674cSDavid du Colombier
130*1c9d674cSDavid du Colombier	/* be sure icache is cleared */
131*1c9d674cSDavid du Colombier	BL	resetcaches(SB)
132*1c9d674cSDavid du Colombier
133*1c9d674cSDavid du Colombier/*
134*1c9d674cSDavid du Colombier * jump to kernel entry point.  Note the true kernel entry point is
135*1c9d674cSDavid du Colombier * the virtual address R6, and the MMU is always enabled.
136*1c9d674cSDavid du Colombier */
137*1c9d674cSDavid du Colombier	OR	R6, R6		/* NOP: avoid link bug */
138*1c9d674cSDavid du Colombier	MOVW	R6, LR
139*1c9d674cSDavid du ColombierPROG('t')
140*1c9d674cSDavid du ColombierPROG('\r')
141*1c9d674cSDavid du ColombierPROG('\n')
142*1c9d674cSDavid du Colombier	BL	(LR)	/* without reset. leaves qtm, dram, etc. intact */
143*1c9d674cSDavid du Colombier	BR	0(PC)
144*1c9d674cSDavid du Colombier
145*1c9d674cSDavid du Colombier//	BR	reset
146*1c9d674cSDavid du Colombierbuggered:
147*1c9d674cSDavid du Colombier	PROG('C')
148*1c9d674cSDavid du Colombier	PROG('m')
149*1c9d674cSDavid du Colombier	PROG('p')
150*1c9d674cSDavid du Colombier	PROG(' ')
151*1c9d674cSDavid du Colombier	PROG('f')
152*1c9d674cSDavid du Colombier	PROG('a')
153*1c9d674cSDavid du Colombier	PROG('i')
154*1c9d674cSDavid du Colombier	PROG('l')
155*1c9d674cSDavid du Colombierreset:
156*1c9d674cSDavid du Colombier	ISYNC
157*1c9d674cSDavid du Colombier	MOVW	$(3<<28), R3
158*1c9d674cSDavid du Colombier	MOVW	R3, SPR(SPR_DBCR0)	/* cause a system reset */
159*1c9d674cSDavid du Colombier	ISYNC
160*1c9d674cSDavid du Colombier	BR	0(PC)
161*1c9d674cSDavid du Colombier
162*1c9d674cSDavid du ColombierTEXT	introff(SB), 1, $-4
163*1c9d674cSDavid du Colombier	MOVW	LR, R7
164*1c9d674cSDavid du Colombier	MOVW	R7, SPR(SPR_SRR0)
165*1c9d674cSDavid du Colombier
166*1c9d674cSDavid du Colombier	/*
167*1c9d674cSDavid du Colombier	 * turn off interrupts & MMU
168*1c9d674cSDavid du Colombier	 * disable machine check
169*1c9d674cSDavid du Colombier	 */
170*1c9d674cSDavid du Colombier	MOVW	MSR, R7
171*1c9d674cSDavid du Colombier	RLWNM	$0, R7, $~(MSR_EE), R7
172*1c9d674cSDavid du Colombier	RLWNM	$0, R7, $~(MSR_CE), R7
173*1c9d674cSDavid du Colombier	RLWNM	$0, R7, $~(MSR_DE), R7
174*1c9d674cSDavid du Colombier	RLWNM	$0, R7, $~(MSR_ME), R7
175*1c9d674cSDavid du Colombier	RLWNM	$0, R7, $~(MSR_IS|MSR_DS), R7
176*1c9d674cSDavid du Colombier	MOVW	R7, SPR(SPR_SRR1)
177*1c9d674cSDavid du Colombier	SYNC		/* fix 405 errata cpu_210 */
178*1c9d674cSDavid du Colombier	RFI		/* resume in kernel mode in caller */
179*1c9d674cSDavid du Colombier
180*1c9d674cSDavid du Colombier/*
181*1c9d674cSDavid du Colombier * reset the caches
182*1c9d674cSDavid du Colombier * clobbers R7
183*1c9d674cSDavid du Colombier */
184*1c9d674cSDavid du ColombierTEXT	resetcaches(SB),1,$-4
185*1c9d674cSDavid du Colombier	ICCCI(0, 2)  /* errata cpu_121 reveals that EA is used; we'll use SB */
186*1c9d674cSDavid du Colombier	ISYNC
187*1c9d674cSDavid du Colombier
188*1c9d674cSDavid du Colombier	MOVW	$(DCACHEWAYSIZE/DCACHELINESZ), R7
189*1c9d674cSDavid du Colombier	MOVW	R7, CTR
190*1c9d674cSDavid du Colombier	MOVW	$KZERO, R7
191*1c9d674cSDavid du Colombierdcinv:
192*1c9d674cSDavid du Colombier	DCBF	(R7)
193*1c9d674cSDavid du Colombier	ADD	$DCACHELINESZ, R7
194*1c9d674cSDavid du Colombier	BDNZ	dcinv
195*1c9d674cSDavid du Colombier
196*1c9d674cSDavid du Colombier	SYNC; ISYNC
197*1c9d674cSDavid du Colombier
198*1c9d674cSDavid du Colombier	BR	(LR)
199*1c9d674cSDavid du Colombier	BR	0(PC)
200