I'm back. I got frustrated, and had to take some time off of this project for a while. I had stared too long then I ended up having to reinstall my system... so you get the picture. Haha
Anyways, since then, I have rewritten Multitasking code with a simpler concept. I was having problems, and so I decided to dump the priorities until I get a better grasp on what exactly I'm doing wrong. So right now, I just have a one priority, and an idle task. As simple as you can get (aside from monotasking )
Well, my scheduler is actually working. It switches task, and I have also written a nice little set of console buffer functions so each task has it's own buffer, and can flush it whenever it likes, but I run into a problem after the first task switch. I realized that errors were stemming from the fact that all my tasks were using the same stack! I have my register state set up correctly (I have checked it in the debugger) and I even check the register structure passed to my IRQ handler that it's value is getting set and it is. Everything is set correctly, but IRET isn't popping ESP (and therefore SS either). When I return to a task, if I break, and dump a backtrace with GDB I get:
#1 0xb0000000 in ?? ()
and of course #0 is the current frame. So I have concluded that IRET isn't popping ESP, and leaving it on the stack. Anybody have any more ideas on why it would do this? My understanding is that IRET does this:
pop eip
pop cs
pop eflags
pop esp
pop ss
I have done searching but found nothing on this being a problem, so either I'm doing something wrong or there is a common solution that I'm missing. lol
EDIT:
well right as I posted this, I switched tabs to read a page I had just opened (the tech. specs. of IRET/IRETD) and it seems IRET only pops ESP/SS if there is a privilege change! Anybody know how to get around that??? Or a better way to switch the stacks? I can't think of one off the top of my head, but I will be trying... lol
[SOLVED] IRET only pops SS:ESP on privilege change?
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: IRET only pops SS:ESP on privilege change?
If what you need is ESP to change, just MOV ESP, something
Re: IRET only pops SS:ESP on privilege change?
Okay but with something like this:
(P.S. assuming 'task' is not a stack variable )
then the IRQ stub would pop everything like normal and the stack should be left like the user wanted it, but what about SS and ESP? I can't remove them from the stack before IRET since sometimes they will be needed, but I can't remove them after since I will then be in the other task.
Code: Select all
switch_page_directory(task->dir); // switch to the new tasks directory
task->regs->useresp += sizeof(registers_t); // Offset the stack pointer
memcpy(task->regs->useresp, task->regs, sizeof(registers_t)); // Fill the stack with the data that the IRQ stub needs
set_esp(task->regs->useresp); // switch to the new stack
return;
then the IRQ stub would pop everything like normal and the stack should be left like the user wanted it, but what about SS and ESP? I can't remove them from the stack before IRET since sometimes they will be needed, but I can't remove them after since I will then be in the other task.
Re: IRET only pops SS:ESP on privilege change?
It's not a problem in practice once your system is running because interrupts (syscalls, faults etc.) only push ss and esp on privilege change. So the processor ensures that the stack is always correct.
If a trainstation is where trains stop, what is a workstation ?
Re: IRET only pops SS:ESP on privilege change?
I think this all stems from trying to allow processes to run in ring 0... I just wanted to see my process running without having to setup syscalls just yet... lol is it possible without doing some odd stuff to have ring 0 processes? Because if the process is ring 0 then tss->esp0 won't be loaded, and the old esp value won't be pushed. Aside from having specific statements only for ring 0 tasks (seeing if the task was ring zero, then figuring the stack pointer from it's current value, and fixing other things if any that got messed up since it didn't use the esp0 stack), I don't see a way of doing it. Plus, you would have to have 2 ways of switching tasks. Because if the task you are switching TO is a user task, iret will pop ESP. So you would need another special case for ring 0 tasks. If it is a Ring0 task, copy return data to it's stack, switch stack pointers manually, then iret. It just seems like a lot of little 'hacks' (I know technically not hacks if I'm writing the system but still) just for this.
Will ring 0 tasks ever be needed? With my old setup, it should work just fine with ring3 or even ring1/2 (in theory). If all my functions are provided through syscalls, it shouldn't be a big deal (atleast not in my head lol).
Will ring 0 tasks ever be needed? With my old setup, it should work just fine with ring3 or even ring1/2 (in theory). If all my functions are provided through syscalls, it shouldn't be a big deal (atleast not in my head lol).
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: IRET only pops SS:ESP on privilege change?
You're seeing ghosts.
If you interrupt ring 0, push all registers then save the stackpointer you have everything you need on the stack to resume a ring 0 task. You have eax/ebx/ecx/edx/esi/edi/ebp using pusha, you have the original esp which is the current esp + 44, and you have the original eip and eflags on the interrupt frame. CS is duplicated (does not change on iret), SS is not needed since it doesn't change either.
If you interrupt ring 3, push all registers, then save the stackpointer you have everything to resume a userland task. The only difference is that the task's backed up esp is now stored in the interrupt frame instead of as a function of the current esp.
If you set a stackpointer saved previously, pop all registers, then iret, you resume a task if the original was in ring 0, and with no change in code you can resume a task in ring 3 as well.
If you interrupt ring 0, push all registers then save the stackpointer you have everything you need on the stack to resume a ring 0 task. You have eax/ebx/ecx/edx/esi/edi/ebp using pusha, you have the original esp which is the current esp + 44, and you have the original eip and eflags on the interrupt frame. CS is duplicated (does not change on iret), SS is not needed since it doesn't change either.
If you interrupt ring 3, push all registers, then save the stackpointer you have everything to resume a userland task. The only difference is that the task's backed up esp is now stored in the interrupt frame instead of as a function of the current esp.
If you set a stackpointer saved previously, pop all registers, then iret, you resume a task if the original was in ring 0, and with no change in code you can resume a task in ring 3 as well.
Re: IRET only pops SS:ESP on privilege change?
You are very correct. I just went back, stopped thinking, and took your suggestion and it works! My thread sleeping needs a little work, but it's switching fine, and no errors! I can have both tasks run, print to their console and then flush with no problems I need to go fix my semaphores now though