Multi Tasking: User level task return problem[SOLVED]
Posted: Thu Oct 02, 2008 5:14 pm
Hello fellow OS developers, i am having a rather persistent and frustrating problem getting multitasking working on my OS. My kernel currently has paged memory managment and interrupt handling. Im intending to do pre emptive, software based multitasking using the stack to store the processes current state. The following is the procedure i go through to start multitasking:
i create a TSS for the system to use, install it into my gdt, load it with ltr.
I set the PIC to gennerate intterupts at regular intervals and have a handler that catches them, pushes registers,saves stack position, checks to see if it should switch task, loads cr3,loads stack position,pops registers then ireturns.
i create two processes, fill in some generic details for both, and create a page directory for both.
I switch into each processes Address space and setup there stack to mimmic a interrupt followed by pushad instructions (Ie make the stack look like its been the result of a timer interrupt). The code i use for this is the following:
i then can start the task running using the following:
Now as some of you will have spotted from the comments this works fine if i am attempting to start a supervisor level task, i use a ring 0 CS descriptor (0x08) and the task will start perfectly. However, if i try using a user level code descriptor(0x1b) to start a ring 3 task i get a general protection fault . Fortuantltly i am using bochs to develop my OS so i can give you the logfile outpt from the crash:
Since it works for supervisor level return but not for user level i am guessing the problem will be due to a priveledge violation. I think either i havent correctly setup the user level code segment of my GDT correctly or the fault is being cause by the fact that the stack location is currently mapped with supervisor page protection(but surely this would cause a pagefault not GP). I am quite happy to provide anymore code or additional output you guys need but i fell this post is long enough already(I dont want to bore people to death ).
Thanks for your time,
Pinky
(P.S I had a post on this issue over a year ago but due to the elapsed time period and my better understanding of the problem i felt a new post was appropriate but i would like to thank althoughs that helped me then)
i create a TSS for the system to use, install it into my gdt, load it with ltr.
I set the PIC to gennerate intterupts at regular intervals and have a handler that catches them, pushes registers,saves stack position, checks to see if it should switch task, loads cr3,loads stack position,pops registers then ireturns.
i create two processes, fill in some generic details for both, and create a page directory for both.
I switch into each processes Address space and setup there stack to mimmic a interrupt followed by pushad instructions (Ie make the stack look like its been the result of a timer interrupt). The code i use for this is the following:
Code: Select all
//Used when creating a process, function replicates the stack from that would have resulted from a Timer Interrupt.
void processInitializeProcess(unsigned long entrypoint,char*name,ProcessStructure* p)
{
unsigned long oldpd = read_cr3();
write_cr3(p->PageDirectoryAddress);
unsigned long* stacksetup = (unsigned long*)((1022 << 22)+( 1022<< 12));
//mimic interupt stackframe
stacksetup--;
*stacksetup = 0x23;//ss
stacksetup--;
*stacksetup = ((1022 << 22)+( 510<< 12));//esp
stacksetup--;
*stacksetup=0x0202; //eflags
stacksetup--;
*stacksetup= 0x1b;//a user level CS, 0x08 was ring 0, put it back in and the whole thing works
stacksetup--;
*stacksetup=entrypoint;//ip
//Mimics pushad
stacksetup--;
*stacksetup = 0;
stacksetup--;
*stacksetup = 0;
stacksetup--;
*stacksetup = 0;
stacksetup--;
*stacksetup = 0;
stacksetup--;
*stacksetup = 0;
stacksetup--;
*stacksetup = 0;
stacksetup--;
*stacksetup = 0;
stacksetup--;
*stacksetup = 0;
//push segments
stacksetup--;
*stacksetup=0x23;
stacksetup--;
*stacksetup=0x23;
stacksetup--;
*stacksetup=0x23;
stacksetup--;
*stacksetup=0x23;
p->KStackPointer = (unsigned long) stacksetup;
write_cr3(oldpd);
return;
}
Code: Select all
VGADriver::putStr("Starting Multitasking with Process: ");
VGADriver::print(CurrentProcess->ProcessName);
write_cr3(CurrentProcess->PageDirectoryAddress);
asm ("movl %0, %%esp\n\t" : :"r"(CurrentProcess->KStackPointer));
asm("pop %ds\n\t");
asm("pop %es\n\t");
asm("pop %fs\n\t");
asm("pop %gs\n\t");
asm("popa\n\t");
asm("iret\n\t");
Code: Select all
00024214632i[CPU0 ] >> push ebp : 55
00024214632p[CPU0 ] >>PANIC<< exception(): 3rd (10) exception with no resolution
00024214632i[CPU0 ] CPU is in protected mode (active)
00024214632i[CPU0 ] CS.d_b = 32 bit
00024214632i[CPU0 ] SS.d_b = 32 bit
00024214632i[CPU0 ] | EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000000
00024214632i[CPU0 ] | ESP=ff9fe000 EBP=00000000 ESI=00000000 EDI=00000000
00024214632i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df IF tf sf zf af pf cf
00024214632i[CPU0 ] | SEG selector base limit G D
00024214632i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00024214632i[CPU0 ] | CS:001b( 0003| 0| 3) 00000000 000fffff 1 1
00024214632i[CPU0 ] | DS:0023( 0004| 0| 3) 00000000 000fffff 1 1
00024214632i[CPU0 ] | SS:0023( 0004| 0| 3) 00000000 000fffff 1 1
00024214632i[CPU0 ] | ES:0023( 0004| 0| 3) 00000000 000fffff 1 1
00024214632i[CPU0 ] | FS:0023( 0004| 0| 3) 00000000 000fffff 1 1
00024214632i[CPU0 ] | GS:0023( 0004| 0| 3) 00000000 000fffff 1 1
00024214632i[CPU0 ] | EIP=00900053 (00900053)
00024214632i[CPU0 ] | CR0=0xe0000011 CR1=0 CR2=0x00900000
00024214632i[CPU0 ] | CR3=0x01b9c000 CR4=0x00000000
00024214632i[CPU0 ] >> push ebp : 55
00024214632i[CMOS ] Last time is 1222986078 (Thu Oct 2 23:21:18 2008)
00024214632i[XGUI ] Exit
Thanks for your time,
Pinky
(P.S I had a post on this issue over a year ago but due to the elapsed time period and my better understanding of the problem i felt a new post was appropriate but i would like to thank althoughs that helped me then)