xref: /netbsd-src/sys/arch/hpcarm/hpcarm/locore.S (revision 590893a92f09f4131bf06799c509b6c5c2f07b97)
1/*	$NetBSD: locore.S,v 1.20 2020/08/28 12:41:17 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_cputypes.h"
35#include "assym.h"
36#include <sys/syscall.h>
37#include <sys/errno.h>
38#include <machine/asm.h>
39#include <machine/frame.h>
40#if defined(CPU_XSCALE_PXA250) || defined(CPU_XSCALE_PXA270)
41#include <arm/armreg.h>
42#endif
43
44
45/* What size should this really be ? It is only used by initarm() */
46#define INIT_ARM_STACK_SIZE	2048
47
48/*
49 * This is for kvm_mkdb, and should be the address of the beginning
50 * of the kernel text segment (not necessarily the same as kernbase).
51 */
52
53ENTRY_NP(kernel_text)
54
55ASENTRY_NP(start)
56	/* Put the processer in SVC mode */
57	mov	r5, sp
58	mrs	r4, cpsr
59	bic	r4, r4, #(PSR_MODE)
60	orr	r4, r4, #(PSR_SVC32_MODE)
61	msr	cpsr_all, r4
62	mov	sp, r5
63
64	/* Disable PID virtual address mapping */
65	mov	r4, #0
66	mcr	p15, 0, r4, c13, c0, 0
67
68#if defined(CPU_XSCALE_PXA250) || defined(CPU_XSCALE_PXA270)
69/*
70 * CPWAIT -- Canonical method to wait for CP15 update.
71 * NOTE: Clobbers the specified temp reg.
72 * copied from arm/arm/cpufunc_asm_xscale.S
73 * XXX: better be in a common header file.
74 */
75#define	CPWAIT_BRANCH							 \
76	sub	pc, pc, #4
77
78#define	CPWAIT(tmp)							 \
79	mrc	p15, 0, tmp, c2, c0, 0	/* arbitrary read of CP15 */	;\
80	mov	tmp, tmp		/* wait for it to complete */	;\
81	CPWAIT_BRANCH			/* branch to next insn */
82
83	/*
84	 *  Kernel is loaded in SDRAM (0xa0200000..), and is expected to run
85	 *  in VA 0xc0200000..
86	 */
87
88	/* build page table from scratch */
89	adr	r9, .Lstartup_pagetable
90	ldr	r9, [r9]
91	adr	r4, .Lmmu_init_table
92	b	3f
93
942:
95	str	r8, [r9, r7]
96	add	r7, r7, #4
97	add	r8, r8, #(L1_S_SIZE)
98	subs	r6, r6, #1
99	bne	2b
1003:
101	ldmia	r4!, {r6,r7,r8}		/* # of sections, VA, PA|attr */
102	cmp	r6, #0
103	bne	2b
104
105	/* Set translation table */
106	mcr	p15, 0, r9, c2, c0, 0
107	mcr	p15, 0, r9, c8, c7, 0	/* flush I/D-TLBs */
108	CPWAIT(r9)
109
110	/* Set the Domain Access register.  Very important! */
111	mov	r9, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
112	mcr	p15, 0, r9, c3, c0, 0
113
114	/* Enable MMU */
115	mrc	p15, 0, r9, c1, c0, 0
116	orr	r9, r9, #CPU_CONTROL_SYST_ENABLE
117	orr	r9, r9, #CPU_CONTROL_MMU_ENABLE
118	mcr	p15, 0, r9, c1, c0, 0
119	CPWAIT(r9)
120
121	/* Jump to kernel code in TRUE VA */
122	ldr	r9, .Lhpc_start
123	mov	pc, r9
124
125.Lhpc_start:
126	.word	hpc_start
127
128#define MMU_INIT(va,pa,n_sec,attr)					\
129	.word	(n_sec);						\
130	.word	4 * ((va) >> L1_S_SHIFT);				\
131	.word	(pa)|(attr);
132
133.Lstartup_pagetable:
134	.word	0xa0004000
135
136.Lmmu_init_table:
137	/* fill all table VA==PA */
138	MMU_INIT(0x00000000, 0x00000000, 1<<(32-L1_S_SHIFT), L1_TYPE_S|L1_S_AP_KRW)
139	/* map SDRAM VA==PA, WT cacheable */
140	MMU_INIT(0xa0000000, 0xa0000000, 256, L1_TYPE_S|L1_S_C|L1_S_AP_KRW)
141	/* map VA 0xc0000000..0xcfffffff to PA 0xa0000000..0xafffffff */
142	MMU_INIT(0xc0000000, 0xa0000000, 256, L1_TYPE_S|L1_S_C|L1_S_AP_KRW)
143	.word	0,0,0	/* end of table */
144
145	.text
146	.align	0
147ASENTRY_NP(hpc_start)
148#endif	/* CPU_XSCALE_PXA250 | CPU_XSCALE_PXA270 */
149
150	adr	r5, .Lstart
151	ldmia	r5, {r3, r4, sp}	/* Set initial stack and */
152	sub	r4, r4, r3		/* get zero init data */
153
154	mov	r5, #0
155.L1:
156	str	r5, [r3], #4		/* Zero the bss */
157	subs	r4, r4, #4
158	bgt	.L1
159
160	mov	fp, #0x00000000		/* trace back starts here */
161	bl	_C_LABEL(initarm)	/* Off we go */
162
163	/* initarm will return the new stack pointer. */
164	mov	sp, r0
165
166	mov	fp, #0x00000000		/* trace back starts here */
167	mov	ip, sp
168	stmfd	sp!, {fp, ip, lr, pc}
169	sub	fp, ip, #4
170
171	/* Setup an initial trap frame for start_init to use */
172	PUSHFRAME
173	mov	r0, sp			/* parameter to main is trap frame */
174	bl	_C_LABEL(main)		/* Lets light the flame and start her up */
175	PULLFRAME			/* Pull the trap frame, now valid */
176	movs	pc, lr			/* Exit to user process */
177	/* Never gets here */
178	b	.
179
180.Lstart:
181	.word	_edata
182	.word	_end
183	.word	svcstk + INIT_ARM_STACK_SIZE
184
185	.bss
186svcstk:
187	.space	INIT_ARM_STACK_SIZE
188
189	.text
190	.align	0
191
192.Lcpufuncs:
193	.word	_C_LABEL(cpufuncs)
194
195ENTRY_NP(cpu_reset)
196	mrs     r2, cpsr
197	bic	r2, r2, #(PSR_MODE)
198	orr     r2, r2, #(PSR_SVC32_MODE)
199	orr	r2, r2, #(I32_bit | F32_bit)
200	msr     cpsr_all, r2
201
202	ldr	r4, .Lcpu_reset_address
203	ldr	r4, [r4]
204
205	ldr	r0, .Lcpufuncs
206	mov	lr, pc
207	ldr	pc, [r0, #CF_IDCACHE_WBINV_ALL]
208
209	/*
210 	 * MMU & IDC off, 32 bit program & data space
211	 * Hurl ourselves into the ROM
212	 */
213	mov	r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
214	mcr     p15, 0, r0, c1, c0, 0
215	mcr     p15, 0, r0, c8, c7, 0
216	mov     pc, r4
217
218	/*
219	 * _cpu_reset_address contains the address to branch to, to complete
220	 * the CPU reset after turning the MMU off
221	 * This variable is provided by the hardware specific code
222	 */
223
224.Lcpu_reset_address:
225	.word	_C_LABEL(cpu_reset_address)
226
227/*
228 * setjump + longjmp
229 */
230ENTRY(setjmp)
231	stmia	r0, {r4-r14}
232	mov	r0, #0x00000000
233	mov	pc, lr
234
235ENTRY(longjmp)
236	ldmia	r0, {r4-r14}
237	mov	r0, #0x00000001
238	mov	pc, lr
239
240	.data
241	.global _C_LABEL(esym)
242_C_LABEL(esym):	.word	_C_LABEL(end)
243
244ENTRY_NP(abort)
245	b	_C_LABEL(abort)
246
247/*
248 * part of doing a system dump, we need to save registers and cpsr onto the
249 * stack, then save the rest of the registers into the dumppcb
250 */
251ENTRY(dumpsys)
252	/* push registers onto stack */
253	stmfd	sp!, {r0-r7, lr}
254
255	/* push the status bits onto the stack */
256	mrs	r0, cpsr
257	stmfd	sp!, {r0}
258
259	/* fill in dumppcb */
260	ldr	r0, .Ldumppcb
261
262#ifndef __XSCALE__
263        add     r2, r0, #(PCB_R8)
264        stmia   r2, {r8-r13}
265#else
266        strd    r8, r9, [r0, #(PCB_R8)]
267        strd    r10, r11, [r0, #(PCB_R10)]
268        strd    r12, r13, [r0, #(PCB_R12)]
269#endif
270
271	bl	_C_LABEL(dodumpsys)
272
273	/* unwind the stack */
274	ldmfd	sp!, {r0}
275	nop
276	ldmfd	sp!, {r0-r7, pc}
277
278.Ldumppcb:
279	.word	_C_LABEL(dumppcb)
280
281/* End of locore.S */
282