aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/memory/paging.c
diff options
context:
space:
mode:
authorMarvin Borner2020-05-13 21:28:56 +0200
committerMarvin Borner2020-05-13 22:12:41 +0200
commita9c7529dcca845d98192ece62be70f752972216b (patch)
tree666d49ceb411a669abe6191151b2238fd7156c30 /src/kernel/memory/paging.c
parente1a6ed079303dc7d218f1d5326a13b6755781271 (diff)
Replaced alloc.h with liballoc
And many more adaptions to the lib
Diffstat (limited to 'src/kernel/memory/paging.c')
-rw-r--r--src/kernel/memory/paging.c236
1 files changed, 128 insertions, 108 deletions
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 <acpi/acpi.h>
-#include <interrupts/interrupts.h>
-#include <io/io.h>
#include <lib/lib.h>
#include <memory/alloc.h>
#include <memory/paging.h>
#include <stdint.h>
#include <system.h>
-#include <tasks/process.h>
-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