Rework x86_64 paging and vmm

This commit is contained in:
2025-08-30 00:31:20 +02:00
parent 8cf1bde879
commit 7a52f2f051
28 changed files with 262 additions and 291 deletions

View File

@ -50,7 +50,7 @@ typedef struct {
ALIGNED(16) static Tss tss = {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->basemid = (base >> 16) & 0xff;
ent->basehigh = (base >> 24) & 0xff;

View File

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

View File

@ -1,5 +1,6 @@
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "intr.h"
#include "io.h"
#include "gdt.h"
@ -55,45 +56,6 @@ void idt_init(void) {
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[];
static const char *exceptions[] = {
@ -164,36 +126,39 @@ void intr_init(void) {
}
void intr_dumpframe(IntrStackFrame *frame) {
kprintf("r15=%016lx r14=%016lx r13=%016lx r12=%016lx\n"
"r11=%016lx r10=%016lx r9 =%016lx r8 =%016lx\n"
"rsi=%016lx rdi=%016lx rbp=%016lx rdx=%016lx\n"
"rcx=%016lx rbx=%016lx rax=%016lx\n"
"cr8=%016lx cr4=%016lx cr3=%016lx cr2=%016lx\n"
"cr0=%016lx rip=%016lx cs =%016lx rfl=%016lx\n"
"rsp=%016lx ss =%016lx trp=%016lx err=%016lx\n",
frame->regs.r15, frame->regs.r14, frame->regs.r13, frame->regs.r12,
frame->regs.r11, frame->regs.r10, frame->regs.r9, frame->regs.r8,
frame->regs.rsi, frame->regs.rdi, frame->regs.rbp, frame->regs.rdx,
frame->regs.rcx, frame->regs.rbx, frame->regs.rax,
frame->ctrl.cr8, frame->ctrl.cr4, frame->ctrl.cr3,
frame->ctrl.cr2, frame->ctrl.cr0, frame->rip, frame->cs, frame->rflags,
frame->rsp, frame->ss, frame->trapnum, frame->errnum
uint64_t cr2;
asm volatile("mov %%cr2, %0" : "=r"(cr2));
uint64_t cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
uint64_t cr4;
asm volatile("mov %%cr4, %0" : "=r"(cr4));
kprintf_unsafe("rax=%016lx rcx=%016lx rdx=%016lx\n"
"rsi=%016lx rdi=%016lx r8 =%016lx\n"
"r9 =%016lx r10=%016lx r11=%016lx\n"
"rip=%016lx rfl=%016lx rsp=%016lx\n"
"cs =%016lx ss =%016lx trp=%016lx\n"
"cr2=%016lx cr3=%016lx cr4=%016lx\n"
"\n\n",
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) {
if (frame->trapnum >= 0 && frame->trapnum <= 31) {
// 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);
hal_hang();
} else if (frame->trapnum >= 32 && frame->trapnum <= 47) {
if (frame->trapnum == INTR_TIMER) {
kprintf("ACK %d\n", PIT_TICKS);
PIT_TICKS++;
io_out8(PIC2_CMD, 0x20);
PIT_TICKS++;
}
io_out8(PIC1_CMD, 0x20);
lapic_write(LAPIC_EOI, 0x00);
}

View File

@ -6,6 +6,35 @@
#define INTR_TIMER 0x20
#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);
#endif // HAL_INTR_H_

View File

@ -49,14 +49,12 @@
.global intr_vec46
.global intr_vec47
.macro _PUSHAQ
.macro _push_regs
push %rax
push %rbx
push %rcx
push %rdx
push %rbp
push %rdi
push %rsi
push %rdi
push %r8
push %r9
push %r10
@ -67,7 +65,7 @@
push %r15
.endm
.macro _POPAQ
.macro _pop_regs
pop %r15
pop %r14
pop %r13
@ -76,58 +74,30 @@
pop %r10
pop %r9
pop %r8
pop %rsi
pop %rdi
pop %rbp
pop %rsi
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
pushq $\num
_PUSHAQ
_PUSHACR
.endm
.macro _vecintr_plain_save num
pushq $0x0
pushq $\num
_PUSHAQ
_PUSHACR
.endm
siema:
jmp siema
.macro _vecintr_bodygen
_push_regs
cld
mov %rsp, %rdi
call intr_handleintr
_POPACR
_POPAQ
_pop_regs
add $0x10, %rsp
iretq
.endm
@ -227,7 +197,6 @@ intr_vec30:
intr_vec31:
_vecintr_plain_save 31
_vecintr_bodygen
intr_vec32:
_vecintr_plain_save 32
_vecintr_bodygen

View File

@ -0,0 +1,9 @@
.global hal_loadpd
hal_loadpd:
mov %rdi, %cr3
retq
.global hal_invalpg
hal_invalpg:
invlpg (%rdi)
retq

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

@ -0,0 +1,65 @@
#include <stddef.h>
#include <stdint.h>
#include "vmm.h"
#include "hal/hal.h"
#include "bootinfo/bootinfo.h"
#include "pmm/pmm.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 & ((uint64_t)0x1ff < 39)) >> 39;
ret.pml3 = (vaddr & ((uint64_t)0x1ff < 30)) >> 30;
ret.pml2 = (vaddr & ((uint64_t)0x1ff < 21)) >> 21;
ret.pml1 = (vaddr & ((uint64_t)0x1ff < 12)) >> 12;
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 | (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 = physaddr & (~0x7);
}
void hal_vmm_init(void) {
KERNEL_CR3 = hal_vmm_current_cr3();
}

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

@ -0,0 +1,45 @@
#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);
#endif // HAL_VMM_H_