This source file includes following definitions.
- Debug
- GetPTIndex
- GetPDIndex
- GetPDPIndex
- GetPML4Index
- GetPT
- GetPD
- GetPDP
- VCreatePageDir
- AllocAndCreatePTE
- CreatePTEWithPT
- CreatePTE
- ClearUserMemory
- AllocPage
#include "kstructs.h"
#include "memory.h"
#include "pagetab.h"
#define VIRT(type, name) ((struct type *) ((long) name + VAddr))
extern long nPagesFree;
extern unsigned short int *PMap;
long kernelPT;
long virtualPDP;
extern struct Task *currentTask;
void Debug()
{
}
GetPTIndex(long lAddress)
{
return lAddress >> 12 & 0x1FF;
}
GetPDIndex(long lAddress)
{
return lAddress >> 21 & 0x1FF;
}
GetPDPIndex(long lAddress)
{
return lAddress >> 30 & 0x1FF;
}
GetPML4Index(long lAddress)
{
return lAddress >> 39 & 0x1FF;
}
struct PT *GetPT(struct PML4 *pml4, long lAddress, unsigned short pid)
{
int pdIndex = GetPDIndex(lAddress);
int pdpIndex = GetPDPIndex(lAddress);
int pml4Index = GetPML4Index(lAddress);
long pdp = VIRT(PML4,pml4)->entries[pml4Index].value & 0xFFFFF000;
if (!pdp)
{
long newpage = (long) AllocPage(pid);
VIRT(PML4,pml4)->entries[pml4Index].value = newpage | P | RW | US;
pdp = newpage;
}
long pd = VIRT(PDP,pdp)->entries[pdpIndex].value & 0xFFFFF000;
if (!pd)
{
long newpage = (long) AllocPage(pid);
VIRT(PDP,pdp)->entries[pdpIndex].value = newpage | P | RW | US;
pd = newpage;
}
long pt = VIRT(PD,pd)->entries[pdIndex].value & 0xFFFFF000;
if (!pt)
{
long newpage = (long) AllocPage(pid);
VIRT(PD,pd)->entries[pdIndex].value = newpage | P | RW | US;
pt = newpage;
}
return (struct PT *) (pt & 0xFFFFF000);
}
struct PD *GetPD(struct PML4 *pml4, long lAddress, unsigned short pid)
{
int pdpIndex = lAddress >> 30 & 0x1FF;
int pml4Index = lAddress >> 39 & 0x1FF;
long pdp = VIRT(PML4,pml4)->entries[pml4Index].value & 0xFFFFF000;
if (!pdp)
{
long newpage = (long) AllocPage(pid);
VIRT(PML4,pml4)->entries[pml4Index].value = newpage | P | RW | US;
pdp = newpage;
}
long pd = VIRT(PDP,pdp)->entries[pdpIndex].value & 0xFFFFF000;
if (!pd)
{
long newpage = (long) AllocPage(pid);
VIRT(PDP,pdp)->entries[pdpIndex].value = newpage | P | RW | US;
pd = newpage;
}
return (struct PD *) (pd & 0xFFFFF000);
}
struct PDP *GetPDP(struct PML4 *pml4, long lAddress, unsigned short pid)
{
int pml4Index = GetPML4Index(lAddress);
long pdp = VIRT(PML4,pml4)->entries[pml4Index].value & 0xFFFFF000;
if (!pdp)
{
long newpage = (long) AllocPage(pid);
VIRT(PML4,pml4)->entries[pml4Index].value = newpage | P | RW | US;
pdp = newpage;
}
return (struct PDP *) (pdp & 0xFFFFF000);
}
void * VCreatePageDir(unsigned short pid, unsigned short parentPid)
{
struct PML4 *pml4 = (struct PML4 *) AllocPage(pid);
VIRT(PD,GetPD(pml4, UserCode, pid))->entries[GetPDIndex(UserCode)].value =
(long) AllocPage(pid) | P | RW | US;
VIRT(PD,GetPD(pml4, UserData, pid))->entries[GetPDIndex(UserData)].value =
(long) AllocPage(pid) | P | RW | US;
VIRT(PD,GetPD(pml4, UserStack, pid))->entries[GetPDIndex(UserStack)].value =
(long) AllocPage(pid) | P | RW | US;
VIRT(PD,GetPD(pml4, KernelStack, pid))->entries[GetPDIndex(KernelStack)].value =
(long) AllocPage(pid) | P | RW;
VIRT(PML4,pml4)->entries[GetPML4Index(VAddr)].value = virtualPDP | P | RW;
struct PD *pd = GetPD(pml4, 0, pid);
VIRT(PD,pd)->entries[GetPDIndex(0)].value = kernelPT | P | RW;
if (parentPid == 0)
{
long c;
struct PT *pt = GetPT(pml4, UserData, pid);
VIRT(PT,pt)->entries[GetPTIndex(UserData)].value = AllocAndCreatePTE(
TempUserData, pid, RW | P);
c = TempUserData;
asm ("invlpg %0;"
:
:"m"(*(char *)TempUserData)
);
pt = GetPT(pml4, UserStack, pid);
VIRT(PT,pt)->entries[GetPTIndex(UserStack)].value =
AllocAndCreatePTE(TempUStack, pid, RW | P);
c = TempUStack;
asm ("invlpg %0;"
:
:"m"(*(char *)TempUStack)
);
}
else
{
struct PML4 *current_pml4 = (struct PML4 *) (currentTask->cr3
& 0xFFFF000);
struct PT *pt = GetPT(pml4, UserCode, pid);
struct PT *currentPT = GetPT(current_pml4, UserCode, parentPid);
int i = GetPTIndex(UserCode);
long c = TempUserCode;
while (VIRT(PT,currentPT)->entries[i].value)
{
VIRT(PT,pt)->entries[i].value = AllocAndCreatePTE(TempUserCode,
pid, US | RW | P);
copyMem(
((VIRT(PT, currentPT)->entries[i].value) & 0xFFFFF000)
+ VAddr,
((VIRT(PT, pt)->entries[i].value) & 0xFFFFF000) + VAddr,
PageSize);
i++;
}
pt = GetPT(pml4, UserData, pid);
currentPT = GetPT(current_pml4, UserData, parentPid);
i = GetPTIndex(UserData);
while (VIRT(PT,currentPT)->entries[i].value)
{
VIRT(PT,pt)->entries[i].value = AllocAndCreatePTE(TempUserCode,
pid, US | RW | P);
copyMem(
((VIRT(PT, currentPT)->entries[i].value) & 0xFFFFF000)
+ VAddr,
((VIRT(PT, pt)->entries[i].value) & 0xFFFFF000) + VAddr,
PageSize);
i++;
}
pt = GetPT(pml4, UserStack, pid);
currentPT = GetPT(current_pml4, UserStack, parentPid);
i = GetPTIndex(UserStack);
while (VIRT(PT,currentPT)->entries[i].value)
{
VIRT(PT,pt)->entries[i].value = AllocAndCreatePTE(TempUserCode,
pid, US | RW | P);
copyMem(
((VIRT(PT, currentPT)->entries[i].value) & 0xFFFFF000)
+ VAddr,
((VIRT(PT, pt)->entries[i].value) & 0xFFFFF000) + VAddr,
PageSize);
i--;
}
pt = GetPT(pml4, KernelStack, pid);
currentPT = GetPT(current_pml4, KernelStack, parentPid);
i = GetPTIndex(KernelStack);
while (VIRT(PT,currentPT)->entries[i].value)
{
VIRT(PT,pt)->entries[i].value = AllocAndCreatePTE(TempUserCode,
pid, US | RW | P);
copyMem(
((VIRT(PT, currentPT)->entries[i].value) & 0xFFFFF000)
+ VAddr,
((VIRT(PT, pt)->entries[i].value) & 0xFFFFF000) + VAddr,
PageSize);
i--;
}
}
return (void *) pml4;
}
long AllocAndCreatePTE(long lAddress, unsigned short pid, short flags)
{
void *pAddress = AllocPage(pid);
return CreatePTE(pAddress, lAddress, pid, flags);
}
long CreatePTEWithPT(struct PML4 *pml4, void *pAddress, long lAddress,
unsigned short pid, short flags)
{
int ptIndex = GetPTIndex(lAddress);
;
struct PT *pt = GetPT(pml4, lAddress, pid);
asm ("cli");
VIRT(PT,pt)->entries[ptIndex].value = ((long) pAddress & 0xFFFFF000)
| flags;
asm ("sti");
return ((long) pAddress | flags);
}
long CreatePTE(void *pAddress, long lAddress, unsigned short pid, short flags)
{
long retVal = 0;
struct PML4 *pml4 = (struct PML4 *) (currentTask->cr3 & 0xFFFFF000);
retVal = CreatePTEWithPT(pml4, pAddress, lAddress, pid, flags);
asm ("invlpg %0;"
:
:""(lAddress)
);
return retVal;
}
void ClearUserMemory(void)
{
struct PT *pt = GetPT((struct PML4 *) (currentTask->cr3 & 0xFFFFF000),
UserCode, currentTask->pid);
int i = 0;
while (VIRT(PT, pt)->entries[i].value)
{
PMap[VIRT(PT,pt)->entries[i].value >> 12] = 0;
VIRT(PT,pt)->entries[i++].value = 0;
}
pt = GetPT((struct PML4 *) (currentTask->cr3 & 0xFFFFF000), UserData,
currentTask->pid);
i = 0;
while (VIRT(PT, pt)->entries[i].value)
{
PMap[VIRT(PT,pt)->entries[i].value >> 12] = 0;
VIRT(PT,pt)->entries[i++].value = 0;
}
return;
}
void * AllocPage(unsigned short int PID)
{
long i = 0;
while (PMap[i] != 0)
i++;
PMap[i] = PID;
i = i << 12;
nPagesFree--;
return ((void *) i);
}