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>
40271327Sian#include <machine/cpuconf.h>
41129198Scognet#include <machine/pte.h>
42236524Simp
43129198Scognet__FBSDID("$FreeBSD$");
44129198Scognet
45159849Simp/* What size should this really be ? It is only used by initarm() */
46239268Sgonzo#define INIT_ARM_STACK_SIZE	(2048 * 4)
47129198Scognet
48129198Scognet#define	CPWAIT_BRANCH							 \
49129198Scognet	sub	pc, pc, #4
50129198Scognet
51129198Scognet#define	CPWAIT(tmp)							 \
52129198Scognet	mrc	p15, 0, tmp, c2, c0, 0	/* arbitrary read of CP15 */	;\
53129198Scognet	mov	tmp, tmp		/* wait for it to complete */	;\
54129198Scognet	CPWAIT_BRANCH			/* branch to next insn */
55129198Scognet
56235277Simp/*
57235277Simp * This is for kvm_mkdb, and should be the address of the beginning
58235277Simp * of the kernel text segment (not necessarily the same as kernbase).
59235277Simp */
60129198Scognet	.text
61129198Scognet	.align	0
62129198Scognet.globl kernbase
63129198Scognet.set kernbase,KERNBASE
64150863Scognet.globl physaddr
65150863Scognet.set physaddr,PHYSADDR
66129198Scognet
67183878Sraj/*
68236524Simp * On entry for FreeBSD boot ABI:
69236524Simp *	r0 - metadata pointer or 0 (boothowto on AT91's boot2)
70218227Smarcel *	r1 - if (r0 == 0) then metadata pointer
71236524Simp * On entry for Linux boot ABI:
72236524Simp *	r0 - 0
73236524Simp *	r1 - machine type (passed as arg2 to initarm)
74236524Simp *	r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm)
75236524Simp *
76236524Simp * For both types of boot we gather up the args, put them in a struct arm_boot_params
77236524Simp * structure and pass that to initarm.
78183878Sraj */
79269796Sian	.globl	btext
80269796Sianbtext:
81218227SmarcelASENTRY_NP(_start)
82250253Sian	STOP_UNWINDING		/* Can't unwind into the bootloader! */
83250253Sian
84236524Simp	mov	r9, r0		/* 0 or boot mode from boot2 */
85236524Simp	mov	r8, r1		/* Save Machine type */
86236524Simp	mov	ip, r2		/* Save meta data */
87236524Simp	mov	fp, r3		/* Future expantion */
88183878Sraj
89193846Smarcel	/* Make sure interrupts are disabled. */
90193846Smarcel	mrs	r7, cpsr
91193846Smarcel	orr	r7, r7, #(I32_bit|F32_bit)
92193846Smarcel	msr	cpsr_c, r7
93193846Smarcel
94166819Scognet#if defined (FLASHADDR) && defined(LOADERRAMADDR)
95166819Scognet	/* Check if we're running from flash. */
96166819Scognet	ldr	r7, =FLASHADDR
97175983Sraj	/*
98166819Scognet	 * If we're running with MMU disabled, test against the
99166819Scognet	 * physical address instead.
100166819Scognet	 */
101166819Scognet	mrc     p15, 0, r2, c1, c0, 0
102166819Scognet	ands	r2, r2, #CPU_CONTROL_MMU_ENABLE
103236524Simp	ldreq	r6, =PHYSADDR
104236524Simp	ldrne	r6, =LOADERRAMADDR
105236524Simp	cmp	r7, r6
106166819Scognet	bls 	flash_lower
107166819Scognet	cmp	r7, pc
108166819Scognet	bhi	from_ram
109166819Scognet	b	do_copy
110166819Scognet
111166819Scognetflash_lower:
112236524Simp	cmp	r6, pc
113166819Scognet	bls	from_ram
114166819Scognetdo_copy:
115236524Simp	ldr	r7, =KERNBASE
116175983Sraj	adr	r1, _start
117166819Scognet	ldr	r0, Lreal_start
118166819Scognet	ldr	r2, Lend
119166819Scognet	sub	r2, r2, r0
120236524Simp	sub	r0, r0, r7
121236524Simp	add	r0, r0, r6
122166819Scognet	mov	r4, r0
123166819Scognet	bl	memcpy
124166819Scognet	ldr	r0, Lram_offset
125166819Scognet	add	pc, r4, r0
126166819ScognetLram_offset:	.word from_ram-_C_LABEL(_start)
127166819Scognetfrom_ram:
128166819Scognet	nop
129135640Scognet#endif
130135640Scognet	adr	r7, Lunmapped
131190602Scognet	bic     r7, r7, #0xf0000000
132153616Scognet	orr     r7, r7, #PHYSADDR
133143681Sjmg
134175983Sraj
135166819Scognetdisable_mmu:
136135640Scognet	/* Disable MMU for a while */
137143681Sjmg	mrc     p15, 0, r2, c1, c0, 0
138153550Scognet	bic	r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
139153550Scognet	    CPU_CONTROL_WBUF_ENABLE)
140153550Scognet	bic	r2, r2, #(CPU_CONTROL_IC_ENABLE)
141153550Scognet	bic	r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
142135640Scognet	mcr     p15, 0, r2, c1, c0, 0
143129198Scognet
144135640Scognet	nop
145135640Scognet	nop
146135640Scognet	nop
147135640Scognet	mov	pc, r7
148135640ScognetLunmapped:
149266110Sian	/*
150266110Sian	 * Build page table from scratch.
151266110Sian	 */
152266110Sian
153266198Sian	/* Find the delta between VA and PA */
154266198Sian	adr	r0, Lpagetable
155266198Sian	ldr	r1, [r0]
156266198Sian	sub	r2, r1, r0
157266198Sian	/* At this point: r2 = VA - PA */
158266198Sian
159266198Sian	/*
160266198Sian	 * Find the physical address of the table. After these two
161266198Sian	 * instructions:
162266198Sian	 * r1 = va(pagetable)
163266198Sian	 *
164266198Sian	 * r0 = va(pagetable) - (VA - PA)
165266198Sian	 *    = va(pagetable) - VA + PA
166266198Sian	 *    = pa(pagetable)
167266198Sian	 */
168266198Sian	ldr	r1, [r0, #4]
169266110Sian	sub	r0, r1, r2
170266110Sian
171266160Sian	/*
172266160Sian	 * Map PA == VA
173266160Sian	 */
174266198Sian	/* Find the start kernels load address */
175266198Sian	adr	r5, _start
176266198Sian	ldr	r2, =(L1_S_OFFSET)
177266198Sian	bic	r5, r2
178266160Sian	mov	r1, r5
179266160Sian	mov	r2, r5
180266160Sian	/* Map 64MiB, preserved over calls to build_pagetables */
181266160Sian	mov	r3, #64
182266160Sian	bl	build_pagetables
183129198Scognet
184266160Sian	/* Create the kernel map to jump to */
185266160Sian	mov	r1, r5
186266198Sian	ldr	r2, =(KERNVIRTADDR)
187266160Sian	bl	build_pagetables
188266160Sian
189266160Sian#if defined(SOCDEV_PA) && defined(SOCDEV_VA)
190266160Sian	/* Create the custom map */
191266196Sian	ldr	r1, =SOCDEV_PA
192266196Sian	ldr	r2, =SOCDEV_VA
193266160Sian	bl	build_pagetables
194266160Sian#endif
195129198Scognet
196239268Sgonzo#if defined(SMP)
197239268Sgonzo	orr 	r0, r0, #2		/* Set TTB shared memory flag */
198239268Sgonzo#endif
199129198Scognet	mcr	p15, 0, r0, c2, c0, 0	/* Set TTB */
200129198Scognet	mcr	p15, 0, r0, c8, c7, 0	/* Flush TLB */
201129198Scognet
202266058Sian#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B) || defined(CPU_KRAIT)
203239268Sgonzo	mov	r0, #0
204239268Sgonzo	mcr	p15, 0, r0, c13, c0, 1	/* Set ASID to 0 */
205239268Sgonzo#endif
206239268Sgonzo
207129198Scognet	/* Set the Domain Access register.  Very important! */
208143681Sjmg	mov     r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
209129198Scognet	mcr	p15, 0, r0, c3, c0, 0
210248961Sian	/*
211248961Sian	 * Enable MMU.
212248961Sian	 * On armv6 enable extended page tables, and set alignment checking
213248961Sian	 * to modulo-4 (CPU_CONTROL_UNAL_ENABLE) for the ldrd/strd
214248961Sian	 * instructions emitted by clang.
215248961Sian	 */
216129198Scognet	mrc	p15, 0, r0, c1, c0, 0
217248961Sian#ifdef _ARM_ARCH_6
218248961Sian	orr	r0, r0, #(CPU_CONTROL_V6_EXTPAGE | CPU_CONTROL_UNAL_ENABLE)
219259308Sian	orr	r0, r0, #(CPU_CONTROL_AFLT_ENABLE)
220250928Sgber	orr	r0, r0, #(CPU_CONTROL_AF_ENABLE)
221239268Sgonzo#endif
222243602Sgonzo	orr	r0, r0, #(CPU_CONTROL_MMU_ENABLE)
223129198Scognet	mcr	p15, 0, r0, c1, c0, 0
224153550Scognet	nop
225153550Scognet	nop
226153550Scognet	nop
227129198Scognet	CPWAIT(r0)
228129198Scognet
229129198Scognetmmu_done:
230153550Scognet	nop
231129198Scognet	adr	r1, .Lstart
232129198Scognet	ldmia	r1, {r1, r2, sp}	/* Set initial stack and */
233129198Scognet	sub	r2, r2, r1		/* get zero init data */
234129198Scognet	mov	r3, #0
235129198Scognet.L1:
236150863Scognet	str	r3, [r1], #0x0004	/* get zero init data */
237129198Scognet	subs	r2, r2, #4
238129198Scognet	bgt	.L1
239153550Scognet	ldr	pc, .Lvirt_done
240129198Scognet
241142145Scognetvirt_done:
242266194Sian	mov	r1, #28			/* loader info size is 28 bytes also second arg */
243236524Simp	subs	sp, sp, r1		/* allocate arm_boot_params struct on stack */
244266198Sian	mov	r0, sp			/* loader info pointer is first arg */
245247608Sandrew	bic	sp, sp, #7		/* align stack to 8 bytes */
246236524Simp	str	r1, [r0]		/* Store length of loader info */
247236524Simp	str	r9, [r0, #4]		/* Store r0 from boot loader */
248236524Simp	str	r8, [r0, #8]		/* Store r1 from boot loader */
249236524Simp	str	ip, [r0, #12]		/* store r2 from boot loader */
250236524Simp	str	fp, [r0, #16]		/* store r3 from boot loader */
251266160Sian	str	r5, [r0, #20]		/* store the physical address */
252266198Sian	adr	r4, Lpagetable		/* load the pagetable address */
253266198Sian	ldr	r5, [r4, #4]
254266194Sian	str	r5, [r0, #24]		/* store the pagetable address */
255175983Sraj	mov	fp, #0			/* trace back starts here */
256129198Scognet	bl	_C_LABEL(initarm)	/* Off we go */
257129198Scognet
258129198Scognet	/* init arm will return the new stack pointer. */
259129198Scognet	mov	sp, r0
260129198Scognet
261129198Scognet	bl	_C_LABEL(mi_startup)		/* call mi_startup()! */
262129198Scognet
263129198Scognet	adr	r0, .Lmainreturned
264130164Sphk	b	_C_LABEL(panic)
265175983Sraj	/* NOTREACHED */
266266160SianEND(_start)
267266160Sian
268266160Sian/*
269266160Sian * Builds the page table
270266160Sian * r0 - The table base address
271266160Sian * r1 - The physical address (trashed)
272266160Sian * r2 - The virtual address (trashed)
273266160Sian * r3 - The number of 1MiB sections
274266160Sian * r4 - Trashed
275266160Sian *
276266160Sian * Addresses must be 1MiB aligned
277266160Sian */
278266160Sianbuild_pagetables:
279266160Sian	/* Set the required page attributed */
280266160Sian	ldr	r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
281266160Sian#if defined(SMP)
282266160Sian	orr	r4, #(L1_SHARED)
283266160Sian#endif
284266160Sian	orr	r1, r4
285266160Sian
286266160Sian	/* Move the virtual address to the correct bit location */
287266160Sian	lsr	r2, #(L1_S_SHIFT - 2)
288266160Sian
289266160Sian	mov	r4, r3
290266160Sian1:
291266160Sian	str	r1, [r0, r2]
292266160Sian	add	r2, r2, #4
293266160Sian	add	r1, r1, #(L1_S_SIZE)
294266160Sian	adds	r4, r4, #-1
295266160Sian	bhi	1b
296266160Sian
297266160Sian	RET
298266160Sian
299266198SianLpagetable:
300266198Sian	.word	.
301266198Sian	.word	pagetable
302266198Sian
303150863ScognetLvirtaddr:
304150863Scognet	.word	KERNVIRTADDR
305150863ScognetLphysaddr:
306150863Scognet	.word	KERNPHYSADDR
307166819ScognetLreal_start:
308166819Scognet	.word	_start
309266198SianLend:
310166819Scognet	.word	_edata
311266198Sian
312129198Scognet.Lstart:
313129198Scognet	.word	_edata
314266110Sian	.word	_ebss
315129198Scognet	.word	svcstk + INIT_ARM_STACK_SIZE
316129198Scognet
317153550Scognet.Lvirt_done:
318153550Scognet	.word	virt_done
319239268Sgonzo
320129198Scognet.Lmainreturned:
321129198Scognet	.asciz	"main() returned"
322129198Scognet	.align	0
323129198Scognet
324129198Scognet	.bss
325129198Scognetsvcstk:
326129198Scognet	.space	INIT_ARM_STACK_SIZE
327129198Scognet
328266110Sian/*
329266110Sian * Memory for the initial pagetable. We are unable to place this in
330266110Sian * the bss as this will be cleared after the table is loaded.
331266110Sian */
332266110Sian	.section ".init_pagetable"
333266110Sian	.align	14 /* 16KiB aligned */
334266110Sianpagetable:
335266110Sian	.space	L1_TABLE_SIZE
336266110Sian
337129198Scognet	.text
338129198Scognet	.align	0
339129198Scognet
340143681Sjmg.Lcpufuncs:
341129198Scognet	.word	_C_LABEL(cpufuncs)
342129198Scognet
343239268Sgonzo#if defined(SMP)
344239268Sgonzo
345266385Sian.Lmpvirt_done:
346266385Sian	.word	mpvirt_done
347266385SianLstartup_pagetable_secondary:
348266385Sian	.word	temp_pagetable
349239268Sgonzo
350239268SgonzoASENTRY_NP(mpentry)
351239268Sgonzo
352239268Sgonzo	/* Make sure interrupts are disabled. */
353239268Sgonzo	mrs	r7, cpsr
354239268Sgonzo	orr	r7, r7, #(I32_bit|F32_bit)
355239268Sgonzo	msr	cpsr_c, r7
356239268Sgonzo
357266385Sian	/* Disable MMU.  It should be disabled already, but make sure. */
358239268Sgonzo	mrc	p15, 0, r2, c1, c0, 0
359239268Sgonzo	bic	r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
360239268Sgonzo	    CPU_CONTROL_WBUF_ENABLE)
361239268Sgonzo	bic	r2, r2, #(CPU_CONTROL_IC_ENABLE)
362239268Sgonzo	bic	r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
363239268Sgonzo	mcr	p15, 0, r2, c1, c0, 0
364239268Sgonzo	nop
365239268Sgonzo	nop
366239268Sgonzo	nop
367266385Sian	CPWAIT(r0)
368239268Sgonzo
369271327Sian#if ARM_MMU_V6
370266385Sian	bl	armv6_idcache_inv_all	/* Modifies r0 only */
371271327Sian#elif ARM_MMU_V7
372266385Sian	bl	armv7_idcache_inv_all	/* Modifies r0-r3, ip */
373266385Sian#endif
374239268Sgonzo
375239268Sgonzo	ldr	r0, Lstartup_pagetable_secondary
376239268Sgonzo	bic	r0, r0, #0xf0000000
377239268Sgonzo	orr	r0, r0, #PHYSADDR
378239268Sgonzo	ldr	r0, [r0]
379266203Sian	orr 	r0, r0, #2		/* Set TTB shared memory flag */
380239268Sgonzo	mcr	p15, 0, r0, c2, c0, 0	/* Set TTB */
381239268Sgonzo	mcr	p15, 0, r0, c8, c7, 0	/* Flush TLB */
382239268Sgonzo
383239268Sgonzo	mov	r0, #0
384239268Sgonzo	mcr	p15, 0, r0, c13, c0, 1	/* Set ASID to 0 */
385239268Sgonzo
386239268Sgonzo	/* Set the Domain Access register.  Very important! */
387239268Sgonzo	mov	r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
388239268Sgonzo	mcr	p15, 0, r0, c3, c0, 0
389239268Sgonzo	/* Enable MMU */
390239268Sgonzo	mrc	p15, 0, r0, c1, c0, 0
391239268Sgonzo	orr	r0, r0, #CPU_CONTROL_V6_EXTPAGE
392266058Sian	orr	r0, r0, #CPU_CONTROL_AF_ENABLE
393266385Sian	orr	r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
394266385Sian	    CPU_CONTROL_WBUF_ENABLE)
395266385Sian	orr	r0, r0, #(CPU_CONTROL_IC_ENABLE)
396266385Sian	orr	r0, r0, #(CPU_CONTROL_BPRD_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:
423266385Sian	.asciz	"init_secondary() 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)
433266144Sian	msr     cpsr_fsxc, 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
507266274Sian	add	r0, r0, #SIGF_UC
508245414Sandrew
509245414Sandrew	/*
510245414Sandrew	 * Call the sigreturn system call.
511245414Sandrew	 *
512245414Sandrew	 * We have to load r7 manually rather than using
513245414Sandrew	 * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
514245414Sandrew	 * correct. Using the alternative places esigcode at the address
515245414Sandrew	 * of the data rather than the address one past the data.
516245414Sandrew	 */
517245414Sandrew
518245414Sandrew	ldr	r7, [pc, #12]	/* Load SYS_sigreturn */
519135640Scognet	swi	SYS_sigreturn
520135640Scognet
521135640Scognet	/* Well if that failed we better exit quick ! */
522135640Scognet
523245414Sandrew	ldr	r7, [pc, #8]	/* Load SYS_exit */
524135640Scognet	swi	SYS_exit
525135640Scognet
526245414Sandrew	/* Branch back to retry SYS_sigreturn */
527245414Sandrew	b	. - 16
528269796SianEND(sigcode)
529245414Sandrew	.word	SYS_sigreturn
530245414Sandrew	.word	SYS_exit
531245414Sandrew
532135640Scognet	.align	0
533135640Scognet	.global _C_LABEL(esigcode)
534135640Scognet		_C_LABEL(esigcode):
535143681Sjmg
536135640Scognet	.data
537135640Scognet	.global szsigcode
538135640Scognetszsigcode:
539135640Scognet	.long esigcode-sigcode
540269796Sian
541129198Scognet/* End of locore.S */
542