Cant for the life of me fix paging.
Posted: Fri Mar 29, 2024 9:32 pm
So I've been implementing paging in my os: https://github.com/maxtyson123/MaxOS (see memory management branch)
However, I'm getting a page fault when trying to read the spurious vector from the MEMIO of the local apic.
Note, I'm using 2MB pages with PAE enabled, 64bit OS
What I, ve gathered:
- APIC base address has been mapped from its lower half address of 0xFEE00000 to the higher half where the kernel is.
- The resultant page (in memory) is as follows:
- This page has the physical address of 0x1200dc1 (which according to my memory map is a valid and previously unused region)
- When this page is being created a new pml3 is created at index 511 and pml2 at index 509
- The CR3 register shows that the pml4 root address is 0x00000000001bc000 and the higher half address my kernel uses is 0xffffffff801bc000
- Memory view shows that they are mapped correctly (their first entries are both of value: 23 D0 1B 00 00 00 00 00)
- I invalidate the TLB before returning so cache shouldn't be a problem
- When trying to read from this mapped value interrupt 14 is triggered with error code 0x0 (decoded to nonpresent page)
- Registered at the time of error:
So I come to the conclusion that my page mapping is not correct, however, I cant figure out where I went wrong and have spent a couple of months on and off debugging every aspect I can think of, any help would be appreciated.
What Ive Tried:
- Identity mapping 0xFEE00000 and reading that
- Using the lower half addresses for the PML4 root (0x00000000001bc000)
- Loading a new PML4 stored in the PhysicalMemoryManager class during initialisation
- Mapping other addresses (didn't have a way to test if worked)
- Printing tlb info before and after mapping in qemu monitor (no change, this is how I came to my conclusion)
However, I'm getting a page fault when trying to read the spurious vector from the MEMIO of the local apic.
Note, I'm using 2MB pages with PAE enabled, 64bit OS
What I, ve gathered:
- APIC base address has been mapped from its lower half address of 0xFEE00000 to the higher half where the kernel is.
- The resultant page (in memory) is as follows:
Code: Select all
present = {uint64_t} 1 [0x1]
write = {uint64_t} 1 [0x1]
user = {uint64_t} 0 [0x0]
write_through = {uint64_t} 0 [0x0]
cache_disabled = {uint64_t} 0 [0x0]
accessed = {uint64_t} 0 [0x0]
dirty = {uint64_t} 0 [0x0]
huge_page = {uint64_t} 0 [0x0]
global = {uint64_t} 0 [0x0]
available = {uint64_t} 0 [0x0]
physical_address = {uint64_t} 1043968 [0xfee00]
- When this page is being created a new pml3 is created at index 511 and pml2 at index 509
- The CR3 register shows that the pml4 root address is 0x00000000001bc000 and the higher half address my kernel uses is 0xffffffff801bc000
- Memory view shows that they are mapped correctly (their first entries are both of value: 23 D0 1B 00 00 00 00 00)
- I invalidate the TLB before returning so cache shouldn't be a problem
- When trying to read from this mapped value interrupt 14 is triggered with error code 0x0 (decoded to nonpresent page)
- Registered at the time of error:
Code: Select all
rax = 0xffffffff7ee000f0 [-2166357776]
rbx = 0x0000000000281ce0 [2628832]
rcx = 0x0000000000000010 [16]
rdx = 0xffffffff7ee00000 [-2166358016]
rsi = 0x00000000000000f0 [240]
rdi = 0xffffffff801c0180 [-2145648256]
r8 = 0xffffffff7ee00000 [-2166358016]
r9 = 0xffffffff7ee00000 [-2166358016]
r10 = 0x0000000000000000 [0]
r11 = 0x0000000000000000 [0]
r12 = 0x0000000000000000 [0]
r13 = 0x0000000000000000 [0]
r14 = 0x0000000000000000 [0]
r15 = 0x0000000000000000 [0]
rip = 0xffffffff80114500 [0xffffffff80114500 <MaxOS::hardwarecommunication::InterruptManager::HandleInterrupt(MaxOS::system::cpu_status_t*)+12>]
rsp = 0xffffffff801c0160 [0xffffffff801c0160]
rbp = 0xffffffff801c0170 [0xffffffff801c0170]
eflags = 0x00200086 [ID IOPL=0 SF PF]
cs = 0x00000008 [8]
ds = 0x00000010 [16]
es = 0x00000010 [16]
ss = 0x00000010 [16]
fs = 0x00000010 [16]
gs = 0x00000010 [16]
fs_base = 0x0000000000000000 [0]
gs_base = 0x0000000000000000 [0]
k_gs_base = 0x0000000000000000 [0]
cr0 = 0x0000000080010011 [PG WP ET PE]
cr2 = 0xffffffff7ee000f0 [-2166357776]
cr3 = 0x00000000001bc000 [PDBR=444 PCID=0]
cr4 = 0x0000000000000020 [PAE]
cr8 = 0x0000000000000000 [0]
efer = 0x0000000000000500 [LMA LME]
What Ive Tried:
- Identity mapping 0xFEE00000 and reading that
- Using the lower half addresses for the PML4 root (0x00000000001bc000)
- Loading a new PML4 stored in the PhysicalMemoryManager class during initialisation
- Mapping other addresses (didn't have a way to test if worked)
- Printing tlb info before and after mapping in qemu monitor (no change, this is how I came to my conclusion)