My kernel is loaded at 0x400000 so when initializing paging I'm identity mapping two first page Directories (8MiB).
That's the code I try to enable paging with. paging_init() is called:
Code: Select all
typedef uint32_t PTE; // Page Table Entry
typedef uint32_t PDE; // Page Directory Entry
// page table
struct pTable
{
PTE entries[1024];
} __attribute__((packed)); // make sure it's not alligned by compiler
typedef struct pTable pTable;
// page directory
struct pDirectoryTable
{
PDE entries[1024];
} __attribute__((packed)); // make sure it's not alligned by compiler
typedef struct pDirectoryTable pDirectoryTable;
// ...
static void paging_set_pDirectoryTable( pDirectoryTable *dir )
{
Paging.currPDirectoryTable = dir;
__asm("mov %0, %%cr3" : : "r" (dir));
}
static void enable_paging()
{
uint32_t cr0;
__asm("mov %%cr0, %0" : "=r" (cr0));
cr0 |= 0x80000001;
__asm("mov %0, %%cr0" : : "r" (cr0));
/*__asm("mov %%cr0, %%eax" : : : "%eax");
__asm("or $0x80000000, %%eax" : : : "%eax");
__asm("mov %%eax, %%cr0");*/
}
//_________________________________________________________________________________________
void paging_init()
{
// 0-4 MiB (identity mapped)
pTable *table1 = (pTable *)memory_alloc_block();
if (!table1)
{
terminal_print(debugTerminal, "paging.c, paging_initialize(): initialization failed no space for Paging Table 1");
return;
}
memsetk(table1, (uint8_t)0x00, sizeof(pTable));
// 4 MiB - 8MiB (identity mapped)
pTable *table2 = (pTable *)memory_alloc_block();
if (!table2)
{
terminal_print(debugTerminal, "paging.c, paging_initialize(): initialization failed no space for Paging Table 2");
return;
}
memsetk(table2, (uint8_t)0x00, sizeof(pTable));
//! 1st 4mb are idenitity mapped
for (int i=0, frame=0x0; i<1024; i++, frame+=4096)
{
// create a new page
PTE page = 0;
PTE_set_adress(&page, frame);
PTE_set_present_flag(&page, true); // present
PTE_set_rw_flag(&page, true); // writable
PTE_set_usm_flag(&page, false); // supervisor mode
// ...and add it to the page table
table1->entries[i] = page;
}
for (int i=0, frame=0x400000; i<1024; i++, frame+=4096)
{
// create a new page
PTE page = 0;
PTE_set_adress (&page, frame);
PTE_set_present_flag(&page, true); // present
PTE_set_rw_flag(&page, true); // writable
PTE_set_usm_flag(&page, false); // supervisor mode
// ...and add it to the page table
table2->entries[i] = page;
}
// create default directory table
pDirectoryTable *dir = (pDirectoryTable *) memory_alloc_block(); // memory_alloc_block() returns 4096 alligned pointer
if (!dir)
{
terminal_print(debugTerminal, "paging.c, paging_initialize(): initialization failed no space for Paging Directory Table");
return;
}
memsetk(dir, 0, sizeof (pDirectoryTable));
PDE *entry = &dir->entries[0];
PDE_set_adress(entry, (uint32_t)table1);
PDE_set_present_flag(entry, true);
PDE_set_rw_flag(entry, true);
PDE_set_usm_flag(entry, false); // supervisor mode
entry = &dir->entries[1];
PDE_set_adress(entry, (uint32_t)table2);
PDE_set_present_flag(entry, true);
PDE_set_rw_flag(entry, true);
PDE_set_usm_flag(entry, false); // supervisor mode
//! switch to our page directory
paging_set_pDirectoryTable(dir);
//! enable paging
enable_paging();
terminal_print(debugTerminal, "Paging initialized and enabled!\n");
}
Also, I try to compile this function but it gives an error. Do you know what's the problem with this assembly?
Code: Select all
void paging_flush_tlb_entry( uint32_t addr )
{
disable_interrupts();
__asm("invlpg %0" : : "r"(addr));
enable_interrupts();
}