📄 windalib.s
字号:
* : %esi : return addr * : %edi : %eax * : V * V * */ cmpl $0,FUNC(vxIntStackEnabled) /* if vxIntStackEnabled == 0 then */ je intEnt0 /* skip the interrupt stack switch */ movl ESF0_CS+12(%esp), %eax /* get CS in ESF0 */ cmpw FUNC(sysCsInt), %ax /* is it nested interrupt ? */ je intEnt0 /* yes: skip followings */ cmpl $1,FUNC(intNest) /* already in the interrupt stack? */ jne intEnt0 /* skip the interrupt stack switch */ /* copy the supervisor stack to the interrupt stack. */intEntStackSwitch: pushl %ecx /* save %ecx */ pushl %esi /* save %esi */ pushl %edi /* save %edi */ /* copy ESF0(12 bytes), errno, return addr, %eax */ subl $ ESF0_NBYTES+12+4, FUNC(vxIntStackPtr) /* alloc */ movl FUNC(vxIntStackPtr), %eax /* get int-stack ptr */ leal 20(%esp), %ecx /* get addr of errno */ movl %ecx, ESF0_NBYTES+12(%eax) /* save the original ESP */ leal 12(%esp), %esi /* set the source addr */ movl %eax, %edi /* set the destination addr */ movl $ ESF0_NLONGS+3, %ecx /* set number of longs to copy */ cld /* set direction ascending order */ rep /* repeat next inst */ movsl /* copy ESF0_NLONGS + 3 longs */ popl %edi /* restore %edi */ popl %esi /* restore %esi */ popl %ecx /* restore %ecx */ movl %eax, %esp /* switch to the interrupt stack */ /* now, we are in the interrupt stack */#endif /* INT_STACK_USE */intEnt0: pushl ESF0_EFLAGS+12(%esp) /* push the saved EFLAGS */ popfl /* UNLOCK INTERRUPT */ popl %eax /* restore %eax */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * enter an interrupt handler. * * ALL registers must be saved. */ cmpl $0,FUNC(evtAction) /* is WindView on? */ je noIntEnt pushal /* save regs */ pushfl /* save EFLAGS */ cli /* LOCK INTERRUPTS */ movl 32+4(%esp),%edi /* use %edi to store the return address */ movl $ WV_CLASS_1_ON,%eax andl FUNC(wvEvtClass),%eax /* is event collection on? */ cmpl $ WV_CLASS_1_ON,%eax /* is event collection on? */ jne trgCheckIntEnt movl INT_CONNECT_CODE29(%edi), %eax /* get IRQ number */ addl $ MIN_INT_ID,%eax /* get event ID */ movl FUNC(_func_evtLogT0),%edx /* event log routine */ cmpl $0,%edx je trgCheckIntEnt pushl %eax call *%edx /* call event log routine */ addl $4,%esptrgCheckIntEnt: movl $ TRG_CLASS_1,%eax orl $ TRG_ON,%eax cmpl FUNC(trgEvtClass),%eax /* any trigger? */ jne intEntClean movl INT_CONNECT_CODE29(%edi), %eax /* get IRQ number */ addl $ MIN_INT_ID,%eax /* get event ID */ movl FUNC(_func_trgCheck),%edx /* triggering routine */ cmpl $0,%edx je intEntClean pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* obj */ pushl $ 0 /* TRG_CLASS1_INDEX */ pushl %eax /* push event ID */ call *%edx /* call triggering routine */ addl $32,%espintEntClean: popfl /* restore EFLAGS */ popal /* restore regs */noIntEnt: /* windview instrumentation - END */#endif /* WV_INSTRUMENTATION */ ret/********************************************************************************* intExit - exit an interrupt service routine** Check the kernel ready queue to determine if resheduling is necessary. If* no higher priority task has been readied, and no kernel work has been queued,* then we return to the interrupted task.** If rescheduling is necessary, the context of the interrupted task is saved* in its associated TCB with the PC, EFLAGS and EFLAGS retrieved from the * exception frame on the master stack.** This routine must be branched to when exiting an interrupt service routine.* This normally happens automatically, from the stub built by intConnect (2).** This routine can NEVER be called from C.** It can only be jumped to because a jsr will push a return address on the* stack.** SEE ALSO: intConnect(2)* void intExit ()* INTERNAL* This routine must preserve all registers up until the context is saved,* so any registers that are used to check the queues must first be saved on* the stack.** At the call to reschedule the value of taskIdCurrent must be in edx.*/ .balign 16,0x90FUNC_LABEL(intExit) popl FUNC(errno) /* restore errno */ pushl %eax /* push %eax onto the stack */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * log event if work has been done in the interrupt handler. * NOTE: a0 is still on the stack */ cmpl $0,FUNC(evtAction) /* is WindView on? */ je noIntExit pushl %edx pushl %ecx pushfl /* save EFLAGS */ cli /* LOCK INTERRUPTS */ movl $ WV_CLASS_1_ON,%eax andl FUNC(wvEvtClass),%eax /* is event collection on? */ cmpl $ WV_CLASS_1_ON,%eax /* is event collection on? */ jne trgCheckIntExit movl FUNC(_func_evtLogT0),%edx /* event log routine */ cmpl $0,%edx je trgCheckIntExit cmpl $0,FUNC(workQIsEmpty) /* work in work queue? */ jne intExitEvent pushl $ EVENT_INT_EXIT_K /* event id */ jmp intExitContintExitEvent: pushl $ EVENT_INT_EXIT /* event id */intExitCont: call *%edx /* call event log routine */ addl $4,%esp trgCheckIntExit: movl $ TRG_CLASS_1,%eax orl $ TRG_ON,%eax cmpl FUNC(trgEvtClass),%eax /* any trigger? */ jne intExitClean movl FUNC(_func_trgCheck),%edx /* triggering routine */ cmpl $0,%edx je intExitClean pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* obj */ pushl $ 0 /* TRG_CLASS1_INDEX */ cmpl $0,FUNC(workQIsEmpty) /* work in work queue? */ jne trgIntExitEvent pushl $ EVENT_INT_EXIT_K /* event id */ jmp trgIntExitConttrgIntExitEvent: pushl $ EVENT_INT_EXIT /* event id */trgIntExitCont: call *%edx /* call triggering routine */ addl $32,%espintExitClean: popfl /* UNLOCK INTERRUPTS */ popl %ecx /* restore regs */ popl %edxnoIntExit: /* windview instrumentation - END */#endif /* WV_INSTRUMENTATION */ cli /* LOCK INTERRUPTS */ decl FUNC(intCnt) /* decrement intCnt */ decl FUNC(intNest) /* decrement the private counter */ movl ESF0_CS+4(%esp),%eax /* if CS on stack is sysCsInt, */ cmpw FUNC(sysCsInt),%ax /* then we were in an ISR */ je intRte /* so just clean up/rte */#ifdef INT_STACK_USE /* * switch to the supervisor stack from the interrupt stack * * stack growth in the 1st interrupt * (supervisor stack) (interrupt stack) * ---------------------------------------------- * : +----- supervisor SP * ESF(12 bytes) | ESF(12 bytes) --- 1st int * errno <-----+ : errno / %eax --- 1st int * : : %eax * : : * V V * * stack growth in the 2nd interrupt * (supervisor stack) (interrupt stack) * ---------------------------------------------- * : +----- supervisor SP * ESF(12 bytes) | ESF(12 bytes) --- 1st int * errno <-----+ errno --- 1st int * : : * : ESF(12 bytes) --- 2nd int * : : errno / %eax --- 2nd int * V : %eax * : * V * */ cmpl $0,FUNC(vxIntStackEnabled) /* if vxIntStackEnabled == 0 then */ je intExit0 /* skip the interrupt stack switch */ cmpl $0, FUNC(intNest) /* is it nested interrupt ? */ jne intExit0 /* yes: goto intRteInt */ popl %eax /* restore %eax */ addl $ ESF0_NBYTES+12+4, FUNC(vxIntStackPtr) /* free */ movl ESF0_NBYTES(%esp), %esp /* switch to supervisor stack */ popl FUNC(errno) /* restore errno */ pushl %eax /* save %eax */#endif /* INT_STACK_USE */intExit0: cmpl $0,FUNC(kernelState) /* if kernelState == TRUE then */ jne intRte /* just clean up and rte */ movl FUNC(taskIdCurrent),%eax /* put current task in %eax */ cmpl FUNC(readyQHead),%eax /* compare to highest ready task */ je intRte /* if same then don't reschedule */ cmpl $0,WIND_TCB_LOCK_CNT(%eax) /* is task preemption allowed */ je saveIntContext /* if yes, then save context */ cmpl $0,WIND_TCB_STATUS(%eax) /* is task ready to run */ jne saveIntContext /* if no, then save context */intRte: popl %eax /* restore %eax */ iret /* UNLOCK INTERRUPTS *//* We are here if we have decided that rescheduling is a distinct possibility. * The context must be gathered and stored in the current task's tcb. * The stored stack pointers must be modified to clean up the stacks (SP). */ .balign 16,0x90saveIntContext: /* interrupts are still locked out */ movl $1,FUNC(kernelState) /* kernelState = TRUE; */ movl FUNC(taskIdCurrent),%eax /* tcb to be fixed up */ popl WIND_TCB_EAX(%eax) /* store %eax in tcb */ popl WIND_TCB_PC(%eax) /* save pc in tcb */ leal 4(%esp),%esp /* do not save %cs in tcb */ popl WIND_TCB_EFLAGS(%eax) /* save eflags in tcb */ sti /* UNLOCK INTERRUPTS */ /* interrupts unlocked and using master stack*/ movl %edx,WIND_TCB_EDX(%eax) /* save %edx */ movl %ecx,WIND_TCB_ECX(%eax) /* save %ecx */ movl %ebx,WIND_TCB_EBX(%eax) /* save %ebx */ movl %esi,WIND_TCB_ESI(%eax) /* save %esi */ movl %edi,WIND_TCB_EDI(%eax) /* save %edi */ movl %ebp,WIND_TCB_EBP(%eax) /* save %ebp */ movl %esp,WIND_TCB_ESP(%eax) /* save %esp */ movl FUNC(errno),%edx /* save errno */ movl %edx,WIND_TCB_ERRNO(%eax) movl %eax,%edx /* taskIdCurrent into %edx */ jmp FUNC(reschedule) /* goto rescheduler *//********************************************************************************* vxTaskEntry - task startup code following spawn** This hunk of code is the initial entry point to every task created via* the "spawn" routines. taskCreate(2) has put the true entry point of the* task into the tcb extension before creating the task,* and then pushed exactly ten arguments (although the task may use* fewer) onto the stack. This code picks up the real entry point and calls it.* Upon return, the 10 task args are popped, and the result of the main* routine is passed to "exit" which terminates the task.* This way of doing things has several purposes. First a task is easily* "restartable" via the routine taskRestart(2) since the real* entry point is available in the tcb extension. Second, the call to the main* routine is a normal call including the usual stack clean-up afterwards,* which means that debugging stack trace facilities will handle the call of* the main routine properly.** NOMANUAL* void vxTaskEntry ()*/ .balign 16,0x90FUNC_LABEL(vxTaskEntry) xorl %ebp,%ebp /* make sure frame pointer is 0 */ movl FUNC(taskIdCurrent),%eax /* get current task id */ movl WIND_TCB_ENTRY(%eax),%eax /* entry point for task is in tcb */ call *%eax /* call main routine */ addl $40,%esp /* pop args to main routine */ pushl %eax /* pass result to exit */ call FUNC(exit) /* gone for good *//********************************************************************************* windIntStackSet - set the interrupt stack pointer** This routine sets the interrupt stack pointer to the specified address.* It is only valid on architectures with an interrupt stack pointer.* For I80X86, the switch to/from the interrupt stack is done by software.** NOMANUAL* void windIntStackSet (pBotStack)* char *pBotStack; /* pointer to bottom of interrupt stack **/ .balign 16,0x90FUNC_LABEL(windIntStackSet) movl SP_ARG1(%esp), %eax /* get pBotStack */ movl %eax, FUNC(vxIntStackPtr) /* set it to vxIntStackPtr */ ret/********************************************************************************* intStackEnable - enable the interrupt stack usage** This routine enables the interrupt stack usage.* This routine is only callable from the task level, returns ERROR otherwise.* The interrupt stack usage is disabled in the default configuration * for the backward compatibility.** RETURNS: OK, or ERROR if it is not in the task level.* STATUS intStackEnable * (* BOOL enable /@ TRUE to enable, FALSE to disable @/* )*/ .balign 16,0x90FUNC_LABEL(intStackEnable) movl %cs, %eax cmpl FUNC(sysCsSuper), %eax /* is the CS for the task level? */ jne intStackEnableError /* no: return ERROR */ xorl %eax, %eax /* zero for OK */ movl SP_ARG1(%esp), %edx /* get & set the parameter */ /* next "movl" instruction is atomic, so no intLock/Unlock is needed */ movl %edx, FUNC(vxIntStackEnabled) retintStackEnableError: movl $ ERROR, %eax ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -