xref: /plan9/sys/src/9/bcm/rebootcode.s (revision 5d9de2d38d2503efca29e12e0e32036368a7a75f)
1*5d9de2d3SDavid du Colombier/*
2*5d9de2d3SDavid du Colombier * armv6 reboot code
3*5d9de2d3SDavid du Colombier */
4*5d9de2d3SDavid du Colombier#include "arm.s"
5*5d9de2d3SDavid du Colombier
6*5d9de2d3SDavid du Colombier/*
7*5d9de2d3SDavid du Colombier * Turn off MMU, then copy the new kernel to its correct location
8*5d9de2d3SDavid du Colombier * in physical memory.  Then jump to the start of the kernel.
9*5d9de2d3SDavid du Colombier */
10*5d9de2d3SDavid du Colombier
11*5d9de2d3SDavid du Colombier/* main(PADDR(entry), PADDR(code), size); */
12*5d9de2d3SDavid du ColombierTEXT	main(SB), 1, $-4
13*5d9de2d3SDavid du Colombier	MOVW	$setR12(SB), R12
14*5d9de2d3SDavid du Colombier
15*5d9de2d3SDavid du Colombier	/* copy in arguments before stack gets unmapped */
16*5d9de2d3SDavid du Colombier	MOVW	R0, R8			/* entry point */
17*5d9de2d3SDavid du Colombier	MOVW	p2+4(FP), R9		/* source */
18*5d9de2d3SDavid du Colombier	MOVW	n+8(FP), R10		/* byte count */
19*5d9de2d3SDavid du Colombier
20*5d9de2d3SDavid du Colombier	/* SVC mode, interrupts disabled */
21*5d9de2d3SDavid du Colombier	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R1
22*5d9de2d3SDavid du Colombier	MOVW	R1, CPSR
23*5d9de2d3SDavid du Colombier
24*5d9de2d3SDavid du Colombier	/* prepare to turn off mmu  */
25*5d9de2d3SDavid du Colombier	BL	cachesoff(SB)
26*5d9de2d3SDavid du Colombier
27*5d9de2d3SDavid du Colombier	/* turn off mmu */
28*5d9de2d3SDavid du Colombier	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
29*5d9de2d3SDavid du Colombier	BIC	$CpCmmu, R1
30*5d9de2d3SDavid du Colombier	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
31*5d9de2d3SDavid du Colombier
32*5d9de2d3SDavid du Colombier	/* set up a tiny stack for local vars and memmove args */
33*5d9de2d3SDavid du Colombier	MOVW	R8, SP			/* stack top just before kernel dest */
34*5d9de2d3SDavid du Colombier	SUB	$20, SP			/* allocate stack frame */
35*5d9de2d3SDavid du Colombier
36*5d9de2d3SDavid du Colombier	/* copy the kernel to final destination */
37*5d9de2d3SDavid du Colombier	MOVW	R8, 16(SP)		/* save dest (entry point) */
38*5d9de2d3SDavid du Colombier	MOVW	R8, R0			/* first arg is dest */
39*5d9de2d3SDavid du Colombier	MOVW	R9, 8(SP)		/* push src */
40*5d9de2d3SDavid du Colombier	MOVW	R10, 12(SP)		/* push size */
41*5d9de2d3SDavid du Colombier	BL	memmove(SB)
42*5d9de2d3SDavid du Colombier	MOVW	16(SP), R8		/* restore entry point */
43*5d9de2d3SDavid du Colombier
44*5d9de2d3SDavid du Colombier	/* jump to kernel physical entry point */
45*5d9de2d3SDavid du Colombier	B	(R8)
46*5d9de2d3SDavid du Colombier	B	0(PC)
47*5d9de2d3SDavid du Colombier
48*5d9de2d3SDavid du Colombier/*
49*5d9de2d3SDavid du Colombier * turn the caches off, double map PHYSDRAM & KZERO, invalidate TLBs, revert
50*5d9de2d3SDavid du Colombier * to tiny addresses.  upon return, it will be safe to turn off the mmu.
51*5d9de2d3SDavid du Colombier * clobbers R0-R2, and returns with SP invalid.
52*5d9de2d3SDavid du Colombier */
53*5d9de2d3SDavid du ColombierTEXT cachesoff(SB), 1, $-4
54*5d9de2d3SDavid du Colombier
55*5d9de2d3SDavid du Colombier	/* write back and invalidate caches */
56*5d9de2d3SDavid du Colombier	BARRIERS
57*5d9de2d3SDavid du Colombier	MOVW	$0, R0
58*5d9de2d3SDavid du Colombier	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEall
59*5d9de2d3SDavid du Colombier	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
60*5d9de2d3SDavid du Colombier
61*5d9de2d3SDavid du Colombier	/* turn caches off */
62*5d9de2d3SDavid du Colombier	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
63*5d9de2d3SDavid du Colombier	BIC	$(CpCdcache|CpCicache|CpCpredict), R1
64*5d9de2d3SDavid du Colombier	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
65*5d9de2d3SDavid du Colombier
66*5d9de2d3SDavid du Colombier	/* invalidate stale TLBs before changing them */
67*5d9de2d3SDavid du Colombier	BARRIERS
68*5d9de2d3SDavid du Colombier	MOVW	$KZERO, R0			/* some valid virtual address */
69*5d9de2d3SDavid du Colombier	MCR	CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
70*5d9de2d3SDavid du Colombier	BARRIERS
71*5d9de2d3SDavid du Colombier
72*5d9de2d3SDavid du Colombier	/* from here on, R0 is base of physical memory */
73*5d9de2d3SDavid du Colombier	MOVW	$PHYSDRAM, R0
74*5d9de2d3SDavid du Colombier
75*5d9de2d3SDavid du Colombier	/* redo double map of first MiB PHYSDRAM = KZERO */
76*5d9de2d3SDavid du Colombier	MOVW	$(L1+L1X(PHYSDRAM)), R2		/* address of PHYSDRAM's PTE */
77*5d9de2d3SDavid du Colombier	MOVW	$PTEDRAM, R1			/* PTE bits */
78*5d9de2d3SDavid du Colombier	ORR	R0, R1				/* dram base */
79*5d9de2d3SDavid du Colombier	MOVW	R1, (R2)
80*5d9de2d3SDavid du Colombier
81*5d9de2d3SDavid du Colombier	/* invalidate stale TLBs again */
82*5d9de2d3SDavid du Colombier	BARRIERS
83*5d9de2d3SDavid du Colombier	MCR	CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
84*5d9de2d3SDavid du Colombier	BARRIERS
85*5d9de2d3SDavid du Colombier
86*5d9de2d3SDavid du Colombier	/* relocate SB and return address to PHYSDRAM addressing */
87*5d9de2d3SDavid du Colombier	MOVW	$KSEGM, R1		/* clear segment bits */
88*5d9de2d3SDavid du Colombier	BIC	R1, R12			/* adjust SB */
89*5d9de2d3SDavid du Colombier	ORR	R0, R12
90*5d9de2d3SDavid du Colombier	BIC	R1, R14			/* adjust return address */
91*5d9de2d3SDavid du Colombier	ORR	R0, R14
92*5d9de2d3SDavid du Colombier
93*5d9de2d3SDavid du Colombier	RET
94