SOLVED Strange solution to strange problem.
Posted: Sun Apr 01, 2012 12:37 pm
Hi, i'm a longtime lurker, but now i've got a problem, so: first post.
I'm currently trying to get multitasking with usermode applications working. The task-switching and fork code follow the general idears of JamesM's tutorials, with the exception that the kernel stacks (tss.esp0) are always mapped at the same address in userspace. So when forking the current processes stack gets copied (haven't employed copy-on-write yet). In my kernel's main i do something like that:
This totally works (kernel pages are still user readable/writable). But when calling syscall_fork in the usermode application (test2), i get an illegal opcode exception inside fork for the calling process (no problems with other syscalls). Tell me if i'm wrong, but i think that can only happen when there is some kind of stack corruption. My fork:
I'm trying to find my mistake for 3 days now, debugged with bochs, but no success. But then, by accident, i changed this
to this
which is obviously nonsense.But with the 'if' everything works just fine. No problems/errors at all.
So my question is: How does the if construct affect the stack? What does that tell me about my problem? What the f***?
gdb disassembly and test2 code are http://pastebin.com/T06VRuzP.
Sorry if my question is noobish, i'm still learning . And sorry for typos+grammar, english is not my native language.
I'm currently trying to get multitasking with usermode applications working. The task-switching and fork code follow the general idears of JamesM's tutorials, with the exception that the kernel stacks (tss.esp0) are always mapped at the same address in userspace. So when forking the current processes stack gets copied (haven't employed copy-on-write yet). In my kernel's main i do something like that:
Code: Select all
switch_to_usermode();
int ret = syscall_fork(); <-- this works
if(!ret) {
syscall_execvp("/boot/test2"); <-- inside there it doesn't
}
Code: Select all
int fork() {
asm volatile("cli");
task_t *parent_task = (task_t*) current_task;
UINT32 physical;
UINT32 esp, ebp, eip;
task_t *new_task = (task_t*) kvmalloc(sizeof(task_t));
clone_directory(FALSE, &physical);
new_task->pid = get_next_pid();
new_task->esp = new_task->ebp = 0;
new_task->eip = 0;
new_task->directory_physical = physical;
new_task->kernel_stack = parent_task->kernel_stack;
new_task->next = 0;
...
copy_open_files(new_task, parent_task);
BOCHS_BREAKPOINT;
task_t *tmpt = ready_queue;
while(tmpt->next) tmpt = tmpt->next;
tmpt->next = new_task;t <-- exactly here: Illegal opcode exception (for the parent_task)
eip = read_eip();
if(current_task == parent_task) {
asm volatile("mov %%esp, %0" : "=r" (esp));
asm volatile("mov %%ebp, %0" : "=r" (ebp));
new_task->esp = esp;
new_task->ebp = ebp;
new_task->eip = eip;
return new_task->pid;
} else {
return 0;
}
}
Code: Select all
task_t *tmpt = ready_queue;
while(tmpt->next) tmpt = tmpt->next;
tmpt->next = new_task;t
Code: Select all
if(parent_task->pid != 0) {
task_t *tmpt = ready_queue;
while(tmpt->next) tmpt = tmpt->next;
tmpt->next = new_task;
} else {
task_t *tmpt = ready_queue;
while(tmpt->next) tmpt = tmpt->next;
tmpt->next = new_task;
}
So my question is: How does the if construct affect the stack? What does that tell me about my problem? What the f***?
gdb disassembly and test2 code are http://pastebin.com/T06VRuzP.
Sorry if my question is noobish, i'm still learning . And sorry for typos+grammar, english is not my native language.