syscalls: hopefully fix fork syscall

This commit is contained in:
2025-11-23 15:23:38 +03:00
parent c8036a9aae
commit a358d0b1ac
3 changed files with 52 additions and 22 deletions
-3
View File
@@ -48,9 +48,6 @@ typedef struct __attribute__((packed)) Context {
typedef struct __attribute__((packed)) TrapFrame { typedef struct __attribute__((packed)) TrapFrame {
uint32_t gs,fs,es,ds; uint32_t gs,fs,es,ds;
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
uint32_t interrupt, error;
uint32_t eip, cs, eflags, usermode_esp, usermode_ss; uint32_t eip, cs, eflags, usermode_esp, usermode_ss;
} TrapFrame; } TrapFrame;
+1 -7
View File
@@ -33,9 +33,6 @@ switchProcess:
trapret: trapret:
; Восстанавливаем общие регистры из trap frame
;popal ; edi, esi, ebp, oesp, ebx, edx, ecx, eax
; Восстанавливаем сегментные регистры ; Восстанавливаем сегментные регистры
pop gs pop gs
pop fs pop fs
@@ -44,9 +41,6 @@ trapret:
popad popad
; Пропускаем trapno и err
add esp, 8 ; trapno (4 байта) + err (4 байта)
; Теперь ESP указывает на eip, cs, eflags, esp, ss ; Теперь ESP указывает на eip, cs, eflags, esp, ss
; (interrupt and error fields removed from TrapFrame)
iret iret
+50 -11
View File
@@ -86,8 +86,16 @@ int sys_fork(TrapFrame *tf)
destroy_page_dir(new_pd); destroy_page_dir(new_pd);
return -1; 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)); memset(child, 0, sizeof(Process));
child->pid = ++pid_counter; child->pid = ++pid_counter;
@@ -102,27 +110,58 @@ int sys_fork(TrapFrame *tf)
debug_log("Failed to allocate kernel stack\n"); debug_log("Failed to allocate kernel stack\n");
return -1; 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); debug_log("child->kstack: %X\n", child->kstack);
child->kstack_top = (uint32_t)child->kstack + KSTACKSIZE;
uint8_t* sp = (uint8_t*)(child->kstack + KSTACKSIZE); uint8_t* sp = (uint8_t*)(child->kstack + KSTACKSIZE);
// 1. Place the TrapFrame on the child's stack. // 1. Place the TrapFrame on the child's stack.
sp -= sizeof(TrapFrame); sp -= sizeof(TrapFrame);
child->tf = (TrapFrame*)sp; 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)); // Copy the trapframe contents from the parent into the child's trapframe
uint32_t* parent_cpu_state_ptr = (uint32_t*)&tf->interrupt; memcpy(child->tf, tf, sizeof(TrapFrame));
child->tf->eip = parent_cpu_state_ptr[0]; /* Copy instruction pointer and segment registers from parent trapframe */
child->tf->cs = parent_cpu_state_ptr[1]; child->tf->eip = tf->eip;
child->tf->eflags = parent_cpu_state_ptr[2]; child->tf->cs = tf->cs;
child->tf->usermode_esp = parent_cpu_state_ptr[3]; child->tf->eflags = tf->eflags;
child->tf->usermode_ss = parent_cpu_state_ptr[4]; child->tf->usermode_esp = tf->usermode_esp;
child->tf->usermode_ss = tf->usermode_ss;
/* 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 child->tf->eax = 0; // Child returns 0
debug_log("Parent returns PID: %X, Child returns 0\n", child->pid); 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); sp -= sizeof(Context);
child->context = (Context*)sp; child->context = (Context*)sp;
memset(child->context, 0, sizeof(Context)); memset(child->context, 0, sizeof(Context));