From 1d794d87f4307f7b34f5b69d69213343aed9d137 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Fri, 2 Feb 2024 10:10:24 -0500 Subject: [PATCH] looping kalloc can allocate all of memory (sometimes) :3 --- Makefile | 55 ++++++++--------- arch/amd64/linker.ld | 1 + src/arch/amd64/paging.c | 8 ++- src/kmain.c | 4 +- src/lib.c | 1 - src/memory/memory.c | 11 +++- src/memory/physalloc.c | 40 +++++------- src/memory/virtalloc.c | 132 +++++++++++++++++++++++++++------------- 8 files changed, 147 insertions(+), 105 deletions(-) diff --git a/Makefile b/Makefile index 2e58dd1..19b2342 100644 --- a/Makefile +++ b/Makefile @@ -1,62 +1,59 @@ -SRC_DIR=src -INCLUDE_DIR=include -BUILD_DIR=build - -K_BIN_NAME=kernel.bin -ISO_NAME=os_image.iso +KERNEL=kernel.bin +ISO=os_image.iso +ARCH=amd64 CC=cc LD=ld AS=nasm -CFLAGS+=-std=c2x -ffreestanding -fno-stack-protector -g -Wall -Wextra -pedantic -lgcc -isystem $(INCLUDE_DIR) -CFLAGS+=-DPAGE_SIZE=4096 +CFLAGS += -std=c2x -ffreestanding -fno-stack-protector -g -Wall -Wextra -pedantic -lgcc -isystem include +CFLAGS += -DPAGE_SIZE=4096 -LDFLAGS+=-nmagic +LDFLAGS += -nmagic -nostdlib -C_SRC=$(shell find $(SRC_DIR) -type f -name "*.c") -C_OBJ=$(patsubst %.c,$(BUILD_DIR)/%.o,$(C_SRC)) +H_SRC = $(shell find src include -type f -name "*.h") -H_SRC=$(shell find $(SRC_DIR) -type f -name "*.h") -H_INCLUDE=$(shell find $(INCLUDE_DIR) -type f -name "*.h") +C_SRC = $(shell find src -type f -name "*.c") +C_OBJ = $(patsubst %.c,build/%.o,$(C_SRC)) -A_SRC=$(shell find $(SRC_DIR) -type f -name "*.S") -A_OBJ=$(patsubst %.S,$(BUILD_DIR)/%.S.o,$(A_SRC)) +A_SRC = $(shell find src -type f -name "*.S" -not -path "src/arch/*") +A_SRC += $(shell find src/arch/$(ARCH) -type f -name "*.S") +A_OBJ = $(patsubst %.S,build/%.S.o,$(A_SRC)) .PHONY: all clean -all: $(BUILD_DIR)/$(ISO_NAME) +all: build/$(ISO) clean: - @printf "\033[31m RM \033[0m%s\n" $(BUILD_DIR) - @rm -rf $(BUILD_DIR)/* + @printf "\033[31m RM \033[0m%s\n" build + @rm -rf build/* -$(A_OBJ): $(BUILD_DIR)/%.S.o : %.S +$(A_OBJ): build/%.S.o : %.S @mkdir -p $(@D) @printf "\033[33m AS \033[0m%s\n" $< @nasm $< -f elf64 -o $@ -$(C_OBJ): $(BUILD_DIR)/%.o : %.c +$(C_OBJ): build/%.o : %.c @mkdir -p $(@D) @printf "\033[34m CC \033[0m%s\n" $< @$(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) @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 $(BUILD_DIR)/iso/boot/grub - @cp grub.cfg $(BUILD_DIR)/iso/boot/grub - @cp $(BUILD_DIR)/$(K_BIN_NAME) $(BUILD_DIR)/iso/boot - @printf "\033[35m ISO \033[0m%s\n" $(BUILD_DIR)/$(ISO_NAME) - @grub-mkrescue -o $(BUILD_DIR)/$(ISO_NAME) $(BUILD_DIR)/iso 2> /dev/null + @mkdir -p build/iso/boot/grub + @cp grub.cfg build/iso/boot/grub + @cp build/$(KERNEL) build/iso/boot + @printf "\033[35m ISO \033[0m%s\n" build/$(ISO) + @grub-mkrescue -o build/$(ISO) build/iso 2> /dev/null run: all @qemu-system-x86_64 \ - -cdrom $(BUILD_DIR)/$(ISO_NAME) \ + -cdrom build/$(ISO) \ -serial stdio \ -display gtk,show-menubar=off,zoom-to-fit=on \ -m 1G \ diff --git a/arch/amd64/linker.ld b/arch/amd64/linker.ld index 7a34a9e..797dc35 100644 --- a/arch/amd64/linker.ld +++ b/arch/amd64/linker.ld @@ -31,6 +31,7 @@ SECTIONS { .bss BLOCK(4K) : ALIGN(4K) { + *(COMMON) *(.bss) } diff --git a/src/arch/amd64/paging.c b/src/arch/amd64/paging.c index 607267e..604e0a0 100644 --- a/src/arch/amd64/paging.c +++ b/src/arch/amd64/paging.c @@ -103,7 +103,7 @@ static void load_pd(void *phys) { return; pt->address = (uint64_t)phys >> 12; pt->flags = F_PRESENT | F_WRITEABLE; - invlpg(pdpt_mapped); + invlpg(pd_mapped); } static void load_pt(void *phys) { @@ -456,10 +456,14 @@ static int map_pages( page->address = (uint64_t)phys >> 12; page->flags = F_PRESENT | flags; - invlpg(virt); + + if (flags & F_GLOBAL) + invlpg(virt); } + __asm volatile("mov %cr3, %rax; mov %rax, %cr3;"); + return 0; failed: diff --git a/src/kmain.c b/src/kmain.c index 07244bf..7501669 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -8,8 +8,8 @@ void kmain(struct boot_info *info) { memory_init(&info->map); - //acpi_init(info->acpi_table); //fb_init(1024, 768); + //acpi_init(info->acpi_table); kprintf("enterd kmain\n"); @@ -17,7 +17,7 @@ void kmain(struct boot_info *info) { *(char *)(0xB8000 + 0x146) = 'i'; while (1) { - //kprintf("ret: 0x%p\n", kalloc(1024)); + __asm__("hlt;"); // loop so we dont halt // this allows interrupts to fire } diff --git a/src/lib.c b/src/lib.c index ee4afcb..d2708c8 100644 --- a/src/lib.c +++ b/src/lib.c @@ -31,7 +31,6 @@ void *memmove(void *dest, const void *src, unsigned long n) { } void *memset(void *restrict dest, int c, unsigned long n) { - unsigned char *d = dest; for (; n; n--) *d++ = c; return dest; diff --git a/src/memory/memory.c b/src/memory/memory.c index ae26bfe..d1a163f 100644 --- a/src/memory/memory.c +++ b/src/memory/memory.c @@ -1,4 +1,3 @@ -#include "serial.h" #include #include #include @@ -52,6 +51,7 @@ void *kalloc_new(size_t size) { node = 0; } + memset(addr, 0, pages * PAGE_SIZE); struct page_header *header = addr; header->magic = 0xBEEFCAFE; header->used = size; @@ -66,6 +66,8 @@ void *kalloc_new(size_t size) { if (end_header != NULL) { end_header->next = header; + } else { + end_header = header; } return mem; @@ -146,7 +148,12 @@ void *krealloc(void *src, size_t dst_len) { return NULL; // allocation failed } + if (dst_len < src_len) + src_len = dst_len; + memcpy(dst, src, src_len); + kfree(src); + return dst; } @@ -159,7 +166,7 @@ void kfree(void *ptr) { header = get_header(ptr); - if (header == NULL || header->used == 0) { + if (header == NULL) { panic("attempted to kfree invalid pointer"); } diff --git a/src/memory/physalloc.c b/src/memory/physalloc.c index 67c99c7..b0dbdcd 100644 --- a/src/memory/physalloc.c +++ b/src/memory/physalloc.c @@ -1,4 +1,3 @@ -#include "serial.h" #include #include #include @@ -15,8 +14,6 @@ extern char kernel_end; // between memory_start and kernel_start will be the bitmap static uintptr_t memory_start = 0; -typedef unsigned char page[4096]; - struct memory_area { uint64_t len; uintptr_t addr; @@ -26,9 +23,8 @@ static uint64_t *bitmap; static uint64_t total_memory; static uint64_t free_memory; static uint64_t page_count; -static uint64_t page_free_start; 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) { return m->len / PAGE_SIZE; @@ -37,7 +33,7 @@ static int n_pages(const struct memory_area *m) { static void *page_at(int i) { int cur_page = 0; 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); if (i - cur_page < pages) { return (void *) (m->addr + (PAGE_SIZE * (i - cur_page))); @@ -47,10 +43,11 @@ static void *page_at(int i) { return NULL; } -static long page_idx(page p) { - uintptr_t addr = (uintptr_t) p; +static long page_idx(void *page) { + uintptr_t addr = (uintptr_t) page; 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) { return cur_page + ((addr - m->addr) / PAGE_SIZE); } @@ -82,15 +79,9 @@ void *alloc_phys_pages(int pages) { int n_contiguous = 0; int free_region_start = 0; - bool first = true; - for (uint64_t i = page_free_start; i < page_count; i++) { + for (uint64_t i = 0; i < page_count; i++) { bool free = !bitmap_get(i); - if (first) { - first = false; - page_free_start = i; - } - if (free) { if (n_contiguous == 0) free_region_start = i; n_contiguous++; @@ -113,8 +104,6 @@ void free_phys_pages(void *ptr, int pages) { long idx = page_idx(ptr); if (idx == -1) return; - if ((unsigned) idx < page_free_start) page_free_start = idx; - for (int i = 0; i < pages; i++) bitmap_set(idx + pages, false); } @@ -165,7 +154,6 @@ void memory_init(struct memory_map *map) { total_memory = 0; free_memory = 0; page_count = 0; - page_free_start = 0; page_start = NULL; segment_count = 0; @@ -181,21 +169,21 @@ void memory_init(struct memory_map *map) { segment_count++; } - long bitmap_pages = page_count / 64 / PAGE_SIZE + 1; - free_memory = page_count * PAGE_SIZE; - - //HACK: terrible hack bad bad bad bad + long bitmap_pages = (page_count / 64 / PAGE_SIZE) + 1; long bitmap_size = bitmap_pages * PAGE_SIZE; bitmap = (uint64_t *) page_align(kaddr(kernel_end)); long page_area_size = segment_count * sizeof(struct memory_area); 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); 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); + memset(page_area_addr, 0, page_area_size); + page_start = (struct memory_area *) page_area_addr; struct memory_area *area = page_start; diff --git a/src/memory/virtalloc.c b/src/memory/virtalloc.c index baa7892..bfeb670 100644 --- a/src/memory/virtalloc.c +++ b/src/memory/virtalloc.c @@ -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) { 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; if (new_alloc < 8) new_alloc = 8; - int allocated = new_alloc - alloc_node_count; - int old = new_alloc - allocated; - alloc_nodes = krealloc(alloc_nodes, sizeof(struct addr_node) * new_alloc); - memset(alloc_nodes + old, 0, sizeof(struct addr_node) + allocated);; + struct addr_node *new_nodes; + new_nodes = kalloc(sizeof(struct addr_node) * new_alloc); + if (new_nodes == NULL) + 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; is_allocating = false; count = BSS_NODES + alloc_node_count; @@ -83,45 +112,15 @@ void virtaddr_init(void) { 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) { - while (node->prev && !node->is_alloc) { + while(node->prev) { + if (node->is_alloc != node->prev->is_alloc) + break; struct addr_node *temp = node->prev; - node->start = node->prev->start; - node->prev = node->prev->prev; + node->start = temp->start; + node->prev = temp->prev; + if (temp->prev) + temp->prev->next = node; free_node(temp); } if (node->prev == NULL) { @@ -130,14 +129,61 @@ static void merge_back(struct addr_node *node) { } static void merge_forward(struct addr_node *node) { +<<<<<<< HEAD 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; - node->end = node->next->end; - node->next = node->next->next; + node->end = temp->end; + node->next = temp->next; + if (temp->next) + temp->next->prev = node; 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) { uintptr_t virt = (uintptr_t) virtaddr;