Oops, missed this earlier.
Octocontrabass wrote:
Schol-R-LEA wrote:
Code:
IP=0008:00000000c000166b
CR2=0000000000a00000
I would guess one of your loops is iterating far beyond the end of an array. Try addr2line or objdump to track down which one.
I've never heard of
addr2line before, and I've only used
objdump for dumping the headers and disassembly of an ELF file. I'm not sure how I would use either of them to determine where a loop was overrunning. I'll have to check the documentation on both.
Meanwhile, I have added some sanity checks to my code, though none of them have caught anything yet.
Code:
void set_page_directory_entry(uint32_t index,
size_t pte_address,
bool page_size, bool rw,
bool user, bool write_thru, bool no_caching)
{
// first, clear the directory entry
// memset(&page_directory[index], 0, sizeof(union Page_Directory_Entry));
// SANITY CHECK - does this overrun the table?
if (index > PD_ENTRY_COUNT)
{
kprintf("Invalid directory entry index: %x\n", index);
panic();
}
if (page_size)
{
page_directory[index].mpage_entry.present = true;
page_directory[index].mpage_entry.read_write = rw;
page_directory[index].mpage_entry.user = user;
page_directory[index].mpage_entry.write_thru = write_thru;
page_directory[index].mpage_entry.cache_disable = no_caching;
page_directory[index].mpage_entry.accessed = false;
page_directory[index].mpage_entry.dirty = false;
page_directory[index].mpage_entry.page_size = true;
page_directory[index].mpage_entry.global = false;
page_directory[index].mpage_entry.available = 0;
page_directory[index].mpage_entry.page_attribute_table = false;
page_directory[index].mpage_entry.address_hi = (pte_address >> 20) & 0x1FF;
page_directory[index].mpage_entry.reserved = false;
page_directory[index].mpage_entry.address_lo = pte_address & 0xFF;
}
else
{
page_directory[index].kpage_entry.present = true;
page_directory[index].kpage_entry.read_write = rw;
page_directory[index].kpage_entry.user = user;
page_directory[index].kpage_entry.write_thru = write_thru;
page_directory[index].kpage_entry.cache_disable = no_caching;
page_directory[index].kpage_entry.accessed = false;
page_directory[index].kpage_entry.dirty = false;
page_directory[index].kpage_entry.page_size = false;
page_directory[index].kpage_entry.available = 0;
page_directory[index].kpage_entry.address = pte_address & 0xFFFFF;
}
}
void set_page_table_entry(uint32_t de,
uint32_t te,
size_t address,
bool page_size, bool rw,
bool user, bool write_thru,
bool no_caching)
{
uint32_t index = te + (de * PT_ENTRY_COUNT);
// kprintf("Page dir:table = %x:%x -> index %x\n", de, te, index);
// SANITY CHECK - does this overrun the table?
if (de > PD_ENTRY_COUNT)
{
kprintf("Invalid directory entry: %x\n", de);
panic();
}
if (index > (PT_ENTRY_COUNT * PD_ENTRY_COUNT))
{
kprintf("Invalid table entry index: %x\n", index);
panic();
}
page_tables[index].fields.present = true;
page_tables[index].fields.read_write = rw;
page_tables[index].fields.user = user;
page_tables[index].fields.write_thru = write_thru;
page_tables[index].fields.cache_disable = no_caching;
page_tables[index].fields.accessed = false;
page_tables[index].fields.dirty = false;
page_tables[index].fields.page_size = page_size;
page_tables[index].fields.page_attribute_table = false;
page_tables[index].fields.global = false;
page_tables[index].fields.available = 0;
page_tables[index].fields.address = address;
}
Code:
/* set a block of page directory and page table entries matching a block of memory */
void set_page_block(uint32_t phys_address,
uint32_t virt_address,
uint32_t block_size,
bool page_size, bool rw,
bool user, bool write_thru,
bool no_caching)
{
struct Page_Directory_Frame frame;
get_frame(&frame, virt_address, block_size);
// SANITY CHECKS - make sure that the calculated values are sound
if (frame.dir_start > PD_ENTRY_COUNT)
{
kprintf("Invalid directory start: %x\n", frame.dir_start);
panic();
}
if (frame.dir_end > PD_ENTRY_COUNT)
{
kprintf("Invalid directory endpoint: %x\n", frame.dir_end);
panic();
}
if (frame.page_start > PT_ENTRY_COUNT)
{
kprintf("Invalid page table entry start: %x\n", frame.page_start);
panic();
}
if (frame.page_end > PT_ENTRY_COUNT)
{
kprintf("Invalid page table entry endpoint: %x\n", frame.page_end);
panic();
}
// initialize the iteration variables here rather than in the for statement,
// as the values need to carry over fro one iteration to the next
uint32_t pd_entry = frame.dir_start;
uint32_t pt_entry;
size_t addr = phys_address;
for (bool first_entry = true; pd_entry <= frame.dir_end; pd_entry++, first_entry = false)
{
// if this is the first iteration of the loop, use the computed page entry location,
// otherwise start from the beginning of the page entry
pt_entry = first_entry ? frame.page_start : 0;
// if this is the final iteration of the loop, use the computed page end location,
// otherwise fill the whole page entry
uint32_t pt_current_end = (pd_entry == frame.dir_end) ? (frame.page_end + 1) : PT_ENTRY_COUNT;
// SANITY CHECK - does this overrun the table?
if (pt_current_end > PT_ENTRY_COUNT)
{
kprintf("Invalid local page table entry endpoint: %x\n", pt_current_end);
panic();
}
set_page_directory_entry(pd_entry,
(size_t) &page_tables[pt_entry],
page_size, rw,
user, write_thru,
no_caching);
for (; pt_entry < pt_current_end; pt_entry++, addr += PAGE_SPAN)
{
set_page_table_entry(pd_entry,
pt_entry,
addr,
page_size, rw,
user, write_thru,
no_caching);
}
}
}