📄 sb1250_altcpu.s
字号:
# la a0,PHYS_TO_K1(A_IMR_REGISTER(1,R_IMR_MAILBOX_SET_CPU)) LR t0,mem_datareloc or t0,1 sd t0,0(a0) # # CPU1 is back in our control. # move ra,t7 move v0,zero j raEND(sb1250_altcpu_kill)/* ********************************************************************* * ALTCPU_RESET * * Start address for secondary CPU(s) - do the initialization of * the local CPU and then notify CPU0 that we're done. * * This routine is called in KSEG1. * * Input parameters: * t0 - CPU identifier * * Return value: * nothing ********************************************************************* */LEAF(sb1250_altcpu_reset) mfc0 t0,C0_PRID # get CPU PRID register and t0,t0,0xe000000 # determine cpu number beq t0,zero,iscpu0 # go if on CPU0#if CFG_RELOC /* * SVR4 PIC mode: get a copy of GP for use in the boot ROM. */ lui gp,%hi(_gp) addiu gp,%lo(_gp) or gp,gp,K1BASE#endif /* * Note: we should never get to the CPU1 code if we're * with only one CPU. Theoretically, nobody got past the * check in altcpu_start. But, just in case, if we * get here and we're on CPU1, and we supposedly only * have one CPU, reset CPU1. */ la t0,PHYS_TO_K1(A_SCD_SYSTEM_REVISION) ld t0,(t0) # Get system revision dsrl t0,S_SYS_PART # Shift part # to low bits dsrl t0,8 # isolate CPU part of number and t0,0x0F # T0 = number of CPUs beq t0,1,iscpu0 # If only one CPU, kill off CPU1 /* * Initialize CPU registers. */ JAL_KSEG1(sb1_cpu_init)#ifdef _SB1250_PASS1_WORKAROUNDS_ /* * See the above note about this workaround. It's important * to remain noncoherent until we're done with the flash. */ SETCCAMODE(v0,K_CFG_K0COH_CACHEABLE) /* cacheable NONCOHERENT */#endif SETLEDS1('C','P','U','1') /* * Initialize the L1 cache */#if CFG_INIT_L1 JAL_KSEG1(sb1250_l1cache_init)#endif /* * Notify the SCD that we're done initializing. Do this by * ringing CPU0's doorbell. */ la a0,PHYS_TO_K1(A_IMR_REGISTER(0,R_IMR_MAILBOX_SET_CPU)); mfc0 t0,C0_PRID # get processor number srl t0,t0,25 # shift CPU bits into low and t0,t0,7 # keep only low 3 bits li t1,1 # make a bit mask depending on CPU sll t1,t1,t0 # calculate t1 = 1 shl cpu number sd t1,0(a0) # set corresponding bit in mailbox /* * Go to the idle loop */ b altcpu_idle # go to idle loop /* * We get here if we were running on CPU0. Make things * pretty for the reset of CPU initialization. */iscpu0: /* * If we are on CPU0, then force CPU1 into reset. This is needed * for the case where the firmware has crashed and we need to get * control of the system again. */ li a0,PHYS_TO_K1(A_SCD_SYSTEM_CFG) ld t0,0(a0) dli t1,M_SYS_CPU_RESET_1 # Reset mask or t0,t1 # New value to write sd t0,0(a0) # CPU1 is now in reset j ra # return (we were on CPU 0)END(sb1250_altcpu_reset)/* ********************************************************************* * ALTCPU_CMD_START(cpu,addr) * * Start an alternate CPU. * * Input parameters: * a0 - cpu number (must be 1 for the SB1250) * a1 - pointer to start parameters (four 64-bit values) * array[0] = start address (PC) * array[1] = start stack pointer (SP) * array[2] = start global pointer (GP) * array[3] = start user argument (A1) * * Return value: * v0 - 0 if ok * else -1 if request could not be handled ********************************************************************* */#define R_CPUSTART_PCVAL 0#define R_CPUSTART_SPVAL 8#define R_CPUSTART_GPVAL 16#define R_CPUSTART_A1VAL 24LEAF(altcpu_cmd_start) li v0,-1 /* assume failure */ bne a0,1,1f /* go if not CPU 1 */ /* * Return an error if running in uniprocessor mode. */ la t0,PHYS_TO_K1(A_SCD_SYSTEM_REVISION) ld t0,(t0) # Get system revision dsrl t0,S_SYS_PART # Shift part # to low bits dsrl t0,8 # isolate CPU part of number and t0,0x0F # T0 = number of CPUs beq t0,1,1f # If only one CPU, error. /* * Multiprocessor mode, start the other CPU */ move t0,a0 /* get CPU number */ sll t0,BPWSIZE /* multiply by 8/4 for 64/32-bit offset */ la t1,cpu_start_gpvals add t1,t0 /* copy the GP value */ ld t2,R_CPUSTART_GPVAL(a1) SR t2,0(t1) la t1,cpu_start_spvals add t1,t0 /* copy the SP value */ ld t2,R_CPUSTART_SPVAL(a1) SR t2,0(t1) la t1,cpu_start_args add t1,t0 /* copy the A1 value */ ld t2,R_CPUSTART_A1VAL(a1) SR t2,0(t1) la t1,cpu_startvectors add t1,t0 /* copy the PC value */ ld t2,R_CPUSTART_PCVAL(a1) SR t2,0(t1) move v0,zero /* success */1: j raEND(altcpu_cmd_start)/* ********************************************************************* * ALTCPU_CMD_STOP(cpu) * * Stop the specified CPU. * * We don't really support this at the moment. * * Input parameters: * a0 - cpu number * * Return value: * v0 - 0 if ok, else error code ********************************************************************* */LEAF(altcpu_cmd_stop) li v0,-1 /* assume failure */ bne a0,1,1f /* go if not CPU 1 */ /* * Return an error if running in uniprocessor mode. */ la t0,PHYS_TO_K1(A_SCD_SYSTEM_REVISION) ld t0,(t0) # Get system revision dsrl t0,S_SYS_PART # Shift part # to low bits dsrl t0,8 # isolate CPU part of number and t0,0x0F # T0 = number of CPUs beq t0,1,1f # If only one CPU, error. /* * Multiprocessor mode, stop the other CPU */ JMP(sb1250_altcpu_kill) /* kill the CPU */1: j raEND(altcpu_cmd_stop)/* ********************************************************************* * ALTCPU_IDLE * * Loop forever waiting for someone to tell us where to go. * * Input parameters: * nothing. * * Return value: * nothing ********************************************************************* */altcpu_idle: /* * Switch to KSEG0 (cached) */ bal altcpu_kseg0_switch#if CFG_RELOC lui gp,%hi(_gp) addiu gp,%lo(_gp)#endif SETLEDS('c','p','u','1') /* * Now wait for CPU0 to ring *our* doorbell. This is our signal that * it's safe to go to the idle loop. Until CPU0 rings our * doorbell, we can't use memory (but we can use the cache). * XXX Very SB1250 specific here. */1: la a0,PHYS_TO_K1(A_IMR_REGISTER(1,R_IMR_MAILBOX_CPU)) ld t0,(a0) # Read mailbox beq t0,zero,1b # Loop till the bit is set /* * Clear all the bits in the mailbox register to dismiss the * pending interrupt */ la a0,PHYS_TO_K1(A_IMR_REGISTER(1,R_IMR_MAILBOX_CLR_CPU)) li t1,-1 sd t1,0(a0) /* * We may need GP, especially in relocated version * * Yucky hack: The relocation factor was passed to us in * the mailbox register, which is conveniently in t0 right now. * (except the lower bit is set just in case the reloc was * zero, so clear that first). */ li t1,1 # 1 not t1 # FFFFFFFFE and t0,t1 # clear lower bit.#if (CFG_RELOC) /* * SVR4 PIC: GP is already set to GOT, relocate * it and jump to relocated code */__AltCpuGoRel: la t1,1f # Get address of where to go ADDU gp,t0 # Relocate GP ADDU t1,t0 # Relocate address jr t1 # Go there.1: # we will go "here" in the reloc world#else /* * non-PIC: Standard GP */ la gp,_gp ADD gp,t0 # relocate GP.#endif /* * Get our processor number */ mfc0 t0,C0_PRID # Get PRID (for processor id) srl t0,t0,25 # shift CPU bits into low and t0,t0,7 # keep only low 3 bits sll t0,t0,BPWSIZE # mult by 8/4 for 64/32-bit offset /* * Set up registers like we were launching a program. */ la a2,cpu_apientry # A2 = firmware entry vector move a0,gp # A0 = handle li a3,CFE_EPTSEAL # A3 = entrypoint signature#ifdef _SB1250_PASS1_WORKAROUNDS_ /* * Okay, it's safe now to be coherent. * Flush the D cache to invalidate all the lines we have, * then change the config register back. * * Danger! It's imperative that *no stores to memory* be done * prior to this point, otherwise flushing the cache * will race with core 0, which will also be flushing * lines at this time. */ move k0,t0 JAL(sb1250_l1cache_flush_d) SETCCAMODE(v0,K_CFG_K0COH_COHERENT) /* cacheable coherent */ move t0,k0#endif /* * Read the start address from the CPU restart table * and jump to it. For an idle CPU, the address in the * table below will be the zero, causing * the CPU to loop forever. To start a secondary CPU, * just write an address in cpu_startvectors[cpu_id] * * Warning: This kind of assumes that this code will * live in cacheable space. If it doesn't, it will * probably cause lots of unwanted bus traffic. */ li s4,0loop_forever: LR t1,cpu_startvectors(t0) # Load address of routine beq t1,zero,loop_forever LR a1,cpu_start_args(t0) # Load user argument (A1) LR sp,cpu_start_spvals(t0) # Load stack pointer LR t2,cpu_start_gpvals(t0) # Load global pointer move gp,t2 # and put in real register j t1 # jump to start address/* ********************************************************************* * End ********************************************************************* */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -