Context Switching

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
spix
Member
Member
Posts: 128
Joined: Mon Jun 26, 2006 8:41 am
Location: Millicent, South Australia
Contact:

Context Switching

Post by spix »

Hi

I'm trying to write a system call that will demote the running task from ring 0 to ring 3.

I have one TSS descripter and have software task switching that works when just switching between ring 0 tasks.

I can fork() from my kernel proc, but i want to demote it to ring 3, so I do a system call, change the CS, DS ES... to the User mode ones, (my interrupt handlers pass these values as a structure, then I return (iret) from the system call.

However I get a GPF because the CS is wrong, the DS, ES and so on are correct, but the eip, cs & eflags are wrong (it appears that the system has inserted these 3 values, as after these three values are the correct values..

Am I missing something? Is there more I have to change in my demote syscall? I have read the Context Switching FAQ, but can't seem to figure this out.

my isr looks like this:

Code: Select all

syscall_irq:
   cli
   push byte 0

   push byte 48
   jmp irq_common_stub


extern irq_handler

extern current
extern morts_tss

irq_common_stub:
   cld
   pushad
   push ds
   push es
   push fs
   push gs

        mov eax,[current] 
        mov [eax],esp 

   mov eax, 0x10
   mov ds, eax
   mov es, eax
   mov fs, eax
   mov gs, eax

   push esp
   call irq_handler

        mov eax,[current] ;put adress of struct of current process in eax.
        mov esp,[eax] ;restore adress of esp.

   mov ebx,[eax+8];put content of the k-stack field into ebx.
        mov [morts_tss+4],ebx ;update system tss. (esp)

   mov ebx, [eax+4]
   mov [morts_tss+8],ebx ; (ss)

   mov ebx, [eax+20]
   mov cr3, ebx

   pop gs   
   pop fs
   pop es
   pop ds
   popad

   add esp, 8

   iret
my regs structure looks like this:

Code: Select all

struct regs {
   unsigned int gs;
   unsigned int fs;
   unsigned int es;
   unsigned int ds;
   unsigned int edi;
   unsigned int esi;
   unsigned int ebp;
   unsigned int esp;
   unsigned int ebx;
   unsigned int edx;
   unsigned int ecx;
   unsigned int eax;
   unsigned int int_no;
   unsigned int err_code;    /* our 'push byte #' and ecodes do this */
   unsigned int eip;
   unsigned int cs;
   unsigned int eflags;
   unsigned int useresp;
   unsigned int ss;   /* pushed by the processor automatically */ 
};
and my demote syscall looks like this

Code: Select all

int sys_demote(struct regs *r) {
   r->cs = 0x18;
   current->ss = r->ss = r->es = r->gs = r->fs = r->ds = 0x20;
   return 0;
}
the KERNEL_CS = 0x8 KERNEL_DS = 0x10, USER_CS = 0x18 and USER_DS = 0x20, all these segments span the whole address space

any help would be really appreciated, i'm quite stuck

thanks.
andrew
RetainSoftware

Re:Context Switching

Post by RetainSoftware »

hi,
What's a selector?
In protected mode, the segment registers contain selectors, which index into one of the descriptor tables. Only the top 13 bits of the selector are used for this index. The next lower bit choses between the GDT and LDT. The lowest two bits of the selector set a privilege value.
so this would mean that the demoted cs should be 0x21 instead of 0x18 and i guests that also holds for the other selectors so they should be 0x23

also a longjump is required (dunno for sure anyone?)

greets,

Rene
User avatar
spix
Member
Member
Posts: 128
Joined: Mon Jun 26, 2006 8:41 am
Location: Millicent, South Australia
Contact:

Re:Context Switching

Post by spix »

so this would mean that the demoted cs should be 0x21 instead of 0x18 and i guests that also holds for the other selectors so they should be 0x23

also a longjump is required (dunno for sure anyone?)
Thanks for that, I've now fixed my selectors. I had thought that IRET would load a new CS?

Thanks for the help
raywill

Re:Context Switching

Post by raywill »

spix wrote:
. I had thought that IRET would load a new CS?
Yes.
You can find more information in Intel's manual ,the part about IRET instruction.
User avatar
spix
Member
Member
Posts: 128
Joined: Mon Jun 26, 2006 8:41 am
Location: Millicent, South Australia
Contact:

Re:Context Switching

Post by spix »

Hi there

My context switching now works with the iret, just had to fix the selectors and some other bugs in my code.

I've a new problem now, once the context switch is done and it's in usermode, the next instruction (which is supposed to fork an init() process) page faults, as the kernel is in ring 0 marked pages - so being in ring 3 it can no longer read them.

I'm not really sure how to approach this problem, should I have some sort of page fault instruction that sets the appropriate page to ring 3, (that seems like a bad idea because it would kind of make useless ring 0/ring 3 thing) - perhaps it could only work for the init task?
proxy

Re:Context Switching

Post by proxy »

well that iret is gonna pop 3 things and put them into use:

eflags, cs and eip

just change the eip portition of the stack to be the address of a function found on a user mode accessible page and you are good to go.

proxy
User avatar
spix
Member
Member
Posts: 128
Joined: Mon Jun 26, 2006 8:41 am
Location: Millicent, South Australia
Contact:

Re:Context Switching

Post by spix »

just change the eip portition of the stack to be the address of a function found on a user mode accessible page and you are good to go.
Thanks for that.. I think now my demote syscall was a dumb idea, better to do the context changing in the execve() function for the first user proc.

Anyway, thanks everyone for your tips, you all helped me along.
Post Reply