kernel: whatever changes i didn't keep track of lol

This commit is contained in:
Raphaël M. 2025-06-01 22:45:43 +02:00
parent b2cf9b4710
commit edbb5d106d
67 changed files with 340 additions and 88 deletions

0
.gitignore vendored Normal file → Executable file
View file

0
GNUmakefile Normal file → Executable file
View file

0
LICENSE Normal file → Executable file
View file

4
README.md Normal file → Executable file
View 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
View file

0
kernel/GNUmakefile Normal file → Executable file
View file

0
kernel/linker-aarch64.ld Normal file → Executable file
View file

0
kernel/linker-loongarch64.ld Normal file → Executable file
View file

0
kernel/linker-riscv64.ld Normal file → Executable file
View file

0
kernel/linker-x86_64.ld Normal file → Executable file
View file

0
kernel/src/acpi/acpi.c Normal file → Executable file
View file

0
kernel/src/acpi/acpi.h Normal file → Executable file
View file

0
kernel/src/acpi/madt.c Normal file → Executable file
View file

0
kernel/src/acpi/madt.h Normal file → Executable file
View file

0
kernel/src/arch/aarch64/cpu.c Normal file → Executable file
View file

3
kernel/src/arch/cpu.h Normal file → Executable file
View 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
View file

0
kernel/src/arch/riscv/cpu.c Normal file → Executable file
View file

4
kernel/src/arch/x86_64/cpu.c Normal file → Executable file
View 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
View file

6
kernel/src/arch/x86_64/gdt.asm Normal file → Executable file
View 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
View 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
View file

6
kernel/src/arch/x86_64/idt.asm Normal file → Executable file
View 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
View 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");
} }

3
kernel/src/arch/x86_64/idt.h Normal file → Executable file
View file

@ -59,4 +59,5 @@ typedef struct {
} __attribute__((packed)) idtr_t; } __attribute__((packed)) idtr_t;
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
View file

3
kernel/src/arch/x86_64/pit.c Normal file → Executable file
View 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
View 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
View file

2
kernel/src/boot/limine.c Normal file → Executable file
View 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
View file

0
kernel/src/config.h Normal file → Executable file
View file

0
kernel/src/dev/ioapic.c Normal file → Executable file
View file

0
kernel/src/dev/ioapic.h Normal file → Executable file
View file

6
kernel/src/dev/lapic.c Normal file → Executable file
View 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
View 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
View file

0
kernel/src/dev/tty.h Normal file → Executable file
View file

45
kernel/src/fs/vfs.h Executable file
View 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
View file

0
kernel/src/lib/ansi.h Normal file → Executable file
View file

4
kernel/src/lib/log.c Normal file → Executable file
View 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
View file

0
kernel/src/lib/logoutputs_sk.c Normal file → Executable file
View file

0
kernel/src/lib/logoutputs_sk.h Normal file → Executable file
View file

0
kernel/src/lib/npf.c Normal file → Executable file
View file

25
kernel/src/lib/spinlock.c Executable file
View 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
View 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
View file

0
kernel/src/lib/string.h Normal file → Executable file
View file

5
kernel/src/main.c Normal file → Executable file
View 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
View file

0
kernel/src/mm/memop.h Normal file → Executable file
View file

