xref: /plan9-contrib/sys/src/9/vt4/rebootcode.s (revision 272efad760864ee41cfe633b56aea9b4f5cf3ae7)
1/* virtex4 ppc405 reboot code */
2#include "mem.h"
3
4#define SPR_SRR0	26		/* Save/Restore Register 0 */
5#define SPR_SRR1	27		/* Save/Restore Register 1 */
6#define SPR_DCWR	954		/* Data Cache Write-through Register */
7#define SPR_DCCR	1018		/* Data Cache Cachability Register */
8#define SPR_ICCR	1019		/* Instruction Cache Cachability Register */
9
10/* special instruction definitions */
11#define	BDNZ	BC	16,0,
12#define	BDNE	BC	0,2,
13
14#define	ICCCI(a,b)	WORD	$((31<<26)|((a)<<16)|((b)<<11)|(966<<1))
15#define	DCCCI(a,b)	WORD	$((31<<26)|((a)<<16)|((b)<<11)|(454<<1))
16
17/* on the 400 series, the prefetcher madly fetches across RFI, sys call, and others; use BR 0(PC) to stop */
18#define	RFI	WORD $((19<<26)|(50<<1)); BR 0(PC)
19#define	RFCI	WORD $((19<<26)|(51<<1)); BR 0(PC)
20
21/* print progress character.  steps on R7 and R8, needs SB set. */
22#define PROG(c)	MOVW $(Uartlite+4), R7; MOVW $(c), R8; MOVW	R8, 0(R7); SYNC
23
24/*
25 * Turn off MMU, then copy the new kernel to its correct location
26 * in physical memory.  Then jump to the start of the kernel.
27 */
28
29	NOSCHED
30
31TEXT	main(SB),1,$-4
32	MOVW	$setSB+KZERO(SB), R2
33
34PROG('*')
35	MOVW	R3, p1+0(FP)		/* destination, passed in R3 */
36	MOVW	R3, R6			/* entry point */
37	MOVW	p2+4(FP), R4		/* source */
38	MOVW	n+8(FP), R5		/* byte count */
39
40	BL	mmuoff(SB)
41	MOVW	$setSB(SB), R2
42
43//	BL	resetcaches(SB)
44
45PROG('*')
46	MOVW	R3, R1			/* tiny trampoline stack */
47	SUB	$0x20, R1		/* bypass a.out header */
48
49	MOVWU	R0, -48(R1)		/* allocate stack frame */
50	MOVW	R3, 44(R1)		/* save dest */
51	MOVW	R5, 40(R1)		/* save count */
52	MOVW	R3, 0(R1)
53	MOVW	R3, 4(R1)		/* push dest */
54	MOVW	R4, 8(R1)		/* push src */
55	MOVW	R5, 12(R1)		/* push size */
56	BL	memmove(SB)
57	SYNC
58	MOVW	44(R1), R6		/* restore R6 (dest) */
59	MOVW	40(R1), R5		/* restore R5 (count) */
60PROG('-')
61	/*
62	 * flush data cache
63	 */
64	MOVW	R6, R3			/* virtaddr */
65	MOVW	R5, R4			/* count */
66	RLWNM	$0, R3, $~(DCACHELINESZ-1), R5
67	CMP	R4, $0
68	BLE	dcf1
69	SUB	R5, R3
70	ADD	R3, R4
71	ADD	$(DCACHELINESZ-1), R4
72	SRAW	$DCACHELINELOG, R4
73	MOVW	R4, CTR
74dcf0:	DCBF	(R5)
75	ADD	$DCACHELINESZ, R5
76	BDNZ	dcf0
77dcf1:
78	SYNC
79
80	/* be sure icache is cleared */
81	BL	resetcaches(SB)
82
83/*
84 * jump to kernel entry point.  Note the true kernel entry point is
85 * the virtual address KZERO|R6, but this must wait until
86 * the MMU is enabled by the kernel in l.s
87 */
88	OR	R6, R6		/* NOP: avoid link bug */
89	MOVW	R6, LR
90PROG('>')
91PROG('\r');
92PROG('\n');
93	BL	(LR)
94	BR	0(PC)
95
96TEXT	mmuoff(SB), 1, $-4
97	MOVW	LR, R7
98	RLWNM	$0, R7, $~KZERO, R7	/* new PC */
99	MOVW	R7, SPR(SPR_SRR0)
100
101	RLWNM	$0, R1, $~KZERO, R1	/* make stack pointer physical */
102
103	/*
104	 * turn off interrupts & MMU
105	 * disable machine check
106	 */
107	MOVW	MSR, R7
108	RLWNM	$0, R7, $~(MSR_EE), R7
109	RLWNM	$0, R7, $~(MSR_ME), R7
110	RLWNM	$0, R7, $~(MSR_IR|MSR_DR), R7
111	MOVW	R7, SPR(SPR_SRR1)
112/*	ISYNC		/* no ISYNC here as we have no TLB entry for the PC */
113	SYNC		/* fix 405 errata cpu_210 */
114	RFI		/* resume in kernel mode in caller */
115
116/* clobbers R7 */
117TEXT	resetcaches(SB),1,$-4
118	/*
119	 * reset the caches and disable them
120	 */
121	MOVW	R0, SPR(SPR_ICCR)
122	ICCCI(0, 2)  /* errata cpu_121 reveals that EA is used; we'll use SB */
123	ISYNC
124	DCCCI(0, 0)
125	SYNC; ISYNC
126
127	MOVW	$((DCACHEWAYSIZE/DCACHELINESZ)-1), R7
128	MOVW	R7, CTR
129	MOVW	R0, R7
130dcinv:
131	DCCCI(0,7)
132	ADD	$32, R7
133	BDNZ	dcinv
134
135	/* cache is copy-back, disabled */
136	MOVW	R0, SPR(SPR_DCWR)
137	MOVW	R0, SPR(SPR_DCCR)
138	MOVW	R0, SPR(SPR_ICCR)
139	ISYNC
140	SYNC
141	BR	(LR)
142