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

📄 entry.s

📁 linux内核源码
💻 S
📖 第 1 页 / 共 3 页
字号:
	cmpu.w	NR_syscalls, $r9		bcc	ret_from_sys_call	lslq	2, $r9		;  multiply by 4, in the delay slot	;; as a bonus 7th parameter, we give the location on the stack	;; of the register structure itself. some syscalls need this.	push	$sp		;; the parameter carrying registers r10, r11, r12 and 13 are intact.	;; the fifth and sixth parameters (if any) was in mof and srp 	;; respectively, and we need to put them on the stack.	push	$srp	push	$mof		jsr	[$r9+sys_call_table]	; actually do the system call	addq	3*4, $sp		; pop the mof, srp and regs parameters	move.d	$r10, [$sp+PT_r10]	; save the return value	moveq	1, $r9		; "parameter" to ret_from_sys_call to show it was a sys call		;; fall through into ret_from_sys_call to return	ret_from_sys_call:	;; r9 is a parameter - if >=1 we came from a syscall, if 0, from an irq			;; get the current task-struct pointer (see top for defs)	movs.w	-8192, $r0	; THREAD_SIZE == 8192 	and.d	$sp, $r0	di			; make sure need_resched and sigpending don't change	move.d	[$r0+TI_flags],$r1	and.d	_TIF_ALLWORK_MASK, $r1	bne	_syscall_exit_work	nop_Rexit:	;; this epilogue MUST match the prologues in multiple_interrupt, irq.h and ptregs.h	pop	$r10		; frametype	bne	_RBFexit	; was not CRIS_FRAME_NORMAL, handle otherwise	addq	4, $sp		; skip orig_r10, in delayslot	movem	[$sp+], $r13	; registers r0-r13	pop	$mof		; multiply overflow register 	pop	$dccr		; condition codes	pop	$srp		; subroutine return pointer	;; now we have a 4-word SBFS frame which we do not want to restore	;; using RBF since it was not stacked with SBFS. instead we would like to	;; just get the PC value to restart it with, and skip the rest of	;; the frame.	;; Also notice that it's important to use instructions here that	;; keep the interrupts disabled (since we've already popped DCCR)	move	[$sp=$sp+16], $p8; pop the SBFS frame from the sp	jmpu	[$sp-16]	; return through the irp field in the sbfs frame_RBFexit:	movem	[$sp+], $r13	; registers r0-r13, in delay slot	pop	$mof		; multiply overflow register 	pop	$dccr		; condition codes	pop	$srp		; subroutine return pointer	rbf	[$sp+]		; return by popping the CPU status	;; We get here after doing a syscall if extra work might need to be done	;; perform syscall exit tracing if needed	_syscall_exit_work:	;; $r0 contains current at this point and irq's are disabled	move.d  [$r0+TI_flags], $r1	btstq	TIF_SYSCALL_TRACE, $r1	bpl	_work_pending	nop		ei	move.d	$r9, $r1	; preserve r9	jsr	do_syscall_trace	move.d	$r1, $r9		ba	_resume_userspace	nop	_work_pending:	move.d  [$r0+TI_flags], $r1	btstq   TIF_NEED_RESCHED, $r1	bpl	_work_notifysig	; was neither trace nor sched, must be signal/notify	nop	_work_resched:	move.d	$r9, $r1	; preserve r9	jsr	schedule	move.d	$r1, $r9	di	move.d	[$r0+TI_flags], $r1	and.d	_TIF_WORK_MASK, $r1; ignore the syscall trace counter	beq	_Rexit	nop	btstq	TIF_NEED_RESCHED, $r1	bmi	_work_resched	; current->work.need_resched	nop_work_notifysig:	;; deal with pending signals and notify-resume requests	move.d	$r9, $r10	; do_notify_resume syscall/irq param	move.d	$sp, $r11	; the regs param	move.d  $r1, $r12	; the thread_info_flags parameter	jsr	do_notify_resume		ba _Rexit	nop	;; We get here as a sidetrack when we've entered a syscall with the	;; trace-bit set. We need to call do_syscall_trace and then continue	;; with the call.	_syscall_trace_entry:	;; PT_r10 in the frame contains -ENOSYS as required, at this point		jsr	do_syscall_trace	;; now re-enter the syscall code to do the syscall itself	;; we need to restore $r9 here to contain the wanted syscall, and	;; the other parameter-bearing registers	move.d	[$sp+PT_r9], $r9	move.d	[$sp+PT_orig_r10], $r10  ; PT_r10 is already filled with -ENOSYS.	move.d	[$sp+PT_r11],      $r11	move.d	[$sp+PT_r12],      $r12	move.d	[$sp+PT_r13],      $r13	move	[$sp+PT_mof],      $mof	move	[$sp+PT_srp],      $srp		ba	_syscall_traced	nop		;; resume performs the actual task-switching, by switching stack pointers	;; input arguments: r10 = prev, r11 = next, r12 = thread offset in task struct	;; returns old current in r10	;;	;; TODO:  see the i386 version. The switch_to which calls resume in our version	;;        could really be an inline asm of this.resume:		push	$srp		         ; we keep the old/new PC on the stack 	add.d	$r12, $r10		 ; r10 = current tasks tss	move	$dccr, [$r10+THREAD_dccr]; save irq enable state	di	move	$usp, [$r10+ THREAD_usp] ; save user-mode stackpointer		;; See copy_thread for the reason why register R9 is saved.	subq	10*4, $sp	movem	$r9, [$sp]		 ; save non-scratch registers and R9.		move.d	$sp, [$r10+THREAD_ksp]	 ; save the kernel stack pointer for the old task	move.d	$sp, $r10		 ; return last running task in r10	and.d   -8192, $r10	         ; get thread_info from stackpointer	move.d  [$r10+TI_task], $r10     ; get task  	add.d	$r12, $r11		 ; find the new tasks tss	move.d	[$r11+THREAD_ksp], $sp	 ; switch into the new stackframe by restoring kernel sp	movem	[$sp+], $r9		 ; restore non-scratch registers and R9.	move	[$r11+THREAD_usp], $usp ; restore user-mode stackpointer		move	[$r11+THREAD_dccr], $dccr ; restore irq enable status	jump	[$sp+]		         ; restore PC	;; This is the MMU bus fault handler.	;; It needs to stack the CPU status and overall is different	;; from the other interrupt handlers.mmu_bus_fault:	;; For refills we try to do a quick page table lookup. If it is	;; a real fault we let the mm subsystem handle it.	;; the first longword in the sbfs frame was the interrupted PC	;; which fits nicely with the "IRP" slot in pt_regs normally used to	;; contain the return address. used by Oops to print kernel errors.	sbfs	[$sp=$sp-16]	; push the internal CPU status	push	$dccr	di	subq	2*4, $sp	movem	$r1, [$sp]	move.d  [R_MMU_CAUSE], $r1	;; ETRAX 100LX TR89 bugfix: if the second half of an unaligned	;; write causes a MMU-fault, it will not be restarted correctly.	;; This could happen if a write crosses a page-boundary and the	;; second page is not yet COW'ed or even loaded. The workaround	;; is to clear the unaligned bit in the CPU status record, so	;; that the CPU will rerun both the first and second halves of	;; the instruction. This will not have any sideeffects unless	;; the first half goes to any device or memory that can't be	;; written twice, and which is mapped through the MMU.	;;	;; We only need to do this for writes.	btstq	8, $r1		   ; Write access?	bpl	1f	nop	move.d	[$sp+16], $r0	   ; Clear unaligned bit in csrinstr	and.d	~(1<<5), $r0	move.d	$r0, [$sp+16]1:	btstq	12, $r1		   ; Refill?	bpl	2f	lsrq	24, $r1     ; Get PGD index (bit 24-31)	move.d  [per_cpu__current_pgd], $r0 ; PGD for the current process	move.d	[$r0+$r1.d], $r0   ; Get PMD	beq	2f	nop	and.w	PAGE_MASK, $r0	   ; Remove PMD flags	move.d  [R_MMU_CAUSE], $r1	lsrq	PAGE_SHIFT, $r1	and.d	0x7ff, $r1         ; Get PTE index into PGD (bit 13-23)	move.d	[$r0+$r1.d], $r1   ; Get PTE	beq	2f	nop	;; Store in TLB	move.d  $r1, [R_TLB_LO]	;; Return	movem	[$sp+], $r1	pop	$dccr	rbf	[$sp+]		; return by popping the CPU status2:	; PMD or PTE missing, let the mm subsystem fix it up.	movem	[$sp+], $r1	pop	$dccr	; Ok, not that easy, pass it on to the mm subsystem	; The MMU status record is now on the stack	push	$srp		; make a stackframe similar to pt_regs	push	$dccr	push	$mof	di	subq	14*4, $sp	movem	$r13, [$sp]	push	$r10		; dummy orig_r10	moveq	1, $r10	push	$r10		; frametype == 1, BUSFAULT frame type	move.d	$sp, $r10	; pt_regs argument to handle_mmu_bus_fault			jsr	handle_mmu_bus_fault  ; in arch/cris/arch-v10/mm/fault.c	;; now we need to return through the normal path, we cannot just	;; do the RBFexit since we might have killed off the running	;; process due to a SEGV, scheduled due to a page blocking or	;; whatever.	moveq	0, $r9		; busfault is equivalent to an irq			ba	ret_from_intr	nop			;; special handlers for breakpoint and NMIhwbreakpoint:	push	$dccr	di	push	$r10	push	$r11	move.d	[hw_bp_trig_ptr],$r10	move	$brp,$r11	move.d	$r11,[$r10+]	move.d	$r10,[hw_bp_trig_ptr]1:	pop	$r11	pop	$r10	pop	$dccr	retb	nop	IRQ1_interrupt:	;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!	move	$brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame	push	$srp	push	$dccr	push	$mof	di	subq	14*4, $sp	movem	$r13, [$sp]	push	$r10		; push orig_r10	clear.d [$sp=$sp-4]	; frametype == 0, normal frame	;; If there is a glitch on the NMI pin shorter than ~100ns	;; (i.e. non-active by the time we get here) then the nmi_pin bit	;; in R_IRQ_MASK0_RD will already be cleared.  The watchdog_nmi bit	;; is cleared by us however (when feeding the watchdog), which is why	;; we use that bit to determine what brought us here.	move.d	[R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog?	and.d   (1<<30), $r1	bne	wdog	move.d  $sp, $r10	jsr	handle_nmi	setf m			; Enable NMI again	ba	_Rexit		; Return the standard way	nopwdog:#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM);; Check if we're waiting for reset to happen, as signalled by;; hard_reset_now setting cause_of_death to a magic value.  If so, just;; get stuck until reset happens.	.comm	cause_of_death, 4	;; Don't declare this anywhere.	move.d	[cause_of_death], $r10	cmp.d	0xbedead, $r10_killed_by_death:	beq	_killed_by_death	nop;; We'll see this in ksymoops dumps.Watchdog_bite:#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY       ;; We just restart the watchdog here to be sure we dont get       ;; hit while printing the watchdogmsg below       ;; This restart is compatible with the rest of the C-code, so       ;; the C-code can keep restarting the watchdog after this point.       ;; The non-NICE_DOGGY code below though, disables the possibility       ;; to restart since it changes the watchdog key, to avoid any       ;; buggy loops etc. keeping the watchdog alive after this.       jsr     reset_watchdog#else;; We need to extend the 3.3ms after the NMI at watchdog bite, so we have;; time for an oops-dump over a 115k2 serial wire.  Another 100ms should do.;; Change the watchdog key to an arbitrary 3-bit value and restart the;; watchdog.#define WD_INIT 2	moveq	  IO_FIELD (R_WATCHDOG, key, WD_INIT), $r10	move.d	R_WATCHDOG, $r11	move.d	$r10, [$r11]	moveq	  IO_FIELD (R_WATCHDOG, key,				\			    IO_EXTRACT (R_WATCHDOG, key,		\					IO_MASK (R_WATCHDOG, key))	\			    ^ WD_INIT)					\		| IO_STATE (R_WATCHDOG, enable, start), $r10	move.d	$r10, [$r11]#endif	;; Note that we don't do "setf m" here (or after two necessary NOPs),;; since *not* doing that saves us from re-entrancy checks.  We don't want;; to get here again due to possible subsequent NMIs; we want the watchdog;; to reset us.	move.d	_watchdogmsg,$r10	jsr	printk	move.d	$sp, $r10	jsr	watchdog_bite_hook;; This nop is here so we see the "Watchdog_bite" label in ksymoops dumps;; rather than "spurious_interrupt".	nop;; At this point we drop down into spurious_interrupt, which will do a;; hard reset.	.section .rodata,"a"_watchdogmsg:	.ascii	"Oops: bitten by watchdog\n\0"	.previous#endif /* CONFIG_ETRAX_WATCHDOG and not CONFIG_SVINTO_SIM */spurious_interrupt:		di	jump hard_reset_now	;; this handles the case when multiple interrupts arrive at the same time	;; we jump to the first set interrupt bit in a priority fashion	;; the hardware will call the unserved interrupts after the handler finishes	multiple_interrupt:	;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!	move	$irp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame	push	$srp	push	$dccr	push	$mof	di	subq	14*4, $sp	movem	$r13, [$sp]	push	$r10		; push orig_r10	clear.d [$sp=$sp-4]	; frametype == 0, normal frame		move.d  $sp, $r10	jsr	do_multiple_IRQ		jump    ret_from_intrdo_sigtrap:	;; 	;; SIGTRAP the process that executed the break instruction.

⌨️ 快捷键说明

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