From 707a87828b821fcd7e54c7212d8da460579c4db1 Mon Sep 17 00:00:00 2001 From: Arnau478 Date: Sun, 24 Jul 2022 18:35:30 +0200 Subject: [PATCH] Scoped VMM and PMM to arch/i686 --- src/kernel/arch/i686/mm/pde.c | 33 ++++++ src/kernel/arch/i686/mm/pde.h | 30 +++++ src/kernel/{ => arch/i686}/mm/pmm.asm | 16 +-- src/kernel/arch/i686/mm/pmm.c | 152 ++++++++++++++++++++++++++ src/kernel/arch/i686/mm/pmm.h | 28 +++++ src/kernel/arch/i686/mm/pte.c | 25 +++++ src/kernel/arch/i686/mm/pte.h | 27 +++++ src/kernel/{ => arch/i686}/mm/vmm.asm | 4 +- src/kernel/arch/i686/mm/vmm.c | 142 ++++++++++++++++++++++++ src/kernel/arch/i686/mm/vmm.h | 33 ++++++ src/kernel/main.c | 12 +- src/kernel/mm/pde.c | 33 ------ src/kernel/mm/pde.h | 30 ----- src/kernel/mm/pmm.c | 152 -------------------------- src/kernel/mm/pmm.h | 28 ----- src/kernel/mm/pte.c | 25 ----- src/kernel/mm/pte.h | 27 ----- src/kernel/mm/vmm.c | 142 ------------------------ src/kernel/mm/vmm.h | 33 ------ 19 files changed, 486 insertions(+), 486 deletions(-) create mode 100644 src/kernel/arch/i686/mm/pde.c create mode 100644 src/kernel/arch/i686/mm/pde.h rename src/kernel/{ => arch/i686}/mm/pmm.asm (72%) create mode 100644 src/kernel/arch/i686/mm/pmm.c create mode 100644 src/kernel/arch/i686/mm/pmm.h create mode 100644 src/kernel/arch/i686/mm/pte.c create mode 100644 src/kernel/arch/i686/mm/pte.h rename src/kernel/{ => arch/i686}/mm/vmm.asm (50%) create mode 100644 src/kernel/arch/i686/mm/vmm.c create mode 100644 src/kernel/arch/i686/mm/vmm.h delete mode 100644 src/kernel/mm/pde.c delete mode 100644 src/kernel/mm/pde.h delete mode 100644 src/kernel/mm/pmm.c delete mode 100644 src/kernel/mm/pmm.h delete mode 100644 src/kernel/mm/pte.c delete mode 100644 src/kernel/mm/pte.h delete mode 100644 src/kernel/mm/vmm.c delete mode 100644 src/kernel/mm/vmm.h diff --git a/src/kernel/arch/i686/mm/pde.c b/src/kernel/arch/i686/mm/pde.c new file mode 100644 index 0000000..345d53d --- /dev/null +++ b/src/kernel/arch/i686/mm/pde.c @@ -0,0 +1,33 @@ +#include "pde.h" + +void i686_pd_entry_add_attr(i686_pd_entry_t *entry, uint32_t attr){ + *entry |= attr; +} + +void i686_pd_entry_del_attr(i686_pd_entry_t *entry, uint32_t attr){ + *entry &= ~attr; +} + +void i686_pd_entry_set_frame(i686_pd_entry_t *entry, i686_phys_addr frame){ + *entry = (*entry & ~i686_PDE_FRAME) | frame; +} + +i686_phys_addr i686_pd_entry_get_frame(i686_pd_entry_t entry){ + return entry & i686_PDE_FRAME; +} + +bool i686_pd_entry_is_present(i686_pd_entry_t entry){ + return entry & i686_PDE_PRESENT; +} + +bool i686_pd_entry_is_user(i686_pd_entry_t entry){ + return entry & i686_PDE_USER; +} + +bool i686_pd_entry_is_4mb(i686_pd_entry_t entry){ + return entry & i686_PDE_4MB; +} + +bool i686_pd_entry_is_writable(i686_pd_entry_t entry){ + return entry & i686_PDE_WRITABLE; +} diff --git a/src/kernel/arch/i686/mm/pde.h b/src/kernel/arch/i686/mm/pde.h new file mode 100644 index 0000000..3680738 --- /dev/null +++ b/src/kernel/arch/i686/mm/pde.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include "pmm.h" + +enum i686_PDE_PAGE_FLAGS{ + i686_PDE_PRESENT = 0x0001, + i686_PDE_WRITABLE = 0x0002, + i686_PDE_USER = 0x0004, + i686_PDE_WRITETHROUGH = 0x0008, + i686_PDE_CACHE_DISABLED = 0x0010, + i686_PDE_ACCESSED = 0x0020, + i686_PDE_DIRTY = 0x0040, + i686_PDE_4MB = 0x0080, + i686_PDE_CPU_GLOBAL = 0x0100, + i686_PDE_LV4_GLOBAL = 0x0200, + i686_PDE_FRAME = 0x7FFFF000, +}; + +typedef uint32_t i686_pd_entry_t; + +void i686_pd_entry_add_attr(i686_pd_entry_t *entry, uint32_t attr); +void i686_pd_entry_del_attr(i686_pd_entry_t *entry, uint32_t attr); +void i686_pd_entry_set_frame(i686_pd_entry_t *entry, i686_phys_addr frame); +i686_phys_addr i686_pd_entry_get_frame(i686_pd_entry_t entry); +bool i686_pd_entry_is_present(i686_pd_entry_t entry); +bool i686_pd_entry_is_user(i686_pd_entry_t entry); +bool i686_pd_entry_is_4mb(i686_pd_entry_t entry); +bool i686_pd_entry_is_writable(i686_pd_entry_t entry); diff --git a/src/kernel/mm/pmm.asm b/src/kernel/arch/i686/mm/pmm.asm similarity index 72% rename from src/kernel/mm/pmm.asm rename to src/kernel/arch/i686/mm/pmm.asm index 51db936..c3659f1 100644 --- a/src/kernel/mm/pmm.asm +++ b/src/kernel/arch/i686/mm/pmm.asm @@ -1,5 +1,5 @@ -global pmm_paging_enable -pmm_paging_enable: +global i686_pmm_paging_enable +i686_pmm_paging_enable: [bits 32] ; New call frame push ebp @@ -22,22 +22,22 @@ pmm_paging_enable: pop ebp ret -global pmm_is_paging -pmm_is_paging: +global i686_pmm_is_paging +i686_pmm_is_paging: [bits 32] mov eax, cr0 and eax, 0x80000000 ret -global pmm_load_pdbr -pmm_load_pdbr: +global i686_pmm_load_pdbr +i686_pmm_load_pdbr: [bits 32] mov eax, [esp + 4] mov cr3, eax ret -global pmm_get_pdbr -pmm_get_pdbr: +global i686_pmm_get_pdbr +i686_pmm_get_pdbr: [bits 32] mov eax, cr3 ret diff --git a/src/kernel/arch/i686/mm/pmm.c b/src/kernel/arch/i686/mm/pmm.c new file mode 100644 index 0000000..7af7b5b --- /dev/null +++ b/src/kernel/arch/i686/mm/pmm.c @@ -0,0 +1,152 @@ +#include +#include "pmm.h" +#include "../../../lib/memory.h" + +static uint32_t g_pmm_memory_size = 0; +static uint32_t g_pmm_used_blocks = 0; +static uint32_t g_pmm_max_blocks = 0; +static uint32_t *g_pmm_memory_map = 0; + +static inline void i686_pmm_map_set(int bit){ + g_pmm_memory_map[bit / 32] |= (1 << (bit % 32)); +} + +static inline void i686_pmm_map_unset(int bit){ + g_pmm_memory_map[bit / 32] &= ~(1 << (bit % 32)); +} + +static inline bool i686_pmm_map_get(int bit){ + return g_pmm_memory_map[bit / 32] & (1 << (bit % 32)); +} + +int i686_pmm_map_first_free(){ + for(uint32_t i = 0; i < i686_pmm_get_block_count() / 32; i++){ + if(g_pmm_memory_map[i] != 0xffffffff){ + for(int j = 0; j < 32; j++){ + if(!(g_pmm_memory_map[i] & (1 << j))){ + return i*4*8+j; + } + } + } + } + return -1; +} + +int i686_pmm_map_first_free_s(size_t size){ + if(size == 0) return -1; + if(size == 1) return i686_pmm_map_first_free(); + + for(uint32_t i = 0; i < i686_pmm_get_block_count() / 32; i++){ + if(g_pmm_memory_map[i] != 0xffffffff){ + for(int j = 0; j < 32; j++){ + int bit = 1 << j; + if(!(g_pmm_memory_map[i] & bit)){ + int start_bit = i*32; + start_bit+=bit; + + uint32_t free = 0; + for(uint32_t count = 0; count <= size; count++){ + if(!i686_pmm_map_get(start_bit+count)) free++; + if(free == size) return i*4*8+j; + } + } + } + } + } + return -1; +} + +void i686_pmm_initialize(size_t mem_size, i686_phys_addr bitmap){ + g_pmm_memory_size = mem_size; + g_pmm_memory_map = (uint32_t *)bitmap; + g_pmm_max_blocks = (i686_pmm_get_memory_size()*1024) / i686_PMM_BLOCK_SIZE; + g_pmm_used_blocks = g_pmm_max_blocks; + + memset(g_pmm_memory_map, 0xFF, i686_pmm_get_block_count() / i686_PMM_BLOCKS_PER_BYTE); +} + +void i686_pmm_init_region(i686_phys_addr base, size_t size){ + int align = base / i686_PMM_BLOCK_SIZE; + int blocks = size / i686_PMM_BLOCK_SIZE; + + for(; blocks >= 0; blocks--){ + i686_pmm_map_unset(align++); + g_pmm_used_blocks--; + } + + i686_pmm_map_set(0); // First block always set +} + +void i686_pmm_deinit_region(i686_phys_addr base, size_t size){ + int align = base / i686_PMM_BLOCK_SIZE; + int blocks = size / i686_PMM_BLOCK_SIZE; + + for(; blocks >= 0; blocks--){ + i686_pmm_map_set(align++); + g_pmm_used_blocks++; + } + + i686_pmm_map_set(0); // First block always set +} + +void *i686_pmm_alloc_block(){ + if(i686_pmm_get_free_block_count() <= 0) return 0; // Out of memory + + int frame = i686_pmm_map_first_free(); + if(frame == -1) return 0; // Out of memory + + i686_pmm_map_set(frame); + + i686_phys_addr addr = frame * i686_PMM_BLOCK_SIZE; + g_pmm_used_blocks++; + + return (void *)addr; +} + +void i686_pmm_free_block(void *p){ + i686_phys_addr addr = (i686_phys_addr)p; + int frame = addr / i686_PMM_BLOCK_SIZE; + + i686_pmm_map_unset(frame); + + g_pmm_used_blocks--; +} + +void *i686_pmm_alloc_blocks(size_t size){ + if(i686_pmm_get_free_block_count() <= size) return 0; // Out of memory + + int frame = i686_pmm_map_first_free_s(size); + if(frame == -1) return 0; // Out of memory + + for(uint32_t i = 0; i < size; i++) i686_pmm_map_set(frame+i); + + i686_phys_addr addr = frame * i686_PMM_BLOCK_SIZE; + g_pmm_used_blocks += size; + + return (void *)addr; +} + +void i686_pmm_free_blocks(void *p, size_t size){ + i686_phys_addr addr = (i686_phys_addr)p; + int frame = addr / i686_PMM_BLOCK_SIZE; + + for(uint32_t i = 0; i < size; i++) i686_pmm_map_unset(frame+i); + + g_pmm_used_blocks -= size; +} + +size_t i686_pmm_get_memory_size(){ + return g_pmm_memory_size; +} + +uint32_t i686_pmm_get_block_count(){ + return g_pmm_max_blocks; +} + +uint32_t i686_pmm_get_used_block_count(){ + return g_pmm_used_blocks; +} + +uint32_t i686_pmm_get_free_block_count(){ + return g_pmm_max_blocks - g_pmm_used_blocks; +} diff --git a/src/kernel/arch/i686/mm/pmm.h b/src/kernel/arch/i686/mm/pmm.h new file mode 100644 index 0000000..2172840 --- /dev/null +++ b/src/kernel/arch/i686/mm/pmm.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#define i686_PMM_BLOCKS_PER_BYTE 8 +#define i686_PMM_BLOCK_SIZE 4096 +#define i686_PMM_BLOCK_ALIGN PMM_BLOCK_SIZE + +typedef uint32_t i686_phys_addr; + +int i686_pmm_map_first_free(); +int i686_pmm_map_first_free_s(size_t size); +void i686_pmm_initialize(size_t mem_size, i686_phys_addr bitmap); +void i686_pmm_init_region(i686_phys_addr base, size_t size); +void i686_pmm_deinit_region(i686_phys_addr base, size_t size); +void *i686_pmm_alloc_block(); +void i686_pmm_free_block(void *p); +void *i686_pmm_alloc_blocks(size_t size); +void i686_pmm_free_blocks(void *p, size_t size); +size_t i686_pmm_get_memory_size(); +uint32_t i686_pmm_get_block_count(); +uint32_t i686_pmm_get_used_block_count(); +uint32_t i686_pmm_get_free_block_count(); +void __attribute__((cdecl)) i686_pmm_paging_enable(bool enabled); +bool __attribute__((cdecl)) i686_pmm_is_paging(); +void __attribute__((cdecl)) i686_pmm_load_pdbr(i686_phys_addr addr); +i686_phys_addr __attribute__((cdecl)) i686_pmm_get_pdbr(); diff --git a/src/kernel/arch/i686/mm/pte.c b/src/kernel/arch/i686/mm/pte.c new file mode 100644 index 0000000..a2bcec0 --- /dev/null +++ b/src/kernel/arch/i686/mm/pte.c @@ -0,0 +1,25 @@ +#include "pte.h" + +void i686_pt_entry_add_attr(i686_pt_entry_t *entry, uint32_t attr){ + *entry |= attr; +} + +void i686_pt_entry_del_attr(i686_pt_entry_t *entry, uint32_t attr){ + *entry &= ~attr; +} + +void i686_pt_entry_set_frame(i686_pt_entry_t *entry, i686_phys_addr frame){ + *entry = (*entry & ~i686_PTE_FRAME) | frame; +} + +i686_phys_addr i686_pt_entry_get_frame(i686_pt_entry_t entry){ + return entry & i686_PTE_FRAME; +} + +bool i686_pt_entry_is_present(i686_pt_entry_t entry){ + return entry & i686_PTE_PRESENT; +} + +bool i686_pt_entry_is_writable(i686_pt_entry_t entry){ + return entry & i686_PTE_WRITABLE; +} diff --git a/src/kernel/arch/i686/mm/pte.h b/src/kernel/arch/i686/mm/pte.h new file mode 100644 index 0000000..7b3dd62 --- /dev/null +++ b/src/kernel/arch/i686/mm/pte.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include "pmm.h" + +enum i686_PTE_PAGE_FLAGS{ + i686_PTE_PRESENT = 0x0001, + i686_PTE_WRITABLE = 0x0002, + i686_PTE_USER = 0x0004, + i686_PTE_WRITETHROUGH = 0x0008, + i686_PTE_NOT_CACHEABLE = 0x0010, + i686_PTE_ACCESSED = 0x0020, + i686_PTE_DIRTY = 0x0040, + i686_PTE_PAT = 0x0080, + i686_PTE_CPU_GLOBAL = 0x0100, + i686_PTE_LV4_GLOBAL = 0x0200, + i686_PTE_FRAME = 0x7FFFF000 +}; + +typedef uint32_t i686_pt_entry_t; + +void i686_pt_entry_add_attr(i686_pt_entry_t *entry, uint32_t attr); +void i686_pt_entry_del_attr(i686_pt_entry_t *entry, uint32_t attr); +void i686_pt_entry_set_frame(i686_pt_entry_t *entry, i686_phys_addr frame); +i686_phys_addr i686_pt_entry_get_frame(i686_pt_entry_t entry); +bool i686_pt_entry_is_present(i686_pt_entry_t entry); +bool i686_pt_entry_is_writable(i686_pt_entry_t entry); diff --git a/src/kernel/mm/vmm.asm b/src/kernel/arch/i686/mm/vmm.asm similarity index 50% rename from src/kernel/mm/vmm.asm rename to src/kernel/arch/i686/mm/vmm.asm index e9883ae..9f3b332 100644 --- a/src/kernel/mm/vmm.asm +++ b/src/kernel/arch/i686/mm/vmm.asm @@ -1,5 +1,5 @@ -global vmm_flush_tlb_entry -vmm_flush_tlb_entry: +global i686_vmm_flush_tlb_entry +i686_vmm_flush_tlb_entry: [bits 32] cli invlpg [esp + 4] diff --git a/src/kernel/arch/i686/mm/vmm.c b/src/kernel/arch/i686/mm/vmm.c new file mode 100644 index 0000000..b9ebf03 --- /dev/null +++ b/src/kernel/arch/i686/mm/vmm.c @@ -0,0 +1,142 @@ +#include "vmm.h" +#include "pmm.h" +#include "../../../lib/memory.h" + +i686_vmm_page_directory_t *g_vmm_current_dir = 0; +i686_phys_addr g_vmm_current_pdbr = 0; + +void __attribute__((cdecl)) i686_vmm_flush_tlb_entry(i686_virt_addr addr); + +static inline i686_pt_entry_t *i686_vmm_ptable_lookup_entry(i686_vmm_page_table_t *p, i686_virt_addr addr){ + if(p) return &p->entries[i686_PAGE_TABLE_INDEX(addr)]; + return 0; +} + +static inline i686_pd_entry_t *i686_vmm_pdirectory_lookup_entry(i686_vmm_page_directory_t *p, i686_virt_addr addr){ + if(p) return &p->entries[i686_PAGE_DIRECTORY_INDEX(addr)]; + return 0; +} + +static inline bool i686_vmm_switch_pdirectory(i686_vmm_page_directory_t *dir){ + if(!dir) return false; + + g_vmm_current_dir = dir; + i686_pmm_load_pdbr(g_vmm_current_pdbr); + return true; +} + +static inline i686_vmm_page_directory_t *i686_vmm_get_pdirectory(){ + return g_vmm_current_dir; +} + +bool i686_vmm_alloc_page(i686_pt_entry_t *entry){ + void *p = i686_pmm_alloc_block(); + if(!p) return false; + + i686_pt_entry_set_frame(entry, (i686_phys_addr)p); + i686_pt_entry_add_attr(entry, i686_PTE_PRESENT); + + return true; +} + +void i686_vmm_free_page(i686_pt_entry_t *entry){ + void *p = (void *)i686_pt_entry_get_frame(*entry); + if(p) i686_pmm_free_block(p); + + i686_pt_entry_del_attr(entry, i686_PTE_PRESENT); +} + +void i686_vmm_map_page(void *phys, void *virt){ + // Get page directory + i686_vmm_page_directory_t *page_dir = i686_vmm_get_pdirectory(); + + // Get page table + i686_pd_entry_t *e = &page_dir->entries[i686_PAGE_DIRECTORY_INDEX((uint32_t)virt)]; + if((*e & i686_PTE_PRESENT) != i686_PTE_PRESENT){ + // Must allocate + i686_vmm_page_table_t *table = (i686_vmm_page_table_t *)i686_pmm_alloc_block(); + if(!table) return; + + // Clear page table + memset(table, 0, sizeof(i686_vmm_page_table_t)); + + // Create a new entry + i686_pd_entry_t *entry = &page_dir->entries[i686_PAGE_DIRECTORY_INDEX((uint32_t)virt)]; + + // Map in the table + i686_pd_entry_add_attr(entry, i686_PDE_PRESENT); + i686_pd_entry_add_attr(entry, i686_PDE_WRITABLE); + i686_pd_entry_set_frame(entry, (i686_phys_addr)table); + } + + // Get table + i686_vmm_page_table_t *table = (i686_vmm_page_table_t *)i686_PAGE_GET_PHYS_ADDR(e); + + // Get page + i686_pt_entry_t *page = &table->entries[i686_PAGE_TABLE_INDEX((uint32_t)virt)]; + + // Map it + i686_pt_entry_set_frame(page, (i686_phys_addr)phys); + i686_pt_entry_add_attr(page, i686_PTE_PRESENT); +} + +void i686_vmm_initialize(){ + // Allocate default page table + i686_vmm_page_table_t *table = (i686_vmm_page_table_t *)i686_pmm_alloc_block(); + if(!table) return; + + // Allocate 3GB page table + i686_vmm_page_table_t *table2 = (i686_vmm_page_table_t *)i686_pmm_alloc_block(); + if(!table2) return; + + // Clear default table + memset(table, 0, sizeof(i686_vmm_page_table_t)); + + // First 4MB are identity mapped + for(int i = 0, frame = 0x0, virt = 0x00000000; i<1024; i++, frame += 4096, virt += 4096){ + // Create a new page + i686_pt_entry_t page = 0; + i686_pt_entry_add_attr(&page, i686_PTE_PRESENT); + i686_pt_entry_set_frame(&page, frame); + + // Add the page to the page table + table2->entries[i686_PAGE_TABLE_INDEX(virt)] = page; + } + + // Map 1MB to 3GB + for(int i = 0, frame = 0x100000, virt = 0xc0000000; i<1024; i++, frame += 4096, virt += 4096){ + // Create a new page + i686_pt_entry_t page = 0; + i686_pt_entry_add_attr(&page, i686_PTE_PRESENT); + i686_pt_entry_set_frame(&page, frame); + + // Add the page to the page table + table->entries[i686_PAGE_TABLE_INDEX(virt)] = page; + } + + // Create default directory table + i686_vmm_page_directory_t *dir = (i686_vmm_page_directory_t *)i686_pmm_alloc_blocks(3); + if(!dir) return; + + // Clear directory table and set it as current + memset(dir, 0, sizeof(i686_vmm_page_directory_t)); + + i686_pd_entry_t *entry = &dir->entries[i686_PAGE_DIRECTORY_INDEX(0xc0000000)]; + i686_pd_entry_add_attr(entry, i686_PDE_PRESENT); + i686_pd_entry_add_attr(entry, i686_PDE_WRITABLE); + i686_pd_entry_set_frame(entry, (i686_phys_addr)table); + + i686_pd_entry_t *entry2 = &dir->entries[i686_PAGE_DIRECTORY_INDEX(0x00000000)]; + i686_pd_entry_add_attr(entry2, i686_PDE_PRESENT); + i686_pd_entry_add_attr(entry2, i686_PDE_WRITABLE); + i686_pd_entry_set_frame(entry2, (i686_phys_addr)table2); + + // Store current PDBR + g_vmm_current_pdbr = (i686_phys_addr)&dir->entries; + + // Switch to our page directory + i686_vmm_switch_pdirectory(dir); + + // Enable paging + i686_pmm_paging_enable(true); +} diff --git a/src/kernel/arch/i686/mm/vmm.h b/src/kernel/arch/i686/mm/vmm.h new file mode 100644 index 0000000..fdc7212 --- /dev/null +++ b/src/kernel/arch/i686/mm/vmm.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include "pte.h" +#include "pde.h" + +typedef uint32_t i686_virt_addr; + +#define i686_PAGES_PER_TABLE 1024 +#define i686_PAGES_PER_DIR 1024 + +#define i686_PAGE_DIRECTORY_INDEX(x) (((x) >> 22) & 0x3FF) +#define i686_PAGE_TABLE_INDEX(x) (((x) >> 12) & 0x3FF) +#define i686_PAGE_GET_PHYS_ADDR(x) (*(x) & ~0xFFF) + +#define i686_PTABLE_ADDR_SPACE_SIZE 0x400000 +#define i686_DTABLE_ADDR_SPACE_SIZE 0x100000000 + +#define i686_PAGE_SIZE 4096 + +typedef struct{ + i686_pt_entry_t entries[i686_PAGES_PER_TABLE]; +} i686_vmm_page_table_t; + +typedef struct{ + i686_pd_entry_t entries[i686_PAGES_PER_DIR]; +} i686_vmm_page_directory_t; + +bool i686_vmm_alloc_page(i686_pt_entry_t *entry); +void i686_vmm_free_page(i686_pt_entry_t *entry); +void i686_vmm_map_page(void *phys, void *virt); +void i686_vmm_initialize(); diff --git a/src/kernel/main.c b/src/kernel/main.c index e726d61..37044b8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -5,8 +5,8 @@ #include "drivers/keyboard.h" #include "drivers/serial.h" #include "fs/vfs.h" -#include "mm/pmm.h" -#include "mm/vmm.h" +#include "arch/i686/mm/pmm.h" +#include "arch/i686/mm/vmm.h" #include "multiboot.h" extern uint8_t end; // Kernel end @@ -21,21 +21,21 @@ void __attribute__((cdecl)) kmain(multiboot_info_t *multiboot_info){ // Initialize physical memory manager uint32_t mem_size = 1024 + multiboot_info->mem_lower + multiboot_info->mem_upper*64; - pmm_initialize(mem_size, (int)(&end)); + i686_pmm_initialize(mem_size, (int)(&end)); for(int i = 0; i < multiboot_info->mmap_length; i += sizeof(multiboot_memory_map_t)){ multiboot_memory_map_t *memory_map = (multiboot_memory_map_t *)(multiboot_info->mmap_addr + i); printf("Start Addr: 0x%x%x | Length: 0x%x%x | Size: 0x%x | Type: %i\n", memory_map->addr_h, memory_map->addr_l, memory_map->len_h, memory_map->len_l, memory_map->size, memory_map->type); if(memory_map->type == 1){ - pmm_init_region(memory_map->addr_l, memory_map->len_l); + i686_pmm_init_region(memory_map->addr_l, memory_map->len_l); } } - pmm_deinit_region(0x100000, (int)(&end) - 0x100000); // Deinit the section the kernel is in + i686_pmm_deinit_region(0x100000, (int)(&end) - 0x100000); // Deinit the section the kernel is in // Initialize virtual memory - vmm_initialize(); + i686_vmm_initialize(); // Initialize drivers timer_initialize(); diff --git a/src/kernel/mm/pde.c b/src/kernel/mm/pde.c deleted file mode 100644 index c5d604e..0000000 --- a/src/kernel/mm/pde.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "pde.h" - -void pd_entry_add_attr(pd_entry_t *entry, uint32_t attr){ - *entry |= attr; -} - -void pd_entry_del_attr(pd_entry_t *entry, uint32_t attr){ - *entry &= ~attr; -} - -void pd_entry_set_frame(pd_entry_t *entry, phys_addr frame){ - *entry = (*entry & ~PDE_FRAME) | frame; -} - -phys_addr pd_entry_get_frame(pd_entry_t entry){ - return entry & PDE_FRAME; -} - -bool pd_entry_is_present(pd_entry_t entry){ - return entry & PDE_PRESENT; -} - -bool pd_entry_is_user(pd_entry_t entry){ - return entry & PDE_USER; -} - -bool pd_entry_is_4mb(pd_entry_t entry){ - return entry & PDE_4MB; -} - -bool pd_entry_is_writable(pd_entry_t entry){ - return entry & PDE_WRITABLE; -} diff --git a/src/kernel/mm/pde.h b/src/kernel/mm/pde.h deleted file mode 100644 index 6c9b04b..0000000 --- a/src/kernel/mm/pde.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include -#include "pmm.h" - -enum PDE_PAGE_FLAGS{ - PDE_PRESENT = 0x0001, - PDE_WRITABLE = 0x0002, - PDE_USER = 0x0004, - PDE_WRITETHROUGH = 0x0008, - PDE_CACHE_DISABLED = 0x0010, - PDE_ACCESSED = 0x0020, - PDE_DIRTY = 0x0040, - PDE_4MB = 0x0080, - PDE_CPU_GLOBAL = 0x0100, - PDE_LV4_GLOBAL = 0x0200, - PDE_FRAME = 0x7FFFF000, -}; - -typedef uint32_t pd_entry_t; - -void pd_entry_add_attr(pd_entry_t *entry, uint32_t attr); -void pd_entry_del_attr(pd_entry_t *entry, uint32_t attr); -void pd_entry_set_frame(pd_entry_t *entry, phys_addr frame); -phys_addr pd_entry_get_frame(pd_entry_t entry); -bool pd_entry_is_present(pd_entry_t entry); -bool pd_entry_is_user(pd_entry_t entry); -bool pd_entry_is_4mb(pd_entry_t entry); -bool pd_entry_is_writable(pd_entry_t entry); diff --git a/src/kernel/mm/pmm.c b/src/kernel/mm/pmm.c deleted file mode 100644 index dfb3fd0..0000000 --- a/src/kernel/mm/pmm.c +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include "pmm.h" -#include "../lib/memory.h" - -static uint32_t g_pmm_memory_size = 0; -static uint32_t g_pmm_used_blocks = 0; -static uint32_t g_pmm_max_blocks = 0; -static uint32_t *g_pmm_memory_map = 0; - -static inline void pmm_map_set(int bit){ - g_pmm_memory_map[bit / 32] |= (1 << (bit % 32)); -} - -static inline void pmm_map_unset(int bit){ - g_pmm_memory_map[bit / 32] &= ~(1 << (bit % 32)); -} - -static inline bool pmm_map_get(int bit){ - return g_pmm_memory_map[bit / 32] & (1 << (bit % 32)); -} - -int pmm_map_first_free(){ - for(uint32_t i = 0; i < pmm_get_block_count() / 32; i++){ - if(g_pmm_memory_map[i] != 0xffffffff){ - for(int j = 0; j < 32; j++){ - if(!(g_pmm_memory_map[i] & (1 << j))){ - return i*4*8+j; - } - } - } - } - return -1; -} - -int pmm_map_first_free_s(size_t size){ - if(size == 0) return -1; - if(size == 1) return pmm_map_first_free(); - - for(uint32_t i = 0; i < pmm_get_block_count() / 32; i++){ - if(g_pmm_memory_map[i] != 0xffffffff){ - for(int j = 0; j < 32; j++){ - int bit = 1 << j; - if(!(g_pmm_memory_map[i] & bit)){ - int start_bit = i*32; - start_bit+=bit; - - uint32_t free = 0; - for(uint32_t count = 0; count <= size; count++){ - if(!pmm_map_get(start_bit+count)) free++; - if(free == size) return i*4*8+j; - } - } - } - } - } - return -1; -} - -void pmm_initialize(size_t mem_size, phys_addr bitmap){ - g_pmm_memory_size = mem_size; - g_pmm_memory_map = (uint32_t *)bitmap; - g_pmm_max_blocks = (pmm_get_memory_size()*1024) / PMM_BLOCK_SIZE; - g_pmm_used_blocks = g_pmm_max_blocks; - - memset(g_pmm_memory_map, 0xFF, pmm_get_block_count() / PMM_BLOCKS_PER_BYTE); -} - -void pmm_init_region(phys_addr base, size_t size){ - int align = base / PMM_BLOCK_SIZE; - int blocks = size / PMM_BLOCK_SIZE; - - for(; blocks >= 0; blocks--){ - pmm_map_unset(align++); - g_pmm_used_blocks--; - } - - pmm_map_set(0); // First block always set -} - -void pmm_deinit_region(phys_addr base, size_t size){ - int align = base / PMM_BLOCK_SIZE; - int blocks = size / PMM_BLOCK_SIZE; - - for(; blocks >= 0; blocks--){ - pmm_map_set(align++); - g_pmm_used_blocks++; - } - - pmm_map_set(0); // First block always set -} - -void *pmm_alloc_block(){ - if(pmm_get_free_block_count() <= 0) return 0; // Out of memory - - int frame = pmm_map_first_free(); - if(frame == -1) return 0; // Out of memory - - pmm_map_set(frame); - - phys_addr addr = frame * PMM_BLOCK_SIZE; - g_pmm_used_blocks++; - - return (void *)addr; -} - -void pmm_free_block(void *p){ - phys_addr addr = (phys_addr)p; - int frame = addr / PMM_BLOCK_SIZE; - - pmm_map_unset(frame); - - g_pmm_used_blocks--; -} - -void *pmm_alloc_blocks(size_t size){ - if(pmm_get_free_block_count() <= size) return 0; // Out of memory - - int frame = pmm_map_first_free_s(size); - if(frame == -1) return 0; // Out of memory - - for(uint32_t i = 0; i < size; i++) pmm_map_set(frame+i); - - phys_addr addr = frame * PMM_BLOCK_SIZE; - g_pmm_used_blocks += size; - - return (void *)addr; -} - -void pmm_free_blocks(void *p, size_t size){ - phys_addr addr = (phys_addr)p; - int frame = addr / PMM_BLOCK_SIZE; - - for(uint32_t i = 0; i < size; i++) pmm_map_unset(frame+i); - - g_pmm_used_blocks -= size; -} - -size_t pmm_get_memory_size(){ - return g_pmm_memory_size; -} - -uint32_t pmm_get_block_count(){ - return g_pmm_max_blocks; -} - -uint32_t pmm_get_used_block_count(){ - return g_pmm_used_blocks; -} - -uint32_t pmm_get_free_block_count(){ - return g_pmm_max_blocks - g_pmm_used_blocks; -} diff --git a/src/kernel/mm/pmm.h b/src/kernel/mm/pmm.h deleted file mode 100644 index be4e2c1..0000000 --- a/src/kernel/mm/pmm.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include - -#define PMM_BLOCKS_PER_BYTE 8 -#define PMM_BLOCK_SIZE 4096 -#define PMM_BLOCK_ALIGN PMM_BLOCK_SIZE - -typedef uint32_t phys_addr; - -int pmm_map_first_free(); -int pmm_map_first_free_s(size_t size); -void pmm_initialize(size_t mem_size, phys_addr bitmap); -void pmm_init_region(phys_addr base, size_t size); -void pmm_deinit_region(phys_addr base, size_t size); -void *pmm_alloc_block(); -void pmm_free_block(void *p); -void *pmm_alloc_blocks(size_t size); -void pmm_free_blocks(void *p, size_t size); -size_t pmm_get_memory_size(); -uint32_t pmm_get_block_count(); -uint32_t pmm_get_used_block_count(); -uint32_t pmm_get_free_block_count(); -void __attribute__((cdecl)) pmm_paging_enable(bool enabled); -bool __attribute__((cdecl)) pmm_is_paging(); -void __attribute__((cdecl)) pmm_load_pdbr(phys_addr addr); -phys_addr __attribute__((cdecl)) pmm_get_pdbr(); diff --git a/src/kernel/mm/pte.c b/src/kernel/mm/pte.c deleted file mode 100644 index 799168b..0000000 --- a/src/kernel/mm/pte.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "pte.h" - -void pt_entry_add_attr(pt_entry_t *entry, uint32_t attr){ - *entry |= attr; -} - -void pt_entry_del_attr(pt_entry_t *entry, uint32_t attr){ - *entry &= ~attr; -} - -void pt_entry_set_frame(pt_entry_t *entry, phys_addr frame){ - *entry = (*entry & ~PTE_FRAME) | frame; -} - -phys_addr pt_entry_get_frame(pt_entry_t entry){ - return entry & PTE_FRAME; -} - -bool pt_entry_is_present(pt_entry_t entry){ - return entry & PTE_PRESENT; -} - -bool pt_entry_is_writable(pt_entry_t entry){ - return entry & PTE_WRITABLE; -} diff --git a/src/kernel/mm/pte.h b/src/kernel/mm/pte.h deleted file mode 100644 index 445abe0..0000000 --- a/src/kernel/mm/pte.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include "pmm.h" - -enum PTE_PAGE_FLAGS{ - PTE_PRESENT = 0x0001, - PTE_WRITABLE = 0x0002, - PTE_USER = 0x0004, - PTE_WRITETHROUGH = 0x0008, - PTE_NOT_CACHEABLE = 0x0010, - PTE_ACCESSED = 0x0020, - PTE_DIRTY = 0x0040, - PTE_PAT = 0x0080, - PTE_CPU_GLOBAL = 0x0100, - PTE_LV4_GLOBAL = 0x0200, - PTE_FRAME = 0x7FFFF000 -}; - -typedef uint32_t pt_entry_t; - -void pt_entry_add_attr(pt_entry_t *entry, uint32_t attr); -void pt_entry_del_attr(pt_entry_t *entry, uint32_t attr); -void pt_entry_set_frame(pt_entry_t *entry, phys_addr frame); -phys_addr pt_entry_get_frame(pt_entry_t entry); -bool pt_entry_is_present(pt_entry_t entry); -bool pt_entry_is_writable(pt_entry_t entry); diff --git a/src/kernel/mm/vmm.c b/src/kernel/mm/vmm.c deleted file mode 100644 index 1025c5f..0000000 --- a/src/kernel/mm/vmm.c +++ /dev/null @@ -1,142 +0,0 @@ -#include "vmm.h" -#include "pmm.h" -#include "../lib/memory.h" - -vmm_page_directory_t *g_vmm_current_dir = 0; -phys_addr g_vmm_current_pdbr = 0; - -void __attribute__((cdecl)) vmm_flush_tlb_entry(virt_addr addr); - -static inline pt_entry_t *vmm_ptable_lookup_entry(vmm_page_table_t *p, virt_addr addr){ - if(p) return &p->entries[PAGE_TABLE_INDEX(addr)]; - return 0; -} - -static inline pd_entry_t *vmm_pdirectory_lookup_entry(vmm_page_directory_t *p, virt_addr addr){ - if(p) return &p->entries[PAGE_DIRECTORY_INDEX(addr)]; - return 0; -} - -static inline bool vmm_switch_pdirectory(vmm_page_directory_t *dir){ - if(!dir) return false; - - g_vmm_current_dir = dir; - pmm_load_pdbr(g_vmm_current_pdbr); - return true; -} - -static inline vmm_page_directory_t *vmm_get_pdirectory(){ - return g_vmm_current_dir; -} - -bool vmm_alloc_page(pt_entry_t *entry){ - void *p = pmm_alloc_block(); - if(!p) return false; - - pt_entry_set_frame(entry, (phys_addr)p); - pt_entry_add_attr(entry, PTE_PRESENT); - - return true; -} - -void vmm_free_page(pt_entry_t *entry){ - void *p = (void *)pt_entry_get_frame(*entry); - if(p) pmm_free_block(p); - - pt_entry_del_attr(entry, PTE_PRESENT); -} - -void vmm_map_page(void *phys, void *virt){ - // Get page directory - vmm_page_directory_t *page_dir = vmm_get_pdirectory(); - - // Get page table - pd_entry_t *e = &page_dir->entries[PAGE_DIRECTORY_INDEX((uint32_t)virt)]; - if((*e & PTE_PRESENT) != PTE_PRESENT){ - // Must allocate - vmm_page_table_t *table = (vmm_page_table_t *)pmm_alloc_block(); - if(!table) return; - - // Clear page table - memset(table, 0, sizeof(vmm_page_table_t)); - - // Create a new entry - pd_entry_t *entry = &page_dir->entries[PAGE_DIRECTORY_INDEX((uint32_t)virt)]; - - // Map in the table - pd_entry_add_attr(entry, PDE_PRESENT); - pd_entry_add_attr(entry, PDE_WRITABLE); - pd_entry_set_frame(entry, (phys_addr)table); - } - - // Get table - vmm_page_table_t *table = (vmm_page_table_t *)PAGE_GET_PHYS_ADDR(e); - - // Get page - pt_entry_t *page = &table->entries[PAGE_TABLE_INDEX((uint32_t)virt)]; - - // Map it - pt_entry_set_frame(page, (phys_addr)phys); - pt_entry_add_attr(page, PTE_PRESENT); -} - -void vmm_initialize(){ - // Allocate default page table - vmm_page_table_t *table = (vmm_page_table_t *)pmm_alloc_block(); - if(!table) return; - - // Allocate 3GB page table - vmm_page_table_t *table2 = (vmm_page_table_t *)pmm_alloc_block(); - if(!table2) return; - - // Clear default table - memset(table, 0, sizeof(vmm_page_table_t)); - - // First 4MB are identity mapped - for(int i = 0, frame = 0x0, virt = 0x00000000; i<1024; i++, frame += 4096, virt += 4096){ - // Create a new page - pt_entry_t page = 0; - pt_entry_add_attr(&page, PTE_PRESENT); - pt_entry_set_frame(&page, frame); - - // Add the page to the page table - table2->entries[PAGE_TABLE_INDEX(virt)] = page; - } - - // Map 1MB to 3GB - for(int i = 0, frame = 0x100000, virt = 0xc0000000; i<1024; i++, frame += 4096, virt += 4096){ - // Create a new page - pt_entry_t page = 0; - pt_entry_add_attr(&page, PTE_PRESENT); - pt_entry_set_frame(&page, frame); - - // Add the page to the page table - table->entries[PAGE_TABLE_INDEX(virt)] = page; - } - - // Create default directory table - vmm_page_directory_t *dir = (vmm_page_directory_t *)pmm_alloc_blocks(3); - if(!dir) return; - - // Clear directory table and set it as current - memset(dir, 0, sizeof(vmm_page_directory_t)); - - pd_entry_t *entry = &dir->entries[PAGE_DIRECTORY_INDEX(0xc0000000)]; - pd_entry_add_attr(entry, PDE_PRESENT); - pd_entry_add_attr(entry, PDE_WRITABLE); - pd_entry_set_frame(entry, (phys_addr)table); - - pd_entry_t *entry2 = &dir->entries[PAGE_DIRECTORY_INDEX(0x00000000)]; - pd_entry_add_attr(entry2, PDE_PRESENT); - pd_entry_add_attr(entry2, PDE_WRITABLE); - pd_entry_set_frame(entry2, (phys_addr)table2); - - // Store current PDBR - g_vmm_current_pdbr = (phys_addr)&dir->entries; - - // Switch to our page directory - vmm_switch_pdirectory(dir); - - // Enable paging - pmm_paging_enable(true); -} diff --git a/src/kernel/mm/vmm.h b/src/kernel/mm/vmm.h deleted file mode 100644 index 0c2bab7..0000000 --- a/src/kernel/mm/vmm.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include -#include "pte.h" -#include "pde.h" - -typedef uint32_t virt_addr; - -#define PAGES_PER_TABLE 1024 -#define PAGES_PER_DIR 1024 - -#define PAGE_DIRECTORY_INDEX(x) (((x) >> 22) & 0x3FF) -#define PAGE_TABLE_INDEX(x) (((x) >> 12) & 0x3FF) -#define PAGE_GET_PHYS_ADDR(x) (*(x) & ~0xFFF) - -#define PTABLE_ADDR_SPACE_SIZE 0x400000 -#define DTABLE_ADDR_SPACE_SIZE 0x100000000 - -#define PAGE_SIZE 4096 - -typedef struct{ - pt_entry_t entries[PAGES_PER_TABLE]; -} vmm_page_table_t; - -typedef struct{ - pd_entry_t entries[PAGES_PER_DIR]; -} vmm_page_directory_t; - -bool vmm_alloc_page(pt_entry_t *entry); -void vmm_free_page(pt_entry_t *entry); -void vmm_map_page(void *phys, void *virt); -void vmm_initialize();