xref: /openbsd-src/sys/arch/arm/arm/locore.S (revision 8162193374858e8d7dceca506657f13b21b8be44)
1/*	$OpenBSD: locore.S,v 1.23 2022/12/08 01:25:44 guenther Exp $	*/
2/*	$NetBSD: locore.S,v 1.14 2003/04/20 16:21:40 thorpej Exp $	*/
3
4/*
5 * Copyright (C) 1994-1997 Mark Brinicombe
6 * Copyright (C) 1994 Brini
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by Brini.
20 * 4. The name of Brini may not be used to endorse or promote products
21 *    derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include "assym.h"
36
37#include <sys/syscall.h>
38#include <sys/errno.h>
39
40#include <machine/asm.h>
41#include <machine/frame.h>
42#include <arm/armreg.h>
43#include <arm/sysreg.h>
44#include <arm/pte.h>
45
46/* What size should this really be ? It is only used by init_arm() */
47#define INIT_ARM_STACK_SIZE	2048
48
49.arch_extension virt
50
51/*
52 * This is for kvm_mkdb, and should be the address of the beginning
53 * of the kernel text segment (not necessarily the same as kernbase).
54 */
55
56	.text
57	.align	2
58
59ENTRY_NP(kernel_text)
60
61ASENTRY_NP(start)
62	mov	r5, r1
63	mov	r6, r2
64	mov	r7, r3
65	adr	r1, .Lstart
66	ldmia	r1, {r1, r2, r8, sp}	/* Set initial stack and */
67
68	mcr	CP15_TPIDRPRW(r8)	/* put curcpu into the TPIDRPRW */
69
70	sub	r2, r2, r1		/* get zero init data */
71	mov	r3, #0
72
73.L1:
74	str	r3, [r1], #0x0004	/* Zero the bss */
75	subs	r2, r2, #4
76	bgt	.L1
77
78	mov	fp, #0x00000000		/* trace back starts here */
79	mov	r1, r5
80	mov	r2, r6
81	mov	r3, r7
82	bl	initarm			/* Off we go */
83
84	/* init arm will return the new stack pointer. */
85	mov	sp, r0
86
87	mov	fp, #0x00000000		/* trace back starts here */
88	mov	ip, sp
89	stmfd	sp!, {fp, ip, lr, pc}
90	sub	fp, ip, #4
91
92	bl	main			/* call main()! */
93
94	adr	r0, .Lmainreturned
95	b	panic
96	/* NOTREACHED */
97
98.Lstart:
99	.word	_edata
100	.word	_end
101	.word	cpu_info_primary
102	.word	svcstk + INIT_ARM_STACK_SIZE
103
104.Lmainreturned:
105	.asciz	"main() returned"
106	.align	2
107
108	.globl drop_to_pl1
109drop_to_pl1:
110	/* Drop to PL1 */
111	mrs	r0, cpsr
112	and	r0, r0, #(PSR_MODE)
113	teq	r0, #(PSR_HYP32_MODE)
114	beq	1f			/* If we are not in HYP, we're done */
115	mov	pc, lr
1161:
117	mrs	r0, cpsr
118	bic	r0, r0, #(PSR_MODE)
119	orr	r0, r0, #(PSR_SVC32_MODE)
120	orr	r0, r0, #(PSR_I | PSR_F | PSR_A)
121	msr	spsr_fsxc, r0
122	msr	ELR_hyp, lr
123	eret				/* Use the HYP LR to get into SVC */
124	dsb nsh
125	isb
126
127	.globl start_mmu
128start_mmu:
129	/* Set ASID to zero */
130	mov	r1, #0
131	mcr	CP15_CONTEXTIDR(r1)
132	isb
133
134	mcr	CP15_TTBR0(r0)		/* Set TTB */
135	mcr	CP15_TLBIALL(r0)	/* Flush TLB */
136
137	/* Set the Domain Access register.  Very important! */
138	mov     r0, #DOMAIN_CLIENT	/* We only use domain 0 */
139	mcr	CP15_DACR(r0)
140	isb
141
142	/* Enable MMU */
143	mrc	CP15_SCTLR(r0)
144	orr	r0, r0, #CPU_CONTROL_MMU_ENABLE
145	mcr	CP15_SCTLR(r0)
146	isb
147
148	mov	pc, lr
149
150#ifdef MULTIPROCESSOR
151
152	.globl cpu_hatch
153cpu_hatch:
154	/* Drop to PL1 */
155	bl	drop_to_pl1
156
157	/* Convert virt -> phys */
158	mov r9, pc
159	and r9, r9, #0xf0000000
160
161	/* Set up CPU info */
162	adr	r0, .Lcpu_hatch_ci
163	ldr	r0, [r0]
164	bic	r0, r0, #0xf0000000
165	orr	r0, r0, r9
166	ldr	r0, [r0]
167	ldr	r1, [r0, #CI_SELF]
168	mcr	CP15_TPIDRPRW(r1)
169	ldr	r8, [r0, #CI_TTBR0]
170
171	/* Enable the mmu */
172	orr	r0, r9, #0x00200000
173	bl	start_mmu
174
175	adr	r1, .Lcpu_hatch_virt
176	ldr	pc, [r1]
177
178cpu_hatch_virt:
179	mcr	CP15_TTBR0(r8)		/* Set TTB */
180	mcr	CP15_TLBIALL(r8)	/* Flush TLB */
181
182	mrc	CP15_TPIDRPRW(r0)
183	ldr	r1, [r0, #CI_PL1_STKEND]
184	mov	sp, r1
185
186	adr	r1, .Lcpu_start_secondary
187	ldr	pc, [r1]
188
189	b	.
190
191.Lcpu_hatch_virt:
192	.word	cpu_hatch_virt
193.Lcpu_start_secondary:
194	.word	cpu_start_secondary
195.Lcpu_hatch_ci:
196	.word	cpu_hatch_ci
197
198	.data
199	.align	2
200	.global cpu_hatch_ci
201cpu_hatch_ci:
202	.word	0
203
204#endif
205
206	.bss
207	.align	3
208svcstk:
209	.space	INIT_ARM_STACK_SIZE
210
211	.text
212	.align	2
213
214#ifndef OFW
215	/* OFW based systems will use OF_boot() */
216
217.Lcpufuncs:
218	.word	cpufuncs
219
220ENTRY_NP(cpu_reset)
221	mrs     r2, cpsr
222	bic	r2, r2, #(PSR_MODE)
223	orr     r2, r2, #(PSR_SVC32_MODE)
224	orr	r2, r2, #(PSR_I | PSR_F)
225	msr     cpsr_c, r2
226
227	ldr	r4, .Lcpu_reset_address
228	ldr	r4, [r4]
229
230	ldr	r0, .Lcpufuncs
231	mov	lr, pc
232	ldr	pc, [r0, #CF_IDCACHE_WBINV_ALL]
233
234	/*
235 	 * MMU & IDC off, 32 bit program & data space
236	 * Hurl ourselves into the ROM
237	 */
238	mov	r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
239	mov	r2, #0
240	mcr	CP15_SCTLR(r0)
241	mcr	CP15_TLBIALL(r2) 	/* nail I+D TLB */
242	mov	pc, r4
243
244	/*
245	 * _cpu_reset_address contains the address to branch to, to complete
246	 * the cpu reset after turning the MMU off
247	 * This variable is provided by the hardware specific code
248	 */
249.Lcpu_reset_address:
250	.word	cpu_reset_address
251
252#endif	/* OFW */
253
254#ifdef DDB
255/*
256 * setjump + longjmp
257 */
258ENTRY(setjmp)
259	stmia	r0, {r4-r14}
260	mov	r0, #0x00000000
261	mov	pc, lr
262
263ENTRY(longjmp)
264	ldmia	r0, {r4-r14}
265	mov	r0, #0x00000001
266	mov	pc, lr
267#endif /* DDB */
268
269	.data
270	.align	2
271	.global esym
272esym:		.word	end
273
274ENTRY_NP(abort)
275	b	abort
276