I'm having problems implementing basic paging.
What I'm trying to do is identity mapping all available memory just to test if it works correctly.
I've tried all sorts of different solutions I could think off, but no result...
The kernel initializes a GDT (for code and data, base=0 and limit=4G) and calls kPagingSetup(32000);
Could you please help me find out where the problem is ?
paging.h
Code: Select all
typedef struct page_t
{
unsigned long int present : 1;
unsigned long int rw : 1;
unsigned long int user : 1;
unsigned long int accessed : 1;
unsigned long int dirty : 1;
unsigned long int unused : 7 ;
unsigned long int frame : 20;
} __attribute__((packed)) page;
typedef struct pagetable_t
{
page pages[1024];
} pagetable;
typedef struct pagedir_t
{
pagetable* tables[1024];
} pagedir;
void kPagingAllocateFrame(pagedir* dir, unsigned long int addr, int user, int writable);
void kPagingFreeFrame(pagedir* dir, unsigned long int addr);
void kPagingSetup(unsigned long int end_mem);
void kPagingSwitchPagedir(pagedir* pd);
paging.c
Code: Select all
pagedir* kdir=0;
void kPagingAllocateFrame(pagedir* dir, unsigned long int addr, int user, int writable)
{
// Compute offsets
unsigned long int pdoffset = (addr & 0xFFC00000) >> 22;
unsigned long int ptoffset = (addr & 0x3FF000) >> 12;
if(dir->tables[pdoffset] != 0)
{
if(dir->tables[pdoffset]->pages[ptoffset].present == 1)
{
return; // Page already allocated
}
else
{
mmap_map(addr);
dir->tables[pdoffset]->pages[ptoffset].present = 1;
dir->tables[pdoffset]->pages[ptoffset].rw = 1;
dir->tables[pdoffset]->pages[ptoffset].user = 1;
dir->tables[pdoffset]->pages[ptoffset].frame = (addr & 0xFFFFF000) >> 12;
}
}
else
{
pagetable* pt;
pt = (pagetable*) kmalloc_a(sizeof(pagetable));
memzero(pt, sizeof(pagetable));
dir->tables[pdoffset] = pt;
mmap_map(addr);
dir->tables[pdoffset]->pages[ptoffset].present = 1;
dir->tables[pdoffset]->pages[ptoffset].rw = 1;
dir->tables[pdoffset]->pages[ptoffset].user = 1;
dir->tables[pdoffset]->pages[ptoffset].frame = (addr & 0xFFFFF000) >> 12;
}
}
void kPagingFreeFrame(pagedir* dir, unsigned long int addr)
{
unsigned long int pdoffset = (addr & 0xFFC00000) >> 22;
unsigned long int ptoffset = (addr & 0x3FF000) >> 12;
if(dir->tables[pdoffset]->pages[ptoffset].present == 0)
return;
mmap_unmap(addr);
dir->tables[pdoffset]->pages[ptoffset].present = 0;
}
void kPagingSetup(unsigned long int end_mem)
{
end_mem *= 1024; // Convert end_mem from KBytes to bytes
// Create kernel pagedir
kdir = (pagedir*) kmalloc_a(sizeof(pagedir));
memzero(kdir, sizeof(pagedir));
int i;
for(i=0; i<end_mem; i += 0x1000)
{
// TEST : Map all memory 1:1
kPagingAllocateFrame(kdir, i, 0, 1);
}
print("[CORE] Switching pagedir\n");
kPagingSwitchPagedir(kdir);
}
void kPagingSwitchPagedir(pagedir* pd)
{
asm volatile("mov %0, %%cr3" :: "r"(pd));
unsigned long int cr0;
asm volatile("mov %%cr0, %0" : "=r"(cr0));
cr0 |= 0x80000000;
asm volatile("mov %0, %%cr0" :: "r"(cr0));
}