summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-12-09 18:35:54 +0100
committerAnton Kling <anton@kling.gg>2024-12-09 19:17:57 +0100
commite7272b29feb855f4678c5c510d331f297351d3a2 (patch)
treea1961628a7466af9320f14827cb528ac688ddb76 /kernel
parent906923ad3f2ecb2c73d286924e2ac05f8f3ae502 (diff)
mmu: Make certain allocations physical and virtual mapping linear
Previously it was possible for fragmentation to occur and as a result certain allocations would have a linear virtual address space but not a linear physical address space. This is bad since a lot of calls to kmalloc_align rely upon both being linear, it has now been changed such that all allocations done by kmalloc_align now guarantee this mapping holds for both virtual and physical addresses. It was due to oversight and sheer luck that this had been working for so long.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/arch/i386/mmu.c72
-rw-r--r--kernel/drivers/ahci.c6
-rw-r--r--kernel/fs/ext2.c3
-rw-r--r--kernel/includes/mmu.h3
-rw-r--r--kernel/kmalloc.c5
-rw-r--r--kernel/ksbrk.c40
-rw-r--r--kernel/ksbrk.h8
8 files changed, 67 insertions, 72 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index 164b41c..7fd8310 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -1,6 +1,6 @@
CC="i686-sb-gcc"
AS="i686-sb-as"
-OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o kubsan.o drivers/serial.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o elf.o ksbrk.o sched/scheduler.o libc/string/copy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o signal.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o lib/ringbuffer.o lib/relist.o arch/i386/tsc.o arch/i386/asm_tsc.o drivers/cmos.o timer.o queue.o fonts.o drivers/ac97.o audio.o libc/ctype/isdigit.o
+OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o kubsan.o drivers/serial.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o elf.o sched/scheduler.o libc/string/copy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o signal.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o lib/ringbuffer.o lib/relist.o arch/i386/tsc.o arch/i386/asm_tsc.o drivers/cmos.o timer.o queue.o fonts.o drivers/ac97.o audio.o libc/ctype/isdigit.o
CFLAGS = -std=c99 -O0 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Wextra -Wno-int-conversion -Wno-unused-parameter -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
LDFLAGS=
#CFLAGS = -std=c99 -O3 -flto -ggdb -ffreestanding -Wall -Wextra -Wno-int-conversion -Wno-unused-parameter -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
diff --git a/kernel/arch/i386/mmu.c b/kernel/arch/i386/mmu.c
index 1e00f17..d46b077 100644
--- a/kernel/arch/i386/mmu.c
+++ b/kernel/arch/i386/mmu.c
@@ -1,6 +1,5 @@
#include <assert.h>
#include <cpu/arch_inst.h>
-#include <ksbrk.h>
#include <log.h>
#include <math.h>
#include <mmu.h>
@@ -26,8 +25,9 @@ u32 *tmp_small_frames = tmp_array;
extern uintptr_t data_end;
void change_frame(u32 frame, int on);
-int get_free_frame(u32 *frame);
+int get_free_frames(u32 *frame, size_t num_frames);
int allocate_frame(Page *page, int rw, int is_kernel);
+int mmu_allocate_kernel_linear_virtual_to_physical_mapping(void *rc, size_t n);
static int create_kernel_table(int table_index) {
u32 physical;
@@ -53,7 +53,7 @@ static int create_kernel_table(int table_index) {
return 1;
}
-void *ksbrk(size_t s) {
+void *ksbrk(size_t s, int enforce_linear) {
uintptr_t rc = (uintptr_t)align_page((void *)data_end);
data_end += s;
data_end = (uintptr_t)align_page((void *)data_end);
@@ -70,11 +70,18 @@ void *ksbrk(size_t s) {
if (!create_kernel_table(table_index)) {
return NULL;
}
- return ksbrk(s);
+ return ksbrk(s, enforce_linear);
}
- if (!mmu_allocate_shared_kernel_region((void *)rc,
- (data_end - (uintptr_t)rc))) {
- return NULL;
+ if (enforce_linear) {
+ if (!mmu_allocate_kernel_linear_virtual_to_physical_mapping(
+ (void *)rc, (data_end - (uintptr_t)rc))) {
+ return NULL;
+ }
+ } else {
+ if (!mmu_allocate_shared_kernel_region((void *)rc,
+ (data_end - (uintptr_t)rc))) {
+ return NULL;
+ }
}
get_fast_insecure_random(rc, s);
assert(((uintptr_t)rc % PAGE_SIZE) == 0);
@@ -82,7 +89,7 @@ void *ksbrk(size_t s) {
}
void *ksbrk_physical(size_t s, void **physical) {
- void *r = ksbrk(s);
+ void *r = ksbrk(s, 1);
if (!r) {
return NULL;
}
@@ -147,7 +154,8 @@ void mmu_free_pages(void *a, u32 n) {
}
u32 start_frame_search = 1;
-int get_free_frame(u32 *frame) {
+int get_free_frames(u32 *frame, size_t num_frames) {
+ size_t counter = num_frames;
u32 i = start_frame_search;
for (; i < INDEX_FROM_BIT(num_array_frames * 32); i++) {
if (tmp_small_frames[i] == 0xFFFFFFFF) {
@@ -155,9 +163,15 @@ int get_free_frame(u32 *frame) {
}
for (u32 c = 0; c < 32; c++) {
- if (!(tmp_small_frames[i] & ((u32)1 << c))) {
- start_frame_search = i;
- *frame = i * 32 + c;
+ if ((tmp_small_frames[i] & ((u32)1 << c))) {
+ counter = num_frames;
+ continue;
+ }
+ start_frame_search = min(start_frame_search, i);
+
+ counter--;
+ if (0 == counter) {
+ *frame = i * 32 + c - (num_frames - 1);
return 1;
}
}
@@ -211,7 +225,7 @@ PageTable *clone_table(u32 src_index, PageDirectory *src_directory,
continue;
}
u32 frame_address;
- if (!get_free_frame(&frame_address)) {
+ if (!get_free_frames(&frame_address, 1)) {
kmalloc_align_free(new_table, sizeof(PageTable));
return NULL;
}
@@ -277,6 +291,9 @@ PageDirectory *clone_directory(PageDirectory *original) {
}
u32 offset = (u32)new_directory->physical_tables - (u32)new_directory;
new_directory->physical_address = physical_address + offset;
+ assert(
+ new_directory->physical_address ==
+ (uintptr_t)virtual_to_physical((uintptr_t)new_directory + offset, NULL));
for (int i = 0; i < 1024; i++) {
if (!original->tables[i] && !kernel_directory->tables[i]) {
@@ -320,6 +337,33 @@ PageDirectory *clone_directory(PageDirectory *original) {
return new_directory;
}
+int mmu_allocate_kernel_linear_virtual_to_physical_mapping(void *rc, size_t n) {
+ size_t num_pages = align_page(n) / PAGE_SIZE;
+
+ u32 start_frame;
+ if (!get_free_frames(&start_frame, num_pages)) {
+ goto mmu_allocate_shared_kernel_region_error;
+ }
+
+ for (size_t i = 0; i < num_pages; i++) {
+ Page *p = get_page((void *)(rc + i * 0x1000), NULL, PAGE_ALLOCATE, 0);
+ if (!p) {
+ goto mmu_allocate_shared_kernel_region_error;
+ }
+ assert(!p->present);
+ p->present = 1;
+ p->rw = 1;
+ p->user = 0;
+ p->frame = start_frame + i;
+ assert(write_to_frame(p->frame * 0x1000, 1));
+ }
+ flush_tlb();
+ return 1;
+mmu_allocate_shared_kernel_region_error:
+ mmu_free_address_range(rc, n, NULL);
+ return 0;
+}
+
int mmu_allocate_shared_kernel_region(void *rc, size_t n) {
size_t num_pages = n / PAGE_SIZE;
for (size_t i = 0; i <= num_pages; i++) {
@@ -436,7 +480,7 @@ int allocate_frame(Page *page, int rw, int is_kernel) {
return 0;
}
u32 frame_address;
- if (!get_free_frame(&frame_address)) {
+ if (!get_free_frames(&frame_address, 1)) {
return 0;
}
assert(write_to_frame(frame_address * 0x1000, 1));
diff --git a/kernel/drivers/ahci.c b/kernel/drivers/ahci.c
index 1f3dcf4..9018df1 100644
--- a/kernel/drivers/ahci.c
+++ b/kernel/drivers/ahci.c
@@ -267,9 +267,9 @@ void ahci_sata_setup(volatile struct HBA_PORT *port) {
// clb_address: size has to be 1024 and byte aligned to 1024
// fb_address: size has to be 256 and byte aligned to 256
// command_table_array: size has to be 256*32
- u32 clb_address = (u32)ksbrk(1024);
- u32 fb_address = (u32)ksbrk(256);
- u32 command_table_array = (u32)ksbrk(256 * 32);
+ u32 clb_address = (u32)kmalloc_align(1024, 0);
+ u32 fb_address = (u32)kmalloc_align(256, 0);
+ u32 command_table_array = (u32)kmalloc_align(256 * 32, 0);
create_physical_to_virtual_mapping(
virtual_to_physical((void *)clb_address, NULL), (void *)clb_address,
1024);
diff --git a/kernel/fs/ext2.c b/kernel/fs/ext2.c
index 948b0af..fe09834 100644
--- a/kernel/fs/ext2.c
+++ b/kernel/fs/ext2.c
@@ -382,7 +382,6 @@ int get_free_blocks(int allocate, int entries[], u32 num_entries) {
u32 current_entry = 0;
bgdt_t block_group;
if (num_entries > superblock->num_blocks_unallocated) {
- kprintf("greater than\n");
return 0;
}
assert(0 == superblock->num_blocks_in_group % 8);
@@ -975,7 +974,7 @@ ext2_mount_error:
}
void parse_superblock(void) {
- superblock = ksbrk(2 * SECTOR_SIZE);
+ superblock = kmalloc(2 * SECTOR_SIZE);
raw_vfs_pread(mount_fd, superblock, 2 * SECTOR_SIZE,
EXT2_SUPERBLOCK_SECTOR * SECTOR_SIZE);
diff --git a/kernel/includes/mmu.h b/kernel/includes/mmu.h
index 319169f..580b40e 100644
--- a/kernel/includes/mmu.h
+++ b/kernel/includes/mmu.h
@@ -42,6 +42,7 @@ int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags,
PageDirectory *pd);
void mmu_free_pagedirectory(PageDirectory *pd);
int mmu_allocate_shared_kernel_region(void *rc, size_t n);
+int mmu_allocate_kernel_linear_virtual_to_physical_mapping(void *rc, size_t n);
void *mmu_find_unallocated_virtual_range(void *addr, size_t length);
void mmu_remove_virtual_physical_address_mapping(void *ptr, size_t length);
void mmu_free_address_range(void *ptr, size_t length, PageDirectory *pd);
@@ -60,7 +61,7 @@ PageDirectory *get_active_pagedirectory(void);
void switch_page_directory(PageDirectory *directory);
PageDirectory *clone_directory(PageDirectory *original);
void *virtual_to_physical(void *address, PageDirectory *directory);
-void *ksbrk(size_t s);
+void *ksbrk(size_t s, int enforce_linear);
void *ksbrk_physical(size_t s, void **physical);
int write_to_frame(u32 frame_address, u8 on);
diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c
index bea9431..e5c95af 100644
--- a/kernel/kmalloc.c
+++ b/kernel/kmalloc.c
@@ -1,7 +1,6 @@
#include <assert.h>
#include <interrupts.h>
#include <kmalloc.h>
-#include <ksbrk.h>
#include <log.h>
#include <math.h>
#include <mmu.h>
@@ -62,7 +61,7 @@ MallocHeader *final = NULL;
u32 total_heap_size = 0;
int init_heap(void) {
- head = (MallocHeader *)ksbrk(NEW_ALLOC_SIZE);
+ head = (MallocHeader *)ksbrk(NEW_ALLOC_SIZE, 0);
if (!head) {
return 0;
}
@@ -80,7 +79,7 @@ int add_heap_memory(size_t min_desired) {
size_t allocation_size = max(min_desired, NEW_ALLOC_SIZE);
allocation_size += delta_page(allocation_size);
void *p;
- if (!(p = (void *)ksbrk(allocation_size))) {
+ if (!(p = (void *)ksbrk(allocation_size, 0))) {
return 0;
}
total_heap_size += allocation_size - sizeof(MallocHeader);
diff --git a/kernel/ksbrk.c b/kernel/ksbrk.c
deleted file mode 100644
index 82fc5ed..0000000
--- a/kernel/ksbrk.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <assert.h>
-#include <ksbrk.h>
-#include <mmu.h>
-#include <stddef.h>
-#include <typedefs.h>
-
-/*
-extern uintptr_t data_end;
-extern PageDirectory *kernel_directory;
-
-#define HEAP 0x00E00000
-#define PHYS 0x403000
-#define PAGE_SIZE ((uintptr_t)0x1000)
-void *ksbrk(size_t s) {
- uintptr_t rc = (uintptr_t)align_page((void *)data_end);
- data_end += s;
- data_end = (uintptr_t)align_page((void *)data_end);
-
- if (!get_active_pagedirectory()) {
- // If there is no active pagedirectory we
- // just assume that the memory is
- // already mapped.
- return (void *)rc;
- }
- mmu_allocate_shared_kernel_region((void *)rc, (data_end - (uintptr_t)rc));
- assert(((uintptr_t)rc % PAGE_SIZE) == 0);
- memset((void *)rc, 0xFF, s);
- return (void *)rc;
-}
-
-void *ksbrk_physical(size_t s, void **physical) {
- void *r = ksbrk(s);
- if (physical) {
- // if (0 == get_active_pagedirectory())
- // *physical = (void *)((uintptr_t)r - (0xC0000000 + PHYS) + HEAP);
- // else
- *physical = (void *)virtual_to_physical(r, 0);
- }
- return r;
-}*/
diff --git a/kernel/ksbrk.h b/kernel/ksbrk.h
deleted file mode 100644
index fba060e..0000000
--- a/kernel/ksbrk.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef KSBRK_H
-#define KSBRK_H
-#include <stddef.h>
-#include <typedefs.h>
-
-void *ksbrk(size_t s);
-void *ksbrk_physical(size_t s, void **physical);
-#endif