Compare commits

..

4 Commits

Author SHA1 Message Date
0273330cf4 Kernel processes / multitasking 2025-08-30 23:47:25 +02:00
60a530b900 hal x86_64 vmm minor fixes in mapping/unmapping 2025-08-30 13:41:47 +02:00
7a52f2f051 Rework x86_64 paging and vmm 2025-08-30 00:31:20 +02:00
8cf1bde879 Make spinlock disable interrupts 2025-08-22 12:42:04 +02:00
38 changed files with 627 additions and 327 deletions

1
.gdbinit Normal file
View File

@ -0,0 +1 @@
target remote :1234

View File

@ -47,6 +47,7 @@ SRCFILES := $(wildcard *.c) \
$(wildcard fs/littlefs/*.c) \ $(wildcard fs/littlefs/*.c) \
$(wildcard fs/portlfs/*.c) \ $(wildcard fs/portlfs/*.c) \
$(wildcard baseimg/*.c) \ $(wildcard baseimg/*.c) \
$(wildcard proc/*.c) \
$(wildcard hal/*.c) \ $(wildcard hal/*.c) \
$(wildcard hal/$(ARCH)/*.c) \ $(wildcard hal/$(ARCH)/*.c) \
$(wildcard hal/$(ARCH)/*.S) \ $(wildcard hal/$(ARCH)/*.S) \

6
kernel/atomic.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef ATOMIC_H_
#define ATOMIC_H_
#define ATOMIC(X) _Atomic(X)
#endif // ATOMIC_H_

View File

@ -12,7 +12,6 @@ typedef struct {
size_t alloc_blocks; size_t alloc_blocks;
size_t last_deep_frag; size_t last_deep_frag;
uintptr_t mem_start; uintptr_t mem_start;
bool init;
} BitMap; } BitMap;
#define BITMAP_BLOCKS_PER_BYTE 8 #define BITMAP_BLOCKS_PER_BYTE 8

View File

@ -3,5 +3,6 @@
#define PACKED __attribute__((packed)) #define PACKED __attribute__((packed))
#define ALIGNED(x) __attribute__((aligned((x)))) #define ALIGNED(x) __attribute__((aligned((x))))
#define NORETURN __attribute__((noreturn))
#endif // COMPILER_ATTR_H_ #endif // COMPILER_ATTR_H_

View File

@ -7,6 +7,7 @@
#include "bitmap/bitmap.h" #include "bitmap/bitmap.h"
#include "util/util.h" #include "util/util.h"
#include "vmm/vmm.h" #include "vmm/vmm.h"
#include "pmm/pmm.h"
#include "malloc.h" #include "malloc.h"
#define USE_DL_PREFIX 1 #define USE_DL_PREFIX 1
@ -64,10 +65,9 @@ void *sbrk(long inc) {
} }
uint64_t blocks = _DIV_ROUNDUP(inc, BITMAP_BLOCK_SIZE); uint64_t blocks = _DIV_ROUNDUP(inc, BITMAP_BLOCK_SIZE);
void *virt = vmm_alloc(blocks); uint8_t *virt = VIRT(pmm_alloc(blocks));
hal_memset(virt, 0, blocks * BITMAP_BLOCK_SIZE); hal_memset(virt, 0, blocks * BITMAP_BLOCK_SIZE);
_last = (void *)(virt + inc);
_last = (void *)((size_t)virt + inc);
return virt; return virt;
} }

View File

@ -22,6 +22,11 @@ void hal_init_withmalloc(void);
#if defined(__x86_64__) #if defined(__x86_64__)
# define HAL_PAGE_SIZE 0x1000 # define HAL_PAGE_SIZE 0x1000
# include "x86_64/vmm.h"
# include "x86_64/proc.h"
# include "x86_64/switch.h"
# include "x86_64/paging.h"
# include "x86_64/cpu.h"
#endif #endif
#endif // KERNEL_HAL_HAL_H_ #endif // KERNEL_HAL_HAL_H_

View File

@ -1,13 +1,13 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
uint64_t cpu_rdmsr(uint32_t id) { uint64_t hal_cpu_rdmsr(uint32_t id) {
uint32_t lo, hi; uint32_t lo, hi;
asm volatile("rdmsr" : "=m"(lo), "=d"(hi) : "c"(id)); asm volatile("rdmsr" : "=m"(lo), "=d"(hi) : "c"(id));
return ((uint64_t)lo) | ((uint64_t)hi << 32); return ((uint64_t)lo) | ((uint64_t)hi << 32);
} }
uint64_t cpu_wrmsr(uint32_t id, uint64_t val) { uint64_t hal_cpu_wrmsr(uint32_t id, uint64_t val) {
uint32_t lo = val & 0xffffffff, hi = (val >> 32) & 0xffffffff; uint32_t lo = val & 0xffffffff, hi = (val >> 32) & 0xffffffff;
asm volatile("wrmsr" :: "a"(lo), "d"(hi), "c"(id) : "memory"); asm volatile("wrmsr" :: "a"(lo), "d"(hi), "c"(id) : "memory");
return val; return val;

View File

@ -1,7 +1,11 @@
#ifndef HAL_CPU_H_ #ifndef HAL_CPU_H_
#define HAL_CPU_H_ #define HAL_CPU_H_
uint64_t cpu_rdmsr(uint32_t id); #define HAL_CPU_FSBASE 0xC0000100
uint64_t cpu_wrmsr(uint32_t id, uint64_t val); #define HAL_CPU_GSBASE 0xC0000101
#define HAL_CPU_KGSBASE 0xC0000102
uint64_t hal_cpu_rdmsr(uint32_t id);
uint64_t hal_cpu_wrmsr(uint32_t id, uint64_t val);
#endif // HAL_CPU_H_ #endif // HAL_CPU_H_

View File

@ -50,7 +50,7 @@ typedef struct {
ALIGNED(16) static Tss tss = {0}; ALIGNED(16) static Tss tss = {0};
ALIGNED(16) static ExtendedGdt gdt = {0}; ALIGNED(16) static ExtendedGdt gdt = {0};
void gdt_setentry(GdtEntry *ent, uint32_t base, uint32_t limit, uint32_t acc, uint8_t gran) { void gdt_setentry(GdtEntry *ent, uint32_t base, uint32_t limit, uint8_t acc, uint8_t gran) {
ent->baselow = base & 0xffff; ent->baselow = base & 0xffff;
ent->basemid = (base >> 16) & 0xff; ent->basemid = (base >> 16) & 0xff;
ent->basehigh = (base >> 24) & 0xff; ent->basehigh = (base >> 24) & 0xff;

View File

@ -31,6 +31,6 @@ void hal_init_withmalloc(void) {
intr_init(); intr_init();
pit_init(); pit_init();
ioapic_setentry(IOAPIC, acpi_remapirq(0x00), INTR_TIMER); ioapic_setentry(IOAPIC, acpi_remapirq(0x00), INTR_TIMER);
hal_intr_enable(); hal_intr_disable();
} }

View File

@ -1,5 +1,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "intr.h" #include "intr.h"
#include "io.h" #include "io.h"
#include "gdt.h" #include "gdt.h"
@ -9,6 +10,7 @@
#include "pic.h" #include "pic.h"
#include "apic.h" #include "apic.h"
#include "pit.h" #include "pit.h"
#include "proc/proc.h"
void hal_intr_disable(void) { void hal_intr_disable(void) {
asm volatile("cli"); asm volatile("cli");
@ -55,45 +57,6 @@ void idt_init(void) {
LOG("hal", "idt init\n"); LOG("hal", "idt init\n");
} }
typedef struct {
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rsi;
uint64_t rdi;
uint64_t rbp;
uint64_t rdx;
uint64_t rcx;
uint64_t rbx;
uint64_t rax;
} PACKED CpuRegs;
typedef struct {
uint64_t cr8;
uint64_t cr4;
uint64_t cr3;
uint64_t cr2;
uint64_t cr0;
} PACKED CpuCtrlRegs;
typedef struct {
CpuCtrlRegs ctrl;
CpuRegs regs;
uint64_t trapnum;
uint64_t errnum;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} PACKED IntrStackFrame;
extern void *ISR_REDIRTABLE[]; extern void *ISR_REDIRTABLE[];
static const char *exceptions[] = { static const char *exceptions[] = {
@ -164,38 +127,43 @@ void intr_init(void) {
} }
void intr_dumpframe(IntrStackFrame *frame) { void intr_dumpframe(IntrStackFrame *frame) {
kprintf("r15=%016lx r14=%016lx r13=%016lx r12=%016lx\n" uint64_t cr2;
"r11=%016lx r10=%016lx r9 =%016lx r8 =%016lx\n" asm volatile("mov %%cr2, %0" : "=r"(cr2));
"rsi=%016lx rdi=%016lx rbp=%016lx rdx=%016lx\n" uint64_t cr3;
"rcx=%016lx rbx=%016lx rax=%016lx\n" asm volatile("mov %%cr3, %0" : "=r"(cr3));
"cr8=%016lx cr4=%016lx cr3=%016lx cr2=%016lx\n" uint64_t cr4;
"cr0=%016lx rip=%016lx cs =%016lx rfl=%016lx\n" asm volatile("mov %%cr4, %0" : "=r"(cr4));
"rsp=%016lx ss =%016lx trp=%016lx err=%016lx\n", kprintf_unsafe("rax=%016lx rcx=%016lx rdx=%016lx\n"
frame->regs.r15, frame->regs.r14, frame->regs.r13, frame->regs.r12, "rsi=%016lx rdi=%016lx r8 =%016lx\n"
frame->regs.r11, frame->regs.r10, frame->regs.r9, frame->regs.r8, "r9 =%016lx r10=%016lx r11=%016lx\n"
frame->regs.rsi, frame->regs.rdi, frame->regs.rbp, frame->regs.rdx, "rip=%016lx rfl=%016lx rsp=%016lx\n"
frame->regs.rcx, frame->regs.rbx, frame->regs.rax, "cs =%016lx ss =%016lx trp=%016lx\n"
frame->ctrl.cr8, frame->ctrl.cr4, frame->ctrl.cr3, "cr2=%016lx cr3=%016lx cr4=%016lx\n"
frame->ctrl.cr2, frame->ctrl.cr0, frame->rip, frame->cs, frame->rflags, "\n\n",
frame->rsp, frame->ss, frame->trapnum, frame->errnum frame->regs.rax, frame->regs.rcx, frame->regs.rdx,
frame->regs.rsi, frame->regs.rdi, frame->regs.r8,
frame->regs.r9, frame->regs.r10, frame->regs.r11,
frame->rip, frame->rflags, frame->rsp,
frame->cs, frame->ss, frame->trapnum,
cr2, cr3, cr4
); );
} }
void intr_handleintr(IntrStackFrame *frame) { void intr_handleintr(IntrStackFrame *frame) {
if (frame->trapnum >= 0 && frame->trapnum <= 31) { if (frame->trapnum >= 0 && frame->trapnum <= 31) {
// EXCEPTION // EXCEPTION
ERR("ERROR", "%s, 0x%lX\n", exceptions[frame->trapnum], frame->errnum); kprintf_unsafe("ERROR %s, 0x%lX\n", exceptions[frame->trapnum], frame->errnum);
intr_dumpframe(frame); intr_dumpframe(frame);
hal_hang(); hal_hang();
} else if (frame->trapnum >= 32 && frame->trapnum <= 47) { } else if (frame->trapnum >= 32 && frame->trapnum <= 47) {
if (frame->trapnum == INTR_TIMER) { if (frame->trapnum == INTR_TIMER) {
kprintf("ACK %d\n", PIT_TICKS);
PIT_TICKS++;
io_out8(PIC2_CMD, 0x20); io_out8(PIC2_CMD, 0x20);
PIT_TICKS++;
} }
io_out8(PIC1_CMD, 0x20); io_out8(PIC1_CMD, 0x20);
lapic_write(LAPIC_EOI, 0x00); lapic_write(LAPIC_EOI, 0x00);
proc_sched((void *)frame);
} }
} }

View File

@ -6,6 +6,35 @@
#define INTR_TIMER 0x20 #define INTR_TIMER 0x20
#define INTR_SPURIOUS 0xff #define INTR_SPURIOUS 0xff
#include "compiler/attr.h"
typedef struct {
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rdi;
uint64_t rsi;
uint64_t rdx;
uint64_t rcx;
uint64_t rax;
} PACKED SavedRegs;
typedef struct {
SavedRegs regs;
uint64_t trapnum;
uint64_t errnum;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} PACKED IntrStackFrame;
void intr_init(void); void intr_init(void);
#endif // HAL_INTR_H_ #endif // HAL_INTR_H_

View File

@ -1,3 +1,5 @@
#include "regs.S"
.extern intr_handleintr .extern intr_handleintr
.global intr_vec0 .global intr_vec0
@ -49,85 +51,23 @@
.global intr_vec46 .global intr_vec46
.global intr_vec47 .global intr_vec47
.macro _PUSHAQ
push %rax
push %rbx
push %rcx
push %rdx
push %rbp
push %rdi
push %rsi
push %r8
push %r9
push %r10
push %r11
push %r12
push %r13
push %r14
push %r15
.endm
.macro _POPAQ
pop %r15
pop %r14
pop %r13
pop %r12
pop %r11
pop %r10
pop %r9
pop %r8
pop %rsi
pop %rdi
pop %rbp
pop %rdx
pop %rcx
pop %rbx
pop %rax
.endm
.macro _PUSHACR
mov %cr0, %rax
push %rax
mov %cr2, %rax
push %rax
mov %cr3, %rax
push %rax
mov %cr4, %rax
push %rax
mov %cr8, %rax
push %rax
.endm
.macro _POPACR
add $0x28, %rsp
.endm
.macro _vecintr_errorcode_present_save num .macro _vecintr_errorcode_present_save num
pushq $\num pushq $\num
_PUSHAQ
_PUSHACR
.endm .endm
.macro _vecintr_plain_save num .macro _vecintr_plain_save num
pushq $0x0 pushq $0x0
pushq $\num pushq $\num
_PUSHAQ
_PUSHACR
.endm .endm
siema:
jmp siema
.macro _vecintr_bodygen .macro _vecintr_bodygen
_push_regs
cld
mov %rsp, %rdi mov %rsp, %rdi
call intr_handleintr call intr_handleintr
_POPACR _pop_regs
_POPAQ
add $0x10, %rsp add $0x10, %rsp
iretq iretq
.endm .endm
@ -227,7 +167,6 @@ intr_vec30:
intr_vec31: intr_vec31:
_vecintr_plain_save 31 _vecintr_plain_save 31
_vecintr_bodygen _vecintr_bodygen
intr_vec32: intr_vec32:
_vecintr_plain_save 32 _vecintr_plain_save 32
_vecintr_bodygen _vecintr_bodygen

View File

@ -0,0 +1,4 @@
.global hal_loadpd
hal_loadpd:
mov %rdi, %cr3
retq

View File

@ -0,0 +1,6 @@
#ifndef HAL_PAGING_H_
#define HAL_PAGING_H_
void hal_loadpd(PgTable *cr3);
#endif // HAL_PAGING_H_

15
kernel/hal/x86_64/proc.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef HAL_PROC_H_
#define HAL_PROC_H_
#include <stdint.h>
#include "intr.h"
#include "vmm.h"
typedef struct {
uint64_t fsbase;
IntrStackFrame trapframe;
uint8_t *kstack;
PgTable *cr3;
} ProcPlatformData;
#endif // HAL_PROC_H_

31
kernel/hal/x86_64/regs.S Normal file
View File

@ -0,0 +1,31 @@
.macro _push_regs
push %rax
push %rcx
push %rdx
push %rsi
push %rdi
push %r8
push %r9
push %r10
push %r11
push %r12
push %r13
push %r14
push %r15
.endm
.macro _pop_regs
pop %r15
pop %r14
pop %r13
pop %r12
pop %r11
pop %r10
pop %r9
pop %r8
pop %rdi
pop %rsi
pop %rdx
pop %rcx
pop %rax
.endm

View File

@ -0,0 +1,19 @@
#include "regs.S"
siema:
jmp siema
.global hal_switchproc
hal_switchproc:
mov %cr3, %rcx
cmp %rsi, %rcx
je .done
mov %rsi, %cr3
.done:
mov %rdi, %rsp
_pop_regs
add $0x10, %rsp
iretq

View File

@ -0,0 +1,6 @@
#ifndef HAL_SWITCH_H_
#define HAL_SWITCH_H_
extern void hal_switchproc(void *newsp, PgTable *cr3);
#endif // HAL_SWITCH_H_

101
kernel/hal/x86_64/vmm.c Normal file
View File

@ -0,0 +1,101 @@
#include <stddef.h>
#include <stdint.h>
#include "vmm.h"
#include "hal/hal.h"
#include "bootinfo/bootinfo.h"
#include "pmm/pmm.h"
#include "paging.h"
PgTable *KERNEL_CR3 = NULL;
PgTable *hal_vmm_current_cr3(void) {
PgTable *cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
return cr3;
}
PgIndex hal_vmm_pageindex(uint64_t vaddr) {
PgIndex ret;
ret.pml4 = (vaddr >> 39) & 0x1ff;
ret.pml3 = (vaddr >> 30) & 0x1ff;
ret.pml2 = (vaddr >> 21) & 0x1ff;
ret.pml1 = (vaddr >> 12) & 0x1ff;
return ret;
}
uint64_t *hal_vmm_nexttable(uint64_t *table, uint64_t ent) {
uint8_t *addr;
if (table[ent] & HAL_PG_PRESENT) {
addr = (uint8_t *)(table[ent] & ~((uint64_t)0xfff));
} else {
addr = pmm_alloc(1);
hal_memset(BOOT_INFO.hhdm_off + addr, 0, HAL_PAGE_SIZE);
table[ent] = (uint64_t)addr | HAL_PG_USER | HAL_PG_RW | HAL_PG_PRESENT;
}
return (uint64_t *)(BOOT_INFO.hhdm_off + addr);
}
void hal_vmm_map_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr, uint32_t flags) {
PgIndex pi = hal_vmm_pageindex(virtaddr);
uint64_t *pml3 = hal_vmm_nexttable((uint64_t *)pml4, pi.pml4);
uint64_t *pml2 = hal_vmm_nexttable((uint64_t *)pml3, pi.pml3);
uint64_t *pml1 = hal_vmm_nexttable((uint64_t *)pml2, pi.pml2);
uint64_t *pte = &pml1[pi.pml1];
*pte = (physaddr & ~0xFFF) | (flags & 0x7);
}
void hal_vmm_unmap_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr) {
PgIndex pi = hal_vmm_pageindex(virtaddr);
uint64_t *pml3 = hal_vmm_nexttable((uint64_t *)pml4, pi.pml4);
uint64_t *pml2 = hal_vmm_nexttable((uint64_t *)pml3, pi.pml3);
uint64_t *pml1 = hal_vmm_nexttable((uint64_t *)pml2, pi.pml2);
uint64_t *pte = &pml1[pi.pml1];
*pte &= ~HAL_PG_PRESENT;
}
void hal_vmm_map_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags) {
if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PG_PRESENT != 0) {
return;
}
uint8_t *vaddr = virtstart, *paddr = physstart;
for (; vaddr <= ((uint8_t *)virtstart + size); vaddr += HAL_PAGE_SIZE, paddr += HAL_PAGE_SIZE) {
hal_vmm_map_page(cr3, (uint64_t)vaddr, (uint64_t)paddr, flags);
}
}
void hal_vmm_unmap_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags) {
if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PG_PRESENT != 0) {
return;
}
uint8_t *vaddr = virtstart, *paddr = physstart;
for (; vaddr <= ((uint8_t *)virtstart + size); vaddr += HAL_PAGE_SIZE, paddr += HAL_PAGE_SIZE) {
hal_vmm_unmap_page(cr3, (uint64_t)vaddr, (uint64_t)paddr);
}
}
void hal_vmm_map_kern(PgTable *cr3) {
PgTable *kcr3 = BOOT_INFO.hhdm_off + KERNEL_CR3;
for (size_t i = 256; i < 512; i++) {
cr3->ents[i] = kcr3->ents[i];
}
}
void hal_vmm_switch_pd(PgTable *cr3) {
hal_loadpd(cr3);
}
void hal_vmm_init(void) {
KERNEL_CR3 = hal_vmm_current_cr3();
}

48
kernel/hal/x86_64/vmm.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef HAL_VMM_H_
#define HAL_VMM_H_
#include <stdint.h>
#include <stdbool.h>
#include "compiler/attr.h"
enum {
HAL_PG_PRESENT = 1<<0,
HAL_PG_RW = 1<<1,
HAL_PG_USER = 1<<2,
};
typedef struct {
uint64_t pml4;
uint64_t pml3;
uint64_t pml2;
uint64_t pml1;
} PACKED PgIndex;
typedef struct {
bool present: 1;
bool rw: 1;
bool user: 1;
bool writethrough: 1;
bool cachedisabled: 1;
bool accessed: 1;
bool zero0: 1;
bool size: 1;
bool zero1: 1;
uint8_t avail: 3;
uint64_t addr: 52;
} PACKED Pte;
typedef struct {
Pte ents[512];
} PACKED PgTable;
extern PgTable *KERNEL_CR3;
void hal_vmm_init(void);
void hal_vmm_unmap_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr);
void hal_vmm_map_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr, uint32_t flags);
PgTable *hal_vmm_current_cr3(void);
void hal_vmm_map_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags);
void hal_vmm_unmap_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags);
#endif // HAL_VMM_H_

View File

@ -4,13 +4,14 @@
#include "hal/hal.h" #include "hal/hal.h"
#include "bootinfo/bootinfo.h" #include "bootinfo/bootinfo.h"
#include "pmm/pmm.h" #include "pmm/pmm.h"
#include "vmm/vmm.h"
#include "term/term.h" #include "term/term.h"
#include "paging/paging.h"
#include "dlmalloc/malloc.h" #include "dlmalloc/malloc.h"
#include "vfs/vfs.h" #include "vfs/vfs.h"
#include "baseimg/baseimg.h" #include "baseimg/baseimg.h"
#include "storedev/storedev.h" #include "storedev/storedev.h"
#include "util/util.h" #include "util/util.h"
#include "proc/proc.h"
const char *human_size(uint64_t bytes, char *buf, size_t bufsize) { const char *human_size(uint64_t bytes, char *buf, size_t bufsize) {
static const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" }; static const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" };
@ -56,19 +57,17 @@ void kmain(void) {
} }
bootinfo_init(); bootinfo_init();
term_init(); term_init(BOOT_INFO.fb->address);
log_bootinfo(); log_bootinfo();
hal_init(); hal_init();
pmm_init(); pmm_init();
paging_init(); vmm_init();
dlmalloc_check(); dlmalloc_check();
hal_init_withmalloc();
/* hal_intr_disable(); */
storedev_init(); storedev_init();
baseimg_init(); baseimg_init();
vfs_init(); vfs_init();
hal_init_withmalloc();
proc_init();
/* kprintf(BANNER_TEXT "\n"); */ for(;;);
hal_hang();
} }

