powerpc e500系列,linux初始化的tlb汇编,添加人肉代码注释
powerpc e500的内核启动,关于tlb的初始化可以说是重头戏。看懂这段代码后,powerpc的虚实映射基本不在话下。
这段初始化tlb要考虑的,主要是将boot可能初始化过的tlb全清零,然后自己建立一套PAGE_OFFSET的虚实映射,即为0xc打头的地址
建立映射。
inux kernel 3.10.7将这段初始化代码,全部放到fsl_booke_entry_mapping.S里,这段代码除了linux初始化会用,
也被kexec使用。下面先直接贴出代码,之后分析核心流程。
/* 1. Find the index of the entry we're executing in */blinvstr/* Find our address */invstr:mflrr6/* Make it accessible */mfmsrr7rlwinmr4,r7,27,31,31/* extract MSR[IS] */ mfsprr7, SPRN_PID0 slwir7,r7,16orr7,r7,r4mtsprSPRN_MAS6,r7tlbsx0,r6/* search MSR[IS], SPID=PID0 */mfsprr7,SPRN_MAS1andis.r7,r7,MAS1_VALID@h bnematch_TLBmfsprr7,SPRN_MMUCFGrlwinmr7,r7,21,28,31/* extract MMUCFG[NPIDS] */cmpwir7,3bnematch_TLB/* skip if NPIDS != 3 */mfsprr7,SPRN_PID1slwir7,r7,16orr7,r7,r4mtsprSPRN_MAS6,r7tlbsx0,r6/* search MSR[IS], SPID=PID1 */mfsprr7,SPRN_MAS1andis.r7,r7,MAS1_VALID@hbnematch_TLBmfsprr7, SPRN_PID2slwir7,r7,16orr7,r7,r4mtsprSPRN_MAS6,r7tlbsx0,r6/* Fall through, we had to match */match_TLB:mfsprr7,SPRN_MAS0rlwinmr3,r7,16,20,31/* Extract MAS0(Entry) */ mfsprr7,SPRN_MAS1/* Insure IPROT set */ orisr7,r7,MAS1_IPROT@hmtsprSPRN_MAS1,r7tlbwe/* 2. Invalidate all entries except the entry we're executing in */mfsprr9,SPRN_TLB1CFGandi.r9,r9,0xfff //r9 = tlb numberlir6,0/* Set Entry counter to 0 */1:lisr7,0x1000/* Set MAS0(TLBSEL) = 1 */ rlwimir7,r6,16,4,15/* Setup MAS0 = TLBSEL | ESEL(r6) */mtsprSPRN_MAS0,r7tlbremfsprr7,SPRN_MAS1rlwinmr7,r7,0,2,31/* Clear MAS1 Valid and IPROT */cmpwr3,r6beqskpinv/* Dont update the current execution TLB */mtsprSPRN_MAS1,r7tlbweisyncskpinv:addir6,r6,1/* Increment */cmpwr6,r9/* Are we done? */bne1b/* If not, repeat *//* Invalidate TLB0 */lir6,0x04tlbivax 0,r6TLBSYNC/* Invalidate TLB1 */lir6,0x0ctlbivax 0,r6TLBSYNC/* 3. Setup a temp mapping and jump to it */andi.r5, r3, 0x1/* Find an entry not used and is non-zero */addir5, r5, 0x1lisr7,0x1000/* Set MAS0(TLBSEL) = 1 */ rlwimir7,r3,16,4,15/* Setup MAS0 = TLBSEL | ESEL(r3) */mtsprSPRN_MAS0,r7tlbre/* grab and fixup the RPN */mfsprr6,SPRN_MAS1/* extract MAS1[SIZE] */rlwinmr6,r6,25,27,31 lir8,-1addir6,r6,10slwr6,r8,r6/* convert to mask */ bl1f/* Find our address */1:mflrr7mfsprr8,SPRN_MAS3#ifdef CONFIG_PHYS_64BITmfsprr23,SPRN_MAS7#endifandr8,r6,r8subficr9,r6,-4096andr9,r9,r7orr25,r8,r9orir8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)/* Just modify the entry ID and EPN for the temp mapping */lisr7,0x1000/* Set MAS0(TLBSEL) = 1 */rlwimir7,r5,16,4,15/* Setup MAS0 = TLBSEL | ESEL(r5) */mtsprSPRN_MAS0,r7xorir6,r4,1/* Setup TMP mapping in the other Address space */slwir6,r6,12orisr6,r6,(MAS1_VALID|MAS1_IPROT)@horir6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@lmtsprSPRN_MAS1,r6mfsprr6,SPRN_MAS2lir7,0/* temp EPN = 0 */ rlwimir7,r6,0,20,31mtsprSPRN_MAS2,r7mtsprSPRN_MAS3,r8tlbwexorir6,r4,1slwir6,r6,5/* setup new context with other address space */bl1f/* Find our address */1:mflrr9rlwimir7,r9,0,20,31 addir7,r7,(2f - 1b)mtsprSPRN_SRR0,r7mtsprSPRN_SRR1,r6rfi2:/* 4. Clear out PIDs & Search info */lir6,0mtspr SPRN_MAS6,r6mtsprSPRN_PID0,r6mfsprr7,SPRN_MMUCFGrlwinmr7,r7,21,28,31/* extract MMUCFG[NPIDS] */cmpwir7,3bne2f/* skip if NPIDS != 3 */mtsprSPRN_PID1,r6mtsprSPRN_PID2,r6/* 5. Invalidate mapping we started in */2:lisr7,0x1000/* Set MAS0(TLBSEL) = 1 */rlwimir7,r3,16,4,15/* Setup MAS0 = TLBSEL | ESEL(r3) */mtsprSPRN_MAS0,r7tlbremfsprr6,SPRN_MAS1rlwinmr6,r6,0,2,0/* clear IPROT */mtsprSPRN_MAS1,r6tlbwe/* Invalidate TLB1 */lir9,0x0ctlbivax 0,r9TLBSYNC/* The mapping only needs to be cache-coherent on SMP */#ifdef CONFIG_SMP#define M_IF_SMPMAS2_M#else#define M_IF_SMP0#endif#if defined(ENTRY_MAPPING_BOOT_SETUP)/* 6. Setup KERNELBASE mapping in TLB1[0] */lisr6,0x1000/* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */mtsprSPRN_MAS0,r6lisr6,(MAS1_VALID|MAS1_IPROT)@horir6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@lmtsprSPRN_MAS1,r6lisr6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@horir6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@lmtsprSPRN_MAS2,r6mtsprSPRN_MAS3,r8tlbwe/* 7. Jump to KERNELBASE mapping */lisr6,(KERNELBASE & ~0xfff)@horir6,r6,(KERNELBASE & ~0xfff)@l#elif defined(ENTRY_MAPPING_KEXEC_SETUP)/* * 6. Setup a 1:1 mapping in TLB1. Esel 0 is unsued, 1 or 2 contains the tmp * mapping so we start at 3. We setup 8 mappings, each 256MiB in size. This * will cover the first 2GiB of memory. */lis r10, (MAS1_VALID|MAS1_IPROT)@hori r10,r10, (MAS1_TSIZE(BOOK3E_PAGESZ_256M))@lli r11, 0li r0, 8mtctr r0next_tlb_setup:addir0, r11, 3rlwinm r0, r0, 16, 4, 15 // Compute eselrlwinm r9, r11, 28, 0, 3 // Compute [ER]PNoris r0, r0, (MAS0_TLBSEL(1))@hmtspr SPRN_MAS0,r0mtspr SPRN_MAS1,r10mtspr SPRN_MAS2,r9ori r9, r9, (MAS3_SX|MAS3_SW|MAS3_SR)mtspr SPRN_MAS3,r9tlbweaddi r11, r11, 1bdnz+ next_tlb_setup/* 7. Jump to our 1:1 mapping */mrr6, r25#else#error You need to specify the mapping or not use this at all.#endiflisr7,MSR_KERNEL@horir7,r7,MSR_KERNEL@lbl1f/* Find our address */1:mflrr9rlwimir6,r9,0,20,31addir6,r6,(2f - 1b)mtsprSPRN_SRR0,r6mtsprSPRN_SRR1,r7rfi/* start execution out of TLB1[0] entry *//* 8. Clear out the temp mapping */2:lisr7,0x1000/* Set MAS0(TLBSEL) = 1 */rlwimir7,r5,16,4,15/* Setup MAS0 = TLBSEL | ESEL(r5) */mtsprSPRN_MAS0,r7tlbremfsprr8,SPRN_MAS1rlwinmr8,r8,0,2,0/* clear IPROT */mtsprSPRN_MAS1,r8tlbwe/* Invalidate TLB1 */lir9,0x0ctlbivax 0,r9TLBSYNC