3. CPU Initialization
The following code initializes the CPU. The functions are blocked by watchdog, the interrupt control register is initialized, the cache is cleared, and MMU is disabled.
. Globlinit_e300_coreinit_e300_core:/* time T 10 * // * initialize machine status; Enable machine check interrupt */lir3, msr_kernel/* Set MSR, allow data \ command replication and machine check */rlwimir3, R5, 0, 25, 25/* preserve IP bit set by hrcw */# ifdef debugrlwimir3, R5, 0, 21, 22/* debugger might set se & be bits */# endifsync/* some chip revs need this... */mtmsrr3syncmtsprsrr1, R3/* Make srr1 match MSR interrupt related */lisr3, ipv_ I MMR @ H # If defined (config_watchdog)/* initialise the wathcdog values and reset it (if req) */LIS R4, 1_r4, R4, (swcrr_swen | swcrr_swri | swcrr_swpr) STW R4, swcrr (r3)/* and reset it */lir4, 0x556csthr4, swsrr @ l (r3) lir4,-0x55c7sthr4, swsrr @ l (r3) # else/* disable wathcdog */lwz R4, swcrr (r3)/* check to see if its enabled for disabling once disabled by Sw You can't re-enable */Andi. r4, r4, 0x4beq 1 fxor R4, R4, r4stw R4, swcrr (r3) 1: # endif/* config_watchdog * // * initialize the hardware implementation-dependent registers * // * hid0 also contains Cache Control * // * optional */lisr3, __hid0_init @ horir3, R3, cfg_hid0_init @ login, r3lisr3, cfg_hid0_final @ horir3, R3, 1__hid0_final @ lsyncmtsprhid0, r3lisr3, 1__hid2 @ horir3, R3, 1__hid2 @ Lsyncmtsprhid2, R3/* disable the MMU function, first clear all bat (block address translation) */xorr0, R0, priority, priority, r0mtsprdbat1u, r0mtsprdbat1l, r0mtsprdbat2u, priority, disable, disable, disable, r0mtspribat1l, r0mtspribat2u, hour, r0sync/* disable TLB (fast table) */lir3, 32mtctrr3lir3, 01: tlbier3addir3, R3, 0x1000bdnz1bsync/* done! */BLR
Note that when the program runs in flash, the jump command is used to execute the program jump, but not the absolute address jump (that is, directly operate on the PC ). If an absolute address is used, the address of the program is a space forward or backward relative to the current PC position, instead of jumping into the SDRAM.
4. initialize the memory controller.
The initial knowledge of the PowerPC processor memory controller is implemented by operating bat and TLB, ibat0 ~ 7. dbat0 ~ 7. initialize and disable TLB. The Code is as follows:
/* setup_bats - set them up to some initial state */.globlsetup_batssetup_bats:addisr0, r0, 0x0000/* IBAT 0 */addisr4, r0, CFG_IBAT0L@horir4, r4, CFG_IBAT0L@laddisr3, r0, CFG_IBAT0U@horir3, r3, CFG_IBAT0U@lmtsprIBAT0L, r4mtsprIBAT0U, r3isync/* DBAT 0 */addisr4, r0, CFG_DBAT0L@horir4, r4, CFG_DBAT0L@laddisr3, r0, CFG_DBAT0U@horir3, r3, CFG_DBAT0U@lmtsprDBAT0L, r4mtsprDBAT0U, r3isync#ifdef CONFIG_HIGH_BATS/* IBAT 4 */addis r4, r0, CFG_IBAT4L@hori r4, r4, CFG_IBAT4L@laddis r3, r0, CFG_IBAT4U@hori r3, r3, CFG_IBAT4U@lmtspr IBAT4L, r4mtspr IBAT4U, r3isync/* DBAT 4 */addis r4, r0, CFG_DBAT4L@hori r4, r4, CFG_DBAT4L@laddis r3, r0, CFG_DBAT4U@hori r3, r3, CFG_DBAT4U@lmtspr DBAT4L, r4mtspr DBAT4U, r3isync#endif/* Invalidate TLBs. * -> for (val = 0; val < 0x20000; val+=0x1000) * -> tlbie(val); */lisr3, 0lisr5, 21:tlbier3addir3, r3, 0x1000cmp0, 0, r3, r5blt1bblr
The above only posts the bat operation code for each of the high and low bits. Other operations are similar.
5. Copy the program to ram
In PowerPC, this program does not return. After all the program code is copied to Rom, it will continue to run directly in Ram:
/* If the code is copied and no response is returned, call in_ram to execute */addir0, R10, in_ram-_ start + exc_off_sys_resetmtlrr0blr.globlrelocate_coderelocate_code: mrr1, r3/* Create a New stack pointer */mrr9, R4/* Backup */mrr10, r5mrr3, R5/* R3: copy end point */lisr4, performance_monitor_base @ H/* R4: Copy start point */orir4, R4, performance_monitor_base @ llwzr5, got (_ init_end) subr5, R5, R4/* R5: copy length */lir6, pai_cacheline_size/* cache line size * // * New GOT-PTR = (old GOT-PTR-pai_monitor_base) + Destination Address */subr15, R10, R4/* First our own got */addr14, R14, R15/* then the one used by the C code */addr30, R30, r15/* Now relocate Code */cmplwcr1, R3, r4addir0, R5, 3srwi. r0, R0, 2beqcr1, 4f/* in place copy is not necessary */beq7f/* Protect Against 0 count */mtctrr0bgecr1, 2flar8,-4 (R4) lar7, -4 (r3)/* Copy */1: lwzur0, 4 (R8) stwur0, 4 (r7) bdnz1baddir0, R5, 3srwi. r0, R0, 2mtctrr0lar8,-4 (R4) lar7,-4 (R 3)/* and compare */20: lwzur20, 4 (R8) lwzur21, 4 (r7) XOR. r22, R20, r21bne 30fbdnz20bb 4f/* compare failed */30: Li R3, 0blr2: slwir0, R0, 2/* re copy in reverse order... y do we needed it? */Addr8, R4, r0addr7, R3, r03: lwzur0,-4 (R8) stwur0,-4 (r7) bdnz3b/** now flush the cache: note that we must start from a cache aligned * address. otherwise we might miss one cache line. */4: cmpwir6, 0addr5, R3, queues/* always flush prefetch queue in any case */subir0, R6, 1and375, R3, r0mrr4, r35: dcbst0, r4addr4, R4, r6cmplwr4, r5blt5bsync/* Wait For All dcbst to complete on bus */mrr4, r36: icbi0, r4addr4, R4, r6cmplwr4, r5blt6b7: sync/* Wait For All icbi to complete on bus */isync
6. initialize the stack
For the mpc83xx series, the initialization stack code is as follows:
/* set up the stack pointer in our newly created cache-ram (r1) */lisr1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@horir1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@llir0, 0/* Make room for stack frame header and*/stwur0, -4(r1)/* clear final stack frame so that*/stwur0, -4(r1)/* stack backtraces terminate cleanly*/
7. Jump to the stage2 entrance
This is also the last step of stage1. After the program executes this step, the basic hardware initialization is complete. The following is the code to jump:
GET_GOT/* initialize GOT access*//* r3: IMMR */lisr3, CFG_IMMR@h/* run low-level CPU init code (in Flash)*/blcpu_init_f/* r3: BOOTFLAG */mrr3, r21/* run 1st part of board init code (in Flash)*/blboard_init_f
Board_init_f is the function entry of stage2.
From the above we can see that start. the s process is as follows: exception vector -- enter the reset exception vector after power-on -- jump to the startup code -- set the processor to enter management mode -- disable the watchdog -- disable the interrupt -- set the clock frequency division -- disable MMU and cache -- enter lowlever_init.s -- check the location of the current Code, if it is in flash, the code will be moved to ram. So far, stage1 analysis has ended.
After the jump to board_init_f, the program starts to execute the stage2 stage, and the code is mostly C.