106 lines
2.5 KiB
C
106 lines
2.5 KiB
C
#include "proc.h"
|
|
#include "drivers/pit.h"
|
|
#include "drivers/vga.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;
|
|
struct kstack stack;
|
|
};
|
|
|
|
struct vm {
|
|
void *kernel_thread;
|
|
struct task *user_task;
|
|
} vm;
|
|
|
|
void trapret();
|
|
void swtch(void **oldstack, void *newstack);
|
|
|
|
pde_t *get_user_proc_page_directory() {
|
|
if (!vm.user_task) {
|
|
return 0;
|
|
}
|
|
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();
|
|
}
|
|
// 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
|
|
vm.user_task->pgdir = setupkvm();
|
|
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;
|
|
}
|
|
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;
|
|
disable_beep();
|
|
if (!vga_is_text_mode()) {
|
|
switch_to_text_mode();
|
|
vga_clear_screen();
|
|
}
|
|
switchkvm();
|
|
freevm(vm.user_task->pgdir);
|
|
sti();
|
|
swtch(&task_stack, vm.kernel_thread);
|
|
__builtin_unreachable();
|
|
}
|