Hi,
I'm quite a newbie to OS programming, and tried to get a context switch (on x86) to work. My "context switch" (for now) works like this:
1. Push EIP and EBP to the (current) stack.
2. Save the current ESP in the current process's structure
3. Load the ESP of the context to switch to from that process's structure
4. Pop EBP & EIP from the stack (we just switched to)
5. jmp to the EIP just popped
Since I don't have any "userspace" yet, I don't have to mess with changing segments or the TSS (at least I think so). Now my problem is: After the first context switch, my interrupts just stop firing. The Interrupt Enable flag is still set, the timer interrupt is not being masked out, the IDT has not been overwritten...
From what I found by searching, I think that "usually", iret is used to perform context switches - is that correct? Is that perhaps the flaw? In the Sections of the Intel Developer's Manual that I read they were only talking about using iret for returning from procedures, so I think this is nothing more than a shortcut for popping certain values from the stack and restoring these registers - or are there any sideeffects in using iret instead of unsing pop and moving the stuff into the registers by hand?
Or do I perhaps have to restore anything beyond ESP, EBP and EIP? I mean, of course I know that there is a lot more to do, like CR3, Segments, TSS, etc., but since I'm not switching between user- and kernelspace, or even different "processes" (everything runs directly within the kernel), Paging, Segments and the TSS should not have to change, right?
I mean, it could very well be that I trash some stack or whatever by context switching (as I said, I'm quite new to OS and *that* low-level programming, and I messed a lot with that code lately to get it running...), but then at least the interrupts should fire (and produce some page fault or whatever).
Context switch disabling interrupts
Re: Context switch disabling interrupts
You should use iret to switch to the new context because iret is used to return from an interrupt and your context switch code is triggered by an interrupt all the time. Apart from this, you have to use iret because the CPU will push some more registers to the stack when an interrupt is fired (at least EFLAGS, CS and EIP) and you have to remove these values from the stack when you return from the interrupt, otherwise the size of the available stack will decrease every time the timer interrupt is fired. The iret instruction will do this for you
So the context switching should look something like this:
1. Timer interrupt is fired (EFLAGS, CS and EIP is pushed to the stack)
2. Save the current ESP to the process's structure.
3. Load the ESP of the new process.
4. Execute iret
Note that you also have to save any other register (general purpose registers, segment registers, etc.)
giszo
So the context switching should look something like this:
1. Timer interrupt is fired (EFLAGS, CS and EIP is pushed to the stack)
2. Save the current ESP to the process's structure.
3. Load the ESP of the new process.
4. Execute iret
Note that you also have to save any other register (general purpose registers, segment registers, etc.)
giszo
- xenos
- Member
- Posts: 1121
- Joined: Thu Aug 11, 2005 11:00 pm
- Libera.chat IRC: xenos1984
- Location: Tartu, Estonia
- Contact:
Re: Context switch disabling interrupts
Do you notify (i.e. send an EOI to) the PIT at the end of of your interrupt handler?
Re: Context switch disabling interrupts
Aww.. i knew that I missed something, thanks. I'll try as soon as I'm home (my build & test-system at work isn't that stable and fun to work with).XenOS wrote:Do you notify (i.e. send an EOI to) the PIT at the end of of your interrupt handler?
@giszo:
Well, I actually use iret, but not to switch contexts. It works like this:
1.) The timer interrupt is received, CPU pushes lots of stuff to the stack, additional stuff is pushed to the (kernel-)stack by pusha, etc.
2.) The timer interrupt calls a scheduling function. This scheduling function pushes EIP and EBP to the kernel stack.
3.) The scheduling function switches to the next task
Now of course on the kernel stack of the context we just left there is all that stuff pushed by the interrupt. Now, when execution returns to this process, it goes like this:
4.) ESP is being switched back to our stack, EBP and EIP are being popped of and loaded (EIP via jmp)
5.) Now we're "back" in the scheduling function of the process we left in 3
6.) The function (and the functions that leaded to calling this function) return, up to the assembler "function" that was initially called by the interrupt
6.) At the end of that function, there is an iret, returning back to "userspace" (no, there is no userspace, but to the non-kernel-stack of the process...)
As you see, the stuff pushed to the stack by the intterupt is being cleaned, but not at the time the context is switched. Or am I doing something wrong here?