From fae1c1a4c1f75c0db2483417b1342d15f85afb69 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Wed, 23 Feb 2011 05:25:28 +0100 Subject: [PATCH] Now with arbitrary kernel page allocation. --- include/Tier0/paging.h | 1 + include/Tier0/system.h | 1 + src/Tier0/kmain.c | 6 +++ src/Tier0/paging.c | 95 +++++++++++++++++++++++++++++++++++------- src/Tier0/system.c | 22 ++++++++++ 5 files changed, 111 insertions(+), 14 deletions(-) diff --git a/include/Tier0/paging.h b/include/Tier0/paging.h index 6b739b6..c0490fd 100644 --- a/include/Tier0/paging.h +++ b/include/Tier0/paging.h @@ -5,4 +5,5 @@ void paging_init_simple(void); u8 paging_get_physical(u32 Virtual, u32 *Physical); +void paging_allocate_page(u32 Virtual); #endif diff --git a/include/Tier0/system.h b/include/Tier0/system.h index cb924a8..368aebc 100644 --- a/include/Tier0/system.h +++ b/include/Tier0/system.h @@ -21,5 +21,6 @@ void system_parse_multiboot_header(void *Header); u32 system_get_memory_upper(void); u32 system_get_memory_lower(void); s8 *system_get_bootloader_name(void); +u8 system_memory_available(u32 Start, u32 Length); #endif diff --git a/src/Tier0/kmain.c b/src/Tier0/kmain.c index e1dbba0..9b26909 100644 --- a/src/Tier0/kmain.c +++ b/src/Tier0/kmain.c @@ -45,4 +45,10 @@ void kmain(void *MultibootHeader, u32 Magic) } interrupts_init_simple(); + + paging_allocate_page(0xDEADBEEF); + u32 *Beef = (u32*)0xDEADBEEF; + *Beef = 13371337; + + kprintf("Beef: %u\n", *Beef); } diff --git a/src/Tier0/paging.c b/src/Tier0/paging.c index 3d2cc0e..e789796 100644 --- a/src/Tier0/paging.c +++ b/src/Tier0/paging.c @@ -1,9 +1,15 @@ #include "Tier0/paging.h" +#include "Tier0/system.h" #include "Tier0/kstdio.h" #include "types.h" +// 10 megabytes is safe guess, I guess. +#define PAGING_FREEFORALL_START 0x00F00000 + u32 g_kernel_page_directory[1024] __attribute__ ((aligned (4096))); -u32 g_low_page_table[1024] __attribute__ ((aligned (4096))); +u32 g_kernel_page_tables[1024][1024] __attribute__ ((aligned (4096))); + +u32 g_paging_current_offset = PAGING_FREEFORALL_START; u8 paging_get_physical(u32 Virtual, u32 *Physical) { @@ -37,28 +43,89 @@ void paging_dump_directory(void) { for (u32 i = 0; i < 10; i++) { - kprintf("[i] Virtual 0x%X - 0x%X, Entry 0x%X.\n", i * 4096 * 1024, \ - (i + 1) * 4096 * 1024, g_kernel_page_directory[i] & 0xFFFFF000); + kprintf("[i] Virtual 0x%X - 0x%X, Table 0x%X.\n", i * 4096 * 1024, \ + (i + 1) * 4096 * 1024, g_kernel_page_directory[i]); } } +// Hey, Serge, or whoever will read this. +// +// Do NOT modify me to be used in user processes. I know it may be tempting to +// do so, but don't. I'm dead serious. +// +// This is strictly (!) kernel-only. This assumes that the tables are already +// created. If we were to create an empty set of tables, it would mean wasting +// 1MB of memory for each process - and that's a Bad Thing. However, we can +// permit ourselves to do this for the kernel. Heck, it's necessary - we need +// solid paging to make a solid heap which will enable us to create dynamic +// page tables for user processes. Woo. + +// This maps 4KB +void paging_map_kernel_page(u32 Virtual, u32 Physical) +{ + u16 DirectoryIndex = (Virtual >> 22) & 0x3FF; + + // Set directory entry to available + u32 *DirectoryEntry = &g_kernel_page_directory[DirectoryIndex]; + *DirectoryEntry |= 0x03; + + u16 TableIndex = (Virtual >> 12) & 0x3FF; + + u32 *TableEntry = &g_kernel_page_tables[DirectoryIndex][TableIndex]; + + + *TableEntry = 0; + // Set to present and writable + *TableEntry |= 0x3; + // Set to point to the physical address. + *TableEntry |= (Physical & 0xFFFFF000); +} + + +// This maps 4MB +void paging_map_kernel_table(u32 Virtual, u32 Physical) +{ + for (u16 i = 0; i < 1024; i++) + paging_map_kernel_page(Virtual + i * 0x1000, Physical + i * 0x1000); +} + void paging_init_simple(void) { - void *RealKernelPageDir = (u8 *)g_kernel_page_directory + 0x40000000; - void *RealLowPageTable = (u8 *)g_low_page_table + 0x40000000; + // Initialize the directory + for (u16 i = 0; i < 1024; i++) + g_kernel_page_directory[i] = (((u32)g_kernel_page_tables[i]) \ + + 0x40000000); - for (u16 i = 0; i < 1024; i++) - { - g_low_page_table[i] = (i * 4096) | 0x03; - g_kernel_page_directory[i] = 0; - } + // Initialize the kernel mappings (0..8MB and 3072..3080MB + paging_map_kernel_table(0x00000000, 0x00000000); + paging_map_kernel_table(0x00400000, 0x00400000); - g_kernel_page_directory[0] = (u32)RealLowPageTable | 0x03; - g_kernel_page_directory[768] = (u32)RealLowPageTable | 0x03; - + paging_map_kernel_table(0xC0000000, 0x00000000); + paging_map_kernel_table(0xC0400000, 0x00400000); + + void *PhysicalDirectory = (u8 *)g_kernel_page_directory + \ + 0x40000000; __asm volatile ( "mov %0, %%eax\n" "mov %%eax, %%cr3\n" "mov %%cr0, %%eax\n" "orl $0x80000000, %%eax\n" - "mov %%eax, %%cr0\n" :: "m" (RealKernelPageDir)); + "mov %%eax, %%cr0\n" :: "m" (PhysicalDirectory)); +} + +// This allocates a 4kb page for whatever reason +void paging_allocate_page(u32 Virtual) +{ + u32 MaximumAddress = system_get_memory_upper(); + while (!system_memory_available(g_paging_current_offset, 0x1000)) + { + g_paging_current_offset += 0x1000; + if (g_paging_current_offset > MaximumAddress) + { + kprintf("[e] Fatal error: out of memory!\n"); + for (;;) {} + } + } + + paging_map_kernel_page(Virtual, g_paging_current_offset); + g_paging_current_offset += 0x1000; } diff --git a/src/Tier0/system.c b/src/Tier0/system.c index 361648c..89e2832 100644 --- a/src/Tier0/system.c +++ b/src/Tier0/system.c @@ -76,3 +76,25 @@ s8 *system_get_bootloader_name(void) { return g_system_bootloader; } + +u8 system_memory_available(u32 Start, u32 Length) +{ + for (u8 i = 0; i < g_system_num_invalid_areas; i++) + { + T_SYSTEM_INVALID_RAM Area = g_system_invalid_areas[i]; + + // If the start address is somwhere in the invalid area + if (Area.Base <= Start && Area.Base + Area.Size > Start) + return 0; + + // If the end address is somewhere in the invalid area + if (Area.Base <= Start + Length && Area.Base + Area.Size > Start + Length) + return 0; + + // If the request spans accross an invalid area + if (Area.Base >= Start && Start + Length < Area.Base + Area.Size) + return 0; + } + return 1; +} +