I'm currently working on process management and therefore wondering about the order of stuff which is pushed by the CPU on a interrupt. What *is* pushed on the stack? I know that eflags, cs and eip are pushed onto the stack - what about an error code - is it also pushed onto the stack, if yes in which order?
best regards and thanks,
.abless
Stack context
Re:Stack context
I am also at this stage but since I have just been trying to finish Starcraft brood war for 10th or 11th time I can just not proceed, anyway enough chatting I will try to answer question hoping I am clear. Basic mentality of cpu while preparing stack for interrupt procedure is:
if(privilege transition)
{
if(exception)
{
push 16 bits of 0
push ss //->16 bit
push esp //->32 bit
push eflags //->32 bit
push 16 bits of 0
push cs //->16 bit
push eip //->32 bit
push errorCode //->32 bit
}
else // ->no exception
{
push 16 bits of 0
push ss //->16 bit
push esp //->32 bit
push eflags //->32 bit
push 16 bits of 0
push cs //->16 bit
push eip //->32 bit
}
}
else //->no privilege transition
{
if(exception)
{
push eflags //->32 bit
push 16 bits of 0
push cs //->16 bit
push eip //->32 bit
push errorCode //->32 bit
}
else // ->no exception
{
push eflags //->32 bit
push 16 bits of 0
push cs //->16 bit
push eip //->32 bit
}
}
These push 16 bit 0 means that since cs and ss are 16 bit values, these 16 bits before cs and ss are there without any meaning.
if(privilege transition)
{
if(exception)
{
push 16 bits of 0
push ss //->16 bit
push esp //->32 bit
push eflags //->32 bit
push 16 bits of 0
push cs //->16 bit
push eip //->32 bit
push errorCode //->32 bit
}
else // ->no exception
{
push 16 bits of 0
push ss //->16 bit
push esp //->32 bit
push eflags //->32 bit
push 16 bits of 0
push cs //->16 bit
push eip //->32 bit
}
}
else //->no privilege transition
{
if(exception)
{
push eflags //->32 bit
push 16 bits of 0
push cs //->16 bit
push eip //->32 bit
push errorCode //->32 bit
}
else // ->no exception
{
push eflags //->32 bit
push 16 bits of 0
push cs //->16 bit
push eip //->32 bit
}
}
These push 16 bit 0 means that since cs and ss are 16 bit values, these 16 bits before cs and ss are there without any meaning.
Re:Stack context
I'd like to add to the original question!
In the TSS, ESP0 and SS0 hold the kernel stack address for level 0.
Now if we are using stack based task switching, when an interrupt (timer int) occurs we are supposed to push the registers on to the processes stack, get the next process and then pop the registers of the new process' stack.
the problem is, if on the Interrupt the CPU loads SS0:ESP0 for the stack pointers, wouldn't the registers pushed onto the stack be on the SYSTEM stack instead of the PROCESS stack?
In the TSS, ESP0 and SS0 hold the kernel stack address for level 0.
Now if we are using stack based task switching, when an interrupt (timer int) occurs we are supposed to push the registers on to the processes stack, get the next process and then pop the registers of the new process' stack.
the problem is, if on the Interrupt the CPU loads SS0:ESP0 for the stack pointers, wouldn't the registers pushed onto the stack be on the SYSTEM stack instead of the PROCESS stack?
Re:Stack context
By the way, does a stack switch occur when an interrupt (trap gate) occurs? I mean are the values pushed on the kernel's stack or on the current task's stack?
Re:Stack context
Yes, code slasher, this is by decision.
For instance if an exception occurs (i.e page fault) the ring 0 stack is used because we can not guarantee that a user stack is valid or even exists, this would cause a triple fault (reset).
You just need a ring 0 stack for each process, or have a reliable method of sharing one stack.
Daryl.
For instance if an exception occurs (i.e page fault) the ring 0 stack is used because we can not guarantee that a user stack is valid or even exists, this would cause a triple fault (reset).
You just need a ring 0 stack for each process, or have a reliable method of sharing one stack.
Daryl.
Re:Stack context
Does this mean that I have to set up a TSS and load it (ltr) even if I don't use user processes but kernel processes. Note that my kernel processes don't use the kernel stack but their own stack, allocated by malloc().
Re:Stack context
Not if it is only running kernel tasks. You don't need one because no DPL changes are likely to occur.
One per processor is the minimum really when using user tasks.
I have only one TSS setup for my kernel, which is currently only running kernel tasks. Although I am not actually using the TSS yet. Its just there in place for when I start using ring 3 tasks.
Daryl.
One per processor is the minimum really when using user tasks.
I have only one TSS setup for my kernel, which is currently only running kernel tasks. Although I am not actually using the TSS yet. Its just there in place for when I start using ring 3 tasks.
Daryl.
Re:Stack context
Hi,
okay Daryl. If it have interrupt gates for some interrupts and task gates for the exceptions, then according to my understanding of the intel docs, only the task gates will cause the stack to be loaded with SS0:SP0. the interrupt gates won't change the stack (as i'm tying this I'm doubting my reasoning already :-[) or am I wrong? Okay, if the stack is changed on change from ring 3 to ring 0, how would we use the TIMER int to save registers on the running process' stack?
okay Daryl. If it have interrupt gates for some interrupts and task gates for the exceptions, then according to my understanding of the intel docs, only the task gates will cause the stack to be loaded with SS0:SP0. the interrupt gates won't change the stack (as i'm tying this I'm doubting my reasoning already :-[) or am I wrong? Okay, if the stack is changed on change from ring 3 to ring 0, how would we use the TIMER int to save registers on the running process' stack?
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Stack context
the interrupt gates won't change the stack (as i'm tying this I'm doubting my reasoning already ) or am I wrong? Okay, if the stack is changed on change from ring 3 to ring 0, how would we use the TIMER int to save registers on the running process' stack?[/quote ]
Each process usually has its own user stack and its own kernel stack. When an IRQ is received while in user mode, the user stack is left unmodified. The processor load SS<-SS0 and SP<-ESP0 and then pushes the old values of ESP and SS on that kernel stack. Any register saving is made on the kernel stack before you start processing the interrupt.
If a software stack-switching is to be performed, you just need to remind where on the kernel stack you were: the rest of the state is located on that kernel stack and will be resumed as POPs goes on once the task is switched-back.