diff options
author | Marvin Borner | 2020-06-02 23:10:27 +0200 |
---|---|---|
committer | Marvin Borner | 2020-06-02 23:10:27 +0200 |
commit | cf9135829836c85735b383f7c50f34232bea94f9 (patch) | |
tree | c6385aae76407504f34f371b799e03aa53c63e5c /src | |
parent | 0b3b63ffdedb2e37e0732c09eb0e967e256f0d71 (diff) |
Much work on the ELF parser and userspace jumping
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/fs/elf.c | 60 | ||||
-rw-r--r-- | src/kernel/interrupts/isr.c | 2 | ||||
-rw-r--r-- | src/kernel/io/io.c | 5 | ||||
-rw-r--r-- | src/kernel/io/io.h | 1 | ||||
-rw-r--r-- | src/kernel/memory/paging.c | 12 | ||||
-rw-r--r-- | src/kernel/memory/paging.h | 2 | ||||
-rw-r--r-- | src/kernel/syscall/actions/sys_wait.c | 4 | ||||
-rw-r--r-- | src/kernel/tasks/process.c | 62 | ||||
-rw-r--r-- | src/kernel/tasks/process.h | 5 | ||||
-rw-r--r-- | src/kernel/tasks/userspace.asm | 4 | ||||
-rw-r--r-- | src/kernel/tasks/userspace.c | 59 | ||||
-rw-r--r-- | src/kernel/tasks/userspace.h | 17 | ||||
-rw-r--r-- | src/userspace/programs/init.c | 2 |
13 files changed, 93 insertions, 142 deletions
diff --git a/src/kernel/fs/elf.c b/src/kernel/fs/elf.c index 7b95c3b..f6cdecb 100644 --- a/src/kernel/fs/elf.c +++ b/src/kernel/fs/elf.c @@ -34,7 +34,6 @@ struct process *elf_load(char *path) } struct elf_header *header = (struct elf_header *)file; - struct elf_program_header *program_header = (void *)header + header->phoff; if (!is_elf(header)) { warn("File not valid: %s", path); @@ -44,35 +43,46 @@ struct process *elf_load(char *path) } struct process *proc = process_make_new(); - strcpy(proc->name, path); - proc->registers.eip = header->entry; + paging_switch_dir(proc->cr3); - //paging_switch_directory(proc->cr3); - u32 stk = (u32)valloc(PAGE_SIZE); + u32 image_low = 0xFFFFFFFF; + u32 image_high = 0; - proc->registers.useresp = 0x40000000 - (PAGE_SIZE / 2); - proc->registers.ebp = proc->registers.useresp; - proc->registers.esp = proc->registers.useresp; - //paging_map_user(stk, 0x40000000 - PAGE_SIZE); + // Parse ELF + for (u32 i = 0; i < header->shentsize * header->shnum; i += header->shentsize) { + struct elf_section_header *sh = (void *)header + (header->shoff + i); + if (sh->addr != 0) { + log("%x", sh->addr); + for (u32 j = 0; j < sh->size; j += PAGE_SIZE) { + paging_frame_alloc(paging_get_page(sh->addr + j, proc->cr3)); + invlpg(sh->addr + j); + j += PAGE_SIZE; + } - for (int i = 0; i < header->phnum; i++, program_header++) { - switch (program_header->type) { - case 0: - break; - case 1: { - u32 loc = (u32)valloc(PAGE_SIZE); - //paging_map_user(loc, program_header->vaddr); - memcpy((void *)program_header->vaddr, - ((void *)((u32)file) + program_header->offset), - program_header->filesz); - assert(program_header->filesz <= PAGE_SIZE); - break; - } - default: - warn("Unknown header type"); + if (sh->type == 8) // Is .bss + memset(sh->addr, 0, sh->size); + else + memcpy(sh->addr, header + sh->offset, sh->size); + + if (sh->addr < image_low) + image_low = sh->addr; + + if (sh->addr + sh->size > image_high) + image_high = sh->addr + sh->size; } } - /* paging_switch_directory(page_tables); */ + // Stack + struct page_table_entry *stack_page = paging_get_page(0x400000, proc->cr3); + paging_frame_alloc(stack_page); + stack_page->writable = 1; + invlpg(0x400000); + + strcpy(proc->name, path); + proc->brk = image_high; + proc->regs.eip = header->entry; + proc->regs.esp = 0x401000; + proc->regs.useresp = 0x401000; + return proc; }
\ No newline at end of file diff --git a/src/kernel/interrupts/isr.c b/src/kernel/interrupts/isr.c index 73e24a3..ae72a0f 100644 --- a/src/kernel/interrupts/isr.c +++ b/src/kernel/interrupts/isr.c @@ -128,7 +128,7 @@ void fault_handler(struct regs *r) if (current_proc != NULL) { warn("%s: Suspending process %s with ID %d", message, current_proc->name, current_proc->pid); - memcpy(¤t_proc->registers, r, sizeof(struct regs)); + memcpy(¤t_proc->regs, r, sizeof(struct regs)); process_suspend(current_proc->pid); process_force_switch(); } else { diff --git a/src/kernel/io/io.c b/src/kernel/io/io.c index af5f008..1ef82b6 100644 --- a/src/kernel/io/io.c +++ b/src/kernel/io/io.c @@ -98,6 +98,11 @@ void cr0_set(u32 cr0) asm volatile("movl %%eax, %%cr0" ::"a"(cr0)); } +void invlpg(u32 addr) +{ + asm volatile("invlpg (%0)" ::"r"(addr) : "memory"); +} + void serial_install() { outb(0x3f8 + 1, 0x00); diff --git a/src/kernel/io/io.h b/src/kernel/io/io.h index ce3c72b..9274dfb 100644 --- a/src/kernel/io/io.h +++ b/src/kernel/io/io.h @@ -55,6 +55,7 @@ u32 cr3_get(); void cr3_set(u32 cr3); u32 cr0_get(); void cr0_set(u32 cr0); +void invlpg(u32 addr); /** * Initialize the serial conenction diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 1d9f6b1..e2c48b8 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -1,5 +1,6 @@ #include <io/io.h> #include <lib/lib.h> +#include <memory/alloc.h> #include <memory/mmap.h> #include <memory/paging.h> #include <stdint.h> @@ -27,9 +28,16 @@ void paging_install() kernel_page_directory->entries[0].writable = 1; kernel_page_directory->entries[0].address = SHIFT((u32)page_table); - paging_switch_directory((u32)kernel_page_directory); + paging_switch_dir((u32)kernel_page_directory); paging_enable(); info("Installed paging"); + + // Test mallocing + u32 *c = malloc(2048); + c[42] = 0x4242; + assert(c[42] == 0x4242); + free(c); + info("Malloc test succeeded!"); } void paging_disable() @@ -48,7 +56,7 @@ void paging_enable() paging_enabled = 1; } -void paging_switch_directory(u32 dir) +void paging_switch_dir(u32 dir) { cr3_set(dir); } diff --git a/src/kernel/memory/paging.h b/src/kernel/memory/paging.h index ac0dbfa..af7d4a2 100644 --- a/src/kernel/memory/paging.h +++ b/src/kernel/memory/paging.h @@ -49,7 +49,7 @@ struct page_dir { void paging_install(); void paging_enable(); void paging_disable(); -void paging_switch_directory(u32 dir); +void paging_switch_dir(u32 dir); struct page_table_entry *paging_get_page(u32 address, struct page_dir *page_dir); void paging_frame_alloc(struct page_table_entry *page); diff --git a/src/kernel/syscall/actions/sys_wait.c b/src/kernel/syscall/actions/sys_wait.c index 01deef3..23d4639 100644 --- a/src/kernel/syscall/actions/sys_wait.c +++ b/src/kernel/syscall/actions/sys_wait.c @@ -4,7 +4,7 @@ u32 sys_wait(u32 pid, u32 *status, u32 options) { - if (pid > 0) - return process_wait_pid(pid, status); + /* if (pid > 0) */ + /* return process_wait_pid(pid, status); */ return -1; }
\ No newline at end of file diff --git a/src/kernel/tasks/process.c b/src/kernel/tasks/process.c index 0b13b6b..a4c1c79 100644 --- a/src/kernel/tasks/process.c +++ b/src/kernel/tasks/process.c @@ -8,7 +8,6 @@ #include <stdint.h> #include <system.h> #include <tasks/process.h> -#include <tasks/userspace.h> #include <timer/timer.h> u32 pid = 0; @@ -36,7 +35,7 @@ void scheduler(struct regs *regs) } serial_put('+'); - memcpy(¤t_proc->registers, regs, sizeof(struct regs)); + memcpy(¤t_proc->regs, regs, sizeof(struct regs)); timer_handler(regs); @@ -55,10 +54,18 @@ void scheduler(struct regs *regs) } } - memcpy(regs, ¤t_proc->registers, sizeof(struct regs)); - paging_switch_directory(current_proc->cr3); + memcpy(regs, ¤t_proc->regs, sizeof(struct regs)); + paging_switch_dir(current_proc->cr3); + if (regs->cs != 0x1B) { + regs->gs = 0x23; + regs->fs = 0x23; + regs->es = 0x23; + regs->ds = 0x23; + regs->cs = 0x1B; + regs->ss = 0x23; + } + locked = 0; - cli(); } void process_force_switch() @@ -68,6 +75,9 @@ void process_force_switch() //scheduler(regs); } +u32 hl_cr3; +u32 hl_eip; +u32 hl_esp; void process_init(struct process *proc) { log("Initializing process %d", pid); @@ -78,7 +88,15 @@ void process_init(struct process *proc) current_proc = root; irq_install_handler(0, scheduler); - userspace_enter(proc); + + hl_eip = proc->regs.eip; + hl_esp = proc->regs.esp; + //paging_switch_dir(proc->cr3); + + debug("Jumping to userspace!"); + extern void userspace_jump(); + userspace_jump(); + panic("This should not happen!"); } // Only for debugging purposes @@ -113,25 +131,6 @@ u32 process_spawn(struct process *process) return process->pid; } -u32 process_wait_pid(u32 pid, u32 *status) -{ - struct process *i = current_proc->next; - - while (i != NULL) { - if (i->pid == pid) { - if (i->state == PROC_ASLEEP) { - *status = i->registers.ebx; - return i->pid; - } else { - return WAIT_OKAY; - } - } - i = i->next; - } - - return WAIT_ERROR; -} - void process_suspend(u32 pid) { debug("Suspending process %d", pid); @@ -175,15 +174,20 @@ struct process *process_from_pid(u32 pid) return PID_NOT_FOUND; } +void no_entry() +{ + panic("No entry point given!"); +} + struct process *process_make_new() { debug("Making new process %d", pid); struct process *proc = (struct process *)valloc(sizeof(struct process)); - proc->registers.cs = 0x1B; - proc->registers.ds = 0x23; - proc->registers.ss = 0x23; + proc->regs.cs = 0x1B; + proc->regs.ds = 0x23; + proc->regs.ss = 0x23; + proc->regs.eip = no_entry; proc->cr3 = paging_make_dir(); - proc->brk = 0x50000000; proc->pid = pid++; return proc; } diff --git a/src/kernel/tasks/process.h b/src/kernel/tasks/process.h index 5c72e64..493dbe5 100644 --- a/src/kernel/tasks/process.h +++ b/src/kernel/tasks/process.h @@ -14,7 +14,7 @@ struct mmap { struct process { u32 cr3; - struct regs registers; + struct regs regs; u32 pid; char name[256]; @@ -35,9 +35,6 @@ u32 process_spawn(struct process *process); void process_suspend(u32 pid); void process_wake(u32 pid); -u32 process_wait_gid(u32 gid, u32 *status); -u32 process_wait_pid(u32 pid, u32 *status); - struct process *process_from_pid(u32 pid); void process_init(struct process *proc); diff --git a/src/kernel/tasks/userspace.asm b/src/kernel/tasks/userspace.asm index ebdcf26..6881bdf 100644 --- a/src/kernel/tasks/userspace.asm +++ b/src/kernel/tasks/userspace.asm @@ -1,9 +1,9 @@ -global jump_userspace +global userspace_jump extern hl_cr3 extern hl_esp extern hl_eip -jump_userspace: +userspace_jump: mov ax, 0x23 mov ds, ax mov es, ax diff --git a/src/kernel/tasks/userspace.c b/src/kernel/tasks/userspace.c deleted file mode 100644 index 3164965..0000000 --- a/src/kernel/tasks/userspace.c +++ /dev/null @@ -1,59 +0,0 @@ -#include <interrupts/interrupts.h> -#include <io/io.h> -#include <lib/lib.h> -#include <memory/paging.h> -#include <stddef.h> -#include <stdint.h> -#include <system.h> -#include <tasks/process.h> -#include <tasks/userspace.h> - -struct process *proc_bottom = NULL; - -u32 hl_cr3; -u32 hl_eip; -u32 hl_esp; - -u32 spawn_child(struct process *child) -{ - return (u32)-1; -} - -void userspace_enter(struct process *proc) -{ - proc_bottom = proc; - hl_eip = proc->registers.eip; - hl_esp = proc->registers.esp; - paging_switch_directory(proc->cr3); - - //debug("Jumping to userspace!"); - jump_userspace(); -} - -void single_yield(struct process *proc, struct regs *regs) -{ - memcpy(&proc_bottom->registers, regs, sizeof(struct regs)); - - if (proc == proc_bottom) - panic("Can't return from parent process"); - - proc->next = proc_bottom; - proc_bottom = proc; - - memcpy(regs, &proc->registers, sizeof(struct regs)); - paging_switch_directory(proc->cr3); -} - -u32 single_exit(struct regs *regs) -{ - u32 hold = regs->ebx; - proc_bottom = proc_bottom->next; - - if (proc_bottom == NULL) - panic("Return from process with no parent"); - - memcpy(regs, &proc_bottom->registers, sizeof(struct regs)); - paging_switch_directory(proc_bottom->cr3); - - return hold; -}
\ No newline at end of file diff --git a/src/kernel/tasks/userspace.h b/src/kernel/tasks/userspace.h deleted file mode 100644 index d66ba54..0000000 --- a/src/kernel/tasks/userspace.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef MELVIX_USERSPACE_H -#define MELVIX_USERSPACE_H - -#include <interrupts/interrupts.h> -#include <stdint.h> -#include <tasks/process.h> - -u32 spawn_child(struct process *child); - -void userspace_enter(struct process *proc); - -void single_yield(struct process *proc, struct regs *regs); -u32 single_exit(struct regs *regs); - -extern void jump_userspace(); - -#endif
\ No newline at end of file diff --git a/src/userspace/programs/init.c b/src/userspace/programs/init.c index 51aea63..8e5887f 100644 --- a/src/userspace/programs/init.c +++ b/src/userspace/programs/init.c @@ -21,6 +21,8 @@ int interrupts_enabled() void main() { + while (1) { + }; if (get_pid() != 1) { printf("Wrong PID!\n"); exit(1); |