11.44Sskrll/*	$NetBSD: locore.S,v 1.44 2022/04/02 11:16:07 skrll 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.39Sskrll#include "opt_arm_debug.h"
351.39Sskrll
361.1Schris#include "assym.h"
371.39Sskrll#include <sys/cdefs.h>
381.1Schris#include <sys/syscall.h>
391.1Schris#include <sys/errno.h>
401.33Smatt#include <arm/asm.h>
411.33Smatt#include <arm/locore.h>
421.1Schris
431.44Sskrll	RCSID("$NetBSD: locore.S,v 1.44 2022/04/02 11:16:07 skrll Exp $")
441.23Smatt
451.1Schris/*
461.1Schris * This is for kvm_mkdb, and should be the address of the beginning
471.1Schris * of the kernel text segment (not necessarily the same as kernbase).
481.1Schris */
491.1Schris
501.2Sthorpej	.text
511.2Sthorpej	.align	0
521.5Sthorpej
531.5SthorpejENTRY_NP(kernel_text)
541.2Sthorpej
551.1SchrisASENTRY_NP(start)
561.29Smatt	mrs	r1, cpsr		/* fetch CPSR value */
571.29Smatt	msr	spsr_sx, r1		/* set SPSR[23:8] to known value */
581.29Smatt
591.38Sskrll	/*
601.38Sskrll	 * Get bss bounds (r1, r2), curlwp or curcpu (r8), and set initial
611.38Sskrll	 * stack.
621.38Sskrll	 */
631.9Sbjh21	adr	r1, .Lstart
641.38Sskrll	ldmia	r1, {r1, r2, r8, sp}
651.25Smatt
661.27Smatt#if defined(TPIDRPRW_IS_CURCPU) || defined(TPIDRPRW_IS_CURLWP)
671.27Smatt	mcr	p15, 0, r8, c13, c0, 4
681.25Smatt#endif
691.28Smatt#if defined(TPIDRPRW_IS_CURLWP)
701.28Smatt	ldr	r8, [r8, #L_CPU]	/* r8 needs curcpu in it */
711.28Smatt#endif
721.25Smatt
731.32Smatt	mov	r4, #0
741.32Smatt#ifdef _ARM_ARCH_DWORD_OK
751.32Smatt	mov	r5, #0
761.32Smatt#endif
771.7Sbriggs.L1:
781.32Smatt#ifdef _ARM_ARCH_DWORD_OK
791.34Sjoerg	strd	r4, r5, [r1], #0x0008	/* Zero the bss */
801.32Smatt#else
811.32Smatt	str	r4, [r1], #0x0004	/* Zero the bss */
821.32Smatt#endif
831.32Smatt	cmp	r1, r2
841.32Smatt	blt	.L1
851.1Schris
861.27Smatt	mrc	p15, 0, r3, c0, c0, 0	/* get our cpuid and save it early */
871.27Smatt	str	r3, [r8, #CI_ARM_CPUID]
881.27Smatt
891.4Sthorpej	mov	fp, #0x00000000		/* trace back starts here */
901.4Sthorpej	bl	_C_LABEL(initarm)	/* Off we go */
911.1Schris
921.40Sskrll	/* initarm will return the new stack pointer. */
931.1Schris	mov	sp, r0
941.1Schris
951.1Schris	mov	fp, #0x00000000		/* trace back starts here */
961.1Schris	mov	ip, sp
971.33Smatt	push	{fp, ip, lr, pc}
981.1Schris	sub	fp, ip, #4
991.1Schris
1001.4Sthorpej	bl	_C_LABEL(main)		/* call main()! */
1011.1Schris
1021.9Sbjh21	adr	r0, .Lmainreturned
1031.4Sthorpej	b	_C_LABEL(panic)
1041.17Spooka	/* NOTREACHED */
1051.1Schris
1061.39SskrllENTRY_NP(uartputc)
1071.39Sskrll#ifdef EARLYCONS
1081.39Sskrll	b	___CONCAT(EARLYCONS, _platform_early_putchar)
1091.39Sskrll#endif
1101.39Sskrll	RET
1111.39SskrllASEND(uartputc)
1121.39Sskrll
1131.7Sbriggs.Lstart:
1141.1Schris	.word	_edata
1151.1Schris	.word	_end
1161.28Smatt#if defined(TPIDRPRW_IS_CURLWP)
1171.27Smatt	.word	_C_LABEL(lwp0)
1181.27Smatt#else
1191.28Smatt	.word	_C_LABEL(cpu_info_store)
1201.27Smatt#endif
1211.41Sskrll#if !defined(__HAVE_GENERIC_START)
1221.39Sskrll	.word	svcstk_end
1231.41Sskrll#else
1241.41Sskrll	.word   start_stacks_top
1251.41Sskrll#endif
1261.4Sthorpej
1271.8Sthorpej.Lmainreturned:
1281.4Sthorpej	.asciz	"main() returned"
1291.4Sthorpej	.align	0
1301.33SmattASEND(start)
1311.1Schris
1321.41Sskrll#if !defined(__HAVE_GENERIC_START)
1331.1Schris	.bss
1341.37Smatt#ifdef __ARM_EABI__
1351.37Smatt	.align	3
1361.37Smatt#endif
1371.43Sskrll/* What size should this really be ? It is only used by initarm() */
1381.1Schrissvcstk:
1391.1Schris	.space	INIT_ARM_STACK_SIZE
1401.39Sskrllsvcstk_end:
1411.41Sskrll#endif
1421.1Schris
1431.1Schris	.text
1441.1Schris	.align	0
1451.1Schris
1461.1Schris#ifndef OFW
1471.1Schris	/* OFW based systems will used OF_boot() */
1481.36Smatt
1491.36Smatt.Lcpufuncs:
1501.1Schris	.word	_C_LABEL(cpufuncs)
1511.1Schris
1521.1SchrisENTRY_NP(cpu_reset)
1531.27Smatt#ifdef _ARM_ARCH_6
1541.27Smatt	cpsid	if, #PSR_SVC32_MODE
1551.27Smatt#else
1561.7Sbriggs	mrs     r2, cpsr
1571.1Schris	bic	r2, r2, #(PSR_MODE)
1581.1Schris	orr     r2, r2, #(PSR_SVC32_MODE)
1591.24Smatt	orr	r2, r2, #(IF32_bits)
1601.22Schris	msr     cpsr_c, r2
1611.27Smatt#endif
1621.1Schris
1631.8Sthorpej	ldr	r0, .Lcpufuncs
1641.10Sbsh	mov	lr, pc
1651.3Sthorpej	ldr	pc, [r0, #CF_IDCACHE_WBINV_ALL]
1661.1Schris
1671.1Schris	/*
1681.26Smatt	 * Load the virutal address of the MD reset function first.
1691.1Schris	 */
1701.26Smatt	ldr	r4, .Lcpu_reset_address
1711.26Smatt	ldr	r4, [r4]
1721.26Smatt	cmp	r4, #0
1731.1Schris
1741.26Smatt	/*
1751.26Smatt	 * If virtual address is NULL, we must be using the physical address
1761.26Smatt	 */
1771.26Smatt	ldreq	r4, .Lcpu_reset_address_paddr
1781.26Smatt	ldreq	r4, [r4]
1791.1Schris
1801.1Schris	/*
1811.1Schris 	 * MMU & IDC off, 32 bit program & data space
1821.1Schris	 * Hurl ourselves into the ROM
1831.1Schris	 */
1841.27Smatt	mrc	p15, 0, r0, c1, c0, 0
1851.30Smatt	bic	r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE)
1861.30Smatt	bic	r0, r0, #(CPU_CONTROL_IC_ENABLE)
1871.30Smatt	orr	r0, r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
1881.27Smatt	mcr	p15, 0, r0, c1, c0, 0
1891.27Smatt	mcreq	p15, 0, r2, c8, c7, 0 	/* nail I+D TLB on ARMv4 and greater */
1901.1Schris	mov     pc, r4
1911.1Schris
1921.1Schris	/*
1931.26Smatt	 * cpu_reset_address contains the address to branch to, to complete
1941.15Swiz	 * the CPU reset after turning the MMU off
1951.1Schris	 * This variable is provided by the hardware specific code
1961.1Schris	 */
1971.8Sthorpej.Lcpu_reset_address:
1981.1Schris	.word	_C_LABEL(cpu_reset_address)
1991.26Smatt.Lcpu_reset_address_paddr:
2001.26Smatt	.word	_C_LABEL(cpu_reset_address_paddr)
2011.33SmattEND(cpu_reset)
2021.1Schris#endif	/* OFW */
2031.1Schris
2041.44Sskrll
2051.44Sskrll/*
2061.44Sskrll * int cpu_set_onfault(struct faultbuf *fb)
2071.44Sskrll */
2081.44SskrllENTRY_NP(cpu_set_onfault)
2091.44Sskrll	GET_CURPCB(r1)
2101.44Sskrll	str	r0, [r1, #PCB_ONFAULT]
2111.44Sskrll	stmia	r0, {r4-r14}
2121.44Sskrll	mov	r0, #0
2131.44Sskrll	RET
2141.44SskrllEND(cpu_set_onfault)
2151.44Sskrll
2161.1Schris/*
2171.1Schris * setjump + longjmp
2181.1Schris */
2191.1SchrisENTRY(setjmp)
2201.1Schris	stmia	r0, {r4-r14}
2211.1Schris	mov	r0, #0x00000000
2221.33Smatt	RET
2231.33SmattEND(setjmp)
2241.1Schris
2251.1SchrisENTRY(longjmp)
2261.1Schris	ldmia	r0, {r4-r14}
2271.1Schris	mov	r0, #0x00000001
2281.33Smatt	RET
2291.33SmattEND(longjmp)
2301.1Schris
2311.1Schris	.data
2321.1Schris	.global _C_LABEL(esym)
2331.1Schris_C_LABEL(esym):	.word	_C_LABEL(end)
2341.1Schris
2351.1SchrisENTRY_NP(abort)
2361.1Schris	b	_C_LABEL(abort)
2371.33SmattEND(abort)
2381.1Schris
2391.19Schris/*
2401.21Sskrll * Part of doing a system dump, we need to save a switchframe onto the
2411.21Sskrll * stack, then save the rest of the registers into the dumppcb.
2421.19Schris */
2431.19SchrisENTRY(dumpsys)
2441.19Schris	/* push registers onto stack */
2451.20Sskrll	mov	ip, sp
2461.33Smatt	push	{r4-r7, ip, lr}
2471.19Schris
2481.19Schris	/* fill in dumppcb */
2491.19Schris	ldr	r0, .Ldumppcb
2501.19Schris
2511.19Schris#ifndef __XSCALE__
2521.19Schris        add     r2, r0, #(PCB_R8)
2531.19Schris        stmia   r2, {r8-r13}
2541.19Schris#else
2551.35Sjoerg        strd    r8, r9, [r0, #(PCB_R8)]
2561.35Sjoerg        strd    r10, r11, [r0, #(PCB_R10)]
2571.35Sjoerg        strd    r12, r13, [r0, #(PCB_R12)]
2581.19Schris#endif
2591.19Schris
2601.19Schris	bl	_C_LABEL(dodumpsys)
2611.19Schris
2621.19Schris	/* unwind the stack */
2631.33Smatt	pop	{r4-r7, ip, pc}
2641.19Schris
2651.19Schris.Ldumppcb:
2661.19Schris	.word	_C_LABEL(dumppcb)
2671.33SmattEND(dumpsys)
2681.1Schris
2691.1Schris/* End of locore.S */
270