Add first C user program
This commit is contained in:
+63
-31
@@ -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
|
||||
+1
-1
@@ -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();
|
||||
Reference in New Issue
Block a user