VM Problems
Posted: Wed Jan 17, 2007 4:20 pm
Something is wrong with this code (when I try to allocate a page, it Pagefaults). I don't know what it is. Can anyone fix it, please
[code]
extern unsigned char end;
#define VROFFSET(x) ((unsigned long)x & 0xFFF) // Phys Mem Offset // Lower 12 Bits
#define PTOFFSET(x) (((unsigned long)x & 0x003FF000) >> 12) // PT Offset // Middle 10
#define PDOFFSET(x) (((unsigned long)x & 0xFFC00000) >> 22) // PD Offset // High 10
#define TOVIRT(x) (( (unsigned long)(KeReadCR0() & 0x80000000 )!= 0) ? (unsigned long*)((x) + 0x80000000 ) : ((unsigned long*)(x)))
void KeMapAddress(unsigned long* phys, unsigned long* virt, unsigned long* pagedir, unsigned long flags) {
if(TOVIRT(pagedir)[PDOFFSET(virt)] == 0) {
TOVIRT(pagedir)[PDOFFSET(virt)] = (unsigned long)KeAllocPhysPage() | flags;
}
(TOVIRT(TOVIRT(pagedir)[PDOFFSET(virt)] & ~0xFFF))[PTOFFSET(virt)] = (unsigned long)phys | flags;
}
unsigned long* KeGetPhysAddress(unsigned long *virt, unsigned long* pagedir) {
if(TOVIRT(pagedir)[PDOFFSET(virt)] == 0)
return 0;
else
return (TOVIRT(TOVIRT(pagedir)[PDOFFSET(virt)] & ~0xFFF))[PTOFFSET(virt)] & ~0xFFF;
}
unsigned long* KeMakePageDirectory(unsigned long cpl, unsigned long memsize) {
unsigned long* pagedir = (unsigned long*)KeAllocPhysPage();
unsigned long i;
unsigned long rflags = cpl == 3 ? 5 : 1;
unsigned long rwflags = cpl == 3 ? 7 : 3;
for(i=0;i < ((unsigned long)&end / 4096 + 1) * 4096; i+= 4096) {
KeMapAddress((unsigned long*)i,(unsigned long*)i,pagedir,rwflags) ;
}
for(i=0;i < memsize && i < 0x80000000; i+= 4096) {
KeMapAddress((unsigned long*)i,(unsigned long*)i + 0x80000000,pagedir,rwflags) ; // Map first 2GB of memory into
// 80000000 area
}
return pagedir;
}
unsigned long* KeAllocPage(unsigned long* pagedir) {
if((unsigned long)pagedir == 0)
pagedir = (unsigned long*)KeReadCR3();
printf("%u",KeReadCR0() & 0x80000000 == 0);
unsigned char* curr = (unsigned char*)0x70000000;
while((((unsigned long)KeGetPhysAddress((unsigned long*)curr,pagedir)) & 1) == 0 && (unsigned long)curr < 0xE0000000)
curr += 4096;
if((unsigned long)curr == 0x80000000)
{
return 0;
}
else {
KeMapAddress(KeAllocPhysPage(),(unsigned long*)curr,pagedir, ((KeGetEFlags() & 0x3000) == 0) ? 3 : 7);
KeWriteCR3(pagedir); // Invalidates Page Directories
return (unsigned long*)curr;
}
}
void KeInitPaging(multiboot_info_t* info)
{
KeInitPhysPageMM(info->mem_lower + info->mem_upper);
unsigned long *pagedirectory=KeMakePageDirectory(0,info->mem_lower + info->mem_upper);
KeWriteCR3((unsigned long)pagedirectory);
KeWriteCR0(KeReadCR0() | 0x80000000);
}
[/code]
[code]
extern unsigned char end;
#define VROFFSET(x) ((unsigned long)x & 0xFFF) // Phys Mem Offset // Lower 12 Bits
#define PTOFFSET(x) (((unsigned long)x & 0x003FF000) >> 12) // PT Offset // Middle 10
#define PDOFFSET(x) (((unsigned long)x & 0xFFC00000) >> 22) // PD Offset // High 10
#define TOVIRT(x) (( (unsigned long)(KeReadCR0() & 0x80000000 )!= 0) ? (unsigned long*)((x) + 0x80000000 ) : ((unsigned long*)(x)))
void KeMapAddress(unsigned long* phys, unsigned long* virt, unsigned long* pagedir, unsigned long flags) {
if(TOVIRT(pagedir)[PDOFFSET(virt)] == 0) {
TOVIRT(pagedir)[PDOFFSET(virt)] = (unsigned long)KeAllocPhysPage() | flags;
}
(TOVIRT(TOVIRT(pagedir)[PDOFFSET(virt)] & ~0xFFF))[PTOFFSET(virt)] = (unsigned long)phys | flags;
}
unsigned long* KeGetPhysAddress(unsigned long *virt, unsigned long* pagedir) {
if(TOVIRT(pagedir)[PDOFFSET(virt)] == 0)
return 0;
else
return (TOVIRT(TOVIRT(pagedir)[PDOFFSET(virt)] & ~0xFFF))[PTOFFSET(virt)] & ~0xFFF;
}
unsigned long* KeMakePageDirectory(unsigned long cpl, unsigned long memsize) {
unsigned long* pagedir = (unsigned long*)KeAllocPhysPage();
unsigned long i;
unsigned long rflags = cpl == 3 ? 5 : 1;
unsigned long rwflags = cpl == 3 ? 7 : 3;
for(i=0;i < ((unsigned long)&end / 4096 + 1) * 4096; i+= 4096) {
KeMapAddress((unsigned long*)i,(unsigned long*)i,pagedir,rwflags) ;
}
for(i=0;i < memsize && i < 0x80000000; i+= 4096) {
KeMapAddress((unsigned long*)i,(unsigned long*)i + 0x80000000,pagedir,rwflags) ; // Map first 2GB of memory into
// 80000000 area
}
return pagedir;
}
unsigned long* KeAllocPage(unsigned long* pagedir) {
if((unsigned long)pagedir == 0)
pagedir = (unsigned long*)KeReadCR3();
printf("%u",KeReadCR0() & 0x80000000 == 0);
unsigned char* curr = (unsigned char*)0x70000000;
while((((unsigned long)KeGetPhysAddress((unsigned long*)curr,pagedir)) & 1) == 0 && (unsigned long)curr < 0xE0000000)
curr += 4096;
if((unsigned long)curr == 0x80000000)
{
return 0;
}
else {
KeMapAddress(KeAllocPhysPage(),(unsigned long*)curr,pagedir, ((KeGetEFlags() & 0x3000) == 0) ? 3 : 7);
KeWriteCR3(pagedir); // Invalidates Page Directories
return (unsigned long*)curr;
}
}
void KeInitPaging(multiboot_info_t* info)
{
KeInitPhysPageMM(info->mem_lower + info->mem_upper);
unsigned long *pagedirectory=KeMakePageDirectory(0,info->mem_lower + info->mem_upper);
KeWriteCR3((unsigned long)pagedirectory);
KeWriteCR0(KeReadCR0() | 0x80000000);
}
[/code]