The capacity is configurable via "AllocatorCapacity" registry value.
If this value is missing (or is invalid), then value of hypervisor_allocator_recommended_capacity() is used.
These structures are mainly used for purpose of easier debugging.
That means - instead of adding each member separately "on the watch"
of the debugger, the whole structure is put on the watch.
Also, these structures shouldn't be accessible outside of the compilation
unit, therefore it makes sense to make them static. This has also benefit
of avoiding potential name conflicts.
Previously, vmexit_handler::teardown() initiated the termination of VMX operation (e.g. by vmcall, which subsequently executed VMXOFF).
Now this process is moved into vmexit_handler::terminate() method (in layman's terms, "teardown" method has been renamed to "terminate").
The vmexit_handler::teardown() method hasn't been removed, though. From now, it is used as a complementary method to vmexit_handler::setup().
Previously, EPT was completely managed by vcpu_t.
Current design delegates all EPT management to the user, which gives
them more freedom in how they use EPT.
More specifically, in previous design it was impossible to create new
EPT dynamically, after virtualization has been enabled. This issue is
resolved with the new design.
Calling this method will perform "long-jump" at the end of the VM-exit handler. You can imagine it as some kind of "throw"-statement, that VM-exit handler "catch".
Note that calling this method IS DANGEROUS, AS IT WON'T FREE ANY OBJECTS ON STACK.
Previous "custom" allocator was non-replaceable and hard-coded.
The "custom allocator" term has been replaced with "hypervisor allocator", as it more closely reflects when is this allocator used.
Most importantly, this change allows anyone to write their own allocator/heap manager (or use existing one, such as dlmalloc) and bind it as the hypervisor allocator.
This might be useful in cases where it's desired to catch rdtsc/rdtscp begin executed only in user-mode.
Disabling rdtsc/rdstcp for user-mode is achieved by setting cr4_t::timestamp_disable flag (it might be needed to set correct value to the shadow CR4 due to patch-guard).
Note: this commit temporarily disables VMWARE_WORKAROUND, until correct solution is implemented.
Using cr3_guard for reading instructions is not optimal, as the memory holding the instructions could be paged out (probably due to being only in instruction cache and not data cache).
Crash is more probable on system with more than 1 CPU.
The solution is to try to read the memory manually via page tables. In case the pages are not present, a page-fault exception is injected into the guest.
Purpose of this class is to safely access guest-virtual-memory, instead of naive CR3 switch.
CR3 switch and accessing the virtual addresses directly may result in page-fault, which is undesirable in VMX-root mode. Even if we use something like MmIsAddressValid(), other CPU might unmap any virtual address we're about to touch.
The solution is "memory_translator", which helps to manipulate with guest virtual memory in safe manner, i.e. by manually looking up physical addresses for virtual addresses, and copying directly from/to them.
Previous code assumed that callbacks called from the KeIpiGenericCall function are guaranteed to have system CR3. That assumption was wrong and the hypervisor might have crashed because of this.
This class initializes pointers to important paging structures (PML4, PDPT, PD, PT).
When the system is older than Win10 RS1, then page-tables are at fixed known location.
Since Win10 RS1, paging structures are not located at fixed virtual address, therefore we have to find them dynamically.
There are 2 ways to do this:
1) Look at some function that references PTE_BASE (e.g. MmGetVirtualForPhysical) and take the pointer from there
2) Find KDDEBUGGER_DATA64 structure, and read it from the PteBase field.
2nd method seems more reliable, as KDDEBUGGER_DATA64 is easy to find in memory, the structure is documented
and it doesn't change between versions.
* make ia32::byte_offset return uint64_t instead of uint32_t
* move ia32::mapping_t to mm::memory_mapper
* move ia32::physical_memory_descriptor to mm::physical_memory_descriptor
* move ia32::mtrr to mm::mtrr_descriptor
* remove useless pa_from_va (with cr3) function; the reason is that physical address for each active CR3 is actually always same