xref: /netbsd-src/sys/arch/arm/arm32/locore.S (revision e65a0eaa66f2baacfbf4ae60f2f7b641eb98db8d)
1/*	$NetBSD: locore.S,v 1.44 2022/04/02 11:16:07 skrll Exp $	*/
2
3/*
4 * Copyright (C) 1994-1997 Mark Brinicombe
5 * Copyright (C) 1994 Brini
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by Brini.
19 * 4. The name of Brini may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include "opt_arm_debug.h"
35
36#include "assym.h"
37#include <sys/cdefs.h>
38#include <sys/syscall.h>
39#include <sys/errno.h>
40#include <arm/asm.h>
41#include <arm/locore.h>
42
43	RCSID("$NetBSD: locore.S,v 1.44 2022/04/02 11:16:07 skrll Exp $")
44
45/*
46 * This is for kvm_mkdb, and should be the address of the beginning
47 * of the kernel text segment (not necessarily the same as kernbase).
48 */
49
50	.text
51	.align	0
52
53ENTRY_NP(kernel_text)
54
55ASENTRY_NP(start)
56	mrs	r1, cpsr		/* fetch CPSR value */
57	msr	spsr_sx, r1		/* set SPSR[23:8] to known value */
58
59	/*
60	 * Get bss bounds (r1, r2), curlwp or curcpu (r8), and set initial
61	 * stack.
62	 */
63	adr	r1, .Lstart
64	ldmia	r1, {r1, r2, r8, sp}
65
66#if defined(TPIDRPRW_IS_CURCPU) || defined(TPIDRPRW_IS_CURLWP)
67	mcr	p15, 0, r8, c13, c0, 4
68#endif
69#if defined(TPIDRPRW_IS_CURLWP)
70	ldr	r8, [r8, #L_CPU]	/* r8 needs curcpu in it */
71#endif
72
73	mov	r4, #0
74#ifdef _ARM_ARCH_DWORD_OK
75	mov	r5, #0
76#endif
77.L1:
78#ifdef _ARM_ARCH_DWORD_OK
79	strd	r4, r5, [r1], #0x0008	/* Zero the bss */
80#else
81	str	r4, [r1], #0x0004	/* Zero the bss */
82#endif
83	cmp	r1, r2
84	blt	.L1
85
86	mrc	p15, 0, r3, c0, c0, 0	/* get our cpuid and save it early */
87	str	r3, [r8, #CI_ARM_CPUID]
88
89	mov	fp, #0x00000000		/* trace back starts here */
90	bl	_C_LABEL(initarm)	/* Off we go */
91
92	/* initarm will return the new stack pointer. */
93	mov	sp, r0
94
95	mov	fp, #0x00000000		/* trace back starts here */
96	mov	ip, sp
97	push	{fp, ip, lr, pc}
98	sub	fp, ip, #4
99
100	bl	_C_LABEL(main)		/* call main()! */
101
102	adr	r0, .Lmainreturned
103	b	_C_LABEL(panic)
104	/* NOTREACHED */
105
106ENTRY_NP(uartputc)
107#ifdef EARLYCONS
108	b	___CONCAT(EARLYCONS, _platform_early_putchar)
109#endif
110	RET
111ASEND(uartputc)
112
113.Lstart:
114	.word	_edata
115	.word	_end
116#if defined(TPIDRPRW_IS_CURLWP)
117	.word	_C_LABEL(lwp0)
118#else
119	.word	_C_LABEL(cpu_info_store)
120#endif
121#if !defined(__HAVE_GENERIC_START)
122	.word	svcstk_end
123#else
124	.word   start_stacks_top
125#endif
126
127.Lmainreturned:
128	.asciz	"main() returned"
129	.align	0
130ASEND(start)
131
132#if !defined(__HAVE_GENERIC_START)
133	.bss
134#ifdef __ARM_EABI__
135	.align	3
136#endif
137/* What size should this really be ? It is only used by initarm() */
138svcstk:
139	.space	INIT_ARM_STACK_SIZE
140svcstk_end:
141#endif
142
143	.text
144	.align	0
145
146#ifndef OFW
147	/* OFW based systems will used OF_boot() */
148
149.Lcpufuncs:
150	.word	_C_LABEL(cpufuncs)
151
152ENTRY_NP(cpu_reset)
153#ifdef _ARM_ARCH_6
154	cpsid	if, #PSR_SVC32_MODE
155#else
156	mrs     r2, cpsr
157	bic	r2, r2, #(PSR_MODE)
158	orr     r2, r2, #(PSR_SVC32_MODE)
159	orr	r2, r2, #(IF32_bits)
160	msr     cpsr_c, r2
161#endif
162
163	ldr	r0, .Lcpufuncs
164	mov	lr, pc
165	ldr	pc, [r0, #CF_IDCACHE_WBINV_ALL]
166
167	/*
168	 * Load the virutal address of the MD reset function first.
169	 */
170	ldr	r4, .Lcpu_reset_address
171	ldr	r4, [r4]
172	cmp	r4, #0
173
174	/*
175	 * If virtual address is NULL, we must be using the physical address
176	 */
177	ldreq	r4, .Lcpu_reset_address_paddr
178	ldreq	r4, [r4]
179
180	/*
181 	 * MMU & IDC off, 32 bit program & data space
182	 * Hurl ourselves into the ROM
183	 */
184	mrc	p15, 0, r0, c1, c0, 0
185	bic	r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE)
186	bic	r0, r0, #(CPU_CONTROL_IC_ENABLE)
187	orr	r0, r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
188	mcr	p15, 0, r0, c1, c0, 0
189	mcreq	p15, 0, r2, c8, c7, 0 	/* nail I+D TLB on ARMv4 and greater */
190	mov     pc, r4
191
192	/*
193	 * cpu_reset_address contains the address to branch to, to complete
194	 * the CPU reset after turning the MMU off
195	 * This variable is provided by the hardware specific code
196	 */
197.Lcpu_reset_address:
198	.word	_C_LABEL(cpu_reset_address)
199.Lcpu_reset_address_paddr:
200	.word	_C_LABEL(cpu_reset_address_paddr)
201END(cpu_reset)
202#endif	/* OFW */
203
204
205/*
206 * int cpu_set_onfault(struct faultbuf *fb)
207 */
208ENTRY_NP(cpu_set_onfault)
209	GET_CURPCB(r1)
210	str	r0, [r1, #PCB_ONFAULT]
211	stmia	r0, {r4-r14}
212	mov	r0, #0
213	RET
214END(cpu_set_onfault)
215
216/*
217 * setjump + longjmp
218 */
219ENTRY(setjmp)
220	stmia	r0, {r4-r14}
221	mov	r0, #0x00000000
222	RET
223END(setjmp)
224
225ENTRY(longjmp)
226	ldmia	r0, {r4-r14}
227	mov	r0, #0x00000001
228	RET
229END(longjmp)
230
231	.data
232	.global _C_LABEL(esym)
233_C_LABEL(esym):	.word	_C_LABEL(end)
234
235ENTRY_NP(abort)
236	b	_C_LABEL(abort)
237END(abort)
238
239/*
240 * Part of doing a system dump, we need to save a switchframe onto the
241 * stack, then save the rest of the registers into the dumppcb.
242 */
243ENTRY(dumpsys)
244	/* push registers onto stack */
245	mov	ip, sp
246	push	{r4-r7, ip, lr}
247
248	/* fill in dumppcb */
249	ldr	r0, .Ldumppcb
250
251#ifndef __XSCALE__
252        add     r2, r0, #(PCB_R8)
253        stmia   r2, {r8-r13}
254#else
255        strd    r8, r9, [r0, #(PCB_R8)]
256        strd    r10, r11, [r0, #(PCB_R10)]
257        strd    r12, r13, [r0, #(PCB_R12)]
258#endif
259
260	bl	_C_LABEL(dodumpsys)
261
262	/* unwind the stack */
263	pop	{r4-r7, ip, pc}
264
265.Ldumppcb:
266	.word	_C_LABEL(dumppcb)
267END(dumpsys)
268
269/* End of locore.S */
270