/* As with the other PowerPC ports, it is expected that when code *executionbeginshere,thefollowingregisterscontainvalid,yet *optional,information: * *r3-Boardinfostructurepointer(DRAM,frequency,MACaddress,etc.) *r4-StartingaddressoftheinitRAMdisk *r5-EndingaddressoftheinitRAMdisk *r6-Startofkernelcommandlinestring(e.g."mem=128") *r7-Endofkernelcommandlinestring *
*/
__HEAD
_GLOBAL(_stext);
_GLOBAL(_start); /* *Reserveawordatafixedlocationtostoretheaddress *ofabatron_pteptrs
*/
nop
mr r31,r3 /* save device tree ptr */
li r24,0/* CPU number */
#ifdef CONFIG_RELOCATABLE /* *Relocateourselvestothecurrentruntimeaddress. *ThisiscalledonlybytheBootCPU. *"relocate"iscalledwithourcurrentruntimevirutal *address. *r21willbeloadedwiththephysicalruntimeaddressof_stext
*/
bcl 20,31,$+4/* Get our runtime address */ 0: mflr r21 /* Make it accessible */
addis r21,r21,(_stext - 0b)@ha
addi r21,r21,(_stext - 0b)@l /* Get our current runtime base */
/* Data TLB Error Interrupt */
START_EXCEPTION(DataTLBError44x)
mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */
mtspr SPRN_SPRG_WSCRATCH1, r11
mtspr SPRN_SPRG_WSCRATCH2, r12
mtspr SPRN_SPRG_WSCRATCH3, r13
mfcr r11
mtspr SPRN_SPRG_WSCRATCH4, r11
mfspr r10, SPRN_DEAR /* Get faulting address */
/* If we are faulting a kernel address, we have to use the *kernelpagetables.
*/
lis r11, PAGE_OFFSET@h
cmplw cr7, r10, r11
blt+ cr7, 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
mfspr r12,SPRN_MMUCR
rlwinm r12,r12,0,0,23/* Clear TID */
b 4f
/* Get the PGD for the current thread */ 3:
mfspr r11,SPRN_SPRG_THREAD
lwz r11,PGDIR(r11)
/* Load PID into MMUCR TID */
mfspr r12,SPRN_MMUCR
mfspr r13,SPRN_PID /* Get PID */
rlwimi r12,r13,0,24,31/* Set TID */
#ifdef CONFIG_PPC_KUAP
cmpwi r13,0
beq 2f /* KUAP Fault */
#endif
4:
mtspr SPRN_MMUCR,r12
/* Mask of required permission bits. Note that while we *docopyESR:STto_PAGE_WRITEpositionastryingtowrite *toanROpageisprettycommon,wedon'tdoitwith *_PAGE_DIRTY.Wecoulddoit,butit'safairlyrare *eventsoI'drathertaketheoverheadwhenithappens *ratherthanaddinganinstructionhere.Weshouldmeasure *whetherthewholethingisworthitinthefirstplace *aswecouldavoidloadingSPRN_ESRcompletelyinthefirst *place... * *TODO:Isitworthdoingthatmfspr&rlwimiinthefirst *placeorcanwesaveacoupleofinstructionshere?
*/
mfspr r12,SPRN_ESR
li r13,_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_READ
rlwimi r13,r12,10,30,30
/* Load the PTE */ /* Compute pgdir/pmd offset */
rlwinm r12, r10, PPC44x_PGD_OFF_SHIFT, PPC44x_PGD_OFF_MASK_BIT, 29
lwzx r11, r12, r11 /* Get pgd/pmd entry */
rlwinm. r12, r11, 0, 0, 20/* Extract pt base address */
beq 2f /* Bail if no table */
/* Compute pte address */
rlwimi r12, r10, PPC44x_PTE_ADD_SHIFT, PPC44x_PTE_ADD_MASK_BIT, 28
lwz r11, 0(r12) /* Get high word of pte entry */
lwz r12, 4(r12) /* Get low word of pte entry */
lis r10,tlb_44x_index@ha
andc. r13,r13,r12 /* Check permission */
/* Load the next available TLB index */
lwz r13,tlb_44x_index@l(r10)
bne 2f /* Bail if permission mismatch */
/* Increment, rollover, and store TLB index */
addi r13,r13,1
patch_site 0f, patch__tlb_44x_hwater_D /* Compare with watermark (instruction gets patched) */ 0: cmpwi 0,r13,1/* reserve entries */
ble 5f
li r13,0 5: /* Store the next available TLB index */
stw r13,tlb_44x_index@l(r10)
/* Re-load the faulting address */
mfspr r10,SPRN_DEAR
/* Jump to common tlb load */
b finish_tlb_load_44x
2: /* The bailout. Restore registers to pre-exception conditions *andcalltheheavyweightstohelpusout.
*/
mfspr r11, SPRN_SPRG_RSCRATCH4
mtcr r11
mfspr r13, SPRN_SPRG_RSCRATCH3
mfspr r12, SPRN_SPRG_RSCRATCH2
mfspr r11, SPRN_SPRG_RSCRATCH1
mfspr r10, SPRN_SPRG_RSCRATCH0
b DataStorage
/* If we are faulting a kernel address, we have to use the *kernelpagetables.
*/
lis r11, PAGE_OFFSET@h
cmplw cr7, r10, r11
blt+ cr7, 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
mfspr r12,SPRN_MMUCR
rlwinm r12,r12,0,0,23/* Clear TID */
b 4f
/* Get the PGD for the current thread */ 3:
mfspr r11,SPRN_SPRG_THREAD
lwz r11,PGDIR(r11)
/* Load PID into MMUCR TID */
mfspr r12,SPRN_MMUCR
mfspr r13,SPRN_PID /* Get PID */
rlwimi r12,r13,0,24,31/* Set TID */
#ifdef CONFIG_PPC_KUAP
cmpwi r13,0
beq 2f /* KUAP Fault */
#endif
4:
mtspr SPRN_MMUCR,r12
/* Make up the required permissions */
li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
/* Compute pgdir/pmd offset */
rlwinm r12, r10, PPC44x_PGD_OFF_SHIFT, PPC44x_PGD_OFF_MASK_BIT, 29
lwzx r11, r12, r11 /* Get pgd/pmd entry */
rlwinm. r12, r11, 0, 0, 20/* Extract pt base address */
beq 2f /* Bail if no table */
/* Compute pte address */
rlwimi r12, r10, PPC44x_PTE_ADD_SHIFT, PPC44x_PTE_ADD_MASK_BIT, 28
lwz r11, 0(r12) /* Get high word of pte entry */
lwz r12, 4(r12) /* Get low word of pte entry */
lis r10,tlb_44x_index@ha
andc. r13,r13,r12 /* Check permission */
/* Load the next available TLB index */
lwz r13,tlb_44x_index@l(r10)
bne 2f /* Bail if permission mismatch */
/* Increment, rollover, and store TLB index */
addi r13,r13,1
patch_site 0f, patch__tlb_44x_hwater_I /* Compare with watermark (instruction gets patched) */ 0: cmpwi 0,r13,1/* reserve entries */
ble 5f
li r13,0 5: /* Store the next available TLB index */
stw r13,tlb_44x_index@l(r10)
/* Re-load the faulting address */
mfspr r10,SPRN_SRR0
/* Jump to common TLB load point */
b finish_tlb_load_44x
2: /* The bailout. Restore registers to pre-exception conditions *andcalltheheavyweightstohelpusout.
*/
mfspr r11, SPRN_SPRG_RSCRATCH4
mtcr r11
mfspr r13, SPRN_SPRG_RSCRATCH3
mfspr r12, SPRN_SPRG_RSCRATCH2
mfspr r11, SPRN_SPRG_RSCRATCH1
mfspr r10, SPRN_SPRG_RSCRATCH0
b InstructionStorage
/* And WS 2 */
li r10,0xf84 /* Mask to apply from PTE */
rlwimi r10,r12,29,30,31/* DIRTY,READ -> SW,SR position */
and r11,r12,r10 /* Mask PTE bits to keep */
bge cr7,1f /* User page ? no, leave U bits empty */
rlwimi r11,r11,3,26,28/* yes, copy S bits to U */
rlwinm r11,r11,0,~PPC44x_TLB_SX /* Clear SX if User page */ 1: tlbwe r11,r13,PPC44x_TLB_ATTRIB /* Write ATTRIB */
/* Done...restore registers and get out of here.
*/
mfspr r11, SPRN_SPRG_RSCRATCH4
mtcr r11
mfspr r13, SPRN_SPRG_RSCRATCH3
mfspr r12, SPRN_SPRG_RSCRATCH2
mfspr r11, SPRN_SPRG_RSCRATCH1
mfspr r10, SPRN_SPRG_RSCRATCH0
rfi /* Force context change */
/* TLB error interrupts for 476
*/
#ifdef CONFIG_PPC_47x
START_EXCEPTION(DataTLBError47x)
mtspr SPRN_SPRG_WSCRATCH0,r10 /* Save some working registers */
mtspr SPRN_SPRG_WSCRATCH1,r11
mtspr SPRN_SPRG_WSCRATCH2,r12
mtspr SPRN_SPRG_WSCRATCH3,r13
mfcr r11
mtspr SPRN_SPRG_WSCRATCH4,r11
mfspr r10,SPRN_DEAR /* Get faulting address */
/* If we are faulting a kernel address, we have to use the *kernelpagetables.
*/
lis r11,PAGE_OFFSET@h
cmplw cr7,r10,r11
blt+ cr7,3f
lis r11,swapper_pg_dir@h
ori r11,r11, swapper_pg_dir@l
li r12,0/* MMUCR = 0 */
b 4f
/* Get the PGD for the current thread and setup MMUCR */ 3: mfspr r11,SPRN_SPRG3
lwz r11,PGDIR(r11)
mfspr r12,SPRN_PID /* Get PID */
#ifdef CONFIG_PPC_KUAP
cmpwi r12,0
beq 2f /* KUAP Fault */
#endif 4: mtspr SPRN_MMUCR,r12 /* Set MMUCR */
/* Mask of required permission bits. Note that while we *docopyESR:STto_PAGE_WRITEpositionastryingtowrite *toanROpageisprettycommon,wedon'tdoitwith *_PAGE_DIRTY.Wecoulddoit,butit'safairlyrare *eventsoI'drathertaketheoverheadwhenithappens *ratherthanaddinganinstructionhere.Weshouldmeasure *whetherthewholethingisworthitinthefirstplace *aswecouldavoidloadingSPRN_ESRcompletelyinthefirst *place... * *TODO:Isitworthdoingthatmfspr&rlwimiinthefirst *placeorcanwesaveacoupleofinstructionshere?
*/
mfspr r12,SPRN_ESR
li r13,_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_READ
rlwimi r13,r12,10,30,30
/* Load the PTE */ /* Compute pgdir/pmd offset */
rlwinm r12,r10,PPC44x_PGD_OFF_SHIFT,PPC44x_PGD_OFF_MASK_BIT,29
lwzx r11,r12,r11 /* Get pgd/pmd entry */
/* Word 0 is EPN,V,TS,DSIZ */
li r12,PPC47x_TLB0_VALID | PPC47x_TLBE_SIZE
rlwimi r10,r12,0,32-PAGE_SHIFT,31/* Insert valid and page size*/
li r12,0
tlbwe r10,r12,0
/* XXX can we do better ? Need to make sure tlbwe has established
* latch V bit in MMUCR0 before the PTE is loaded further down */
#ifdef CONFIG_SMP
isync
#endif
rlwinm. r12,r11,0,0,20/* Extract pt base address */ /* Compute pte address */
rlwimi r12,r10,PPC44x_PTE_ADD_SHIFT,PPC44x_PTE_ADD_MASK_BIT,28
beq 2f /* Bail if no table */
lwz r11,0(r12) /* Get high word of pte entry */
/* XXX can we do better ? maybe insert a known 0 bit from r11 into the *bottomofr12tocreateadatadependency...Wecanalsouser10 *asdestinationnowadays
*/
#ifdef CONFIG_SMP
lwsync
#endif
lwz r12,4(r12) /* Get low word of pte entry */
andc. r13,r13,r12 /* Check permission */
/* Jump to common tlb load */
beq finish_tlb_load_47x
2: /* The bailout. Restore registers to pre-exception conditions *andcalltheheavyweightstohelpusout.
*/
mfspr r11,SPRN_SPRG_RSCRATCH4
mtcr r11
mfspr r13,SPRN_SPRG_RSCRATCH3
mfspr r12,SPRN_SPRG_RSCRATCH2
mfspr r11,SPRN_SPRG_RSCRATCH1
mfspr r10,SPRN_SPRG_RSCRATCH0
b DataStorage
/* Instruction TLB Error Interrupt */ /* *Nearlythesameasabove,exceptwegetour *informationfromdifferentregistersandbailout *toadifferentpoint.
*/
START_EXCEPTION(InstructionTLBError47x)
mtspr SPRN_SPRG_WSCRATCH0,r10 /* Save some working registers */
mtspr SPRN_SPRG_WSCRATCH1,r11
mtspr SPRN_SPRG_WSCRATCH2,r12
mtspr SPRN_SPRG_WSCRATCH3,r13
mfcr r11
mtspr SPRN_SPRG_WSCRATCH4,r11
mfspr r10,SPRN_SRR0 /* Get faulting address */
/* If we are faulting a kernel address, we have to use the *kernelpagetables.
*/
lis r11,PAGE_OFFSET@h
cmplw cr7,r10,r11
blt+ cr7,3f
lis r11,swapper_pg_dir@h
ori r11,r11, swapper_pg_dir@l
li r12,0/* MMUCR = 0 */
b 4f
/* Get the PGD for the current thread and setup MMUCR */ 3: mfspr r11,SPRN_SPRG_THREAD
lwz r11,PGDIR(r11)
mfspr r12,SPRN_PID /* Get PID */
#ifdef CONFIG_PPC_KUAP
cmpwi r12,0
beq 2f /* KUAP Fault */
#endif 4: mtspr SPRN_MMUCR,r12 /* Set MMUCR */
/* Make up the required permissions */
li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
/* Word 0 is EPN,V,TS,DSIZ */
li r12,PPC47x_TLB0_VALID | PPC47x_TLBE_SIZE
rlwimi r10,r12,0,32-PAGE_SHIFT,31/* Insert valid and page size*/
li r12,0
tlbwe r10,r12,0
/* XXX can we do better ? Need to make sure tlbwe has established
* latch V bit in MMUCR0 before the PTE is loaded further down */
#ifdef CONFIG_SMP
isync
#endif
rlwinm. r12,r11,0,0,20/* Extract pt base address */ /* Compute pte address */
rlwimi r12,r10,PPC44x_PTE_ADD_SHIFT,PPC44x_PTE_ADD_MASK_BIT,28
beq 2f /* Bail if no table */
lwz r11,0(r12) /* Get high word of pte entry */ /* XXX can we do better ? maybe insert a known 0 bit from r11 into the *bottomofr12tocreateadatadependency...Wecanalsouser10 *asdestinationnowadays
*/
#ifdef CONFIG_SMP
lwsync
#endif
lwz r12,4(r12) /* Get low word of pte entry */
andc. r13,r13,r12 /* Check permission */
/* Jump to common TLB load point */
beq finish_tlb_load_47x
2: /* The bailout. Restore registers to pre-exception conditions *andcalltheheavyweightstohelpusout.
*/
mfspr r11, SPRN_SPRG_RSCRATCH4
mtcr r11
mfspr r13, SPRN_SPRG_RSCRATCH3
mfspr r12, SPRN_SPRG_RSCRATCH2
mfspr r11, SPRN_SPRG_RSCRATCH1
mfspr r10, SPRN_SPRG_RSCRATCH0
b InstructionStorage
/* And make up word 2 */
li r10,0xf84 /* Mask to apply from PTE */
rlwimi r10,r12,29,30,31/* DIRTY,READ -> SW,SR position */
and r11,r12,r10 /* Mask PTE bits to keep */
bge cr7,1f /* User page ? no, leave U bits empty */
rlwimi r11,r11,3,26,28/* yes, copy S bits to U */
rlwinm r11,r11,0,~PPC47x_TLB2_SX /* Clear SX if User page */ 1: tlbwe r11,r13,2
/* Done...restore registers and get out of here.
*/
mfspr r11, SPRN_SPRG_RSCRATCH4
mtcr r11
mfspr r13, SPRN_SPRG_RSCRATCH3
mfspr r12, SPRN_SPRG_RSCRATCH2
mfspr r11, SPRN_SPRG_RSCRATCH1
mfspr r10, SPRN_SPRG_RSCRATCH0
rfi
/* *SearchTLBforentrythatwearecurrentlyusing. *Invalidateallentriesbuttheoneweareusing.
*/ /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */
mfspr r3,SPRN_PID /* Get PID */
mfmsr r4 /* Get MSR */
andi. r4,r4,MSR_IS@l /* TS=1? */
beq wmmucr /* If not, leave STS=0 */
oris r3,r3,PPC44x_MMUCR_STS@h /* Set STS=1 */
wmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */
sync
bcl 20,31,$+4/* Find our address */
invstr: mflr r5 /* Make it accessible */
tlbsx r23,0,r5 /* Find entry we are in */
li r4,0/* Start at TLB entry 0 */
li r3,0/* Set PAGEID inval value */ 1: cmpw r23,r4 /* Is this our entry? */
beq skpinv /* If so, skip the inval */
tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */
skpinv: addi r4,r4,1/* Increment */
cmpwi r4,64/* Are we done? */
bne 1b /* If not, repeat */
isync /* If so, context change */
/* Read the XLAT entry for our current mapping */
tlbre r25,r23,PPC44x_TLB_XLAT
lis r3,KERNELBASE@h
ori r3,r3,KERNELBASE@l
/* Use our current RPN entry */
mr r4,r25
#else
lis r3,PAGE_OFFSET@h
ori r3,r3,PAGE_OFFSET@l
/* Kernel is at the base of RAM */
li r4, 0/* Load the kernel physical address */
#endif
/* Load the kernel PID = 0 */
li r0,0
mtspr SPRN_PID,r0
sync
/* Initialize MMUCR */
li r5,0
mtspr SPRN_MMUCR,r5
sync
/* pageid fields */
clrrwi r3,r3,10/* Mask off the effective page number */
ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
/* xlat fields */
clrrwi r4,r4,10/* Mask off the real page number */ /* ERPN is 0 for first 4GB page */
/* attrib fields */ /* Added guarded bit to protect against speculative loads/stores */
li r5,0
ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
li r0,63/* TLB slot 63 */
tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */
tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
/* Force context change */
mfmsr r0
mtspr SPRN_SRR1, r0
lis r0,3f@h
ori r0,r0,3f@l
mtspr SPRN_SRR0,r0
sync
rfi
/* If necessary, invalidate original entry we used */ 3: cmpwi r23,63
beq 4f
li r6,0
tlbwe r6,r23,PPC44x_TLB_PAGEID
isync
4:
#ifdef CONFIG_PPC_EARLY_DEBUG_44x /* Add UART mapping for early debug. */
/* pageid fields */
lis r3,PPC44x_EARLY_DEBUG_VIRTADDR@h
ori r3,r3,PPC44x_TLB_VALID|PPC44x_TLB_TS|PPC44x_TLB_64K
/* xlat fields */
lis r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW@h
ori r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH
/* attrib fields */
li r5,(PPC44x_TLB_SW|PPC44x_TLB_SR|PPC44x_TLB_I|PPC44x_TLB_G)
li r0,62/* TLB slot 0 */
/* Entry point for secondary 47x processors */
_GLOBAL(start_secondary_47x)
mr r24,r3 /* CPU number */
bl init_cpu_state
/* Now we need to bolt the rest of kernel memory which *isdoneinCcode.Wemustbecarefulbecauseourtask *structorourstackcan(andwillprobably)beout *ofreachoftheinitial256MTLBentry,soweusea *smalltemporarystackin.bssforthat.Thisworks *becauseonlyoneCPUatatimecanbeinthiscode
*/
lis r1,temp_boot_stack@h
ori r1,r1,temp_boot_stack@l
addi r1,r1,1024-STACK_FRAME_MIN_SIZE
li r0,0
stw r0,0(r1)
bl mmu_init_secondary
/* Now we can get our task struct and real stack pointer */
/* Get current's stack and current */
lis r2,secondary_current@ha
lwz r2,secondary_current@l(r2)
lwz r1,TASK_STACK(r2)
/* Current stack pointer */
addi r1,r1,THREAD_SIZE-STACK_FRAME_MIN_SIZE
li r0,0
stw r0,0(r1)
/* Kernel stack for exception entry in SPRG3 */
addi r4,r2,THREAD /* init task's THREAD */
mtspr SPRN_SPRG3,r4
/* Force context change */
mfmsr r0
mtspr SPRN_SRR1, r0
lis r0,3f@h
ori r0,r0,3f@l
mtspr SPRN_SRR0,r0
sync
rfi
/* Invalidate original entry we used */ 3:
rlwinm r24,r24,0,21,19/* clear the "valid" bit */
tlbwe r24,r23,0
addi r24,0,0
tlbwe r24,r23,1
tlbwe r24,r23,2
isync /* Clear out the shadow TLB entries */
#ifdef CONFIG_PPC_EARLY_DEBUG_44x /* Add UART mapping for early debug. */
/* Word 0 */
lis r3,PPC44x_EARLY_DEBUG_VIRTADDR@h
ori r3,r3,PPC47x_TLB0_VALID | PPC47x_TLB0_TS | PPC47x_TLB0_1M
/* Word 1 */
lis r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW@h
ori r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH
/* Word 2 */
li r5,(PPC47x_TLB2_S_RW | PPC47x_TLB2_IMG)
/* Bolted in way 0, bolt slot 5, we -hope- we don't hit the same *congruenceclassasthekernel,weneedtomakesureofitat *somepoint
*/
lis r0,0x8d00
tlbwe r3,r0,0
tlbwe r4,r0,1
tlbwe r5,r0,2
/* Force context change */
isync
#endif /* CONFIG_PPC_EARLY_DEBUG_44x */
/* We configure icbi to invalidate 128 bytes at a time since the *current32-bitkernelcodeisn'ttoohappywithicache!= dcache *blocksize.WealsodisabletheBTACasthiscancauseerrors *insomecircumstances(seeIBMErratum47).
*/
mfspr r3,SPRN_CCR0
oris r3,r3,0x0020
ori r3,r3,0x0040
mtspr SPRN_CCR0,r3
isync
#endif /* CONFIG_PPC_47x */
/* *Herewearebacktocodethatiscommonbetween44xand47x * *Weproceedtofurtherkernelinitializationandreturntothe *mainkernelentry
*/
head_start_common: /* Establish the interrupt vector base */
lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
mtspr SPRN_IVPR,r4
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.