summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-04-12 14:03:29 +0200
committerAnton Kling <anton@kling.gg>2024-04-12 14:13:08 +0200
commitb450065984b1588966694579230dc40c802212e7 (patch)
treee67a056b1f3d0d2fa9a8f07fd76f925080dfbf44 /kernel
parentca082f686fd2dc7ee6f0284421f6212d6d4acee8 (diff)
Kernel/MMU: Dellocate pagedirectory when process exits.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/arch/i386/mmu.c41
-rw-r--r--kernel/includes/mmu.h4
-rw-r--r--kernel/kmalloc.c24
-rw-r--r--kernel/kmalloc.h4
-rw-r--r--kernel/sched/scheduler.c6
5 files changed, 67 insertions, 12 deletions
diff --git a/kernel/arch/i386/mmu.c b/kernel/arch/i386/mmu.c
index 53b2156..2c05fb6 100644
--- a/kernel/arch/i386/mmu.c
+++ b/kernel/arch/i386/mmu.c
@@ -9,9 +9,6 @@
#define INDEX_FROM_BIT(a) (a / (32))
#define OFFSET_FROM_BIT(a) (a % (32))
-#define PAGE_ALLOCATE 1
-#define PAGE_NO_ALLOCATE 0
-
PageDirectory *kernel_directory;
PageDirectory real_kernel_directory;
PageDirectory *active_directory = 0;
@@ -92,7 +89,7 @@ Page *get_page(void *ptr, PageDirectory *directory, int create_new_page,
u32 physical;
directory->tables[table_index] =
- (PageTable *)ksbrk_physical(sizeof(PageTable), (void **)&physical);
+ (PageTable *)kmalloc_align(sizeof(PageTable), (void **)&physical);
memset(directory->tables[table_index], 0, sizeof(PageTable));
directory->physical_tables[table_index] =
(u32)physical | ((set_user) ? 0x7 : 0x3);
@@ -157,7 +154,7 @@ PageDirectory *get_active_pagedirectory(void) {
PageTable *clone_table(u32 src_index, PageDirectory *src_directory,
u32 *physical_address) {
PageTable *new_table =
- ksbrk_physical(sizeof(PageTable), (void **)physical_address);
+ kmalloc_align(sizeof(PageTable), (void **)physical_address);
PageTable *src = src_directory->tables[src_index];
// Copy all the pages
@@ -214,7 +211,7 @@ PageTable *clone_table(u32 src_index, PageDirectory *src_directory,
PageTable *copy_table(PageTable *src, u32 *physical_address) {
PageTable *new_table =
- ksbrk_physical(sizeof(PageTable), (void **)physical_address);
+ kmalloc_align(sizeof(PageTable), (void **)physical_address);
// copy all the pages
for (u16 i = 0; i < 1024; i++) {
@@ -239,7 +236,7 @@ PageDirectory *clone_directory(PageDirectory *original) {
u32 physical_address;
PageDirectory *new_directory =
- ksbrk_physical(sizeof(PageDirectory), (void **)&physical_address);
+ kmalloc_align(sizeof(PageDirectory), (void **)&physical_address);
u32 offset = (u32)new_directory->physical_tables - (u32)new_directory;
new_directory->physical_address = physical_address + offset;
@@ -388,6 +385,34 @@ void *allocate_frame(Page *page, int rw, int is_kernel) {
return (void *)(frame_address * 0x1000);
}
+void mmu_free_pagedirectory(PageDirectory *pd) {
+ for (int i = 0; i < 1024; i++) {
+ if (!pd->tables[i]) {
+ continue;
+ }
+ if (pd->tables[i] == kernel_directory->tables[i]) {
+ continue;
+ }
+
+ for (int j = 0; j < 1024; j++) {
+ Page *page = &(pd->tables[i]->pages[j]);
+ if (!page) {
+ continue;
+ }
+ if (!page->present) {
+ continue;
+ }
+ if (!page->frame) {
+ continue;
+ }
+ write_to_frame(((u32)page->frame) * 0x1000, 0);
+ }
+ kmalloc_align_free(pd->tables[i], sizeof(PageTable));
+ pd->tables[i] = NULL;
+ }
+ kmalloc_align_free(pd, sizeof(PageDirectory));
+}
+
void mmu_free_address_range(void *ptr, size_t length, PageDirectory *pd) {
size_t num_pages = (size_t)align_page((void *)length) / PAGE_SIZE;
for (size_t i = 0; i < num_pages; i++, ptr += PAGE_SIZE) {
@@ -581,7 +606,7 @@ void create_table(int table_index) {
u32 physical;
kernel_directory->tables[table_index] = (PageTable *)0xDEADBEEF;
kernel_directory->tables[table_index] =
- (PageTable *)ksbrk_physical(sizeof(PageTable), (void **)&physical);
+ (PageTable *)kmalloc_align(sizeof(PageTable), (void **)&physical);
memset(kernel_directory->tables[table_index], 0, sizeof(PageTable));
kernel_directory->physical_tables[table_index] = (u32)physical | 0x3;
}
diff --git a/kernel/includes/mmu.h b/kernel/includes/mmu.h
index 43814d5..211a950 100644
--- a/kernel/includes/mmu.h
+++ b/kernel/includes/mmu.h
@@ -9,6 +9,9 @@ typedef u8 mmu_flags;
#define MMU_FLAG_RW (1 << 0)
#define MMU_FLAG_KERNEL (1 << 1)
+#define PAGE_ALLOCATE 1
+#define PAGE_NO_ALLOCATE 0
+
#define PAGE_SIZE ((uintptr_t)0x1000)
#define next_page(_ptr) \
((_ptr) + (PAGE_SIZE - (((uintptr_t)_ptr) & (PAGE_SIZE - 1))))
@@ -37,6 +40,7 @@ typedef struct PageDirectory {
int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags,
PageDirectory *pd);
+void mmu_free_pagedirectory(PageDirectory *pd);
void mmu_allocate_shared_kernel_region(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);
diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c
index 7138d61..59cc93d 100644
--- a/kernel/kmalloc.c
+++ b/kernel/kmalloc.c
@@ -2,12 +2,36 @@
#include <kmalloc.h>
#include <ksbrk.h>
#include <math.h>
+#include <mmu.h>
#include <random.h>
#define NEW_ALLOC_SIZE 0x5000
#define IS_FREE (1 << 0)
#define IS_FINAL (1 << 1)
+void *kmalloc_align(size_t s, void **physical) {
+ // TODO: It should reuse virtual regions so that it does not run out
+ // of address space.
+ return ksbrk_physical(s, physical);
+}
+
+void kmalloc_align_free(void *p, size_t s) {
+ for (int i = 0; i < s; i += 0x1000) {
+ Page *page = get_page((char *)p + i, NULL, PAGE_NO_ALLOCATE, 0);
+ if (!page) {
+ continue;
+ }
+ if (!page->present) {
+ continue;
+ }
+ if (!page->frame) {
+ continue;
+ }
+ write_to_frame(((u32)page->frame) * 0x1000, 0);
+ page->present = 0;
+ }
+}
+
typedef struct MallocHeader {
u64 magic;
u32 size;
diff --git a/kernel/kmalloc.h b/kernel/kmalloc.h
index 8c55cb4..8b9d59d 100644
--- a/kernel/kmalloc.h
+++ b/kernel/kmalloc.h
@@ -4,10 +4,12 @@
#include <string.h>
#include <typedefs.h>
+void *kmalloc_align(size_t s, void **physical);
+void kmalloc_align_free(void *p, size_t s);
+
void kmalloc_allocate_heap(void);
void *kmalloc(size_t s);
-void *kmalloc_align(size_t s);
void *krealloc(void *ptr, size_t size);
void *kreallocarray(void *ptr, size_t nmemb, size_t size);
void *kallocarray(size_t nmemb, size_t size);
diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c
index 52e4848..45969b0 100644
--- a/kernel/sched/scheduler.c
+++ b/kernel/sched/scheduler.c
@@ -191,9 +191,6 @@ void free_process(process_t *p) {
mmu_remove_virtual_physical_address_mapping(m->u_address, m->length);
}
- // NOTE: Kernel stuff begins at 0x90000000
- mmu_free_address_range((void *)0x1000, 0x90000000, p->cr3);
-
list_free(&p->read_list);
list_free(&p->write_list);
list_free(&p->disconnect_list);
@@ -202,9 +199,12 @@ void free_process(process_t *p) {
list_free(&p->event_queue);
list_free(&p->file_descriptors);
kfree(p->tcb);
+
+ mmu_free_pagedirectory(p->cr3);
}
void exit_process(process_t *p, int status) {
+ disable_interrupts();
assert(p->pid != 1);
if (p->parent) {
p->parent->halts[WAIT_CHILD_HALT] = 0;