diff --git a/meson.build b/meson.build index acd5f80..a70c0de 100644 --- a/meson.build +++ b/meson.build @@ -31,23 +31,15 @@ custom_target( build_by_default: true, ) -custom_target( - 'hello', - input: 'src/app/hello.asm', - output: 'hello.bin', - command: [nasm, '-f', 'bin', '-l', 'hello.lst', '@INPUT@', '-o', '@OUTPUT@'], - build_by_default: true, -) - kernel_entry_o = custom_target( 'kernel_entry', - input: 'src/kernel_entry.asm', + input: 'src/kernel/kernel_entry.asm', output: 'kernel_entry.o', command: [nasm, '-f', 'elf64', '@INPUT@', '-o', '@OUTPUT@'], ) syscall_o = custom_target('syscall', - input: 'src/syscall.asm', + input: 'src/kernel/syscall.asm', output: 'syscall.o', command: [nasm, '-f', 'elf64', '@INPUT@', '-o', '@OUTPUT@'], ) @@ -55,25 +47,26 @@ syscall_o = custom_target('syscall', cc = meson.get_compiler('c') kernel_sources = files( - 'src/app/cat.c', - 'src/app/ls.c', - 'src/app/terminal.c', - 'src/ata.c', - 'src/fat16.c', - 'src/fs.c', - 'src/gdt.c', - 'src/idt.c', - 'src/kernel.c', - 'src/keyboard.c', - 'src/memory.c', - 'src/panic.c', - 'src/path.c', - 'src/pic.c', - 'src/process.c', - 'src/string.c', - 'src/syscall.c', - 'src/tss.c', - 'src/vga.c', + 'src/kernel/app/cat.c', + 'src/kernel/app/ls.c', + 'src/kernel/app/terminal.c', + 'src/kernel/ata.c', + 'src/kernel/fat16.c', + 'src/kernel/fs.c', + 'src/kernel/gdt.c', + 'src/kernel/idt.c', + 'src/kernel/kernel.c', + 'src/kernel/keyboard.c', + 'src/kernel/memory.c', + 'src/kernel/panic.c', + 'src/kernel/path.c', + 'src/kernel/pic.c', + 'src/kernel/process.c', + 'src/kernel/syscall.c', + 'src/kernel/tss.c', + 'src/kernel/vga.c', + 'src/lib/memory.c', + 'src/lib/string.c', ) kernel_elf = executable( @@ -88,13 +81,14 @@ kernel_elf = executable( '-mcmodel=kernel', '-Wno-unused-command-line-argument', '-Wconversion', + '-DKERNEL="yes"', '-DVERSION="' + meson.project_version() + '"', ], link_args: [ - '-T', meson.project_source_root() / 'src/linker.ld', + '-T', meson.project_source_root() / 'src/kernel/linker.ld', '-nostdlib', ], - link_depends: 'src/linker.ld', + link_depends: 'src/kernel/linker.ld', ) custom_target( @@ -104,3 +98,41 @@ custom_target( command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'], build_by_default: true, ) + +hello_start = custom_target( + 'hello_start', + input: 'src/user/start.asm', + output: 'hello_start.o', + command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'], +) + +hello_syscall = custom_target( + 'hello_syscall', + input: 'src/user/syscall.asm', + output: 'hello_syscall.o', + command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'], +) + +hello_elf = executable( + 'hello.elf', + sources: [hello_start, hello_syscall, 'src/user/app/hello/hello.c'], + c_args: [ + '-ffreestanding', + '-nostdlib', + '-fno-stack-protector', + '-mcmodel=large', + ], + link_args: [ + '-T', meson.project_source_root() / 'src/user/linker.ld', + '-nostdlib', + ], + link_depends: 'src/user/linker.ld', +) + +custom_target( + 'hello_bin', + input: hello_elf, + output: 'hello.bin', + command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'], + build_by_default: true, +) diff --git a/src/app/hello.asm b/src/app/hello.asm deleted file mode 100644 index b8bb7fd..0000000 --- a/src/app/hello.asm +++ /dev/null @@ -1,16 +0,0 @@ -bits 64 -org 0x400000 - -section .text - mov rax, 1 - mov rdi, 1 - lea rsi, [rel msg] - mov rdx, 14 - syscall - - mov rax, 60 - xor rdi, rdi - syscall - -section .data -msg: db "Hello, ring 3!", 10 diff --git a/src/bootloader.asm b/src/bootloader.asm index bbb8b58..cb74629 100644 --- a/src/bootloader.asm +++ b/src/bootloader.asm @@ -334,7 +334,7 @@ long_mode: mov ds, ax mov es, ax mov ss, ax - mov rsp, 0xFFFFFFFF80090000 + mov rsp, 0xFFFFFFFF80F00000 xor rax, rax xor rbx, rbx diff --git a/src/app/cat.c b/src/kernel/app/cat.c similarity index 84% rename from src/app/cat.c rename to src/kernel/app/cat.c index 35e293f..ee7ffaa 100644 --- a/src/app/cat.c +++ b/src/kernel/app/cat.c @@ -1,8 +1,7 @@ -#include "src/app/cat.h" -#include "src/fs.h" -#include "src/memory.h" -#include "src/path.h" -#include +#include "src/kernel/app/cat.h" +#include "src/kernel/fs.h" +#include "src/kernel/path.h" +#include "src/lib/memory.h" void cat(process_t *proc, uint8_t argc, char **argv) { if (argc != 2) { diff --git a/src/app/cat.h b/src/kernel/app/cat.h similarity index 68% rename from src/app/cat.h rename to src/kernel/app/cat.h index be8a4ae..aa044da 100644 --- a/src/app/cat.h +++ b/src/kernel/app/cat.h @@ -1,5 +1,5 @@ #pragma once -#include "src/process.h" +#include "src/kernel/process.h" void cat(process_t *proc, uint8_t argc, char **argv); diff --git a/src/app/ls.c b/src/kernel/app/ls.c similarity index 88% rename from src/app/ls.c rename to src/kernel/app/ls.c index 05a1990..c6c0a3f 100644 --- a/src/app/ls.c +++ b/src/kernel/app/ls.c @@ -1,6 +1,6 @@ -#include "src/app/ls.h" -#include "src/fs.h" -#include "src/path.h" +#include "src/kernel/app/ls.h" +#include "src/kernel/fs.h" +#include "src/kernel/path.h" #include void ls(process_t *proc, uint8_t argc, char **argv) { diff --git a/src/app/ls.h b/src/kernel/app/ls.h similarity index 68% rename from src/app/ls.h rename to src/kernel/app/ls.h index 3f4963e..913b859 100644 --- a/src/app/ls.h +++ b/src/kernel/app/ls.h @@ -1,5 +1,5 @@ #pragma once -#include "src/process.h" +#include "src/kernel/process.h" void ls(process_t *proc, uint8_t argc, char **argv); diff --git a/src/app/terminal.c b/src/kernel/app/terminal.c similarity index 95% rename from src/app/terminal.c rename to src/kernel/app/terminal.c index 8968c5c..a11c606 100644 --- a/src/app/terminal.c +++ b/src/kernel/app/terminal.c @@ -1,14 +1,12 @@ -#include "src/app/terminal.h" -#include "src/app/cat.h" -#include "src/app/ls.h" -#include "src/fs.h" -#include "src/memory.h" -#include "src/path.h" -#include "src/process.h" -#include "src/string.h" -#include "src/util.h" - -#include +#include "src/kernel/app/terminal.h" +#include "src/kernel/app/cat.h" +#include "src/kernel/app/ls.h" +#include "src/kernel/fs.h" +#include "src/kernel/path.h" +#include "src/kernel/process.h" +#include "src/lib/memory.h" +#include "src/lib/string.h" +#include "src/lib/util.h" static void help(process_t *proc, uint8_t argc, char **argv); static void cd(process_t *proc, uint8_t argc, char **argv); diff --git a/src/app/terminal.h b/src/kernel/app/terminal.h similarity index 69% rename from src/app/terminal.h rename to src/kernel/app/terminal.h index 1d4932e..20019a6 100644 --- a/src/app/terminal.h +++ b/src/kernel/app/terminal.h @@ -1,5 +1,5 @@ #pragma once -#include "src/process.h" +#include "src/kernel/process.h" void terminal(process_t *proc, uint8_t argc, char **argv); diff --git a/src/ata.c b/src/kernel/ata.c similarity index 94% rename from src/ata.c rename to src/kernel/ata.c index c43f134..c12796d 100644 --- a/src/ata.c +++ b/src/kernel/ata.c @@ -1,6 +1,6 @@ -#include "src/ata.h" -#include "src/panic.h" -#include "src/util.h" +#include "src/kernel/ata.h" +#include "src/kernel/panic.h" +#include "src/kernel/util.h" #define BSY 0b10000000 #define DF 0b00100000 diff --git a/src/ata.h b/src/kernel/ata.h similarity index 100% rename from src/ata.h rename to src/kernel/ata.h diff --git a/src/fat16.c b/src/kernel/fat16.c similarity index 97% rename from src/fat16.c rename to src/kernel/fat16.c index d659316..2f8883c 100644 --- a/src/fat16.c +++ b/src/kernel/fat16.c @@ -1,10 +1,10 @@ -#include "src/fat16.h" -#include "src/ata.h" -#include "src/fs.h" -#include "src/memory.h" -#include "src/string.h" -#include "src/util.h" -#include +#include "src/kernel/fat16.h" +#include "src/kernel/ata.h" +#include "src/kernel/fs.h" +#include "src/kernel/panic.h" +#include "src/lib/memory.h" +#include "src/lib/string.h" +#include "src/lib/util.h" #define SECTOR_SIZE 512 #define FIRST_PARTITION_SECTOR 2048 diff --git a/src/fat16.h b/src/kernel/fat16.h similarity index 93% rename from src/fat16.h rename to src/kernel/fat16.h index e74abe6..e55573b 100644 --- a/src/fat16.h +++ b/src/kernel/fat16.h @@ -1,6 +1,6 @@ #pragma once -#include "src/fs.h" +#include "src/kernel/fs.h" #define FAT16 1 diff --git a/src/fs.c b/src/kernel/fs.c similarity index 91% rename from src/fs.c rename to src/kernel/fs.c index 2c9fc13..6d26978 100644 --- a/src/fs.c +++ b/src/kernel/fs.c @@ -1,5 +1,5 @@ -#include "src/fs.h" -#include "src/fat16.h" +#include "src/kernel/fs.h" +#include "src/kernel/fat16.h" fs_node_t *fs_mount() { return fat16_mount(); diff --git a/src/fs.h b/src/kernel/fs.h similarity index 100% rename from src/fs.h rename to src/kernel/fs.h diff --git a/src/gdt.c b/src/kernel/gdt.c similarity index 96% rename from src/gdt.c rename to src/kernel/gdt.c index 89a8535..5daa146 100644 --- a/src/gdt.c +++ b/src/kernel/gdt.c @@ -1,6 +1,5 @@ -#include "src/gdt.h" -#include "src/tss.h" -#include +#include "src/kernel/gdt.h" +#include "src/kernel/tss.h" typedef struct { uint16_t limit_low; diff --git a/src/gdt.h b/src/kernel/gdt.h similarity index 100% rename from src/gdt.h rename to src/kernel/gdt.h diff --git a/src/idt.c b/src/kernel/idt.c similarity index 97% rename from src/idt.c rename to src/kernel/idt.c index 659b911..dfb2da4 100644 --- a/src/idt.c +++ b/src/kernel/idt.c @@ -1,4 +1,4 @@ -#include "src/idt.h" +#include "src/kernel/idt.h" struct idt_entry { uint16_t offset_low; diff --git a/src/idt.h b/src/kernel/idt.h similarity index 100% rename from src/idt.h rename to src/kernel/idt.h diff --git a/src/kernel.c b/src/kernel/kernel.c similarity index 82% rename from src/kernel.c rename to src/kernel/kernel.c index cc790ee..41b3b16 100644 --- a/src/kernel.c +++ b/src/kernel/kernel.c @@ -1,15 +1,15 @@ -#include "src/fs.h" -#include "src/gdt.h" -#include "src/idt.h" -#include "src/keyboard.h" -#include "src/memory.h" -#include "src/panic.h" -#include "src/path.h" -#include "src/pic.h" -#include "src/process.h" -#include "src/syscall.h" -#include "src/util.h" -#include "src/vga.h" +#include "src/kernel/fs.h" +#include "src/kernel/gdt.h" +#include "src/kernel/idt.h" +#include "src/kernel/keyboard.h" +#include "src/kernel/panic.h" +#include "src/kernel/path.h" +#include "src/kernel/pic.h" +#include "src/kernel/process.h" +#include "src/kernel/syscall.h" +#include "src/kernel/util.h" +#include "src/kernel/vga.h" +#include "src/lib/memory.h" __attribute__((interrupt)) void isr_divide_by_zero(__attribute__((unused)) struct interrupt_frame *frame) { vga_set_string(VGA_HEIGHT - 1, 0, "EXCEPTION: divide by zero", 0x4F); @@ -47,8 +47,6 @@ void kernel_main() { gdt_init(); syscall_init(); - memory_init(); - process_t *kp = memory_allocate(sizeof(process_t)); kp->root = fs_mount(); kp->cwd = memory_allocate(sizeof(path_t)); @@ -69,7 +67,8 @@ void kernel_main() { process_run(proc); - while (1); + while (1) + ; fs_unmount(kp->root); diff --git a/src/kernel_entry.asm b/src/kernel/kernel_entry.asm similarity index 100% rename from src/kernel_entry.asm rename to src/kernel/kernel_entry.asm diff --git a/src/keyboard.c b/src/kernel/keyboard.c similarity index 95% rename from src/keyboard.c rename to src/kernel/keyboard.c index 4fd5b98..60e807d 100644 --- a/src/keyboard.c +++ b/src/kernel/keyboard.c @@ -1,9 +1,8 @@ -#include "src/keyboard.h" -#include "src/idt.h" -#include "src/memory.h" -#include "src/stream.h" -#include "src/util.h" -#include +#include "src/kernel/keyboard.h" +#include "src/kernel/idt.h" +#include "src/kernel/stream.h" +#include "src/kernel/util.h" +#include "src/lib/memory.h" #define KEYBOARD_STATE_LSHIFT 0b00000001 #define KEYBOARD_STATE_RSHIFT 0b00000010 @@ -51,7 +50,8 @@ static void append_sequence(const char *s) { } } -static void stream_write(__attribute__((unused)) stream_t *self, __attribute__((unused)) const char *from, __attribute__((unused)) uint64_t size) { +static void stream_write(__attribute__((unused)) stream_t *self, __attribute__((unused)) const char *from, + __attribute__((unused)) uint64_t size) { } static uint64_t stream_read(__attribute__((unused)) stream_t *self, uint64_t max, char *to) { diff --git a/src/keyboard.h b/src/kernel/keyboard.h similarity index 66% rename from src/keyboard.h rename to src/kernel/keyboard.h index ddf730d..3c47fd5 100644 --- a/src/keyboard.h +++ b/src/kernel/keyboard.h @@ -1,6 +1,6 @@ #pragma once -#include "src/stream.h" +#include "src/kernel/stream.h" #include stream_t *keyboard_init(); diff --git a/src/linker.ld b/src/kernel/linker.ld similarity index 100% rename from src/linker.ld rename to src/kernel/linker.ld diff --git a/src/memory.c b/src/kernel/memory.c similarity index 64% rename from src/memory.c rename to src/kernel/memory.c index da22192..28e2e87 100644 --- a/src/memory.c +++ b/src/kernel/memory.c @@ -1,14 +1,28 @@ -#include "src/memory.h" -#include "src/panic.h" -#include "src/util.h" +#include "src/kernel/memory.h" +#include "src/kernel/panic.h" +#include "src/lib/layout.h" +#include "src/lib/memory.h" #define MAP_UNIT 64 #define FULL_UNIT 0xFFFFFFFFFFFFFFFF -// Claim 2MB for bootloader, kernel, and stuff. -static uint16_t free_page = MAP_UNIT * 8; -static uint64_t allocation[PAGE_COUNT / MAP_UNIT] = {FULL_UNIT, FULL_UNIT, FULL_UNIT, FULL_UNIT, - FULL_UNIT, FULL_UNIT, FULL_UNIT, FULL_UNIT}; +// TODO keep aligned with `src/lib/layout.h`. +static uint16_t free_page = MAP_UNIT * 12; +static uint64_t allocation[PAGE_COUNT / MAP_UNIT] = { + FULL_UNIT, + FULL_UNIT, + FULL_UNIT, + FULL_UNIT, + FULL_UNIT, + FULL_UNIT, + FULL_UNIT, + FULL_UNIT, + FULL_UNIT, + FULL_UNIT, + FULL_UNIT, + FULL_UNIT, + [59] = 0x8000000000000000ULL, +}; static uint8_t get_allocated(uint16_t page) { return !!allocation[page / MAP_UNIT] & ((uint64_t)1 << (page % MAP_UNIT)); @@ -104,58 +118,3 @@ void memory_page_unmap(uint64_t *pml4, void *virt) { __asm__ volatile("invlpg (%0)" : : "r"(virt) : "memory"); } - -typedef struct free_chunk { - uint64_t size; // header + data - struct free_chunk *next; -} free_chunk_t; - -static free_chunk_t *free_list; - -void memory_init() { - free_list = PHYS_TO_VIRT(memory_page_allocate()); - for (uint64_t i = 1; i < HEAP_PAGE_COUNT; i++) { - memory_page_allocate(); - } - free_list->size = HEAP_PAGE_COUNT * PAGE_SIZE; - free_list->next = NUL; -} - -void *memory_allocate(uint64_t size) { - size = sizeof(free_chunk_t) + (size + 7) & (uint64_t)~7; - - free_chunk_t *prev = NUL; - free_chunk_t *curr = free_list; - - while (curr) { - if (curr->size >= size + (sizeof(free_chunk_t) + 8)) { - free_chunk_t *remainder = (free_chunk_t *)((uint8_t *)curr + size); - remainder->size = curr->size - size; - remainder->next = curr->next; - curr->size = size; - curr->next = remainder; - } - if (curr->size >= size) { - if (prev) { - prev->next = curr->next; - } else { - free_list = curr->next; - } - void *result = (void *)((uint8_t *)curr + sizeof(free_chunk_t)); - memory_set(0, size - sizeof(free_chunk_t), result); - return result; - } - prev = curr; - curr = curr->next; - } - - ASSERT(0, "memory_heap_allocate: out of heap memory"); - return 0; -} - -void memory_free(void *pointer) { - free_chunk_t *chunk = (free_chunk_t *)((uint8_t *)pointer - sizeof(free_chunk_t)); - chunk->next = free_list; - free_list = chunk; - // TODO Merge adjacent free chunks. -} diff --git a/src/kernel/memory.h b/src/kernel/memory.h new file mode 100644 index 0000000..9d9b610 --- /dev/null +++ b/src/kernel/memory.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#define PAGE_PRESENT 0x01 +#define PAGE_WRITABLE 0x02 +#define PAGE_USER 0x04 +#define PAGE_PWT 0x08 +#define PAGE_PCD 0x10 +#define PAGE_ACCESSED 0x20 +#define PAGE_DIRTY 0x40 +#define PAGE_HUGE 0x80 +#define PAGE_GLOBAL 0x100 +#define PAGE_NX (1ULL << 63) + +void *memory_page_allocate(); + +void memory_page_free(void *page); + +void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags); + +void memory_page_unmap(uint64_t *pml4, void *virt); diff --git a/src/panic.c b/src/kernel/panic.c similarity index 75% rename from src/panic.c rename to src/kernel/panic.c index 207016b..f7adc8c 100644 --- a/src/panic.c +++ b/src/kernel/panic.c @@ -1,5 +1,5 @@ -#include "src/panic.h" -#include "src/vga.h" +#include "src/kernel/panic.h" +#include "src/kernel/vga.h" void kernel_panic(const char *msg, __attribute__((unused)) const char *file, __attribute__((unused)) int line) { vga_set_string(0, VGA_HEIGHT - 1, msg, 0x28); diff --git a/src/panic.h b/src/kernel/panic.h similarity index 100% rename from src/panic.h rename to src/kernel/panic.h diff --git a/src/path.c b/src/kernel/path.c similarity index 89% rename from src/path.c rename to src/kernel/path.c index cca28fe..41ccfd5 100644 --- a/src/path.c +++ b/src/kernel/path.c @@ -1,8 +1,8 @@ -#include "src/path.h" -#include "src/fs.h" -#include "src/memory.h" -#include "src/string.h" -#include "src/util.h" +#include "src/kernel/path.h" +#include "src/kernel/fs.h" +#include "src/lib/memory.h" +#include "src/lib/string.h" +#include "src/lib/util.h" path_t *path_open(const fs_node_t *root, const path_t *source, char *path) { path_t *result = memory_allocate(sizeof(path_t)); diff --git a/src/path.h b/src/kernel/path.h similarity index 90% rename from src/path.h rename to src/kernel/path.h index 9ccd20a..9d09df6 100644 --- a/src/path.h +++ b/src/kernel/path.h @@ -1,6 +1,6 @@ #pragma once -#include "src/fs.h" +#include "src/kernel/fs.h" #include #define PATH_DEPTH 255 diff --git a/src/pic.c b/src/kernel/pic.c similarity index 88% rename from src/pic.c rename to src/kernel/pic.c index c599509..770d23c 100644 --- a/src/pic.c +++ b/src/kernel/pic.c @@ -1,5 +1,5 @@ -#include "src/pic.h" -#include "src/util.h" +#include "src/kernel/pic.h" +#include "src/kernel/util.h" static void pic_remap() { uint8_t mask1 = inb(0x21); diff --git a/src/pic.h b/src/kernel/pic.h similarity index 100% rename from src/pic.h rename to src/kernel/pic.h diff --git a/src/process.c b/src/kernel/process.c similarity index 91% rename from src/process.c rename to src/kernel/process.c index 1b193e8..bf9b923 100644 --- a/src/process.c +++ b/src/kernel/process.c @@ -1,9 +1,11 @@ -#include "src/process.h" -#include "src/gdt.h" -#include "src/memory.h" -#include "src/panic.h" -#include "src/path.h" -#include "src/tss.h" +#include "src/kernel/process.h" +#include "src/kernel/gdt.h" +#include "src/kernel/memory.h" +#include "src/kernel/panic.h" +#include "src/kernel/path.h" +#include "src/kernel/tss.h" +#include "src/lib/layout.h" +#include "src/lib/memory.h" process_t *current_process; @@ -16,7 +18,7 @@ process_t *process_create(const process_t *parent, const uint8_t *code, uint64_t proc->pml4 = PHYS_TO_VIRT(memory_page_allocate()); memory_set(0, PAGE_SIZE / 2, proc->pml4); - memory_copy((uint64_t *)KERNEL_PML4 + 256, PAGE_SIZE / 2, proc->pml4 + 256); + memory_copy((uint64_t *)KERNEL_VIRTUAL_PML4 + 256, PAGE_SIZE / 2, proc->pml4 + 256); memory_page_map(proc->pml4, (void *)USER_VIRTUAL_STACK, memory_page_allocate(), PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER); diff --git a/src/process.h b/src/kernel/process.h similarity index 84% rename from src/process.h rename to src/kernel/process.h index 2429dcf..53b230a 100644 --- a/src/process.h +++ b/src/kernel/process.h @@ -1,9 +1,9 @@ #pragma once -#include "src/fs.h" -#include "src/path.h" -#include "src/stream.h" -#include "src/string.h" +#include "src/kernel/fs.h" +#include "src/kernel/path.h" +#include "src/kernel/stream.h" +#include "src/lib/string.h" #define USER_RFLAGS 0x202 diff --git a/src/stream.h b/src/kernel/stream.h similarity index 100% rename from src/stream.h rename to src/kernel/stream.h diff --git a/src/syscall.asm b/src/kernel/syscall.asm similarity index 100% rename from src/syscall.asm rename to src/kernel/syscall.asm diff --git a/src/syscall.c b/src/kernel/syscall.c similarity index 79% rename from src/syscall.c rename to src/kernel/syscall.c index c325e81..8db6521 100644 --- a/src/syscall.c +++ b/src/kernel/syscall.c @@ -1,8 +1,8 @@ -#include "src/syscall.h" -#include "src/gdt.h" -#include "src/memory.h" -#include "src/process.h" -#include "src/util.h" +#include "src/kernel/syscall.h" +#include "src/kernel/gdt.h" +#include "src/kernel/process.h" +#include "src/lib/layout.h" +#include "src/lib/util.h" #define MSR_EFER 0xC0000080 #define MSR_STAR 0xC0000081 @@ -28,14 +28,13 @@ void syscall_init() { wrmsr(MSR_FMASK, 0x200); } -static void write(uint64_t fd, uint64_t buf, uint64_t size) { +static void write(uint64_t fd, uint64_t data, uint64_t bytes) { (void)fd; - current_process->stdout->write(current_process->stdout, (const char *)buf, size); + current_process->stdout->write(current_process->stdout, (const char *)data, bytes); } static void exit() { - __asm__ volatile("mov %0, %%cr3" : : "r"(KERNEL_PML4) : "memory"); - + __asm__ volatile("mov %0, %%cr3" : : "r"(KERNEL_VIRTUAL_PML4) : "memory"); process_destroy(current_process); current_process = NUL; diff --git a/src/syscall.h b/src/kernel/syscall.h similarity index 100% rename from src/syscall.h rename to src/kernel/syscall.h diff --git a/src/tss.c b/src/kernel/tss.c similarity index 85% rename from src/tss.c rename to src/kernel/tss.c index a8ec480..ddaa63f 100644 --- a/src/tss.c +++ b/src/kernel/tss.c @@ -1,4 +1,4 @@ -#include "src/tss.h" +#include "src/kernel/tss.h" tss_t tss = { .iopb_offset = sizeof(tss_t) // points past end of TSS = no I/O permissions diff --git a/src/tss.h b/src/kernel/tss.h similarity index 100% rename from src/tss.h rename to src/kernel/tss.h diff --git a/src/util.h b/src/kernel/util.h similarity index 91% rename from src/util.h rename to src/kernel/util.h index b31c4c6..6377ef3 100644 --- a/src/util.h +++ b/src/kernel/util.h @@ -2,8 +2,6 @@ #include -#define NUL 0 // TODO Fix VSCode thinking `NULL` conflicts with some other definition. - static inline uint8_t inb(uint16_t port) { uint8_t value; __asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port)); diff --git a/src/vga.c b/src/kernel/vga.c similarity index 96% rename from src/vga.c rename to src/kernel/vga.c index 6203d0e..011c095 100644 --- a/src/vga.c +++ b/src/kernel/vga.c @@ -1,6 +1,7 @@ -#include "src/vga.h" -#include "src/memory.h" -#include "src/util.h" +#include "src/kernel/vga.h" +#include "src/kernel/panic.h" +#include "src/kernel/util.h" +#include "src/lib/memory.h" static uint16_t *vga = (uint16_t *)0xFFFFFFFF800B8000; static uint16_t color = (uint16_t)0x0F << 8; diff --git a/src/vga.h b/src/kernel/vga.h similarity index 83% rename from src/vga.h rename to src/kernel/vga.h index cb5a220..47769cd 100644 --- a/src/vga.h +++ b/src/kernel/vga.h @@ -1,6 +1,6 @@ #pragma once -#include "src/stream.h" +#include "src/kernel/stream.h" #define VGA_WIDTH 80 #define VGA_HEIGHT 25 diff --git a/src/lib/layout.h b/src/lib/layout.h new file mode 100644 index 0000000..d545bba --- /dev/null +++ b/src/lib/layout.h @@ -0,0 +1,26 @@ +#pragma once + +#define MEMORY_SIZE 0x08000000 +#define PAGE_SIZE 4096 +#define PAGE_COUNT (MEMORY_SIZE / PAGE_SIZE) + +#define HEAP_PAGE_COUNT 256 +#define HEAP_SIZE (HEAP_PAGE_COUNT * PAGE_SIZE) + +#define KERNEL_VIRTUAL_BASE 0xFFFFFFFF80000000ULL +#define PHYS_TO_VIRT(phys) ((void *)((uint64_t)(phys) + KERNEL_VIRTUAL_BASE)) +#define VIRT_TO_PHYS(virt) ((uint64_t)(virt) - KERNEL_VIRTUAL_BASE) + +#define KERNEL_VIRTUAL_PML4 (KERNEL_VIRTUAL_BASE + 0x10000) +#define KERNEL_VIRTUAL_CODE (KERNEL_VIRTUAL_PML4 + 0x10000) +#define KERNEL_VIRTUAL_HEAP (KERNEL_VIRTUAL_CODE + 0x100000) +#define KERNEL_VIRTUAL_UNUSED (KERNEL_VIRTUAL_HEAP + HEAP_SIZE) +#define KERNEL_VIRTUAL_STACK (KERNEL_VIRTUAL_BASE + 0xF00000 - PAGE_SIZE) +#define KERNEL_VIRTUAL_STACK_TOP (KERNEL_VIRTUAL_STACK + PAGE_SIZE) + +#define USER_VIRTUAL_BASE 0x0000000000000000ULL +#define USER_VIRTUAL_CODE (USER_VIRTUAL_BASE + 0x400000) +#define USER_VIRTUAL_HEAP (USER_VIRTUAL_CODE + 0x100000) +#define USER_VIRTUAL_UNUSED (USER_VIRTUAL_HEAP + HEAP_SIZE) +#define USER_VIRTUAL_STACK (0x0000700000000000ULL - PAGE_SIZE) +#define USER_VIRTUAL_STACK_TOP (USER_VIRTUAL_STACK + PAGE_SIZE) diff --git a/src/lib/memory.c b/src/lib/memory.c new file mode 100644 index 0000000..972a6d2 --- /dev/null +++ b/src/lib/memory.c @@ -0,0 +1,60 @@ +#include "src/lib/memory.h" +#include "src/lib/layout.h" +#include "src/lib/util.h" + +#ifdef KERNEL +#define HEAP_VIRTUAL_BASE KERNEL_VIRTUAL_HEAP +#else +#define HEAP_VIRTUAL_BASE USER_VIRTUAL_HEAP +#endif + +typedef struct free_chunk { + uint64_t size; // header + data + struct free_chunk *next; +} free_chunk_t; + +static free_chunk_t *free_list; + +void *memory_allocate(uint64_t size) { + if (!free_list) { + free_list = (free_chunk_t *)HEAP_VIRTUAL_BASE; + free_list->size = HEAP_SIZE; + free_list->next = NUL; + } + + size = sizeof(free_chunk_t) + (size + 7) & (uint64_t)~7; + + free_chunk_t *prev = NUL; + free_chunk_t *curr = free_list; + + while (curr) { + if (curr->size >= size + (sizeof(free_chunk_t) + 8)) { + free_chunk_t *remainder = (free_chunk_t *)((uint8_t *)curr + size); + remainder->size = curr->size - size; + remainder->next = curr->next; + curr->size = size; + curr->next = remainder; + } + if (curr->size >= size) { + if (prev) { + prev->next = curr->next; + } else { + free_list = curr->next; + } + void *result = (void *)((uint8_t *)curr + sizeof(free_chunk_t)); + memory_set(0, size - sizeof(free_chunk_t), result); + return result; + } + prev = curr; + curr = curr->next; + } + + return NUL; +} + +void memory_free(void *pointer) { + free_chunk_t *chunk = (free_chunk_t *)((uint8_t *)pointer - sizeof(free_chunk_t)); + chunk->next = free_list; + free_list = chunk; + // TODO Merge adjacent free chunks. +} diff --git a/src/lib/memory.h b/src/lib/memory.h new file mode 100644 index 0000000..a682d2f --- /dev/null +++ b/src/lib/memory.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +void *memory_allocate(uint64_t size); + +void memory_free(void *pointer); + +static inline void memory_set(uint8_t value, uint64_t bytes, void *to) { + __asm__ volatile("rep stosb" : "=D"(to), "=c"(bytes) : "D"(to), "a"(value), "c"(bytes) : "memory"); +} + +static inline void memory_move(void *from, uint64_t bytes, void *to) { + if (to == from) { + return; + } else if (to < from) { + __asm__ volatile("rep movsb" : "=D"(to), "=S"(from), "=c"(bytes) : "D"(to), "S"(from), "c"(bytes) : "memory"); + } else { + // TODO ASSERT(0, "memory_move: forward overlapping move not implemented"); + } +} + +static inline void memory_copy(const void *from, uint64_t bytes, void *to) { + // TODO ASSERT((uint64_t)to + bytes <= (uint64_t)from || (uint64_t)to >= (uint64_t)from + bytes, "memory_copy: overlapping backward + // copy"); + + __asm__ volatile("rep movsb" : "=D"(to), "=S"(from), "=c"(bytes) : "D"(to), "S"(from), "c"(bytes) : "memory"); +} diff --git a/src/string.c b/src/lib/string.c similarity index 99% rename from src/string.c rename to src/lib/string.c index 27f3e3e..79a4e93 100644 --- a/src/string.c +++ b/src/lib/string.c @@ -1,4 +1,4 @@ -#include "src/string.h" +#include "src/lib/string.h" #include uint8_t bytes_equal(const char *l, const char *r, uint64_t count) { diff --git a/src/string.h b/src/lib/string.h similarity index 100% rename from src/string.h rename to src/lib/string.h diff --git a/src/lib/util.h b/src/lib/util.h new file mode 100644 index 0000000..6551b63 --- /dev/null +++ b/src/lib/util.h @@ -0,0 +1,3 @@ +#pragma once + +#define NUL 0 // TODO Fix VSCode thinking `NULL` conflicts with some other definition. diff --git a/src/memory.h b/src/memory.h deleted file mode 100644 index eb2cf1b..0000000 --- a/src/memory.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include "src/panic.h" -#include - -#define PAGE_PRESENT 0x01 -#define PAGE_WRITABLE 0x02 -#define PAGE_USER 0x04 -#define PAGE_PWT 0x08 -#define PAGE_PCD 0x10 -#define PAGE_ACCESSED 0x20 -#define PAGE_DIRTY 0x40 -#define PAGE_HUGE 0x80 -#define PAGE_GLOBAL 0x100 -#define PAGE_NX (1ULL << 63) - -#define MEMORY_SIZE 0x08000000 -#define PAGE_SIZE 4096 -#define PAGE_COUNT (MEMORY_SIZE / PAGE_SIZE) - -#define HEAP_PAGE_COUNT 256 - -#define KERNEL_VIRTUAL_BASE 0xFFFFFFFF80000000ULL -#define PHYS_TO_VIRT(phys) ((void *)((uint64_t)(phys) + KERNEL_VIRTUAL_BASE)) -#define VIRT_TO_PHYS(virt) ((uint64_t)(virt) - KERNEL_VIRTUAL_BASE) - -#define KERNEL_PML4 0xFFFFFFFF80010000ULL - -#define USER_VIRTUAL_BASE 0x0000000000000000ULL -#define USER_VIRTUAL_CODE (USER_VIRTUAL_BASE + 0x400000) -#define USER_VIRTUAL_HEAP (USER_VIRTUAL_CODE + 0x400000) -#define USER_VIRTUAL_STACK (0x0000700000000000ULL - PAGE_SIZE) - -void memory_init(); - -void *memory_page_allocate(); - -void memory_page_free(void *page); - -void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags); - -void memory_page_unmap(uint64_t *pml4, void *virt); - -void *memory_allocate(uint64_t size); - -void memory_free(void *pointer); - -static inline void memory_set(uint8_t value, uint64_t bytes, void *to) { - __asm__ volatile("rep stosb" : "=D"(to), "=c"(bytes) : "D"(to), "a"(value), "c"(bytes) : "memory"); -} - -static inline void memory_move(void *from, uint64_t bytes, void *to) { - if (to == from) { - return; - } else if (to < from) { - __asm__ volatile("rep movsb" : "=D"(to), "=S"(from), "=c"(bytes) : "D"(to), "S"(from), "c"(bytes) : "memory"); - } else { - ASSERT(0, "memory_move: forward overlapping move not implemented"); - } -} - -static inline void memory_copy(const void *from, uint64_t bytes, void *to) { - ASSERT((uint64_t)to + bytes <= (uint64_t)from || (uint64_t)to >= (uint64_t)from + bytes, "memory_copy: overlapping backward copy"); - - __asm__ volatile("rep movsb" : "=D"(to), "=S"(from), "=c"(bytes) : "D"(to), "S"(from), "c"(bytes) : "memory"); -} diff --git a/src/user/app/hello/hello.c b/src/user/app/hello/hello.c new file mode 100644 index 0000000..eb0e00d --- /dev/null +++ b/src/user/app/hello/hello.c @@ -0,0 +1,6 @@ +#include "src/user/syscall.h" + +int main() { + write(1, "Hello from C!\n", 14); + return 0; +} diff --git a/src/user/linker.ld b/src/user/linker.ld new file mode 100644 index 0000000..5ff9262 --- /dev/null +++ b/src/user/linker.ld @@ -0,0 +1,10 @@ +ENTRY(_start) + +SECTIONS { + . = 0x0000000000400000; + + .text : { *(.text) } + .rodata : { *(.rodata) } + .data : { *(.data) } + .bss : { *(.bss) } +} diff --git a/src/user/start.asm b/src/user/start.asm new file mode 100644 index 0000000..08b6c02 --- /dev/null +++ b/src/user/start.asm @@ -0,0 +1,10 @@ +bits 64 + +extern main + +global _start +_start: + call main + mov rdi, rax ; return value + mov rax, 60 ; exit syscall + syscall diff --git a/src/user/syscall.asm b/src/user/syscall.asm new file mode 100644 index 0000000..872e773 --- /dev/null +++ b/src/user/syscall.asm @@ -0,0 +1,13 @@ +bits 64 + +global write +write: + mov rax, 1 + syscall + ret + +global exit +exit: + mov rax, 60 + syscall + ; never returns diff --git a/src/user/syscall.h b/src/user/syscall.h new file mode 100644 index 0000000..081054f --- /dev/null +++ b/src/user/syscall.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +void write(int64_t fd, const void *data, uint64_t bytes); + +void exit();