1 /* 1 /* 2 * arch/xtensa/kernel/head.S << 3 * << 4 * Xtensa Processor startup code. << 5 * << 6 * This file is subject to the terms and condi 2 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the mai 3 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 4 * for more details. 9 * 5 * 10 * Copyright (C) 2001 - 2008 Tensilica Inc. !! 6 * Copyright (C) 1994, 1995 Waldorf Electronics 11 * !! 7 * Written by Ralf Baechle and Andreas Busse 12 * Chris Zankel <chris@zankel.net> !! 8 * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 Ralf Baechle 13 * Marc Gauthier <marc@tensilica.com, marc@alum !! 9 * Copyright (C) 1996 Paul M. Antoine 14 * Joe Taylor <joe@tensilica.com, joetylr@yahoo !! 10 * Modified for DECStation and hence R3000 support by Paul M. Antoine 15 * Kevin Chea !! 11 * Further modifications by David S. Miller and Harald Koerfgen >> 12 * Copyright (C) 1999 Silicon Graphics, Inc. >> 13 * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com >> 14 * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. 16 */ 15 */ 17 !! 16 #include <linux/config.h> 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> 17 #include <linux/init.h> 26 #include <linux/linkage.h> !! 18 #include <linux/threads.h> 27 19 28 /* !! 20 #include <asm/asm.h> 29 * This module contains the entry code for ker !! 21 #include <asm/regdef.h> 30 * minimal setup needed to call the generic C !! 22 #include <asm/page.h> 31 * !! 23 #include <asm/processor.h> 32 * Prerequisites: !! 24 #include <asm/mipsregs.h> 33 * !! 25 #include <asm/stackframe.h> 34 * - The kernel image has been loaded to the a !! 26 #ifdef CONFIG_SGI_IP27 35 * compiled to. !! 27 #include <asm/sn/addrs.h> 36 * - a2 contains either 0 or a pointer to a li !! 28 #include <asm/sn/sn0/hubni.h> 37 * (see setup.c for more details) !! 29 #include <asm/sn/klkernvars.h> 38 * !! 30 #endif 39 */ !! 31 40 !! 32 .macro ARC64_TWIDDLE_PC 41 /* !! 33 #if defined(CONFIG_ARC64) || defined(CONFIG_MAPPED_KERNEL) 42 * _start !! 34 /* We get launched at a XKPHYS address but the kernel is linked to 43 * !! 35 run at a KSEG0 address, so jump there. */ 44 * The bootloader passes a pointer to a list !! 36 PTR_LA t0, \@f 45 */ !! 37 jr t0 46 !! 38 \@: 47 /* The first bytes of the kernel image !! 39 #endif 48 * manually allocate and define the li !! 40 .endm 49 * instruction. << 50 */ << 51 << 52 __HEAD << 53 .begin no-absolute-literals << 54 << 55 ENTRY(_start) << 56 41 57 /* Preserve the pointer to the boot pa !! 42 #ifdef CONFIG_SGI_IP27 58 wsr a2, excsave1 << 59 _j _SetupOCD << 60 << 61 .align 4 << 62 .literal_position << 63 _SetupOCD: << 64 /* 43 /* 65 * Initialize WB, WS, and clear PS.EXC !! 44 * outputs the local nasid into res. IP27 stuff. 66 * Set Interrupt Level just below XCHA << 67 * xt-gdb to single step via DEBUG exc << 68 * by ocd. << 69 */ 45 */ 70 #if XCHAL_HAVE_WINDOWED !! 46 .macro GET_NASID_ASM res 71 movi a1, 1 !! 47 dli \res, LOCAL_HUB_ADDR(NI_STATUS_REV_ID) 72 movi a0, 0 !! 48 ld \res, (\res) 73 wsr a1, windowstart !! 49 and \res, NSRI_NODEID_MASK 74 wsr a0, windowbase !! 50 dsrl \res, NSRI_NODEID_SHFT 75 rsync !! 51 .endm 76 #endif !! 52 #endif /* CONFIG_SGI_IP27 */ 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_VML << 87 initialize_mmu << 88 #if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU << 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 initi << 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, << 140 53 141 wsr a0, ccount # not really n !! 54 /* 142 !! 55 * inputs are the text nasid in t1, data nasid in t2. 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_SOFTWAR << 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 << 171 */ 56 */ 172 !! 57 .macro MAPPED_KERNEL_SETUP_TLB 173 #if XCHAL_DCACHE_LINE_LOCKABLE !! 58 #ifdef CONFIG_MAPPED_KERNEL 174 ___unlock_dcache_all a2 a3 !! 59 /* 175 #endif !! 60 * This needs to read the nasid - assume 0 for now. 176 !! 61 * Drop in 0xffffffffc0000000 in tlbhi, 0+VG in tlblo_0, 177 #if XCHAL_ICACHE_LINE_LOCKABLE !! 62 * 0+DVG in tlblo_1. 178 ___unlock_icache_all a2 a3 !! 63 */ 179 #endif !! 64 dli t0, 0xffffffffc0000000 180 !! 65 dmtc0 t0, CP0_ENTRYHI 181 ___invalidate_dcache_all a2 a3 !! 66 li t0, 0x1c000 # Offset of text into node memory 182 ___invalidate_icache_all a2 a3 !! 67 dsll t1, NASID_SHFT # Shift text nasid into place 183 !! 68 dsll t2, NASID_SHFT # Same for data nasid 184 isync !! 69 or t1, t1, t0 # Physical load address of kernel text 185 !! 70 or t2, t2, t0 # Physical load address of kernel data 186 initialize_cacheattr !! 71 dsrl t1, 12 # 4K pfn 187 !! 72 dsrl t2, 12 # 4K pfn 188 #ifdef CONFIG_HAVE_SMP !! 73 dsll t1, 6 # Get pfn into place 189 movi a2, CCON # MX External !! 74 dsll t2, 6 # Get pfn into place 190 movi a3, 1 !! 75 li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _CACHE_CACHABLE_COW) >> 6) 191 wer a3, a2 !! 76 or t0, t0, t1 >> 77 mtc0 t0, CP0_ENTRYLO0 # physaddr, VG, cach exlwr >> 78 li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _PAGE_DIRTY|_CACHE_CACHABLE_COW) >> 6) >> 79 or t0, t0, t2 >> 80 mtc0 t0, CP0_ENTRYLO1 # physaddr, DVG, cach exlwr >> 81 li t0, 0x1ffe000 # MAPPED_KERN_TLBMASK, TLBPGMASK_16M >> 82 mtc0 t0, CP0_PAGEMASK >> 83 li t0, 0 # KMAP_INX >> 84 mtc0 t0, CP0_INDEX >> 85 li t0, 1 >> 86 mtc0 t0, CP0_WIRED >> 87 tlbwi >> 88 #else >> 89 mtc0 zero, CP0_WIRED 192 #endif 90 #endif >> 91 .endm 193 92 194 /* Setup stack and enable window excep << 195 << 196 movi a1, start_info << 197 l32i a1, a1, 0 << 198 << 199 /* Disable interrupts. */ << 200 /* Enable window exceptions if kernel << 201 movi a2, KERNEL_PS_WOE_MASK | LOCKL << 202 wsr a2, ps << 203 rsync << 204 << 205 #ifdef CONFIG_SMP << 206 /* 93 /* 207 * Notice that we assume with SMP that !! 94 * Reserved space for exception handlers. 208 * supported by the cores. !! 95 * Necessary for machines which link their kernels at KSEG0. 209 */ 96 */ 210 rsr a2, prid !! 97 .fill 0x400 211 bnez a2, .Lboot_secondary << 212 << 213 #endif /* CONFIG_SMP */ << 214 << 215 /* Unpack data sections << 216 * << 217 * The linker script used to build the << 218 * creates a table located at __boot_r << 219 * that contains the information what << 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 entr << 228 l32i a4, a2, 0 # start destin << 229 l32i a5, a2, 4 # end destinat << 230 l32i a6, a2, 8 # start source << 231 addi a2, a2, 12 # next entry << 232 beq a4, a5, 1b # skip, empty << 233 beq a4, a6, 1b # skip, source << 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 segme << 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 writebac << 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 ke << 269 98 270 movi a1, start_info !! 99 EXPORT(stext) # used for profiling 271 l32i a1, a1, 0 !! 100 EXPORT(_stext) 272 #endif << 273 101 274 movi abi_arg0, 0 !! 102 __INIT 275 xsr abi_arg0, excsave1 << 276 103 277 /* init_arch kick-starts the linux ker !! 104 NESTED(kernel_entry, 16, sp) # kernel entry point >> 105 #ifdef CONFIG_SGI_IP27 >> 106 GET_NASID_ASM t1 >> 107 move t2, t1 # text and data are here >> 108 MAPPED_KERNEL_SETUP_TLB >> 109 #endif /* IP27 */ 278 110 279 abi_call init_arch !! 111 ARC64_TWIDDLE_PC 280 abi_call start_kernel << 281 112 282 should_never_return: !! 113 CLI # disable interrupts 283 j should_never_return << 284 114 285 #ifdef CONFIG_SMP !! 115 PTR_LA $28, init_thread_union 286 .Lboot_secondary: !! 116 PTR_ADDIU sp, $28, _THREAD_SIZE - 32 >> 117 set_saved_sp sp, t0, t1 >> 118 PTR_SUBU sp, 4 * SZREG # init stack pointer 287 119 288 movi a2, cpu_start_ccount !! 120 /* 289 1: !! 121 * The firmware/bootloader passes argc/argp/envp 290 memw !! 122 * to us as arguments. But clear bss first because 291 l32i a3, a2, 0 !! 123 * the romvec and other important info is stored there 292 beqi a3, 0, 1b !! 124 * by prom_init(). 293 movi a3, 0 !! 125 */ 294 s32i a3, a2, 0 !! 126 PTR_LA t0, __bss_start >> 127 LONG_S zero, (t0) >> 128 PTR_LA t1, __bss_stop - LONGSIZE 295 1: 129 1: 296 memw !! 130 PTR_ADDIU t0, LONGSIZE 297 l32i a3, a2, 0 !! 131 LONG_S zero, (t0) 298 beqi a3, 0, 1b !! 132 bne t0, t1, 1b 299 wsr a3, ccount << 300 movi a3, 0 << 301 s32i a3, a2, 0 << 302 memw << 303 133 304 movi abi_arg0, 0 !! 134 jal init_arch 305 wsr abi_arg0, excsave1 !! 135 END(kernel_entry) 306 136 307 abi_call secondary_start_kernel !! 137 #ifdef CONFIG_SMP 308 j should_never_return !! 138 /* 309 !! 139 * SMP slave cpus entry point. Board specific code for bootstrap calls this 310 #endif /* CONFIG_SMP */ !! 140 * function after setting up the stack and gp registers. >> 141 */ >> 142 NESTED(smp_bootstrap, 16, sp) >> 143 #ifdef CONFIG_SGI_IP27 >> 144 GET_NASID_ASM t1 >> 145 li t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \ >> 146 KLDIR_OFF_POINTER + K0BASE >> 147 dsll t1, NASID_SHFT >> 148 or t0, t0, t1 >> 149 ld t0, 0(t0) # t0 points to kern_vars struct >> 150 lh t1, KV_RO_NASID_OFFSET(t0) >> 151 lh t2, KV_RW_NASID_OFFSET(t0) >> 152 MAPPED_KERNEL_SETUP_TLB >> 153 ARC64_TWIDDLE_PC >> 154 #endif /* CONFIG_SGI_IP27 */ 311 155 312 ENDPROC(_startup) !! 156 CLI 313 157 314 #ifdef CONFIG_HOTPLUG_CPU !! 158 #ifdef CONFIG_MIPS64 >> 159 /* >> 160 * For the moment set ST0_KU so the CPU will not spit fire when >> 161 * executing 64-bit instructions. The full initialization of the >> 162 * CPU's status register is done later in per_cpu_trap_init(). >> 163 */ >> 164 mfc0 t0, CP0_STATUS >> 165 or t0, ST0_KX >> 166 mtc0 t0, CP0_STATUS >> 167 #endif >> 168 jal start_secondary >> 169 END(smp_bootstrap) >> 170 #endif /* CONFIG_SMP */ >> 171 >> 172 __FINIT >> 173 >> 174 .comm kernelsp, NR_CPUS * 8, 8 >> 175 .comm pgd_current, NR_CPUS * 8, 8 >> 176 >> 177 .macro page name, order=0 >> 178 .globl \name >> 179 \name: .size \name, (_PAGE_SIZE << \order) >> 180 .org . + (_PAGE_SIZE << \order) >> 181 .type \name, @object >> 182 .endm 315 183 316 ENTRY(cpu_restart) !! 184 .data >> 185 .align PAGE_SHIFT 317 186 318 #if XCHAL_DCACHE_IS_WRITEBACK !! 187 #ifdef CONFIG_MIPS32 319 ___flush_invalidate_dcache_all a2 a3 !! 188 /* 320 #else !! 189 * Here we only have a two-level pagetable structure ... 321 ___invalidate_dcache_all a2 a3 !! 190 */ 322 #endif !! 191 page swapper_pg_dir, _PGD_ORDER 323 memw !! 192 page invalid_pte_table, _PTE_ORDER 324 movi a2, CCON # MX External << 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 193 #endif 337 1: !! 194 #ifdef CONFIG_MIPS64 338 memw << 339 l32i a2, a3, 0 << 340 dhi a3, 0 << 341 bne a2, a0, 1b << 342 << 343 /* 195 /* 344 * Initialize WB, WS, and clear PS.EXC !! 196 * ... but on 64-bit we've got three-level pagetables with a 345 * Set Interrupt Level just below XCHA !! 197 * slightly different layout ... 346 * xt-gdb to single step via DEBUG exc << 347 * by ocd. << 348 */ 198 */ 349 movi a1, 1 !! 199 page swapper_pg_dir, _PGD_ORDER 350 movi a0, 0 !! 200 page invalid_pmd_table, _PMD_ORDER 351 wsr a1, windowstart !! 201 page invalid_pte_table, _PTE_ORDER 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 202 363 #endif /* CONFIG_HOTPLUG_CPU */ !! 203 /* 364 !! 204 * 64-bit kernel mappings are really screwed up ... 365 /* !! 205 */ 366 * DATA section !! 206 page kptbl, _PGD_ORDER 367 */ !! 207 .globl ekptbl 368 !! 208 page kpmdtbl, 0 369 __REFDATA !! 209 ekptbl: 370 .align 4 << 371 ENTRY(start_info) << 372 .long init_thread_union + KERNEL_STA << 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 210 #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.