View File

@ -2,8 +2,21 @@
#define KPRINTF_H_ #define KPRINTF_H_
#include <printf/printf.h> #include <printf/printf.h>
#include "term/term.h"
#include "spinlock/spinlock.h"
#define kprintf(fmt, ...) \
do { \
spinlock_acquire(&TERM.spinlock); \
printf_(fmt, ##__VA_ARGS__); \
spinlock_release(&TERM.spinlock); \
} while(0)
#define kprintf_unsafe(fmt, ...) \
do { \
printf_(fmt, ##__VA_ARGS__); \
} while(0)
#define kprintf printf_
#define ksprintf sprintf_ #define ksprintf sprintf_
#define kvsprintf vsprintf_ #define kvsprintf vsprintf_
#define ksnprintf snprintf_ #define ksnprintf snprintf_

View File

@ -1,10 +0,0 @@
#ifndef PAGING_PAGING_H_
#define PAGING_PAGING_H_
#include <stddef.h>
#include <stdint.h>
void paging_init(void);
size_t paging_virt2phys(size_t virtaddr);
#endif // PAGING_PAGING_H_

View File

@ -1,124 +0,0 @@
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
#include "paging/paging.h"
#include "hal/hal.h"
#include "bootinfo/bootinfo.h"
#include "util/util.h"
#include "kprintf.h"
enum {
PF_PRESENT = 1<<0,
PF_READWRITE = 1<<1,
PF_USER = 1<<2,
PF_WRITETHROUGH = 1<<3,
PF_NOCACHE = 1<<4,
PF_ACCESS = 1<<5,
PF_DIRTY = 1<<6,
PF_PAGESIZE = 1<<7,
PF_ATTRTAB = 1<<7,
PF_GLOBAL = 1<<8,
PF_SHARED = 1<<9,
PF_CACHE_WC = PF_ATTRTAB | PF_WRITETHROUGH,
};
#define PGSHIFT_PML4E 39
#define PGSHIFT_PDPTE 30
#define PGSHIFT_PDE 21
#define PGSHIFT_PTE 12
#define PGMASK_ENTRY 0x1ff
#define PGMASK_OFFSET 0x3ff
#define BITS_TO_VIRT_ADDR(pml4_index, pdpte_index, pd_index, pt_index) \
(((uint64_t)pml4_index << PGSHIFT_PML4E) | \
((uint64_t)pdpte_index << PGSHIFT_PDPTE) | \
((uint64_t)pd_index << PGSHIFT_PDE) | ((uint64_t)pt_index << PGSHIFT_PTE))
// Workaround repeated characters
#define AMD64_MM_STRIPSX(a) ((uintptr_t)(a) & 0xFFFFFFFFFFFF)
#define AMD64_MM_ADDRSX(a) \
(((uintptr_t)(a) & (1ULL << 47)) ? (0xFFFFFF0000000000 | ((uintptr_t)(a))) \
: ((uintptr_t)(a)))
// Virtual address' macros
#define PML4E(a) (((a) >> PGSHIFT_PML4E) & PGMASK_ENTRY)
#define PDPTE(a) (((a) >> PGSHIFT_PDPTE) & PGMASK_ENTRY)
#define PDE(a) (((a) >> PGSHIFT_PDE) & PGMASK_ENTRY)
#define PTE(a) (((a) >> PGSHIFT_PTE) & PGMASK_ENTRY)
#define PTE_ADDR_MASK 0x000ffffffffff000
#define PTE_GET_ADDR(VALUE) ((VALUE) & PTE_ADDR_MASK)
#define PTE_GET_FLAGS(VALUE) ((VALUE) & ~PTE_ADDR_MASK)
#define PAGE_MASK(x) ((1 << (x)) - 1)
#define USER_STACK_PAGES 2048
#define PAGE_SIZE 0x1000
#define PAGE_SIZE_LARGE 0x200000
#define PAGE_SIZE_HUGE 0x40000000
#define P_PHYs_ADD(x) ((x) & ~0xfff)
uint64_t *global_page_dir = NULL;
void paging_init(void) {
uint64_t pdphys = 0;
asm volatile("movq %%cr3, %0" : "=r"(pdphys));
if (!pdphys) {
ERR("paging", "could not get default page dir\n");
hal_hang();
}
uint64_t pdvirt = pdphys + BOOT_INFO.hhdm_off;
global_page_dir = (uint64_t *)pdvirt;
LOG("paging", "global_page_dir = %p\n", global_page_dir);
}
size_t _paging_virt2phys(uint64_t *pgdir, size_t virtaddr) {
if (!pgdir) return 0;
if (virtaddr >= BOOT_INFO.hhdm_off
&& virtaddr <= (BOOT_INFO.hhdm_off + MAX(BOOT_INFO.memmap_total, UINT32_MAX))) {
return virtaddr - BOOT_INFO.hhdm_off;
}
size_t virtaddr_init = virtaddr;
virtaddr &= ~0xfff;
virtaddr = AMD64_MM_STRIPSX(virtaddr);
uint32_t pml4idx = PML4E(virtaddr);
uint32_t pdpidx = PDPTE(virtaddr);
uint32_t pdidx = PDE(virtaddr);
uint32_t ptidx = PTE(virtaddr);
if (!(pgdir[pml4idx] & PF_PRESENT)) {
return 0;
}
size_t *pdp = (size_t *)(PTE_GET_ADDR(pgdir[pml4idx]) + BOOT_INFO.hhdm_off);
if (!(pdp[pdpidx] & PF_PRESENT)) {
return 0;
}
size_t *pd = (size_t *)(PTE_GET_ADDR(pdp[pdpidx]) + BOOT_INFO.hhdm_off);
if (!(pd[pdidx] & PF_PRESENT)) {
return 0;
}
size_t *pt = (size_t *)(PTE_GET_ADDR(pd[pdidx]) + BOOT_INFO.hhdm_off);
if (pt[ptidx] & PF_PRESENT) {
return (size_t)(PTE_GET_ADDR(pt[ptidx]) + ((size_t)virtaddr_init & 0xfff));
}
return 0;
}
size_t paging_virt2phys(size_t virtaddr) {
return _paging_virt2phys(global_page_dir, virtaddr);
}

View File

@ -6,6 +6,7 @@
#include "bootinfo/bootinfo.h" #include "bootinfo/bootinfo.h"
#include "spinlock/spinlock.h" #include "spinlock/spinlock.h"
#include "util/util.h" #include "util/util.h"
#include "hal/hal.h"
PhysMem PHYS_MEM; PhysMem PHYS_MEM;
@ -13,7 +14,6 @@ void pmm_init(void) {
spinlock_init(&PHYS_MEM.spinlock); spinlock_init(&PHYS_MEM.spinlock);
BitMap *bm = &PHYS_MEM.self; BitMap *bm = &PHYS_MEM.self;
bm->init = false;
bm->nblocks = _DIV_ROUNDUP(BOOT_INFO.memmap_total, BITMAP_BLOCK_SIZE); bm->nblocks = _DIV_ROUNDUP(BOOT_INFO.memmap_total, BITMAP_BLOCK_SIZE);
bm->nbytes = _DIV_ROUNDUP(bm->nblocks, 8); bm->nbytes = _DIV_ROUNDUP(bm->nblocks, 8);
@ -48,7 +48,6 @@ void pmm_init(void) {
bm->alloc_blocks = 0; bm->alloc_blocks = 0;
LOG("pmm", "phys bitmap init 0x%lx, size = 0x%lx\n", physbegin, bm->nbytes); LOG("pmm", "phys bitmap init 0x%lx, size = 0x%lx\n", physbegin, bm->nbytes);
bm->init = true;
} }
void *pmm_alloc(size_t pages) { void *pmm_alloc(size_t pages) {

159
kernel/proc/proc.c Normal file
View File

@ -0,0 +1,159 @@
#include <stdint.h>
#include <stdlib.h>
#include "hal/hal.h"
#include "vmm/vmm.h"
#include "spinlock/spinlock.h"
#include "proc.h"
#include "dlmalloc/malloc.h"
#include "pmm/pmm.h"
#include "util/util.h"
#include "kprintf.h"
#define PROC_REAPER_FREQ 30
uint64_t pids = 0;
uint64_t sched_ticks = 0;
Procs PROCS;
Proc *proc_spawnkern(void (*ent)(void), char *name) {
Proc *proc = dlmalloc(sizeof(*proc));
if (proc == NULL) {
return NULL;
}
hal_memset(proc, 0, sizeof(*proc));
hal_memcpy(proc->name, name, PROC_NAME_MAX);
proc->kern = true;
uint8_t *sp = (uint8_t *)pmm_alloc(PROC_STACKBLOCKS) + PROC_STACKSIZE;
#if defined(__x86_64__)
proc->platformdata.kstack = sp;
hal_memset(&proc->platformdata.trapframe, 0, sizeof(proc->platformdata.trapframe));
proc->platformdata.trapframe.ss = 0x10;
proc->platformdata.trapframe.rsp = (uint64_t)VIRT(sp);
proc->platformdata.trapframe.rflags = 0x202;
proc->platformdata.trapframe.cs = 0x08;
proc->platformdata.trapframe.rip = (uint64_t)ent;
proc->platformdata.cr3 = hal_vmm_current_cr3();
proc->state = PROC_READY;
proc->pid = pids++;
#endif
return proc;
}
void proc_register(Proc *proc) {
spinlock_acquire(&PROCS.spinlock);
LL_APPEND(PROCS.procs, proc);
spinlock_release(&PROCS.spinlock);
}
Proc *proc_nextready(void) {
Proc *next = PROCS.current->next;
Proc *proc = next == NULL ? PROCS.procs : next;
return proc;
}
void proc_sched(void *cpustate) {
hal_intr_disable();
sched_ticks++;
if (sched_ticks % PROC_REAPER_FREQ == 0) {
Proc *head = PROCS.procs;
while (head) {
if (head->state == PROC_ZOMBIE) {
Proc *zombie = head;
head = head->next;
LL_REMOVE(PROCS.procs, zombie);
pmm_free((uintptr_t)(zombie->platformdata.kstack - PROC_STACKSIZE), PROC_STACKBLOCKS);
dlfree(zombie);
} else {
head = head->next;
}
}
}
#if defined(__x86_64__)
IntrStackFrame *frame = cpustate;
PROCS.current->platformdata.trapframe = *frame;
PROCS.current->platformdata.fsbase = hal_cpu_rdmsr(HAL_CPU_FSBASE);
#endif
PROCS.current = proc_nextready();
PROCS.current->state = PROC_RUNNING;
#if defined(__x86_64__)
hal_cpu_wrmsr(HAL_CPU_FSBASE, PROCS.current->platformdata.fsbase);
hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3);
#endif
}
void proc_kill(Proc *proc) {
proc->state = PROC_ZOMBIE;
}
void proc_killself(void) {
spinlock_acquire(&PROCS.spinlock);
Proc *proc = PROCS.current;
proc_kill(proc);
spinlock_release(&PROCS.spinlock);
}
void proc_idle(void) {
for(;;) {
// .
}
}
int a = 0;
void proc_print(void) {
for (;;) {
for (volatile size_t i = 0; i < 0x1000000; i++) {
}
if (a == 10) {
proc_killself();
for(;;);
}
kprintf("A");
a++;
}
}
int b = 0;
void proc_print2(void) {
for (;;) {
for (volatile size_t i = 0; i < 0x1000000; i++) {
}
if (b == 20) {
proc_killself();
for(;;);
}
kprintf("B");
b++;
}
}
void proc_init(void) {
spinlock_init(&PROCS.spinlock);
PROCS.procs = NULL;
Proc *idle = proc_spawnkern(&proc_idle, "kIDLE");
proc_register(idle);
PROCS.current = idle;
proc_register(proc_spawnkern(&proc_print, "print"));
proc_register(proc_spawnkern(&proc_print2, "print"));
#if defined(__x86_64__)
hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3);
#endif
}

44
kernel/proc/proc.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef PROC_PROC_H_
#define PROC_PROC_H_
#include <stdint.h>
#include "hal/hal.h"
#include "vmm/vmm.h"
#include "spinlock/spinlock.h"
#include "bitmap/bitmap.h"
#define PROC_NAME_MAX 0x100
#define PROC_STACKBLOCKS 32
#define PROC_STACKSIZE (PROC_STACKBLOCKS * BITMAP_BLOCK_SIZE)
enum {
PROC_READY,
PROC_RUNNING,
PROC_ZOMBIE,
PROC_WAITING,
};
typedef struct Proc {
struct Proc *next;
uint64_t pid;
char name[PROC_NAME_MAX];
ProcPlatformData platformdata;
uint8_t state;
VasRange *vas;
bool kern;
} Proc;
typedef struct {
SpinLock spinlock;
Proc *procs;
Proc *current;
} Procs;
extern Procs PROCS;
void proc_init(void);
Proc *proc_spawnkern(void (*ent)(void), char *name);
void proc_sched(void *cpustate);
#endif // PROC_PROC_H_

View File

@ -1,6 +1,7 @@
#include <stdatomic.h> #include <stdatomic.h>
#include <stdint.h> #include <stdint.h>
#include "spinlock.h" #include "spinlock.h"
#include "hal/hal.h"
void spinlock_init(SpinLock *sl) { void spinlock_init(SpinLock *sl) {
atomic_store(&sl->lock, false); atomic_store(&sl->lock, false);
@ -15,6 +16,9 @@ void spinlock_acquire(SpinLock *sl) {
} }
void spinlock_release(SpinLock *sl) { void spinlock_release(SpinLock *sl) {
bool locked = true;
if (atomic_compare_exchange_strong(&sl->lock, &locked, false)) {
atomic_store(&sl->lock, false); atomic_store(&sl->lock, false);
}
} }

View File

@ -3,9 +3,10 @@
#include <stdatomic.h> #include <stdatomic.h>
#include <stdint.h> #include <stdint.h>
#include "hal/hal.h"
typedef struct { atomic_bool lock; } SpinLock; typedef struct {
atomic_bool lock;
} SpinLock;
// Spin more efficiently - cpu dependant // Spin more efficiently - cpu dependant
#if defined(__x86_64__) #if defined(__x86_64__)

View File

@ -12,11 +12,14 @@
#define atomic_store_explicit __atomic_store_n #define atomic_store_explicit __atomic_store_n
#define atomic_store(p, v) atomic_store_explicit(p, v, memory_order_relaxed) #define atomic_store(p, v) atomic_store_explicit(p, v, memory_order_relaxed)
#define atomic_load(p, v) atomic_load_explicit(p, v, memory_order_relaxed) #define atomic_load(p) atomic_load_explicit(p, memory_order_relaxed)
#define atomic_compare_exchange_weak(p, old, new) \ #define atomic_compare_exchange_weak(p, old, new) \
__atomic_compare_exchange_n(p, old, new, true, memory_order_relaxed, memory_order_relaxed) __atomic_compare_exchange_n(p, old, new, true, memory_order_relaxed, memory_order_relaxed)
#define atomic_compare_exchange_strong(p, old, new) \
__atomic_compare_exchange_n(p, old, new, false, memory_order_relaxed, memory_order_relaxed)
#define atomic_bool volatile bool #define atomic_bool volatile bool
#endif #endif

View File

@ -7,10 +7,10 @@
Term TERM; Term TERM;
void term_init(void) { void term_doinit(void *addr) {
TERM.ftctx = flanterm_fb_init( TERM.ftctx = flanterm_fb_init(
NULL, NULL, NULL, NULL,
BOOT_INFO.fb->address, addr,
BOOT_INFO.fb->width, BOOT_INFO.fb->width,
BOOT_INFO.fb->height, BOOT_INFO.fb->height,
BOOT_INFO.fb->pitch, BOOT_INFO.fb->pitch,
@ -30,13 +30,18 @@ void term_init(void) {
); );
} }
void term_write(const char *s, size_t len) { void term_init(void *addr) {
spinlock_init(&TERM.spinlock);
term_doinit(addr);
}
void term_write_unsafe(const char *s, size_t len) {
flanterm_write(TERM.ftctx, s, len); flanterm_write(TERM.ftctx, s, len);
} }
#if PUTCHAR_ == PUTCHAR_FB #if PUTCHAR_ == PUTCHAR_FB
// For printf library // For printf library
void putchar_(char c) { void putchar_(char c) {
term_write(&c, 1); term_write_unsafe(&c, 1);
} }
#endif #endif

View File

@ -7,10 +7,12 @@
typedef struct { typedef struct {
struct flanterm_context *ftctx; struct flanterm_context *ftctx;
SpinLock spinlock;
} Term; } Term;
extern Term TERM; extern Term TERM;
void term_init(void); void term_init(void *addr);
void term_write_unsafe(const char *s, size_t len);
#endif // TERM_TERM_H_ #endif // TERM_TERM_H_

View File

@ -35,6 +35,18 @@
} \ } \
} while(0) } while(0)
#define LL_FINDPROP(head, out, propname, propvalue) \
do { \
typeof((head)) __tmp = (head); \
while (__tmp) { \
if (__tmp->propname == (propvalue)) { \
(out) = __tmp; \
break; \
} \
__tmp = __tmp->next; \
} \
} while(0)
char *util_get_filename(char *path); char *util_get_filename(char *path);
#endif // UTIL_UTIL_H_ #endif // UTIL_UTIL_H_

