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/processor.h> 19#include <asm/page.h> 20#include <asm/cacheasm.h> 21#include <asm/initialize_mmu.h> 22 23#include <linux/init.h> 24#include <linux/linkage.h> 25 26/* 27 * This module contains the entry code for kernel images. It performs the 28 * minimal setup needed to call the generic C routines. 29 * 30 * Prerequisites: 31 * 32 * - The kernel image has been loaded to the actual address where it was 33 * compiled to. 34 * - a2 contains either 0 or a pointer to a list of boot parameters. 35 * (see setup.c for more details) 36 * 37 */ 38 39/* 40 * _start 41 * 42 * The bootloader passes a pointer to a list of boot parameters in a2. 43 */ 44 45 /* The first bytes of the kernel image must be an instruction, so we 46 * manually allocate and define the literal constant we need for a jx 47 * instruction. 48 */ 49 50 __HEAD 51 .begin no-absolute-literals 52 53ENTRY(_start) 54 55 /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ 56 wsr a2, excsave1 57 _j _SetupMMU 58 59 .align 4 60 .literal_position 61.Lstartup: 62 .word _startup 63 64 .align 4 65 .global _SetupMMU 66_SetupMMU: 67 Offset = _SetupMMU - _start 68 69#ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX 70 initialize_mmu 71#endif 72 .end no-absolute-literals 73 74 l32r a0, .Lstartup 75 jx a0 76 77ENDPROC(_start) 78 79 __INIT 80 .literal_position 81 82ENTRY(_startup) 83 84 /* Disable interrupts and exceptions. */ 85 86 movi a0, LOCKLEVEL 87 wsr a0, ps 88 89 /* Start with a fresh windowbase and windowstart. */ 90 91 movi a1, 1 92 movi a0, 0 93 wsr a1, windowstart 94 wsr a0, windowbase 95 rsync 96 97 /* Set a0 to 0 for the remaining initialization. */ 98 99 movi a0, 0 100 101 /* Clear debugging registers. */ 102 103#if XCHAL_HAVE_DEBUG 104#if XCHAL_NUM_IBREAK > 0 105 wsr a0, ibreakenable 106#endif 107 wsr a0, icount 108 movi a1, 15 109 wsr a0, icountlevel 110 111 .set _index, 0 112 .rept XCHAL_NUM_DBREAK - 1 113 wsr a0, SREG_DBREAKC + _index 114 .set _index, _index + 1 115 .endr 116#endif 117 118 /* Clear CCOUNT (not really necessary, but nice) */ 119 120 wsr a0, ccount # not really necessary, but nice 121 122 /* Disable zero-loops. */ 123 124#if XCHAL_HAVE_LOOPS 125 wsr a0, lcount 126#endif 127 128 /* Disable all timers. */ 129 130 .set _index, 0 131 .rept XCHAL_NUM_TIMERS 132 wsr a0, SREG_CCOMPARE + _index 133 .set _index, _index + 1 134 .endr 135 136 /* Interrupt initialization. */ 137 138 movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE 139 wsr a0, intenable 140 wsr a2, intclear 141 142 /* Disable coprocessors. */ 143 144#if XCHAL_HAVE_CP 145 wsr a0, cpenable 146#endif 147 148 /* Set PS.INTLEVEL=LOCKLEVEL, PS.WOE=0, kernel stack, PS.EXCM=0 149 * 150 * Note: PS.EXCM must be cleared before using any loop 151 * instructions; otherwise, they are silently disabled, and 152 * at most one iteration of the loop is executed. 153 */ 154 155 movi a1, LOCKLEVEL 156 wsr a1, ps 157 rsync 158 159 /* Initialize the caches. 160 * a2, a3 are just working registers (clobbered). 161 */ 162 163#if XCHAL_DCACHE_LINE_LOCKABLE 164 ___unlock_dcache_all a2 a3 165#endif 166 167#if XCHAL_ICACHE_LINE_LOCKABLE 168 ___unlock_icache_all a2 a3 169#endif 170 171 ___invalidate_dcache_all a2 a3 172 ___invalidate_icache_all a2 a3 173 174 isync 175 176 /* Unpack data sections 177 * 178 * The linker script used to build the Linux kernel image 179 * creates a table located at __boot_reloc_table_start 180 * that contans the information what data needs to be unpacked. 181 * 182 * Uses a2-a7. 183 */ 184 185 movi a2, __boot_reloc_table_start 186 movi a3, __boot_reloc_table_end 187 1881: beq a2, a3, 3f # no more entries? 189 l32i a4, a2, 0 # start destination (in RAM) 190 l32i a5, a2, 4 # end desination (in RAM) 191 l32i a6, a2, 8 # start source (in ROM) 192 addi a2, a2, 12 # next entry 193 beq a4, a5, 1b # skip, empty entry 194 beq a4, a6, 1b # skip, source and dest. are the same 195 1962: l32i a7, a6, 0 # load word 197 addi a6, a6, 4 198 s32i a7, a4, 0 # store word 199 addi a4, a4, 4 200 bltu a4, a5, 2b 201 j 1b 202 2033: 204 /* All code and initialized data segments have been copied. 205 * Now clear the BSS segment. 206 */ 207 208 movi a2, __bss_start # start of BSS 209 movi a3, __bss_stop # end of BSS 210 211 __loopt a2, a3, a4, 2 212 s32i a0, a2, 0 213 __endla a2, a4, 4 214 215#if XCHAL_DCACHE_IS_WRITEBACK 216 217 /* After unpacking, flush the writeback cache to memory so the 218 * instructions/data are available. 219 */ 220 221 ___flush_dcache_all a2 a3 222#endif 223 memw 224 isync 225 ___invalidate_icache_all a2 a3 226 isync 227 228 /* Setup stack and enable window exceptions (keep irqs disabled) */ 229 230 movi a1, init_thread_union 231 addi a1, a1, KERNEL_STACK_SIZE 232 233 movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL 234 # WOE=1, INTLEVEL=LOCKLEVEL, UM=0 235 wsr a2, ps # (enable reg-windows; progmode stack) 236 rsync 237 238 /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/ 239 240 movi a2, debug_exception 241 wsr a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL 242 243 /* Set up EXCSAVE[1] to point to the exc_table. */ 244 245 movi a6, exc_table 246 xsr a6, excsave1 247 248 /* init_arch kick-starts the linux kernel */ 249 250 movi a4, init_arch 251 callx4 a4 252 253 movi a4, start_kernel 254 callx4 a4 255 256should_never_return: 257 j should_never_return 258 259ENDPROC(_startup) 260 261/* 262 * BSS section 263 */ 264 265__PAGE_ALIGNED_BSS 266#ifdef CONFIG_MMU 267ENTRY(swapper_pg_dir) 268 .fill PAGE_SIZE, 1, 0 269END(swapper_pg_dir) 270#endif 271ENTRY(empty_zero_page) 272 .fill PAGE_SIZE, 1, 0 273END(empty_zero_page) 274