User mode problems
Posted: Sat Aug 27, 2011 4:31 am
Hi
I've have lately implemented processes in my system and it all seems to be working properly in kernel space, but unfortunately not in user space. The problem arises when I execute an application from within another application. The first application runs as expected but as soon as I spawn a second application (processes) from the first process, the first process crashes while waiting for the second process to be up and running. I have thought of different problems and made several minor fixes related to the stack and the segment selectors, but without any change. And now I've run out of ideas.
The code below is used to spawn a new processes. The status variable should of course be thread/process specific but until I get it working with just two processes I'll leave it as is.
When the first process crashes it is usually from a Page Fault at 0x0 because RIP = 0x0. Sometimes it causes a GP instead with a random (but rather large ~0x1000) GDT descriptor as error code. The error seems to occur right after the while(status == 1); loop ends.
I really don't know what else to tell, I'm pretty lost. Please ask if your need more information.
All help is appreciated!
I've have lately implemented processes in my system and it all seems to be working properly in kernel space, but unfortunately not in user space. The problem arises when I execute an application from within another application. The first application runs as expected but as soon as I spawn a second application (processes) from the first process, the first process crashes while waiting for the second process to be up and running. I have thought of different problems and made several minor fixes related to the stack and the segment selectors, but without any change. And now I've run out of ideas.
The code below is used to spawn a new processes. The status variable should of course be thread/process specific but until I get it working with just two processes I'll leave it as is.
Code: Select all
static volatile int status;
void process_to_usermode(uint64_t rip)
{
asm volatile("cli");
asm volatile("mov $0x23, %ax");
asm volatile("mov %ax, %ds");
asm volatile("mov %ax, %es");
asm volatile("mov %ax, %fs");
asm volatile("mov %ax, %gs");
asm volatile("mov %rsp, %rax");
asm volatile("push $0x23");
asm volatile("push %rax");
asm volatile("pushf");
asm volatile("pop %rax");
asm volatile("or $0x200, %rax");
asm volatile("push %rax");
asm volatile("push $0x1B");
asm volatile("push %%rdx" :: "d"(rip));
asm volatile("iretq");
// IT WORKS IF I USE A SIMPLE JUMP AND LEAVE THEM RUNNING IN KERNEL MODE (CODE BELOW)
// void (*init)();
// init = (void*)rip;
// init();
}
void process_init(args_t *args)
{
uint64_t addr, entry;
addr = elf64_load(args->path, 0);
if(!addr) // File not loaded
{
status = 0;
printf("ELF loading failed!\n");
process_exit(1);
}
entry = elf64_prepare(addr);
if(!entry) // Linking failed
{
status = 0;
printf("ELF linking failed!\n");
process_exit(1);
}
// Allocate a new stack in user space
if(!alloc_page(get_page(USER_STACK_ADDR, 1)))
{
printf("Failed to allocate memory for stack!\n");
process_exit(1);
}
memset((void*)USER_STACK_ADDR, 0, USER_STACK_SIZE);
asm volatile("movq %0, %%rsp" :: "r"(USER_STACK_ADDR+USER_STACK_SIZE));
status = 2; // All good!
kfree((void*)addr);
process_to_usermode(entry);
}
int process_spawn(char *path, char *str, char *cwd, int modal)
{
stream_t *file = vfs_open(path, "r");
int value;
if(file)
{
vfs_close(file);
args_t *args = (args_t*)kmalloc(sizeof(args_t));
strcpy(args->path, path);
strcpy(args->param, str);
strcpy(args->cwd, cwd);
if(modal)
{
args->parent = smp_get_thread();
args->modal = modal;
}
else
{
args->parent = 0;
args->modal = 0;
}
status = 1;
uint64_t pml4 = vmm_create_user_space();
new_thread(&process_init, args, pml4);
while(status == 1); // THE FIRST PROCESS CRASHES HERE WHILE WAITING ON THE SECOND PROCESS
value = status;
if(!value)
{
return 0;
}
else
{
if(args->modal)
{
// This is a temporary solution (the parent process should be put to sleep in this case)
status = 1;
while(status == 1);
}
return 1;
}
}
return 0;
}
I really don't know what else to tell, I'm pretty lost. Please ask if your need more information.
All help is appreciated!