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, 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_o = custom_target(
'kernel_entry', 'kernel_entry',
input: 'src/kernel_entry.asm', input: 'src/kernel/kernel_entry.asm',
output: 'kernel_entry.o', output: 'kernel_entry.o',
command: [nasm, '-f', 'elf64', '@INPUT@', '-o', '@OUTPUT@'], command: [nasm, '-f', 'elf64', '@INPUT@', '-o', '@OUTPUT@'],
) )
syscall_o = custom_target('syscall', syscall_o = custom_target('syscall',
input: 'src/syscall.asm', input: 'src/kernel/syscall.asm',
output: 'syscall.o', output: 'syscall.o',
command: [nasm, '-f', 'elf64', '@INPUT@', '-o', '@OUTPUT@'], command: [nasm, '-f', 'elf64', '@INPUT@', '-o', '@OUTPUT@'],
) )
@ -55,25 +47,26 @@ syscall_o = custom_target('syscall',
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
kernel_sources = files( kernel_sources = files(
'src/app/cat.c', 'src/kernel/app/cat.c',
'src/app/ls.c', 'src/kernel/app/ls.c',
'src/app/terminal.c', 'src/kernel/app/terminal.c',
'src/ata.c', 'src/kernel/ata.c',
'src/fat16.c', 'src/kernel/fat16.c',
'src/fs.c', 'src/kernel/fs.c',
'src/gdt.c', 'src/kernel/gdt.c',
'src/idt.c', 'src/kernel/idt.c',
'src/kernel.c', 'src/kernel/kernel.c',
'src/keyboard.c', 'src/kernel/keyboard.c',
'src/memory.c', 'src/kernel/memory.c',
'src/panic.c', 'src/kernel/panic.c',
'src/path.c', 'src/kernel/path.c',
'src/pic.c', 'src/kernel/pic.c',
'src/process.c', 'src/kernel/process.c',
'src/string.c', 'src/kernel/syscall.c',
'src/syscall.c', 'src/kernel/tss.c',
'src/tss.c', 'src/kernel/vga.c',
'src/vga.c', 'src/lib/memory.c',
'src/lib/string.c',
) )
kernel_elf = executable( kernel_elf = executable(
@ -88,13 +81,14 @@ kernel_elf = executable(
'-mcmodel=kernel', '-mcmodel=kernel',
'-Wno-unused-command-line-argument', '-Wno-unused-command-line-argument',
'-Wconversion', '-Wconversion',
'-DKERNEL="yes"',
'-DVERSION="' + meson.project_version() + '"', '-DVERSION="' + meson.project_version() + '"',
], ],
link_args: [ link_args: [
'-T', meson.project_source_root() / 'src/linker.ld', '-T', meson.project_source_root() / 'src/kernel/linker.ld',
'-nostdlib', '-nostdlib',
], ],
link_depends: 'src/linker.ld', link_depends: 'src/kernel/linker.ld',
) )
custom_target( custom_target(
@ -104,3 +98,41 @@ custom_target(
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'], command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
build_by_default: true, 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 ds, ax
mov es, ax mov es, ax
mov ss, ax mov ss, ax
mov rsp, 0xFFFFFFFF80090000 mov rsp, 0xFFFFFFFF80F00000
xor rax, rax xor rax, rax
xor rbx, rbx xor rbx, rbx

@ -1,8 +1,7 @@
#include "src/app/cat.h" #include "src/kernel/app/cat.h"
#include "src/fs.h" #include "src/kernel/fs.h"
#include "src/memory.h" #include "src/kernel/path.h"
#include "src/path.h" #include "src/lib/memory.h"
#include <stdint.h>
void cat(process_t *proc, uint8_t argc, char **argv) { void cat(process_t *proc, uint8_t argc, char **argv) {
if (argc != 2) { if (argc != 2) {

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "src/process.h" #include "src/kernel/process.h"
void cat(process_t *proc, uint8_t argc, char **argv); void cat(process_t *proc, uint8_t argc, char **argv);

@ -1,6 +1,6 @@
#include "src/app/ls.h" #include "src/kernel/app/ls.h"
#include "src/fs.h" #include "src/kernel/fs.h"
#include "src/path.h" #include "src/kernel/path.h"
#include <stdint.h> #include <stdint.h>
void ls(process_t *proc, uint8_t argc, char **argv) { void ls(process_t *proc, uint8_t argc, char **argv) {

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "src/process.h" #include "src/kernel/process.h"
void ls(process_t *proc, uint8_t argc, char **argv); void ls(process_t *proc, uint8_t argc, char **argv);

@ -1,14 +1,12 @@
#include "src/app/terminal.h" #include "src/kernel/app/terminal.h"
#include "src/app/cat.h" #include "src/kernel/app/cat.h"
#include "src/app/ls.h" #include "src/kernel/app/ls.h"
#include "src/fs.h" #include "src/kernel/fs.h"
#include "src/memory.h" #include "src/kernel/path.h"
#include "src/path.h" #include "src/kernel/process.h"
#include "src/process.h" #include "src/lib/memory.h"
#include "src/string.h" #include "src/lib/string.h"
#include "src/util.h" #include "src/lib/util.h"
#include <stdint.h>
static void help(process_t *proc, uint8_t argc, char **argv); static void help(process_t *proc, uint8_t argc, char **argv);
static void cd(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 #pragma once
#include "src/process.h" #include "src/kernel/process.h"
void terminal(process_t *proc, uint8_t argc, char **argv); void terminal(process_t *proc, uint8_t argc, char **argv);

@ -1,6 +1,6 @@
#include "src/ata.h" #include "src/kernel/ata.h"
#include "src/panic.h" #include "src/kernel/panic.h"
#include "src/util.h" #include "src/kernel/util.h"
#define BSY 0b10000000 #define BSY 0b10000000
#define DF 0b00100000 #define DF 0b00100000

@ -1,10 +1,10 @@
#include "src/fat16.h" #include "src/kernel/fat16.h"
#include "src/ata.h" #include "src/kernel/ata.h"
#include "src/fs.h" #include "src/kernel/fs.h"
#include "src/memory.h" #include "src/kernel/panic.h"
#include "src/string.h" #include "src/lib/memory.h"
#include "src/util.h" #include "src/lib/string.h"
#include <stdint.h> #include "src/lib/util.h"
#define SECTOR_SIZE 512 #define SECTOR_SIZE 512
#define FIRST_PARTITION_SECTOR 2048 #define FIRST_PARTITION_SECTOR 2048

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

@ -1,5 +1,5 @@
#include "src/fs.h" #include "src/kernel/fs.h"
#include "src/fat16.h" #include "src/kernel/fat16.h"
fs_node_t *fs_mount() { fs_node_t *fs_mount() {
return fat16_mount(); return fat16_mount();

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

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

@ -1,15 +1,15 @@
#include "src/fs.h" #include "src/kernel/fs.h"
#include "src/gdt.h" #include "src/kernel/gdt.h"
#include "src/idt.h" #include "src/kernel/idt.h"
#include "src/keyboard.h" #include "src/kernel/keyboard.h"
#include "src/memory.h" #include "src/kernel/panic.h"
#include "src/panic.h" #include "src/kernel/path.h"
#include "src/path.h" #include "src/kernel/pic.h"
#include "src/pic.h" #include "src/kernel/process.h"
#include "src/process.h" #include "src/kernel/syscall.h"
#include "src/syscall.h" #include "src/kernel/util.h"
#include "src/util.h" #include "src/kernel/vga.h"
#include "src/vga.h" #include "src/lib/memory.h"
__attribute__((interrupt)) void isr_divide_by_zero(__attribute__((unused)) struct interrupt_frame *frame) { __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); vga_set_string(VGA_HEIGHT - 1, 0, "EXCEPTION: divide by zero", 0x4F);
@ -47,8 +47,6 @@ void kernel_main() {
gdt_init(); gdt_init();
syscall_init(); syscall_init();
memory_init();
process_t *kp = memory_allocate(sizeof(process_t)); process_t *kp = memory_allocate(sizeof(process_t));
kp->root = fs_mount(); kp->root = fs_mount();
kp->cwd = memory_allocate(sizeof(path_t)); kp->cwd = memory_allocate(sizeof(path_t));
@ -69,7 +67,8 @@ void kernel_main() {
process_run(proc); process_run(proc);
while (1); while (1)
;
fs_unmount(kp->root); fs_unmount(kp->root);

@ -1,9 +1,8 @@
#include "src/keyboard.h" #include "src/kernel/keyboard.h"
#include "src/idt.h" #include "src/kernel/idt.h"
#include "src/memory.h" #include "src/kernel/stream.h"
#include "src/stream.h" #include "src/kernel/util.h"
#include "src/util.h" #include "src/lib/memory.h"
#include <stdint.h>
#define KEYBOARD_STATE_LSHIFT 0b00000001 #define KEYBOARD_STATE_LSHIFT 0b00000001
#define KEYBOARD_STATE_RSHIFT 0b00000010 #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) { static uint64_t stream_read(__attribute__((unused)) stream_t *self, uint64_t max, char *to) {

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

@ -1,14 +1,28 @@
#include "src/memory.h" #include "src/kernel/memory.h"
#include "src/panic.h" #include "src/kernel/panic.h"
#include "src/util.h" #include "src/lib/layout.h"
#include "src/lib/memory.h"
#define MAP_UNIT 64 #define MAP_UNIT 64
#define FULL_UNIT 0xFFFFFFFFFFFFFFFF #define FULL_UNIT 0xFFFFFFFFFFFFFFFF
// Claim 2MB for bootloader, kernel, and stuff. // TODO keep aligned with `src/lib/layout.h`.
static uint16_t free_page = MAP_UNIT * 8; static uint16_t free_page = MAP_UNIT * 12;
static uint64_t allocation[PAGE_COUNT / MAP_UNIT] = {FULL_UNIT, FULL_UNIT, FULL_UNIT, FULL_UNIT, 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,
FULL_UNIT,
FULL_UNIT,
FULL_UNIT,
FULL_UNIT,
[59] = 0x8000000000000000ULL,
};
static uint8_t get_allocated(uint16_t page) { static uint8_t get_allocated(uint16_t page) {
return !!allocation[page / MAP_UNIT] & ((uint64_t)1 << (page % MAP_UNIT)); 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"); __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/kernel/panic.h"
#include "src/vga.h" #include "src/kernel/vga.h"
void kernel_panic(const char *msg, __attribute__((unused)) const char *file, __attribute__((unused)) int line) { void kernel_panic(const char *msg, __attribute__((unused)) const char *file, __attribute__((unused)) int line) {
vga_set_string(0, VGA_HEIGHT - 1, msg, 0x28); vga_set_string(0, VGA_HEIGHT - 1, msg, 0x28);

@ -1,8 +1,8 @@
#include "src/path.h" #include "src/kernel/path.h"
#include "src/fs.h" #include "src/kernel/fs.h"
#include "src/memory.h" #include "src/lib/memory.h"
#include "src/string.h" #include "src/lib/string.h"
#include "src/util.h" #include "src/lib/util.h"
path_t *path_open(const fs_node_t *root, const path_t *source, char *path) { path_t *path_open(const fs_node_t *root, const path_t *source, char *path) {
path_t *result = memory_allocate(sizeof(path_t)); path_t *result = memory_allocate(sizeof(path_t));

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

@ -1,5 +1,5 @@
#include "src/pic.h" #include "src/kernel/pic.h"
#include "src/util.h" #include "src/kernel/util.h"
static void pic_remap() { static void pic_remap() {
uint8_t mask1 = inb(0x21); uint8_t mask1 = inb(0x21);

@ -1,9 +1,11 @@
#include "src/process.h" #include "src/kernel/process.h"
#include "src/gdt.h" #include "src/kernel/gdt.h"
#include "src/memory.h" #include "src/kernel/memory.h"
#include "src/panic.h" #include "src/kernel/panic.h"
#include "src/path.h" #include "src/kernel/path.h"
#include "src/tss.h" #include "src/kernel/tss.h"
#include "src/lib/layout.h"
#include "src/lib/memory.h"
process_t *current_process; 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()); proc->pml4 = PHYS_TO_VIRT(memory_page_allocate());
memory_set(0, PAGE_SIZE / 2, proc->pml4); 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); memory_page_map(proc->pml4, (void *)USER_VIRTUAL_STACK, memory_page_allocate(), PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER);

@ -1,9 +1,9 @@
#pragma once #pragma once
#include "src/fs.h" #include "src/kernel/fs.h"
#include "src/path.h" #include "src/kernel/path.h"
#include "src/stream.h" #include "src/kernel/stream.h"
#include "src/string.h" #include "src/lib/string.h"
#define USER_RFLAGS 0x202 #define USER_RFLAGS 0x202

@ -1,8 +1,8 @@
#include "src/syscall.h" #include "src/kernel/syscall.h"
#include "src/gdt.h" #include "src/kernel/gdt.h"
#include "src/memory.h" #include "src/kernel/process.h"
#include "src/process.h" #include "src/lib/layout.h"
#include "src/util.h" #include "src/lib/util.h"
#define MSR_EFER 0xC0000080 #define MSR_EFER 0xC0000080
#define MSR_STAR 0xC0000081 #define MSR_STAR 0xC0000081
@ -28,14 +28,13 @@ void syscall_init() {
wrmsr(MSR_FMASK, 0x200); 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; (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() { 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); process_destroy(current_process);
current_process = NUL; current_process = NUL;

@ -1,4 +1,4 @@
#include "src/tss.h" #include "src/kernel/tss.h"
tss_t tss = { tss_t tss = {
.iopb_offset = sizeof(tss_t) // points past end of TSS = no I/O permissions .iopb_offset = sizeof(tss_t) // points past end of TSS = no I/O permissions

@ -2,8 +2,6 @@
#include <stdint.h> #include <stdint.h>
#define NUL 0 // TODO Fix VSCode thinking `NULL` conflicts with some other definition.
static inline uint8_t inb(uint16_t port) { static inline uint8_t inb(uint16_t port) {
uint8_t value; uint8_t value;
__asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port)); __asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port));

@ -1,6 +1,7 @@
#include "src/vga.h" #include "src/kernel/vga.h"
#include "src/memory.h" #include "src/kernel/panic.h"
#include "src/util.h" #include "src/kernel/util.h"
#include "src/lib/memory.h"
static uint16_t *vga = (uint16_t *)0xFFFFFFFF800B8000; static uint16_t *vga = (uint16_t *)0xFFFFFFFF800B8000;
static uint16_t color = (uint16_t)0x0F << 8; static uint16_t color = (uint16_t)0x0F << 8;

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "src/stream.h" #include "src/kernel/stream.h"
#define VGA_WIDTH 80 #define VGA_WIDTH 80
#define VGA_HEIGHT 25 #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> #include <stdarg.h>
uint8_t bytes_equal(const char *l, const char *r, uint64_t count) { 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