looping kalloc can allocate all of memory (sometimes) :3

This commit is contained in:
Freya Murphy 2024-02-02 10:10:24 -05:00
parent c8c8d009f6
commit 1d794d87f4
Signed by: freya
GPG key ID: 744AB800E383AE52
8 changed files with 147 additions and 105 deletions

View file

@ -1,62 +1,59 @@
SRC_DIR=src KERNEL=kernel.bin
INCLUDE_DIR=include ISO=os_image.iso
BUILD_DIR=build
K_BIN_NAME=kernel.bin
ISO_NAME=os_image.iso
ARCH=amd64
CC=cc CC=cc
LD=ld LD=ld
AS=nasm AS=nasm
CFLAGS+=-std=c2x -ffreestanding -fno-stack-protector -g -Wall -Wextra -pedantic -lgcc -isystem $(INCLUDE_DIR) CFLAGS += -std=c2x -ffreestanding -fno-stack-protector -g -Wall -Wextra -pedantic -lgcc -isystem include
CFLAGS += -DPAGE_SIZE=4096 CFLAGS += -DPAGE_SIZE=4096
LDFLAGS+=-nmagic LDFLAGS += -nmagic -nostdlib
C_SRC=$(shell find $(SRC_DIR) -type f -name "*.c") H_SRC = $(shell find src include -type f -name "*.h")
C_OBJ=$(patsubst %.c,$(BUILD_DIR)/%.o,$(C_SRC))
H_SRC=$(shell find $(SRC_DIR) -type f -name "*.h") C_SRC = $(shell find src -type f -name "*.c")
H_INCLUDE=$(shell find $(INCLUDE_DIR) -type f -name "*.h") C_OBJ = $(patsubst %.c,build/%.o,$(C_SRC))
A_SRC=$(shell find $(SRC_DIR) -type f -name "*.S") A_SRC = $(shell find src -type f -name "*.S" -not -path "src/arch/*")
A_OBJ=$(patsubst %.S,$(BUILD_DIR)/%.S.o,$(A_SRC)) A_SRC += $(shell find src/arch/$(ARCH) -type f -name "*.S")
A_OBJ = $(patsubst %.S,build/%.S.o,$(A_SRC))
.PHONY: all clean .PHONY: all clean
all: $(BUILD_DIR)/$(ISO_NAME) all: build/$(ISO)
clean: clean:
@printf "\033[31m RM \033[0m%s\n" $(BUILD_DIR) @printf "\033[31m RM \033[0m%s\n" build
@rm -rf $(BUILD_DIR)/* @rm -rf build/*
$(A_OBJ): $(BUILD_DIR)/%.S.o : %.S $(A_OBJ): build/%.S.o : %.S
@mkdir -p $(@D) @mkdir -p $(@D)
@printf "\033[33m AS \033[0m%s\n" $< @printf "\033[33m AS \033[0m%s\n" $<
@nasm $< -f elf64 -o $@ @nasm $< -f elf64 -o $@
$(C_OBJ): $(BUILD_DIR)/%.o : %.c $(C_OBJ): build/%.o : %.c
@mkdir -p $(@D) @mkdir -p $(@D)
@printf "\033[34m CC \033[0m%s\n" $< @printf "\033[34m CC \033[0m%s\n" $<
@$(CC) -c $(CFLAGS) -o $@ $< @$(CC) -c $(CFLAGS) -o $@ $<
$(BUILD_DIR)/$(K_BIN_NAME): arch/amd64/linker.ld $(A_OBJ) $(C_OBJ) $(H_SRC) $(H_INCLUDE) build/$(KERNEL): arch/$(ARCH)/linker.ld $(A_OBJ) $(C_OBJ) $(H_SRC)
@mkdir -p $(@D) @mkdir -p $(@D)
@printf "\033[32m LD \033[0m%s\n" $@ @printf "\033[32m LD \033[0m%s\n" $@
@$(LD) $(LDFLAGS) --no-warn-rwx-segments -T arch/amd64/linker.ld -o $(BUILD_DIR)/$(K_BIN_NAME) $(A_OBJ) $(C_OBJ) @$(LD) $(LDFLAGS) --no-warn-rwx-segments -T arch/$(ARCH)/linker.ld -o build/$(KERNEL) $(A_OBJ) $(C_OBJ)
$(BUILD_DIR)/$(ISO_NAME): $(BUILD_DIR)/$(K_BIN_NAME) grub.cfg build/$(ISO): build/$(KERNEL) grub.cfg
@mkdir -p $(@D) @mkdir -p $(@D)
@mkdir -p $(BUILD_DIR)/iso/boot/grub @mkdir -p build/iso/boot/grub
@cp grub.cfg $(BUILD_DIR)/iso/boot/grub @cp grub.cfg build/iso/boot/grub
@cp $(BUILD_DIR)/$(K_BIN_NAME) $(BUILD_DIR)/iso/boot @cp build/$(KERNEL) build/iso/boot
@printf "\033[35m ISO \033[0m%s\n" $(BUILD_DIR)/$(ISO_NAME) @printf "\033[35m ISO \033[0m%s\n" build/$(ISO)
@grub-mkrescue -o $(BUILD_DIR)/$(ISO_NAME) $(BUILD_DIR)/iso 2> /dev/null @grub-mkrescue -o build/$(ISO) build/iso 2> /dev/null
run: all run: all
@qemu-system-x86_64 \ @qemu-system-x86_64 \
-cdrom $(BUILD_DIR)/$(ISO_NAME) \ -cdrom build/$(ISO) \
-serial stdio \ -serial stdio \
-display gtk,show-menubar=off,zoom-to-fit=on \ -display gtk,show-menubar=off,zoom-to-fit=on \
-m 1G \ -m 1G \

View file

@ -31,6 +31,7 @@ SECTIONS {
.bss BLOCK(4K) : ALIGN(4K) .bss BLOCK(4K) : ALIGN(4K)
{ {
*(COMMON)
*(.bss) *(.bss)
} }

View file

@ -103,7 +103,7 @@ static void load_pd(void *phys) {
return; return;
pt->address = (uint64_t)phys >> 12; pt->address = (uint64_t)phys >> 12;
pt->flags = F_PRESENT | F_WRITEABLE; pt->flags = F_PRESENT | F_WRITEABLE;
invlpg(pdpt_mapped); invlpg(pd_mapped);
} }
static void load_pt(void *phys) { static void load_pt(void *phys) {
@ -456,10 +456,14 @@ static int map_pages(
page->address = (uint64_t)phys >> 12; page->address = (uint64_t)phys >> 12;
page->flags = F_PRESENT | flags; page->flags = F_PRESENT | flags;
if (flags & F_GLOBAL)
invlpg(virt); invlpg(virt);
} }
__asm volatile("mov %cr3, %rax; mov %rax, %cr3;");
return 0; return 0;
failed: failed:

View file

@ -8,8 +8,8 @@
void kmain(struct boot_info *info) { void kmain(struct boot_info *info) {
memory_init(&info->map); memory_init(&info->map);
//acpi_init(info->acpi_table);
//fb_init(1024, 768); //fb_init(1024, 768);
//acpi_init(info->acpi_table);
kprintf("enterd kmain\n"); kprintf("enterd kmain\n");
@ -17,7 +17,7 @@ void kmain(struct boot_info *info) {
*(char *)(0xB8000 + 0x146) = 'i'; *(char *)(0xB8000 + 0x146) = 'i';
while (1) { while (1) {
//kprintf("ret: 0x%p\n", kalloc(1024)); __asm__("hlt;");
// loop so we dont halt // loop so we dont halt
// this allows interrupts to fire // this allows interrupts to fire
} }

View file

@ -31,7 +31,6 @@ void *memmove(void *dest, const void *src, unsigned long n) {
} }
void *memset(void *restrict dest, int c, unsigned long n) { void *memset(void *restrict dest, int c, unsigned long n) {
unsigned char *d = dest; unsigned char *d = dest;
for (; n; n--) *d++ = c; for (; n; n--) *d++ = c;
return dest; return dest;

View file

@ -1,4 +1,3 @@
#include "serial.h"
#include <memory.h> #include <memory.h>
#include <stdint.h> #include <stdint.h>
#include <lib.h> #include <lib.h>
@ -52,6 +51,7 @@ void *kalloc_new(size_t size) {
node = 0; node = 0;
} }
memset(addr, 0, pages * PAGE_SIZE);
struct page_header *header = addr; struct page_header *header = addr;
header->magic = 0xBEEFCAFE; header->magic = 0xBEEFCAFE;
header->used = size; header->used = size;
@ -66,6 +66,8 @@ void *kalloc_new(size_t size) {
if (end_header != NULL) { if (end_header != NULL) {
end_header->next = header; end_header->next = header;
} else {
end_header = header;
} }
return mem; return mem;
@ -146,7 +148,12 @@ void *krealloc(void *src, size_t dst_len) {
return NULL; // allocation failed return NULL; // allocation failed
} }
if (dst_len < src_len)
src_len = dst_len;
memcpy(dst, src, src_len); memcpy(dst, src, src_len);
kfree(src);
return dst; return dst;
} }
@ -159,7 +166,7 @@ void kfree(void *ptr) {
header = get_header(ptr); header = get_header(ptr);
if (header == NULL || header->used == 0) { if (header == NULL) {
panic("attempted to kfree invalid pointer"); panic("attempted to kfree invalid pointer");
} }

View file

@ -1,4 +1,3 @@
#include "serial.h"
#include <memory.h> #include <memory.h>
#include <stdint.h> #include <stdint.h>
#include <lib.h> #include <lib.h>
@ -15,8 +14,6 @@ extern char kernel_end;
// between memory_start and kernel_start will be the bitmap // between memory_start and kernel_start will be the bitmap
static uintptr_t memory_start = 0; static uintptr_t memory_start = 0;
typedef unsigned char page[4096];
struct memory_area { struct memory_area {
uint64_t len; uint64_t len;
uintptr_t addr; uintptr_t addr;
@ -26,9 +23,8 @@ static uint64_t *bitmap;
static uint64_t total_memory; static uint64_t total_memory;
static uint64_t free_memory; static uint64_t free_memory;
static uint64_t page_count; static uint64_t page_count;
static uint64_t page_free_start;
static uint64_t segment_count; static uint64_t segment_count;
static struct memory_area *page_start; struct memory_area *page_start;
static int n_pages(const struct memory_area *m) { static int n_pages(const struct memory_area *m) {
return m->len / PAGE_SIZE; return m->len / PAGE_SIZE;
@ -37,7 +33,7 @@ static int n_pages(const struct memory_area *m) {
static void *page_at(int i) { static void *page_at(int i) {
int cur_page = 0; int cur_page = 0;
for (uint64_t idx = 0; idx < segment_count; idx++) { for (uint64_t idx = 0; idx < segment_count; idx++) {
struct memory_area *m = &page_start[idx]; const struct memory_area *m = page_start;
int pages = n_pages(m); int pages = n_pages(m);
if (i - cur_page < pages) { if (i - cur_page < pages) {
return (void *) (m->addr + (PAGE_SIZE * (i - cur_page))); return (void *) (m->addr + (PAGE_SIZE * (i - cur_page)));
@ -47,10 +43,11 @@ static void *page_at(int i) {
return NULL; return NULL;
} }
static long page_idx(page p) { static long page_idx(void *page) {
uintptr_t addr = (uintptr_t) p; uintptr_t addr = (uintptr_t) page;
int cur_page = 0; int cur_page = 0;
for (struct memory_area *m = page_start; m != NULL; m++) { for (uint64_t idx = 0; idx < segment_count; idx++) {
const struct memory_area *m = page_start;
if ((uintptr_t) m + m->len > addr) { if ((uintptr_t) m + m->len > addr) {
return cur_page + ((addr - m->addr) / PAGE_SIZE); return cur_page + ((addr - m->addr) / PAGE_SIZE);
} }
@ -82,15 +79,9 @@ void *alloc_phys_pages(int pages) {
int n_contiguous = 0; int n_contiguous = 0;
int free_region_start = 0; int free_region_start = 0;
bool first = true; for (uint64_t i = 0; i < page_count; i++) {
for (uint64_t i = page_free_start; i < page_count; i++) {
bool free = !bitmap_get(i); bool free = !bitmap_get(i);
if (first) {
first = false;
page_free_start = i;
}
if (free) { if (free) {
if (n_contiguous == 0) free_region_start = i; if (n_contiguous == 0) free_region_start = i;
n_contiguous++; n_contiguous++;
@ -113,8 +104,6 @@ void free_phys_pages(void *ptr, int pages) {
long idx = page_idx(ptr); long idx = page_idx(ptr);
if (idx == -1) return; if (idx == -1) return;
if ((unsigned) idx < page_free_start) page_free_start = idx;
for (int i = 0; i < pages; i++) for (int i = 0; i < pages; i++)
bitmap_set(idx + pages, false); bitmap_set(idx + pages, false);
} }
@ -165,7 +154,6 @@ void memory_init(struct memory_map *map) {
total_memory = 0; total_memory = 0;
free_memory = 0; free_memory = 0;
page_count = 0; page_count = 0;
page_free_start = 0;
page_start = NULL; page_start = NULL;
segment_count = 0; segment_count = 0;
@ -181,21 +169,21 @@ void memory_init(struct memory_map *map) {
segment_count++; segment_count++;
} }
long bitmap_pages = page_count / 64 / PAGE_SIZE + 1; long bitmap_pages = (page_count / 64 / PAGE_SIZE) + 1;
free_memory = page_count * PAGE_SIZE;
//HACK: terrible hack bad bad bad bad
long bitmap_size = bitmap_pages * PAGE_SIZE; long bitmap_size = bitmap_pages * PAGE_SIZE;
bitmap = (uint64_t *) page_align(kaddr(kernel_end)); bitmap = (uint64_t *) page_align(kaddr(kernel_end));
long page_area_size = segment_count * sizeof(struct memory_area); long page_area_size = segment_count * sizeof(struct memory_area);
char *page_area_addr = (char *)bitmap + bitmap_size; char *page_area_addr = (char *)bitmap + bitmap_size;
page_area_addr = (char *) page_align((uintptr_t) page_area_addr);
memory_start = page_align((uintptr_t)page_area_addr + page_area_size);
bitmap = mmap(bitmap, bitmap_size); bitmap = mmap(bitmap, bitmap_size);
memset(bitmap, 0, bitmap_size); memset(bitmap, 0, bitmap_size);
memory_start = page_align(kaddr(kernel_end) + bitmap_size + page_area_size);
page_area_addr = mmap(page_area_addr, page_area_size); page_area_addr = mmap(page_area_addr, page_area_size);
memset(page_area_addr, 0, page_area_size);
page_start = (struct memory_area *) page_area_addr; page_start = (struct memory_area *) page_area_addr;
struct memory_area *area = page_start; struct memory_area *area = page_start;

View file

@ -35,6 +35,32 @@ static struct addr_node *get_node_idx(int idx) {
} }
} }
static void update_node_ptrs(
struct addr_node *old,
struct addr_node *new,
int old_len,
int new_len
) {
if (old == NULL)
return;
int idx = 0;
for (int i = 0; i < old_len; i++) {
struct addr_node *o = &old[i];
if (o && !o->is_used)
continue;
struct addr_node *n = &new[idx++];
*n = *o;
if (n->prev != NULL)
n->prev->next = n;
if (n->next != NULL)
n->next->prev = n;
}
for (int i = idx; i < new_len; i++) {
struct addr_node *n = &new[idx++];
n->is_used = false;
}
}
static struct addr_node *get_node(void) { static struct addr_node *get_node(void) {
size_t count = BSS_NODES + alloc_node_count; size_t count = BSS_NODES + alloc_node_count;
@ -43,10 +69,13 @@ static struct addr_node *get_node(void) {
int new_alloc = alloc_node_count * 2; int new_alloc = alloc_node_count * 2;
if (new_alloc < 8) if (new_alloc < 8)
new_alloc = 8; new_alloc = 8;
int allocated = new_alloc - alloc_node_count; struct addr_node *new_nodes;
int old = new_alloc - allocated; new_nodes = kalloc(sizeof(struct addr_node) * new_alloc);
alloc_nodes = krealloc(alloc_nodes, sizeof(struct addr_node) * new_alloc); if (new_nodes == NULL)
memset(alloc_nodes + old, 0, sizeof(struct addr_node) + allocated);; panic("virt addr alloc nodes is null");
update_node_ptrs(alloc_nodes, new_nodes, alloc_node_count, new_alloc);
kfree(alloc_nodes);
alloc_nodes = new_nodes;
alloc_node_count = new_alloc; alloc_node_count = new_alloc;
is_allocating = false; is_allocating = false;
count = BSS_NODES + alloc_node_count; count = BSS_NODES + alloc_node_count;
@ -83,45 +112,15 @@ void virtaddr_init(void) {
start_node = &bootstrap_nodes[0]; start_node = &bootstrap_nodes[0];
} }
void *virtaddr_alloc(int n_pages) {
if (n_pages < 1)
return NULL;
long n_length = n_pages * PAGE_SIZE;
struct addr_node *node = start_node;
for (; node != NULL ; node = node->next) {
if (node->is_alloc)
continue;
long length = node->end - node->start;
if (length >= n_length) {
struct addr_node *new = get_node();
if (node->prev != NULL) {
node->prev->next = new;
}
new->next = node;
node->prev = new;
new->start = node->start;
new->end = new->start + n_length;
node->start = new->end;
new->is_alloc = true;
new->is_used = true;
new->next = node;
return (void *) new->start;
}
}
return NULL;
}
static void merge_back(struct addr_node *node) { static void merge_back(struct addr_node *node) {
while (node->prev && !node->is_alloc) { while(node->prev) {
if (node->is_alloc != node->prev->is_alloc)
break;
struct addr_node *temp = node->prev; struct addr_node *temp = node->prev;
node->start = node->prev->start; node->start = temp->start;
node->prev = node->prev->prev; node->prev = temp->prev;
if (temp->prev)
temp->prev->next = node;
free_node(temp); free_node(temp);
} }
if (node->prev == NULL) { if (node->prev == NULL) {
@ -130,14 +129,61 @@ static void merge_back(struct addr_node *node) {
} }
static void merge_forward(struct addr_node *node) { static void merge_forward(struct addr_node *node) {
<<<<<<< HEAD
while (node->next && !node->is_alloc) { while (node->next && !node->is_alloc) {
=======
while(node->next) {
if (node->is_alloc != node->next->is_alloc)
break;
>>>>>>> ea2de5a (looping kalloc can allocate all of memory (sometimes) :3)
struct addr_node *temp = node->next; struct addr_node *temp = node->next;
node->end = node->next->end; node->end = temp->end;
node->next = node->next->next; node->next = temp->next;
if (temp->next)
temp->next->prev = node;
free_node(temp); free_node(temp);
} }
} }
void *virtaddr_alloc(int n_pages) {
if (n_pages < 1)
return NULL;
long n_length = n_pages * PAGE_SIZE;
struct addr_node *node = start_node;
for (; node != NULL ; node = node->next) {
long length = node->end - node->start;
if (node->is_alloc)
continue;
if (length >= n_length) {
struct addr_node *new = get_node();
if (node->prev != NULL) {
node->prev->next = new;
} else {
start_node = new;
}
new->next = node;
new->prev = node->prev;
node->prev = new;
new->start = node->start;
new->end = new->start + n_length;
node->start = new->end;
new->is_alloc = true;
new->is_used = true;
new->next = node;
return (void*)new->start;
//void *mem = (void *) new->start;
//merge_back(new);
//merge_forward(new);
//return mem;
}
}
return NULL;
}
long virtaddr_free(void *virtaddr) { long virtaddr_free(void *virtaddr) {
uintptr_t virt = (uintptr_t) virtaddr; uintptr_t virt = (uintptr_t) virtaddr;