View File

@ -190,7 +190,7 @@ void vfs_init(void) {
tmpvars_init(); tmpvars_init();
base_init(); base_init();
LOG("vfs", "init done\n"); LOG("vfs", "init\n");
for (size_t i = 0; i < LEN(VFS_TABLE.mountpoints); i++) { for (size_t i = 0; i < LEN(VFS_TABLE.mountpoints); i++) {
if (!VFS_TABLE.mountpoints[i].taken) continue; if (!VFS_TABLE.mountpoints[i].taken) continue;

View File

@ -8,45 +8,46 @@
#include "util/util.h" #include "util/util.h"
#include "hal/hal.h" #include "hal/hal.h"
#include "pmm/pmm.h" #include "pmm/pmm.h"
#include "paging/paging.h"
#define POS_ENSURE 0x40000000
#define PAGE_SIZE 0x1000
VirtMem VIRT_MEM; VirtMem VIRT_MEM;
void vmm_map_kern_page(uint64_t virtaddr, uint64_t physaddr, uint32_t flags) {
spinlock_acquire(&VIRT_MEM.spinlock);
#if defined(__x86_64__)
hal_vmm_map_page(KERNEL_CR3, virtaddr, physaddr, flags);
#endif
spinlock_release(&VIRT_MEM.spinlock);
}
void vmm_unmap_kern_page(uint64_t virtaddr, uint64_t physaddr) {
spinlock_acquire(&VIRT_MEM.spinlock);
#if defined(__x86_64__)
hal_vmm_unmap_page(KERNEL_CR3, virtaddr, physaddr);
#endif
spinlock_release(&VIRT_MEM.spinlock);
}
void vmm_map_kern_range(void *virtstart, void *physstart, size_t size, uint32_t flags) {
spinlock_acquire(&VIRT_MEM.spinlock);
#if defined(__x86_64__)
hal_vmm_map_range(KERNEL_CR3, virtstart, physstart, size, flags);
#endif
spinlock_release(&VIRT_MEM.spinlock);
}
void vmm_unmap_kern_range(void *virtstart, void *physstart, size_t size, uint32_t flags) {
spinlock_acquire(&VIRT_MEM.spinlock);
#if defined(__x86_64__)
hal_vmm_unmap_range(KERNEL_CR3, virtstart, physstart, size, flags);
#endif
spinlock_release(&VIRT_MEM.spinlock);
}
void vmm_init(void) { void vmm_init(void) {
spinlock_init(&VIRT_MEM.spinlock); spinlock_init(&VIRT_MEM.spinlock);
BitMap *bm = &VIRT_MEM.self;
size_t targetpos = _DIV_ROUNDUP(BOOT_INFO.hhdm_off - BOOT_INFO.memmap_total - POS_ENSURE, PAGE_SIZE) * PAGE_SIZE; hal_vmm_init();
bm->init = false;
bm->mem_start = targetpos; LOG("vmm", "init\n");
bm->nblocks = _DIV_ROUNDUP(BOOT_INFO.memmap_total, BITMAP_BLOCK_SIZE);
bm->nbytes = _DIV_ROUNDUP(bm->nblocks, 8);
uint64_t pagesrequired = _DIV_ROUNDUP(bm->nbytes, BITMAP_BLOCK_SIZE);
bm->map = (uint8_t *)vmm_alloc(pagesrequired);
hal_memset(bm->map, 0, bm->nbytes);
bm->init = true;
}
void *vmm_alloc(size_t pages) {
size_t phys = (size_t)pmm_alloc(pages);
uint64_t out = phys + BOOT_INFO.hhdm_off;
return (void *)out;
}
void vmm_free(void *ptr, size_t pages) {
size_t phys = paging_virt2phys((size_t)ptr);
if (!phys) {
ERR("vmm", "could not find phys addr for %p\n", ptr);
hal_hang();
}
pmm_free(phys, pages);
} }

View File

@ -2,18 +2,27 @@
#define VMM_VMM_H_ #define VMM_VMM_H_
#include <stddef.h> #include <stddef.h>
#include "bitmap/bitmap.h"
#include "spinlock/spinlock.h" #include "spinlock/spinlock.h"
#include "bootinfo/bootinfo.h"
#include "compiler/attr.h"
typedef struct { typedef struct {
SpinLock spinlock; SpinLock spinlock;
BitMap self;
} VirtMem; } VirtMem;
typedef struct VasRange {
struct VasRange *next;
uint8_t *virtstart;
uint8_t *physstart;
size_t size;
uint8_t pgflags;
} PACKED VasRange;
extern VirtMem VIRT_MEM; extern VirtMem VIRT_MEM;
void vmm_init(void); void vmm_init(void);
void *vmm_alloc(size_t pages);
void vmm_free(void *ptr, size_t pages); #define VIRT(X) ((void *)(BOOT_INFO.hhdm_off + (uint64_t)(X)))
#endif // VMM_VMM_H_ #endif // VMM_VMM_H_