locore-v6.S revision 282024
1276396Sian/*-
2276396Sian * Copyright 2004-2014 Olivier Houchard <cognet@FreeBSD.org>
3276396Sian * Copyright 2012-2014 Ian Lepore <ian@FreeBSD.org>
4276396Sian * Copyright 2013-2014 Andrew Turner <andrew@FreeBSD.org>
5276396Sian * Copyright 2014 Svatopluk Kraus <onwahe@gmail.com>
6276396Sian * Copyright 2014 Michal Meloun <meloun@miracle.cz>
7276396Sian * All rights reserved.
8276396Sian *
9276396Sian * Redistribution and use in source and binary forms, with or without
10276396Sian * modification, are permitted provided that the following conditions
11276396Sian * are met:
12276396Sian * 1. Redistributions of source code must retain the above copyright
13276396Sian *    notice, this list of conditions and the following disclaimer.
14276396Sian * 2. Redistributions in binary form must reproduce the above copyright
15276396Sian *    notice, this list of conditions and the following disclaimer in the
16276396Sian *    documentation and/or other materials provided with the distribution.
17276396Sian *
18276396Sian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19276396Sian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20276396Sian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21276396Sian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22276396Sian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23276396Sian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24276396Sian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25276396Sian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26276396Sian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27276396Sian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28276396Sian * SUCH DAMAGE.
29276396Sian */
30276396Sian
31276396Sian#include "assym.s"
32276396Sian#include <sys/syscall.h>
33276396Sian#include <machine/asm.h>
34276396Sian#include <machine/asmacros.h>
35276396Sian#include <machine/armreg.h>
36276396Sian#include <machine/sysreg.h>
37276396Sian#include <machine/cpuconf.h>
38276396Sian#include <machine/pte.h>
39276396Sian
40276396Sian__FBSDID("$FreeBSD: head/sys/arm/arm/locore-v6.S 282024 2015-04-26 16:18:41Z andrew $");
41276396Sian
42276396Sian#ifndef	ARM_NEW_PMAP
43276396Sian#define	PTE1_OFFSET	L1_S_OFFSET
44276396Sian#define	PTE1_SHIFT	L1_S_SHIFT
45276396Sian#define	PTE1_SIZE	L1_S_SIZE
46276396Sian#endif
47276396Sian
48276396Sian/* A small statically-allocated stack used only during initarm() and AP startup. */
49276396Sian#define	INIT_ARM_STACK_SIZE	2048
50276396Sian
51276396Sian	.text
52276596Sian	.align	2
53276396Sian
54276396Sian/*
55282024Sandrew * On entry for FreeBSD boot ABI:
56282024Sandrew *	r0 - metadata pointer or 0 (boothowto on AT91's boot2)
57282024Sandrew *	r1 - if (r0 == 0) then metadata pointer
58282024Sandrew * On entry for Linux boot ABI:
59276396Sian *	r0 - 0
60276396Sian *	r1 - machine type (passed as arg2 to initarm)
61282024Sandrew *	r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm)
62276396Sian *
63276396Sian * For both types of boot we gather up the args, put them in a struct arm_boot_params
64276396Sian * structure and pass that to initarm.
65276396Sian */
66276396Sian	.globl	btext
67276396Sianbtext:
68276396SianASENTRY_NP(_start)
69282024Sandrew	STOP_UNWINDING		/* Can't unwind into the bootloader! */
70276396Sian
71282024Sandrew	/* Make sure interrupts are disabled. */
72276396Sian	cpsid	ifa
73276396Sian
74282024Sandrew	mov	r8, r0		/* 0 or boot mode from boot2 */
75282024Sandrew	mov	r9, r1		/* Save Machine type */
76282024Sandrew	mov	r10, r2		/* Save meta data */
77276396Sian	mov	r11, r3		/* Future expansion */
78276396Sian
79282024Sandrew	/*
80276396Sian	 * Check whether data cache is enabled.  If it is, then we know
81276396Sian	 * current tags are valid (not power-on garbage values) and there
82276396Sian	 * might be dirty lines that need cleaning.  Disable cache to prevent
83276396Sian	 * new lines being allocated, then call wbinv_poc_all to clean it.
84276396Sian	 */
85276396Sian	mrc	CP15_SCTLR(r7)
86276396Sian	tst	r7, #CPU_CONTROL_DC_ENABLE
87276445Sian	blne	dcache_wbinv_poc_all
88276396Sian
89276445Sian	/* ! Do not write to memory between wbinv and disabling cache ! */
90276445Sian
91276396Sian	/*
92276396Sian	 * Now there are no dirty lines, but there may still be lines marked
93276396Sian	 * valid.  Disable all caches and the MMU, and invalidate everything
94276396Sian	 * before setting up new page tables and re-enabling the mmu.
95276396Sian	 */
96276396Sian1:
97276445Sian	bic	r7, #CPU_CONTROL_DC_ENABLE
98276396Sian	bic	r7, #CPU_CONTROL_MMU_ENABLE
99276396Sian	bic	r7, #CPU_CONTROL_IC_ENABLE
100276396Sian	bic	r7, #CPU_CONTROL_UNAL_ENABLE
101276396Sian	bic	r7, #CPU_CONTROL_BPRD_ENABLE
102276396Sian	bic	r7, #CPU_CONTROL_SW_ENABLE
103276396Sian	orr	r7, #CPU_CONTROL_AFLT_ENABLE
104276396Sian	orr	r7, #CPU_CONTROL_VECRELOC
105276396Sian	mcr	CP15_SCTLR(r7)
106276396Sian	ISB
107276396Sian	bl	dcache_inv_poc_all
108276396Sian	mcr	CP15_ICIALLU
109276396Sian	ISB
110276396Sian
111276396Sian	/*
112276396Sian	 * Build page table from scratch.
113276396Sian	 */
114276396Sian
115276396Sian	/* Calculate the physical address of the startup pagetable. */
116276396Sian	adr	r0, Lpagetable
117276396Sian	bl	translate_va_to_pa
118276396Sian
119276396Sian	/*
120276396Sian	 * Map PA == VA
121276396Sian	 */
122282024Sandrew	/* Find the start kernels load address */
123276396Sian	adr	r5, _start
124276396Sian	ldr	r2, =(PTE1_OFFSET)
125276396Sian	bic	r5, r2
126276396Sian	mov	r1, r5
127276396Sian	mov	r2, r5
128282024Sandrew	/* Map 64MiB, preserved over calls to build_pagetables */
129276396Sian	mov	r3, #64
130276396Sian	bl	build_pagetables
131276396Sian
132276396Sian	/* Create the kernel map to jump to */
133276396Sian	mov	r1, r5
134276396Sian	ldr	r2, =(KERNVIRTADDR)
135276396Sian	bl	build_pagetables
136276396Sian
137276396Sian#if defined(SOCDEV_PA) && defined(SOCDEV_VA)
138276396Sian	/* Create the custom map used for early_printf(). */
139276396Sian	ldr	r1, =SOCDEV_PA
140276396Sian	ldr	r2, =SOCDEV_VA
141276396Sian	bl	build_pagetables
142276396Sian#endif
143276396Sian	bl	init_mmu
144276396Sian
145282024Sandrew	/* Switch to virtual addresses. */
146276396Sian	ldr	pc, =1f
147276396Sian1:
148276396Sian
149282024Sandrew	/* Setup stack, clear BSS */
150276396Sian	ldr	r1, =.Lstart
151276396Sian	ldmia	r1, {r1, r2, sp}	/* Set initial stack and */
152276396Sian	add	sp, sp,	#INIT_ARM_STACK_SIZE
153282024Sandrew	sub	r2, r2, r1		/* get zero init data */
154276396Sian	mov	r3, #0
155276396Sian2:
156276396Sian	str	r3, [r1], #0x0004	/* get zero init data */
157282024Sandrew	subs	r2, r2, #4
158276396Sian	bgt	2b
159276396Sian
160282024Sandrew	mov	r1, #28			/* loader info size is 28 bytes also second arg */
161282024Sandrew	subs	sp, sp, r1		/* allocate arm_boot_params struct on stack */
162282024Sandrew	mov	r0, sp			/* loader info pointer is first arg */
163282024Sandrew	bic	sp, sp, #7		/* align stack to 8 bytes */
164282024Sandrew	str	r1, [r0]		/* Store length of loader info */
165276396Sian	str	r8, [r0, #4]		/* Store r0 from boot loader */
166276396Sian	str	r9, [r0, #8]		/* Store r1 from boot loader */
167276396Sian	str	r10, [r0, #12]		/* store r2 from boot loader */
168276396Sian	str	r11, [r0, #16]		/* store r3 from boot loader */
169276396Sian	str	r5, [r0, #20]		/* store the physical address */
170282024Sandrew	adr	r4, Lpagetable		/* load the pagetable address */
171276396Sian	ldr	r5, [r4, #4]
172276396Sian	str	r5, [r0, #24]		/* store the pagetable address */
173276396Sian	mov	fp, #0			/* trace back starts here */
174276396Sian	bl	_C_LABEL(initarm)	/* Off we go */
175276396Sian
176282024Sandrew	/* init arm will return the new stack pointer. */
177276396Sian	mov	sp, r0
178276396Sian
179282024Sandrew	bl	_C_LABEL(mi_startup)	/* call mi_startup()! */
180276396Sian
181276396Sian	ldr	r0, =.Lmainreturned
182276396Sian	b	_C_LABEL(panic)
183276396Sian	/* NOTREACHED */
184276396SianEND(_start)
185276396Sian
186276396Sian#define VA_TO_PA_POINTER(name, table)	 \
187276396Sianname:					;\
188276396Sian	.word	.			;\
189276396Sian	.word	table
190276396Sian
191276396Sian/*
192276396Sian * Returns the physical address of a magic va to pa pointer.
193276396Sian * r0     - The pagetable data pointer. This must be built using the
194276396Sian *          VA_TO_PA_POINTER macro.
195276396Sian *          e.g.
196276396Sian *            VA_TO_PA_POINTER(Lpagetable, pagetable)
197276396Sian *            ...
198276396Sian *            adr  r0, Lpagetable
199276396Sian *            bl   translate_va_to_pa
200276396Sian *            r0 will now contain the physical address of pagetable
201276396Sian * r1, r2 - Trashed
202276396Sian */
203276396Siantranslate_va_to_pa:
204276396Sian	ldr	r1, [r0]
205276396Sian	sub	r2, r1, r0
206276396Sian	/* At this point: r2 = VA - PA */
207276396Sian
208276396Sian	/*
209276396Sian	 * Find the physical address of the table. After these two
210276396Sian	 * instructions:
211276396Sian	 * r1 = va(pagetable)
212276396Sian	 *
213276396Sian	 * r0 = va(pagetable) - (VA - PA)
214276396Sian	 *    = va(pagetable) - VA + PA
215276396Sian	 *    = pa(pagetable)
216276396Sian	 */
217276396Sian	ldr	r1, [r0, #4]
218276396Sian	sub	r0, r1, r2
219276396Sian	mov	pc, lr
220276396Sian
221276396Sian/*
222282024Sandrew * Init MMU
223282024Sandrew * r0 - the table base address
224276396Sian */
225276396Sian
226276396SianASENTRY_NP(init_mmu)
227276396Sian
228276396Sian	/* Setup TLB and MMU registers */
229276396Sian	mcr	CP15_TTBR0(r0)		/* Set TTB */
230276396Sian	mov	r0, #0
231276396Sian	mcr	CP15_CONTEXTIDR(r0)	/* Set ASID to 0 */
232276396Sian
233276396Sian	/* Set the Domain Access register */
234276396Sian	mov	r0, #((DOMAIN_CLIENT <<	(PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
235276396Sian	mcr	CP15_DACR(r0)
236276396Sian
237276396Sian#ifdef ARM_NEW_PMAP
238276396Sian	/*
239276396Sian	 * Set TEX remap registers
240276396Sian	 *  - All is set to uncacheable memory
241276396Sian	 */
242276396Sian	ldr	r0, =0xAAAAA
243276396Sian	mrc	CP15_PRRR(r0)
244276396Sian	mov	r0, #0
245276396Sian	mcr	CP15_NMRR(r0)
246276396Sian#endif
247276396Sian	mcr	CP15_TLBIALL		/* Flush TLB */
248276396Sian	DSB
249276396Sian	ISB
250276396Sian
251276396Sian	/* Enable MMU */
252276396Sian	mrc	CP15_SCTLR(r0)
253276396Sian	orr	r0, r0,	#CPU_CONTROL_MMU_ENABLE
254276396Sian	orr	r0, r0,	#CPU_CONTROL_V6_EXTPAGE
255276396Sian#ifdef ARM_NEW_PMAP
256276396Sian	orr	r0, r0,	#CPU_CONTROL_TR_ENABLE
257276396Sian#endif
258276396Sian	orr	r0, r0,	#CPU_CONTROL_AF_ENABLE
259276396Sian	mcr	CP15_SCTLR(r0)
260276396Sian	DSB
261276396Sian	ISB
262276396Sian	mcr	CP15_TLBIALL		/* Flush TLB */
263276396Sian	mcr	CP15_BPIALL		/* Flush Branch predictor */
264276396Sian	ISB
265276396Sian	mov	pc, lr
266276396SianEND(init_mmu)
267276396Sian
268276396Sian
269276396Sian/*
270282024Sandrew * Init SMP coherent mode, enable caching and switch to final MMU table.
271282024Sandrew * Called with disabled caches
272282024Sandrew * r0 - The table base address
273282024Sandrew * r1 - clear bits for aux register
274282024Sandrew * r2 - set bits for aux register
275276396Sian */
276276396SianASENTRY_NP(reinit_mmu)
277276396Sian	push	{r4-r11, lr}
278276396Sian	mov	r4, r0
279276396Sian	mov	r5, r1
280276396Sian	mov	r6, r2
281276396Sian
282276396Sian	/* !! Be very paranoid here !! */
283276396Sian	/* !! We cannot write single bit here !! */
284276396Sian
285276396Sian#if 0	/* XXX writeback shouldn't be necessary */
286276396Sian	/* Write back and invalidate all integrated caches */
287276396Sian	bl 	dcache_wbinv_poc_all
288276396Sian#else
289276396Sian	bl	dcache_inv_pou_all
290276396Sian#endif
291276396Sian	mcr	CP15_ICIALLU
292276396Sian	ISB
293276396Sian
294276396Sian	/* Set auxiliary register */
295276396Sian	mrc	CP15_ACTLR(r7)
296276396Sian	bic	r8, r7, r5		/* Mask bits */
297276396Sian	eor 	r8, r8, r6		/* Set bits */
298276396Sian	teq 	r7, r8
299276396Sian	mcrne 	CP15_ACTLR(r8)
300276396Sian	ISB
301276396Sian
302276396Sian	/* Enable caches. */
303276396Sian	mrc	CP15_SCTLR(r7)
304276396Sian	orr	r7, #CPU_CONTROL_DC_ENABLE
305276396Sian	orr	r7, #CPU_CONTROL_IC_ENABLE
306276396Sian	orr	r7, #CPU_CONTROL_BPRD_ENABLE
307276396Sian	mcr	CP15_SCTLR(r7)
308276396Sian	DSB
309276396Sian
310276396Sian	mcr	CP15_TTBR0(r4)		/* Set new TTB */
311276396Sian	DSB
312276396Sian	ISB
313276396Sian
314276396Sian	/* Flush all TLBs */
315276396Sian	mcr	CP15_TLBIALL
316276396Sian	DSB
317276396Sian	ISB
318276396Sian
319276396Sian#if 0 /* XXX writeback shouldn't be necessary */
320276396Sian	/* Write back and invalidate all integrated caches */
321276396Sian	bl 	dcache_wbinv_poc_all
322276396Sian#else
323276396Sian	bl	dcache_inv_pou_all
324276396Sian#endif
325276396Sian	mcr	CP15_ICIALLU
326276396Sian	ISB
327276396Sian
328276396Sian	pop	{r4-r11, pc}
329276396SianEND(reinit_mmu)
330276396Sian
331276396Sian
332276396Sian/*
333276396Sian * Builds the page table
334282024Sandrew * r0 - The table base address
335282024Sandrew * r1 - The physical address (trashed)
336282024Sandrew * r2 - The virtual address (trashed)
337282024Sandrew * r3 - The number of 1MiB sections
338282024Sandrew * r4 - Trashed
339276396Sian *
340276396Sian * Addresses must be 1MiB aligned
341276396Sian */
342276470Sianbuild_pagetables:
343276396Sian	/* Set the required page attributed */
344276396Sian#if defined(ARM_NEW_PMAP)
345276396Sian	ldr	r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0
346276396Sian#elif defined(SMP)
347276396Sian	ldr	r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)|L1_SHARED)
348276396Sian#else
349276396Sian	ldr	r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
350276396Sian#endif
351276396Sian	orr	r1, r4
352276396Sian
353282024Sandrew	/* Move the virtual address to the correct bit location */
354276396Sian	lsr	r2, #(PTE1_SHIFT - 2)
355276396Sian
356276396Sian	mov	r4, r3
357276396Sian1:
358276396Sian	str	r1, [r0, r2]
359282024Sandrew	add	r2, r2, #4
360282024Sandrew	add	r1, r1, #(PTE1_SIZE)
361282024Sandrew	adds	r4, r4, #-1
362276396Sian	bhi	1b
363276396Sian
364276396Sian	mov	pc, lr
365276396Sian
366276396SianVA_TO_PA_POINTER(Lpagetable, boot_pt1)
367276396Sian
368276396Sian
369276396Sian.Lstart:
370277305Sian	.word	_edata			/* Note that these three items are */
371277305Sian	.word	_ebss			/* loaded with a single ldmia and */
372277305Sian	.word	svcstk			/* must remain in order together. */
373276396Sian
374276396Sian.Lmainreturned:
375282024Sandrew	.asciz	"main() returned"
376276596Sian	.align	2
377276396Sian
378276396Sian	.bss
379276396Siansvcstk:
380276396Sian	.space	INIT_ARM_STACK_SIZE * MAXCPU
381276396Sian
382276396Sian/*
383282024Sandrew * Memory for the initial pagetable. We are unable to place this in
384282024Sandrew * the bss as this will be cleared after the table is loaded.
385276396Sian */
386276396Sian	.section ".init_pagetable"
387276396Sian	.align	14 /* 16KiB aligned */
388276396Sian	.globl	boot_pt1
389276396Sianboot_pt1:
390276396Sian	.space	L1_TABLE_SIZE
391276396Sian
392276396Sian	.text
393276596Sian	.align	2
394276396Sian
395276396Sian.Lcpufuncs:
396276396Sian	.word	_C_LABEL(cpufuncs)
397276396Sian
398276396Sian#if defined(SMP)
399276396Sian
400276396SianASENTRY_NP(mpentry)
401282024Sandrew	/* Make sure interrupts are disabled. */
402276396Sian	cpsid	ifa
403276396Sian
404276396Sian	/* Setup core, disable all caches. */
405276396Sian	mrc	CP15_SCTLR(r0)
406276396Sian	bic	r0, #CPU_CONTROL_MMU_ENABLE
407276396Sian	bic	r0, #CPU_CONTROL_DC_ENABLE
408276396Sian	bic	r0, #CPU_CONTROL_IC_ENABLE
409276396Sian	bic	r0, #CPU_CONTROL_UNAL_ENABLE
410276396Sian	bic	r0, #CPU_CONTROL_BPRD_ENABLE
411276396Sian	bic	r0, #CPU_CONTROL_SW_ENABLE
412276396Sian	orr	r0, #CPU_CONTROL_AFLT_ENABLE
413276396Sian	orr	r0, #CPU_CONTROL_VECRELOC
414276396Sian	mcr	CP15_SCTLR(r0)
415276396Sian	ISB
416276396Sian
417276396Sian	/* Invalidate L1 cache I+D cache */
418276396Sian	bl	dcache_inv_pou_all
419276396Sian	mcr	CP15_ICIALLU
420276396Sian	ISB
421276396Sian
422282024Sandrew	/* Find the delta between VA and PA */
423276396Sian	adr	r0, Lpagetable
424276396Sian	bl	translate_va_to_pa
425276396Sian
426276396Sian	bl	init_mmu
427276396Sian
428277305Sian	adr	r1, .Lstart+8		/* Get initstack pointer from */
429277305Sian	ldr	sp, [r1]		/* startup data. */
430277305Sian	mrc	CP15_MPIDR(r0)		/* Get processor id number. */
431277305Sian	and	r0, r0,	#0x0f
432276396Sian	mov	r1, #INIT_ARM_STACK_SIZE
433277305Sian	mul	r2, r1,	r0		/* Point sp to initstack */
434277305Sian	add	sp, sp,	r2		/* area for this processor. */
435276396Sian
436282024Sandrew	/* Switch to virtual addresses. */
437276396Sian	ldr	pc, =1f
438276396Sian1:
439276396Sian	mov	fp, #0			/* trace back starts here */
440277305Sian	bl	_C_LABEL(init_secondary)/* Off we go, cpu id in r0. */
441276396Sian
442276396Sian	adr	r0, .Lmpreturned
443276396Sian	b	_C_LABEL(panic)
444276396Sian	/* NOTREACHED */
445276596SianEND(mpentry)
446276396Sian
447276396Sian.Lmpreturned:
448276396Sian	.asciz	"init_secondary() returned"
449276596Sian	.align	2
450276396Sian#endif
451276396Sian
452276396SianENTRY_NP(cpu_halt)
453276396Sian
454276396Sian	/* XXX re-implement !!! */
455276396Sian	cpsid	ifa
456276396Sian	bl	dcache_wbinv_poc_all
457276396Sian
458276396Sian	ldr	r4, .Lcpu_reset_address
459276396Sian	ldr	r4, [r4]
460276396Sian	teq	r4, #0
461276396Sian	movne	pc, r4
462276396Sian1:
463276519Sian	WFI
464276396Sian	b	1b
465276396Sian
466276396Sian	/*
467276396Sian	 * _cpu_reset_address contains the address to branch to, to complete
468276396Sian	 * the cpu reset after turning the MMU off
469282024Sandrew	 * This variable is provided by the hardware specific code
470276396Sian	 */
471276396Sian.Lcpu_reset_address:
472276396Sian	.word	_C_LABEL(cpu_reset_address)
473276396SianEND(cpu_halt)
474276396Sian
475276396Sian
476276396Sian/*
477276396Sian * setjump + longjmp
478276396Sian */
479276396SianENTRY(setjmp)
480276396Sian	stmia	r0, {r4-r14}
481276396Sian	mov	r0, #0x00000000
482276396Sian	RET
483276396SianEND(setjmp)
484276396Sian
485276396SianENTRY(longjmp)
486276396Sian	ldmia	r0, {r4-r14}
487276396Sian	mov	r0, #0x00000001
488276396Sian	RET
489276396SianEND(longjmp)
490276396Sian
491276396Sian	.data
492276396Sian	.global	_C_LABEL(esym)
493276396Sian_C_LABEL(esym):	.word	_C_LABEL(end)
494276396Sian
495276396SianENTRY_NP(abort)
496276396Sian	b	_C_LABEL(abort)
497276396SianEND(abort)
498276396Sian
499276396SianENTRY_NP(sigcode)
500276396Sian	mov	r0, sp
501282024Sandrew	add	r0, r0, #SIGF_UC
502276396Sian
503276396Sian	/*
504282024Sandrew	 * Call the sigreturn system call.
505276396Sian	 *
506276396Sian	 * We have to load r7 manually rather than using
507282024Sandrew	 * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
508276396Sian	 * correct. Using the alternative places esigcode at the address
509282024Sandrew	 * of the data rather than the address one past the data.
510276396Sian	 */
511276396Sian
512282024Sandrew	ldr	r7, [pc, #12]	/* Load SYS_sigreturn */
513276396Sian	swi	SYS_sigreturn
514276396Sian
515282024Sandrew	/* Well if that failed we better exit quick ! */
516276396Sian
517282024Sandrew	ldr	r7, [pc, #8]	/* Load SYS_exit */
518276396Sian	swi	SYS_exit
519276396Sian
520282024Sandrew	/* Branch back to retry SYS_sigreturn */
521276396Sian	b	. - 16
522276470SianEND(sigcode)
523276396Sian	.word	SYS_sigreturn
524276396Sian	.word	SYS_exit
525276396Sian
526276596Sian	.align	2
527282024Sandrew	.global _C_LABEL(esigcode)
528276396Sian		_C_LABEL(esigcode):
529276396Sian
530276396Sian	.data
531282024Sandrew	.global szsigcode
532276396Sianszsigcode:
533276396Sian	.long esigcode-sigcode
534276470Sian
535276396Sian/* End of locore.S */
536