I modified SimpleVisor (a small windows hypervisor implemented as a driver) to remove RW access to guest's PML4. I remove RW access on every syscall (I've pml4 physical address from guest's CR3). This causes an EPT violation immediately when accessing the kernel address space, which is ok. As a test, I handle this violation by restoring RW access to guest's PML4 and continue guest.
This method works for 1-2s, then the OS hangs (vmware) or restarts after few seconds (bare metal). All debug output in windbg stops and windbg becomes unresponsive.
How is this possible? I've asserts in my code to break on GuestCR3 == HostCR3 and it's not triggered. In what other situations above method is wrong? The hypervisor runs on IRQL=HIGH_LEVEL so it can't be preempted by another thread -- this eliminates concurrency issues, correct?