I am very new to osdev, so please excuse if my problem arises from a complete lack of understanding.
I have read through a few resources and tried implementing paging in C++.
This is the relevant code:
Code: Select all
extern TTY tty;
uint32_t kmalloc_next_address = 0;
void *kmalloc(uint32_t size, bool align)
{
if (align && (kmalloc_next_address & 0xFFFFF000))
{
// Align the address
kmalloc_next_address &= 0xFFFFF000;
kmalloc_next_address += 0x1000;
}
uint32_t tmp = kmalloc_next_address;
kmalloc_next_address += size;
return (void *)tmp;
}
void *kmalloc(uint32_t size)
{
return kmalloc(size, false);
}
class PageManager {
public:
PageManager();
void map_next_free_block_to_page(uint32_t address);
private:
void enable_paging();
uint32_t* create_new_page_table(uint32_t index);
uint8_t* blocks;
void set_block(uint32_t address, bool used);
uint32_t** m_page_directory;
uint32_t current_page_directory_entry;
};
void PageManager::enable_paging()
{
// Enable paging
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::PageManager()
{
// 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
blocks = (uint8_t *)kmalloc(block_count / 8);
// TODO: Replace this with a memset
for (int i = 0; i < block_count / 8; i++)
{
blocks[i] = 0;
}
m_page_directory = (uint32_t**)kmalloc(1024 * 4, true);
for (int i = 0; i < 1024; i++)
{
m_page_directory[i] = (uint32_t *)2;
}
// Map the first 4MB of memory to the first 4MB of memory
// This is so we can access the VGA text buffer
uint32_t *page_table = create_new_page_table(0);
for (int i = 0; i < 1024; i++)
{
page_table[i] = (uint32_t)((i * 0x1000) | 7); // attributes: user level, read/write, present.
set_block(i * 0x1000, true);
}
enable_paging();
tty.write("Page Manager Initialized");
tty.write("Enabled Paging!");
}
uint32_t *PageManager::create_new_page_table(uint32_t index)
{
// TODO: Make sure that the whole page table is mapped
uint32_t *page_table = (uint32_t *)kmalloc(1024 * 4, true);
for (int i = 0; i < 1024; i++)
{
page_table[i] = 2;
}
m_page_directory[index] = (uint32_t *)((uint32_t)page_table | 3);
return page_table;
}
Is there something that I am doing very wrong? I understand that identity mapping the first 4MB of RAM should keep the VGA buffer accesible.
Thank you in advance for the help!