I am trying to switch to user mode but I have some questions as it seems that I have some blanks that need to be filled.
I have a 64-bit hobby OS and I was able to create different processes (Different stack and different C Functions) that run all in kernel mode. I use the PIT to do the switching between them.
SO far it runs good and it does what I want.
Every process runs a new function that has an infinite loop and the loop body just displays a string on the screen at a specific location together with a loop counter.
I followed James Molley tutorial and I read this http://www.jamesmolloy.co.uk/tutorial_h ... 0Mode.html and did some parts of it, and read the OSDev wiki articles http://wiki.osdev.org/Getting_to_Ring_3 and http://wiki.osdev.org/System_Calls.
James Molley's tutorial switchs to user mode in the main function and print a string on the screen, which does not run forever. Also most of the documentation I read are in 32-bit and I don't know if it is the same as 64 or there are other considerations I need to take care of.
In my case I think (correct me if I am wrong) this will be the scenario:
1. create process and at creation switch to usermode through the IRET as per the documentation and off course switch the stack.
2. When PIT occurs, the processor will switch to the RSP0 and SS0 from the GDT TSS selector. (Kernel mode)
3. The processor will go to the interrupt handler of the PIT where the scheduler is.
4. The scheduler will fetch the next task to switch to which is a usermode task (But I am still in kernle mode)
My question is that how can I switch here to the usermode using IRET since the infinite loop is already running and I don't know which instruction I will return to.
I mean in the entry point of the new process I can insert the switch_to_usermode but when I come back from the PIT interrupt where can I do that.
Here is the code of my current scheduler
Code: Select all
uint64_t rsp,rbp,rip;
asm volatile("mov %%rsp, %0" : "=r"(rsp));
asm volatile("mov %%rbp, %0" : "=r"(rbp));
rip = read_rip();
if (rip == 0x12345) return;
tasks[current_task]->setRBP(rbp);
tasks[current_task]->setRSP(rsp);
tasks[current_task]->setRIP(rip);
current_task ++;
if ( current_task >= task_count ) current_task = 0;
rbp = tasks[current_task]->getRBP();
rsp = tasks[current_task]->getRSP();
rip = tasks[current_task]->getRIP();
currentkernelPageManager = tasks[current_task]->getPageManager();
asm volatile(" \
cli; \
mov %0, %%rcx; \
mov %1, %%rsp; \
mov %2, %%rbp; \
mov %3, %%cr3; \
mov $0x12345, %%rax; \
sti; \
jmp *%%rcx "
: : "r"(rip), "r"(rsp), "r"(rbp), "r"(currentkernelPageManager));
How can I switch back the code selector and the data selector to the GDT user mode entries which are 0x1b and 0x23
Thanks
Karim.