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#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY 72 rsr a2, excsave1 73 movi a3, 0x08000000 74 bgeu a2, a3, 1f 75 movi a3, 0xd0000000 76 add a2, a2, a3 77 wsr a2, excsave1 781: 79#endif 80#endif 81 .end no-absolute-literals 82 83 l32r a0, .Lstartup 84 jx a0 85 86ENDPROC(_start) 87 88 __INIT 89 .literal_position 90 91ENTRY(_startup) 92 93 /* Disable interrupts and exceptions. */ 94 95 movi a0, LOCKLEVEL 96 wsr a0, ps 97 98 /* Start with a fresh windowbase and windowstart. */ 99 100 movi a1, 1 101 movi a0, 0 102 wsr a1, windowstart 103 wsr a0, windowbase 104 rsync 105 106 /* Set a0 to 0 for the remaining initialization. */ 107 108 movi a0, 0 109 110 /* Clear debugging registers. */ 111 112#if XCHAL_HAVE_DEBUG 113#if XCHAL_NUM_IBREAK > 0 114 wsr a0, ibreakenable 115#endif 116 wsr a0, icount 117 movi a1, 15 118 wsr a0, icountlevel 119 120 .set _index, 0 121 .rept XCHAL_NUM_DBREAK - 1 122 wsr a0, SREG_DBREAKC + _index 123 .set _index, _index + 1 124 .endr 125#endif 126 127 /* Clear CCOUNT (not really necessary, but nice) */ 128 129 wsr a0, ccount # not really necessary, but nice 130 131 /* Disable zero-loops. */ 132 133#if XCHAL_HAVE_LOOPS 134 wsr a0, lcount 135#endif 136 137 /* Disable all timers. */ 138 139 .set _index, 0 140 .rept XCHAL_NUM_TIMERS 141 wsr a0, SREG_CCOMPARE + _index 142 .set _index, _index + 1 143 .endr 144 145 /* Interrupt initialization. */ 146 147 movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE 148 wsr a0, intenable 149 wsr a2, intclear 150 151 /* Disable coprocessors. */ 152 153#if XCHAL_HAVE_CP 154 wsr a0, cpenable 155#endif 156 157 /* Set PS.INTLEVEL=LOCKLEVEL, PS.WOE=0, kernel stack, PS.EXCM=0 158 * 159 * Note: PS.EXCM must be cleared before using any loop 160 * instructions; otherwise, they are silently disabled, and 161 * at most one iteration of the loop is executed. 162 */ 163 164 movi a1, LOCKLEVEL 165 wsr a1, ps 166 rsync 167 168 /* Initialize the caches. 169 * a2, a3 are just working registers (clobbered). 170 */ 171 172#if XCHAL_DCACHE_LINE_LOCKABLE 173 ___unlock_dcache_all a2 a3 174#endif 175 176#if XCHAL_ICACHE_LINE_LOCKABLE 177 ___unlock_icache_all a2 a3 178#endif 179 180 ___invalidate_dcache_all a2 a3 181 ___invalidate_icache_all a2 a3 182 183 isync 184 185 /* Unpack data sections 186 * 187 * The linker script used to build the Linux kernel image 188 * creates a table located at __boot_reloc_table_start 189 * that contans the information what data needs to be unpacked. 190 * 191 * Uses a2-a7. 192 */ 193 194 movi a2, __boot_reloc_table_start 195 movi a3, __boot_reloc_table_end 196 1971: beq a2, a3, 3f # no more entries? 198 l32i a4, a2, 0 # start destination (in RAM) 199 l32i a5, a2, 4 # end desination (in RAM) 200 l32i a6, a2, 8 # start source (in ROM) 201 addi a2, a2, 12 # next entry 202 beq a4, a5, 1b # skip, empty entry 203 beq a4, a6, 1b # skip, source and dest. are the same 204 2052: l32i a7, a6, 0 # load word 206 addi a6, a6, 4 207 s32i a7, a4, 0 # store word 208 addi a4, a4, 4 209 bltu a4, a5, 2b 210 j 1b 211 2123: 213 /* All code and initialized data segments have been copied. 214 * Now clear the BSS segment. 215 */ 216 217 movi a2, __bss_start # start of BSS 218 movi a3, __bss_stop # end of BSS 219 220 __loopt a2, a3, a4, 2 221 s32i a0, a2, 0 222 __endla a2, a4, 4 223 224#if XCHAL_DCACHE_IS_WRITEBACK 225 226 /* After unpacking, flush the writeback cache to memory so the 227 * instructions/data are available. 228 */ 229 230 ___flush_dcache_all a2 a3 231#endif 232 memw 233 isync 234 ___invalidate_icache_all a2 a3 235 isync 236 237 /* Setup stack and enable window exceptions (keep irqs disabled) */ 238 239 movi a1, init_thread_union 240 addi a1, a1, KERNEL_STACK_SIZE 241 242 movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL 243 # WOE=1, INTLEVEL=LOCKLEVEL, UM=0 244 wsr a2, ps # (enable reg-windows; progmode stack) 245 rsync 246 247 /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/ 248 249 movi a2, debug_exception 250 wsr a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL 251 252 /* Set up EXCSAVE[1] to point to the exc_table. */ 253 254 movi a6, exc_table 255 xsr a6, excsave1 256 257 /* init_arch kick-starts the linux kernel */ 258 259 movi a4, init_arch 260 callx4 a4 261 262 movi a4, start_kernel 263 callx4 a4 264 265should_never_return: 266 j should_never_return 267 268ENDPROC(_startup) 269 270/* 271 * BSS section 272 */ 273 274__PAGE_ALIGNED_BSS 275#ifdef CONFIG_MMU 276ENTRY(swapper_pg_dir) 277 .fill PAGE_SIZE, 1, 0 278END(swapper_pg_dir) 279#endif 280ENTRY(empty_zero_page) 281 .fill PAGE_SIZE, 1, 0 282END(empty_zero_page) 283