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 + -
显示快捷键?