New dynamic paging implementation (2)
This commit is contained in:
parent
9fde358447
commit
2677c200f5
|
@ -136,7 +136,7 @@ static inline ulong KeReadStsc(void) {
|
|||
return ((ulong)edx << 32) + eax;
|
||||
}
|
||||
|
||||
static inline void KeFlushTlbSingle(unsigned long addr)
|
||||
static inline void KeFlushTlbSingle(ulong addr)
|
||||
{
|
||||
asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
|
||||
}
|
||||
|
|
|
@ -158,6 +158,9 @@ extern void MmLoadGdt(GdtPtr_t *gdtPtr, ushort tssOffset);
|
|||
//
|
||||
extern void MmStoreGdt(void);
|
||||
|
||||
//
|
||||
// Paging misc
|
||||
//
|
||||
void MmInitPaging(void);
|
||||
|
||||
void MmActivatePageHandler(void);
|
||||
|
@ -168,9 +171,10 @@ void MmActivatePageHandler(void);
|
|||
void *MmGetStackGuards(char rank);
|
||||
|
||||
//
|
||||
// Translate a virtual address into physical address
|
||||
// Translate a virtual address into physical address and the opposite
|
||||
//
|
||||
void *MmTranslateKPageToAddr(void *rank);
|
||||
void *MmTransVirtToPhyAddr(void*);
|
||||
void *MmTransPhyToVirtAddr(void* virtualAddr);
|
||||
|
||||
// Page table entry
|
||||
typedef ulong pte_t;
|
||||
|
@ -188,7 +192,6 @@ typedef pdpe_t* pml4_t;
|
|||
void MmLoadPML4(void *);
|
||||
void MmEnableWriteProtect(void);
|
||||
void MmDisableWriteProtect(void);
|
||||
void *MmGetStackGuards(char rank);
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
|
|
@ -7,12 +7,11 @@
|
|||
#include <lib/buf.h>
|
||||
#include <io/vga.h>
|
||||
|
||||
#define USERSPACE 0x40000000
|
||||
#define USERSPACE 0x80000000
|
||||
|
||||
//-----------
|
||||
|
||||
volatile pml4_t MmPageMapLevel4[512] __attribute__((__aligned__(KPAGESIZE)));
|
||||
volatile pml4_t MmPageMapLevel4Unmasked[512] __attribute__((__aligned__(KPAGESIZE)));
|
||||
|
||||
extern ulong _text;
|
||||
extern ulong _text_end;
|
||||
|
@ -34,7 +33,7 @@ enum
|
|||
ACCESSED = 1 << 5,
|
||||
DIRTY = 1 << 6,
|
||||
HUGE = 1 << 7,
|
||||
NX = 1 << 31
|
||||
NX = 1UL << 63
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -43,9 +42,9 @@ enum
|
|||
void MmInitPaging(void)
|
||||
{
|
||||
extern MemoryMap_t memoryMap;
|
||||
pdpe_t *MmPDP;
|
||||
pde_t *MmPD;
|
||||
pte_t *MmPT;
|
||||
pdpe_t *MmPDP = NULL;
|
||||
pde_t *MmPD = NULL;
|
||||
pte_t *MmPT = NULL;
|
||||
ulong index;
|
||||
ulong lastKernelAddr = (ulong)(_heap_start + _heap_max);
|
||||
ulong firstDirectoryAddr = 0;
|
||||
|
@ -63,8 +62,6 @@ void MmInitPaging(void)
|
|||
DebugLog("\tPaging gap : %u MB (%p)\n\tLast virtual address %p\n", diffKernUsr / MB, diffKernUsr, MmVirtLastAddress);
|
||||
|
||||
memzero((void *)&MmPageMapLevel4[0], sizeof(MmPageMapLevel4));
|
||||
memzero((void *)&MmPageMapLevel4Unmasked[0], sizeof(MmPageMapLevel4));
|
||||
|
||||
|
||||
for (ulong curAddrPML4 = 0;
|
||||
curAddrPML4 < MmVirtLastAddress;
|
||||
|
@ -139,36 +136,123 @@ void MmInitPaging(void)
|
|||
}
|
||||
// SECTION .DATA PROTECTION
|
||||
else if ((ulong)curAddrPT >= (ulong)&_data && (ulong)curAddrPT <= (ulong)&_data_end) {
|
||||
MmPT[index] = (ulong)curAddrPT | PRESENT | WRITETHR | READWRITE;
|
||||
MmPT[index] = (ulong)curAddrPT | PRESENT | WRITETHR | READWRITE | NX;
|
||||
//DebugLog("\tSection .data at %p\n", curAddrPT);
|
||||
}
|
||||
// SECTION .RODATA PROTECTION
|
||||
else if ((ulong)curAddrPT >= (ulong)&_rodata && (ulong)curAddrPT <= (ulong)&_rodata_end) {
|
||||
MmPT[index] = (ulong)curAddrPT | PRESENT | WRITETHR;
|
||||
MmPT[index] = (ulong)curAddrPT | PRESENT | WRITETHR | NX;
|
||||
//DebugLog("\tSection .rodata at %p\n", curAddrPT);
|
||||
}
|
||||
// While we're inside the kernel pages
|
||||
else if ((ulong)curAddrPT <= lastKernelAddr) {
|
||||
MmPT[index] = (ulong)curAddrPT | PRESENT | READWRITE;
|
||||
}
|
||||
else if ((ulong)curAddrPT >= USERSPACE) {
|
||||
MmPT[index] = ((ulong)curAddrPT - diffKernUsr) | READWRITE | USERMODE; // Not present for instance
|
||||
|
||||
if ((ulong)curAddrPT == USERSPACE) {
|
||||
DebugLog("\tMapped userspace at %p\n", curAddrPT);
|
||||
if ((ulong)curAddrPT == lastKernelAddr) {
|
||||
DebugLog("\tLast page of kernel at %p\n", curAddrPT);
|
||||
}
|
||||
}
|
||||
// While we're inside the userspace pages
|
||||
else if ((ulong)curAddrPT >= USERSPACE) {
|
||||
MmPT[index] = ((ulong)curAddrPT); // Not present for instance
|
||||
|
||||
if ((ulong)curAddrPT == USERSPACE) {
|
||||
DebugLog("\tUserspace at %p:%p\n", curAddrPT, curAddrPT + diffKernUsr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
MmPT[index] = 0;
|
||||
}
|
||||
|
||||
KeFlushTlbSingle(curAddrPT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lastDirectoryAddr = MmPT;
|
||||
lastDirectoryAddr = (ulong)MmPT;
|
||||
|
||||
MmLoadPML4((void *)MmPageMapLevel4);
|
||||
//MmEnableWriteProtect();
|
||||
|
||||
MmEnableWriteProtect();
|
||||
DebugLog("\tPage table size : %u MB\n", (lastDirectoryAddr - firstDirectoryAddr)/MB);
|
||||
}
|
||||
|
||||
//
|
||||
// Translates a virtual address to its physical equivalent
|
||||
//
|
||||
void *MmTransVirtToPhyAddr(void* virtualAddr)
|
||||
{
|
||||
ulong virtAddrPage = (ulong)virtualAddr & ( ~(KPAGESIZE - 1));
|
||||
|
||||
if (virtAddrPage > MmVirtLastAddress) {
|
||||
KeStartPanic("MmTransVirtToPhyAddr() Out of bound of the address space !");
|
||||
}
|
||||
|
||||
pdpe_t *pdp = (pdpe_t*)((ulong)MmPageMapLevel4[(virtAddrPage / ((ulong)KPAGESIZE * 0x8000000)) % 512] & ~(KPAGESIZE - 1));
|
||||
DebugLog("pdp : %p\n", pdp);
|
||||
pde_t *pd = (pde_t*)( (ulong)pdp[(virtAddrPage / ((ulong)KPAGESIZE * 0x40000)) % 512] & ~(KPAGESIZE - 1));
|
||||
DebugLog("pd : %p\n", pd);
|
||||
pte_t *pt = (pte_t*)( (ulong)pd[(virtAddrPage / ((ulong)KPAGESIZE * 0x200)) % 512] & ~(KPAGESIZE - 1));
|
||||
DebugLog("pt : %p\n", pt);
|
||||
|
||||
ulong page = (ulong)pt[(virtAddrPage / ((ulong)KPAGESIZE)) % 512];
|
||||
DebugLog("page : %p\n", page);
|
||||
|
||||
if (page == (page & ~(KPAGESIZE - 1))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void*)((page & ~(KPAGESIZE - 1))+ ((ulong)virtualAddr - (ulong)virtAddrPage));
|
||||
}
|
||||
|
||||
void *MmTransPhyToVirtAddr(void* physicalAddr)
|
||||
{
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
//
|
||||
// Add flags to a page
|
||||
//
|
||||
void MmSetPage(void* virtualAddr, ulong flags)
|
||||
{
|
||||
ulong virtAddrPage = (ulong)virtualAddr & ( ~(KPAGESIZE - 1));
|
||||
|
||||
if (virtAddrPage > MmVirtLastAddress) {
|
||||
KeStartPanic("MmSetPage() Out of bound of the address space !");
|
||||
}
|
||||
|
||||
pdpe_t *pdp = (pdpe_t*)((ulong)MmPageMapLevel4[virtAddrPage / ((ulong)KPAGESIZE * 0x8000000)] & ~(KPAGESIZE - 1));
|
||||
pde_t *pd = (pde_t*)( (ulong)pdp[virtAddrPage / ((ulong)KPAGESIZE * 0x40000)] & ~(KPAGESIZE - 1));
|
||||
pte_t *pt = (pte_t*)( (ulong)pd[virtAddrPage / ((ulong)KPAGESIZE * 0x200)] & ~(KPAGESIZE - 1));
|
||||
|
||||
pt[virtAddrPage / ((ulong)KPAGESIZE)] |= flags;
|
||||
|
||||
KeFlushTlbSingle(virtAddrPage);
|
||||
}
|
||||
|
||||
//
|
||||
// Remove flags of a page
|
||||
//
|
||||
void MmUnsetPage(void* virtualAddr, ulong flags)
|
||||
{
|
||||
ulong virtAddrPage = (ulong)virtualAddr & ( ~(KPAGESIZE - 1));
|
||||
|
||||
if (virtAddrPage > MmVirtLastAddress) {
|
||||
KeStartPanic("MmUnsetPage() Out of bound of the address space !");
|
||||
}
|
||||
|
||||
pdpe_t *pdp = (pdpe_t*)((ulong)MmPageMapLevel4[virtAddrPage / ((ulong)KPAGESIZE * 0x8000000)] & ~(KPAGESIZE - 1));
|
||||
pde_t *pd = (pde_t*)( (ulong)pdp[virtAddrPage / ((ulong)KPAGESIZE * 0x40000)] & ~(KPAGESIZE - 1));
|
||||
pte_t *pt = (pte_t*)( (ulong)pd[virtAddrPage / ((ulong)KPAGESIZE * 0x200)] & ~(KPAGESIZE - 1));
|
||||
|
||||
pt[virtAddrPage / ((ulong)KPAGESIZE)] &= (~flags);
|
||||
|
||||
KeFlushTlbSingle(virtAddrPage);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the rank of the Stack Guards
|
||||
//
|
||||
void *MmGetStackGuards(char rank)
|
||||
{
|
||||
return (void *)MmStackGuards[(int)rank];
|
||||
|
@ -227,7 +311,7 @@ static void PagingHandler(ISRFrame_t *regs)
|
|||
);
|
||||
} else {
|
||||
//XXX page fault
|
||||
bprintf(BStdOut, "\n\n%CPANICC\n[ISR 0x8] Irrecoverable Kernel Page Fault at %p\n\n"
|
||||
bprintf(BStdOut, "\n\n%CPANIC\n[ISR 0x8] Irrecoverable Kernel Page Fault at %p\n\n"
|
||||
" Error code : 0x%x (%b)",
|
||||
|
||||
VGA_COLOR_LIGHT_RED,
|
||||
|
|
|
@ -189,12 +189,40 @@ error_t CmdHelpTest(int argc, char **argv, char *cmdline)
|
|||
return EOK;
|
||||
}
|
||||
|
||||
error_t CmdPageTranslateVirtToPhy(int argc, char **argv, char *cmdline)
|
||||
{
|
||||
void *address = (void*)atoul(argv[1]);
|
||||
|
||||
if (!(void*)atoul(argv[1])) {
|
||||
address = (void *)0x80000001;
|
||||
}
|
||||
|
||||
void *translation = MmTransVirtToPhyAddr(address);
|
||||
|
||||
KernLog("Translation of %p is %p\n", address, translation);
|
||||
return EOK;
|
||||
}
|
||||
|
||||
error_t CmdPageTranslatePhyToVirt(int argc, char **argv, char *cmdline)
|
||||
{
|
||||
void *address = (void*)atoul(argv[1]);
|
||||
|
||||
/* if (!(void*)atoul(argv[1])) { */
|
||||
/* address = (ulong *)0x80000000; */
|
||||
/* } */
|
||||
|
||||
void *translation = MmTransPhyToVirtAddr(address);
|
||||
|
||||
KernLog("Translation of %p is %p\n", address, translation);
|
||||
return EOK;
|
||||
}
|
||||
|
||||
error_t CmdPF(int argc, char **argv, char *cmdline)
|
||||
{
|
||||
ulong *address = (ulong*)(ulong)atoul(argv[1]);
|
||||
|
||||
if (!address) {
|
||||
address = (ulong *)0x12fdc3000 - 1 ;
|
||||
address = (ulong *)0x80000000;
|
||||
}
|
||||
|
||||
KernLog("Provoking Page Fault at %#x\n", address);
|
||||
|
@ -253,6 +281,10 @@ static Command_t testcmdtable[] =
|
|||
{ "dmp", CmdDumpMem, "Dump 1MB of memory starting from addr"},
|
||||
{ "help", CmdHelpTest, "Show this message" },
|
||||
{ "div", CmdFloatDiv, "Float div. Usage : div a b. Returns a/b"},
|
||||
{ "transvtp", CmdPageTranslateVirtToPhy, "Translate a virtual to"
|
||||
" physical address (paging)"},
|
||||
{ "transptv", CmdPageTranslatePhyToVirt, "Translate a physical to"
|
||||
" virtual address (paging)"},
|
||||
{ "pf", CmdPF, "Provoke a PF. Usage: pfault <address>"},
|
||||
{ "shell", CmdShell, "Start a new shell (nested)", },
|
||||
{ "stkov", CmdStackOverflow, "Provoke a stack overflow" },
|
||||
|
|
Loading…
Reference in New Issue