diff options
| author | Anton Kling <anton@kling.gg> | 2024-04-12 14:03:29 +0200 | 
|---|---|---|
| committer | Anton Kling <anton@kling.gg> | 2024-04-12 14:13:08 +0200 | 
| commit | b450065984b1588966694579230dc40c802212e7 (patch) | |
| tree | e67a056b1f3d0d2fa9a8f07fd76f925080dfbf44 /kernel | |
| parent | ca082f686fd2dc7ee6f0284421f6212d6d4acee8 (diff) | |
Kernel/MMU: Dellocate pagedirectory when process exits.
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/arch/i386/mmu.c | 41 | ||||
| -rw-r--r-- | kernel/includes/mmu.h | 4 | ||||
| -rw-r--r-- | kernel/kmalloc.c | 24 | ||||
| -rw-r--r-- | kernel/kmalloc.h | 4 | ||||
| -rw-r--r-- | kernel/sched/scheduler.c | 6 | 
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; |