Kernel triple faults when I dont map the first 261 pages?
Posted: Mon Oct 30, 2023 7:43 am
Hi!
I am adding paging to my small kernel, but I am encountering an issue that causes my kernel to triple fault and crash. If I don't identity-map the first 261 blocks (I have found this number through trial and error), the kernel crashes immediately after enabling paging. I have my paging code attached below.
Notice the 261, which is the minimum number of pages on which the kernel runs. This is the output I get from QEMU:
It crashes at the leave instruction of the enable_paging method.
Thank you in advance for the help! Let me know if you need more information, I am just really confused why this might be happening, as the encoding seems good.
I am adding paging to my small kernel, but I am encountering an issue that causes my kernel to triple fault and crash. If I don't identity-map the first 261 blocks (I have found this number through trial and error), the kernel crashes immediately after enabling paging. I have my paging code attached below.
Code: Select all
void PageManager::initialize()
{
PageManager* page_manager = PageManager::get();
// Assume we have 4GB of RAM (2^32 bytes), so we need 2^32 / 4096 = 2^21
uint32_t block_count = 0x100000;
// Divide by 8 because each byte represents 8 blocks
page_manager->blocks = (uint8_t *)kmalloc(block_count / 8);
memset(page_manager->blocks, 0, block_count / 8);
// This is guaranteed to be physical memory, because we haven't enabled paging and initialized the heap yet.
page_manager->m_page_directory = (Entry*)kmalloc(PAGE_DIRECTORY_SIZE*sizeof(Entry), true);
for (int i = 0; i < 1024; i++)
{
page_manager->m_page_directory[i] = Entry{
.present = 0,
.read_write = 1,
.user_supervisor = 0,
.write_through = 0,
.cache_disabled = 0,
.accessed = 0,
.reserved = 0,
.page_size = 0,
.global = 0,
.available = 0,
.page_table_base_address = 0
};
}
// Map the first 768 blocks to themselves. This is up to the start of the kernel heap.
// In this first section of section of memory we allocate stuff before we initialize the heap
// and we have the page VGA text buffer.
Entry page_directory_entry = page_manager->create_new_page_table(0);
Entry *page_table = (Entry *)(page_directory_entry.page_table_base_address << 12);
uint32_t current = 0;
while(current <= 0x1000 * 261)
{
page_table[current>>12] = Entry{
.present = 1,
.read_write = 1,
.user_supervisor = 1,
.write_through = 0,
.cache_disabled = 0,
.accessed = 0,
.reserved = 0,
.page_size = 0,
.global = 0,
.available = 0,
.page_table_base_address = current >> 12
};
current += 0x1000;
}
page_manager->enable_paging();
TTY::get()->write("Enabled Paging!");
}
void PageManager::enable_paging()
{
// Set location of page directory
asm volatile("movl %0, %%cr3" ::"r"((uint32_t)m_page_directory));
uint32_t cr0;
asm volatile("movl %%cr0, %0"
: "=r"(cr0));
cr0 |= 0x80000001; // enable paging, by setting bit 31 and bit 1
asm volatile("movl %0, %%cr0" ::"r"(cr0));
}
PageManager::Entry PageManager::create_new_page_table(uint32_t index)
{
// FIXME: Get the physical address of the allocated page table, even when heap
// is initialized and paging is enabled.
Entry *page_table_adress = (Entry *)kmalloc(PAGE_TABLE_SIZE * sizeof(Entry), true);
for (int i = 0; i < 1024; i++)
{
page_table_adress[i] = Entry{
.present = 0,
.read_write = 1,
.user_supervisor = 0,
.write_through = 0,
.cache_disabled = 0,
.accessed = 0,
.reserved = 0,
.page_size = 0,
.global = 0,
.available = 0,
.page_table_base_address = 0
};
}
Entry page_table = Entry{
.present = 1,
.read_write = 1,
.user_supervisor = 0,
.write_through = 0,
.cache_disabled = 0,
.accessed = 0,
.reserved = 0,
.page_size = 0,
.global = 0,
.available = 0,
.page_table_base_address = (uint32_t)page_table_adress >> 12
};
m_page_directory[index] = page_table;
return page_table;
}
Code: Select all
6: v=08 e=0000 i=0 cpl=0 IP=0008:001018ef pc=001018ef SP=0010:00105f18 env->regs[R_EAX]=80000011
EAX=80000011 EBX=00000010 ECX=00000000 EDX=00000000
ESI=00000000 EDI=00001000 EBP=00105f28 ESP=00105f18
EIP=001018ef EFL=00000286 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 000fffff 006f9300 DPL=0 DS [-WA]
CS =0008 00000000 000fffff 006f9a00 DPL=0 CS64 [-R-]
SS =0010 00000000 000fffff 006f9300 DPL=0 DS [-WA]
DS =0010 00000000 000fffff 006f9300 DPL=0 DS [-WA]
FS =0010 00000000 000fffff 006f9300 DPL=0 DS [-WA]
GS =0010 00000000 000fffff 006f9300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 00000004 00000031
IDT= 0000004a 000007ff
CR0=80000011 CR2=00105f14 CR3=00021000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000010 CCD=80000011 CCO=LOGICL
EFER=0000000000000000
check_exception old: 0x8 new 0xe
Thank you in advance for the help! Let me know if you need more information, I am just really confused why this might be happening, as the encoding seems good.