Add first C user program

master
Freywar Ulvnaudgari 1 month ago
parent b32c12b311
commit 1c935cf154
  1. 94
      meson.build
  2. 16
      src/app/hello.asm
  3. 2
      src/bootloader.asm
  4. 9
      src/kernel/app/cat.c
  5. 2
      src/kernel/app/cat.h
  6. 6
      src/kernel/app/ls.c
  7. 2
      src/kernel/app/ls.h
  8. 20
      src/kernel/app/terminal.c
  9. 2
      src/kernel/app/terminal.h
  10. 6
      src/kernel/ata.c
  11. 0
      src/kernel/ata.h
  12. 14
      src/kernel/fat16.c
  13. 2
      src/kernel/fat16.h
  14. 4
      src/kernel/fs.c
  15. 0
      src/kernel/fs.h
  16. 5
      src/kernel/gdt.c
  17. 0
      src/kernel/gdt.h
  18. 2
      src/kernel/idt.c
  19. 0
      src/kernel/idt.h
  20. 29
      src/kernel/kernel.c
  21. 0
      src/kernel/kernel_entry.asm
  22. 14
      src/kernel/keyboard.c
  23. 2
      src/kernel/keyboard.h
  24. 0
      src/kernel/linker.ld
  25. 83
      src/kernel/memory.c
  26. 22
      src/kernel/memory.h
  27. 4
      src/kernel/panic.c
  28. 0
      src/kernel/panic.h
  29. 10
      src/kernel/path.c
  30. 2
      src/kernel/path.h
  31. 4
      src/kernel/pic.c
  32. 0
      src/kernel/pic.h
  33. 16
      src/kernel/process.c
  34. 8
      src/kernel/process.h
  35. 0
      src/kernel/stream.h
  36. 0
      src/kernel/syscall.asm
  37. 17
      src/kernel/syscall.c
  38. 0
      src/kernel/syscall.h
  39. 2
      src/kernel/tss.c
  40. 0
      src/kernel/tss.h
  41. 2
      src/kernel/util.h
  42. 7
      src/kernel/vga.c
  43. 2
      src/kernel/vga.h
  44. 26
      src/lib/layout.h
  45. 60
      src/lib/memory.c
  46. 28
      src/lib/memory.h
  47. 2
      src/lib/string.c
  48. 0
      src/lib/string.h
  49. 3
      src/lib/util.h
  50. 66
      src/memory.h
  51. 6
      src/user/app/hello/hello.c
  52. 10
      src/user/linker.ld
  53. 10
      src/user/start.asm
  54. 13
      src/user/syscall.asm
  55. 7
      src/user/syscall.h

@ -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,
)

@ -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

@ -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

@ -1,8 +1,7 @@
#include "src/app/cat.h"
#include "src/fs.h"
#include "src/memory.h"
#include "src/path.h"
#include <stdint.h>
#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) {

@ -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);

@ -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 <stdint.h>
void ls(process_t *proc, uint8_t argc, char **argv) {

@ -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);

@ -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 <stdint.h>
#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);

@ -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);

@ -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

@ -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 <stdint.h>
#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

@ -1,6 +1,6 @@
#pragma once
#include "src/fs.h"
#include "src/kernel/fs.h"
#define FAT16 1

@ -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();

@ -1,6 +1,5 @@
#include "src/gdt.h"
#include "src/tss.h"
#include <stdint.h>
#include "src/kernel/gdt.h"
#include "src/kernel/tss.h"
typedef struct {
uint16_t limit_low;

@ -1,4 +1,4 @@
#include "src/idt.h"
#include "src/kernel/idt.h"
struct idt_entry {
uint16_t offset_low;

@ -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);

@ -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 <stdint.h>
#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) {

@ -1,6 +1,6 @@
#pragma once
#include "src/stream.h"
#include "src/kernel/stream.h"
#include <stdint.h>
stream_t *keyboard_init();

@ -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.
}

@ -0,0 +1,22 @@
#pragma once
#include <stdint.h>
#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);

@ -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);

@ -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));

@ -1,6 +1,6 @@
#pragma once
#include "src/fs.h"
#include "src/kernel/fs.h"
#include <stdint.h>
#define PATH_DEPTH 255

@ -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);

@ -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);

@ -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

@ -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;

@ -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

@ -2,8 +2,6 @@
#include <stdint.h>
#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));

@ -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;

@ -1,6 +1,6 @@
#pragma once
#include "src/stream.h"
#include "src/kernel/stream.h"
#define VGA_WIDTH 80
#define VGA_HEIGHT 25

@ -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)

@ -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.
}

@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
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");
}

@ -1,4 +1,4 @@
#include "src/string.h"
#include "src/lib/string.h"
#include <stdarg.h>
uint8_t bytes_equal(const char *l, const char *r, uint64_t count) {

@ -0,0 +1,3 @@
#pragma once
#define NUL 0 // TODO Fix VSCode thinking `NULL` conflicts with some other definition.

@ -1,66 +0,0 @@
#pragma once
#include "src/panic.h"
#include <stdint.h>
#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");
}

@ -0,0 +1,6 @@
#include "src/user/syscall.h"
int main() {
write(1, "Hello from C!\n", 14);
return 0;
}

@ -0,0 +1,10 @@
ENTRY(_start)
SECTIONS {
. = 0x0000000000400000;
.text : { *(.text) }
.rodata : { *(.rodata) }
.data : { *(.data) }
.bss : { *(.bss) }
}

@ -0,0 +1,10 @@
bits 64
extern main
global _start
_start:
call main
mov rdi, rax ; return value
mov rax, 60 ; exit syscall
syscall

@ -0,0 +1,13 @@
bits 64
global write
write:
mov rax, 1
syscall
ret
global exit
exit:
mov rax, 60
syscall
; never returns

@ -0,0 +1,7 @@
#pragma once
#include <stdint.h>
void write(int64_t fd, const void *data, uint64_t bytes);
void exit();
Loading…
Cancel
Save