日期:2014-05-16  浏览次数:20745 次

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 */
	bl	invstr				/* Find our address */
invstr:	mflr	r6				/* Make it accessible */
	mfmsr	r7
	rlwinm	r4,r7,27,31,31			/* extract MSR[IS] */ 
	mfspr	r7, SPRN_PID0   
	slwi	r7,r7,16
	or	r7,r7,r4
	mtspr	SPRN_MAS6,r7
	tlbsx	0,r6				/* search MSR[IS], SPID=PID0 */
	mfspr	r7,SPRN_MAS1
	andis.	r7,r7,MAS1_VALID@h  
	bne	match_TLB

	mfspr	r7,SPRN_MMUCFG
	rlwinm	r7,r7,21,28,31			/* extract MMUCFG[NPIDS] */
	cmpwi	r7,3
	bne	match_TLB			/* skip if NPIDS != 3 */

	mfspr	r7,SPRN_PID1
	slwi	r7,r7,16
	or	r7,r7,r4
	mtspr	SPRN_MAS6,r7
	tlbsx	0,r6				/* search MSR[IS], SPID=PID1 */
	mfspr	r7,SPRN_MAS1
	andis.	r7,r7,MAS1_VALID@h
	bne	match_TLB
	mfspr	r7, SPRN_PID2
	slwi	r7,r7,16
	or	r7,r7,r4
	mtspr	SPRN_MAS6,r7
	tlbsx	0,r6				/* Fall through, we had to match */

match_TLB:
	mfspr	r7,SPRN_MAS0
	rlwinm	r3,r7,16,20,31			/* Extract MAS0(Entry) */ 

	mfspr	r7,SPRN_MAS1			/* Insure IPROT set */ 
	oris	r7,r7,MAS1_IPROT@h
	mtspr	SPRN_MAS1,r7
	tlbwe

/* 2. Invalidate all entries except the entry we're executing in */
	mfspr	r9,SPRN_TLB1CFG
	andi.	r9,r9,0xfff  //r9 = tlb number
	li	r6,0				/* Set Entry counter to 0 */
1:	lis	r7,0x1000			/* Set MAS0(TLBSEL) = 1 */ 
	rlwimi	r7,r6,16,4,15			/* Setup MAS0 = TLBSEL | ESEL(r6) */
	mtspr	SPRN_MAS0,r7
	tlbre
	mfspr	r7,SPRN_MAS1
	rlwinm	r7,r7,0,2,31			/* Clear MAS1 Valid and IPROT */
	cmpw	r3,r6
	beq	skpinv				/* Dont update the current execution TLB */
	mtspr	SPRN_MAS1,r7
	tlbwe
	isync
skpinv:	addi	r6,r6,1				/* Increment */
	cmpw	r6,r9				/* Are we done? */
	bne	1b				/* If not, repeat */

	/* Invalidate TLB0 */
	li	r6,0x04
	tlbivax 0,r6
	TLBSYNC
	/* Invalidate TLB1 */
	li	r6,0x0c
	tlbivax 0,r6
	TLBSYNC

/* 3. Setup a temp mapping and jump to it */
	andi.	r5, r3, 0x1	/* Find an entry not used and is non-zero */
	addi	r5, r5, 0x1
	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */ 
	rlwimi	r7,r3,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r3) */
	mtspr	SPRN_MAS0,r7
	tlbre

	/* grab and fixup the RPN */
	mfspr	r6,SPRN_MAS1	/* extract MAS1[SIZE] */
	rlwinm	r6,r6,25,27,31   
	li	r8,-1
	addi	r6,r6,10
	slw	r6,r8,r6	/* convert to mask */ 

	bl	1f		/* Find our address */
1:	mflr	r7

	mfspr	r8,SPRN_MAS3
#ifdef CONFIG_PHYS_64BIT
	mfspr	r23,SPRN_MAS7
#endif
	and	r8,r6,r8
	subfic	r9,r6,-4096
	and	r9,r9,r7

	or	r25,r8,r9
	ori	r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)

	/* Just modify the entry ID and EPN for the temp mapping */
	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
	rlwimi	r7,r5,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r5) */
	mtspr	SPRN_MAS0,r7
	xori	r6,r4,1		/* Setup TMP mapping in the other Address space */
	slwi	r6,r6,12
	oris	r6,r6,(MAS1_VALID|MAS1_IPROT)@h
	ori	r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
	mtspr	SPRN_MAS1,r6
	mfspr	r6,SPRN_MAS2
	li	r7,0		/* temp EPN = 0 */ 
	rlwimi	r7,r6,0,20,31
	mtspr	SPRN_MAS2,r7
	mtspr	SPRN_MAS3,r8
	tlbwe

	xori	r6,r4,1
	slwi	r6,r6,5		/* setup new context with other address space */
	bl	1f		/* Find our address */
1:	mflr	r9

	rlwimi	r7,r9,0,20,31  
					
	addi	r7,r7,(2f - 1b)
	mtspr	SPRN_SRR0,r7
	mtspr	SPRN_SRR1,r6
	rfi
2:
/* 4. Clear out PIDs & Search info */
	li	r6,0
	mtspr   SPRN_MAS6,r6
	mtspr	SPRN_PID0,r6

	mfspr	r7,SPRN_MMUCFG
	rlwinm	r7,r7,21,28,31			/* extract MMUCFG[NPIDS] */
	cmpwi	r7,3
	bne	2f				/* skip if NPIDS != 3 */

	mtspr	SPRN_PID1,r6
	mtspr	SPRN_PID2,r6

/* 5. Invalidate mapping we started in */
2:
	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
	rlwimi	r7,r3,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r3) */
	mtspr	SPRN_MAS0,r7
	tlbre
	mfspr	r6,SPRN_MAS1
	rlwinm	r6,r6,0,2,0	/* clear IPROT */
	mtspr	SPRN_MAS1,r6
	tlbwe
	/* Invalidate TLB1 */
	li	r9,0x0c
	tlbivax 0,r9
	TLBSYNC

/* The mapping onl