Now with arbitrary kernel page allocation.

alentours-dev
Sergiusz Bazanski 2011-02-23 05:25:28 +01:00
parent f058f250f8
commit fae1c1a4c1
5 changed files with 111 additions and 14 deletions

View File

@ -5,4 +5,5 @@
void paging_init_simple(void);
u8 paging_get_physical(u32 Virtual, u32 *Physical);
void paging_allocate_page(u32 Virtual);
#endif

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}