SS/ESP on stack after interrupt
SS/ESP on stack after interrupt
Is there a way of forcing the processor to always put SS/ESP on the stack during an interrupt and than an IRET popping this??
I have software task switching working (well!!) but I wan't to have separate stacks for each thread.
According the the intel manuals it will put ss/esp during a privilige level change but is there a way of forcing this?? (Maybe using a different descriptor type?)
Thanks.
I have software task switching working (well!!) but I wan't to have separate stacks for each thread.
According the the intel manuals it will put ss/esp during a privilige level change but is there a way of forcing this?? (Maybe using a different descriptor type?)
Thanks.
Re:SS/ESP on stack after interrupt
Hello
I think there is a very easy way to force the processor to always push ss and esp on the stack: Run only your kernel in ring 0 and all other processes run in ring 3 to 1. But I think there is no way to force the processor to push esp and ss if there is a task-switch within the same privilege level. I have never heart about that. Correct me if I'm wrong!
Another way to do this is using Task State Segments.
I think there is a very easy way to force the processor to always push ss and esp on the stack: Run only your kernel in ring 0 and all other processes run in ring 3 to 1. But I think there is no way to force the processor to push esp and ss if there is a task-switch within the same privilege level. I have never heart about that. Correct me if I'm wrong!
Another way to do this is using Task State Segments.
Re:SS/ESP on stack after interrupt
There's no way of forcing the CPU to use the same stack frame for all privilege level transitions. However, this isn't much of a problem since the CPU always removes everything it's put on the stack (except the error code).
How could a system without separate stacks for each thread work? This is the whole point of threads: to give each thread its own context (registers) and stack (local variables). This applies to both the user-mode and kernel-mode stacks (you want to separate threads in kernel mode, too).
How could a system without separate stacks for each thread work? This is the whole point of threads: to give each thread its own context (registers) and stack (local variables). This applies to both the user-mode and kernel-mode stacks (you want to separate threads in kernel mode, too).
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:SS/ESP on stack after interrupt
no, no way to enforce this (at least about IRQ) unless you CLI your whole kernel (what you probably don't want : the kernel will not be preemptible anymore ...)
the only case when SS/ESP is pushed is when a ring-crossing occurs (not necessarily from ring 3, but also from ring 2 or 1) to handle the interrupt.
the only case when SS/ESP is pushed is when a ring-crossing occurs (not necessarily from ring 3, but also from ring 2 or 1) to handle the interrupt.
Re:SS/ESP on stack after interrupt
Um, this is what I thought.
My kernel is going to be heavily threaded, with worker threads for most devices and fs for a start, but I don't want them bumping into each others stacks.
Maybe I should force a stack reload with each switch to a kernel thread, that might do it, but a little clumsy.
My kernel is going to be heavily threaded, with worker threads for most devices and fs for a start, but I don't want them bumping into each others stacks.
Maybe I should force a stack reload with each switch to a kernel thread, that might do it, but a little clumsy.
Re:SS/ESP on stack after interrupt
If you think about it, this isn't a problem.
Potential problem: CPU doesn't grab SS0:ESP0 from the current TSS on a ring0->ring0 interrupt.
CPU pushes its registers onto the current stack. Your ISR pushes the other registers onto the current stack and reschedules. The ISR switches stacks (mov esp, xxx), pops the context and returns to a new thread.
All that has happened when switching between two kernel threads is that the context (registers) has been saved on the same stack as the local variables; the user-mode stack doesn't get touched.
For a while I thought that threading in ring 0 would require special treatment, because of the different stack frames, but it doesn't.
Potential problem: CPU doesn't grab SS0:ESP0 from the current TSS on a ring0->ring0 interrupt.
CPU pushes its registers onto the current stack. Your ISR pushes the other registers onto the current stack and reschedules. The ISR switches stacks (mov esp, xxx), pops the context and returns to a new thread.
All that has happened when switching between two kernel threads is that the context (registers) has been saved on the same stack as the local variables; the user-mode stack doesn't get touched.
For a while I thought that threading in ring 0 would require special treatment, because of the different stack frames, but it doesn't.
Re:SS/ESP on stack after interrupt
My only worry is this (A and B are ring 0 threads)..
1. Thread A executing.
2. IRQ 0 timer interrupt occurs, kernel switches threads
3. Thread B executing, calls a procedure dumping call data on stack
4. Task switch occurs back to thread A
5. Bamn..stack clobbered
Unless, I have mechanism where a task switch can not occur during kernel threads (which I think linux does) then the stack could be left in an unexpected state.
Unless I have this all wrong of course?!!
1. Thread A executing.
2. IRQ 0 timer interrupt occurs, kernel switches threads
3. Thread B executing, calls a procedure dumping call data on stack
4. Task switch occurs back to thread A
5. Bamn..stack clobbered
Unless, I have mechanism where a task switch can not occur during kernel threads (which I think linux does) then the stack could be left in an unexpected state.
Unless I have this all wrong of course?!!
Re:SS/ESP on stack after interrupt
Can't you just have all threads use the same stack and partition the stack by assigning each a base ESP? Then on a thread switch you deliberately load the ESP with the reference for that particular thread's stack.
Difficult for me to explain, not sure if I've got it clear in my head myself .
Eg Process A has a stack of base 0 and limit FFFF (Just some values to work with, they have no significance)
Thread 1 stack starts at 1000
Thread 2 stack starts at 2000
...etc
Now when thread 2 dumps variables into the stack it doesn't matter, because it's dumping into an area unoccupied by thread 1's stack so when the timer switches threads and loads thread 1's stack pointer into ESP everything is fine. So long as none of the threads go beyond their personal stack area everything will run nicely and they all run in the same segment so no selector loads are required. Of course this allows a malicious thread to trash another thread's stack, so it needs some design problems sorting out, but in theory it could work I think (If not please tell me why not, I haven't looked deeply at threading yet so I'd really like to know).
Curufir
Difficult for me to explain, not sure if I've got it clear in my head myself .
Eg Process A has a stack of base 0 and limit FFFF (Just some values to work with, they have no significance)
Thread 1 stack starts at 1000
Thread 2 stack starts at 2000
...etc
Now when thread 2 dumps variables into the stack it doesn't matter, because it's dumping into an area unoccupied by thread 1's stack so when the timer switches threads and loads thread 1's stack pointer into ESP everything is fine. So long as none of the threads go beyond their personal stack area everything will run nicely and they all run in the same segment so no selector loads are required. Of course this allows a malicious thread to trash another thread's stack, so it needs some design problems sorting out, but in theory it could work I think (If not please tell me why not, I haven't looked deeply at threading yet so I'd really like to know).
Curufir
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:SS/ESP on stack after interrupt
Say Task A is on SSa (current stack segment): ESP0a (stack entry point for system calls & interrupt from ring3): ESPa(current stack pointer),DarylD wrote:
Unless, I have mechanism where a task switch can not occur during kernel threads (which I think linux does) then the stack could be left in an unexpected state.
Unless I have this all wrong of course?!!
And say task B is on SSb, ESP0b, ESPb
when your thread A is interrupted by the IRQ0, we have
Code: Select all
SSa[ESPa--] = current flags
SSa[ESPa--] = current CS
SSa[ESPa--] = current eip
... your handler is called ...
Code: Select all
pusha
mov eax, [current_TSS.ESP0]
mov [threadA_context.esp0],eax
mov [threadA_context.ss],ss
mov [threadA_context.esp],esp
lss esp,[threadB_context.esp]
mov eax,[threadB_context.esp0]
mov [currentTSS.ESP0],eax
popa
ret
Then, the next thread's stack context is restored with LSS operation (loads SS and ESP atomically). Once this has been issued, we're in the next thread, but with corrupted registers value (only SS & ESP are valid), so we just POP all the registers we saved the last time we left B...
I don't see any problem with that mechanism... It works fine in Clicker from about 2 monthes ...
Re:SS/ESP on stack after interrupt
Same here. Mobius has user and kernel threads and either can be interrupted and switched at any time.I don't see any problem with that mechanism... It works fine in Clicker from about 2 monthes ...
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:SS/ESP on stack after interrupt
In fact, what happens is that any thread (in virtually every OS i know) has 2 stacks : its user stack (at DPL3) and its kernel stack (protected at DPL0) ... The task switch always occurs between 2 kernel stacks because only the kernel can sleep/wakeup/preempt user threads...
Re:SS/ESP on stack after interrupt
I think I see what you mean now, I will have a go when I get home tonight and see what happens with my code and the stack.
Although I am still tempted to just make kernel threads non-preemtible, as long as they execute quickly it shouldn't be a problem.
In my design kernel calls just drop a request into a queue which is then picked up by a worker thread, so most only execute for very short periods, so pre-empting kernel threads should not be necessary.
I will keep all informed.
Although I am still tempted to just make kernel threads non-preemtible, as long as they execute quickly it shouldn't be a problem.
In my design kernel calls just drop a request into a queue which is then picked up by a worker thread, so most only execute for very short periods, so pre-empting kernel threads should not be necessary.
I will keep all informed.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:SS/ESP on stack after interrupt
most kernels that were firstly built on non-preemptible kernel threads finally moved to preemptible, but with harder effort than if they were built fully-preemptible from start.
Look at Linux: it start moving to preemption with 2.2.x (iirc), and finally get it with 2.4.x ...
Having a non-preemptible kernel will mean that you will not be able to do complex tasks (and memory management sometimes include complex tasks) without disminishing the whole system's responsiveness ...
better think about it
Look at Linux: it start moving to preemption with 2.2.x (iirc), and finally get it with 2.4.x ...
Having a non-preemptible kernel will mean that you will not be able to do complex tasks (and memory management sometimes include complex tasks) without disminishing the whole system's responsiveness ...
better think about it
Re:SS/ESP on stack after interrupt
More importantly, as long as you have a non-preemptable kernel, you can't take advantage of multiple CPUs.
Re:SS/ESP on stack after interrupt
Doesn't Linux use multiple task selectors to handle multiple cpus?
If that's the case couldn't you get away with it being non-premptive so long as a thread could be guaranteed never to be run by two different cpus at the same time?
Curufir
If that's the case couldn't you get away with it being non-premptive so long as a thread could be guaranteed never to be run by two different cpus at the same time?
Curufir