1/* 2 * interAptiv/start.S 3 * 4 * Created on: Jan 12, 2011 5 * Author: MIPS TECHNOLOGIES, INC 6 * Start of boot code for interAptiv Family of Cores 7*/ 8/* 9Unpublished work (c) MIPS Technologies, Inc. All rights reserved. Unpublished rights reserved 10under the copyright laws of the United States of America and other countries. 11 12This code is confidential and proprietary to MIPS Technologies, Inc. ("MIPS Technologies") and 13may be disclosed only as permitted in writing by MIPS Technologies or an authorized third party. 14Any copying, reproducing, modifying, use or disclosure of this code (in whole or in part) that is 15not expressly permitted in writing by MIPS Technologies or an authorized third party is strictly 16prohibited. At a minimum, this code is protected under trade secret, unfair competition, and 17copyright laws. Violations thereof may result in criminal penalties and fines. 18 19MIPS Technologies reserves the right to change this code to improve function, design or 20otherwise. MIPS Technologies does not assume any liability arising out of the application or use 21of this code, or of any error or omission in such code. Any warranties, whether express, statutory, 22implied or otherwise, including but not limited to the implied warranties of merchantability or 23fitness for a particular purpose, are excluded. Except as expressly provided in any written license 24agreement from MIPS Technologies or an authorized third party, the furnishing of this code does 25not give recipient any license to any intellectual property rights, including any patent rights, that 26cover this code. 27 28This code shall not be exported, reexported, transferred, or released, directly or indirectly, in 29violation of the law of any country or international law, regulation, treaty, Executive Order, 30statute, amendments or supplements thereto. Should a conflict arise regarding the export, 31reexport, transfer, or release of this code, the laws of the United States of America shall be 32the governing law. 33 34This code may only be disclosed to the United States government ("Government"), or to 35Government users, with prior written consent from MIPS Technologies or an authorized third 36party. This code constitutes one or more of the following: commercial computer software, 37commercial computer software documentation or other commercial items. If the user of this 38code, or any related documentation of any kind, including related technical data or manuals, is an 39agency, department, or other entity of the Government, the use, duplication, reproduction, release, 40modification, disclosure, or transfer of this code, or any related documentation of any kind, is 41restricted in accordance with Federal Acquisition Regulation 12.212 for civilian agencies and 42Defense Federal Acquisition Regulation Supplement 227.7202 for military agencies. The use of 43this code by the Government is further restricted in accordance with the terms of the license 44agreement(s) and/or applicable contract terms and conditions covering this code from MIPS 45Technologies or an authorized third party. 46*/ 47 48#include <boot.h> 49#include <m32c0.h> 50#include <regdef.h> 51#include <cps.h> 52 53/* EL Change. Add address for optional user-specified vpe wakeup function. */ 54 55#ifdef TX_THREAD_SMP_WAKEUP_LOGIC 56 .globl TX_THREAD_SMP_WAKEUP_LOGIC_SETUP 57#endif 58 59/* EL Change End. */ 60 61 62 .set noreorder // Don't allow the assembler to reorder instructions. 63 .set noat // Don't allow the assembler to use r1(at) for synthetic instr. 64/************************************************************************************** 65 R E S E T E X C E P T I O N H A N D L E R 66**************************************************************************************/ 67// RAMHACK: Removed boot exception handlers. 68/************************************************************************************** 69 B O O T E X C E P T I O N H A N D L E R S 70**************************************************************************************/ 71 72// RAMHACK: Removed boot exception handlers. 73 74 75/************************************************************************************** 76 R A M E X C E P T I O N H A N D L E R S 77**************************************************************************************/ 78 79.section ".vector_0x000","ax" 80 .globl tlb_refill_exception 81tlb_refill_exception: 82 sdbbp 83 84.section ".vector_0x100","ax" 85 .globl cache_error_exception 86cache_error_exception: 87 sdbbp 88 89.section ".vector_0x180","ax" 90 .globl general_exception 91general_exception: 92 93/* EL Change: Branch to ThreadX error handling. */ 94 95 la k0, _tx_error_exceptions 96 jalr k1, k0 97 nop 98 99/* EL Change end. */ 100 101 102 sdbbp 103 104.section ".vector_0x200","ax" 105 .globl iv1_interrupt 106iv1_interrupt: 107 108/* EL Change: Branch to ThreadX error handling. */ 109 110 la k0, _tx_exception_handler 111 jalr k1, k0 112 nop 113 114/* Disable previous exception handler, since ThreadX is taking care of all exceptions now. */ 115#if 0 116 li k0, MALTA_DISP_ADDR // Malta ASCII character display. 117 mfc0 k1, C0_EBASE // Get cp0 EBase 118 ext k1, k1, 0, 10 // Extract CPUNum 119 sll k1, k1, 3 // Build offset for display char. 120 addiu k1, 8 121 addu k0, k0, k1 // Pointer to a single display character. 122 li k1, 'H' // Indicate that this vpe is in the handler. 123 sw k1, 0(k0) // Write ASCII char to Malta ASCII display. 124 125 li k0, (GIC_SH_WEDGE | GIC_BASE_ADDR) 126 mfc0 k1, C0_EBASE // Get cp0 EBase 127 ext k1, k1, 0, 10 // Extract CPUNum 128 addiu k1, 0x20 // Offset to base of IPI interrupts. 129 sw k1, 0(k0) // Clear this IPI. 130 131 la k0, start_test 132 mfc0 k1, C0_EBASE // Get cp0 EBase 133 ext k1, k1, 0, 10 // Extract CPUNum 134 sll k1, k1, 2 135 addu k0, k0, k1 // index into CMP global "C" variable start_test 136 137 lw k1, 0(k0) # Pickup start_test value 138 addiu k1, k1, 1 # Increment start_test value 139 140 sw k1, 0(k0) // Release "cpu"/vpe to execute "C" test code. 141 eret 142 nop 143#endif 144 145/* EL Change end. */ 146 147 148.section ".vector_0x280","ax" 149 .globl xtlb_refill 150xtlb_refill: 151 sdbbp 152 153.section ".vector_0x300","ax" 154 .globl cache_error 155cache_error: 156 sdbbp 157 158 159/************************************************************************************** 160**************************************************************************************/ 161// RAMHACK: Entry point is _start (execution is started here in (uncached) kseg0. 162 163.section ".text","ax" 164 /* (with vaddr[12..0] = 0 for alignment with GCR_CO_RESET_BASE). */ 165 166 .globl _start 167_start: 168 b verify_isa # Note: Real systems might want to save/dump full context. 169 nop 170 .globl verify_isa 171verify_isa: // Verify device ISA meets code requirements (MIPS32R2 or later.) 172 mfc0 a0, C0_CONFIG // Read CP0 Config 173 srl a0, 10 // Shift [AT AR] into LSBs. 174 andi a3, a0, 0x18 // Inspect CP0 Config[AT] 175 beqz a3, is_mips32 // Branch if executing on MIPS32 ISA. 176 andi a3, a0, 0x07 // Inspect CP0 Config[AR] 177 sdbbp // Failed assertion: MIPS32R2. 178 .globl is_mips32 179is_mips32: 180 bnez a3, init_common_resources // Continue if ISA is MIPS32R2 or later. 181 nop 182 sdbbp // Failed assertion MIPS32R2. 183/************************************************************************************** 184 What is initialized on execution depends on the core/vpe executing it. 185 (A non-MT device is treated as tc0/vpe0, non-CMP device is treated as core0.) 186**************************************************************************************/ 187 .globl init_common_resources 188init_common_resources: // initializes resources for virtual or physical "cpu". 189 la a2,init_gpr // Fill register file with set value. 190 jalr a2 191 nop 192 la a2, set_gpr_boot_values // Fill register file boot info. 193 jalr a2 194 nop 195 196 // Clear Malta Display if processor 0 197 bnez r9_vpe_num, clear_done 198 lui v0, 0xbf00 199 li v1, 0x20 200 sw v1, 1048(v0) 201 sw v1, 1056(v0) 202 sw v1, 1064(v0) 203 sw v1, 1072(v0) 204 sw v1, 1080(v0) 205 sw v1, 1088(v0) 206 sw v1, 1096(v0) 207 sw v1, 1104(v0) 208 .globl clear_done 209clear_done: 210 211 la a2, init_cp0 // Init CP0 Status, Count, Compare, Watch*, and Cause. 212 jalr a2 213 nop 214 215 // Determine if we have a TLB 216 mfc0 v1, C0_CONFIG // read C0_Config 217 ext v1, v1, 7, 3 // extract MT field 218 li a3, 0x1 // load a 1 to check against 219 bne v1, a3, done_tlb // no tlb? 220 nop 221 222 // determined if this is VPE 0 so skip shared TLB check 223 beqz r9_vpe_num, do_tlb // VPE 0? 224 nop 225 226 // Must be VPE1 determined if TLB is shared if it is skip init_tlb (already done by VPE0) 227 mfc0 a0, $0, 1 // MVPControl 228 ext a0, a0, 3, 1 // MVPControl[STLB] 229 beq a0, zero, done_tlb // TLB shared? 230 nop 231 232do_tlb: 233 la a2, init_tlb // Generate unique EntryHi contents per entry pair. 234 jalr a2 235 nop 236 .globl done_tlb 237done_tlb: 238 la a2, init_gic // Configure the global interrupt controller. 239 jalr a2 240 nop 241 242 bnez r9_vpe_num, init_done // If we are not a vpe0 then we are done. 243 nop 244 .globl init_core_resources 245init_core_resources: // We are a vpe0. 246 247 la a2, disable_L23 // Disable L2/L3 caches 248 jalr a2 249 nop 250 251 la a2, init_icache // Initialize the L1 instruction cache. (Executing using I$ on return.) 252 jalr a2 253 nop 254 255// The changing of Kernel mode cacheability must be done from KSEG1 256// Since the code is executing from KSEG0 It needs to do a jump to KSEG1 change K0 and jump back to KSEG0 257 la a2, change_k0_cca 258 li a1, 0xf 259 ins a2, a1, 29, 1 // changed to KSEG1 address by setting bit 29 260 jalr a2 261 nop 262 263// L1 Cache icache is now enabled 264 265 la a2, init_dcache // Initialize the L1 data cache 266 jalr a2 267 nop 268 269 la a2, init_itc // Initialize Inter-Thread Communications unit 270 jalr a2 271 nop 272 273 bnez r8_core_num, init_sys_resources_done // Only core0/vpe0 needs to init systems resources. 274 nop 275 276 .globl init_sys_resources 277init_sys_resources: // We are core0 vpe0. 278 la a2, init_cpc // Initialize the CPS CPC (Cluster Power Controller.) 279 jalr a2 280 nop 281 282 la a2, init_cm // Initialize the CPS CM (Coherence Manager.) 283 jalr a2 284 nop 285 286#ifdef DENALI 287 la a2, init_CoreFPGA6_mem // Initialize the ROC-it2 MC (Memory Controller.) 288 jalr a2 289 nop 290#endif 291 292 la a2, copy_c2_ram // Copy "C" code and data to RAM and zero bss (uncached.) 293 jalr a2 294 nop 295 296 la a2, init_L23 // Initialize the unified L2 and L3 caches 297 jalr a2 298 nop 299 300 /* EL Change. Ensure that the VPE release flag is cleared ahead of BSS clear. */ 301 302 la $8, _tx_thread_smp_release_cores_flag # Build address of release flag 303 sw $0, 0($8) # Clear the flag explicity to make other VPEs don't see it before everything is initialized 304 305 /* EL end Change. */ 306 307 308 la a2, release_mp // Release other cores to execute this boot code. 309 jalr a2 310 nop 311 312init_sys_resources_done: // All Cores (VPE0) 313 314 la a2, join_domain // Join the Coherence domain. (OK to use D$ on return.) 315 jalr a2 316 nop 317 318 la a2, init_vpe1 // Set up MT ASE vpe1 to execute this boot code also. 319 jalr a2 320 nop 321 322 /* EL Change. Add optional user-specified VPE wakeup setup code call. */ 323 324#ifdef TX_THREAD_SMP_WAKEUP_LOGIC 325 326 /* Call optional user-specific code for VPE initialization. */ 327 328 subu $29, 8 # Allocate space to save ra 329 sw $31, 4($29) # Save R31 330 la $9, TX_THREAD_SMP_WAKEUP_LOGIC_SETUP 331 jalr $9 # User-specified VPE setup logic 332 nop # 333 lw $31, 4($29) # Restore ra 334 addu $29, 8 # De-allocate stack storage 335#endif 336 337 /* EL Change End. */ 338 339 .globl init_done 340init_done: 341 342 /* EL Change. Removed call to demo code and instead setup for ThreadX execution. */ 343 344 /* For all VPEs, store the cpu number into the UserLocal field so it is easy to pickup. */ 345 346 mtc0 r23_cpu_num, $4,2 # Save the logical VPE in UserLocal so we don't have calculate it over and over! */ 347 348 /* Save the stack pointer in the array indexed by cpu number. */ 349 350 la $8, _tx_thread_system_stack_ptr # Build address of base of system stack array 351 sll $9, r23_cpu_num, 2 # Build offset into array 352 addu $8, $8, $9 # Build address of array entry 353 sw $29, 0($8) # Store system stack for each VPE 354 355 /* Setup status register in preparation for entering ThreadX. */ 356 357 mfc0 $8, $12 # Pickup SR 358 li $9, 0xFFFFFFF8 # Build mask to clear error, exception bits 359 and $8, $8, $9 # Clear bits 360 ori $8, $8, 1 # Disable all interrupts 361 mtc0 $8, $12 # Setup the status register 362 ehb # 363 364 /* Check for Core 0, VPE 0 for processing ThreadX initialization. All other VPEs will wait until the first 365 VPE has completed initialization before running. */ 366 367 bne r23_cpu_num, $0, _additional_vpe # If non-zero, an additional vpe is present 368 nop # 369 370 /* Core 0, VPE 0 processing. */ 371 372 /* Save some information in globals. */ 373 374 la $8, _tx_thread_smp_detected_cores # Build address of total number of cores detected 375 addiu $9, r19_more_cores, 1 # Calculate the total cores 376 sw $9, 0($8) # Save in global variable 377 378 la $8, _tx_thread_smp_detected_vpes_per_core # Build address of VPEs per core detected 379 addiu $9, r20_more_vpes, 1 # Caculate the total vpes per core 380 sw $9, 0($8) # Save in global variable 381 382 383 /* Simply branch to main to finish initializing ThreadX SMP. */ 384 385 bal main # Branch to main 386 nop # 387 388 /* If return, branch to all_done code. */ 389 390 b all_done 391 nop 392 393 394_additional_vpe: 395 396 397 /* Additional VPE, transfer control to ThreadX. */ 398 399 b _tx_thread_smp_initialize_wait # Enter ThreadX for additional VPEs 400 nop 401 402 .globl all_done 403all_done: 404 b all_done 405 406/* Comment out the previous "init_done" code since it is replaced with ThreadX-specfic code. */ 407#if 0 408 409 mtc0 r23_cpu_num, $4,2 # Setup UserLocal 410 411 // Prepare for eret to main (sp and gp set up per vpe in init_gpr). 412 la ra, all_done // If main return then go to all_done:. 413 la a1, main 414 mtc0 a1, C0_ERRPC // ErrorEPC 415 416 // initialize global variable num_cores. 417// la a1, num_cores 418 // RAMHACK: caches are coherent use cached reference to "C" static "num_cores". 419 // ins a1, r1_all_ones, 29, 1 // Uncached kseg1 420// add a0, r19_more_cores, 1 421// sw a0, 0(a1) 422 423 // Prepare arguments for main() 424 move a0, r23_cpu_num // main(arg0) is the "cpu" number (cp0 EBase[CPUNUM].) 425 move a1, r8_core_num // main(arg1) is the core number. 426 move a2, r9_vpe_num // main(arg2) is the vpe number. 427 addiu a3, r20_more_vpes, 1 // main(arg3) is the number of vpe on this core. 428 429 // RAMHACK: Main appears to take first arg from r16 (s0) in GHS build? 430 move s0, r23_cpu_num // main(arg0) is the "cpu" number (cp0 EBase[CPUNUM].) 431 432 eret // Exit reset exception handler for this vpe and start execution of main(). 433 434 435/************************************************************************************** 436**************************************************************************************/ 437 .globl all_done 438all_done: 439 440 // Main returns the "cpu" number 441 // All cpu spin on atomic potato++ 442 443// la a1, potato 444 445try_again: 446 ll a0, 0(a1) 447 addiu a0, a0, 1 448 sc a0, 0(a1) // Attempt atomic potato++ 449 450 beq a0, $0, try_again // Fail, retry. 451 nop 452 453 b try_again // Success, do again. 454 nop 455 456 b all_done 457 nop 458#endif 459 /* EL Change end. */ 460 461 462