This is how I'm doing it:
Code: Select all
//setup TSS
void* stack = kmalloc(1024);
void* tss = kmalloc(104);
*(uint32_t*)(tss+4) = (uint32_t)stack;
*(uint32_t*)(tss+8) = 0x10; //kernel data descriptor
gdt_set_entry(5, create_gdt_entry(104, (uint32_t)tss, 0x89, 0x4));
load_gdt(6);
__asm__ __volatile__("ltr %%ax" : : "a" (0x28));
void* program = (void*)0x00000000;
void* userstack = (void*)0xBFFFF000;
if(!vmmngr_alloc_page((virtual_addr)program))
PrintString("Fail\n");
else
{
pt_entry_add_attrib(vmmngr_ptable_lookup_entry(get_ptable_address((virtual_addr)program), (virtual_addr)program), PTE_USER); //make it a user page
if(!vmmngr_alloc_page((virtual_addr)userstack))
PrintString("Failed to allocate stack.\n");
else
{
pt_entry_add_attrib(vmmngr_ptable_lookup_entry(get_ptable_address((virtual_addr)userstack), (virtual_addr)userstack), PTE_USER); //make it a user page
vmmngr_flush_tlb_entry((virtual_addr)program);
vmmngr_flush_tlb_entry((virtual_addr)userstack);
struct FileInfo fi;
if(!GetFileInfo("test.bin", &fi, 0))
PrintString("Failed to load file.");
else
{
LoadFile("test.bin", program, 0);
_enter_usermode();
}
}
}
And this is the _enter_usermode() function (NASM)
Code: Select all
bits 32
global _enter_usermode
%define UserModeESP 0xC0000000
_enter_usermode:
cli
mov ax, 0x23 ;user mode data selector
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push 0x23 ;for SS
push UserModeESP ;ESP
pushfd ;eflags
push 0x1B ;user mode code selector
push 0x00 ;EIP of usermode program - prog is loaded at 0
iret
cli
hlt
This is the usermode program I am trying to execute:
Code: Select all
void main(void)
{
for(;;);
}