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