syscalls: hopefully fix fork syscall
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
+50
-11
@@ -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;
|
||||
|
||||
/* 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));
|
||||
|
||||
Reference in New Issue
Block a user