1/* $NetBSD: start.S,v 1.2 2008/01/25 23:18:59 chris Exp $ */ 2 3/* 4 * Copyright (c) 2002 Reinoud Zandijk 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include <machine/asm.h> 31#include <arm/armreg.h> 32#include <riscoscalls.h> 33 34 35/* ----------------------------------------------------------------------- */ 36ENTRY(relocate_code) 37 /* 38 - r0 pointer to configuration structure 39 - r1 pointer to physical restart point 40 - r3 pointer to physical new L1 page address (P) 41 - r4 kernel entry point 42 */ 43 44 /* save registers / move args up in register bank later */ 45 /* r8-r12 becomes r0-r4 */ 46 stmfd sp!, {r0-r4} 47 ldmfd sp!, {r8-r12} 48 49 /* 50 * determine processor architecture version. This is nessisary for the 51 * correct coprocessor instruction. 52 */ 53 mrc 15, 0, r0, c0, c0, 0 /* read CPU id in r0 */ 54 mov r3, r0 /* store in r3 */ 55 56 /* assume its ARMv4 instruction set */ 57 mov r14, #1 58 59 /* check ARM6. It needs a special mask */ 60 mov r0, #0x0000ff00 61 mov r1, #0x00000600 /* check for 0xxxxx06xx => ARM6 */ 62 and r2, r3, r0 63 cmp r2, r1 64 moveq r14, #0 /* mark v3 */ 65 66 /* newer ARM's need a different mask */ 67 mov r0, #0x0000f000 68 69 /* check for ARM7 and derivatives like the ARM 7500 and ARM 7500FE */ 70 mov r1, #0x00007000 /* check for 0xxxxx7xxx => ARM 7 */ 71 and r2, r3, r0 72 cmp r2, r1 73 moveq r14, #0 /* mark v3 */ 74 75 /* flush everything out before we turn off the MMU */ 76 77 /* flush ID cache */ 78 mov r0, #0 79 cmp r14, #0 80 mcreq 15, 0, r0, c7, c0, 0 /* flush v3 ID cache */ 81 mcrne 15, 0, r0, c7, c7, 0 /* flush v4 ID cache */ 82 mcrne 15, 0, r0, c7, c10, 4 /* drain WB (v4) */ 83 84 /* flush TLB */ 85 mcr 15, 0, r0, c5, c0, 0 /* flush TLB for v3 and v4 */ 86 87 /* switch off MMU, IDcache and WB and branch to physical code space */ 88 cmp r14, #0 89 mrcne 15, 0, r0, c1, c0, 0 /* read processor control register if v4*/ 90 bic r0, r0, #0x3f /* clear only known bits */ 91 moveq r0, #0 /* for v3 just set to zero */ 92 orr r0, r0, #CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_32BP_ENABLE 93 mov r13, r0 /* save this control value in r13 */ 94 cmp r14, #0 95 mcr 15, 0, r0, c1, c0, 0 /* write control register! */ 96/*1*/ mcrne 15, 0, r1, c7, c5, 0 /* write zero in ARMv4 MMU disable */ 97/*2*/ mov pc, r9 /* branch to physical address */ 98 99relocate_code_physical_restart: 100 /* we are running in physical flat 1:1 space now */ 101 102 /* make the screen border red */ 103 mov r4, #0x03400000 104 mov r0, #0x40000000 105 orr r0, r0, #0xff 106 str r0, [r4] 107 108 adr r5, relocate_table_start 109 ldr r6, [r5], #4 /* r6 = number of relocated pages */ 110 111loop_relocate_pages: 112 ldr r2, [r5], #4 /* r2 = from address */ 113 ldr r3, [r5], #4 /* r3 = to address */ 114 ldr r7, [r5], #4 /* r7 = number of bytes to travel */ 115 /* its slow ... we dont know anything about alignment here */ 116loop_one_page: 117 ldr r0, [r2], #4 118 str r0, [r3], #4 119 subs r7, r7, #4 120 bgt loop_one_page 121 122 subs r6, r6, #1 123 bne loop_relocate_pages 124 125 /* make the screen border go green */ 126 mov r0, #0x40000000 127 orr r0, r0, #0xff00 128 str r0, [r4] 129 130 /* OK! all is relocated... now switch over to the new L1 pages */ 131 132 /* flush ID cache */ 133 mov r0, #0 134 cmp r14, #0 135 mcreq 15, 0, r0, c7, c0, 0 /* flush v3 ID cache */ 136 mcrne 15, 0, r0, c7, c7, 0 /* flush v4 ID cache */ 137 138 /* drain write buffer (v4) */ 139 mov r0, #0 140 cmp r14, #0 141 mcrne 15, 0, r0, c7, c10, 4 /* drain WB (v4) */ 142 143 /* flush TLB */ 144 mcr 15, 0, r0, c5, c0, 0 /* flush TLB for v3 and v4 */ 145 146 /* set new TLB address */ 147 mov r0, r11 148 mcr 15, 0, r0, c2, c0, 0 /* write TLB address */ 149 150 /* Switch on MMU, IDCache and WB and keep on running on flat translated memory */ 151 orr r0, r13, #CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_32BP_ENABLE 152 orr r0, r0, #CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_MMU_ENABLE 153 mcr 15, 0, r0, c1, c0, 0 /* write register !!! */ 154 mov r0, r0 /* flat */ 155 mov r0, r0 /* flat */ 156 /* not flat anymore but we just continue */ 157 158 /* make the screen border go blue */ 159 mov r0, #0x40000000 160 orr r0, r0, #0xff0000 161 str r0, [r4] 162 163 /* call the kernel! */ 164 mov r0, r8 /* saved configuration structure */ 165 mov pc, r12 /* entry point ..... bye bye! */ 166 167relocate_code_end: 168 b relocate_code_end 169 170relocate_table_start: 171 /* relocation table is copied here, so it must be kept small */ 172 173 174/* ----------------------------------------------------------------------- */ 175 176 177/* we are not expected to ever return from here */ 178ENTRY(start_kernel) 179 /* 180 entry conditions : 181 - on RISC OS page tables in usr26 mode on virtual space 182 - r0 relocation code page (V) 183 - r1 relocation pv offset 184 - r2 configuration structure 185 - r3 relocation table (V) 186 - r4 L1 page descriptor (P) 187 - r5 kernel entry point 188 */ 189 mov ip, sp 190 stmfd sp!, {r4-r9, fp, ip, lr, pc} 191 sub fp, ip, #4 192 193 /* get stuff out of the calling frame */ 194 ldr r4, [ip, #0] 195 ldr r5, [ip, #4] 196 197 /* relocate the relocation routine to the given page */ 198 adr r6, relocate_code 199 mov r7, #relocate_table_start - relocate_code /* get length to copy */ 200 mov r8, r0 201relocate_code_loop: 202 ldr r9, [r6], #4 203 str r9, [r8], #4 204 subs r7, r7, #4 205 bne relocate_code_loop 206 207 /* now relocate the relocate table onto the same page */ 208 209 /* next we need to copy the table over */ 210 ldr r6, [r3], #4 /* r6 has number of threes to copy */ 211 str r6, [r8], #4 212 213relocate_table_loop: 214 ldr r9, [r3], #4 215 str r9, [r8], #4 216 ldr r9, [r3], #4 217 str r9, [r8], #4 218 ldr r9, [r3], #4 219 str r9, [r8], #4 220 subs r6, r6, #1 221 bne relocate_table_loop 222 223 /* we messed up the data cache : lets read a 64 or 128 kb <-- GROSS */ 224 mov r7, #128*1024 225 mov r6, #0x8000 /* start of RISCOS application area */ 226flush_ID_cache_try: 227 ldr r9, [r6], #4 228 subs r7, r7, #4 229 bne flush_ID_cache_try 230 231 /* enter sub26 mode */ 232 swi OS_EnterOS 233 234 /* go to sup32 mode with ICQ and FIQ disabled */ 235 mrs r6, cpsr 236 bic r6, r6, #PSR_MODE /* clear processor mode */ 237 orr r6, r6, #(I32_bit | F32_bit) /* disable ICQ + FIQ */ 238 orr r6, r6, #PSR_SVC32_MODE /* go to 32 bit supervisor mode */ 239 msr cpsr, r6 240 mov r0, r0 /* nops ... just in case */ 241 mov r0, r0 242 243 /* set up info */ 244 mov r9, r0 /* save relocated page address */ 245 mov r7, #relocate_code_physical_restart - relocate_code /* get offset */ 246 add r1, r0, r1 /* get physical address */ 247 add r1, r1, r7 /* add offset */ 248 mov r0, r2 /* put configuration structure in r0 */ 249 mov r2, r3 250 mov r3, r4 /* L1 page discriptor */ 251 mov r4, r5 /* kernel entry point */ 252 253 mov pc, r9 /* jump to page addr == relocate_code */ 254 255emergency_exit: 256 ldmdb fp, {r4-r9, fp, sp, pc} 257 258