From a9c7529dcca845d98192ece62be70f752972216b Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Wed, 13 May 2020 21:28:56 +0200 Subject: Replaced alloc.h with liballoc And many more adaptions to the lib --- src/kernel/memory/paging.c | 236 ++++++++++++++++++++++++--------------------- 1 file changed, 128 insertions(+), 108 deletions(-) (limited to 'src/kernel/memory/paging.c') diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index d538fe9..e3c088a 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -1,174 +1,194 @@ -#include -#include -#include #include #include #include #include #include -#include -struct page_directory *paging_current_directory = NULL; -struct page_directory *paging_root_directory = NULL; +int paging_enabled = 0; -/* void paging_install(u32 multiboot_address) */ -/* { */ -/* if (!memory_init(multiboot_address)) */ -/* paging_set_present(0, memory_get_all() >> 3); // /4 */ -/* paging_set_used(0, ((u32)ASM_KERNEL_END >> 12) + 1); // /4096 */ -/* } */ +u32 root_dir[1024][1024] __attribute__((aligned(4096))); +struct page_directory *paging_directory; // Current +struct page_directory *paging_kernel_directory = (struct page_directory *)root_dir; -struct page_table *get_cr3() +void paging_init(struct page_directory *dir, int user) { - u32 cr3; - asm volatile("movl %%cr3, %%eax" : "=a"(cr3)); - return (struct page_table *)cr3; -} + for (u32 i = 0; i < 1024; i++) { + for (u32 j = 0; j < 1024; j++) { + paging_directory->tables[i]->pages[j] = + ((j * 0x1000) + (i * PAGE_SIZE)) | PT_RW | (user ? PT_USER : 0); + } + } -u32 get_cr0() -{ - u32 cr0; - asm volatile("movl %%cr0, %%eax" : "=a"(cr0)); - return cr0; + for (u32 i = 0; i < 1024; i++) { + paging_directory->tables[i] = ((u32)paging_directory->tables[i]) | PD_RW | + PD_PRESENT | (user ? PD_USER : 0); + } } -void set_cr3(struct page_directory *dir) +struct page_directory *paging_make_directory(int user) { - u32 addr = (u32)&dir->tables[0]; - asm volatile("movl %%eax, %%cr3" ::"a"(addr)); + struct page_directory *dir = (struct page_directory *)malloc(sizeof(struct page_directory)); + + paging_init(dir, user); + + return dir; } -void set_cr0(u32 cr0) +extern u32 end; +void paging_install(u32 multiboot_address) { - asm volatile("movl %%eax, %%cr0" ::"a"(cr0)); + // Kernel paging + paging_switch_directory(paging_directory); + paging_init(paging_directory, 0); + + if (!memory_init(multiboot_address)) + paging_set_present(0, memory_get_all() >> 3); // /4 + paging_set_used(0, ((u32)end >> 12) + 1); // /4096 + log("Enabling"); + + paging_enable(); + log("Installed paging"); } void paging_disable() { - set_cr0(get_cr0() | 0x7fffffff); + u32 cr0; + asm("mov %%cr0, %0" : "=r"(cr0)); + cr0 &= 0x7fffffff; + asm("mov %0, %%cr0" ::"r"(cr0)); + paging_enabled = 0; } void paging_enable() { - set_cr3(paging_current_directory); - set_cr0(get_cr0() | 0x80000000); + asm("mov %0, %%cr3" ::"r"(paging_directory)); + u32 cr0; + asm("mov %%cr0, %0" : "=r"(cr0)); + cr0 |= 0x80000000; + asm("mov %0, %%cr0" ::"r"(cr0)); + paging_enabled = 1; } void paging_switch_directory(struct page_directory *dir) { - set_cr3(dir); - set_cr0(get_cr0() | 0x80000000); + paging_directory = dir; + asm("mov %0, %%cr3" ::"r"(paging_directory)); } -struct page_directory *paging_make_directory() +void invlpg(u32 addr) { - struct page_directory *dir = - (struct page_directory *)kmalloc_a(sizeof(struct page_directory)); - - for (int i = 0; i < 1024; i++) - dir->tables[i] = EMPTY_TAB; - - return dir; + asm("invlpg (%0)" ::"r"(addr) : "memory"); } -struct page_table *paging_make_table() +void paging_map(u32 phy, u32 virt, u16 flags) { - struct page_table *tab = (struct page_table *)kmalloc_a(sizeof(struct page_table)); - - for (int i = 0; i < 1024; i++) { - tab->pages[i].present = 0; - tab->pages[i].rw = 1; - } - - return tab; + u32 pdi = virt >> 22; + u32 pti = virt >> 12 & 0x03FF; + paging_directory->tables[pdi]->pages[pti] = phy | flags; + invlpg(virt); } -void paging_map(struct page_directory *dir, u32 phys, u32 virt) +u32 paging_get_phys(u32 virt) { - short id = virt >> 22; - struct page_table *tab = paging_make_table(); + u32 pdi = virt >> 22; + u32 pti = (virt >> 12) & 0x03FF; + return paging_directory->tables[pdi]->pages[pti] & 0xFFFFF000; +} - dir->tables[id] = ((struct page_table *)((u32)tab | 3)); // RW +u16 paging_get_flags(u32 virt) +{ + u32 pdi = virt >> 22; + u32 pti = (virt >> 12) & 0x03FF; + return paging_directory->tables[pdi]->pages[pti] & 0xFFF; +} - for (int i = 0; i < 1024; i++) { - tab->pages[i].frame = phys >> 12; - tab->pages[i].present = 1; - phys += 4096; +void paging_set_flag_up(u32 virt, u32 count, u32 flag) +{ + u32 page_n = virt / 0x1000; + for (u32 i = page_n; i < page_n + count; i++) { + paging_directory->tables[i / 1024]->pages[i % 1024] |= flag; + invlpg(i * 0x1000); } } -void paging_map_user(struct page_directory *dir, u32 phys, u32 virt) +void paging_set_flag_down(u32 virt, u32 count, u32 flag) { - short id = virt >> 22; - struct page_table *tab = paging_make_table(); - - dir->tables[id] = ((struct page_table *)((u32)tab | 3 | 4)); // RW + usermode - - for (int i = 0; i < 1024; i++) { - tab->pages[i].frame = phys >> 12; - tab->pages[i].present = 1; - tab->pages[i].user = 1; - phys += 4096; + u32 page_n = virt / 0x1000; + for (u32 i = page_n; i < page_n + count; i++) { + paging_directory->tables[i / 1024]->pages[i % 1024] &= ~flag; + invlpg(i * 0x1000); } } -// Hmm -u32 paging_get_phys(u32 virt) +void paging_set_present(u32 virt, u32 count) { - u32 pdi = virt >> 22; - u32 pti = (virt >> 12) & 0x03FF; - return (*(u32 *)&paging_current_directory->tables[pdi]->pages[pti]) & 0xFFFFF000; + paging_set_flag_up(virt, count, PT_PRESENT); } -void paging_install() +void paging_set_absent(u32 virt, u32 count) { - kheap_init(); - - paging_current_directory = paging_make_directory(); - paging_root_directory = paging_current_directory; + paging_set_flag_down(virt, count, PT_PRESENT); +} - for (u32 i = 0; i < 0xF0000000; i += PAGE_S) - paging_map(paging_root_directory, i, i); - paging_switch_directory(paging_root_directory); - info("Installed paging"); +void paging_set_used(u32 virt, u32 count) +{ + paging_set_flag_up(virt, count, PT_USED); +} - // Test mallocing - u32 a = (u32)kmalloc(4096); - u32 b = (u32)kmalloc(4096); - kfree((void *)b); - kfree((void *)a); - u32 c = (u32)kmalloc(2048); - assert(a == c); - info("kmalloc test succeeded!"); +void paging_set_free(u32 virt, u32 count) +{ + paging_set_flag_down(virt, count, PT_USED); } -void paging_convert_page(struct page_directory *kdir) +void paging_set_user(u32 virt, u32 count) { - for (int i = 0; i < 1024; i++) { - kdir->tables[i] = (struct page_table *)((u32)kdir->tables[i] | 4); // Usermode + u32 page_n = virt / 0x1000; + for (u32 i = page_n; i < page_n + count; i += 1024) { + paging_directory->tables[i] = ((u32)paging_directory->tables[i]) | PD_USER; + } + paging_set_flag_up(virt, count, PT_USER); +} - if (((u32)kdir->tables[i]) & 1) { // Is present - for (int j = 0; j < 1024; j++) - kdir->tables[i]->pages[j].user = 1; // Usermode +u32 paging_find_pages(u32 count) +{ + u32 continuous = 0; + u32 start_dir = 0; + u32 start_page = 0; + for (u32 i = 0; i < 1024; i++) { + for (u32 j = 0; j < 1024; j++) { + if (!(paging_directory->tables[i]->pages[j] & PT_PRESENT) || + (paging_directory->tables[i]->pages[j] & PT_USED)) { + continuous = 0; + start_dir = i; + start_page = j + 1; + } else { + if (++continuous == count) + return (start_dir * 0x400000) + (start_page * 0x1000); + } } } + + panic("Out of memory!"); + return 0; } -struct page_directory *paging_copy_user_directory(struct page_directory *dir) +u32 paging_alloc_pages(u32 count) { - struct page_directory *copy = paging_make_directory(); - memcpy(copy, paging_root_directory, sizeof(struct page_directory)); + u32 ptr = paging_find_pages(count); + paging_set_used(ptr, count); + paging_set_user(ptr, count); + return ptr; +} +u32 paging_get_used_pages() +{ + u32 n = 0; for (u32 i = 0; i < 1024; i++) { - if (((u32)dir->tables[i]) & 4) { - struct page_table *tab = - (struct page_table *)((u32)dir->tables[i] & 0xFFFFF000); - - void *buffer = kmalloc_a(PAGE_S); - memcpy(buffer, (void *)(tab->pages[0].frame << 12), PAGE_S); - paging_map_user(copy, (u32)buffer, (u32)i << 22); + for (u32 j = 0; j < 1024; j++) { + u8 flags = paging_directory->tables[i]->pages[j] & PT_USED; + if (flags == 1) + n++; } } - - return copy; + return n; } \ No newline at end of file -- cgit v1.2.3