1 /* 2 * arch/xtensa/kernel/head.S 3 * 4 * Xtensa Processor startup code. 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 * 10 * Copyright (C) 2001 - 2008 Tensilica Inc. 11 * 12 * Chris Zankel <chris@zankel.net> 13 * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca> 14 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> 15 * Kevin Chea 16 */ 17 18 #include <asm/asmmacro.h> 19 #include <asm/processor.h> 20 #include <asm/page.h> 21 #include <asm/cacheasm.h> 22 #include <asm/initialize_mmu.h> 23 #include <asm/mxregs.h> 24 25 #include <linux/init.h> 26 #include <linux/linkage.h> 27 28 /* 29 * This module contains the entry code for kernel images. It performs the 30 * minimal setup needed to call the generic C routines. 31 * 32 * Prerequisites: 33 * 34 * - The kernel image has been loaded to the actual address where it was 35 * compiled to. 36 * - a2 contains either 0 or a pointer to a list of boot parameters. 37 * (see setup.c for more details) 38 * 39 */ 40 41 /* 42 * _start 43 * 44 * The bootloader passes a pointer to a list of boot parameters in a2. 45 */ 46 47 /* The first bytes of the kernel image must be an instruction, so we 48 * manually allocate and define the literal constant we need for a jx 49 * instruction. 50 */ 51 52 __HEAD 53 .begin no-absolute-literals 54 55 ENTRY(_start) 56 57 /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ 58 wsr a2, excsave1 59 _j _SetupOCD 60 61 .align 4 62 .literal_position 63 _SetupOCD: 64 /* 65 * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions). 66 * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow 67 * xt-gdb to single step via DEBUG exceptions received directly 68 * by ocd. 69 */ 70 #if XCHAL_HAVE_WINDOWED 71 movi a1, 1 72 movi a0, 0 73 wsr a1, windowstart 74 wsr a0, windowbase 75 rsync 76 #endif 77 78 movi a1, LOCKLEVEL 79 wsr a1, ps 80 rsync 81 82 .global _SetupMMU 83 _SetupMMU: 84 Offset = _SetupMMU - _start 85 86 #ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX 87 initialize_mmu 88 #if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY 89 rsr a2, excsave1 90 movi a3, XCHAL_KSEG_PADDR 91 bltu a2, a3, 1f 92 sub a2, a2, a3 93 movi a3, XCHAL_KSEG_SIZE 94 bgeu a2, a3, 1f 95 movi a3, XCHAL_KSEG_CACHED_VADDR 96 add a2, a2, a3 97 wsr a2, excsave1 98 1: 99 #endif 100 #endif 101 102 movi a0, _startup 103 jx a0 104 105 ENDPROC(_start) 106 .end no-absolute-literals 107 108 __REF 109 .literal_position 110 111 ENTRY(_startup) 112 113 /* Set a0 to 0 for the remaining initialization. */ 114 115 movi a0, 0 116 117 #if XCHAL_HAVE_VECBASE 118 movi a2, VECBASE_VADDR 119 wsr a2, vecbase 120 #endif 121 122 /* Clear debugging registers. */ 123 124 #if XCHAL_HAVE_DEBUG 125 #if XCHAL_NUM_IBREAK > 0 126 wsr a0, ibreakenable 127 #endif 128 wsr a0, icount 129 movi a1, 15 130 wsr a0, icountlevel 131 132 .set _index, 0 133 .rept XCHAL_NUM_DBREAK 134 wsr a0, SREG_DBREAKC + _index 135 .set _index, _index + 1 136 .endr 137 #endif 138 139 /* Clear CCOUNT (not really necessary, but nice) */ 140 141 wsr a0, ccount # not really necessary, but nice 142 143 /* Disable zero-loops. */ 144 145 #if XCHAL_HAVE_LOOPS 146 wsr a0, lcount 147 #endif 148 149 /* Disable all timers. */ 150 151 .set _index, 0 152 .rept XCHAL_NUM_TIMERS 153 wsr a0, SREG_CCOMPARE + _index 154 .set _index, _index + 1 155 .endr 156 157 /* Interrupt initialization. */ 158 159 movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE 160 wsr a0, intenable 161 wsr a2, intclear 162 163 /* Disable coprocessors. */ 164 165 #if XCHAL_HAVE_CP 166 wsr a0, cpenable 167 #endif 168 169 /* Initialize the caches. 170 * a2, a3 are just working registers (clobbered). 171 */ 172 173 #if XCHAL_DCACHE_LINE_LOCKABLE 174 ___unlock_dcache_all a2 a3 175 #endif 176 177 #if XCHAL_ICACHE_LINE_LOCKABLE 178 ___unlock_icache_all a2 a3 179 #endif 180 181 ___invalidate_dcache_all a2 a3 182 ___invalidate_icache_all a2 a3 183 184 isync 185 186 initialize_cacheattr 187 188 #ifdef CONFIG_HAVE_SMP 189 movi a2, CCON # MX External Register to Configure Cache 190 movi a3, 1 191 wer a3, a2 192 #endif 193 194 /* Setup stack and enable window exceptions (keep irqs disabled) */ 195 196 movi a1, start_info 197 l32i a1, a1, 0 198 199 /* Disable interrupts. */ 200 /* Enable window exceptions if kernel is built with windowed ABI. */ 201 movi a2, KERNEL_PS_WOE_MASK | LOCKLEVEL 202 wsr a2, ps 203 rsync 204 205 #ifdef CONFIG_SMP 206 /* 207 * Notice that we assume with SMP that cores have PRID 208 * supported by the cores. 209 */ 210 rsr a2, prid 211 bnez a2, .Lboot_secondary 212 213 #endif /* CONFIG_SMP */ 214 215 /* Unpack data sections 216 * 217 * The linker script used to build the Linux kernel image 218 * creates a table located at __boot_reloc_table_start 219 * that contains the information what data needs to be unpacked. 220 * 221 * Uses a2-a7. 222 */ 223 224 movi a2, __boot_reloc_table_start 225 movi a3, __boot_reloc_table_end 226 227 1: beq a2, a3, 3f # no more entries? 228 l32i a4, a2, 0 # start destination (in RAM) 229 l32i a5, a2, 4 # end destination (in RAM) 230 l32i a6, a2, 8 # start source (in ROM) 231 addi a2, a2, 12 # next entry 232 beq a4, a5, 1b # skip, empty entry 233 beq a4, a6, 1b # skip, source and dest. are the same 234 235 2: l32i a7, a6, 0 # load word 236 addi a6, a6, 4 237 s32i a7, a4, 0 # store word 238 addi a4, a4, 4 239 bltu a4, a5, 2b 240 j 1b 241 242 3: 243 /* All code and initialized data segments have been copied. 244 * Now clear the BSS segment. 245 */ 246 247 movi a2, __bss_start # start of BSS 248 movi a3, __bss_stop # end of BSS 249 250 __loopt a2, a3, a4, 2 251 s32i a0, a2, 0 252 __endla a2, a3, 4 253 254 #if XCHAL_DCACHE_IS_WRITEBACK 255 256 /* After unpacking, flush the writeback cache to memory so the 257 * instructions/data are available. 258 */ 259 260 ___flush_dcache_all a2 a3 261 #endif 262 memw 263 isync 264 ___invalidate_icache_all a2 a3 265 isync 266 267 #ifdef CONFIG_XIP_KERNEL 268 /* Setup bootstrap CPU stack in XIP kernel */ 269 270 movi a1, start_info 271 l32i a1, a1, 0 272 #endif 273 274 movi abi_arg0, 0 275 xsr abi_arg0, excsave1 276 277 /* init_arch kick-starts the linux kernel */ 278 279 abi_call init_arch 280 abi_call start_kernel 281 282 should_never_return: 283 j should_never_return 284 285 #ifdef CONFIG_SMP 286 .Lboot_secondary: 287 288 movi a2, cpu_start_ccount 289 1: 290 memw 291 l32i a3, a2, 0 292 beqi a3, 0, 1b 293 movi a3, 0 294 s32i a3, a2, 0 295 1: 296 memw 297 l32i a3, a2, 0 298 beqi a3, 0, 1b 299 wsr a3, ccount 300 movi a3, 0 301 s32i a3, a2, 0 302 memw 303 304 movi abi_arg0, 0 305 wsr abi_arg0, excsave1 306 307 abi_call secondary_start_kernel 308 j should_never_return 309 310 #endif /* CONFIG_SMP */ 311 312 ENDPROC(_startup) 313 314 #ifdef CONFIG_HOTPLUG_CPU 315 316 ENTRY(cpu_restart) 317 318 #if XCHAL_DCACHE_IS_WRITEBACK 319 ___flush_invalidate_dcache_all a2 a3 320 #else 321 ___invalidate_dcache_all a2 a3 322 #endif 323 memw 324 movi a2, CCON # MX External Register to Configure Cache 325 movi a3, 0 326 wer a3, a2 327 extw 328 329 rsr a0, prid 330 neg a2, a0 331 movi a3, cpu_start_id 332 memw 333 s32i a2, a3, 0 334 #if XCHAL_DCACHE_IS_WRITEBACK 335 dhwbi a3, 0 336 #endif 337 1: 338 memw 339 l32i a2, a3, 0 340 dhi a3, 0 341 bne a2, a0, 1b 342 343 /* 344 * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions). 345 * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow 346 * xt-gdb to single step via DEBUG exceptions received directly 347 * by ocd. 348 */ 349 movi a1, 1 350 movi a0, 0 351 wsr a1, windowstart 352 wsr a0, windowbase 353 rsync 354 355 movi a1, LOCKLEVEL 356 wsr a1, ps 357 rsync 358 359 j _startup 360 361 ENDPROC(cpu_restart) 362 363 #endif /* CONFIG_HOTPLUG_CPU */ 364 365 /* 366 * DATA section 367 */ 368 369 __REFDATA 370 .align 4 371 ENTRY(start_info) 372 .long init_thread_union + KERNEL_STACK_SIZE 373 374 /* 375 * BSS section 376 */ 377 378 __PAGE_ALIGNED_BSS 379 #ifdef CONFIG_MMU 380 ENTRY(swapper_pg_dir) 381 .fill PAGE_SIZE, 1, 0 382 END(swapper_pg_dir) 383 #endif 384 ENTRY(empty_zero_page) 385 .fill PAGE_SIZE, 1, 0 386 END(empty_zero_page)
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.