Virtual memory and dlmalloc

This commit is contained in:
2025-08-14 01:49:04 +02:00
parent 95832bb3a7
commit b470fb03da
10 changed files with 6618 additions and 6 deletions

View File

@ -9,7 +9,7 @@ CFLAGS += -I. \
-I../limine \
-I./std/include \
-I./flanterm/src \
-DPRINTF_INCLUDE_CONFIG_H=1
-DPRINTF_INCLUDE_CONFIG_H=1 \
ifeq ($(PUTCHAR_),fb)
CFLAGS += -DPUTCHAR_=PUTCHAR_FB
@ -29,9 +29,13 @@ SRCFILES := $(wildcard *.c) \
$(wildcard bootinfo/*.c) \
$(wildcard spinlock/*.c) \
$(wildcard term/*.c) \
$(wildcard vmm/*.c) \
$(wildcard dlmalloc/*.c) \
$(wildcard hal/*.c) \
$(wildcard hal/$(ARCH)/*.c) \
$(wildcard hal/$(ARCH)/*.S) \
$(wildcard paging/$(ARCH)/*.c) \
$(wildcard paging/*.c) \
$(wildcard *.S) \
$(wildcard std/*.c) \
$(wildcard flanterm/src/*.c) \

6380
kernel/dlmalloc/malloc.c Normal file

File diff suppressed because it is too large Load Diff

13
kernel/dlmalloc/malloc.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef MALLOC_MALLOC_H_
#define MALLOC_MALLOC_H_
#include <stddef.h>
void *dlmalloc(size_t);
void dlfree(void *);
void *dlcalloc(size_t, size_t);
void *dlrealloc(void *, size_t);
void *dlrealloc_in_place(void *, size_t);
void dlmalloc_check(void);
#endif // MALLOC_MALLOC_H_

View File

@ -5,6 +5,8 @@
#include "bootinfo/bootinfo.h"
#include "pmm/pmm.h"
#include "term/term.h"
#include "paging/paging.h"
#include "dlmalloc/malloc.h"
static volatile LIMINE_BASE_REVISION(2);
@ -17,6 +19,8 @@ void kmain(void) {
term_init();
hal_init();
pmm_init();
paging_init();
dlmalloc_check();
kprintf(BANNER_TEXT "\n");

10
kernel/paging/paging.h Normal file
View File

@ -0,0 +1,10 @@
#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

@ -0,0 +1,124 @@
#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

@ -5,8 +5,7 @@
#include "bitmap/bitmap.h"
#include "bootinfo/bootinfo.h"
#include "spinlock/spinlock.h"
#define _DIV_ROUNDUP(num, div) ((num + div - 1) / div)
#include "util/util.h"
PhysMem PHYS_MEM;
@ -31,7 +30,7 @@ void pmm_init(void) {
}
if (!memmap_ent) {
ERR("hal/pmm", "required memory: {%lx}\n", bm->nbytes);
ERR("pmm", "required memory: {%lx}\n", bm->nbytes);
hal_hang();
}
@ -48,7 +47,7 @@ void pmm_init(void) {
bitmap_markregion(bm, (void *)physbegin, bm->nbytes, 1);
bm->alloc_blocks = 0;
LOG("hal/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;
}
@ -58,7 +57,7 @@ void *pmm_alloc(size_t pages) {
spinlock_release(&PHYS_MEM.spinlock);
if (!phys) {
ERR("hal/pmm", "phys memory ran out\n");
ERR("pmm", "phys memory ran out\n");
hal_hang();
}
return (void *)phys;

7
kernel/util/util.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef UTIL_UTIL_H_
#define UTIL_UTIL_H_
#define _DIV_ROUNDUP(num, div) ((num + div - 1) / div)
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif // UTIL_UTIL_H_

52
kernel/vmm/vmm.c Normal file
View File

@ -0,0 +1,52 @@
#include <stddef.h>
#include <stdint.h>
#include "bitmap/bitmap.h"
#include "spinlock/spinlock.h"
#include "bootinfo/bootinfo.h"
#include "vmm.h"
#include "kprintf.h"
#include "util/util.h"
#include "hal/hal.h"
#include "pmm/pmm.h"
#include "paging/paging.h"
#define POS_ENSURE 0x40000000
#define PAGE_SIZE 0x1000
VirtMem VIRT_MEM;
void vmm_init(void) {
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;
bm->init = false;
bm->mem_start = targetpos;
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);
}

19
kernel/vmm/vmm.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef VMM_VMM_H_
#define VMM_VMM_H_
#include <stddef.h>
#include "bitmap/bitmap.h"
#include "spinlock/spinlock.h"
typedef struct {
SpinLock spinlock;
BitMap self;
} VirtMem;
extern VirtMem VIRT_MEM;
void vmm_init(void);
void *vmm_alloc(size_t pages);
void vmm_free(void *ptr, size_t pages);
#endif // VMM_VMM_H_