173
kernel/src/mm/paging.c Normal file → Executable file
View 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;
@ -22,82 +22,83 @@ pagemap_t pg_current_pm = NULL;
void pg_init() { void pg_init() {
#if !defined(__x86_64__) #if !defined(__x86_64__)
fatal("vmm: not implemented\n"); fatal("vmm: not implemented\n");
hcf(); hcf();
#endif #endif
// Our objective here is to recreate the // Our objective here is to recreate the
// kernel page map that Limine provide us // kernel page map that Limine provide us
pg_kernel_pm = pg_alloc_pm(); pg_kernel_pm = pg_alloc_pm();
uint64_t kvaddr = limine_get_kernel_vaddr(); uint64_t kvaddr = limine_get_kernel_vaddr();
uint64_t kpaddr = limine_get_kernel_paddr(); uint64_t kpaddr = limine_get_kernel_paddr();
char *elf_addr = (char *)limine_get_kernel_ehdr_addr();
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)elf_addr;
for (uint16_t i = 0; i < ehdr->e_phnum; i++) { char *elf_addr = (char *)limine_get_kernel_ehdr_addr();
Elf64_Phdr *cur_phdr = (Elf64_Phdr*)(elf_addr + ehdr->e_phoff + (i * ehdr->e_phentsize)); Elf64_Ehdr *ehdr = (Elf64_Ehdr *)elf_addr;
if (cur_phdr->p_type != PT_LOAD)
continue;
uintptr_t phys = (cur_phdr->p_vaddr - kvaddr) + kpaddr; for (uint16_t i = 0; i < ehdr->e_phnum; i++) {
uint64_t flags = PTE_PRESENT; Elf64_Phdr *cur_phdr =
if ((cur_phdr->p_flags & PF_X) == 0) { (Elf64_Phdr *)(elf_addr + ehdr->e_phoff + (i * ehdr->e_phentsize));
flags |= PTE_NX; if (cur_phdr->p_type != PT_LOAD)
} continue;
if (cur_phdr->p_flags & PF_W) {
flags |= PTE_WRITE;
}
size_t length = ALIGN_UP(cur_phdr->p_memsz, PMM_PAGE_SIZE); uintptr_t phys = (cur_phdr->p_vaddr - kvaddr) + kpaddr;
uint64_t flags = PTE_PRESENT;
for (uint64_t i = 0; i < length; i += PMM_PAGE_SIZE) { if ((cur_phdr->p_flags & PF_X) == 0) {
pg_map(pg_kernel_pm, cur_phdr->p_vaddr + i, phys + i, flags); flags |= PTE_NX;
} }
trace("vmm: Mapped range: %p -> %p (length: %x)\n", phys, cur_phdr->p_vaddr, length); if (cur_phdr->p_flags & PF_W) {
flags |= PTE_WRITE;
} }
for (uint64_t i = 0; i < 0x100000000; i += PMM_PAGE_SIZE) size_t length = ALIGN_UP(cur_phdr->p_memsz, PMM_PAGE_SIZE);
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);
pg_load_pm(pg_kernel_pm); for (uint64_t i = 0; i < length; i += PMM_PAGE_SIZE) {
trace("vmm: Initialized.\n"); 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);
}
for (uint64_t i = 0; i < 0x100000000; i += PMM_PAGE_SIZE)
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);
pg_load_pm(pg_kernel_pm);
trace("vmm: Initialized.\n");
} }
void pg_load_pm(pagemap_t pm) { void pg_load_pm(pagemap_t pm) {
if (!pm) if (!pm)
return; return;
pg_current_pm = pm; pg_current_pm = pm;
cpu_load_pm((pagemap_t)physical((uint64_t)pm)); cpu_load_pm((pagemap_t)physical((uint64_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]; }
}
return pm; return 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,
uint64_t flags, bool alloc) { uint64_t flags, bool alloc) {
if (level[entry] & PTE_PRESENT) if (level[entry] & PTE_PRESENT)
return (uint64_t *)higher_half(PTE_GET_ADDR(level[entry])); return (uint64_t *)higher_half(PTE_GET_ADDR(level[entry]));
if (alloc) { if (alloc) {
@ -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
View file

0
kernel/src/mm/pmm.c Normal file → Executable file
View file

0
kernel/src/mm/pmm.h Normal file → Executable file
View file

0
kernel/src/mm/pmm.md Normal file → Executable file
View file

0
kernel/src/mm/vma.c Normal file → Executable file
View file

0
kernel/src/mm/vma.h Normal file → Executable file
View file

View file

0
kernel/src/exec/elf.h → kernel/src/proc/exec/elf.h Normal file → Executable file
View file

View 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
View file

@ -0,0 +1,3 @@
void sched_init() {
}

69
kernel/src/proc/sched.h Normal file
View 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
View file