11.6Sandvar/* $NetBSD: start.S,v 1.6 2024/02/09 17:39:33 andvar Exp $ */ 21.1Sreinoud 31.1Sreinoud/* 41.1Sreinoud * Copyright (c) 2002 Reinoud Zandijk 51.1Sreinoud * All rights reserved. 61.1Sreinoud * 71.1Sreinoud * Redistribution and use in source and binary forms, with or without 81.1Sreinoud * modification, are permitted provided that the following conditions 91.1Sreinoud * are met: 101.1Sreinoud * 1. Redistributions of source code must retain the above copyright 111.1Sreinoud * notice, this list of conditions and the following disclaimer. 121.1Sreinoud * 2. Redistributions in binary form must reproduce the above copyright 131.1Sreinoud * notice, this list of conditions and the following disclaimer in the 141.1Sreinoud * documentation and/or other materials provided with the distribution. 151.1Sreinoud * 3. The name of the author may not be used to endorse or promote products 161.1Sreinoud * derived from this software without specific prior written permission. 171.1Sreinoud * 181.1Sreinoud * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 191.1Sreinoud * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 201.1Sreinoud * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 211.1Sreinoud * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 221.1Sreinoud * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 231.1Sreinoud * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 241.1Sreinoud * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 251.1Sreinoud * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 261.1Sreinoud * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 271.1Sreinoud * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 281.1Sreinoud */ 291.1Sreinoud 301.1Sreinoud#include <machine/asm.h> 311.1Sreinoud#include <arm/armreg.h> 321.1Sreinoud#include <riscoscalls.h> 331.1Sreinoud 341.1Sreinoud 351.1Sreinoud/* ----------------------------------------------------------------------- */ 361.1SreinoudENTRY(relocate_code) 371.1Sreinoud /* 381.1Sreinoud - r0 pointer to configuration structure 391.1Sreinoud - r1 pointer to physical restart point 401.1Sreinoud - r3 pointer to physical new L1 page address (P) 411.1Sreinoud - r4 kernel entry point 421.1Sreinoud */ 431.1Sreinoud 441.1Sreinoud /* save registers / move args up in register bank later */ 451.1Sreinoud /* r8-r12 becomes r0-r4 */ 461.1Sreinoud stmfd sp!, {r0-r4} 471.1Sreinoud ldmfd sp!, {r8-r12} 481.1Sreinoud 491.1Sreinoud /* 501.5Sandvar * determine processor architecture version. This is necessary for the 511.1Sreinoud * correct coprocessor instruction. 521.1Sreinoud */ 531.4Sjoerg mrc p15, 0, r0, c0, c0, 0 /* read CPU id in r0 */ 541.1Sreinoud mov r3, r0 /* store in r3 */ 551.1Sreinoud 561.1Sreinoud /* assume its ARMv4 instruction set */ 571.1Sreinoud mov r14, #1 581.1Sreinoud 591.1Sreinoud /* check ARM6. It needs a special mask */ 601.1Sreinoud mov r0, #0x0000ff00 611.1Sreinoud mov r1, #0x00000600 /* check for 0xxxxx06xx => ARM6 */ 621.1Sreinoud and r2, r3, r0 631.1Sreinoud cmp r2, r1 641.1Sreinoud moveq r14, #0 /* mark v3 */ 651.1Sreinoud 661.1Sreinoud /* newer ARM's need a different mask */ 671.1Sreinoud mov r0, #0x0000f000 681.1Sreinoud 691.1Sreinoud /* check for ARM7 and derivatives like the ARM 7500 and ARM 7500FE */ 701.1Sreinoud mov r1, #0x00007000 /* check for 0xxxxx7xxx => ARM 7 */ 711.1Sreinoud and r2, r3, r0 721.1Sreinoud cmp r2, r1 731.1Sreinoud moveq r14, #0 /* mark v3 */ 741.1Sreinoud 751.3Schris /* flush everything out before we turn off the MMU */ 761.3Schris 771.3Schris /* flush ID cache */ 781.3Schris mov r0, #0 791.3Schris cmp r14, #0 801.4Sjoerg mcreq p15, 0, r0, c7, c0, 0 /* flush v3 ID cache */ 811.4Sjoerg mcrne p15, 0, r0, c7, c7, 0 /* flush v4 ID cache */ 821.4Sjoerg mcrne p15, 0, r0, c7, c10, 4 /* drain WB (v4) */ 831.3Schris 841.3Schris /* flush TLB */ 851.4Sjoerg mcr p15, 0, r0, c5, c0, 0 /* flush TLB for v3 and v4 */ 861.3Schris 871.1Sreinoud /* switch off MMU, IDcache and WB and branch to physical code space */ 881.1Sreinoud cmp r14, #0 891.4Sjoerg mrcne p15, 0, r0, c1, c0, 0 /* read processor control register if v4*/ 901.1Sreinoud bic r0, r0, #0x3f /* clear only known bits */ 911.1Sreinoud moveq r0, #0 /* for v3 just set to zero */ 921.1Sreinoud orr r0, r0, #CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_32BP_ENABLE 931.1Sreinoud mov r13, r0 /* save this control value in r13 */ 941.1Sreinoud cmp r14, #0 951.4Sjoerg mcr p15, 0, r0, c1, c0, 0 /* write control register! */ 961.4Sjoerg/*1*/ mcrne p15, 0, r1, c7, c5, 0 /* write zero in ARMv4 MMU disable */ 971.1Sreinoud/*2*/ mov pc, r9 /* branch to physical address */ 981.1Sreinoud 991.1Sreinoudrelocate_code_physical_restart: 1001.1Sreinoud /* we are running in physical flat 1:1 space now */ 1011.3Schris 1021.3Schris /* make the screen border red */ 1031.3Schris mov r4, #0x03400000 1041.3Schris mov r0, #0x40000000 1051.3Schris orr r0, r0, #0xff 1061.3Schris str r0, [r4] 1071.3Schris 1081.3Schris adr r5, relocate_table_start 1091.3Schris ldr r6, [r5], #4 /* r6 = number of relocated pages */ 1101.3Schris 1111.1Sreinoudloop_relocate_pages: 1121.1Sreinoud ldr r2, [r5], #4 /* r2 = from address */ 1131.1Sreinoud ldr r3, [r5], #4 /* r3 = to address */ 1141.1Sreinoud ldr r7, [r5], #4 /* r7 = number of bytes to travel */ 1151.1Sreinoud /* its slow ... we dont know anything about alignment here */ 1161.1Sreinoudloop_one_page: 1171.3Schris ldr r0, [r2], #4 1181.3Schris str r0, [r3], #4 1191.3Schris subs r7, r7, #4 1201.3Schris bgt loop_one_page 1211.3Schris 1221.1Sreinoud subs r6, r6, #1 1231.1Sreinoud bne loop_relocate_pages 1241.1Sreinoud 1251.3Schris /* make the screen border go green */ 1261.3Schris mov r0, #0x40000000 1271.3Schris orr r0, r0, #0xff00 1281.3Schris str r0, [r4] 1291.3Schris 1301.1Sreinoud /* OK! all is relocated... now switch over to the new L1 pages */ 1311.1Sreinoud 1321.1Sreinoud /* flush ID cache */ 1331.1Sreinoud mov r0, #0 1341.1Sreinoud cmp r14, #0 1351.4Sjoerg mcreq p15, 0, r0, c7, c0, 0 /* flush v3 ID cache */ 1361.4Sjoerg mcrne p15, 0, r0, c7, c7, 0 /* flush v4 ID cache */ 1371.1Sreinoud 1381.1Sreinoud /* drain write buffer (v4) */ 1391.1Sreinoud mov r0, #0 1401.1Sreinoud cmp r14, #0 1411.4Sjoerg mcrne p15, 0, r0, c7, c10, 4 /* drain WB (v4) */ 1421.1Sreinoud 1431.1Sreinoud /* flush TLB */ 1441.4Sjoerg mcr p15, 0, r0, c5, c0, 0 /* flush TLB for v3 and v4 */ 1451.1Sreinoud 1461.1Sreinoud /* set new TLB address */ 1471.1Sreinoud mov r0, r11 1481.4Sjoerg mcr p15, 0, r0, c2, c0, 0 /* write TLB address */ 1491.1Sreinoud 1501.1Sreinoud /* Switch on MMU, IDCache and WB and keep on running on flat translated memory */ 1511.1Sreinoud orr r0, r13, #CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_32BP_ENABLE 1521.1Sreinoud orr r0, r0, #CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_MMU_ENABLE 1531.4Sjoerg mcr p15, 0, r0, c1, c0, 0 /* write register !!! */ 1541.1Sreinoud mov r0, r0 /* flat */ 1551.1Sreinoud mov r0, r0 /* flat */ 1561.1Sreinoud /* not flat anymore but we just continue */ 1571.1Sreinoud 1581.3Schris /* make the screen border go blue */ 1591.3Schris mov r0, #0x40000000 1601.3Schris orr r0, r0, #0xff0000 1611.3Schris str r0, [r4] 1621.3Schris 1631.1Sreinoud /* call the kernel! */ 1641.1Sreinoud mov r0, r8 /* saved configuration structure */ 1651.1Sreinoud mov pc, r12 /* entry point ..... bye bye! */ 1661.1Sreinoud 1671.1Sreinoudrelocate_code_end: 1681.1Sreinoud b relocate_code_end 1691.1Sreinoud 1701.3Schrisrelocate_table_start: 1711.3Schris /* relocation table is copied here, so it must be kept small */ 1721.3Schris 1731.3Schris 1741.1Sreinoud/* ----------------------------------------------------------------------- */ 1751.1Sreinoud 1761.1Sreinoud 1771.1Sreinoud/* we are not expected to ever return from here */ 1781.1SreinoudENTRY(start_kernel) 1791.1Sreinoud /* 1801.1Sreinoud entry conditions : 1811.1Sreinoud - on RISC OS page tables in usr26 mode on virtual space 1821.1Sreinoud - r0 relocation code page (V) 1831.1Sreinoud - r1 relocation pv offset 1841.1Sreinoud - r2 configuration structure 1851.3Schris - r3 relocation table (V) 1861.1Sreinoud - r4 L1 page descriptor (P) 1871.1Sreinoud - r5 kernel entry point 1881.1Sreinoud */ 1891.1Sreinoud mov ip, sp 1901.1Sreinoud stmfd sp!, {r4-r9, fp, ip, lr, pc} 1911.1Sreinoud sub fp, ip, #4 1921.1Sreinoud 1931.1Sreinoud /* get stuff out of the calling frame */ 1941.1Sreinoud ldr r4, [ip, #0] 1951.1Sreinoud ldr r5, [ip, #4] 1961.1Sreinoud 1971.1Sreinoud /* relocate the relocation routine to the given page */ 1981.1Sreinoud adr r6, relocate_code 1991.4Sjoerg ldr r7, =relocate_table_start - relocate_code /* get length to copy */ 2001.1Sreinoud mov r8, r0 2011.1Sreinoudrelocate_code_loop: 2021.1Sreinoud ldr r9, [r6], #4 2031.1Sreinoud str r9, [r8], #4 2041.1Sreinoud subs r7, r7, #4 2051.1Sreinoud bne relocate_code_loop 2061.1Sreinoud 2071.3Schris /* now relocate the relocate table onto the same page */ 2081.3Schris 2091.3Schris /* next we need to copy the table over */ 2101.3Schris ldr r6, [r3], #4 /* r6 has number of threes to copy */ 2111.3Schris str r6, [r8], #4 2121.3Schris 2131.3Schrisrelocate_table_loop: 2141.3Schris ldr r9, [r3], #4 2151.3Schris str r9, [r8], #4 2161.3Schris ldr r9, [r3], #4 2171.3Schris str r9, [r8], #4 2181.3Schris ldr r9, [r3], #4 2191.3Schris str r9, [r8], #4 2201.3Schris subs r6, r6, #1 2211.3Schris bne relocate_table_loop 2221.3Schris 2231.1Sreinoud /* we messed up the data cache : lets read a 64 or 128 kb <-- GROSS */ 2241.1Sreinoud mov r7, #128*1024 2251.1Sreinoud mov r6, #0x8000 /* start of RISCOS application area */ 2261.1Sreinoudflush_ID_cache_try: 2271.1Sreinoud ldr r9, [r6], #4 2281.1Sreinoud subs r7, r7, #4 2291.1Sreinoud bne flush_ID_cache_try 2301.1Sreinoud 2311.1Sreinoud /* enter sub26 mode */ 2321.1Sreinoud swi OS_EnterOS 2331.1Sreinoud 2341.1Sreinoud /* go to sup32 mode with ICQ and FIQ disabled */ 2351.1Sreinoud mrs r6, cpsr 2361.1Sreinoud bic r6, r6, #PSR_MODE /* clear processor mode */ 2371.1Sreinoud orr r6, r6, #(I32_bit | F32_bit) /* disable ICQ + FIQ */ 2381.1Sreinoud orr r6, r6, #PSR_SVC32_MODE /* go to 32 bit supervisor mode */ 2391.1Sreinoud msr cpsr, r6 2401.1Sreinoud mov r0, r0 /* nops ... just in case */ 2411.1Sreinoud mov r0, r0 2421.1Sreinoud 2431.1Sreinoud /* set up info */ 2441.1Sreinoud mov r9, r0 /* save relocated page address */ 2451.4Sjoerg ldr r7, =relocate_code_physical_restart - relocate_code /* get offset */ 2461.1Sreinoud add r1, r0, r1 /* get physical address */ 2471.1Sreinoud add r1, r1, r7 /* add offset */ 2481.1Sreinoud mov r0, r2 /* put configuration structure in r0 */ 2491.3Schris mov r2, r3 2501.6Sandvar mov r3, r4 /* L1 page descriptor */ 2511.1Sreinoud mov r4, r5 /* kernel entry point */ 2521.1Sreinoud 2531.1Sreinoud mov pc, r9 /* jump to page addr == relocate_code */ 2541.1Sreinoud 2551.1Sreinoudemergency_exit: 2561.1Sreinoud ldmdb fp, {r4-r9, fp, sp, pc} 2571.1Sreinoud 258