Thanks to a lot of forum posts and wiki pages, I've been able to run some code in ring 3, in long mode (my OS is in long mode and all user code will be long mode).
I've now reached the point where I want to go from user mode -> kernel mode with system calls, with interrupts.
However, I'm unable to make that working.
I have create a TSS structure and a GDT selector point to it. Just before I switch to user mode, I set the stack in RSP0 of the TSS. I've created entry in the IDT for the the syscall (syscall is working if called from ring 0 kernel code).
When the interrupt occurs in ring 3 user code, a Page Fault is thrown.
Here is the code making the switch:
Code: Select all
uint64_t rsp;
asm volatile("mov %0, rsp;" : "=m" (rsp));
gdt::tss.rsp0 = rsp;
asm volatile("mov ax, %0; mov ds, ax; mov es, ax; mov fs, ax; mov gs, ax;"
: //No outputs
: "i" (gdt::USER_DATA_SELECTOR + 3)
: "rax");
asm volatile("push %0; push %1; pushfq; push %2; push %3; iretq"
: //No outputs
: "i" (gdt::USER_DATA_SELECTOR + 3), "i" (0x500000 + paging::PAGE_SIZE * 2 - 64), "i" (gdt::USER_CODE_SELECTOR + 3), "r" (header->e_entry)
: "rax");
- Obviously, I'd be glad to know where does the PF comes from
- In long mode, it seems that there is no SS in the TSS structure, is there another place I should put it ? Or is it something I should do in the interrupt handling code ?
- For now, I've set the DPL of my syscall to 3, is that correct ? If so, how will the processor go to ring 0 ? If not, how will I call it from user mode ?
- I've seen in many posts that OSes were mapping the kernel into user space, is it related to this problem?
- Finally, the page fault handler of my kernel is not run, instead, I see the page fault in Bochs output and it causes a triple fault and reset. Is it directly related to the fact that I cannot run int in user mode code ?
Thanks