Page 1 of 1
TSS, CPL, paging -- add them together and I am confused
Posted: Sat Jul 09, 2005 9:20 pm
by cabron
Hi,
I have a software task switch / paging situation going on, and it seems to work fine when CPL = 0 everywhere. Every context switch I update the TSS's esp0 and cr3 fields.
There are a few issues, and a few things that confuse me.
First, I can start a CPL = 3 task, but when I switch to it, IRQs no longer get handled and INT instructions lock the machine. Did I do something wrong with the IDT? Do I need a separate segment for handling interrupts?
Secondly... I am a little confused about how CR3 changes fit into the task switch picture. When I update the TSS's cr3 field and iret, it doesn't take effect. I have to load CR3 before iret. But that means I have to map the kernel and the kernel stack into the process's CR3. I don't want to do this. Is there something I'm missing? Am I approaching the thing just plain wrongly?
Re:TSS, CPL, paging -- add them together and I am confused
Posted: Sat Jul 09, 2005 11:40 pm
by Brendan
Hi,
cabron wrote:I have a software task switch / paging situation going on, and it seems to work fine when CPL = 0 everywhere. Every context switch I update the TSS's esp0 and cr3 fields.
There are a few issues, and a few things that confuse me.
First, I can start a CPL = 3 task, but when I switch to it, IRQs no longer get handled and INT instructions lock the machine. Did I do something wrong with the IDT? Do I need a separate segment for handling interrupts?
Secondly... I am a little confused about how CR3 changes fit into the task switch picture. When I update the TSS's cr3 field and iret, it doesn't take effect. I have to load CR3 before iret. But that means I have to map the kernel and the kernel stack into the process's CR3. I don't want to do this. Is there something I'm missing? Am I approaching the thing just plain wrongly?
You must change CR3 yourself during your software task switch. You also must map some things into all address spaces. Things that must be mapped into the address spaces include the GDT, IDT, TSS, and the thread's kernel stack (and it's CPL=3 stack). In addition to this you'd need the code for the kernel's API entry point and all IRQ handlers.
For this reason most OS's map the entire kernel in every address space - usually using the highest 1 GB or 2 GB, leaving the remaining 3 GB or 2GB for the CPL=3 code & data.
If you're willing to have reduced performance, you can put the GDT, IDT, TSS and a minimal "stub" into every address space, and then for each IRQ or kernel API function switch the address space to the kernel's address space and then switch back again. This can result in using around 16 KB of each CPL=3 address space, but it's complex/messy and those address space switches do effect performance.
I assume your problems with IRQs and software INTs come from not having the IDT and interrupt handlers in the address space at the time - you should get a triple fault for any IRQ or software interrupt if this is the case.
Cheers,
Brendan
Re:TSS, CPL, paging -- add them together and I am confused
Posted: Sun Jul 10, 2005 12:09 am
by cabron
Okay, thanks for the tips.
Brendan wrote:
I assume your problems with IRQs and software INTs come from not having the IDT and interrupt handlers in the address space at the time - you should get a triple fault for any IRQ or software interrupt if this is the case.
Nope. I mapped the whole kernel. And an identical process (with the same CR3) works fine if it runs in ring 0. So I wonder if maybe I'm specifying something wrong in a descriptor, or misunderstanding the TSS concept, or what...
Re:TSS, CPL, paging -- add them together and I am confused
Posted: Sun Jul 10, 2005 1:46 am
by AR
The TSS' SS0 and ESP0 are the only fields that are used (unless you long jump to the TSS descriptor to start the scheduler, then every field is used once). Do you change DS, ES, FS, GS and SS to Ring3 segments? Did you set "supervisor" on all the kernel pages but then try to read them directly in the program?
Re:TSS, CPL, paging -- add them together and I am confused
Posted: Sun Jul 10, 2005 4:36 am
by cabron
All the segments are RPL 3 and the ring 3 code only touches user pages. Even if I try to run a process that is just "jmp $" in CPL 3 it doesn't get the timer interrupt.
I'm thinking that it's probably something wrong with my segment/interrupt descriptors.. I find it hard to figure out which bit goes where with some of these structures, even when I have the manual right in front of me.
Trouble is, I've been looking at those flags a lot and I'm unable to find a problem.
Re:TSS, CPL, paging -- add them together and I am confused
Posted: Sun Jul 10, 2005 4:48 am
by AR
Do you change EFLAGS anywhere? (eg. PUSH 0; POPF; Or jump to the TSS to start the scheduler without setting the EFLAGS field)?
I suspect that you've turned IF off in your task setup/switching code.
Re:TSS, CPL, paging -- add them together and I am confused
Posted: Sun Jul 10, 2005 5:01 am
by Brendan
Hi,
Another possibility would be forgetting to tell the CPU where the TSS is - you'd need to use the "LTR" instruction for this..
Cheers,
Brendan
Re:TSS, CPL, paging -- add them together and I am confused
Posted: Sun Jul 10, 2005 5:20 am
by cabron
Nope. EFLAGS has IF set and I have ltr'd the TSS.
Sigh. I suspect I'm making some stupid mistake somewhere. Reading the manuals...
Re:TSS, CPL, paging -- add them together and I am confused
Posted: Sun Jul 10, 2005 9:02 am
by cabron
All right, I found the problem. I accidentally gave TSS->ss0 the wrong segment. Told you it would be something stupid.
It works now.
Thanks for your input, guys.