locore.S revision 1.1
11.1Schris/*	$NetBSD: locore.S,v 1.1 2001/07/28 15:08:11 chris Exp $	*/
21.1Schris
31.1Schris/*
41.1Schris * Copyright (C) 1994-1997 Mark Brinicombe
51.1Schris * Copyright (C) 1994 Brini
61.1Schris * All rights reserved.
71.1Schris *
81.1Schris * Redistribution and use in source and binary forms, with or without
91.1Schris * modification, are permitted provided that the following conditions
101.1Schris * are met:
111.1Schris * 1. Redistributions of source code must retain the above copyright
121.1Schris *    notice, this list of conditions and the following disclaimer.
131.1Schris * 2. Redistributions in binary form must reproduce the above copyright
141.1Schris *    notice, this list of conditions and the following disclaimer in the
151.1Schris *    documentation and/or other materials provided with the distribution.
161.1Schris * 3. All advertising materials mentioning features or use of this software
171.1Schris *    must display the following acknowledgement:
181.1Schris *	This product includes software developed by Brini.
191.1Schris * 4. The name of Brini may not be used to endorse or promote products
201.1Schris *    derived from this software without specific prior written permission.
211.1Schris *
221.1Schris * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
231.1Schris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
241.1Schris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
251.1Schris * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
261.1Schris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
271.1Schris * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
281.1Schris * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
291.1Schris * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
301.1Schris * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
311.1Schris * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
321.1Schris */
331.1Schris
341.1Schris#include "opt_ipkdb.h"
351.1Schris#include "assym.h"
361.1Schris#include <sys/syscall.h>
371.1Schris#include <sys/errno.h>
381.1Schris#include <machine/asm.h>
391.1Schris#include <machine/cpu.h>
401.1Schris#include <machine/frame.h>
411.1Schris#include <machine/param.h>
421.1Schris
431.1Schris/* What size should this really be ? It is only used by init_arm() */
441.1Schris#define INIT_ARM_STACK_SIZE	2048
451.1Schris
461.1Schris/*
471.1Schris * This is for kvm_mkdb, and should be the address of the beginning
481.1Schris * of the kernel text segment (not necessarily the same as kernbase).
491.1Schris */
501.1Schris
511.1Schris#ifndef netwinder
521.1SchrisENTRY_NP(kernel_text)
531.1Schris#endif
541.1Schris
551.1SchrisASENTRY_NP(start)
561.1Schris	add	r1, pc, #(Lstart - . - 8)
571.1Schris	ldmia	r1, {r1, r2, sp}		/* Set initial stack and */
581.1Schris	sub	r2, r2, r1			/* get zero init data */
591.1Schris	mov	r3, #0
601.1Schris
611.1SchrisL1:
621.1Schris	str	r3, [r1], #0x0004		/* Zero the bss */
631.1Schris	subs	r2, r2, #4
641.1Schris	bgt	L1
651.1Schris
661.1Schris	mov	fp, #0x00000000			/* trace back starts here */
671.1Schris	bl	_C_LABEL(initarm)		/* Off we go */
681.1Schris
691.1Schris	/* init arm will return the new stack pointer. */
701.1Schris	mov	sp, r0
711.1Schris
721.1Schris	mov	fp, #0x00000000		/* trace back starts here */
731.1Schris	mov	ip, sp
741.1Schris	stmfd	sp!, {fp, ip, lr, pc}
751.1Schris	sub	fp, ip, #4
761.1Schris
771.1Schris	/* Setup an initial trap frame for start_init to use */
781.1Schris
791.1Schris	PUSHFRAME
801.1Schris
811.1Schris	mov	r0, sp			/* parameter to main is trap frame */
821.1Schris
831.1Schris	bl	_C_LABEL(main)		/* Lets light the flame and start her up */
841.1Schris
851.1Schris	PULLFRAME			/* Pull the trap frame, now valid */
861.1Schris
871.1Schris	movs	pc, lr			/* Exit to user process */
881.1Schris
891.1Schris	/* Never gets here */
901.1Schris
911.1Schris	b	.
921.1Schris
931.1SchrisLstart:
941.1Schris	.word	_edata
951.1Schris	.word	_end
961.1Schris	.word	svcstk + INIT_ARM_STACK_SIZE
971.1Schris
981.1Schris	.bss
991.1Schrissvcstk:
1001.1Schris	.space	INIT_ARM_STACK_SIZE
1011.1Schris
1021.1Schris/*
1031.1Schris * Instructions to copy to the bottom of zero page
1041.1Schris * These are the entry point to the system exception routines
1051.1Schris */
1061.1Schris
1071.1Schris	.text
1081.1Schris	.align	0
1091.1Schris	.global	_C_LABEL(page0), _C_LABEL(page0_end)
1101.1Schris_C_LABEL(page0):
1111.1Schris	ldr	pc, [pc, #Lreset - . - 8]
1121.1Schris	ldr	pc, [pc, #Lundefined - . - 8]
1131.1Schris	ldr	pc, [pc, #Lswi - . - 8]
1141.1Schris	ldr	pc, [pc, #Labortpre - . - 8]
1151.1Schris	ldr	pc, [pc, #Labortdata - . - 8]
1161.1Schris	ldr	pc, [pc, #Laddrexc - . - 8]
1171.1Schris	ldr	pc, [pc, #Lirq - . - 8]
1181.1Schris	ldr	pc, [pc, #Lfiq - . - 8]
1191.1Schris
1201.1SchrisLreset:
1211.1Schris	.word	reset_entry
1221.1SchrisLundefined:
1231.1Schris	.word	undefined_entry
1241.1SchrisLswi:
1251.1Schris	.word	swi_entry
1261.1SchrisLabortpre:
1271.1Schris	.word	prefetch_abort_entry
1281.1SchrisLabortdata:
1291.1Schris	.word	data_abort_entry
1301.1SchrisLaddrexc:
1311.1Schris	.word	addrexc
1321.1SchrisLirq:
1331.1Schris	.word	irq_entry
1341.1SchrisLfiq:
1351.1Schris	.word	fiq
1361.1Schris_C_LABEL(page0_end) =	.
1371.1Schris
1381.1Schris/* vector 0x00000000 - RESET */
1391.1Schris
1401.1SchrisASENTRY_NP(reset_entry)
1411.1Schris	PUSHFRAME
1421.1Schris
1431.1Schris 	mov	r0, sp			/* Pass the frame to function */
1441.1Schris	b	_C_LABEL(resethandler)	/* It's a branch throught zero ! */
1451.1Schris
1461.1Schris/* vector 0x00000008 - ADDRESS EXCEPTION */
1471.1Schris
1481.1SchrisASENTRY_NP(addrexc)
1491.1Schris	mrs	r1, cpsr_all
1501.1Schris	mrs	r2, spsr_all
1511.1Schris	mov	r3, lr
1521.1Schris	add	r0, pc, #Laddrexcmsg - . - 8
1531.1Schris	bl	_C_LABEL(printf)
1541.1Schris	b	data_abort_entry
1551.1Schris
1561.1SchrisLaddrexcmsg:
1571.1Schris	.asciz	"address exception CPSR=%08x SPSR=%08x lr=%08x\n"
1581.1Schris	.align	0
1591.1Schris
1601.1Schris/* vector 0x0000001C - FIQ */
1611.1Schris
1621.1SchrisASENTRY_NP(fiq)
1631.1Schris	ldr	r0, Lfiqmsg
1641.1Schris	b	_C_LABEL(panic)
1651.1Schris
1661.1SchrisLfiqmsg:
1671.1Schris	.asciz	"fiq"
1681.1Schris	.align	0
1691.1Schris
1701.1Schris#ifndef OFW
1711.1Schris	/* OFW based systems will used OF_boot() */
1721.1Schris
1731.1SchrisLcpufuncs:
1741.1Schris	.word	_C_LABEL(cpufuncs)
1751.1Schris
1761.1SchrisENTRY_NP(cpu_reset)
1771.1Schris	mrs     r2, cpsr_all
1781.1Schris	bic	r2, r2, #(PSR_MODE)
1791.1Schris	orr     r2, r2, #(PSR_SVC32_MODE)
1801.1Schris	orr	r2, r2, #(I32_bit | F32_bit)
1811.1Schris	msr     cpsr_all, r2
1821.1Schris
1831.1Schris	ldr	r4, Lcpu_reset_address
1841.1Schris	ldr	r4, [r4]
1851.1Schris
1861.1Schris	ldr	r0, Lcpufuncs
1871.1Schris	add	lr, pc, #Lboot_cache_purged - . - 8
1881.1Schris	ldr	pc, [r0, #CF_CACHE_PURGE_ID]
1891.1Schris
1901.1SchrisLboot_cache_purged:
1911.1Schris
1921.1Schris	/*
1931.1Schris	 * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's
1941.1Schris	 * necessary.
1951.1Schris	 */
1961.1Schris
1971.1Schris	ldr	r1, Lcpu_reset_needs_v4_MMU_disable
1981.1Schris	ldr	r1, [r1]
1991.1Schris	cmp	r1, #0
2001.1Schris
2011.1Schris	/*
2021.1Schris 	 * MMU & IDC off, 32 bit program & data space
2031.1Schris	 * Hurl ourselves into the ROM
2041.1Schris	 */
2051.1Schris	mov	r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
2061.1Schris	mcr     15, 0, r0, c1, c0, 0
2071.1Schris	mcrne   15, 0, r0, c8, c7, 0 	/* only when v4 MMU disable is asked for */
2081.1Schris	mov     pc, r4
2091.1Schris
2101.1Schris	/*
2111.1Schris	 * _cpu_reset_address contains the address to branch to, to complete
2121.1Schris	 * the cpu reset after turning the MMU off
2131.1Schris	 * This variable is provided by the hardware specific code
2141.1Schris	 */
2151.1SchrisLcpu_reset_address:
2161.1Schris	.word	_C_LABEL(cpu_reset_address)
2171.1Schris
2181.1Schris	/*
2191.1Schris	 * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the
2201.1Schris	 * v4 MMU disable instruction needs executing... it is an illegal instruction
2211.1Schris	 * on f.e. ARM6/7 that locks up the computer in an endless illegal
2221.1Schris	 * instruction / data-abort / reset loop.
2231.1Schris	 */
2241.1SchrisLcpu_reset_needs_v4_MMU_disable:
2251.1Schris	.word	_C_LABEL(cpu_reset_needs_v4_MMU_disable)
2261.1Schris
2271.1Schris#endif	/* OFW */
2281.1Schris
2291.1Schris#ifdef IPKDB
2301.1Schris#if	0
2311.1Schris/*
2321.1Schris * ipkdbfbyte and ipkdbsbyte are now in ipkdb_glue.c and do not tweak
2331.1Schris * the abort handler anymore
2341.1Schris */
2351.1SchrisENTRY_NP(ipkdbfbyte)
2361.1Schris	ldr	ip, abortp
2371.1Schris	ldr	r2, [ip]
2381.1Schris	add	r3, pc, #ipkdbfault - . - 8
2391.1Schris	str	r3, [ip]
2401.1Schris	ldrb	r0, [r0]
2411.1Schris	str	r2, [ip]
2421.1Schris	mov	pc, lr
2431.1Schris
2441.1SchrisENTRY_NP(ipkdbsbyte)
2451.1Schris	ldr	ip, abortp
2461.1Schris	ldr	r2, [ip]
2471.1Schris	add	r3, pc, #ipkdbfault - . - 8
2481.1Schris	str	r3, [ip]
2491.1Schris	strb	r1, [r0]
2501.1Schris	sub	r0, r0, r0
2511.1Schris	str	r2, [ip]
2521.1Schris	mov	pc, lr
2531.1Schris
2541.1Schrisabortp:
2551.1Schris	.word	Labortdata - _C_LABEL(page0)
2561.1Schrisipkdbfault:
2571.1Schris	mov	r0, #0xd3
2581.1Schris	msr	cpsr_all, r0
2591.1Schris	mvn	r0, #0			/* mov	r0, #-1 */
2601.1Schris	str	r2, [ip]
2611.1Schris	mov	pc, lr
2621.1Schris#endif
2631.1Schris
2641.1Schris/*
2651.1Schris * Execute(inst, psr, args, sp)
2661.1Schris *
2671.1Schris * Execute INSTruction with PSR and ARGS[0] - ARGS[3] making
2681.1Schris * available stack at SP for next undefined instruction trap.
2691.1Schris *
2701.1Schris * Move the instruction onto the stack and jump to it.
2711.1Schris */
2721.1SchrisENTRY_NP(Execute)
2731.1Schris	mov	ip, sp
2741.1Schris	stmfd	sp!, {r2, r4-r7, fp, ip, lr, pc}
2751.1Schris	sub	fp, ip, #4
2761.1Schris	mov	ip, r3
2771.1Schris	ldr	r7, return
2781.1Schris	stmfd	sp!, {r0, r7}
2791.1Schris	add	r7, pc, #LExec - . - 8
2801.1Schris	mov	r5, r1
2811.1Schris	mrs	r4, cpsr_all
2821.1Schris	ldmia	r2, {r0-r3}
2831.1Schris	mov	r6, sp
2841.1Schris	mov	sp, ip
2851.1Schris	msr	cpsr_all, r5
2861.1Schris	mov	pc, r6
2871.1SchrisLExec:
2881.1Schris	mrs	r5, cpsr_all
2891.1Schris/* XXX Cannot switch thus easily back from user mode */
2901.1Schris	msr	cpsr_all, r4
2911.1Schris	add	sp, r6, #8
2921.1Schris	ldmfd	sp!, {r6}
2931.1Schris	stmia	r6, {r0-r3}
2941.1Schris	mov	r0, r5
2951.1Schris	ldmdb	fp, {r4-r7, fp, sp, pc}
2961.1Schrisreturn:
2971.1Schris	mov	pc, r7
2981.1Schris#endif
2991.1Schris
3001.1Schris/*
3011.1Schris * setjump + longjmp
3021.1Schris */
3031.1SchrisENTRY(setjmp)
3041.1Schris	stmia	r0, {r4-r14}
3051.1Schris	mov	r0, #0x00000000
3061.1Schris	mov	pc, lr
3071.1Schris
3081.1SchrisENTRY(longjmp)
3091.1Schris	ldmia	r0, {r4-r14}
3101.1Schris	mov	r0, #0x00000001
3111.1Schris	mov	pc, lr
3121.1Schris
3131.1Schris	.data
3141.1Schris	.global _C_LABEL(esym)
3151.1Schris_C_LABEL(esym):	.word	_C_LABEL(end)
3161.1Schris
3171.1SchrisENTRY_NP(abort)
3181.1Schris	b	_C_LABEL(abort)
3191.1Schris
3201.1Schris
3211.1Schris/*
3221.1Schris * Atomic bit set and clear functions
3231.1Schris */
3241.1Schris
3251.1SchrisENTRY(atomic_set_bit)
3261.1Schris	mrs	r2, cpsr_all
3271.1Schris	orr	r3, r2, #(I32_bit)
3281.1Schris	msr	cpsr_all, r3
3291.1Schris
3301.1Schris	ldr	r3, [r0]
3311.1Schris	orr	r3, r3, r1
3321.1Schris	str	r3, [r0]
3331.1Schris
3341.1Schris	msr	cpsr_all, r2
3351.1Schris	mov	pc, lr
3361.1Schris
3371.1Schris
3381.1SchrisENTRY(atomic_clear_bit)
3391.1Schris	mrs	r2, cpsr_all
3401.1Schris	orr	r3, r2, #(I32_bit)
3411.1Schris	msr	cpsr_all, r3
3421.1Schris
3431.1Schris	ldr	r3, [r0]
3441.1Schris	bic	r3, r3, r1
3451.1Schris	str	r3, [r0]
3461.1Schris
3471.1Schris	msr	cpsr_all, r2
3481.1Schris	mov	pc, lr
3491.1Schris
3501.1Schris/* End of locore.S */
351