diff options
author | Marvin Borner | 2019-10-31 00:49:00 +0100 |
---|---|---|
committer | Marvin Borner | 2019-10-31 00:49:00 +0100 |
commit | 7d5a9792e57b4088cce5cc97837eb04016b57a4d (patch) | |
tree | 11eac7aa426f3cb597a3ebd2b08cef0d99e9c0cf | |
parent | 91439462f5ad77eb128658229724c9a3660a2068 (diff) |
Implemented basic syscalls and user mode
Doesn't completely work right now
-rw-r--r-- | src/kernel/boot.asm | 19 | ||||
-rw-r--r-- | src/kernel/fs/initrd.c | 26 | ||||
-rw-r--r-- | src/kernel/fs/initrd.h | 2 | ||||
-rw-r--r-- | src/kernel/gdt/gdt.asm | 8 | ||||
-rw-r--r-- | src/kernel/gdt/gdt.c | 75 | ||||
-rw-r--r-- | src/kernel/gdt/gdt.h | 2 | ||||
-rw-r--r-- | src/kernel/graphics/vesa.c | 2 | ||||
-rw-r--r-- | src/kernel/graphics/vesa.h | 6 | ||||
-rw-r--r-- | src/kernel/kernel.c | 38 | ||||
-rw-r--r-- | src/kernel/syscall/syscall.c | 45 | ||||
-rw-r--r-- | src/kernel/syscall/syscall.h | 44 |
11 files changed, 233 insertions, 34 deletions
diff --git a/src/kernel/boot.asm b/src/kernel/boot.asm index fad05ff..8f24066 100644 --- a/src/kernel/boot.asm +++ b/src/kernel/boot.asm @@ -50,6 +50,25 @@ stublet: %include "src/kernel/interact.asm" +global switch_to_user +switch_to_user: + cli + mov ax,0x23 + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + + mov eax,esp + push 0x23 + push eax + pushf + pop eax + or eax, 0x200 + push eax + push 0x1B + iret + ; Store the stack SECTION .bss resb 0x2000 ; Reserve 8KiB diff --git a/src/kernel/fs/initrd.c b/src/kernel/fs/initrd.c index 906498e..acaceb8 100644 --- a/src/kernel/fs/initrd.c +++ b/src/kernel/fs/initrd.c @@ -4,6 +4,7 @@ #include <kernel/lib/lib.h> #include <kernel/lib/alloc.h> #include <kernel/io/io.h> +#include <kernel/graphics/vesa.h> initrd_header_t *initrd_header; initrd_file_header_t *file_headers; @@ -103,3 +104,28 @@ fs_node_t *initialise_initrd(uint32_t location) { } return initrd_root; } + +void initrd_test() { + int i = 0; + struct dirent *node = 0; + vesa_draw_string("\n"); + while ((node = readdir_fs(fs_root, i)) != 0) { + vesa_draw_string("Found file: "); + vesa_draw_string(node->name); + vesa_draw_string("\n"); + fs_node_t *fsnode = finddir_fs(fs_root, node->name); + + if ((fsnode->flags & 0x7) == FS_DIRECTORY) + vesa_draw_string("\t (directory)\n"); + else { + vesa_draw_string("\t contents: \""); + uint8_t buf[fsnode->length]; + uint32_t sz = read_fs(fsnode, 0, fsnode->length, buf); + for (uint32_t j = 0; j < sz; j++) + vesa_draw_char(buf[j]); + + vesa_draw_string("\"\n"); + } + i++; + } +}
\ No newline at end of file diff --git a/src/kernel/fs/initrd.h b/src/kernel/fs/initrd.h index 10dec22..bb5c376 100644 --- a/src/kernel/fs/initrd.h +++ b/src/kernel/fs/initrd.h @@ -17,4 +17,6 @@ typedef struct { fs_node_t *initialise_initrd(uint32_t location); +void initrd_test(); + #endif diff --git a/src/kernel/gdt/gdt.asm b/src/kernel/gdt/gdt.asm index c2128e4..6cb2b7d 100644 --- a/src/kernel/gdt/gdt.asm +++ b/src/kernel/gdt/gdt.asm @@ -11,4 +11,10 @@ gdt_flush: mov ss, ax jmp 0x08:flush2 ; Code segment offset flush2: - ret ; Returns to C code
\ No newline at end of file + ret ; Returns to C code + +global tss_flush +tss_flush: + mov ax, 0x2B + ltr ax + ret
\ No newline at end of file diff --git a/src/kernel/gdt/gdt.c b/src/kernel/gdt/gdt.c index a4d6a57..b933950 100644 --- a/src/kernel/gdt/gdt.c +++ b/src/kernel/gdt/gdt.c @@ -1,4 +1,8 @@ +#include <stdint.h> +#include <kernel/gdt/gdt.h> #include <kernel/system.h> +#include <kernel/lib/lib.h> +#include <kernel/io/io.h> struct gdt_entry { unsigned short limit_low; @@ -14,12 +18,46 @@ struct gdt_ptr { void *base; } __attribute__((packed)); -struct gdt_entry gdt[3]; +struct gdt_entry gdt[6]; struct gdt_ptr gp; +struct tss_entry_struct { + uint32_t prev_tss; + uint32_t esp0; + uint32_t ss0; + uint32_t esp1; + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap; + uint16_t iomap_base; +} __attribute__((packed)); + +struct tss_entry_struct tss_entry; + extern void gdt_flush(); -void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran) { +extern void tss_flush(); + +void gdt_set_gate(int32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) { // Set descriptor base address gdt[num].base_low = (base & 0xFFFF); gdt[num].base_middle = (base >> 16) & 0xFF; @@ -36,7 +74,7 @@ void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned cha void gdt_install() { // Set GDT pointer and limit - gp.limit = (sizeof(struct gdt_entry) * 3) - 1; + gp.limit = (sizeof(struct gdt_entry) * 6) - 1; gp.base = &gdt; // NULL descriptor @@ -48,8 +86,37 @@ void gdt_install() { // Data segment gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + // User mode code segment + gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); + + // User mode data segment + gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); + + // Write TSS + tss_write(5, 0x10, 0x0); + // Remove old GDT and install the new changes! gdt_flush(); + tss_flush(); // FAILS vga_log("Installed Global Descriptor Table", 2); -}
\ No newline at end of file +} + +void tss_write(int32_t num, uint16_t ss0, uint32_t esp0) { + uint32_t base = (uint32_t) &tss_entry; + uint32_t limit = base + sizeof(tss_entry); + + gdt_set_gate(num, base, limit, 0xE9, 0x00); + + memset(&tss_entry, 0, sizeof(tss_entry)); + + tss_entry.ss0 = ss0; + tss_entry.esp0 = esp0; + + tss_entry.cs = 0x0b; + tss_entry.ss = tss_entry.ds = tss_entry.es = tss_entry.fs = tss_entry.gs = 0x13; +} + +void set_kernel_stack(uint32_t stack) { + tss_entry.esp0 = stack; +} diff --git a/src/kernel/gdt/gdt.h b/src/kernel/gdt/gdt.h index de8a6ff..0fffc20 100644 --- a/src/kernel/gdt/gdt.h +++ b/src/kernel/gdt/gdt.h @@ -6,4 +6,6 @@ */ void gdt_install(); +void tss_write(int32_t num, uint16_t ss0, uint32_t esp0); + #endif diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c index 3f8a9ba..32ca717 100644 --- a/src/kernel/graphics/vesa.c +++ b/src/kernel/graphics/vesa.c @@ -324,7 +324,7 @@ void vesa_keyboard_char(char ch) { terminal_color); } -void vesa_draw_string(char *data) { +void vesa_draw_string(const char *data) { int i = 0; while (data[i] != '\0') { vesa_draw_char(data[i]); diff --git a/src/kernel/graphics/vesa.h b/src/kernel/graphics/vesa.h index 748f8d0..3fcef24 100644 --- a/src/kernel/graphics/vesa.h +++ b/src/kernel/graphics/vesa.h @@ -128,6 +128,10 @@ void vesa_clear(); */ void vesa_set_font(int height); +/** + * Draws a single char + * @param ch The char + */ void vesa_draw_char(char ch); /** @@ -140,7 +144,7 @@ void vesa_keyboard_char(char ch); * Draw a string in VESA mode * @param data The string */ -void vesa_draw_string(char *data); +void vesa_draw_string(const char *data); /** * Draw a number in VESA mode diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index dd49949..dd15409 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -8,8 +8,11 @@ #include <kernel/acpi/acpi.h> #include <kernel/mutliboot.h> #include <kernel/fs/initrd.h> +#include <kernel/syscall/syscall.h> -void init() { +extern void switch_to_user(); + +void kernel_main(struct multiboot *mboot_ptr) { vga_log("Installing basic features of Melvix...", 0); // Install features timer_install(); @@ -21,44 +24,25 @@ void init() { isrs_install(); irq_install(); set_optimal_resolution(); + // Install drivers asm volatile ("cli"); keyboard_install(); asm volatile ("sti"); -} - -void kernel_main(struct multiboot *mboot_ptr) { - init(); + // Setup initial ramdisk assert(mboot_ptr->mods_count > 0); uint32_t initrd_location = *((uint32_t *) mboot_ptr->mods_addr); uint32_t initrd_end = *(uint32_t *) (mboot_ptr->mods_addr + 4); paging_set_used(0, (initrd_end >> 12) + 1); - fs_root = initialise_initrd(initrd_location); + initrd_test(); - int i = 0; - struct dirent *node = 0; - vesa_draw_string("\n"); - while ((node = readdir_fs(fs_root, i)) != 0) { - vesa_draw_string("Found file: "); - vesa_draw_string(node->name); - vesa_draw_string("\n"); - fs_node_t *fsnode = finddir_fs(fs_root, node->name); - - if ((fsnode->flags & 0x7) == FS_DIRECTORY) - vesa_draw_string("\t (directory)\n"); - else { - vesa_draw_string("\t contents: \""); - uint8_t buf[fsnode->length]; - uint32_t sz = read_fs(fsnode, 0, fsnode->length, buf); - for (uint32_t j = 0; j < sz; j++) - vesa_draw_char(buf[j]); + // User mode! + syscalls_install(); + switch_to_user(); - vesa_draw_string("\"\n"); - } - i++; - } + syscall_serial_write("Hello, user world!\n"); // asm volatile ("div %0" :: "r"(0)); // Exception testing x/0 loop: diff --git a/src/kernel/syscall/syscall.c b/src/kernel/syscall/syscall.c new file mode 100644 index 0000000..d1dbd6b --- /dev/null +++ b/src/kernel/syscall/syscall.c @@ -0,0 +1,45 @@ +#include <stdint.h> +#include <kernel/syscall/syscall.h> +#include <kernel/interrupts/interrupts.h> +#include <kernel/graphics/vesa.h> +#include <kernel/io/io.h> + +DEFN_SYSCALL1(vesa_draw_string, 0, const char *); + +DEFN_SYSCALL1(vesa_draw_number, 1, int); + +DEFN_SYSCALL1(serial_write, 2, const char *); + +static void *syscalls[3] = { + &vesa_draw_string, + &vesa_draw_number, + &serial_write, +}; +uint32_t num_syscalls = 3; + +void syscall_handler(struct regs *r) { + if (r->eax >= num_syscalls) + return; + + void *location = syscalls[r->eax]; + + int ret; + asm volatile (" \ + push %1; \ + push %2; \ + push %3; \ + push %4; \ + push %5; \ + call *%6; \ + pop %%ebx; \ + pop %%ebx; \ + pop %%ebx; \ + pop %%ebx; \ + pop %%ebx; \ + " : "=a" (ret) : "r" (r->edi), "r" (r->esi), "r" (r->edx), "r" (r->ecx), "r" (r->ebx), "r" (location)); + r->eax = ret; +} + +void syscalls_install() { + irq_install_handler(0x80, &syscall_handler); +} diff --git a/src/kernel/syscall/syscall.h b/src/kernel/syscall/syscall.h new file mode 100644 index 0000000..d35c4e6 --- /dev/null +++ b/src/kernel/syscall/syscall.h @@ -0,0 +1,44 @@ +#ifndef MELVIX_SYSCALL_H +#define MELVIX_SYSCALL_H + +#include <kernel/interrupts/interrupts.h> + +void syscalls_install(); + +void syscall_handler(struct regs *r); + +#define DECL_SYSCALL0(fn) int syscall_##fn(); +#define DECL_SYSCALL1(fn, p1) int syscall_##fn(p1); +#define DECL_SYSCALL2(fn, p1, p2) int syscall_##fn(p1,p2); +#define DECL_SYSCALL3(fn, p1, p2, p3) int syscall_##fn(p1,p2,p3); +#define DECL_SYSCALL4(fn, p1, p2, p3, p4) int syscall_##fn(p1,p2,p3,p4); +#define DECL_SYSCALL5(fn, p1, p2, p3, p4, p5) int syscall_##fn(p1,p2,p3,p4,p5); + +#define DEFN_SYSCALL0(fn, num) \ +int syscall_##fn() { \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num)); \ + return a; \ +} + +#define DEFN_SYSCALL1(fn, num, P1) \ +int syscall_##fn(P1 p1) { \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1)); \ + return a; \ +} + +#define DEFN_SYSCALL2(fn, num, P1, P2) \ +int syscall_##fn(P1 p1, P2 p2) { \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1), "c" ((int)p2)); \ + return a; \ +} + +DECL_SYSCALL1(vesa_draw_string, const char *) + +DECL_SYSCALL1(vesa_draw_number, int) + +DECL_SYSCALL1(serial_write, const char *) + +#endif |