Re: Page Fault and General Protection Fault
Posted: Sat Feb 12, 2022 6:22 pm
I managed to get it working like this:Octocontrabass wrote:Subtracting 1 results in a value that's 1 below what you should use for the stack pointer, and misaligns your stack. I don't know if Rust allows pointers past the end of an array the way C does, but that's basically what you need here.Ethin wrote:Code: Select all
.stack(&STACK.0[MAX_STACK_SIZE - 1] as *const u8)
It looks like your stack will be correctly 16-byte aligned once you fix that.
Other than the off-by-one error above, it looks like everything is set up correctly. Your stack just isn't big enough for whatever it is you're doing. You could make it bigger, but I'm really curious why 256kB isn't enough already.Ethin wrote:The odd thing is that I (think) that ffffffffb99008c7h is beyond my stack, and I don't understand why. I've even reserved it properly in my linker script (I think):
Code: Select all
#[link_section = ".stivale2hdr"]
#[used]
static BOOT_LOADER_HEADER: StivaleHeader = StivaleHeader::new()
.stack(STACK.0.as_ptr_range().end)
.flags(0x1E)
.tags(&FB_TAG as *const StivaleFramebufferHeaderTag as *const ());
As for the lack of space for the 256Kbyte stack, I figured out why. My memory manager contains a stack-allocated vector for the memory map. Since I don't know how large a memory map could be (or, rather, how many entries one might have), I took a gander and chose 16384 as the amount of space to allocate. However, I didn't take into account the size of the struct for each memory region, which is 20 bytes, plus padding/ABI stuff. Thus, 16384 entries times 20 bytes gives me an approximate stack usage of about 330Kbytes. Lowering it to 1024 entries (which I'm assuming is a good amount for pretty much every machine in the world bar NUMA setups) lowers it to about 5 KB exactly. Still a significant number, for sure, but I needed some way of storing the memory map so I could reference it later.
Now I'm just running into heap location issues. I'm trying to smartly allocate my heap in such a way that it doesn't overwrite my kernel and doesn't get set up in the higher half memory range where physical memory is located (that would be bad). Previously, before I switched boot loaders, I chose a memory location (specifically 0x100000000000) plus a random 64-bit offset. Now though I'm not really sure how to go about it. This is my (very inefficient!) initial implementation, which I need to figure out a better version of:
Code: Select all
let mut idx = 0usize;
let addrs = loop {
let entry = mmap.iter().nth(idx);
if entry.is_none() {
break (0, 0);
}
let entry = entry.unwrap();
if entry.entry_type() != StivaleMemoryMapEntryType::Usable {
idx += 1;
continue;
}
if entry.length >= MAX_HEAP_SIZE {
let base = entry.base;
let mut offset = rdrand.get_u64().unwrap() % entry.end_address();
loop {
if (base + offset + MAX_HEAP_SIZE) > entry.end_address() {
offset = rdrand.get_u64().unwrap() % entry.end_address();
continue;
}
break;
}
break (base + offset, entry.end_address());
}
};
if addrs == (0, 0) {
panic!("Can't find a memory region for the heap!");
}
Edit: solved the algorithm problem. Apparently the boot loader set up huge pages in my page table. When I go to map pages when the parent entry is a huge page, do I just skip those that are already mapped because the (parent) page is a huge page?