kernel: whatever changes i didn't keep track of lol
This commit is contained in:
parent
b2cf9b4710
commit
edbb5d106d
67 changed files with 340 additions and 88 deletions
0
.gitignore
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable file
0
GNUmakefile
Normal file → Executable file
0
GNUmakefile
Normal file → Executable file
0
LICENSE
Normal file → Executable file
0
LICENSE
Normal file → Executable file
4
README.md
Normal file → Executable file
4
README.md
Normal file → Executable file
|
@ -6,10 +6,10 @@ This is a carefully rewritten version of Soaplin, that should be held with super
|
||||||
* Support for compiling the kernel on armv8, RISC-V, and LoongArch64 (even though the kernel doesn't do anything on these architectures)
|
* Support for compiling the kernel on armv8, RISC-V, and LoongArch64 (even though the kernel doesn't do anything on these architectures)
|
||||||
* Free list PMM with lazy loading
|
* Free list PMM with lazy loading
|
||||||
* x86_64 paging
|
* x86_64 paging
|
||||||
|
|
||||||
## To do
|
|
||||||
* ACPI & MADT
|
* ACPI & MADT
|
||||||
* IOAPIC / LAPIC
|
* IOAPIC / LAPIC
|
||||||
|
|
||||||
|
## To do
|
||||||
* SMP
|
* SMP
|
||||||
* Multithreaded scheduler
|
* Multithreaded scheduler
|
||||||
* VFS
|
* VFS
|
||||||
|
|
0
kernel/.gitignore
vendored
Normal file → Executable file
0
kernel/.gitignore
vendored
Normal file → Executable file
0
kernel/GNUmakefile
Normal file → Executable file
0
kernel/GNUmakefile
Normal file → Executable file
0
kernel/linker-aarch64.ld
Normal file → Executable file
0
kernel/linker-aarch64.ld
Normal file → Executable file
0
kernel/linker-loongarch64.ld
Normal file → Executable file
0
kernel/linker-loongarch64.ld
Normal file → Executable file
0
kernel/linker-riscv64.ld
Normal file → Executable file
0
kernel/linker-riscv64.ld
Normal file → Executable file
0
kernel/linker-x86_64.ld
Normal file → Executable file
0
kernel/linker-x86_64.ld
Normal file → Executable file
0
kernel/src/acpi/acpi.c
Normal file → Executable file
0
kernel/src/acpi/acpi.c
Normal file → Executable file
0
kernel/src/acpi/acpi.h
Normal file → Executable file
0
kernel/src/acpi/acpi.h
Normal file → Executable file
0
kernel/src/acpi/madt.c
Normal file → Executable file
0
kernel/src/acpi/madt.c
Normal file → Executable file
0
kernel/src/acpi/madt.h
Normal file → Executable file
0
kernel/src/acpi/madt.h
Normal file → Executable file
0
kernel/src/arch/aarch64/cpu.c
Normal file → Executable file
0
kernel/src/arch/aarch64/cpu.c
Normal file → Executable file
3
kernel/src/arch/cpu.h
Normal file → Executable file
3
kernel/src/arch/cpu.h
Normal file → Executable file
|
@ -25,5 +25,8 @@ void cpu_init_smp();
|
||||||
// Initialize the CPU's timer
|
// Initialize the CPU's timer
|
||||||
void cpu_init_timer();
|
void cpu_init_timer();
|
||||||
|
|
||||||
|
// Enable/disable interrupts.
|
||||||
|
void cpu_enable_ints(int enabled);
|
||||||
|
|
||||||
// Disable interrupts and halt the system.
|
// Disable interrupts and halt the system.
|
||||||
void hcf();
|
void hcf();
|
0
kernel/src/arch/la64/cpu.c
Normal file → Executable file
0
kernel/src/arch/la64/cpu.c
Normal file → Executable file
0
kernel/src/arch/riscv/cpu.c
Normal file → Executable file
0
kernel/src/arch/riscv/cpu.c
Normal file → Executable file
4
kernel/src/arch/x86_64/cpu.c
Normal file → Executable file
4
kernel/src/arch/x86_64/cpu.c
Normal file → Executable file
|
@ -29,6 +29,10 @@ void cpu_invalidate_page(uint64_t vaddr) {
|
||||||
asm volatile ( "invlpg (%0)" : : "b"(vaddr) : "memory" );
|
asm volatile ( "invlpg (%0)" : : "b"(vaddr) : "memory" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cpu_enable_ints(int enabled) {
|
||||||
|
if (enabled) asm("sti"); else asm("cli");
|
||||||
|
}
|
||||||
|
|
||||||
void hcf() {
|
void hcf() {
|
||||||
asm ("cli");
|
asm ("cli");
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
0
kernel/src/arch/x86_64/cpu.h
Normal file → Executable file
0
kernel/src/arch/x86_64/cpu.h
Normal file → Executable file
6
kernel/src/arch/x86_64/gdt.asm
Normal file → Executable file
6
kernel/src/arch/x86_64/gdt.asm
Normal file → Executable file
|
@ -1,3 +1,9 @@
|
||||||
|
;
|
||||||
|
; The Soaplin Kernel
|
||||||
|
; Copyright (C) 2025 The SILD Project
|
||||||
|
;
|
||||||
|
; gdt.asm - Utility for reloading the segments.
|
||||||
|
|
||||||
bits 64
|
bits 64
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
|
|
2
kernel/src/arch/x86_64/gdt.c
Normal file → Executable file
2
kernel/src/arch/x86_64/gdt.c
Normal file → Executable file
|
@ -53,8 +53,6 @@ void gdt_init() {
|
||||||
__asm__ volatile("ltr %0\n\t" : : "r"((uint16_t)0x28)); // 0x20 (last GDT entry) + 0x8 (size of a GDT entry)
|
__asm__ volatile("ltr %0\n\t" : : "r"((uint16_t)0x28)); // 0x20 (last GDT entry) + 0x8 (size of a GDT entry)
|
||||||
|
|
||||||
gdt_reload_segments();
|
gdt_reload_segments();
|
||||||
|
|
||||||
trace("arch: GDT & TSS initialized.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
0
kernel/src/arch/x86_64/gdt.h
Normal file → Executable file
0
kernel/src/arch/x86_64/gdt.h
Normal file → Executable file
6
kernel/src/arch/x86_64/idt.asm
Normal file → Executable file
6
kernel/src/arch/x86_64/idt.asm
Normal file → Executable file
|
@ -1,3 +1,9 @@
|
||||||
|
;
|
||||||
|
; The Soaplin Kernel
|
||||||
|
; Copyright (C) 2025 The SILD Project
|
||||||
|
;
|
||||||
|
; idt.asm - Defines the handler for IDT entries.
|
||||||
|
;
|
||||||
|
|
||||||
%macro pushall 0
|
%macro pushall 0
|
||||||
push rax
|
push rax
|
||||||
|
|
9
kernel/src/arch/x86_64/idt.c
Normal file → Executable file
9
kernel/src/arch/x86_64/idt.c
Normal file → Executable file
|
@ -77,6 +77,10 @@ void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags) {
|
||||||
|
|
||||||
extern void* isr_stub_table[];
|
extern void* isr_stub_table[];
|
||||||
|
|
||||||
|
void idt_load() {
|
||||||
|
__asm__ volatile ("lidt %0" : : "m"(idtr));
|
||||||
|
}
|
||||||
|
|
||||||
void idt_init() {
|
void idt_init() {
|
||||||
idtr.base = (uintptr_t)&idt[0];
|
idtr.base = (uintptr_t)&idt[0];
|
||||||
idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1;
|
idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1;
|
||||||
|
@ -99,9 +103,8 @@ void idt_init() {
|
||||||
__idt_vectors[IDT_SPURIOUS_INT] = VT_SPURIOUS;
|
__idt_vectors[IDT_SPURIOUS_INT] = VT_SPURIOUS;
|
||||||
trace("idt: Spurious interrupt vector has been set!\n");
|
trace("idt: Spurious interrupt vector has been set!\n");
|
||||||
|
|
||||||
__asm__ volatile ("lidt %0" : : "m"(idtr));
|
//__asm__ volatile ("sti");
|
||||||
__asm__ volatile ("sti");
|
idt_load();
|
||||||
|
|
||||||
trace("arch: IDT loaded successfully\n");
|
trace("arch: IDT loaded successfully\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
kernel/src/arch/x86_64/idt.h
Normal file → Executable file
1
kernel/src/arch/x86_64/idt.h
Normal file → Executable file
|
@ -60,3 +60,4 @@ typedef struct {
|
||||||
|
|
||||||
void idt_register_handler(uint8_t vector, void *isr);
|
void idt_register_handler(uint8_t vector, void *isr);
|
||||||
void idt_init(void);
|
void idt_init(void);
|
||||||
|
void idt_load();
|
0
kernel/src/arch/x86_64/io.h
Normal file → Executable file
0
kernel/src/arch/x86_64/io.h
Normal file → Executable file
3
kernel/src/arch/x86_64/pit.c
Normal file → Executable file
3
kernel/src/arch/x86_64/pit.c
Normal file → Executable file
|
@ -8,10 +8,11 @@
|
||||||
|
|
||||||
#include <arch/x86_64/io.h>
|
#include <arch/x86_64/io.h>
|
||||||
#include <arch/x86_64/idt.h>
|
#include <arch/x86_64/idt.h>
|
||||||
|
#include <dev/lapic.h>
|
||||||
#include <lib/log.h>
|
#include <lib/log.h>
|
||||||
|
|
||||||
void pit_handler(registers_t *reg) {
|
void pit_handler(registers_t *reg) {
|
||||||
trace("pit: Interrupt!\n");
|
//trace("pit: Interrupt from %d!\n", lapic_get_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_init_timer() {
|
void cpu_init_timer() {
|
||||||
|
|
12
kernel/src/arch/x86_64/smp.c
Normal file → Executable file
12
kernel/src/arch/x86_64/smp.c
Normal file → Executable file
|
@ -5,13 +5,25 @@
|
||||||
* smp.c - x86_64 Symetric Multiprocessing implementation
|
* smp.c - x86_64 Symetric Multiprocessing implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "arch/cpu.h"
|
||||||
|
#include "arch/x86_64/gdt.h"
|
||||||
|
#include "arch/x86_64/idt.h"
|
||||||
|
#include "dev/lapic.h"
|
||||||
|
#include "mm/paging.h"
|
||||||
#include <boot/limine.h>
|
#include <boot/limine.h>
|
||||||
#include <deps/limine.h>
|
#include <deps/limine.h>
|
||||||
|
#include <lib/log.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
uint32_t bootstrap_lapic_id;
|
uint32_t bootstrap_lapic_id;
|
||||||
|
|
||||||
|
// TODO: initialize the CPUs
|
||||||
|
|
||||||
void cpu_init_smp() {
|
void cpu_init_smp() {
|
||||||
struct limine_mp_response *smp = limine_get_smp();
|
struct limine_mp_response *smp = limine_get_smp();
|
||||||
bootstrap_lapic_id = smp->bsp_lapic_id;
|
bootstrap_lapic_id = smp->bsp_lapic_id;
|
||||||
|
|
||||||
|
/*for (uint64_t i = 0; i < smp->cpu_count; i++) {
|
||||||
|
trace("smp: Starting CPU %d\n", i);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
0
kernel/src/arch/x86_64/smp.h
Normal file → Executable file
0
kernel/src/arch/x86_64/smp.h
Normal file → Executable file
2
kernel/src/boot/limine.c
Normal file → Executable file
2
kernel/src/boot/limine.c
Normal file → Executable file
|
@ -9,7 +9,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <boot/limine.h>
|
#include <boot/limine.h>
|
||||||
#include <deps/limine.h>
|
#include <deps/limine.h>
|
||||||
#include <exec/elf.h>
|
#include <proc/exec/elf.h>
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests")))
|
__attribute__((used, section(".limine_requests")))
|
||||||
static volatile LIMINE_BASE_REVISION(3);
|
static volatile LIMINE_BASE_REVISION(3);
|
||||||
|
|
0
kernel/src/boot/limine.h
Normal file → Executable file
0
kernel/src/boot/limine.h
Normal file → Executable file
0
kernel/src/config.h
Normal file → Executable file
0
kernel/src/config.h
Normal file → Executable file
0
kernel/src/dev/ioapic.c
Normal file → Executable file
0
kernel/src/dev/ioapic.c
Normal file → Executable file
0
kernel/src/dev/ioapic.h
Normal file → Executable file
0
kernel/src/dev/ioapic.h
Normal file → Executable file
6
kernel/src/dev/lapic.c
Normal file → Executable file
6
kernel/src/dev/lapic.c
Normal file → Executable file
|
@ -28,6 +28,12 @@ void lapic_eoi() {
|
||||||
__lapic_write(LAPIC_EOI, 0x0);
|
__lapic_write(LAPIC_EOI, 0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lapic_ipi(uint32_t id, uint8_t dat) {
|
||||||
|
__lapic_write(0x310, id << LAPIC_ICDESTSHIFT);
|
||||||
|
__lapic_write(0x300, dat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t lapic_get_id() {
|
uint32_t lapic_get_id() {
|
||||||
return __lapic_read(LAPIC_ID) >> LAPIC_ICDESTSHIFT;
|
return __lapic_read(LAPIC_ID) >> LAPIC_ICDESTSHIFT;
|
||||||
}
|
}
|
1
kernel/src/dev/lapic.h
Normal file → Executable file
1
kernel/src/dev/lapic.h
Normal file → Executable file
|
@ -23,4 +23,5 @@ typedef struct {
|
||||||
|
|
||||||
void lapic_init();
|
void lapic_init();
|
||||||
void lapic_eoi();
|
void lapic_eoi();
|
||||||
|
void lapic_ipi(uint32_t id, uint8_t dat);
|
||||||
uint32_t lapic_get_id();
|
uint32_t lapic_get_id();
|
0
kernel/src/dev/tty.c
Normal file → Executable file
0
kernel/src/dev/tty.c
Normal file → Executable file
0
kernel/src/dev/tty.h
Normal file → Executable file
0
kernel/src/dev/tty.h
Normal file → Executable file
45
kernel/src/fs/vfs.h
Executable file
45
kernel/src/fs/vfs.h
Executable file
|
@ -0,0 +1,45 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct vnode;
|
||||||
|
|
||||||
|
#define VN_FILE 1
|
||||||
|
#define VN_DIR 2
|
||||||
|
|
||||||
|
typedef uint32_t vnode_type_t;
|
||||||
|
|
||||||
|
typedef struct vnode_ops {
|
||||||
|
int (*read)(struct vnode *vn, void *buf, size_t off, size_t size);
|
||||||
|
int (*lookup)(struct vnode *vn, const char *name, struct vnode **out);
|
||||||
|
} vnode_ops_t;
|
||||||
|
|
||||||
|
typedef struct vnode {
|
||||||
|
char name[256];
|
||||||
|
vnode_type_t type;
|
||||||
|
uint32_t refcount;
|
||||||
|
struct vnode* parent; // If this vnode exists, then it's parent too.
|
||||||
|
|
||||||
|
struct vnode_ops *ops;
|
||||||
|
void *internal;
|
||||||
|
} vnode_t;
|
||||||
|
|
||||||
|
typedef struct mountpoint {
|
||||||
|
char name[32];
|
||||||
|
struct fs *fs;
|
||||||
|
vnode_t *mountpoint;
|
||||||
|
} mountpoint_t;
|
||||||
|
|
||||||
|
typedef struct fs {
|
||||||
|
char name[32];
|
||||||
|
struct vnode *root;
|
||||||
|
int (*mount)(struct fs *fs, struct vnode *mountpoint);
|
||||||
|
} fs_t;
|
||||||
|
|
||||||
|
void vfs_init(void);
|
||||||
|
int vfs_mount(char *path, fs_t *fs);
|
||||||
|
int vfs_unmount(char *path);
|
||||||
|
int vfs_open(vnode_t *curdir, const char *path, vnode_t **out);
|
||||||
|
int vfs_read(vnode_t *vn, void *buf, size_t off, size_t size);
|
||||||
|
vnode_t *vfs_create_node(char *name, vnode_type_t type);
|
0
kernel/src/lib/ansi.c
Normal file → Executable file
0
kernel/src/lib/ansi.c
Normal file → Executable file
0
kernel/src/lib/ansi.h
Normal file → Executable file
0
kernel/src/lib/ansi.h
Normal file → Executable file
4
kernel/src/lib/log.c
Normal file → Executable file
4
kernel/src/lib/log.c
Normal file → Executable file
|
@ -6,10 +6,12 @@
|
||||||
*/
|
*/
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <lib/log.h>
|
#include <lib/log.h>
|
||||||
|
#include <lib/spinlock.h>
|
||||||
|
|
||||||
static int __logger_max_loglevel = 0;
|
static int __logger_max_loglevel = 0;
|
||||||
static log_output_func __logger_outputs[16];
|
static log_output_func __logger_outputs[16];
|
||||||
static int __logger_output_count = 0;
|
static int __logger_output_count = 0;
|
||||||
|
static spinlock_t __logger_lock;
|
||||||
|
|
||||||
static char* prelog[7] = {
|
static char* prelog[7] = {
|
||||||
"\033[38;2;169;68;66;mFAULT | \033[39m",
|
"\033[38;2;169;68;66;mFAULT | \033[39m",
|
||||||
|
@ -41,6 +43,7 @@ void log(int loglevel, char *str, ...) {
|
||||||
if (loglevel > __logger_max_loglevel)
|
if (loglevel > __logger_max_loglevel)
|
||||||
return; // The user does not want this type of log to show up.
|
return; // The user does not want this type of log to show up.
|
||||||
|
|
||||||
|
sl_acquire(&__logger_lock);
|
||||||
va_list vl;
|
va_list vl;
|
||||||
va_start(vl, str);
|
va_start(vl, str);
|
||||||
|
|
||||||
|
@ -50,4 +53,5 @@ void log(int loglevel, char *str, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
va_end(vl);
|
va_end(vl);
|
||||||
|
sl_release(&__logger_lock);
|
||||||
}
|
}
|
0
kernel/src/lib/log.h
Normal file → Executable file
0
kernel/src/lib/log.h
Normal file → Executable file
0
kernel/src/lib/logoutputs_sk.c
Normal file → Executable file
0
kernel/src/lib/logoutputs_sk.c
Normal file → Executable file
0
kernel/src/lib/logoutputs_sk.h
Normal file → Executable file
0
kernel/src/lib/logoutputs_sk.h
Normal file → Executable file
0
kernel/src/lib/npf.c
Normal file → Executable file
0
kernel/src/lib/npf.c
Normal file → Executable file
25
kernel/src/lib/spinlock.c
Executable file
25
kernel/src/lib/spinlock.c
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* spinlock.c - Spinlock implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <lib/spinlock.h>
|
||||||
|
|
||||||
|
void sl_acquire(spinlock_t volatile *plock)
|
||||||
|
{
|
||||||
|
while (!__sync_bool_compare_and_swap(plock, 0, 1))
|
||||||
|
{
|
||||||
|
while (*plock)
|
||||||
|
{
|
||||||
|
asm("pause");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sl_release(spinlock_t volatile *plock)
|
||||||
|
{
|
||||||
|
__sync_lock_release(plock);
|
||||||
|
}
|
||||||
|
|
13
kernel/src/lib/spinlock.h
Executable file
13
kernel/src/lib/spinlock.h
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* spinlock.h - Spinlock definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef unsigned int spinlock_t;
|
||||||
|
|
||||||
|
void sl_acquire(spinlock_t volatile *plock);
|
||||||
|
void sl_release(spinlock_t volatile *plock);
|
0
kernel/src/lib/string.c
Normal file → Executable file
0
kernel/src/lib/string.c
Normal file → Executable file
0
kernel/src/lib/string.h
Normal file → Executable file
0
kernel/src/lib/string.h
Normal file → Executable file
5
kernel/src/main.c
Normal file → Executable file
5
kernel/src/main.c
Normal file → Executable file
|
@ -20,6 +20,7 @@
|
||||||
#include <lib/logoutputs_sk.h>
|
#include <lib/logoutputs_sk.h>
|
||||||
#include <mm/memop.h>
|
#include <mm/memop.h>
|
||||||
#include <mm/pmm.h>
|
#include <mm/pmm.h>
|
||||||
|
#include "arch/x86_64/smp.h"
|
||||||
#include "dev/ioapic.h"
|
#include "dev/ioapic.h"
|
||||||
#include "dev/lapic.h"
|
#include "dev/lapic.h"
|
||||||
#include "mm/paging.h"
|
#include "mm/paging.h"
|
||||||
|
@ -46,6 +47,10 @@ void kmain(void) {
|
||||||
cpu_init_smp();
|
cpu_init_smp();
|
||||||
cpu_init_timer();
|
cpu_init_timer();
|
||||||
|
|
||||||
|
|
||||||
|
cpu_enable_ints(1);
|
||||||
|
//lapic_ipi(bootstrap_lapic_id, 32);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
;;
|
;;
|
||||||
// We're done, just hang... for now.
|
// We're done, just hang... for now.
|
||||||
|
|
0
kernel/src/mm/memop.c
Normal file → Executable file
0
kernel/src/mm/memop.c
Normal file → Executable file
0
kernel/src/mm/memop.h
Normal file → Executable file
0
kernel/src/mm/memop.h
Normal file → Executable file
85
kernel/src/mm/paging.c
Normal file → Executable file
85
kernel/src/mm/paging.c
Normal file → Executable file
|
@ -10,11 +10,11 @@
|
||||||
|
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
#include <boot/limine.h>
|
#include <boot/limine.h>
|
||||||
#include <exec/elf.h>
|
|
||||||
#include <lib/log.h>
|
#include <lib/log.h>
|
||||||
#include <mm/memop.h>
|
#include <mm/memop.h>
|
||||||
#include <mm/pmm.h>
|
|
||||||
#include <mm/paging.h>
|
#include <mm/paging.h>
|
||||||
|
#include <mm/pmm.h>
|
||||||
|
#include <proc/exec/elf.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
pagemap_t pg_kernel_pm = NULL;
|
pagemap_t pg_kernel_pm = NULL;
|
||||||
|
@ -37,7 +37,8 @@ void pg_init() {
|
||||||
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)elf_addr;
|
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)elf_addr;
|
||||||
|
|
||||||
for (uint16_t i = 0; i < ehdr->e_phnum; i++) {
|
for (uint16_t i = 0; i < ehdr->e_phnum; i++) {
|
||||||
Elf64_Phdr *cur_phdr = (Elf64_Phdr*)(elf_addr + ehdr->e_phoff + (i * ehdr->e_phentsize));
|
Elf64_Phdr *cur_phdr =
|
||||||
|
(Elf64_Phdr *)(elf_addr + ehdr->e_phoff + (i * ehdr->e_phentsize));
|
||||||
if (cur_phdr->p_type != PT_LOAD)
|
if (cur_phdr->p_type != PT_LOAD)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -55,12 +56,14 @@ void pg_init() {
|
||||||
for (uint64_t i = 0; i < length; i += PMM_PAGE_SIZE) {
|
for (uint64_t i = 0; i < length; i += PMM_PAGE_SIZE) {
|
||||||
pg_map(pg_kernel_pm, cur_phdr->p_vaddr + i, phys + i, flags);
|
pg_map(pg_kernel_pm, cur_phdr->p_vaddr + i, phys + i, flags);
|
||||||
}
|
}
|
||||||
trace("vmm: Mapped range: %p -> %p (length: %x)\n", phys, cur_phdr->p_vaddr, length);
|
trace("vmm: Mapped range: %p -> %p (length: %x)\n", phys, cur_phdr->p_vaddr,
|
||||||
|
length);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint64_t i = 0; i < 0x100000000; i += PMM_PAGE_SIZE)
|
for (uint64_t i = 0; i < 0x100000000; i += PMM_PAGE_SIZE)
|
||||||
pg_map(pg_kernel_pm, higher_half(i), i, PTE_PRESENT | PTE_WRITE);
|
pg_map(pg_kernel_pm, higher_half(i), i, PTE_PRESENT | PTE_WRITE);
|
||||||
trace("vmm: Mapped range: %p -> %p (length: %x)\n", 0x0, 0xFFFF800000000000, 0x100000000);
|
trace("vmm: Mapped range: %p -> %p (length: %x)\n", 0x0, 0xFFFF800000000000,
|
||||||
|
0x100000000);
|
||||||
|
|
||||||
pg_load_pm(pg_kernel_pm);
|
pg_load_pm(pg_kernel_pm);
|
||||||
trace("vmm: Initialized.\n");
|
trace("vmm: Initialized.\n");
|
||||||
|
@ -76,10 +79,9 @@ void pg_load_pm(pagemap_t pm) {
|
||||||
|
|
||||||
pagemap_t pg_alloc_pm() {
|
pagemap_t pg_alloc_pm() {
|
||||||
pagemap_t pm = (pagemap_t)higher_half((uint64_t)pmm_alloc_page());
|
pagemap_t pm = (pagemap_t)higher_half((uint64_t)pmm_alloc_page());
|
||||||
memset((void*)pm, 0, PMM_PAGE_SIZE);
|
memset((void *)pm, 0, PMM_PAGE_SIZE);
|
||||||
|
|
||||||
if (pg_kernel_pm)
|
if (pg_kernel_pm) {
|
||||||
{
|
|
||||||
for (int i = 256; i < 512; i++)
|
for (int i = 256; i < 512; i++)
|
||||||
pm[i] = pg_kernel_pm[i];
|
pm[i] = pg_kernel_pm[i];
|
||||||
}
|
}
|
||||||
|
@ -88,12 +90,11 @@ pagemap_t pg_alloc_pm() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pg_free_pm(pagemap_t pm) {
|
void pg_free_pm(pagemap_t pm) {
|
||||||
if (pm == pg_kernel_pm)
|
if (pm == pg_kernel_pm) {
|
||||||
{
|
|
||||||
warn("vmm: Who tried to free the kernel's pagemap?!\n");
|
warn("vmm: Who tried to free the kernel's pagemap?!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pmm_free_page((void*)pm);
|
pmm_free_page((void *)pm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t *__pg_get_next_lvl(uint64_t *level, uint64_t entry,
|
static uint64_t *__pg_get_next_lvl(uint64_t *level, uint64_t entry,
|
||||||
|
@ -110,48 +111,56 @@ static uint64_t *__pg_get_next_lvl(uint64_t *level, uint64_t entry,
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t pg_physical(pagemap_t pm, uint64_t vaddr) {
|
uint64_t pg_physical(pagemap_t pm, uint64_t vaddr) {
|
||||||
if (!pm) return 0;
|
if (!pm)
|
||||||
|
return 0;
|
||||||
|
|
||||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||||
|
|
||||||
uint64_t *pml3 = __pg_get_next_lvl(pm , pml4_entry, 0, false);
|
uint64_t *pml3 = __pg_get_next_lvl(pm, pml4_entry, 0, false);
|
||||||
if (!pml3) return 0;
|
if (!pml3)
|
||||||
|
return 0;
|
||||||
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, 0, false);
|
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, 0, false);
|
||||||
if (!pml2) return 0;
|
if (!pml2)
|
||||||
|
return 0;
|
||||||
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, 0, false);
|
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, 0, false);
|
||||||
if (!pml1) return 0;
|
if (!pml1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return pml1[pml1_entry] & PTE_ADDR_MASK;
|
return pml1[pml1_entry] & PTE_ADDR_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pg_map(pagemap_t pm, uint64_t vaddr, uint64_t paddr, uint64_t flags) {
|
void pg_map(pagemap_t pm, uint64_t vaddr, uint64_t paddr, uint64_t flags) {
|
||||||
if (!pm) return;
|
if (!pm)
|
||||||
|
return;
|
||||||
|
|
||||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||||
|
|
||||||
uint64_t *pml3 = __pg_get_next_lvl(pm , pml4_entry, PTE_PRESENT | PTE_WRITE, true);
|
uint64_t *pml3 =
|
||||||
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, PTE_PRESENT | PTE_WRITE, true);
|
__pg_get_next_lvl(pm, pml4_entry, PTE_PRESENT | PTE_WRITE, true);
|
||||||
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, PTE_PRESENT | PTE_WRITE, true);
|
uint64_t *pml2 =
|
||||||
|
__pg_get_next_lvl(pml3, pml3_entry, PTE_PRESENT | PTE_WRITE, true);
|
||||||
|
uint64_t *pml1 =
|
||||||
|
__pg_get_next_lvl(pml2, pml2_entry, PTE_PRESENT | PTE_WRITE, true);
|
||||||
|
|
||||||
pml1[pml1_entry] = paddr | flags;
|
pml1[pml1_entry] = paddr | flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pg_map_user(pagemap_t pm, uint64_t vaddr, uint64_t paddr,
|
void pg_map_user(pagemap_t pm, uint64_t vaddr, uint64_t paddr, uint64_t flags) {
|
||||||
uint64_t flags) {
|
if (!pm)
|
||||||
if (!pm) return;
|
return;
|
||||||
|
|
||||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||||
|
|
||||||
uint64_t *pml3 = __pg_get_next_lvl(pm , pml4_entry, flags, true);
|
uint64_t *pml3 = __pg_get_next_lvl(pm, pml4_entry, flags, true);
|
||||||
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, flags, true);
|
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, flags, true);
|
||||||
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, flags, true);
|
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, flags, true);
|
||||||
|
|
||||||
|
@ -159,38 +168,46 @@ void pg_map_user(pagemap_t pm, uint64_t vaddr, uint64_t paddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
void pg_unmap(pagemap_t pm, uint64_t vaddr) {
|
void pg_unmap(pagemap_t pm, uint64_t vaddr) {
|
||||||
if (!pm) return;
|
if (!pm)
|
||||||
|
return;
|
||||||
|
|
||||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||||
|
|
||||||
uint64_t *pml3 = __pg_get_next_lvl(pm , pml4_entry, 0, false);
|
uint64_t *pml3 = __pg_get_next_lvl(pm, pml4_entry, 0, false);
|
||||||
if (!pml3) return;
|
if (!pml3)
|
||||||
|
return;
|
||||||
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, 0, false);
|
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, 0, false);
|
||||||
if (!pml2) return;
|
if (!pml2)
|
||||||
|
return;
|
||||||
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, 0, false);
|
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, 0, false);
|
||||||
if (!pml1) return;
|
if (!pml1)
|
||||||
|
return;
|
||||||
|
|
||||||
pml1[pml1_entry] = 0;
|
pml1[pml1_entry] = 0;
|
||||||
cpu_invalidate_page(vaddr);
|
cpu_invalidate_page(vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pg_protect(pagemap_t pm, uint64_t vaddr, uint64_t flags) {
|
void pg_protect(pagemap_t pm, uint64_t vaddr, uint64_t flags) {
|
||||||
if (!pm) return;
|
if (!pm)
|
||||||
|
return;
|
||||||
|
|
||||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||||
|
|
||||||
uint64_t *pml3 = __pg_get_next_lvl(pm , pml4_entry, 0, false);
|
uint64_t *pml3 = __pg_get_next_lvl(pm, pml4_entry, 0, false);
|
||||||
if (!pml3) return;
|
if (!pml3)
|
||||||
|
return;
|
||||||
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, 0, false);
|
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, 0, false);
|
||||||
if (!pml2) return;
|
if (!pml2)
|
||||||
|
return;
|
||||||
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, 0, false);
|
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, 0, false);
|
||||||
if (!pml1) return;
|
if (!pml1)
|
||||||
|
return;
|
||||||
|
|
||||||
uint64_t paddr = pml1[pml1_entry] & PTE_ADDR_MASK;
|
uint64_t paddr = pml1[pml1_entry] & PTE_ADDR_MASK;
|
||||||
pml1[pml1_entry] = paddr | flags;
|
pml1[pml1_entry] = paddr | flags;
|
||||||
|
|
0
kernel/src/mm/paging.h
Normal file → Executable file
0
kernel/src/mm/paging.h
Normal file → Executable file
0
kernel/src/mm/pmm.c
Normal file → Executable file
0
kernel/src/mm/pmm.c
Normal file → Executable file
0
kernel/src/mm/pmm.h
Normal file → Executable file
0
kernel/src/mm/pmm.h
Normal file → Executable file
0
kernel/src/mm/pmm.md
Normal file → Executable file
0
kernel/src/mm/pmm.md
Normal file → Executable file
0
kernel/src/mm/vma.c
Normal file → Executable file
0
kernel/src/mm/vma.c
Normal file → Executable file
0
kernel/src/mm/vma.h
Normal file → Executable file
0
kernel/src/mm/vma.h
Normal file → Executable file
0
kernel/src/exec/elf.h → kernel/src/proc/exec/elf.h
Normal file → Executable file
0
kernel/src/exec/elf.h → kernel/src/proc/exec/elf.h
Normal file → Executable file
30
kernel/src/proc/exec/exec.h
Normal file
30
kernel/src/proc/exec/exec.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
// Structure for an executable program loaded into memory.
|
||||||
|
|
||||||
|
#include "mm/paging.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EXEC_FMT_ELF,
|
||||||
|
EXEC_FMT_PE,
|
||||||
|
EXEC_FMT_MACHO,
|
||||||
|
EXEC_FMT_SCRIPT
|
||||||
|
} exec_format_t;
|
||||||
|
|
||||||
|
typedef struct exec {
|
||||||
|
pagemap_t pm;
|
||||||
|
|
||||||
|
void *rwdata_start;
|
||||||
|
size_t rwdata_len;
|
||||||
|
|
||||||
|
uint64_t entry;
|
||||||
|
|
||||||
|
int argc; // 0 for useds
|
||||||
|
char **argv; // NULL when the executable is a used
|
||||||
|
|
||||||
|
char *path;
|
||||||
|
exec_format_t format;
|
||||||
|
|
||||||
|
size_t usecount; // -1 for users, else, the number of processes sharing the executable's read only sections
|
||||||
|
struct exec *used; // The reference executable.
|
||||||
|
} exec_t;
|
3
kernel/src/proc/sched.c
Normal file
3
kernel/src/proc/sched.c
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
void sched_init() {
|
||||||
|
|
||||||
|
}
|
69
kernel/src/proc/sched.h
Normal file
69
kernel/src/proc/sched.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "arch/x86_64/idt.h"
|
||||||
|
#include "mm/paging.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <proc/exec/exec.h>
|
||||||
|
|
||||||
|
struct process;
|
||||||
|
|
||||||
|
typedef enum thread_state {
|
||||||
|
THREAD_READY,
|
||||||
|
THREAD_RUNNING,
|
||||||
|
THREAD_BLOCKED,
|
||||||
|
THREAD_TERMINATED
|
||||||
|
} thread_state_t;
|
||||||
|
|
||||||
|
typedef enum process_type {
|
||||||
|
PT_USER,
|
||||||
|
PT_KERNEL
|
||||||
|
} process_type_t;
|
||||||
|
|
||||||
|
typedef enum process_state {
|
||||||
|
PS_ZOMBIE,
|
||||||
|
PS_ACTIVE,
|
||||||
|
PS_TERMINATED
|
||||||
|
} process_state_t;
|
||||||
|
|
||||||
|
typedef struct thread {
|
||||||
|
size_t tid;
|
||||||
|
registers_t regs;
|
||||||
|
uint64_t stack_base;
|
||||||
|
uint64_t stack_end;
|
||||||
|
thread_state_t state;
|
||||||
|
|
||||||
|
struct process *parent;
|
||||||
|
|
||||||
|
// Local only: Only lists the process' threads
|
||||||
|
struct thread *next;
|
||||||
|
struct thread *prev;
|
||||||
|
} thread_t;
|
||||||
|
|
||||||
|
// Global thread list
|
||||||
|
typedef struct thread_list {
|
||||||
|
struct thread *next;
|
||||||
|
struct thread *prev;
|
||||||
|
} thread_list_t;
|
||||||
|
|
||||||
|
typedef struct process {
|
||||||
|
char *name;
|
||||||
|
size_t pid;
|
||||||
|
pagemap_t pm;
|
||||||
|
thread_t *threads;
|
||||||
|
exec_t *exec_clone;
|
||||||
|
process_type_t type;
|
||||||
|
process_state_t state;
|
||||||
|
|
||||||
|
struct process *next_sibling;
|
||||||
|
struct process *prev_sibling;
|
||||||
|
|
||||||
|
struct process *children;
|
||||||
|
struct process *parent;
|
||||||
|
} process_t;
|
||||||
|
|
||||||
|
extern thread_t *current_thread;
|
||||||
|
extern process_t *current_process;
|
||||||
|
extern thread_list_t *thread_list_head;
|
||||||
|
|
||||||
|
void sched_init();
|
||||||
|
void schedule();
|
0
limine.conf
Normal file → Executable file
0
limine.conf
Normal file → Executable file
Loading…
Add table
Add a link
Reference in a new issue