Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
I do get a page fault with e=000a and my CR2=ffff800100400000. Expanding on my previous comment - e=000a is also telling us that the page fault is because the page isn't present as well. This suggests there is something really wrong in an entry. In the QEMU monitor I did an `info tlb` . It is long but I have reduced it to a few entries of which 2 are relevant
You can see the physical addresses are wrong and the pages aren't marked present and the NX bit is set. Something has created those bogus entries. I would do an `info tlb` and look for the virtual address giving you a problem on your build (it might be different than mine) and find it in the TLB. .I don't have time this evening to see why, but I would use the QEMU monitor to look at your page structures in physical memory to see what level in the hierarchy the problems happened at and that might five a clue as to where in the code to look.
When I follow each page level using the QEMU monitor starting at physical address 0x8000 (PML4) I end up at a PML1 (page table) that starts with these entries (the first 2 entries are pml1[0] and pm1l[1]):
(qemu) xp/512g 0x35000
0000000000035000: 0xffff800000033003 0xffff800000036003
0000000000035010: 0x0000000000000000 0x0000000000000000
0000000000035020: 0x0000000000000000 0x0000000000000000
0000000000035030: 0x0000000000000000 0x0000000000000000
... the rest are 0x0000000000000000
Now look closely at those entries. Those are supposed to be physical addresses (of 4KiB page frames) but the upper 17 bits are all set! The lower bits do appear to be physical addresses though. I haven't looked at the code, but maybe you can review your code to find a place where the upper bits are being set (or not being cleared) when updating/setting the physical addresses of page table entries. I am basically providing this to you as a courtesy so that you can attempt to continue the bug hunt.
Other possibility though is that you are using a virtual address returned by pmm_alloc and treating it as a physical address somewhere.
Your pmm_init stores the virtual address in the free pages to create a linked list (not the physical address). Possibly you are eventually reading those virtual addresses back and treating them as physical addresses. I don't have time to go through your code at the moment. Trying to give you ideas so you can find the bug.
I noticed a potential cause of this bug last night but was hoping you might be able to track it down. You likely had a page fault with error code e=0002 which is a write to a non present page. In the QEMU monitor `info tlb` and `info mem` confirm this memory (0xffff800100c001d8) is in a page that is not present. You have many bugs in your vmm and one of the big ones I noticed is in `find_pte`. In particular this function returns back after only descending down to the pml2 (page directory). You need to modify that function to handle 2MiB pages and also descend to the PML1 (page tables) level when not using 2MiB pages.
Your going to need to start learning to debug these issues yourself because OSDev is hard but there is a skill set in doing proper debugging that needs to be learned. Are you using GDB to debug and do you use the QEMU monitor at all?