head_4xx.s
来自「linux-2.4.29操作系统的源码」· S 代码 · 共 1,123 行 · 第 1/3 页
S
1,123 行
/* Other PowerPC processors, namely those derived from the 6xx-series * have vectors from 0x2100 through 0x2F00 defined, but marked as reserved. * However, for the 4xx-series processors these are neither defined nor * reserved. */ /* Damn, I came up one instruction too many to fit into the * exception space :-). Both the instruction and data TLB * miss get to this point to load the TLB. * r20 - EA of fault * r21 - TLB LO (info from Linux PTE) * r22, r23 - avilable to use * PID - loaded with proper value when we get here * Upon exit, we reload everything and RFI. * Actually, it will fit now, but oh well.....a common place * to load the TLB. */tlb_4xx_index: .long 0finish_tlb_load: /* load the next available TLB index. */ lwz r23, tlb_4xx_index@l(0) addi r23, r23, 1#ifdef CONFIG_PIN_TLB cmpwi 0, r23, 61 /* reserve entries 62, 63 for kernel */ ble 7f li r23, 07:#else andi. r23, r23, (PPC4XX_TLB_SIZE-1)#endif stw r23, tlb_4xx_index@l(0)6: ori r21, r21, _PAGE_HWEXEC /* make it executable */ tlbwe r21, r23, TLB_DATA /* Load TLB LO */ /* Create EPN. This is the faulting address plus a static * set of bits. These are size, valid, E, U0, and ensure * bits 20 and 21 are zero. */ li r22, 0x00c0 rlwimi r20, r22, 0, 20, 31 tlbwe r20, r23, TLB_TAG /* Load TLB HI */ /* Done...restore registers and get out of here. */#ifdef CONFIG_403GCX lwz r22, 12(r0) lwz r21, 8(r0) mtspr SPRN_PID, r22 mtcr r21 lwz r23, 4(r0) lwz r22, 0(r0)#else mfspr r22, SPRG6 mfspr r21, SPRG7 mtspr SPRN_PID, r22 mtcr r21 mfspr r23, SPRG5 mfspr r22, SPRG4#endif mfspr r21, SPRG1 mfspr r20, SPRG0 PPC405_ERR77_SYNC rfi /* Should sync shadow TLBs */ b . /* prevent prefetch past rfi *//* This code finishes saving the registers to the exception frame * and jumps to the appropriate handler for the exception, turning * on address translation. */_GLOBAL(transfer_to_handler) stw r22,_NIP(r21) /* Save the faulting IP on the stack */ stw r23,_MSR(r21) /* Save the exception MSR on stack */ SAVE_4GPRS(8, r21) /* Save r8 through r11 on the stack */ SAVE_8GPRS(12, r21) /* Save r12 through r19 on the stack */ SAVE_8GPRS(24, r21) /* Save r24 through r31 on the stack */ andi. r23,r23,MSR_PR /* Is this from user space? */ mfspr r23,SPRN_SPRG3 /* If from user, fix up THREAD.regs */ beq 2f /* No, it is from the kernel; branch. */ mfspr r24,SPRN_DBCR0 stw r24,THREAD_DBCR0(r23) /* Save Debug Control in thread_struct */ addi r24,r1,STACK_FRAME_OVERHEAD stw r24,PT_REGS(r23)2: addi r2,r23,-THREAD /* Set r2 to current thread */ tovirt(r2,r2) mflr r23 andi. r24,r23,0x3f00 /* Get vector offset */ stw r24,TRAP(r21) li r22,RESULT /* No need to put an erratum #77 workaround here because interrupts are currently disabled */ stwcx. r22,r22,r21 /* Clear the reservation */ li r22,0 stw r22,RESULT(r21) mtspr SPRN_SPRG2,r22 /* r1 is now the kernel stack pointer */ addi r24,r2,TASK_STRUCT_SIZE /* Check for kernel stack overflow */ cmplw cr0,r1,r2 cmplw cr1,r1,r24 crand cr1,cr1,cr4 bgt- stack_ovf /* If r2 < r1 < r2 + TASK_STRUCT_SIZE */ lwz r24,0(r23) /* Virtual address of the handler */ lwz r23,4(r23) /* Handler return pointer */ cmpwi cr0,r7,STND_EXC /* What type of exception is this? */ bne 3f /* It is a critical exception... */ /* Standard exception jump path */ /* We have to recover r7 from the register save stack. * It was used to indicate standard/critical exception. In * the case of a standard exception that is the system call * trap, it may have originally contained one of the syscall * parameters and we have to get it back now. */ lwz r7,GPR7(r21) mtspr SPRN_SRR0,r24 /* Set up the instruction pointer */ mtspr SPRN_SRR1,r20 /* Set up the machine state register */ mtlr r23 /* Set up the return pointer */ SYNC /* We shouldn't need a 405 erratum #77 workaround here, because we're not * actually returning to the interrupted instruction yet. */ rfi b . /* prevent prefetch past rfi */ /* Critical exception jump path */3: mtspr SPRN_SRR2,r24 /* Set up the instruction pointer */ mtspr SPRN_SRR3,r20 /* Set up the machine state register */ mtlr r23 /* Set up the return pointer */ SYNC rfci b . /* prevent prefetch past rfci *//* On kernel stack overlow, load up an initial stack pointer and call * StackOverflow(regs), which should NOT return. */stack_ovf: addi r3,r1,STACK_FRAME_OVERHEAD lis r1,init_task_union@ha addi r1,r1,init_task_union@l addi r1,r1,TASK_UNION_SIZE - STACK_FRAME_OVERHEAD lis r24,StackOverflow@ha addi r24,r24,StackOverflow@l li r20,MSR_KERNEL mtspr SPRN_SRR0,r24 mtspr SPRN_SRR1,r20 SYNC rfi b . /* prevent prefetch past rfi *//* extern void giveup_altivec(struct task_struct *prev) * * The PowerPC 4xx family of processors do not have AltiVec capabilities, so * this just returns. */_GLOBAL(giveup_altivec) blr/* extern void giveup_fpu(struct task_struct *prev) * * The PowerPC 4xx family of processors do not have an FPU, so this just * returns. */_GLOBAL(giveup_fpu) blr/* extern void abort(void) * * At present, this routine just applies a system reset. */_GLOBAL(abort) mfspr r13,SPRN_DBCR0 oris r13,r13,DBCR_RST(DBCR_RST_SYSTEM)@h mtspr SPRN_DBCR0,r13/* This is where the main kernel code starts. */start_here: /* ptr to current */ lis r2,init_task_union@h ori r2,r2,init_task_union@l /* ptr to phys current thread */ tophys(r4,r2) addi r4,r4,THREAD /* init task's THREAD */ mtspr SPRG3,r4 li r3,0 mtspr SPRG2,r3 /* 0 => r1 has kernel sp */ /* stack */ addi r1,r2,TASK_UNION_SIZE li r0,0 stwu r0,-STACK_FRAME_OVERHEAD(r1) bl early_init /* We have to do this with MMU on *//* * Decide what sort of machine this is and initialize the MMU. */ mr r3,r31 mr r4,r30 mr r5,r29 mr r6,r28 mr r7,r27 bl machine_init bl MMU_init/* Go back to running unmapped so we can load up new values * and change to using our exception vectors. * On the 4xx, all we have to do is invalidate the TLB to clear * the old 16M byte TLB mappings. */ lis r4,2f@h ori r4,r4,2f@l tophys(r4,r4) li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR) mtspr SRR0,r4 mtspr SRR1,r3 rfi b . /* prevent prefetch past rfi *//* Load up the kernel context */2: SYNC /* Force all PTE updates to finish */#ifndef CONFIG_PIN_TLB tlbia /* Clear all TLB entries */ sync /* wait for tlbia/tlbie to finish */#endif /* set up the PTE pointers for the Abatron bdiGDB. */ lis r6, swapper_pg_dir@h ori r6, r6, swapper_pg_dir@l lis r5, abatron_pteptrs@h ori r5, r5, abatron_pteptrs@l stw r5, 0xf0(r0) /* Must match your Abatron config file */ tophys(r5,r5) stw r6, 0(r5)/* Now turn on the MMU for real! */ li r4,MSR_KERNEL lis r3,start_kernel@h ori r3,r3,start_kernel@l mtspr SRR0,r3 mtspr SRR1,r4 rfi /* enable MMU and jump to start_kernel */ b . /* prevent prefetch past rfi *//* Set up the initial MMU state so we can do the first level of * kernel initialization. This maps the first 16 MBytes of memory 1:1 * virtual to physical and more importantly sets the cache mode. */initial_mmu: tlbia /* Invalidate all TLB entries */ sync /* We should still be executing code at physical address 0x0000xxxx * at this point. However, start_here is at virtual address * 0xC000xxxx. So, set up a TLB mapping to cover this once * translation is enabled. */ lis r3,KERNELBASE@h /* Load the kernel virtual address */ ori r3,r3,KERNELBASE@l tophys(r4,r3) /* Load the kernel physical address */ iccci r0,r3 /* Invalidate the i-cache before use */ /* Load the kernel PID. */ li r0,0 mtspr SPRN_PID,r0 sync /* Configure and load two entries into TLB slots 62 and 63. * In case we are pinning TLBs, these are reserved in by the * other TLB functions. If not reserving, then it doesn't * matter where they are loaded. */ clrrwi r4,r4,10 /* Mask off the real page number */ ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */ clrrwi r3,r3,10 /* Mask off the effective page number */ ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M)) li r0,62 /* TLB slot 62 */ tlbwe r4,r0,TLB_DATA /* Load the data portion of the entry */ tlbwe r3,r0,TLB_TAG /* Load the tag portion of the entry */ addis r4, r4, 0x0100 /* Map next 16 M entries */ addis r3, r3, 0x0100 li r0,63 /* TLB slot 63 */ tlbwe r4,r0,TLB_DATA tlbwe r3,r0,TLB_TAG#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(SERIAL_DEBUG_IO_BASE) /* Load a TLB entry for the UART, so that ppc4xx_progress() can use * the UARTs nice and early. We use a 4k real==virtual mapping. */ lis r3,SERIAL_DEBUG_IO_BASE@h ori r3,r3,SERIAL_DEBUG_IO_BASE@l mr r4,r3 clrrwi r4,r4,12 ori r4,r4,(TLB_WR|TLB_I|TLB_M|TLB_G) clrrwi r3,r3,12 ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_4K)) li r0,0 /* TLB slot 0 */ tlbwe r4,r0,TLB_DATA tlbwe r3,r0,TLB_TAG#endif /* CONFIG_SERIAL_DEBUG_TEXT && SERIAL_DEBUG_IO_BASE */ isync /* Establish the exception vector base */ lis r4,KERNELBASE@h /* EVPR only uses the high 16-bits */ tophys(r0,r4) /* Use the physical address */ mtspr SPRN_EVPR,r0 blr_GLOBAL(set_context)#ifdef CONFIG_BDI_SWITCH /* Context switch the PTE pointer for the Abatron BDI2000. * The PGDIR is the second parameter. */ lis r5, KERNELBASE@h lwz r5, 0xf0(r5) stw r4, 0x4(r5)#endif sync mtspr SPRN_PID,r3 isync /* Need an isync to flush shadow */ /* TLBs after changing PID */ blr/* We put a few things here that have to be page-aligned. This stuff * goes at the beginning of the data segment, which is page-aligned. */ .data_GLOBAL(sdata)_GLOBAL(empty_zero_page) .space 4096_GLOBAL(swapper_pg_dir) .space 4096/* This space gets a copy of optional info passed to us by the bootstrap * which is used to pass parameters into the kernel like root=/dev/sda1, etc. */_GLOBAL(cmd_line) .space 512/* Room for two PTE pointers, usually the kernel and current user pointers * to their respective root page table. */abatron_pteptrs: .space 8
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?