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