locore-v4.S revision 258845
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 258845 2013-12-02 13:09:59Z zbb $");
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)
80250253Sian	STOP_UNWINDING		/* Can't unwind into the bootloader! */
81250253Sian
82236524Simp	mov	r9, r0		/* 0 or boot mode from boot2 */
83236524Simp	mov	r8, r1		/* Save Machine type */
84236524Simp	mov	ip, r2		/* Save meta data */
85236524Simp	mov	fp, r3		/* Future expantion */
86183878Sraj
87193846Smarcel	/* Make sure interrupts are disabled. */
88193846Smarcel	mrs	r7, cpsr
89193846Smarcel	orr	r7, r7, #(I32_bit|F32_bit)
90193846Smarcel	msr	cpsr_c, r7
91193846Smarcel
92166819Scognet#if defined (FLASHADDR) && defined(LOADERRAMADDR)
93166819Scognet	/* Check if we're running from flash. */
94166819Scognet	ldr	r7, =FLASHADDR
95175983Sraj	/*
96166819Scognet	 * If we're running with MMU disabled, test against the
97166819Scognet	 * physical address instead.
98166819Scognet	 */
99166819Scognet	mrc     p15, 0, r2, c1, c0, 0
100166819Scognet	ands	r2, r2, #CPU_CONTROL_MMU_ENABLE
101236524Simp	ldreq	r6, =PHYSADDR
102236524Simp	ldrne	r6, =LOADERRAMADDR
103236524Simp	cmp	r7, r6
104166819Scognet	bls 	flash_lower
105166819Scognet	cmp	r7, pc
106166819Scognet	bhi	from_ram
107166819Scognet	b	do_copy
108166819Scognet
109166819Scognetflash_lower:
110236524Simp	cmp	r6, pc
111166819Scognet	bls	from_ram
112166819Scognetdo_copy:
113236524Simp	ldr	r7, =KERNBASE
114175983Sraj	adr	r1, _start
115166819Scognet	ldr	r0, Lreal_start
116166819Scognet	ldr	r2, Lend
117166819Scognet	sub	r2, r2, r0
118236524Simp	sub	r0, r0, r7
119236524Simp	add	r0, r0, r6
120166819Scognet	mov	r4, r0
121166819Scognet	bl	memcpy
122166819Scognet	ldr	r0, Lram_offset
123166819Scognet	add	pc, r4, r0
124166819ScognetLram_offset:	.word from_ram-_C_LABEL(_start)
125166819Scognetfrom_ram:
126166819Scognet	nop
127135640Scognet#endif
128135640Scognet	adr	r7, Lunmapped
129190602Scognet	bic     r7, r7, #0xf0000000
130153616Scognet	orr     r7, r7, #PHYSADDR
131143681Sjmg
132175983Sraj
133166819Scognetdisable_mmu:
134135640Scognet	/* Disable MMU for a while */
135143681Sjmg	mrc     p15, 0, r2, c1, c0, 0
136153550Scognet	bic	r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
137153550Scognet	    CPU_CONTROL_WBUF_ENABLE)
138153550Scognet	bic	r2, r2, #(CPU_CONTROL_IC_ENABLE)
139153550Scognet	bic	r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
140135640Scognet	mcr     p15, 0, r2, c1, c0, 0
141129198Scognet
142135640Scognet	nop
143135640Scognet	nop
144135640Scognet	nop
145135640Scognet	mov	pc, r7
146135640ScognetLunmapped:
147135640Scognet#ifdef STARTUP_PAGETABLE_ADDR
148129198Scognet	/* build page table from scratch */
149129198Scognet	ldr	r0, Lstartup_pagetable
150129198Scognet	adr	r4, mmu_init_table
151129198Scognet	b	3f
152129198Scognet
153129198Scognet2:
154129198Scognet	str	r3, [r0, r2]
155129198Scognet	add	r2, r2, #4
156129198Scognet	add	r3, r3, #(L1_S_SIZE)
157129198Scognet	adds	r1, r1, #-1
158129198Scognet	bhi	2b
159143681Sjmg3:
160172356Scognet	ldmia	r4!, {r1,r2,r3}   /* # of sections, VA, PA|attr */
161129198Scognet	cmp	r1, #0
162140683Scognet	adrne	r5, 2b
163190602Scognet	bicne	r5, r5, #0xf0000000
164140683Scognet	orrne	r5, r5, #PHYSADDR
165140683Scognet	movne	pc, r5
166129198Scognet
167239268Sgonzo#if defined(SMP)
168239268Sgonzo	orr 	r0, r0, #2		/* Set TTB shared memory flag */
169239268Sgonzo#endif
170129198Scognet	mcr	p15, 0, r0, c2, c0, 0	/* Set TTB */
171129198Scognet	mcr	p15, 0, r0, c8, c7, 0	/* Flush TLB */
172129198Scognet
173244480Sgonzo#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B)
174239268Sgonzo	mov	r0, #0
175239268Sgonzo	mcr	p15, 0, r0, c13, c0, 1	/* Set ASID to 0 */
176239268Sgonzo#endif
177239268Sgonzo
178129198Scognet	/* Set the Domain Access register.  Very important! */
179143681Sjmg	mov     r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
180129198Scognet	mcr	p15, 0, r0, c3, c0, 0
181248961Sian	/*
182248961Sian	 * Enable MMU.
183248961Sian	 * On armv6 enable extended page tables, and set alignment checking
184248961Sian	 * to modulo-4 (CPU_CONTROL_UNAL_ENABLE) for the ldrd/strd
185248961Sian	 * instructions emitted by clang.
186248961Sian	 */
187129198Scognet	mrc	p15, 0, r0, c1, c0, 0
188248961Sian#ifdef _ARM_ARCH_6
189248961Sian	orr	r0, r0, #(CPU_CONTROL_V6_EXTPAGE | CPU_CONTROL_UNAL_ENABLE)
190256628Sian	orr	r0, r0, #(CPU_CONTROL_AFLT_ENABLE)
191250928Sgber	orr	r0, r0, #(CPU_CONTROL_AF_ENABLE)
192239268Sgonzo#endif
193243602Sgonzo	orr	r0, r0, #(CPU_CONTROL_MMU_ENABLE)
194129198Scognet	mcr	p15, 0, r0, c1, c0, 0
195153550Scognet	nop
196153550Scognet	nop
197153550Scognet	nop
198129198Scognet	CPWAIT(r0)
199129198Scognet
200153550Scognet#endif
201129198Scognetmmu_done:
202153550Scognet	nop
203129198Scognet	adr	r1, .Lstart
204129198Scognet	ldmia	r1, {r1, r2, sp}	/* Set initial stack and */
205129198Scognet	sub	r2, r2, r1		/* get zero init data */
206129198Scognet	mov	r3, #0
207129198Scognet.L1:
208150863Scognet	str	r3, [r1], #0x0004	/* get zero init data */
209129198Scognet	subs	r2, r2, #4
210129198Scognet	bgt	.L1
211153550Scognet	ldr	pc, .Lvirt_done
212129198Scognet
213142145Scognetvirt_done:
214236524Simp	mov	r1, #20			/* loader info size is 20 bytes also second arg */
215236524Simp	subs	sp, sp, r1		/* allocate arm_boot_params struct on stack */
216247608Sandrew	bic	sp, sp, #7		/* align stack to 8 bytes */
217236524Simp	mov	r0, sp			/* loader info pointer is first arg */
218236524Simp	str	r1, [r0]		/* Store length of loader info */
219236524Simp	str	r9, [r0, #4]		/* Store r0 from boot loader */
220236524Simp	str	r8, [r0, #8]		/* Store r1 from boot loader */
221236524Simp	str	ip, [r0, #12]		/* store r2 from boot loader */
222236524Simp	str	fp, [r0, #16]		/* store r3 from boot loader */
223175983Sraj	mov	fp, #0			/* trace back starts here */
224129198Scognet	bl	_C_LABEL(initarm)	/* Off we go */
225129198Scognet
226129198Scognet	/* init arm will return the new stack pointer. */
227129198Scognet	mov	sp, r0
228129198Scognet
229129198Scognet	bl	_C_LABEL(mi_startup)		/* call mi_startup()! */
230129198Scognet
231129198Scognet	adr	r0, .Lmainreturned
232130164Sphk	b	_C_LABEL(panic)
233175983Sraj	/* NOTREACHED */
234129198Scognet#ifdef STARTUP_PAGETABLE_ADDR
235129198Scognet#define MMU_INIT(va,pa,n_sec,attr) \
236129198Scognet	.word	n_sec					    ; \
237129198Scognet	.word	4*((va)>>L1_S_SHIFT)			    ; \
238129198Scognet	.word	(pa)|(attr)				    ;
239129198Scognet
240150863ScognetLvirtaddr:
241150863Scognet	.word	KERNVIRTADDR
242150863ScognetLphysaddr:
243150863Scognet	.word	KERNPHYSADDR
244166819ScognetLreal_start:
245166819Scognet	.word	_start
246166819ScognetLend:
247166819Scognet	.word	_edata
248129198ScognetLstartup_pagetable:
249129198Scognet	.word	STARTUP_PAGETABLE_ADDR
250239268Sgonzo#ifdef SMP
251239268SgonzoLstartup_pagetable_secondary:
252239268Sgonzo	.word	temp_pagetable
253239268Sgonzo#endif
254248361SandrewEND(btext)
255248361SandrewEND(_start)
256248361Sandrew
257143681Sjmgmmu_init_table:
258129198Scognet	/* fill all table VA==PA */
259129198Scognet	/* map SDRAM VA==PA, WT cacheable */
260239268Sgonzo#if !defined(SMP)
261135640Scognet	MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
262135640Scognet	/* map VA 0xc0000000..0xc3ffffff to PA */
263135640Scognet	MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
264239268Sgonzo#else
265239268Sgonzo	MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW))
266239268Sgonzo	/* map VA 0xc0000000..0xc3ffffff to PA */
267239268Sgonzo	MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW))
268239268Sgonzo	MMU_INIT(0x48000000, 0x48000000, 1, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW))
269250293Sgber#endif /* SMP */
270129198Scognet	.word 0	/* end of table */
271129198Scognet#endif
272129198Scognet.Lstart:
273129198Scognet	.word	_edata
274129198Scognet	.word	_end
275129198Scognet	.word	svcstk + INIT_ARM_STACK_SIZE
276129198Scognet
277153550Scognet.Lvirt_done:
278153550Scognet	.word	virt_done
279239268Sgonzo#if defined(SMP)
280239268Sgonzo.Lmpvirt_done:
281239268Sgonzo	.word	mpvirt_done
282239268Sgonzo#endif
283239268Sgonzo
284129198Scognet.Lmainreturned:
285129198Scognet	.asciz	"main() returned"
286129198Scognet	.align	0
287129198Scognet
288129198Scognet	.bss
289129198Scognetsvcstk:
290129198Scognet	.space	INIT_ARM_STACK_SIZE
291129198Scognet
292129198Scognet	.text
293129198Scognet	.align	0
294129198Scognet
295143681Sjmg.Lcpufuncs:
296129198Scognet	.word	_C_LABEL(cpufuncs)
297129198Scognet
298239268Sgonzo#if defined(SMP)
299239268SgonzoLsramaddr:
300239268Sgonzo	.word	0xffff0080
301239268Sgonzo
302239268Sgonzo#if 0
303239268Sgonzo#define	AP_DEBUG(tmp)			\
304239268Sgonzo	mrc	p15, 0, r1, c0, c0, 5;	\
305239268Sgonzo	ldr	r0, Lsramaddr;		\
306239268Sgonzo	add	r0, r1, lsl #2;		\
307239268Sgonzo	mov	r1, tmp;		\
308239268Sgonzo	str	r1, [r0], #0x0000;
309239268Sgonzo#else
310239268Sgonzo#define AP_DEBUG(tmp)
311239268Sgonzo#endif
312239268Sgonzo
313239268Sgonzo
314239268SgonzoASENTRY_NP(mptramp)
315239268Sgonzo	mov	r0, #0
316239268Sgonzo	mcr	p15, 0, r0, c7, c7, 0
317239268Sgonzo
318239268Sgonzo	AP_DEBUG(#1)
319239268Sgonzo
320239268Sgonzo	mrs	r3, cpsr_all
321239268Sgonzo	bic	r3, r3, #(PSR_MODE)
322239268Sgonzo	orr	r3, r3, #(PSR_SVC32_MODE)
323239268Sgonzo        msr	cpsr_all, r3
324239268Sgonzo
325239268Sgonzo	mrc	p15, 0, r0, c0, c0, 5
326239268Sgonzo	and	r0, #0x0f		/* Get CPU ID */
327239268Sgonzo
328239268Sgonzo	/* Read boot address for CPU */
329239268Sgonzo	mov	r1, #0x100
330239268Sgonzo	mul	r2, r0, r1
331239268Sgonzo	ldr	r1, Lpmureg
332239268Sgonzo	add	r0, r2, r1
333239268Sgonzo	ldr	r1, [r0], #0x00
334239268Sgonzo
335239268Sgonzo	mov pc, r1
336239268Sgonzo
337239268SgonzoLpmureg:
338239268Sgonzo        .word   0xd0022124
339248361SandrewEND(mptramp)
340239268Sgonzo
341239268SgonzoASENTRY_NP(mpentry)
342239268Sgonzo
343239268Sgonzo	AP_DEBUG(#2)
344239268Sgonzo
345239268Sgonzo	/* Make sure interrupts are disabled. */
346239268Sgonzo	mrs	r7, cpsr
347239268Sgonzo	orr	r7, r7, #(I32_bit|F32_bit)
348239268Sgonzo	msr	cpsr_c, r7
349239268Sgonzo
350239268Sgonzo
351239268Sgonzo	adr     r7, Ltag
352239268Sgonzo	bic     r7, r7, #0xf0000000
353239268Sgonzo	orr     r7, r7, #PHYSADDR
354239268Sgonzo
355239268Sgonzo	/* Disable MMU for a while */
356239268Sgonzo	mrc	p15, 0, r2, c1, c0, 0
357239268Sgonzo	bic	r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
358239268Sgonzo	    CPU_CONTROL_WBUF_ENABLE)
359239268Sgonzo	bic	r2, r2, #(CPU_CONTROL_IC_ENABLE)
360239268Sgonzo	bic	r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
361239268Sgonzo	mcr	p15, 0, r2, c1, c0, 0
362239268Sgonzo
363239268Sgonzo	nop
364239268Sgonzo	nop
365239268Sgonzo	nop
366239268Sgonzo
367239268Sgonzo	AP_DEBUG(#3)
368239268Sgonzo
369239268SgonzoLtag:
370239268Sgonzo	ldr	r0, Lstartup_pagetable_secondary
371239268Sgonzo	bic	r0, r0, #0xf0000000
372239268Sgonzo	orr	r0, r0, #PHYSADDR
373239268Sgonzo	ldr	r0, [r0]
374239268Sgonzo#if defined(SMP)
375239268Sgonzo	orr 	r0, r0, #0		/* Set TTB shared memory flag */
376239268Sgonzo#endif
377239268Sgonzo	mcr	p15, 0, r0, c2, c0, 0	/* Set TTB */
378239268Sgonzo	mcr	p15, 0, r0, c8, c7, 0	/* Flush TLB */
379239268Sgonzo
380244480Sgonzo#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_MV_PJ4B) || defined(CPU_CORTEXA)
381239268Sgonzo	mov	r0, #0
382239268Sgonzo	mcr	p15, 0, r0, c13, c0, 1	/* Set ASID to 0 */
383239268Sgonzo#endif
384239268Sgonzo
385239268Sgonzo	AP_DEBUG(#4)
386239268Sgonzo
387239268Sgonzo	/* Set the Domain Access register.  Very important! */
388239268Sgonzo	mov	r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
389239268Sgonzo	mcr	p15, 0, r0, c3, c0, 0
390239268Sgonzo	/* Enable MMU */
391239268Sgonzo	mrc	p15, 0, r0, c1, c0, 0
392244480Sgonzo#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_MV_PJ4B) || defined(CPU_CORTEXA)
393239268Sgonzo	orr	r0, r0, #CPU_CONTROL_V6_EXTPAGE
394258845Szbb	orr	r0, r0, #CPU_CONTROL_AF_ENABLE
395239268Sgonzo#endif
396239268Sgonzo	orr	r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE)
397239268Sgonzo	mcr	p15, 0, r0, c1, c0, 0
398239268Sgonzo	nop
399239268Sgonzo	nop
400239268Sgonzo	nop
401239268Sgonzo	CPWAIT(r0)
402239268Sgonzo
403239268Sgonzo	adr	r1, .Lstart
404239268Sgonzo	ldmia	r1, {r1, r2, sp}	/* Set initial stack and */
405239268Sgonzo	mrc	p15, 0, r0, c0, c0, 5
406239268Sgonzo	and	r0, r0, #15
407239268Sgonzo	mov	r1, #2048
408239268Sgonzo	mul	r2, r1, r0
409239268Sgonzo	sub	sp, sp, r2
410239268Sgonzo	str	r1, [sp]
411239268Sgonzo	ldr	pc, .Lmpvirt_done
412239268Sgonzo
413239268Sgonzompvirt_done:
414239268Sgonzo
415239268Sgonzo	mov	fp, #0			/* trace back starts here */
416239268Sgonzo	bl	_C_LABEL(init_secondary)	/* Off we go */
417239268Sgonzo
418239268Sgonzo	adr	r0, .Lmpreturned
419239268Sgonzo	b	_C_LABEL(panic)
420239268Sgonzo	/* NOTREACHED */
421239268Sgonzo
422239268Sgonzo.Lmpreturned:
423239268Sgonzo	.asciz	"main() returned"
424239268Sgonzo	.align	0
425248361SandrewEND(mpentry)
426239268Sgonzo#endif
427239268Sgonzo
428135640ScognetENTRY_NP(cpu_halt)
429129198Scognet	mrs     r2, cpsr
430129198Scognet	bic	r2, r2, #(PSR_MODE)
431129198Scognet	orr     r2, r2, #(PSR_SVC32_MODE)
432129198Scognet	orr	r2, r2, #(I32_bit | F32_bit)
433129198Scognet	msr     cpsr_all, r2
434129198Scognet
435129198Scognet	ldr	r4, .Lcpu_reset_address
436129198Scognet	ldr	r4, [r4]
437129198Scognet
438129198Scognet	ldr	r0, .Lcpufuncs
439129198Scognet	mov	lr, pc
440129198Scognet	ldr	pc, [r0, #CF_IDCACHE_WBINV_ALL]
441183839Sraj	mov	lr, pc
442183839Sraj	ldr	pc, [r0, #CF_L2CACHE_WBINV_ALL]
443129198Scognet
444129198Scognet	/*
445129198Scognet	 * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's
446129198Scognet	 * necessary.
447129198Scognet	 */
448129198Scognet
449129198Scognet	ldr	r1, .Lcpu_reset_needs_v4_MMU_disable
450129198Scognet	ldr	r1, [r1]
451129198Scognet	cmp	r1, #0
452129198Scognet	mov	r2, #0
453129198Scognet
454129198Scognet	/*
455175983Sraj	 * MMU & IDC off, 32 bit program & data space
456129198Scognet	 * Hurl ourselves into the ROM
457129198Scognet	 */
458129198Scognet	mov	r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
459129198Scognet	mcr     15, 0, r0, c1, c0, 0
460129198Scognet	mcrne   15, 0, r2, c8, c7, 0 	/* nail I+D TLB on ARMv4 and greater */
461129198Scognet	mov     pc, r4
462129198Scognet
463129198Scognet	/*
464129198Scognet	 * _cpu_reset_address contains the address to branch to, to complete
465129198Scognet	 * the cpu reset after turning the MMU off
466129198Scognet	 * This variable is provided by the hardware specific code
467129198Scognet	 */
468129198Scognet.Lcpu_reset_address:
469129198Scognet	.word	_C_LABEL(cpu_reset_address)
470129198Scognet
471129198Scognet	/*
472129198Scognet	 * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the
473129198Scognet	 * v4 MMU disable instruction needs executing... it is an illegal instruction
474129198Scognet	 * on f.e. ARM6/7 that locks up the computer in an endless illegal
475129198Scognet	 * instruction / data-abort / reset loop.
476129198Scognet	 */
477129198Scognet.Lcpu_reset_needs_v4_MMU_disable:
478129198Scognet	.word	_C_LABEL(cpu_reset_needs_v4_MMU_disable)
479248361SandrewEND(cpu_halt)
480129198Scognet
481129198Scognet
482129198Scognet/*
483129198Scognet * setjump + longjmp
484129198Scognet */
485129198ScognetENTRY(setjmp)
486129198Scognet	stmia	r0, {r4-r14}
487129198Scognet	mov	r0, #0x00000000
488137463Scognet	RET
489248361SandrewEND(setjmp)
490129198Scognet
491129198ScognetENTRY(longjmp)
492129198Scognet	ldmia	r0, {r4-r14}
493129198Scognet	mov	r0, #0x00000001
494137463Scognet	RET
495248361SandrewEND(longjmp)
496129198Scognet
497129198Scognet	.data
498129198Scognet	.global _C_LABEL(esym)
499129198Scognet_C_LABEL(esym):	.word	_C_LABEL(end)
500129198Scognet
501129198ScognetENTRY_NP(abort)
502129198Scognet	b	_C_LABEL(abort)
503248361SandrewEND(abort)
504129198Scognet
505135640ScognetENTRY_NP(sigcode)
506135640Scognet	mov	r0, sp
507245414Sandrew
508245414Sandrew	/*
509245414Sandrew	 * Call the sigreturn system call.
510245414Sandrew	 *
511245414Sandrew	 * We have to load r7 manually rather than using
512245414Sandrew	 * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
513245414Sandrew	 * correct. Using the alternative places esigcode at the address
514245414Sandrew	 * of the data rather than the address one past the data.
515245414Sandrew	 */
516245414Sandrew
517245414Sandrew	ldr	r7, [pc, #12]	/* Load SYS_sigreturn */
518135640Scognet	swi	SYS_sigreturn
519135640Scognet
520135640Scognet	/* Well if that failed we better exit quick ! */
521135640Scognet
522245414Sandrew	ldr	r7, [pc, #8]	/* Load SYS_exit */
523135640Scognet	swi	SYS_exit
524135640Scognet
525245414Sandrew	/* Branch back to retry SYS_sigreturn */
526245414Sandrew	b	. - 16
527245414Sandrew
528245414Sandrew	.word	SYS_sigreturn
529245414Sandrew	.word	SYS_exit
530245414Sandrew
531135640Scognet	.align	0
532135640Scognet	.global _C_LABEL(esigcode)
533135640Scognet		_C_LABEL(esigcode):
534143681Sjmg
535135640Scognet	.data
536135640Scognet	.global szsigcode
537135640Scognetszsigcode:
538135640Scognet	.long esigcode-sigcode
539248361SandrewEND(sigcode)
540129198Scognet/* End of locore.S */
541