Cucumber/Kernel/src/Tier0/paging.c

201 lines
5.8 KiB
C
Raw Normal View History

2011-02-21 11:23:58 +00:00
#include "Tier0/paging.h"
2011-02-21 16:29:53 +00:00
#include "Tier0/kstdio.h"
2011-03-31 10:21:32 +00:00
#include "Tier0/kstdlib.h"
2011-02-21 11:23:58 +00:00
#include "types.h"
2011-07-02 11:03:29 +00:00
// The basic structures for the first kernel thread...
// Since they are < 2Mib, their virtual addresses = their physical addresses -
// some offset given by the loader
//T_PAGING_ML4 g_paging_basic_ml4;
// These are the structures for mapping the lowest 2MiB
//T_PAGING_ML4 g_paging_basic_dpt_lowmap;
//T_PAGING_ML4 g_paging_basic_dir_lowmap;
//T_PAGING_ML4 g_paging_basic_tab_lowmap;
// These are the structures for mapping the kernel memory (2Mib)
//T_PAGING_ML4 g_paging_basic_dpt_kernel;
//T_PAGING_ML4 g_paging_basic_dir_kernel;
//T_PAGING_ML4 g_paging_basic_tab_kernel;
T_PAGING_ML4 *paging_get_ml4(void)
{
u64 Address;
__asm__ volatile("mov %%cr3, %0\n" : "=r"(Address));
return (T_PAGING_ML4*)Address;
}
2011-07-02 11:03:29 +00:00
u8 paging_get_physical_ex(u64 Virtual, u64 *Physical, T_PAGING_ML4 *ML4)
2011-02-21 16:29:53 +00:00
{
2011-07-02 11:03:29 +00:00
u16 ML4Index = PAGING_GET_ML4_INDEX(Virtual);
u16 DPTIndex = PAGING_GET_DPT_INDEX(Virtual);
u16 DirIndex = PAGING_GET_DIR_INDEX(Virtual);
u16 TabIndex = PAGING_GET_TAB_INDEX(Virtual);
2011-02-21 16:29:53 +00:00
2011-07-02 11:03:29 +00:00
if (!ML4->Entries[ML4Index].Present)
return 1;
2011-02-21 16:29:53 +00:00
2011-07-02 11:03:29 +00:00
T_PAGING_DPT *DPT = ML4->Children[ML4Index];
2011-02-21 16:29:53 +00:00
2011-07-02 11:03:29 +00:00
if (!DPT->Entries[DPTIndex].Present)
return 1;
T_PAGING_DIR *Dir = DPT->Children[DPTIndex];
if (!Dir->Entries[DirIndex].Present)
return 1;
2011-02-21 16:29:53 +00:00
2011-07-02 11:03:29 +00:00
T_PAGING_TAB *Tab = Dir->Children[DirIndex];
2011-02-22 17:09:58 +00:00
2011-07-02 11:03:29 +00:00
if (!Tab->Entries[TabIndex].Present)
return 1;
(*Physical) = (Tab->Entries[TabIndex].Physical << 12) + PAGING_GET_PAGE_OFFSET(Virtual);
return 0;
2011-02-22 17:09:58 +00:00
}
2011-02-21 16:29:53 +00:00
2011-07-02 11:03:29 +00:00
u8 paging_get_physical(u64 Virtual, u64 *Physical)
2011-03-18 14:09:49 +00:00
{
2011-07-02 11:03:29 +00:00
T_PAGING_ML4 *ml4 = paging_get_ml4();
return paging_get_physical_ex(Virtual, Physical, ml4);
return 0;
2011-03-18 14:09:49 +00:00
}
2011-07-02 11:03:29 +00:00
// This initializes a very basic paging structure for the first kernel thread
void paging_init_simple(u64 PhysicalVirtualOffset)
{
}
/*void paging_dump_directory(void)
2011-02-21 16:29:53 +00:00
{
for (u32 i = 0; i < 10; i++)
{
kprintf("[i] Virtual 0x%X - 0x%X, Table 0x%X.\n", i * 4096 * 1024, \
2011-03-18 14:09:49 +00:00
(i + 1) * 4096 * 1024, g_kernel_page_directory.Entries[i]);
2011-02-21 16:29:53 +00:00
}
}
// 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)
2011-02-21 11:23:58 +00:00
{
u16 DirectoryIndex = (Virtual >> 22) & 0x3FF;
// Set directory entry to available
2011-03-18 14:09:49 +00:00
u32 *DirectoryEntry = &g_kernel_page_directory.Entries[DirectoryIndex];
*DirectoryEntry |= 0x03;
u16 TableIndex = (Virtual >> 12) & 0x3FF;
2011-03-18 14:09:49 +00:00
T_PAGING_PAGE *Page = &g_kernel_page_tables[DirectoryIndex].Pages[TableIndex];
2011-03-18 14:09:49 +00:00
*((u32*)Page) = 0;
Page->Present = 1;
Page->RW = 1;
Page->Physical = (Physical & 0xFFFFF000) >> 12;
2011-03-31 10:21:32 +00:00
// Flush the TLB
__asm__ volatile("invlpg %0" :: "m" (Virtual));
}
2011-03-31 10:21:32 +00:00
void paging_map_page(u32 Virtual, u32 Physical, T_PAGING_DIRECTORY *Directory,
u8 User, u8 RW)
{
u16 DirectoryIndex = (Virtual >> 22) & 0x3FF;
u32 Entry = Directory->Entries[DirectoryIndex];
u8 TablePresent = (Entry & 0x01) > 0;
if (!TablePresent)
{
u32 NewTablePhysical;
T_PAGING_TABLE *NewTable = (T_PAGING_TABLE*)kmalloc_p(
sizeof(T_PAGING_TABLE), 1, &NewTablePhysical);
kmemsetw((void*)NewTable, 0, 1024);
u32 *Entry = &Directory->Entries[DirectoryIndex];
*Entry = 1;
*Entry |= (RW << 1);
2011-04-01 13:21:31 +00:00
*Entry |= (User << 2);
2011-03-31 10:21:32 +00:00
*Entry |= ((u32)NewTable);
Directory->Tables[DirectoryIndex] = NewTable;
}
T_PAGING_TABLE *Table = Directory->Tables[DirectoryIndex];
u16 TableIndex = (Virtual >> 12) & 0x3FF;
T_PAGING_PAGE *Page = &Table->Pages[TableIndex];
*((u32*)Page) = 1;
Page->User = User;
Page->RW = RW;
Page->Physical = (Physical & 0xFFFFF000) >> 12;
// Flush the TLB
__asm__ volatile("invlpg %0" :: "m" (Virtual));
}
// This maps 4MB
void paging_map_kernel_table(u32 Virtual, u32 Physical)
{
2011-02-21 11:23:58 +00:00
for (u16 i = 0; i < 1024; i++)
paging_map_kernel_page(Virtual + i * 0x1000, Physical + i * 0x1000);
}
2011-03-31 10:21:32 +00:00
void paging_use_directory(T_PAGING_DIRECTORY *Directory)
{
__asm volatile ( "mov %0, %%eax\n"
"mov %%eax, %%cr3\n"
"mov %%cr0, %%eax\n"
"orl $0x80000000, %%eax\n"
"mov %%eax, %%cr0\n" :: "m" (Directory->PhysicalAddress));
}
2011-04-03 16:49:04 +00:00
T_PAGING_DIRECTORY *paging_get_directory(void)
{
u32 Address;
__asm__ volatile("mov %%cr3, %%eax\n"
"mov %%eax, %0\n" : "=r"(Address));
return (T_PAGING_DIRECTORY *)Address;
}
void paging_init_simple(void)
{
// Initialize the directory
for (u16 i = 0; i < 1024; i++)
2011-03-18 14:09:49 +00:00
{
g_kernel_page_directory.Entries[i] = (((u32)&g_kernel_page_tables[i])
+ 0x40000000);
2011-03-18 14:09:49 +00:00
g_kernel_page_directory.Tables[i] = &g_kernel_page_tables[i];
}
2011-03-31 10:21:32 +00:00
g_kernel_page_directory.PhysicalAddress =
(u32)g_kernel_page_directory.Entries + 0x40000000;
// Initialize the kernel mappings (0..8MB and 3072..3080MB
paging_map_kernel_table(0x00000000, 0x00000000);
paging_map_kernel_table(0x00400000, 0x00400000);
2011-02-21 11:23:58 +00:00
paging_map_kernel_table(0xC0000000, 0x00000000);
paging_map_kernel_table(0xC0400000, 0x00400000);
2011-03-31 10:21:32 +00:00
paging_use_directory(&g_kernel_page_directory);
2011-07-02 11:03:29 +00:00
}*/