Problem with paging (Triple fault)
Posted: Sat Aug 12, 2023 2:22 am
Hello forum!
I'm new to OS development and now I'm developing my first OS. I've already implemented simple exception handler and now I'm trying to implement paging. I have decided to start with Identity Paging but for all memory because I have to enable paging for future multitasking, but still want to control memory same as before. So I wrote a simple function for Identify Paging. Here is the code:
But... this function is not working properly. Once I write PG bit to CR0, I get a Triple Fault. GDB tells me that my code doesn't even switch to next instruction and instantly resets I also know that page fault happens before reset (CR2 register != 0) but have no idea why. Can someone help me with explanation about what happens here? Or maybe Identify Paging for all memory is not needed and different memory models can be used.
Thank you for your reply.
I'm new to OS development and now I'm developing my first OS. I've already implemented simple exception handler and now I'm trying to implement paging. I have decided to start with Identity Paging but for all memory because I have to enable paging for future multitasking, but still want to control memory same as before. So I wrote a simple function for Identify Paging. Here is the code:
Code: Select all
#define PAGE_SIZE 4 // given in kilobytes
extern void panic(char* error);
typedef struct {
uint32_t address : 20; // 4 KiB aligned adress of PT
uint16_t avl : 4; // available
uint8_t flags : 8; // 5th bit is available
} __attribute__((packed)) pd_entry_t;
typedef struct {
uint32_t address : 20; // 4 KiB aligned adress of PT
uint8_t avl : 3; // available
uint16_t flags : 9; // flags
} __attribute__((packed)) pt_entry_t;
uint32_t get_memory_size(multiboot_info_t* mbd) {
uint32_t lower = mbd->mem_lower;
uint32_t higher = mbd->mem_upper;
return lower + higher;
}
void init_paging(multiboot_info_t* mbd) {
uint32_t total_memory = get_memory_size(mbd);
if (total_memory < 16384) {
panic("At least 16Mb of RAM required to run operating system.");
}
if (total_memory > 4194303) {
total_memory = 4194303;
}
/*extern uint32_t _end;
uint32_t kernel_end_addr = (uint32_t)&_end;
kernel_end_addr = (kernel_end_addr + 4095) & ~4095;*/
pd_entry_t page_directory[1024] __attribute__((aligned(4096)));
pt_entry_t page_table[(total_memory + PAGE_SIZE - 1) / PAGE_SIZE] __attribute__((aligned(4096)));
uint16_t pd_index;
uint16_t pt_index;
uint32_t phys_addr;
uint32_t pt_addr;
for (uint32_t i = 0; i < total_memory; i += PAGE_SIZE)
{
phys_addr = i * 1024;
pd_index = phys_addr >> 22;
pt_index = phys_addr >> 12 & 0x03FF;
if ((phys_addr & 0xFFF))
{
printf("0x%x ", phys_addr);
panic("Adress cannot be aligned at 4 KB.");
}
pt_addr = (uint32_t)(&page_table[pd_index * 1024]);
if ((pt_addr & 0xFFF))
{
printf("0x%x ", pt_addr);
panic("Adress cannot be aligned at 4 KB.");
}
page_directory[pd_index].address = pt_addr >> 12;
page_directory[pd_index].avl = 0;
page_directory[pd_index].flags = 0b11010000;
page_table[pd_index * 1024 + pt_index].address = phys_addr >> 12;
page_table[pd_index * 1024 + pt_index].avl = 0;
page_table[pd_index * 1024 + pt_index].flags = 0b110100000;
}
uint32_t pd_address = (uint32_t)page_directory;
asm volatile ("mov %0, %%cr3" : : "r" (pd_address) : "memory");
//asm volatile ("mov %%cr0, %%eax; or $0x80000000, %%eax; mov %%eax, %%cr0" : :);
//for(;;);
printf("Paging enabled (1:1, Page Directory = 0x%x)", pd_address);
}
But... this function is not working properly. Once I write PG bit to CR0, I get a Triple Fault. GDB tells me that my code doesn't even switch to next instruction and instantly resets I also know that page fault happens before reset (CR2 register != 0) but have no idea why. Can someone help me with explanation about what happens here? Or maybe Identify Paging for all memory is not needed and different memory models can be used.
Thank you for your reply.