⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 head_4xx.s

📁 是关于linux2.5.1的完全源码
💻 S
📖 第 1 页 / 共 2 页
字号:
/* *    Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> *      Initial PowerPC version. *    Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu> *      Rewritten for PReP *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au> *      Low-level exception handers, MMU support, and rewrite. *    Copyright (c) 1997 Dan Malek <dmalek@jlc.net> *      PowerPC 8xx modifications. *    Copyright (c) 1998-1999 TiVo, Inc. *      PowerPC 403GCX modifications. *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> *      PowerPC 403GCX/405GP modifications. *    Copyright 2000 MontaVista Software Inc. *	PPC405 modifications *      PowerPC 403GCX/405GP modifications. * 	Author: MontaVista Software, Inc. *         	frank_rowand@mvista.com or source@mvista.com * 	   	debbie_chu@mvista.com * * *    Module name: head_4xx.S * *    Description: *      Kernel execution entry point code. * *    This program is free software; you can redistribute it and/or *    modify it under the terms of the GNU General Public License *    as published by the Free Software Foundation; either version *    2 of the License, or (at your option) any later version. * */#include <linux/config.h>#include <asm/processor.h>#include <asm/page.h>#include <asm/mmu.h>#include <asm/pgtable.h>#include <asm/ibm4xx.h>#include <asm/cputable.h>#include <asm/thread_info.h>#include <asm/ppc_asm.h>#include "ppc_defs.h"/* Preprocessor Defines */#define	STND_EXC	0#define	CRIT_EXC	1/* As with the other PowerPC ports, it is expected that when code * execution begins here, the following registers contain valid, yet * optional, information: * *   r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.) *   r4 - Starting address of the init RAM disk *   r5 - Ending address of the init RAM disk *   r6 - Start of kernel command line string (e.g. "mem=96m") *   r7 - End of kernel command line string * * This is all going to change RSN when we add bi_recs.......  -- Dan */ 	.text_GLOBAL(_stext)_GLOBAL(_start)	/* Save parameters we are passed.	*/	mr	r31,r3	mr	r30,r4	mr	r29,r5	mr	r28,r6	mr	r27,r7	li	r24,0		/* CPU number */	/* We have to turn on the MMU right away so we get cache modes	 * set correctly.	 */	bl	initial_mmu/* We now have the lower 16 Meg mapped into TLB entries, and the caches * ready to work. */turn_on_mmu:	li	r0,MSR_KERNEL	mtspr	SRR1,r0	lis	r0,start_here@h	ori	r0,r0,start_here@l	mtspr	SRR0,r0	SYNC	rfi				/* enables MMU *//* Exception vector entry code. This code runs with address translation * turned off (i.e. using physical addresses). We assume SPRG3 has the * physical address of the current task thread_struct. */ #define COMMON_PROLOG(n)                                                     \0:	mtspr	SPRN_SPRG0,r20;         /* We need r20, move it to SPRG0   */\	mtspr	SPRN_SPRG1,r21;         /* We need r21, move it to SPRG1   */\	mfcr	r20;                    /* We need the CR, move it to r20  */\	mfspr	r21,SPRN_SPRG2;         /* Exception stack to use          */\	cmpwi	cr0,r21,0;              /* From user mode or RTAS?         */\	bne	1f;                     /* Not RTAS, branch                */\	tophys(r21, r1);                /* Convert vka in r1 to pka in r21 */\	subi	r21,r21,INT_FRAME_SIZE; /* Allocate an exception frame     */\1:	stw	r20,_CCR(r21);          /* Save CR on the stack            */\	stw	r22,GPR22(r21);         /* Save r22 on the stack           */\	stw	r23,GPR23(r21);         /* r23 Save on the stack           */\	mfspr	r20,SPRN_SPRG0;         /* Get r20 back out of SPRG0       */\	stw	r20,GPR20(r21);         /* Save r20 on the stack           */\	mfspr	r22,SPRN_SPRG1;         /* Get r21 back out of SPRG0       */\	stw	r22,GPR21(r21);         /* Save r21 on the stack           */\	mflr	r20;                                                         \	stw	r20,_LINK(r21);         /* Save LR on the stack            */\	mfctr	r22;                                                         \	stw	r22,_CTR(r21);          /* Save CTR on the stack           */\	mfspr	r20,XER;                                                     \	stw	r20,_XER(r21);          /* Save XER on the stack           */\	mfspr	r20,SPRN_DBCR0;                                              \	stw	r20,_DBCR0(r21);        /* Save Debug Control on the stack */#define	COMMON_EPILOG							     \	stw	r0,GPR0(r21);		/* Save r0 on the stack		   */\	stw	r1,GPR1(r21);		/* Save r1 on the stack		   */\	stw	r2,GPR2(r21);		/* Save r2 on the stack		   */\	stw	r1,0(r21);						     \	tovirt(r1,r21);			/* Set-up new kernel stack pointer */\	SAVE_4GPRS(3, r21);		/* Save r3 through r6 on the stack */\	SAVE_GPR(7, r21);		/* Save r7 on the stack		   */#define	STND_EXCEPTION_PROLOG(n)					     \	COMMON_PROLOG(n);						     \	mfspr	r22,SPRN_SRR0;		/* Faulting instruction address	   */\	lis	r20,MSR_WE@h;						     \	mfspr	r23,SPRN_SRR1;		/* MSR at the time of fault	   */\	andc	r23,r23,r20;		/* disable processor wait state    */\	COMMON_EPILOG;#define	CRIT_EXCEPTION_PROLOG(n)					     \	COMMON_PROLOG(n);						     \	mfspr	r22,SPRN_SRR2;		/* Faulting instruction address	   */\	lis	r20,MSR_WE@h;						     \	mfspr	r23,SPRN_SRR3;		/* MSR at the time of fault	   */\	andc	r23,r23,r20;		/* disable processor wait state    */\	COMMON_EPILOG;#define	START_EXCEPTION(n, label)					     \	. = n;								     \label:#define FINISH_EXCEPTION(func)						     \	bl	transfer_to_handler;					     \	.long	func;							     \	.long	ret_from_except#define STND_EXCEPTION(n, label, func)					     \	START_EXCEPTION(n, label);					     \	STND_EXCEPTION_PROLOG(n);					     \	addi	r3,r1,STACK_FRAME_OVERHEAD;				     \	li	r7,STND_EXC;						     \	li	r20,MSR_KERNEL;						     \	FINISH_EXCEPTION(func)#define	CRIT_EXCEPTION(n, label, func)					     \	START_EXCEPTION(n, label);					     \	CRIT_EXCEPTION_PROLOG(n);					     \	addi	r3,r1,STACK_FRAME_OVERHEAD;				     \	li	r7,CRIT_EXC;						     \	li	r20,MSR_KERNEL;						     \	FINISH_EXCEPTION(func)/* Exception vectors.*/ /* 0x0100 - Critical Interrupt Exception*/	CRIT_EXCEPTION(0x0100,	CriticalInterrupt,	UnknownException)/* 0x0200 - Machine Check Exception*/#if 0	CRIT_EXCEPTION(0x0200,	MachineCheck,		MachineCheckException)#else	START_EXCEPTION(0x0200, MachineCheck)	CRIT_EXCEPTION_PROLOG(0x0200)	/*	lis	r4,0x0400	mtdcr	DCRN_POB0_BESR0,r4	*/#ifdef DCRN_POB0_BEAR	mfdcr	r4,DCRN_POB0_BEAR	mfdcr	r4,DCRN_POB0_BESR0	mfdcr	r4,DCRN_POB0_BESR1#endif#ifdef DCRN_PLB0_BEAR	mfdcr	r4,DCRN_PLB0_ACR	mfdcr	r4,DCRN_PLB0_BEAR	mfdcr	r4,DCRN_PLB0_BESR#endif	addi	r3,r1,STACK_FRAME_OVERHEAD	li	r7,CRIT_EXC	li	r20,MSR_KERNEL	FINISH_EXCEPTION(MachineCheckException)#endif/* 0x0300 - Data Storage Exception * This happens for just a few reasons.  U0 set (but we don't do that), * or zone protection fault (user violation, write to protected page). * If this is just an update of modified status, we do that quickly * and exit.  Otherwise, we call heavywight functions to do the work. */	START_EXCEPTION(0x0300,	DataStore)	mtspr	SPRG0, r20		/* Save some working registers */	mtspr	SPRG1, r21#ifdef CONFIG_403GCX	stw     r22, 0(r0)	stw     r23, 4(r0)	mfcr    r21	mfspr   r22, SPRN_PID	stw     r21, 8(r0)	stw     r22, 12(r0)#else	mtspr	SPRG4, r22	mtspr	SPRG5, r23	mfcr	r21	mfspr	r22, SPRN_PID	mtspr	SPRG7, r21	mtspr	SPRG6, r22#endif	/* First, check if it was a zone fault (which means a user	* tried to access a kernel or read-protected page - always	* a SEGV).  All other faults here must be stores, so no	* need to check ESR_DST as well. */	mfspr	r20, SPRN_ESR	andis.	r20, r20, ESR_DIZ@h	bne	2f	mfspr	r20, SPRN_DEAR		/* Get faulting address */	/* If we are faulting a kernel address, we have to use the	 * kernel page tables.	 */	andis.	r21, r20, 0x8000	beq	3f	lis	r21, swapper_pg_dir@h	ori	r21, r21, swapper_pg_dir@l	li	r23, 0	mtspr	SPRN_PID, r23		/* TLB will have 0 TID */	b	4f	/* Get the PGD for the current thread.	 */3:	mfspr	r21,SPRG3	lwz	r21,PGDIR(r21)4:	tophys(r21, r21)	rlwimi	r21, r20, 12, 20, 29	/* Create L1 (pgdir/pmd) address */	lwz	r21, 0(r21)		/* Get L1 entry */	rlwinm.	r22, r21, 0, 0, 19	/* Extract L2 (pte) base address */	beq	2f			/* Bail if no table */	tophys(r22, r22)	rlwimi	r22, r20, 22, 20, 29	/* Compute PTE address */	lwz	r21, 0(r22)		/* Get Linux PTE */	andi.	r23, r21, _PAGE_RW	/* Is it writeable? */	beq	2f			/* Bail if not */	/* Update 'changed'.	*/	ori	r21, r21, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE	stw	r21, 0(r22)		/* Update Linux page table */	/* Most of the Linux PTE is ready to load into the TLB LO.	 * We set ZSEL, where only the LS-bit determines user access.	 * We set execute, because we don't have the granularity to	 * properly set this at the page level (Linux problem).	 * If shared is set, we cause a zero PID->TID load.	 * Many of these bits are software only.  Bits we don't set	 * here we (properly should) assume have the appropriate value.	 */	li	r22, 0x0ce2	andc	r21, r21, r22		/* Make sure 20, 21 are zero */	/* find the TLB index that caused the fault.  It has to be here.	*/	tlbsx	r23, 0, r20	tlbwe	r21, r23, TLB_DATA		/* Load TLB LO */	/* 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 */2:	/* The bailout.  Restore registers to pre-exception conditions	 * and call the heavyweights to help us out.	 */#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	b	DataAccess/* 0x0400 - Instruction Storage Exception * I don't know why it is called "Storage"....This is caused by a fetch * from non-execute or guarded pages. */	START_EXCEPTION(0x0400, InstructionAccess)	STND_EXCEPTION_PROLOG(0x0400)	mr	r4,r22			/* Pass SRR0 as arg2 */	li	r5,0			/* Pass zero as arg3 */	addi	r3,r1,STACK_FRAME_OVERHEAD	li	r7,STND_EXC	li	r20,MSR_KERNEL	rlwimi	r20,r23,0,16,16		/* Copy EE bit from the saved MSR */	FINISH_EXCEPTION(do_page_fault)	/* do_page_fault(regs, SRR0, SRR1) *//* 0x0500 - External Interrupt Exception*/	START_EXCEPTION(0x0500, HardwareInterrupt)	STND_EXCEPTION_PROLOG(0x0500)	addi	r3,r1,STACK_FRAME_OVERHEAD	li	r7,STND_EXC	li	r20,MSR_KERNEL	li	r4,0	bl	transfer_to_handler_GLOBAL(do_IRQ_intercept)	.long	do_IRQ	.long	ret_from_intercept/* 0x0600 - Alignment Exception*/	START_EXCEPTION(0x0600, Alignment)	STND_EXCEPTION_PROLOG(0x0600)	mfspr	r4,SPRN_DEAR		/* Grab the DEAR and save it */	stw	r4,_DEAR(r21)	addi	r3,r1,STACK_FRAME_OVERHEAD	li	r7,STND_EXC	li	r20,MSR_KERNEL	rlwimi	r20,r23,0,16,16		/* Copy EE bit from the saved MSR */	FINISH_EXCEPTION(AlignmentException)/* 0x0700 - Program Exception*/	START_EXCEPTION(0x0700,	ProgramCheck)	STND_EXCEPTION_PROLOG(0x0700)	addi	r3,r1,STACK_FRAME_OVERHEAD	li	r7,STND_EXC	li	r20,MSR_KERNEL	rlwimi	r20,r23,0,16,16		/* Copy EE bit from the saved MSR */	FINISH_EXCEPTION(ProgramCheckException)/* I'm stealing this unused vector location to build a standard exception * frame for Data TLB Access errors.  The other Data TLB exceptions will bail * out to this point if they can't resolve the lightweight TLB fault. */	START_EXCEPTION(0x0800,	DataAccess)	STND_EXCEPTION_PROLOG(0x0800)	mfspr	r5,SPRN_ESR		/* Grab the ESR, save it, pass arg3 */	stw	r5,_ESR(r21)	mfspr	r4,SPRN_DEAR		/* Grab the DEAR, save it, pass arg2 */	stw	r4,_DEAR(r21)	addi	r3,r1,STACK_FRAME_OVERHEAD	li	r7,STND_EXC	li	r20,MSR_KERNEL	rlwimi	r20,r23,0,16,16		/* Copy EE bit from the saved MSR */	FINISH_EXCEPTION(do_page_fault)	/* do_page_fault(regs, ESR, DEAR) */	STND_EXCEPTION(0x0900,	Trap_09,		UnknownException)	STND_EXCEPTION(0x0A00,	Trap_0A,		UnknownException)	STND_EXCEPTION(0x0B00,	Trap_0B,		UnknownException)/* 0x0C00 - System Call Exception*/	START_EXCEPTION(0x0C00,	SystemCall)	STND_EXCEPTION_PROLOG(0x0C00)	stw	r3,ORIG_GPR3(r21)	li	r7,STND_EXC	li	r20,MSR_KERNEL	rlwimi	r20,r23,0,16,16		/* Copy EE bit from the saved MSR */	FINISH_EXCEPTION(DoSyscall)	STND_EXCEPTION(0x0D00,	Trap_0D,		UnknownException)	STND_EXCEPTION(0x0E00,	Trap_0E,		UnknownException)	STND_EXCEPTION(0x0F00,	Trap_0F,		UnknownException)/* 0x1000 - Programmable Interval Timer (PIT) Exception*/	START_EXCEPTION(0x1000,	Decrementer)	STND_EXCEPTION_PROLOG(0x1000)	lis	r0,TSR_PIS@h		/* Set-up the PIT exception mask */	mtspr	SPRN_TSR,r0		/* Clear the PIT exception */	addi	r3,r1,STACK_FRAME_OVERHEAD	li	r7,STND_EXC	li	r20,MSR_KERNEL	bl	transfer_to_handler_GLOBAL(timer_interrupt_intercept)	.long	timer_interrupt	.long	ret_from_intercept#if 0/* NOTE: * FIT and WDT handlers are not implemented yet. *//* 0x1010 - Fixed Interval Timer (FIT) Exception*/	STND_EXCEPTION(0x1010,	FITException,		UnknownException)/* 0x1020 - Watchdog Timer (WDT) Exception*/	CRIT_EXCEPTION(0x1020,	WDTException,		UnknownException)#endif/* 0x1100 - Data TLB Miss Exception * As the name implies, translation is not in the MMU, so search the * page tables and fix it.  The only purpose of this function is to * load TLB entries from the page table if they exist. */	START_EXCEPTION(0x1100,	DTLBMiss)	mtspr	SPRG0, r20		/* Save some working registers */	mtspr	SPRG1, r21#ifdef CONFIG_403GCX	stw     r22, 0(r0)	stw     r23, 4(r0)	mfcr    r21	mfspr   r22, SPRN_PID	stw     r21, 8(r0)	stw     r22, 12(r0)#else	mtspr	SPRG4, r22	mtspr	SPRG5, r23	mfcr	r21	mfspr	r22, SPRN_PID	mtspr	SPRG7, r21	mtspr	SPRG6, r22#endif	mfspr	r20, SPRN_DEAR		/* Get faulting address */	/* If we are faulting a kernel address, we have to use the	 * kernel page tables.	 */	andis.	r21, r20, 0x8000	beq	3f	lis	r21, swapper_pg_dir@h	ori	r21, r21, swapper_pg_dir@l	li	r23, 0	mtspr	SPRN_PID, r23		/* TLB will have 0 TID */	b	4f	/* Get the PGD for the current thread.	 */3:	mfspr	r21,SPRG3	lwz	r21,PGDIR(r21)4:	tophys(r21, r21)	rlwimi	r21, r20, 12, 20, 29	/* Create L1 (pgdir/pmd) address */	lwz	r21, 0(r21)		/* Get L1 entry */	rlwinm.	r22, r21, 0, 0, 19	/* Extract L2 (pte) base address */	beq	2f			/* Bail if no table */	tophys(r22, r22)	rlwimi	r22, r20, 22, 20, 29	/* Compute PTE address */	lwz	r21, 0(r22)		/* Get Linux PTE */	andi.	r23, r21, _PAGE_PRESENT	beq	2f

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -