The VPN/offset split and present-bit check you implement here are exactly what the x86 MMU performs on every single memory access, and what the CR3 register points to on every context switch. Get the present-bit logic backwards and you turn a clean, recoverable page fault into undefined behavior that silently reads whatever garbage physical memory happens to be there.