head_e500.s

来自「优龙2410linux2.6.8内核源代码」· S 代码 · 共 1,332 行 · 第 1/3 页

S
1,332
字号
	beq	1f;							     \	/* COMING FROM USER MODE */					     \	mfspr	r11,SPRG3;		/* if from user, start at top of   */\	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\	addi	r11,r11,THREAD_SIZE;					     \1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\	stw	r10,_CCR(r11);          /* save various registers	   */\	stw	r12,GPR12(r11);						     \	stw	r9,GPR9(r11);						     \	mflr	r10;							     \	stw	r10,_LINK(r11);						     \	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\	stw	r9,_ESR(r11);		/* exception was taken		   */\	mfspr	r12,CSRR0;						     \	stw	r1,GPR1(r11);						     \	mfspr	r9,CSRR1;						     \	stw	r1,0(r11);						     \	tovirt(r1,r11);							     \	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\	stw	r0,GPR0(r11);						     \	SAVE_4GPRS(3, r11);						     \	SAVE_2GPRS(7, r11)/* * Exception prolog for machine check exceptions.  This is similar to * the critical exception prolog, except that machine check exceptions * have their own save area.  For Book E processors, we also have a * reserved register (SPRG6) that is only used in machine check exceptions * so we can free up a GPR to use as the base for indirect access to the * machine check exception save area.  This is necessary since the MMU * is always on and the save area is offset from KERNELBASE. */#define MCHECK_EXCEPTION_PROLOG					     \	mtspr	SPRG6W,r8;		/* SPRG6 used in machine checks */   \	lis	r8,mcheck_save@ha;					     \	stw	r10,mcheck_r10@l(r8);					     \	stw	r11,mcheck_r11@l(r8);					     \	mfspr	r10,SPRG0;						     \	stw	r10,mcheck_sprg0@l(r8);					     \	mfspr	r10,SPRG1;						     \	stw	r10,mcheck_sprg1@l(r8);					     \	mfspr	r10,SPRG4R;						     \	stw	r10,mcheck_sprg4@l(r8);					     \	mfspr	r10,SPRG5R;						     \	stw	r10,mcheck_sprg5@l(r8);					     \	mfspr	r10,SPRG7R;						     \	stw	r10,mcheck_sprg7@l(r8);					     \	mfspr	r10,SPRN_PID;						     \	stw	r10,mcheck_pid@l(r8);					     \	mfspr	r10,SRR0;						     \	stw	r10,mcheck_srr0@l(r8);					     \	mfspr	r10,SRR1;						     \	stw	r10,mcheck_srr1@l(r8);					     \	mfspr	r10,CSRR0;						     \	stw	r10,mcheck_csrr0@l(r8);					     \	mfspr	r10,CSRR1;						     \	stw	r10,mcheck_csrr1@l(r8);					     \	mfspr	r8,SPRG6R;		/* SPRG6 used in machine checks */   \	mfcr	r10;			/* save CR in r10 for now	   */\	mfspr	r11,SPRN_MCSRR1;	/* check whether user or kernel    */\	andi.	r11,r11,MSR_PR;						     \	lis	r11,mcheck_stack_top@h;					     \	ori	r11,r11,mcheck_stack_top@l;				     \	beq	1f;							     \	/* COMING FROM USER MODE */					     \	mfspr	r11,SPRG3;		/* if from user, start at top of   */\	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\	addi	r11,r11,THREAD_SIZE;					     \1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\	stw	r10,_CCR(r11);          /* save various registers	   */\	stw	r12,GPR12(r11);						     \	stw	r9,GPR9(r11);						     \	mflr	r10;							     \	stw	r10,_LINK(r11);						     \	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\	stw	r9,_ESR(r11);		/* exception was taken		   */\	mfspr	r12,MCSRR0;						     \	stw	r1,GPR1(r11);						     \	mfspr	r9,MCSRR1;						     \	stw	r1,0(r11);						     \	tovirt(r1,r11);							     \	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\	stw	r0,GPR0(r11);						     \	SAVE_4GPRS(3, r11);						     \	SAVE_2GPRS(7, r11)/* * Exception vectors. */#define	START_EXCEPTION(label)						     \        .align 5;              						     \label:#define FINISH_EXCEPTION(func)					\	bl	transfer_to_handler_full;			\	.long	func;						\	.long	ret_from_except_full#define EXCEPTION(n, label, hdlr, xfer)				\	START_EXCEPTION(label);					\	NORMAL_EXCEPTION_PROLOG;				\	addi	r3,r1,STACK_FRAME_OVERHEAD;			\	xfer(n, hdlr)#define CRITICAL_EXCEPTION(n, label, hdlr)			\	START_EXCEPTION(label);					\	CRITICAL_EXCEPTION_PROLOG;				\	addi	r3,r1,STACK_FRAME_OVERHEAD;			\	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \			  NOCOPY, transfer_to_handler_full, \			  ret_from_except_full)#define MCHECK_EXCEPTION(n, label, hdlr)			\	START_EXCEPTION(label);					\	MCHECK_EXCEPTION_PROLOG;				\	mfspr	r5,SPRN_ESR;					\	stw	r5,_ESR(r11);					\	addi	r3,r1,STACK_FRAME_OVERHEAD;			\	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \			  NOCOPY, mcheck_transfer_to_handler,   \			  ret_from_mcheck_exc)#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret)	\	li	r10,trap;					\	stw	r10,TRAP(r11);					\	lis	r10,msr@h;					\	ori	r10,r10,msr@l;					\	copyee(r10, r9);					\	bl	tfer;		 				\	.long	hdlr;						\	.long	ret#define COPY_EE(d, s)		rlwimi d,s,0,16,16#define NOCOPY(d, s)#define EXC_XFER_STD(n, hdlr)		\	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \			  ret_from_except_full)#define EXC_XFER_LITE(n, hdlr)		\	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \			  ret_from_except)#define EXC_XFER_EE(n, hdlr)		\	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \			  ret_from_except_full)#define EXC_XFER_EE_LITE(n, hdlr)	\	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \			  ret_from_except)interrupt_base:	/* Critical Input Interrupt */	CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)	/* Machine Check Interrupt */	MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException)	/* Data Storage Interrupt */	START_EXCEPTION(DataStorage)	mtspr	SPRG0, r10		/* Save some working registers */	mtspr	SPRG1, r11	mtspr	SPRG4W, r12	mtspr	SPRG5W, r13	mfcr	r11	mtspr	SPRG7W, r11	/*	 * Check if it was a store fault, if not then bail	 * because a user tried to access a kernel or	 * read-protected page.  Otherwise, get the	 * offending address and handle it.	 */	mfspr	r10, SPRN_ESR	andis.	r10, r10, ESR_ST@h	beq	2f	mfspr	r10, SPRN_DEAR		/* Get faulting address */	/* If we are faulting a kernel address, we have to use the	 * kernel page tables.	 */	lis	r11, TASK_SIZE@h	ori	r11, r11, TASK_SIZE@l	cmplw	0, r10, r11	bge	2f	/* Get the PGD for the current thread */3:	mfspr	r11,SPRG3	lwz	r11,PGDIR(r11)4:	rlwimi	r11, r10, 12, 20, 29	/* Create L1 (pgdir/pmd) address */	lwz	r11, 0(r11)		/* Get L1 entry */	rlwinm.	r12, r11, 0, 0, 19	/* Extract L2 (pte) base address */	beq	2f			/* Bail if no table */	rlwimi	r12, r10, 22, 20, 29	/* Compute PTE address */	lwz	r11, 0(r12)		/* Get Linux PTE */	/* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */	andi.	r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE	cmpwi	0, r13, _PAGE_RW|_PAGE_USER	bne	2f			/* Bail if not */	/* Update 'changed'. */	ori	r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE	stw	r11, 0(r12)		/* Update Linux page table */	/* MAS2 not updated as the entry does exist in the tlb, this	   fault taken to detect state transition (eg: COW -> DIRTY)	 */	lis	r12, MAS3_RPN@h	ori	r12, r12, _PAGE_HWEXEC | MAS3_RPN@l	and	r11, r11, r12	rlwimi	r11, r11, 31, 27, 27	/* SX <- _PAGE_HWEXEC */	ori     r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */	/* update search PID in MAS6, AS = 0 */	mfspr	r12, SPRN_PID0	slwi	r12, r12, 16	mtspr	SPRN_MAS6, r12	/* find the TLB index that caused the fault.  It has to be here. */	tlbsx	0, r10	mtspr	SPRN_MAS3,r11	tlbwe	/* Done...restore registers and get out of here.  */	mfspr	r11, SPRG7R	mtcr	r11	mfspr	r13, SPRG5R	mfspr	r12, SPRG4R	mfspr	r11, SPRG1	mfspr	r10, SPRG0	rfi			/* Force context change */2:	/*	 * The bailout.  Restore registers to pre-exception conditions	 * and call the heavyweights to help us out.	 */	mfspr	r11, SPRG7R	mtcr	r11	mfspr	r13, SPRG5R	mfspr	r12, SPRG4R	mfspr	r11, SPRG1	mfspr	r10, SPRG0	b	data_access	/* Instruction Storage Interrupt */	START_EXCEPTION(InstructionStorage)	NORMAL_EXCEPTION_PROLOG	mfspr	r5,SPRN_ESR		/* Grab the ESR and save it */	stw	r5,_ESR(r11)	mr      r4,r12                  /* Pass SRR0 as arg2 */	li      r5,0                    /* Pass zero as arg3 */	EXC_XFER_EE_LITE(0x0400, handle_page_fault)	/* External Input Interrupt */	EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)	/* Alignment Interrupt */	START_EXCEPTION(Alignment)	NORMAL_EXCEPTION_PROLOG	mfspr   r4,SPRN_DEAR            /* Grab the DEAR and save it */	stw     r4,_DEAR(r11)	addi    r3,r1,STACK_FRAME_OVERHEAD	EXC_XFER_EE(0x0600, AlignmentException)	/* Program Interrupt */	START_EXCEPTION(Program)	NORMAL_EXCEPTION_PROLOG	mfspr	r4,SPRN_ESR		/* Grab the ESR and save it */	stw	r4,_ESR(r11)	addi	r3,r1,STACK_FRAME_OVERHEAD	EXC_XFER_STD(0x0700, ProgramCheckException)	/* Floating Point Unavailable Interrupt */	EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)	/* System Call Interrupt */	START_EXCEPTION(SystemCall)	NORMAL_EXCEPTION_PROLOG	EXC_XFER_EE_LITE(0x0c00, DoSyscall)	/* Auxillary Processor Unavailable Interrupt */	EXCEPTION(0x2900, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE)	/* Decrementer Interrupt */	START_EXCEPTION(Decrementer)	NORMAL_EXCEPTION_PROLOG	lis     r0,TSR_DIS@h            /* Setup the DEC interrupt mask */	mtspr   SPRN_TSR,r0		/* Clear the DEC interrupt */	addi    r3,r1,STACK_FRAME_OVERHEAD	EXC_XFER_LITE(0x0900, timer_interrupt)	/* Fixed Internal Timer Interrupt */	/* TODO: Add FIT support */	EXCEPTION(0x3100, FixedIntervalTimer, UnknownException, EXC_XFER_EE)	/* Watchdog Timer Interrupt */	/* TODO: Add watchdog support */	CRITICAL_EXCEPTION(0x3200, WatchdogTimer, UnknownException)	/* Data TLB Error Interrupt */	START_EXCEPTION(DataTLBError)	mtspr	SPRG0, r10		/* Save some working registers */	mtspr	SPRG1, r11	mtspr	SPRG4W, r12	mtspr	SPRG5W, r13	mfcr	r11	mtspr	SPRG7W, r11	mfspr	r10, SPRN_DEAR		/* Get faulting address */	/* If we are faulting a kernel address, we have to use the	 * kernel page tables.	 */	lis	r11, TASK_SIZE@h	ori	r11, r11, TASK_SIZE@l	cmplw	5, r10, r11	blt	5, 3f	lis	r11, swapper_pg_dir@h	ori	r11, r11, swapper_pg_dir@l	mfspr	r12,SPRN_MAS1		/* Set TID to 0 */	li	r13,MAS1_TID@l	andc	r12,r12,r13	mtspr	SPRN_MAS1,r12	b	4f	/* Get the PGD for the current thread */3:	mfspr	r11,SPRG3	lwz	r11,PGDIR(r11)4:	rlwimi	r11, r10, 12, 20, 29	/* Create L1 (pgdir/pmd) address */	lwz	r11, 0(r11)		/* Get L1 entry */	rlwinm.	r12, r11, 0, 0, 19	/* Extract L2 (pte) base address */	beq	2f			/* Bail if no table */	rlwimi	r12, r10, 22, 20, 29	/* Compute PTE address */	lwz	r11, 0(r12)		/* Get Linux PTE */	andi.	r13, r11, _PAGE_PRESENT	beq	2f	ori	r11, r11, _PAGE_ACCESSED	stw	r11, 0(r12)	 /* Jump to common tlb load */	b	finish_tlb_load2:	/* The bailout.  Restore registers to pre-exception conditions	 * and call the heavyweights to help us out.	 */	mfspr	r11, SPRG7R	mtcr	r11	mfspr	r13, SPRG5R	mfspr	r12, SPRG4R	mfspr	r11, SPRG1	mfspr	r10, SPRG0	b	data_access	/* Instruction TLB Error Interrupt */	/*	 * Nearly the same as above, except we get our	 * information from different registers and bailout	 * to a different point.	 */	START_EXCEPTION(InstructionTLBError)	mtspr	SPRG0, r10		/* Save some working registers */	mtspr	SPRG1, r11	mtspr	SPRG4W, r12	mtspr	SPRG5W, r13	mfcr	r11	mtspr	SPRG7W, r11	mfspr	r10, SRR0		/* Get faulting address */	/* If we are faulting a kernel address, we have to use the	 * kernel page tables.	 */	lis	r11, TASK_SIZE@h	ori	r11, r11, TASK_SIZE@l	cmplw	5, r10, r11	blt	5, 3f	lis	r11, swapper_pg_dir@h	ori	r11, r11, swapper_pg_dir@l	mfspr	r12,SPRN_MAS1		/* Set TID to 0 */	li	r13,MAS1_TID@l	andc	r12,r12,r13	mtspr	SPRN_MAS1,r12	b	4f	/* Get the PGD for the current thread */3:	mfspr	r11,SPRG3	lwz	r11,PGDIR(r11)4:	rlwimi	r11, r10, 12, 20, 29	/* Create L1 (pgdir/pmd) address */	lwz	r11, 0(r11)		/* Get L1 entry */	rlwinm.	r12, r11, 0, 0, 19	/* Extract L2 (pte) base address */	beq	2f			/* Bail if no table */	rlwimi	r12, r10, 22, 20, 29	/* Compute PTE address */	lwz	r11, 0(r12)		/* Get Linux PTE */	andi.	r13, r11, _PAGE_PRESENT	beq	2f	ori	r11, r11, _PAGE_ACCESSED	stw	r11, 0(r12)	/* Jump to common TLB load point */	b	finish_tlb_load2:	/* The bailout.  Restore registers to pre-exception conditions	 * and call the heavyweights to help us out.	 */	mfspr	r11, SPRG7R	mtcr	r11	mfspr	r13, SPRG5R	mfspr	r12, SPRG4R	mfspr	r11, SPRG1	mfspr	r10, SPRG0	b	InstructionStorage#ifdef CONFIG_SPE	/* SPE Unavailable */	START_EXCEPTION(SPEUnavailable)	NORMAL_EXCEPTION_PROLOG	bne	load_up_spe	addi    r3,r1,STACK_FRAME_OVERHEAD	EXC_XFER_EE_LITE(0x2010, KernelSPE)#else

⌨️ 快捷键说明

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