#pragma once #include "types.h" #define SELF_REF_PML4_IDX 510 #define MAPPING_PML4_IDX 100 #define MAPPING_ADDRESS_BASE 0x0000327FFFE00000 #define SELF_REF_PML4 0xFFFFFF7FBFDFE000 #define EPT_LARGE_PDPTE_OFFSET(_) (((u64)(_)) & ((0x1000 * 0x200 * 0x200) - 1)) #define EPT_LARGE_PDE_OFFSET(_) (((u64)(_)) & ((0x1000 * 0x200) - 1)) #pragma section(".pdpt", read, write) #pragma section(".pd", read, write) #pragma section(".pt", read, write) namespace mm { enum class map_type_t { map_src, map_dest }; 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; u64 writeable : 1; u64 user_supervisor : 1; u64 page_write_through : 1; u64 page_cache : 1; u64 accessed : 1; u64 ignore_1 : 1; u64 page_size : 1; u64 ignore_2 : 4; u64 pfn : 36; u64 reserved : 4; u64 ignore_3 : 11; u64 nx : 1; }; } pml4e, * ppml4e; typedef union _pdpte { u64 value; struct { u64 present : 1; u64 rw : 1; u64 user_supervisor : 1; u64 page_write_through : 1; u64 page_cache : 1; u64 accessed : 1; u64 ignore_1 : 1; u64 large_page : 1; u64 ignore_2 : 4; u64 pfn : 36; u64 reserved : 4; u64 ignore_3 : 11; u64 nx : 1; }; } pdpte, * ppdpte; typedef union _pde { u64 value; struct { u64 present : 1; u64 rw : 1; u64 user_supervisor : 1; u64 page_write_through : 1; u64 page_cache : 1; u64 accessed : 1; u64 ignore_1 : 1; u64 large_page : 1; u64 ignore_2 : 4; u64 pfn : 36; u64 reserved : 4; u64 ignore_3 : 11; u64 nx : 1; }; } pde, * ppde; typedef union _pte { u64 value; struct { u64 present : 1; u64 rw : 1; u64 user_supervisor : 1; u64 page_write_through : 1; u64 page_cache : 1; u64 accessed : 1; u64 dirty : 1; u64 access_type : 1; u64 global : 1; u64 ignore_2 : 3; u64 pfn : 36; u64 reserved : 4; u64 ignore_3 : 7; u64 pk : 4; u64 nx : 1; }; } pte, * ppte; typedef struct _npt_pml4e { union { u64 value; struct { u64 present : 1; u64 writeable : 1; u64 user : 1; u64 write_through : 1; u64 cache_disable : 1; u64 accessed : 1; u64 reserved1 : 3; u64 avl : 3; u64 pfn : 40; u64 reserved2 : 11; u64 nx : 1; }; }; } npt_pml4e, *pnpt_pml4e, npt_pdpte, *pnpt_pdpte, npt_pde, *pnpt_pde; typedef struct _npt_pte { union { u64 value; struct { u64 present : 1; u64 writeable : 1; u64 user : 1; u64 write_through : 1; u64 cache_disable : 1; u64 accessed : 1; u64 dirty : 1; u64 pat : 1; u64 global : 1; u64 avl : 3; u64 pfn : 40; u64 reserved : 11; u64 nx : 1; }; }; } npt_pte, *pnpt_pte; typedef struct _npt_pde_2mb { union { u64 value; struct { u64 present : 1; u64 writeable : 1; u64 user : 1; u64 write_through : 1; u64 cache_disable : 1; u64 accessed : 1; u64 dirty : 1; u64 large_page : 1; u64 global : 1; u64 avl : 3; u64 pat : 1; u64 reserved1 : 8; u64 pfn : 31; u64 reserved2 : 11; u64 nx : 1; }; }; } npt_pde_2mb, * pnpt_pde_2mb; __declspec(allocate(".pdpt")) inline pdpte pdpt[512]; __declspec(allocate(".pd")) inline pde pd[512]; __declspec(allocate(".pt")) inline pte pt[512]; inline const ppml4e hyperv_pml4{ reinterpret_cast(SELF_REF_PML4) }; auto init() -> svm::vmxroot_error_t; auto map_guest_phys(guest_phys_t phys_addr, map_type_t map_type = map_type_t::map_src) -> u64; auto map_guest_virt(guest_phys_t dirbase, guest_virt_t virt_addr, map_type_t map_type = map_type_t::map_src) -> u64; auto map_page(host_phys_t phys_addr, map_type_t map_type = map_type_t::map_src) -> u64; auto get_map_virt(u16 offset = 0u, map_type_t map_type = map_type_t::map_src) -> u64; auto translate(host_virt_t host_virt) -> u64; auto translate_guest_physical(guest_phys_t guest_phys, map_type_t map_type = map_type_t::map_src) -> u64; auto translate_guest_virtual(guest_phys_t dirbase, guest_virt_t guest_virt, map_type_t map_type = map_type_t::map_src) -> u64; auto read_guest_phys(guest_phys_t dirbase, guest_phys_t guest_phys, guest_virt_t guest_virt, u64 size) -> svm::vmxroot_error_t; auto write_guest_phys(guest_phys_t dirbase, guest_phys_t guest_phys, guest_virt_t guest_virt, u64 size) -> svm::vmxroot_error_t; auto copy_guest_virt(guest_phys_t dirbase_src, guest_virt_t virt_src, guest_virt_t dirbase_dest, guest_virt_t virt_dest, u64 size) ->svm::vmxroot_error_t; }