⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sb1250_altcpu.s

📁 一个很好的嵌入式linux平台下的bootloader
💻 S
📖 第 1 页 / 共 2 页
字号:
	#		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 + -