I'm developing a microkernel for my personal research. I have chosen to run my kernel at 0xf0000000, leaving 3.75 GiB for user space programs. When my kernel starts up, it sets up 32-bit paging (with hardcoded page directory and page tables). Then it checks if PAE is supported on host machine and sets up page directory pointer table (PDPT). But the problem comes when I try to load it into %cr3. According to the Intel Software Developer Manual:
Software can transition between 32-bit paging and PAE paging by changing the value of CR4.PAE with MOV to CR4.
So tried to use the following code to switch to PAE paging:
movl %cr4, %eax
orl $(1 << 5), %eax
movl %eax, %cr4
movl %ebx, %cr3 // %ebx holds physical address to PDPT
Or, in Intel syntax (or NASM):
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
mov cr3, ebx // ebx holds physical address to PDPT
But it fails (on QEMU). It writes to %cr4, sets %eip to next instruction, executes it (atleast GDB says this), and resets. I tried to write to %cr3 before %cr4, but still the same result.
Then I tried to switch to PAE paging by: unset PG -> set PAE -> write to %cr3 -> set PG and I succeeded. But I want switch to PAE paging directly. How is that possible?