96 lines
2.3 KiB
C
Raw Normal View History

#include "proc.h"
struct context {
// matches the behavior of swtch()
uint32_t edi, esi, ebp, ebx;
uint32_t eip; // return address for swtch()
};
struct kstack {
uint32_t space[400];
struct context context;
registers_t trapframe;
char bottom[];
};
struct task {
struct taskstate tss;
pde_t *pgdir;
2025-01-18 15:57:47 +04:00
struct kstack stack;
};
struct vm {
void *kernel_thread;
struct task *user_task;
} vm;
void trapret();
void swtch(void** oldstack, void* newstack);
2026-04-06 05:20:00 +03:00
pde_t *get_user_proc_page_directory() {
2026-04-06 05:41:34 +03:00
// if (!vm.user_task) {
// return 0;
// }
2026-04-06 05:20:00 +03:00
return vm.user_task->pgdir;
}
void run_elf(const char* name) {
struct stat statbuf;
if (stat(name, &statbuf) != 0) {
printk(name);
printk(": file not found\n");
return;
}
if (!vm.user_task) {
vm.user_task = kalloc();
}
2026-04-06 05:20:00 +03:00
// todo: this code contains 9999 memory leaks but I don't care
// todo: yabloko is fucking shit made my monkeys, I want to forget this fucking nightmare
2025-01-18 02:38:44 +04:00
vm.user_task->pgdir = setupkvm();
2026-04-06 05:20:00 +03:00
if (allocuvm(vm.user_task->pgdir, USER_BASE, USER_BASE + statbuf.size)) {
printk("Fail: out of memory\n");
return;
}
if (allocuvm(vm.user_task->pgdir, USER_STACK_BASE - 2 * PGSIZE, USER_STACK_BASE)) {
printk("Fail: out of memory\n");
return;
}
2025-01-18 02:38:44 +04:00
switchuvm(&vm.user_task->tss, vm.user_task->stack.bottom, vm.user_task->pgdir);
if (read_file(&statbuf, (void*)USER_BASE, 100 << 20) <= 0) {
printk(name);
printk(": file not found\n");
return;
}
Elf32_Ehdr *hdr = (void*)USER_BASE;
struct kstack *u = &vm.user_task->stack;
memset(u, 0, sizeof(*u));
u->context.eip = (uint32_t)trapret;
registers_t *tf = &u->trapframe;
tf->eip = hdr->e_entry;
tf->cs = (SEG_UCODE << 3) | DPL_USER;
tf->ds = (SEG_UDATA << 3) | DPL_USER;
tf->es = tf->ds;
tf->fs = tf->ds;
tf->gs = tf->ds;
tf->ss = tf->ds;
tf->eflags = FL_IF;
tf->useresp = USER_STACK_BASE;
// initialization done, now switch to the process
swtch(&vm.kernel_thread, &u->context);
// process has finished
}
_Noreturn void killproc() {
void* task_stack;
switchkvm();
2025-01-18 02:38:44 +04:00
freevm(vm.user_task->pgdir);
2025-01-18 02:46:38 +04:00
sti();
swtch(&task_stack, vm.kernel_thread);
__builtin_unreachable();
}