diff --git a/include/task.h b/include/task.h index cd17008..b573124 100644 --- a/include/task.h +++ b/include/task.h @@ -48,9 +48,6 @@ typedef struct __attribute__((packed)) Context { typedef struct __attribute__((packed)) TrapFrame { uint32_t gs,fs,es,ds; uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; - - uint32_t interrupt, error; - uint32_t eip, cs, eflags, usermode_esp, usermode_ss; } TrapFrame; diff --git a/src/tasking/switch.asm b/src/tasking/switch.asm index 01186e5..0270f4f 100644 --- a/src/tasking/switch.asm +++ b/src/tasking/switch.asm @@ -33,9 +33,6 @@ switchProcess: trapret: - ; Восстанавливаем общие регистры из trap frame - ;popal ; edi, esi, ebp, oesp, ebx, edx, ecx, eax - ; Восстанавливаем сегментные регистры pop gs pop fs @@ -44,9 +41,6 @@ trapret: popad - ; Пропускаем trapno и err - add esp, 8 ; trapno (4 байта) + err (4 байта) - - ; Теперь ESP указывает на eip, cs, eflags, esp, ss + ; (interrupt and error fields removed from TrapFrame) iret \ No newline at end of file diff --git a/src/tasking/syscalls.c b/src/tasking/syscalls.c index 45f3893..a5acc8f 100644 --- a/src/tasking/syscalls.c +++ b/src/tasking/syscalls.c @@ -86,8 +86,16 @@ int sys_fork(TrapFrame *tf) destroy_page_dir(new_pd); return -1; } - Process* child = (Process*)((uint32_t)p_physical + 0xC0000000); - map_page(p_physical, (void*)child, PAGE_PRESENT | PAGE_RW); + + // Map the Process structure page into the CHILD's page directory + map_page_in_directory(new_pd, p_physical, (void*)phys_to_virt((uint32_t)p_physical), PAGE_PRESENT | PAGE_RW); + + // Also map the same page into the current (parent) page directory so the + // kernel can access and initialize it now via the kernel virtual mapping. + map_page(p_physical, (void*)phys_to_virt((uint32_t)p_physical), PAGE_PRESENT | PAGE_RW); + + // Get virtual address for initialization (kernel mapping) and clear it + Process* child = (Process*)phys_to_virt((uint32_t)p_physical); memset(child, 0, sizeof(Process)); child->pid = ++pid_counter; @@ -102,27 +110,58 @@ int sys_fork(TrapFrame *tf) debug_log("Failed to allocate kernel stack\n"); return -1; } - child->kstack = (char*)((uint32_t)kstack_physical + 0xC0000000); - map_page(kstack_physical, child->kstack, PAGE_PRESENT | PAGE_RW); + + // Map the kernel stack in the CHILD's page directory + map_page_in_directory(new_pd, kstack_physical, (void*)phys_to_virt((uint32_t)kstack_physical), PAGE_PRESENT | PAGE_RW); + + // Also map kernel stack into the current PD so the kernel can write to it + map_page(kstack_physical, (void*)phys_to_virt((uint32_t)kstack_physical), PAGE_PRESENT | PAGE_RW); + + child->kstack = (char*)phys_to_virt((uint32_t)kstack_physical); debug_log("child->kstack: %X\n", child->kstack); + child->kstack_top = (uint32_t)child->kstack + KSTACKSIZE; + uint8_t* sp = (uint8_t*)(child->kstack + KSTACKSIZE); // 1. Place the TrapFrame on the child's stack. sp -= sizeof(TrapFrame); child->tf = (TrapFrame*)sp; + // Debug: print parent's trapframe before copying + debug_log("parent tf @ %X\n", tf); + debug_log("parent tf->eip=%X cs=%X eflags=%X user_esp=%X user_ss=%X\n", + tf->eip, tf->cs, tf->eflags, tf->usermode_esp, tf->usermode_ss); + debug_log("parent tf regs: eax=%X ebx=%X ecx=%X edx=%X edi=%X esi=%X ebp=%X esp=%X\n", + tf->eax, tf->ebx, tf->ecx, tf->edx, tf->edi, tf->esi, tf->ebp, tf->esp); - memcpy(&child->tf->gs, &tf->gs, 12 * sizeof(uint32_t)); - uint32_t* parent_cpu_state_ptr = (uint32_t*)&tf->interrupt; - child->tf->eip = parent_cpu_state_ptr[0]; - child->tf->cs = parent_cpu_state_ptr[1]; - child->tf->eflags = parent_cpu_state_ptr[2]; - child->tf->usermode_esp = parent_cpu_state_ptr[3]; - child->tf->usermode_ss = parent_cpu_state_ptr[4]; + // Copy the trapframe contents from the parent into the child's trapframe + memcpy(child->tf, tf, sizeof(TrapFrame)); + /* Copy instruction pointer and segment registers from parent trapframe */ + child->tf->eip = tf->eip; + child->tf->cs = tf->cs; + child->tf->eflags = tf->eflags; + child->tf->usermode_esp = tf->usermode_esp; + child->tf->usermode_ss = tf->usermode_ss; - child->tf->eax = 0; // Child returns 0 + /* Ensure saved kernel-ESP in the saved-registers block points + to the location right after the saved registers (where the + iret frame starts). popad will restore ESP from this field, + so it must point to the iret frame, not the user-mode ESP. */ + child->tf->esp = (uint32_t)child->tf + offsetof(TrapFrame, eip); + + child->tf->eax = 0; // Child returns 0 debug_log("Parent returns PID: %X, Child returns 0\n", child->pid); + // Debug: dump important trapframe and stack info for the child + debug_log("child->tf @ %X\n", child->tf); + debug_log("child->tf->eip=%X cs=%X eflags=%X user_esp=%X user_ss=%X\n", + child->tf->eip, child->tf->cs, child->tf->eflags, + child->tf->usermode_esp, child->tf->usermode_ss); + debug_log("child->tf regs: eax=%X ebx=%X ecx=%X edx=%X edi=%X esi=%X ebp=%X esp=%X\n", + child->tf->eax, child->tf->ebx, child->tf->ecx, child->tf->edx, + child->tf->edi, child->tf->esi, child->tf->ebp, child->tf->esp); + debug_log("child->kstack=%X kstack_top=%X kesp=%X\n", child->kstack, child->kstack_top, child->kesp); + sp -= sizeof(Context); child->context = (Context*)sp; memset(child->context, 0, sizeof(Context));