.file "cpu_context_switch.S" .text .globl cpu_context_switch .type cpu_context_switch, @function cpu_context_switch: // arg2= to_context -- esp+68 // arg1= from_context -- esp+64 // caller ip -- esp+60 pushf // (eflags) esp+56 pushl %cs // (cs) esp+52 pushl $resume_pc // (ip) esp+48 pushl $0 // (error code) esp+12+8x4 pushal // (general reg) esp+12 subl $2, %esp // (alignment) esp+10 pushw %ss // esp+8 pushw %ds // esp+6 pushw %es // esp+4 pushw %fs // esp+2 pushw %gs // esp /* * Now that the original eax/ebx are stored, we can use them safely */ /* Store the address of the saved context */ movl 64(%esp), %ebx movl %esp, (%ebx) /* This is the proper context switch ! We change the stack here */ movl 68(%esp), %esp /* Restore the CPU context */ popw %gs popw %fs popw %es popw %ds popw %ss addl $2,%esp popal addl $4, %esp /* Ignore "error code" */ /* This restores the eflags, the cs and the eip registers */ iret /* equivalent to: popfl ; ret */ resume_pc: // Same context as that when cpu_context_switch got called // arg2= to_context -- esp+8 // arg1= from_context -- esp+4 // caller ip -- esp ret /* ------------------------- */ .globl cpu_context_exit_to .type cpu_context_exit_to, @function cpu_context_exit_to: // arg3= reclaiming_arg -- esp+12 // arg2= reclaiming_func -- esp+8 // arg1= to_context -- esp+4 // caller ip -- esp /* Store the current SP in a temporary register */ movl %esp, %eax /* This is the proper context switch ! We change the stack here */ movl 4(%eax), %esp /* Call the reclaiming function (remember: the old frame address is stored in eax) */ pushl 12(%eax) call *8(%eax) addl $4, %esp /* Restore the CPU context */ popw %gs popw %fs popw %es popw %ds popw %ss addl $2,%esp popal addl $4, %esp /* Ignore "error code" */ /* This restores the eflags, the cs and the eip registers */ iret /* equivalent to: popfl ; ret */