#pragma once #include "hv_types.hpp" #define PML4_SELF_REF 255 #pragma section(".pml4", read, write) #pragma section(".epml4", read, write) #pragma section(".epdpt", read, write) #pragma section(".epd", read, write) #pragma section(".ept", read, write) namespace mm { using epml4_t = ept_pml4[512]; using ept_t = epte[512]; using epdpt_t = union { epdpte entry_4kb[512]; epdpte_1gb entry_1gb[512]; }; using epd_t = union { epde entry_4kb[512]; epde_2mb entry_2mb[512]; }; typedef union _virt_addr_t { u64 value; struct { u64 offset_4kb : 12; u64 pt_index : 9; u64 pd_index : 9; u64 pdpt_index : 9; u64 pml4_index : 9; u64 reserved : 16; }; struct { u64 offset_2mb : 21; u64 pd_index : 9; u64 pdpt_index : 9; u64 pml4_index : 9; u64 reserved : 16; }; struct { u64 offset_1gb : 30; u64 pdpt_index : 9; u64 pml4_index : 9; u64 reserved : 16; }; } virt_addr_t, * pvirt_addr_t; using phys_addr_t = virt_addr_t; typedef union _pml4e { u64 value; struct { u64 present : 1; // Must be 1, region invalid if 0. u64 rw : 1; // If 0, writes not allowed. u64 user_supervisor : 1; // If 0, user-mode accesses not allowed. u64 PageWriteThrough : 1; // Determines the memory type used to access PDPT. u64 page_cache : 1; // Determines the memory type used to access PDPT. u64 accessed : 1; // If 0, this entry has not been used for translation. u64 Ignored1 : 1; u64 page_size : 1; // Must be 0 for PML4E. u64 Ignored2 : 4; u64 pfn : 36; // The page frame number of the PDPT of this PML4E. u64 Reserved : 4; u64 Ignored3 : 11; u64 nx : 1; // If 1, instruction fetches not allowed. }; } pml4e, * ppml4e; typedef union _pdpte { u64 value; struct { u64 present : 1; // Must be 1, region invalid if 0. u64 rw : 1; // If 0, writes not allowed. u64 user_supervisor : 1; // If 0, user-mode accesses not allowed. u64 PageWriteThrough : 1; // Determines the memory type used to access PD. u64 page_cache : 1; // Determines the memory type used to access PD. u64 accessed : 1; // If 0, this entry has not been used for translation. u64 Ignored1 : 1; u64 page_size : 1; // If 1, this entry maps a 1GB page. u64 Ignored2 : 4; u64 pfn : 36; // The page frame number of the PD of this PDPTE. u64 Reserved : 4; u64 Ignored3 : 11; u64 nx : 1; // If 1, instruction fetches not allowed. }; } pdpte, * ppdpte; typedef union _pde { u64 value; struct { u64 present : 1; // Must be 1, region invalid if 0. u64 rw : 1; // If 0, writes not allowed. u64 user_supervisor : 1; // If 0, user-mode accesses not allowed. u64 PageWriteThrough : 1; // Determines the memory type used to access PT. u64 page_cache : 1; // Determines the memory type used to access PT. u64 accessed : 1; // If 0, this entry has not been used for translation. u64 Ignored1 : 1; u64 page_size : 1; // If 1, this entry maps a 2MB page. u64 Ignored2 : 4; u64 pfn : 36; // The page frame number of the PT of this PDE. u64 Reserved : 4; u64 Ignored3 : 11; u64 nx : 1; // If 1, instruction fetches not allowed. }; } pde, * ppde; typedef union _pte { u64 value; struct { u64 present : 1; // Must be 1, region invalid if 0. u64 rw : 1; // If 0, writes not allowed. u64 user_supervisor : 1; // If 0, user-mode accesses not allowed. u64 PageWriteThrough : 1; // Determines the memory type used to access the memory. u64 page_cache : 1; // Determines the memory type used to access the memory. u64 accessed : 1; // If 0, this entry has not been used for translation. u64 Dirty : 1; // If 0, the memory backing this page has not been written to. u64 PageAccessType : 1; // Determines the memory type used to access the memory. u64 Global : 1; // If 1 and the PGE bit of CR4 is set, translations are global. u64 Ignored2 : 3; u64 pfn : 36; // The page frame number of the backing physical page. u64 reserved : 4; u64 Ignored3 : 7; u64 ProtectionKey : 4; // If the PKE bit of CR4 is set, determines the protection key. u64 nx : 1; // If 1, instruction fetches not allowed. }; } pte, * ppte; enum class map_type{ dest, src }; inline const ppml4e vmxroot_pml4 = reinterpret_cast(0x7fbfdfeff000); __declspec(allocate(".pml4")) inline pml4e pml4[512]; __declspec(allocate(".epml4")) inline epml4_t epml4; __declspec(allocate(".epdpt")) inline epdpt_t epdpt[64]; __declspec(allocate(".epd")) inline epd_t epd[128]; __declspec(allocate(".ept")) inline ept_t ept[256]; // translate vmxroot address's... auto translate(virt_addr_t virt_addr) -> u64; // translate guest virtual addresses... auto translate(virt_addr_t virt_addr, u64 pml4_phys, map_type type = map_type::src) -> u64; // map a page into vmxroot address space... auto map_page(u64 phys_addr, map_type type = map_type::src) -> u64; // map a page (4kb) from another address into vmxroot... auto map_virt(u64 dirbase, u64 virt_addr, map_type map_type = map_type::src)->u64; // copy virtual memory without changing cr3... this maps the physical memory into vmxroot // address space and copies the memory directly between the physical pages... the memory must be paged in... auto copy_virt(u64 dirbase_src, u64 virt_src, u64 dirbase_dest, u64 virt_dest, u64 size) -> bool; auto read_phys(u64 dirbase, u64 guest_phys, u64 guest_virt, u64 size) -> bool; auto write_phys(u64 dirbase, u64 guest_phys, u64 guest_virt, u64 size) -> bool; }