locore-v4.S revision 245414
1129198Scognet/*	$NetBSD: locore.S,v 1.14 2003/04/20 16:21:40 thorpej Exp $	*/
2129198Scognet
3139735Simp/*-
4239268Sgonzo * Copyright 2011 Semihalf
5129198Scognet * Copyright (C) 1994-1997 Mark Brinicombe
6129198Scognet * Copyright (C) 1994 Brini
7129198Scognet * All rights reserved.
8129198Scognet *
9129198Scognet * Redistribution and use in source and binary forms, with or without
10129198Scognet * modification, are permitted provided that the following conditions
11129198Scognet * are met:
12129198Scognet * 1. Redistributions of source code must retain the above copyright
13129198Scognet *    notice, this list of conditions and the following disclaimer.
14129198Scognet * 2. Redistributions in binary form must reproduce the above copyright
15129198Scognet *    notice, this list of conditions and the following disclaimer in the
16129198Scognet *    documentation and/or other materials provided with the distribution.
17129198Scognet * 3. All advertising materials mentioning features or use of this software
18129198Scognet *    must display the following acknowledgement:
19129198Scognet *	This product includes software developed by Brini.
20129198Scognet * 4. The name of Brini may not be used to endorse or promote products
21129198Scognet *    derived from this software without specific prior written permission.
22129198Scognet *
23129198Scognet * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
24129198Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25129198Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26129198Scognet * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27129198Scognet * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28129198Scognet * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29129198Scognet * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30129198Scognet * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31129198Scognet * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32129198Scognet * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33129198Scognet *
34129198Scognet */
35129198Scognet
36129198Scognet#include "assym.s"
37135640Scognet#include <sys/syscall.h>
38129198Scognet#include <machine/asm.h>
39129198Scognet#include <machine/armreg.h>
40129198Scognet#include <machine/pte.h>
41236524Simp
42129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/locore.S 245414 2013-01-14 09:11:18Z andrew $");
43129198Scognet
44159849Simp/* What size should this really be ? It is only used by initarm() */
45239268Sgonzo#define INIT_ARM_STACK_SIZE	(2048 * 4)
46129198Scognet
47129198Scognet#define	CPWAIT_BRANCH							 \
48129198Scognet	sub	pc, pc, #4
49129198Scognet
50129198Scognet#define	CPWAIT(tmp)							 \
51129198Scognet	mrc	p15, 0, tmp, c2, c0, 0	/* arbitrary read of CP15 */	;\
52129198Scognet	mov	tmp, tmp		/* wait for it to complete */	;\
53129198Scognet	CPWAIT_BRANCH			/* branch to next insn */
54129198Scognet
55235277Simp/*
56235277Simp * This is for kvm_mkdb, and should be the address of the beginning
57235277Simp * of the kernel text segment (not necessarily the same as kernbase).
58235277Simp */
59129198Scognet	.text
60129198Scognet	.align	0
61129198Scognet.globl kernbase
62129198Scognet.set kernbase,KERNBASE
63150863Scognet.globl physaddr
64150863Scognet.set physaddr,PHYSADDR
65129198Scognet
66183878Sraj/*
67236524Simp * On entry for FreeBSD boot ABI:
68236524Simp *	r0 - metadata pointer or 0 (boothowto on AT91's boot2)
69218227Smarcel *	r1 - if (r0 == 0) then metadata pointer
70236524Simp * On entry for Linux boot ABI:
71236524Simp *	r0 - 0
72236524Simp *	r1 - machine type (passed as arg2 to initarm)
73236524Simp *	r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm)
74236524Simp *
75236524Simp * For both types of boot we gather up the args, put them in a struct arm_boot_params
76236524Simp * structure and pass that to initarm.
77183878Sraj */
78236524SimpENTRY_NP(btext)
79218227SmarcelASENTRY_NP(_start)
80236524Simp	mov	r9, r0		/* 0 or boot mode from boot2 */
81236524Simp	mov	r8, r1		/* Save Machine type */
82236524Simp	mov	ip, r2		/* Save meta data */
83236524Simp	mov	fp, r3		/* Future expantion */
84183878Sraj
85193846Smarcel	/* Make sure interrupts are disabled. */
86193846Smarcel	mrs	r7, cpsr
87193846Smarcel	orr	r7, r7, #(I32_bit|F32_bit)
88193846Smarcel	msr	cpsr_c, r7
89193846Smarcel
90166819Scognet#if defined (FLASHADDR) && defined(LOADERRAMADDR)
91166819Scognet	/* Check if we're running from flash. */
92166819Scognet	ldr	r7, =FLASHADDR
93175983Sraj	/*
94166819Scognet	 * If we're running with MMU disabled, test against the
95166819Scognet	 * physical address instead.
96166819Scognet	 */
97166819Scognet	mrc     p15, 0, r2, c1, c0, 0
98166819Scognet	ands	r2, r2, #CPU_CONTROL_MMU_ENABLE
99236524Simp	ldreq	r6, =PHYSADDR
100236524Simp	ldrne	r6, =LOADERRAMADDR
101236524Simp	cmp	r7, r6
102166819Scognet	bls 	flash_lower
103166819Scognet	cmp	r7, pc
104166819Scognet	bhi	from_ram
105166819Scognet	b	do_copy
106166819Scognet
107166819Scognetflash_lower:
108236524Simp	cmp	r6, pc
109166819Scognet	bls	from_ram
110166819Scognetdo_copy:
111236524Simp	ldr	r7, =KERNBASE
112175983Sraj	adr	r1, _start
113166819Scognet	ldr	r0, Lreal_start
114166819Scognet	ldr	r2, Lend
115166819Scognet	sub	r2, r2, r0
116236524Simp	sub	r0, r0, r7
117236524Simp	add	r0, r0, r6
118166819Scognet	mov	r4, r0
119166819Scognet	bl	memcpy
120166819Scognet	ldr	r0, Lram_offset
121166819Scognet	add	pc, r4, r0
122166819ScognetLram_offset:	.word from_ram-_C_LABEL(_start)
123166819Scognetfrom_ram:
124166819Scognet	nop
125135640Scognet#endif
126135640Scognet	adr	r7, Lunmapped
127190602Scognet	bic     r7, r7, #0xf0000000
128153616Scognet	orr     r7, r7, #PHYSADDR
129143681Sjmg
130175983Sraj
131166819Scognetdisable_mmu:
132135640Scognet	/* Disable MMU for a while */
133143681Sjmg	mrc     p15, 0, r2, c1, c0, 0
134153550Scognet	bic	r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
135153550Scognet	    CPU_CONTROL_WBUF_ENABLE)
136153550Scognet	bic	r2, r2, #(CPU_CONTROL_IC_ENABLE)
137153550Scognet	bic	r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
138135640Scognet	mcr     p15, 0, r2, c1, c0, 0
139129198Scognet
140135640Scognet	nop
141135640Scognet	nop
142135640Scognet	nop
143135640Scognet	mov	pc, r7
144135640ScognetLunmapped:
145135640Scognet#ifdef STARTUP_PAGETABLE_ADDR
146129198Scognet	/* build page table from scratch */
147129198Scognet	ldr	r0, Lstartup_pagetable
148129198Scognet	adr	r4, mmu_init_table
149129198Scognet	b	3f
150129198Scognet
151129198Scognet2:
152129198Scognet	str	r3, [r0, r2]
153129198Scognet	add	r2, r2, #4
154129198Scognet	add	r3, r3, #(L1_S_SIZE)
155129198Scognet	adds	r1, r1, #-1
156129198Scognet	bhi	2b
157143681Sjmg3:
158172356Scognet	ldmia	r4!, {r1,r2,r3}   /* # of sections, VA, PA|attr */
159129198Scognet	cmp	r1, #0
160140683Scognet	adrne	r5, 2b
161190602Scognet	bicne	r5, r5, #0xf0000000
162140683Scognet	orrne	r5, r5, #PHYSADDR
163140683Scognet	movne	pc, r5
164129198Scognet
165239268Sgonzo#if defined(SMP)
166239268Sgonzo	orr 	r0, r0, #2		/* Set TTB shared memory flag */
167239268Sgonzo#endif
168129198Scognet	mcr	p15, 0, r0, c2, c0, 0	/* Set TTB */
169129198Scognet	mcr	p15, 0, r0, c8, c7, 0	/* Flush TLB */
170129198Scognet
171244480Sgonzo#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B)
172239268Sgonzo	mov	r0, #0
173239268Sgonzo	mcr	p15, 0, r0, c13, c0, 1	/* Set ASID to 0 */
174239268Sgonzo#endif
175239268Sgonzo
176129198Scognet	/* Set the Domain Access register.  Very important! */
177143681Sjmg	mov     r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
178129198Scognet	mcr	p15, 0, r0, c3, c0, 0
179129198Scognet	/* Enable MMU */
180129198Scognet	mrc	p15, 0, r0, c1, c0, 0
181244480Sgonzo#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B)
182239268Sgonzo	orr	r0, r0, #CPU_CONTROL_V6_EXTPAGE
183239268Sgonzo#endif
184243602Sgonzo	orr	r0, r0, #(CPU_CONTROL_MMU_ENABLE)
185129198Scognet	mcr	p15, 0, r0, c1, c0, 0
186153550Scognet	nop
187153550Scognet	nop
188153550Scognet	nop
189129198Scognet	CPWAIT(r0)
190129198Scognet
191153550Scognet#endif
192129198Scognetmmu_done:
193153550Scognet	nop
194129198Scognet	adr	r1, .Lstart
195129198Scognet	ldmia	r1, {r1, r2, sp}	/* Set initial stack and */
196129198Scognet	sub	r2, r2, r1		/* get zero init data */
197129198Scognet	mov	r3, #0
198129198Scognet.L1:
199150863Scognet	str	r3, [r1], #0x0004	/* get zero init data */
200129198Scognet	subs	r2, r2, #4
201129198Scognet	bgt	.L1
202153550Scognet	ldr	pc, .Lvirt_done
203129198Scognet
204142145Scognetvirt_done:
205236524Simp	mov	r1, #20			/* loader info size is 20 bytes also second arg */
206236524Simp	subs	sp, sp, r1		/* allocate arm_boot_params struct on stack */
207236524Simp	mov	r0, sp			/* loader info pointer is first arg */
208236524Simp	str	r1, [r0]		/* Store length of loader info */
209236524Simp	str	r9, [r0, #4]		/* Store r0 from boot loader */
210236524Simp	str	r8, [r0, #8]		/* Store r1 from boot loader */
211236524Simp	str	ip, [r0, #12]		/* store r2 from boot loader */
212236524Simp	str	fp, [r0, #16]		/* store r3 from boot loader */
213175983Sraj	mov	fp, #0			/* trace back starts here */
214129198Scognet	bl	_C_LABEL(initarm)	/* Off we go */
215129198Scognet
216129198Scognet	/* init arm will return the new stack pointer. */
217129198Scognet	mov	sp, r0
218129198Scognet
219129198Scognet	bl	_C_LABEL(mi_startup)		/* call mi_startup()! */
220129198Scognet
221129198Scognet	adr	r0, .Lmainreturned
222130164Sphk	b	_C_LABEL(panic)
223175983Sraj	/* NOTREACHED */
224129198Scognet#ifdef STARTUP_PAGETABLE_ADDR
225129198Scognet#define MMU_INIT(va,pa,n_sec,attr) \
226129198Scognet	.word	n_sec					    ; \
227129198Scognet	.word	4*((va)>>L1_S_SHIFT)			    ; \
228129198Scognet	.word	(pa)|(attr)				    ;
229129198Scognet
230150863ScognetLvirtaddr:
231150863Scognet	.word	KERNVIRTADDR
232150863ScognetLphysaddr:
233150863Scognet	.word	KERNPHYSADDR
234166819ScognetLreal_start:
235166819Scognet	.word	_start
236166819ScognetLend:
237166819Scognet	.word	_edata
238129198ScognetLstartup_pagetable:
239129198Scognet	.word	STARTUP_PAGETABLE_ADDR
240239268Sgonzo#ifdef SMP
241239268SgonzoLstartup_pagetable_secondary:
242239268Sgonzo	.word	temp_pagetable
243239268Sgonzo#endif
244143681Sjmgmmu_init_table:
245129198Scognet	/* fill all table VA==PA */
246129198Scognet	/* map SDRAM VA==PA, WT cacheable */
247239268Sgonzo#if !defined(SMP)
248135640Scognet	MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
249135640Scognet	/* map VA 0xc0000000..0xc3ffffff to PA */
250135640Scognet	MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
251239268Sgonzo#else
252239268Sgonzo	MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW))
253239268Sgonzo	/* map VA 0xc0000000..0xc3ffffff to PA */
254239268Sgonzo	MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW))
255239268Sgonzo	MMU_INIT(0x48000000, 0x48000000, 1, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW))
256239268Sgonzo#endif
257129198Scognet	.word 0	/* end of table */
258129198Scognet#endif
259129198Scognet.Lstart:
260129198Scognet	.word	_edata
261129198Scognet	.word	_end
262129198Scognet	.word	svcstk + INIT_ARM_STACK_SIZE
263129198Scognet
264153550Scognet.Lvirt_done:
265153550Scognet	.word	virt_done
266239268Sgonzo#if defined(SMP)
267239268Sgonzo.Lmpvirt_done:
268239268Sgonzo	.word	mpvirt_done
269239268Sgonzo#endif
270239268Sgonzo
271129198Scognet.Lmainreturned:
272129198Scognet	.asciz	"main() returned"
273129198Scognet	.align	0
274129198Scognet
275129198Scognet	.bss
276129198Scognetsvcstk:
277129198Scognet	.space	INIT_ARM_STACK_SIZE
278129198Scognet
279129198Scognet	.text
280129198Scognet	.align	0
281129198Scognet
282143681Sjmg.Lcpufuncs:
283129198Scognet	.word	_C_LABEL(cpufuncs)
284129198Scognet
285239268Sgonzo#if defined(SMP)
286239268SgonzoLsramaddr:
287239268Sgonzo	.word	0xffff0080
288239268Sgonzo
289239268Sgonzo#if 0
290239268Sgonzo#define	AP_DEBUG(tmp)			\
291239268Sgonzo	mrc	p15, 0, r1, c0, c0, 5;	\
292239268Sgonzo	ldr	r0, Lsramaddr;		\
293239268Sgonzo	add	r0, r1, lsl #2;		\
294239268Sgonzo	mov	r1, tmp;		\
295239268Sgonzo	str	r1, [r0], #0x0000;
296239268Sgonzo#else
297239268Sgonzo#define AP_DEBUG(tmp)
298239268Sgonzo#endif
299239268Sgonzo
300239268Sgonzo
301239268SgonzoASENTRY_NP(mptramp)
302239268Sgonzo	mov	r0, #0
303239268Sgonzo	mcr	p15, 0, r0, c7, c7, 0
304239268Sgonzo
305239268Sgonzo	AP_DEBUG(#1)
306239268Sgonzo
307239268Sgonzo	mrs	r3, cpsr_all
308239268Sgonzo	bic	r3, r3, #(PSR_MODE)
309239268Sgonzo	orr	r3, r3, #(PSR_SVC32_MODE)
310239268Sgonzo        msr	cpsr_all, r3
311239268Sgonzo
312239268Sgonzo	mrc	p15, 0, r0, c0, c0, 5
313239268Sgonzo	and	r0, #0x0f		/* Get CPU ID */
314239268Sgonzo
315239268Sgonzo	/* Read boot address for CPU */
316239268Sgonzo	mov	r1, #0x100
317239268Sgonzo	mul	r2, r0, r1
318239268Sgonzo	ldr	r1, Lpmureg
319239268Sgonzo	add	r0, r2, r1
320239268Sgonzo	ldr	r1, [r0], #0x00
321239268Sgonzo
322239268Sgonzo	mov pc, r1
323239268Sgonzo
324239268SgonzoLpmureg:
325239268Sgonzo        .word   0xd0022124
326239268Sgonzo
327239268SgonzoASENTRY_NP(mpentry)
328239268Sgonzo
329239268Sgonzo	AP_DEBUG(#2)
330239268Sgonzo
331239268Sgonzo	/* Make sure interrupts are disabled. */
332239268Sgonzo	mrs	r7, cpsr
333239268Sgonzo	orr	r7, r7, #(I32_bit|F32_bit)
334239268Sgonzo	msr	cpsr_c, r7
335239268Sgonzo
336239268Sgonzo
337239268Sgonzo	adr     r7, Ltag
338239268Sgonzo	bic     r7, r7, #0xf0000000
339239268Sgonzo	orr     r7, r7, #PHYSADDR
340239268Sgonzo
341239268Sgonzo	/* Disable MMU for a while */
342239268Sgonzo	mrc	p15, 0, r2, c1, c0, 0
343239268Sgonzo	bic	r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
344239268Sgonzo	    CPU_CONTROL_WBUF_ENABLE)
345239268Sgonzo	bic	r2, r2, #(CPU_CONTROL_IC_ENABLE)
346239268Sgonzo	bic	r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
347239268Sgonzo	mcr	p15, 0, r2, c1, c0, 0
348239268Sgonzo
349239268Sgonzo	nop
350239268Sgonzo	nop
351239268Sgonzo	nop
352239268Sgonzo
353239268Sgonzo	AP_DEBUG(#3)
354239268Sgonzo
355239268SgonzoLtag:
356239268Sgonzo	ldr	r0, Lstartup_pagetable_secondary
357239268Sgonzo	bic	r0, r0, #0xf0000000
358239268Sgonzo	orr	r0, r0, #PHYSADDR
359239268Sgonzo	ldr	r0, [r0]
360239268Sgonzo#if defined(SMP)
361239268Sgonzo	orr 	r0, r0, #0		/* Set TTB shared memory flag */
362239268Sgonzo#endif
363239268Sgonzo	mcr	p15, 0, r0, c2, c0, 0	/* Set TTB */
364239268Sgonzo	mcr	p15, 0, r0, c8, c7, 0	/* Flush TLB */
365239268Sgonzo
366244480Sgonzo#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_MV_PJ4B) || defined(CPU_CORTEXA)
367239268Sgonzo	mov	r0, #0
368239268Sgonzo	mcr	p15, 0, r0, c13, c0, 1	/* Set ASID to 0 */
369239268Sgonzo#endif
370239268Sgonzo
371239268Sgonzo	AP_DEBUG(#4)
372239268Sgonzo
373239268Sgonzo	/* Set the Domain Access register.  Very important! */
374239268Sgonzo	mov	r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
375239268Sgonzo	mcr	p15, 0, r0, c3, c0, 0
376239268Sgonzo	/* Enable MMU */
377239268Sgonzo	mrc	p15, 0, r0, c1, c0, 0
378244480Sgonzo#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_MV_PJ4B) || defined(CPU_CORTEXA)
379239268Sgonzo	orr	r0, r0, #CPU_CONTROL_V6_EXTPAGE
380239268Sgonzo#endif
381239268Sgonzo	orr	r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE)
382239268Sgonzo	mcr	p15, 0, r0, c1, c0, 0
383239268Sgonzo	nop
384239268Sgonzo	nop
385239268Sgonzo	nop
386239268Sgonzo	CPWAIT(r0)
387239268Sgonzo
388239268Sgonzo	adr	r1, .Lstart
389239268Sgonzo	ldmia	r1, {r1, r2, sp}	/* Set initial stack and */
390239268Sgonzo	mrc	p15, 0, r0, c0, c0, 5
391239268Sgonzo	and	r0, r0, #15
392239268Sgonzo	mov	r1, #2048
393239268Sgonzo	mul	r2, r1, r0
394239268Sgonzo	sub	sp, sp, r2
395239268Sgonzo	str	r1, [sp]
396239268Sgonzo	ldr	pc, .Lmpvirt_done
397239268Sgonzo
398239268Sgonzompvirt_done:
399239268Sgonzo
400239268Sgonzo	mov	fp, #0			/* trace back starts here */
401239268Sgonzo	bl	_C_LABEL(init_secondary)	/* Off we go */
402239268Sgonzo
403239268Sgonzo	adr	r0, .Lmpreturned
404239268Sgonzo	b	_C_LABEL(panic)
405239268Sgonzo	/* NOTREACHED */
406239268Sgonzo
407239268Sgonzo.Lmpreturned:
408239268Sgonzo	.asciz	"main() returned"
409239268Sgonzo	.align	0
410239268Sgonzo#endif
411239268Sgonzo
412135640ScognetENTRY_NP(cpu_halt)
413129198Scognet	mrs     r2, cpsr
414129198Scognet	bic	r2, r2, #(PSR_MODE)
415129198Scognet	orr     r2, r2, #(PSR_SVC32_MODE)
416129198Scognet	orr	r2, r2, #(I32_bit | F32_bit)
417129198Scognet	msr     cpsr_all, r2
418129198Scognet
419129198Scognet	ldr	r4, .Lcpu_reset_address
420129198Scognet	ldr	r4, [r4]
421129198Scognet
422129198Scognet	ldr	r0, .Lcpufuncs
423129198Scognet	mov	lr, pc
424129198Scognet	ldr	pc, [r0, #CF_IDCACHE_WBINV_ALL]
425183839Sraj	mov	lr, pc
426183839Sraj	ldr	pc, [r0, #CF_L2CACHE_WBINV_ALL]
427129198Scognet
428129198Scognet	/*
429129198Scognet	 * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's
430129198Scognet	 * necessary.
431129198Scognet	 */
432129198Scognet
433129198Scognet	ldr	r1, .Lcpu_reset_needs_v4_MMU_disable
434129198Scognet	ldr	r1, [r1]
435129198Scognet	cmp	r1, #0
436129198Scognet	mov	r2, #0
437129198Scognet
438129198Scognet	/*
439175983Sraj	 * MMU & IDC off, 32 bit program & data space
440129198Scognet	 * Hurl ourselves into the ROM
441129198Scognet	 */
442129198Scognet	mov	r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
443129198Scognet	mcr     15, 0, r0, c1, c0, 0
444129198Scognet	mcrne   15, 0, r2, c8, c7, 0 	/* nail I+D TLB on ARMv4 and greater */
445129198Scognet	mov     pc, r4
446129198Scognet
447129198Scognet	/*
448129198Scognet	 * _cpu_reset_address contains the address to branch to, to complete
449129198Scognet	 * the cpu reset after turning the MMU off
450129198Scognet	 * This variable is provided by the hardware specific code
451129198Scognet	 */
452129198Scognet.Lcpu_reset_address:
453129198Scognet	.word	_C_LABEL(cpu_reset_address)
454129198Scognet
455129198Scognet	/*
456129198Scognet	 * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the
457129198Scognet	 * v4 MMU disable instruction needs executing... it is an illegal instruction
458129198Scognet	 * on f.e. ARM6/7 that locks up the computer in an endless illegal
459129198Scognet	 * instruction / data-abort / reset loop.
460129198Scognet	 */
461129198Scognet.Lcpu_reset_needs_v4_MMU_disable:
462129198Scognet	.word	_C_LABEL(cpu_reset_needs_v4_MMU_disable)
463129198Scognet
464129198Scognet
465129198Scognet/*
466129198Scognet * setjump + longjmp
467129198Scognet */
468129198ScognetENTRY(setjmp)
469129198Scognet	stmia	r0, {r4-r14}
470129198Scognet	mov	r0, #0x00000000
471137463Scognet	RET
472129198Scognet
473129198ScognetENTRY(longjmp)
474129198Scognet	ldmia	r0, {r4-r14}
475129198Scognet	mov	r0, #0x00000001
476137463Scognet	RET
477129198Scognet
478129198Scognet	.data
479129198Scognet	.global _C_LABEL(esym)
480129198Scognet_C_LABEL(esym):	.word	_C_LABEL(end)
481129198Scognet
482129198ScognetENTRY_NP(abort)
483129198Scognet	b	_C_LABEL(abort)
484129198Scognet
485135640ScognetENTRY_NP(sigcode)
486135640Scognet	mov	r0, sp
487245414Sandrew
488245414Sandrew	/*
489245414Sandrew	 * Call the sigreturn system call.
490245414Sandrew	 *
491245414Sandrew	 * We have to load r7 manually rather than using
492245414Sandrew	 * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
493245414Sandrew	 * correct. Using the alternative places esigcode at the address
494245414Sandrew	 * of the data rather than the address one past the data.
495245414Sandrew	 */
496245414Sandrew
497245414Sandrew	ldr	r7, [pc, #12]	/* Load SYS_sigreturn */
498135640Scognet	swi	SYS_sigreturn
499135640Scognet
500135640Scognet	/* Well if that failed we better exit quick ! */
501135640Scognet
502245414Sandrew	ldr	r7, [pc, #8]	/* Load SYS_exit */
503135640Scognet	swi	SYS_exit
504135640Scognet
505245414Sandrew	/* Branch back to retry SYS_sigreturn */
506245414Sandrew	b	. - 16
507245414Sandrew
508245414Sandrew	.word	SYS_sigreturn
509245414Sandrew	.word	SYS_exit
510245414Sandrew
511135640Scognet	.align	0
512135640Scognet	.global _C_LABEL(esigcode)
513135640Scognet		_C_LABEL(esigcode):
514143681Sjmg
515135640Scognet	.data
516135640Scognet	.global szsigcode
517135640Scognetszsigcode:
518135640Scognet	.long esigcode-sigcode
519129198Scognet/* End of locore.S */
520