entry.s

来自「linux-2.4.29操作系统的源码」· S 代码 · 共 2,106 行 · 第 1/4 页

S
2,106
字号
 * Post-handlers for interrupts (ret_from_irq), exceptions * (ret_from_exception) and common reentrance doors (restore_all * to get back to the original context, ret_from_syscall loop to * check kernel exiting). * * ret_with_reschedule and check_signals are an inner lables of * the ret_from_syscall loop. * * In common to all stack-frame sensitive handlers. * * Inputs: * (SP)   struct pt_regs *, original register's frame pointer (basic) * */ret_from_irq:	ld.q	SP, FRAME_S(FSSR), r6	shlri	r6, 30, r6	andi	r6, 1, r6	_ptar	restore_all, t0	bne	r6, ZERO, t0		/* no further checks */	STI()	_ptar	ret_with_reschedule, t0	blink	t0, ZERO		/* Do not check softirqs */	ret_from_exception:	ld.q	SP, FRAME_S(FSSR), r6	shlri	r6, 30, r6	andi	r6, 1, r6	_ptar	restore_all, t0	bne	r6, ZERO, t0		/* no further checks */	/* Check softirqs */	/*	 * Fall-through:	 * _ptar   ret_from_syscall, t0	 * blink   t0, ZERO	 */ret_from_syscall:	ret_with_reschedule:	getcon	KCR0, r6	ld.l	r6, need_resched, r7	_ptar	check_signals, t0	beq	r7, ZERO, t0	_ptar	ret_from_syscall, t0	gettr	t0, LINK	_loada	schedule, r6	ptabs	r6, t0	blink	t0, ZERO		/* Call schedule(), return on top */check_signals:	getcon	KCR0, r6	ld.l	r6, sigpending, r7	_ptar	restore_all, t0	beq	r7, ZERO, t0	_loada	do_signal, r6	ptabs	r6, t0	or	SP, ZERO, r2	or	ZERO, ZERO, r3	blink	t0, LINK	    /* Call do_signal(regs, 0), return here */	#ifdef CONFIG_SH64_PAGE_TABLE_AUDIT	/* Check page tables before returning (with obvious performance penalty). */	_loada  audit_mm, r6	ptabs   r6, t0	getcon  expevt, r2	getcon  intevt, r3	getcon  tra, r4	getcon  dcr, r5	blink   t0, LINK#endifrestore_all:	/* Do prefetches */		ld.q	SP, FRAME_T(0), r6	ld.q	SP, FRAME_T(1), r7	ld.q	SP, FRAME_T(2), r8	ld.q	SP, FRAME_T(3), r9	ptabs	r6, t0	ptabs	r7, t1	ptabs	r8, t2	ptabs	r9, t3	ld.q	SP, FRAME_T(4), r6	ld.q	SP, FRAME_T(5), r7	ld.q	SP, FRAME_T(6), r8	ld.q	SP, FRAME_T(7), r9	ptabs	r6, t4	ptabs	r7, t5	ptabs	r8, t6	ptabs	r9, t7	ld.q	SP, FRAME_R(0), r0	ld.q	SP, FRAME_R(1), r1	ld.q	SP, FRAME_R(2), r2	ld.q	SP, FRAME_R(3), r3	ld.q	SP, FRAME_R(4), r4	ld.q	SP, FRAME_R(5), r5	ld.q	SP, FRAME_R(6), r6	ld.q	SP, FRAME_R(7), r7	ld.q	SP, FRAME_R(8), r8	ld.q	SP, FRAME_R(9), r9	ld.q	SP, FRAME_R(10), r10	ld.q	SP, FRAME_R(11), r11	ld.q	SP, FRAME_R(12), r12	ld.q	SP, FRAME_R(13), r13	ld.q	SP, FRAME_R(14), r14	ld.q	SP, FRAME_R(16), r16	ld.q	SP, FRAME_R(17), r17	ld.q	SP, FRAME_R(18), r18	ld.q	SP, FRAME_R(19), r19	ld.q	SP, FRAME_R(20), r20	ld.q	SP, FRAME_R(21), r21	ld.q	SP, FRAME_R(22), r22	ld.q	SP, FRAME_R(23), r23	ld.q	SP, FRAME_R(24), r24	ld.q	SP, FRAME_R(25), r25	ld.q	SP, FRAME_R(26), r26	ld.q	SP, FRAME_R(27), r27	ld.q	SP, FRAME_R(28), r28	ld.q	SP, FRAME_R(29), r29	ld.q	SP, FRAME_R(30), r30	ld.q	SP, FRAME_R(31), r31	ld.q	SP, FRAME_R(32), r32	ld.q	SP, FRAME_R(33), r33	ld.q	SP, FRAME_R(34), r34	ld.q	SP, FRAME_R(35), r35	ld.q	SP, FRAME_R(36), r36	ld.q	SP, FRAME_R(37), r37	ld.q	SP, FRAME_R(38), r38	ld.q	SP, FRAME_R(39), r39	ld.q	SP, FRAME_R(40), r40	ld.q	SP, FRAME_R(41), r41	ld.q	SP, FRAME_R(42), r42	ld.q	SP, FRAME_R(43), r43	ld.q	SP, FRAME_R(44), r44	ld.q	SP, FRAME_R(45), r45	ld.q	SP, FRAME_R(46), r46	ld.q	SP, FRAME_R(47), r47	ld.q	SP, FRAME_R(48), r48	ld.q	SP, FRAME_R(49), r49	ld.q	SP, FRAME_R(50), r50	ld.q	SP, FRAME_R(51), r51	ld.q	SP, FRAME_R(52), r52	ld.q	SP, FRAME_R(53), r53	ld.q	SP, FRAME_R(54), r54	ld.q	SP, FRAME_R(55), r55	ld.q	SP, FRAME_R(56), r56	ld.q	SP, FRAME_R(57), r57	ld.q	SP, FRAME_R(58), r58	getcon	SR, r59	movi	SR_BLOCK_EXC, r60	or	r59, r60, r59	putcon	r59, SR			/* SR.BL = 1, keep nesting out */	ld.q	SP, FRAME_S(FSSR), r61	ld.q	SP, FRAME_S(FSPC), r62	movi	SR_ASID_MASK, r60	and	r59, r60, r59	andc	r61, r60, r61		/* Clear out older ASID */	or	r59, r61, r61		/* Retain current ASID */	putcon	r61, SSR	putcon	r62, SPC	/* Ignore FSYSCALL_ID */	ld.q	SP, FRAME_R(59), r59	ld.q	SP, FRAME_R(60), r60	ld.q	SP, FRAME_R(61), r61	ld.q	SP, FRAME_R(62), r62	/* Last touch */	ld.q	SP, FRAME_R(15), SP	rte	nop/* * Third level handlers for VBR-based exceptions. Adapting args to * and/or deflecting to fourth level handlers. * * Fourth level handlers interface. * Most are C-coded handlers directly pointed by the trap_jtable. * (Third = Fourth level) * Inputs: * (r2)   fault/interrupt code, entry number (e.g. NMI = 14, *	  IRL0-3 (0000) = 16, RTLBMISS = 2, SYSCALL = 11, etc ...) * (r3)   struct pt_regs *, original register's frame pointer * (r4)   Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault) * (r5)   TRA control register (for syscall/debug benefit only) * (LINK) return address * (SP)   = r3 * * Kernel TLB fault handlers will get a slightly different interface. * (r2)   struct pt_regs *, original register's frame pointer * (r3)   writeaccess, whether it's a store fault as opposed to load fault * (r4)   execaccess, whether it's a ITLB fault as opposed to DTLB fault * (r5)   Effective Address of fault * (LINK) return address * (SP)   = r2 * * fpu_error_or_IRQ? is a helper to deflect to the right cause. * */tlb_miss_load:	or	SP, ZERO, r2	or	ZERO, ZERO, r3		/* Read */	or	ZERO, ZERO, r4		/* Data */	getcon	TEA, r5	_ptar	call_do_page_fault, t0	beq	ZERO, ZERO, tr0tlb_miss_store:	or	SP, ZERO, r2	movi	1, r3			/* Write */	or	ZERO, ZERO, r4		/* Data */	getcon	TEA, r5	_ptar	call_do_page_fault, t0	beq	ZERO, ZERO, tr0itlb_miss_or_IRQ:	_ptar	its_IRQ, t0	beqi/u	r4, EVENT_INTERRUPT, t0	or	SP, ZERO, r2	or	ZERO, ZERO, r3		/* Read */	movi	1, r4			/* Text */	getcon	TEA, r5	/* Fall through */call_do_page_fault:	_loada	do_page_fault, r6        ptabs	r6, t0        blink	t0, ZERO		fpu_error_or_IRQA:	_ptar	its_IRQ, t0	beqi/l	r4, EVENT_INTERRUPT, t0#ifndef CONFIG_NOFPU_SUPPORT 	_loada	do_fpu_state_restore, r6#else	_loada	do_exception_error, r6#endif	ptabs	r6, t0	blink	t0, ZEROfpu_error_or_IRQB:	_ptar	its_IRQ, t0	beqi/l	r4, EVENT_INTERRUPT, t0#ifndef CONFIG_NOFPU_SUPPORT	_loada	do_fpu_state_restore, r6#else	_loada	do_exception_error, r6#endif	ptabs	r6, t0	blink	t0, ZEROits_IRQ:	_loada	do_IRQ, r6	ptabs	r6, t0	blink	t0, ZERO/* * system_call/unknown_trap third level handler: *  * Inputs: * (r2)   fault/interrupt code, entry number (TRAP = 11) * (r3)   struct pt_regs *, original register's frame pointer * (r4)   Not used. Event (0=interrupt, 1=TLB miss fault, 2=Not TLB miss fault) * (r5)   TRA Control Reg (0x00xyzzzz: x=1 SYSCALL, y = #args, z=nr) * (SP)   = r3 * (LINK) return address: ret_from_exception * (*r3)  Syscall parms: SC#, arg0, arg1, ..., arg5 in order (Saved r2/r7) * * Outputs: * (*r3)  Syscall reply (Saved r2) * (LINK) In case of syscall only it can be scrapped. *        Common second level post handler will be ret_from_syscall. *        Common (non-trace) exit point to that is syscall_ret (saving *        result to r2). Common bad exit point is syscall_bad (returning *        ENOSYS then saved to r2). * */unknown_trap:	/* Unknown Trap or User Trace */	_loada	do_unknown_trapa, r6	ptabs	r6, t0        ld.q    r3, FRAME_R(9), r2	/* r2 = #arg << 16 | syscall # */        andi    r2, 0x1ff, r2		/* r2 = syscall # */	blink	t0, LINK	_ptar	syscall_ret, t0	blink	t0, ZERO        /* New syscall implementation*/system_call:	_ptar	unknown_trap, t0        or      r5, ZERO, r4            /* TRA (=r5) -> r4 */        shlri   r4, 20, r4	bnei	r4, 1, t0		/* unknown_trap if not 0x1yzzzz */        /* It's a system call */	st.q    r3, FRAME_S(FSYSCALL_ID), r5 	/* ID (0x1yzzzz) -> stack */	andi    r5, 0x1ff, r5			/* syscall # -> r5	  */	STI()	_ptar	syscall_allowed, t0	movi	NR_syscalls - 1, r4	/* Last valid */	bgeu/l	r4, r5, t0syscall_bad:	/* Return ENOSYS ! */	movi	-(ENOSYS), r2		/* Fall-through */syscall_ret:	st.q	SP, FRAME_R(9), r2	/* Expecting SP back to BASIC frame */#ifdef POOR_MANS_STRACE	/* nothing useful in registers at this point */	_loada	evt_debug2, r5	ori	r5, 1, r5	ptabs	r5, t0	ld.q	SP, FRAME_R(9), r2	or	SP, ZERO, r3	blink	t0, LINK#endif		ld.q	SP, FRAME_S(FSPC), r2	addi	r2, 4, r2		/* Move PC, being pre-execution event */	st.q	SP, FRAME_S(FSPC), r2	_ptar	ret_from_syscall, t0	blink	t0, ZERO/*  A different return path for ret_from_fork, because we now need  *  to call schedule_tail with the later kernels. Because prev is *  loaded into r2 by switch_to() means we can just call it straight  away */	.global	ret_from_forkret_from_fork:	_loada	schedule_tail,r5	ori	r5, 1, r5	ptabs	r5, t0	blink	t0, LINK	#ifdef POOR_MANS_STRACE	/* nothing useful in registers at this point */	_loada	evt_debug2, r5	ori	r5, 1, r5	ptabs	r5, t0	ld.q	SP, FRAME_R(9), r2	or	SP, ZERO, r3	blink	t0, LINK#endif		ld.q	SP, FRAME_S(FSPC), r2	addi	r2, 4, r2		/* Move PC, being pre-execution event */	st.q	SP, FRAME_S(FSPC), r2	_ptar	ret_from_syscall, t0	blink	t0, ZERO				syscall_allowed:	/* Use LINK to deflect the exit point, default is syscall_ret */	_ptar	syscall_ret, t0	gettr	t0, LINK	_ptar	syscall_notrace, t0	getcon	KCR0, r2	ld.l	r2, ptrace, r4	andi	r4, PT_TRACESYS, r4	beq/l	r4, ZERO, t0	/* Trace it by calling syscall_trace before and after */	_loada	syscall_trace, r4	ptabs	r4, t0	blink	t0, LINK	/* Reload syscall number as r5 is trashed by syscall_trace */	ld.q	SP, FRAME_S(FSYSCALL_ID), r5	andi	r5, 0x1ff, r5	_ptar	syscall_ret_trace, t0	gettr	t0, LINKsyscall_notrace:	/* Now point to the appropriate 4th level syscall handler */	_loada	sys_call_table, r4	shlli	r5, 2, r5	ldx.l	r4, r5, r5	ptabs	r5, t0	/* Prepare original args */	ld.q	SP, FRAME_R(2), r2	ld.q	SP, FRAME_R(3), r3	ld.q	SP, FRAME_R(4), r4	ld.q	SP, FRAME_R(5), r5	ld.q	SP, FRAME_R(6), r6	ld.q	SP, FRAME_R(7), r7	/* And now the trick for those syscalls requiring regs * ! */	or	SP, ZERO, r8	/* Call it */	blink	t0, ZERO	/* LINK is already properly set */syscall_ret_trace:	/* We get back here only if under trace */	st.q	SP, FRAME_R(9), r2	/* Save return value */	/*  ... usage of a pt relative (_ptar _syscall_trace) fails on CDC */	_loada	syscall_trace, LINK	ptabs	LINK, t0	blink	t0, LINK	/* This needs to be done after any syscall tracing */	ld.q	SP, FRAME_S(FSPC), r2	addi	r2, 4, r2	/* Move PC, being pre-execution event */	st.q	SP, FRAME_S(FSPC), r2	_ptar	ret_from_syscall, t0	blink	t0, ZERO		/* Resume normal return sequence *//* * --- Switch to running under a particular ASID and return the previous ASID value * --- The caller is assumed to have done a cli before calling this. * * Input r2 : new ASID * Output r2 : old ASID */	.global switch_and_save_asidswitch_and_save_asid:	getcon	sr, r0	movi	255, r4	shlli 	r4, 16, r4	/* r4 = mask to select ASID */	and	r0, r4, r3	/* r3 = shifted old ASID */	andi	r2, 255, r2	/* mask down new ASID */	shlli	r2, 16, r2	/* align new ASID against SR.ASID */	andc	r0, r4, r0	/* efface old ASID from SR */	or	r0, r2, r0	/* insert the new ASID */	putcon	r0, ssr	_loada	1f, r0	putcon	r0, spc	rte	nop1:	ptabs	r18, tr0	shlri	r3, 16, r2	/* r2 = old ASID */	blink tr0, r63	.global	route_to_panic_handlerroute_to_panic_handler:	/* Switch to real mode, goto panic_handler, don't return.  Useful for	   last-chance debugging, e.g. if no output wants to go to the console.	   */	_loada	panic_handler - CONFIG_CACHED_MEMORY_OFFSET, r1	ptabs	r1, tr0	pta	1f, tr1	gettr	tr1, r0	putcon	r0, spc	getcon	sr, r0	movi	1, r1	shlli	r1, 31, r1	andc	r0, r1, r0	putcon	r0, ssr	rte	nop1:	/* Now in real mode */	blink tr0, r63	nop	.global peek_real_address_qpeek_real_address_q:	/* Two args:	   r2 : real mode address to peek	   r2(out) : result quadword	   This is provided as a cheapskate way of manipulating device	   registers for debugging (to avoid the need to onchip_remap the debug	   module, and to avoid the need to onchip_remap the watchpoint	   controller in a way that identity maps sufficient bits to avoid the	   SH5-101 cut2 silicon defect).	   This code is not performance critical	*/	add.l	r2, r63, r2	/* sign extend address */	getcon	sr, r0		/* r0 = saved original SR */	movi	1, r1	shlli	r1, 28, r1	or	r0, r1, r1	/* r0 with block bit set */	putcon	r1, sr		/* now in critical section */	movi	1, r36	shlli	r36, 31, r36	andc	r1, r36, r1	/* turn sr.mmu off in real mode section */	putcon	r1, ssr	_loada	.peek0 - CONFIG_CACHED_MEMORY_OFFSET, r36 /* real mode target address */	_loada	1f, r37		/* virtual mode return addr */	putcon	r36, spc	synco	rte	nop.peek0:	/* come here in real mode, don't touch caches!!           still in critical section (sr.bl==1) */	putcon	r0, ssr	putcon	r37, spc	/* Here's the actual peek.  If the address is bad, all bets are now off	 * what will happen (handlers invoked in real-mode = bad news) */	ld.q	r2, 0, r2	synco	rte	/* Back to virtual mode */	nop1:

⌨️ 快捷键说明

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