parent
ce7d94c49a
commit
34cacd54a9
@ -1,158 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{09b41831-3164-48ad-8660-23457d82b73b}</ProjectGuid>
|
||||
<RootNamespace>DeepSpaceNetwork</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>Example</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="com.asm">
|
||||
<FileType>Document</FileType>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="com.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#define VMEXIT_KEY 0xDEADBEEFDEADBEEF
|
||||
enum class vmexit_command_t
|
||||
{
|
||||
init_paging_tables = 0x111
|
||||
// add your commands here...
|
||||
};
|
||||
|
||||
extern "C" size_t hypercall(size_t key, vmexit_command_t command);
|
@ -1,9 +0,0 @@
|
||||
#include <iostream>
|
||||
#include "com.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
auto result = hypercall(VMEXIT_KEY, vmexit_command_t::init_paging_tables);
|
||||
std::printf("[+] hyper-v (CPUID) init page table result -> %d\n", result);
|
||||
std::getchar();
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
#include "debug.h"
|
||||
|
||||
auto dbg::debug_print_decimal(long long number) -> void
|
||||
{
|
||||
if (number < 0)
|
||||
{
|
||||
__outbyte(PORT_NUM, '-');
|
||||
number = -number;
|
||||
}
|
||||
|
||||
for (auto d = 1000000000000000000; d != 0; d /= 10)
|
||||
if ((number / d) != 0)
|
||||
__outbyte(PORT_NUM, alphabet[(number / d) % 10]);
|
||||
}
|
||||
|
||||
auto dbg::debug_print_hex(u64 number, const bool show_zeros) -> void
|
||||
{
|
||||
for (auto d = 0x1000000000000000; d != 0; d /= 0x10)
|
||||
if (show_zeros || (number / d) != 0)
|
||||
__outbyte(PORT_NUM, alphabet[(number / d) % 0x10]);
|
||||
}
|
||||
|
||||
auto dbg::print(const char* format, ...) -> void
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
while (format[0])
|
||||
{
|
||||
if (format[0] == '%')
|
||||
{
|
||||
switch (format[1])
|
||||
{
|
||||
case 'd':
|
||||
debug_print_decimal(va_arg(args, int));
|
||||
format += 2;
|
||||
continue;
|
||||
case 'x':
|
||||
debug_print_hex(va_arg(args, u32), false);
|
||||
format += 2;
|
||||
continue;
|
||||
case 'l':
|
||||
if (format[2] == 'l')
|
||||
{
|
||||
switch (format[3])
|
||||
{
|
||||
case 'd':
|
||||
debug_print_decimal(va_arg(args, u64));
|
||||
format += 4;
|
||||
continue;
|
||||
case 'x':
|
||||
debug_print_hex(va_arg(args, u64), false);
|
||||
format += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
debug_print_hex(va_arg(args, u64), true);
|
||||
format += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
__outbyte(PORT_NUM, format[0]);
|
||||
++format;
|
||||
}
|
||||
va_end(args);
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include "types.h"
|
||||
|
||||
#define PORT_NUM 0x2F8
|
||||
namespace dbg
|
||||
{
|
||||
constexpr char alphabet[] = "0123456789ABCDEF";
|
||||
auto debug_print_decimal(long long number) -> void;
|
||||
auto debug_print_hex(u64 number, const bool show_zeros) -> void;
|
||||
auto print(const char* format, ...) -> void;
|
||||
}
|
@ -0,0 +1,363 @@
|
||||
#include "mm.h"
|
||||
#include "debug.h"
|
||||
|
||||
auto mm::map_guest_phys(guest_phys_t phys_addr, map_type_t map_type) -> u64
|
||||
{
|
||||
//const auto host_phys =
|
||||
//translate_guest_physical(
|
||||
//phys_addr, map_type);
|
||||
|
||||
//if (!host_phys)
|
||||
//return {};
|
||||
|
||||
return map_page(phys_addr, map_type);
|
||||
}
|
||||
|
||||
auto mm::map_guest_virt(guest_phys_t dirbase, guest_virt_t virt_addr, map_type_t map_type) -> u64
|
||||
{
|
||||
const auto guest_phys =
|
||||
translate_guest_virtual(
|
||||
dirbase, virt_addr, map_type);
|
||||
|
||||
if (!guest_phys)
|
||||
return {};
|
||||
|
||||
return map_guest_phys(guest_phys, map_type);
|
||||
}
|
||||
|
||||
auto mm::map_page(host_phys_t phys_addr, map_type_t map_type) -> u64
|
||||
{
|
||||
cpuid_eax_01 cpuid_value;
|
||||
__cpuid((int*)&cpuid_value, 1);
|
||||
|
||||
mm::pt[(cpuid_value
|
||||
.cpuid_additional_information
|
||||
.initial_apic_id * 2)
|
||||
+ (unsigned)map_type].pfn = phys_addr >> 12;
|
||||
|
||||
__invlpg(reinterpret_cast<void*>(
|
||||
get_map_virt(virt_addr_t{ phys_addr }.offset_4kb, map_type)));
|
||||
|
||||
return get_map_virt(virt_addr_t{ phys_addr }.offset_4kb, map_type);
|
||||
}
|
||||
|
||||
auto mm::get_map_virt(u16 offset, map_type_t map_type) -> u64
|
||||
{
|
||||
cpuid_eax_01 cpuid_value;
|
||||
__cpuid((int*)&cpuid_value, 1);
|
||||
virt_addr_t virt_addr{ MAPPING_ADDRESS_BASE };
|
||||
|
||||
virt_addr.pt_index = (cpuid_value
|
||||
.cpuid_additional_information
|
||||
.initial_apic_id * 2)
|
||||
+ (unsigned)map_type;
|
||||
|
||||
return virt_addr.value + offset;
|
||||
}
|
||||
|
||||
auto mm::translate(host_virt_t host_virt) -> u64
|
||||
{
|
||||
virt_addr_t virt_addr{ host_virt };
|
||||
virt_addr_t cursor{ (u64)hyperv_pml4 };
|
||||
|
||||
if (!reinterpret_cast<ppml4e>(cursor.value)[virt_addr.pml4_index].present)
|
||||
return {};
|
||||
|
||||
cursor.pt_index = virt_addr.pml4_index;
|
||||
if (!reinterpret_cast<ppdpte>(cursor.value)[virt_addr.pdpt_index].present)
|
||||
return {};
|
||||
|
||||
// handle 1gb large page...
|
||||
if (reinterpret_cast<ppdpte>(cursor.value)[virt_addr.pdpt_index].large_page)
|
||||
return (reinterpret_cast<ppdpte>(cursor.value)
|
||||
[virt_addr.pdpt_index].pfn << 30) + virt_addr.offset_1gb;
|
||||
|
||||
cursor.pd_index = virt_addr.pml4_index;
|
||||
cursor.pt_index = virt_addr.pdpt_index;
|
||||
if (!reinterpret_cast<ppde>(cursor.value)[virt_addr.pd_index].present)
|
||||
return {};
|
||||
|
||||
// handle 2mb large page...
|
||||
if (reinterpret_cast<ppde>(cursor.value)[virt_addr.pd_index].large_page)
|
||||
return (reinterpret_cast<ppde>(cursor.value)
|
||||
[virt_addr.pd_index].pfn << 21) + virt_addr.offset_2mb;
|
||||
|
||||
cursor.pdpt_index = virt_addr.pml4_index;
|
||||
cursor.pd_index = virt_addr.pdpt_index;
|
||||
cursor.pt_index = virt_addr.pd_index;
|
||||
if (!reinterpret_cast<ppte>(cursor.value)[virt_addr.pt_index].present)
|
||||
return {};
|
||||
|
||||
return (reinterpret_cast<ppte>(cursor.value)
|
||||
[virt_addr.pt_index].pfn << 12) + virt_addr.offset_4kb;
|
||||
}
|
||||
|
||||
auto mm::translate_guest_virtual(guest_phys_t dirbase, guest_virt_t guest_virt, map_type_t map_type) -> u64
|
||||
{
|
||||
virt_addr_t virt_addr{ guest_virt };
|
||||
|
||||
const auto pml4 =
|
||||
reinterpret_cast<pml4e*>(
|
||||
map_guest_phys(dirbase, map_type));
|
||||
|
||||
if (!pml4 || !pml4[virt_addr.pml4_index].present)
|
||||
return {};
|
||||
|
||||
const auto pdpt =
|
||||
reinterpret_cast<pdpte*>(map_guest_phys(
|
||||
pml4[virt_addr.pml4_index].pfn << 12, map_type));
|
||||
|
||||
if (!pdpt || !pdpt[virt_addr.pdpt_index].present)
|
||||
return {};
|
||||
|
||||
// handle 1gb pages...
|
||||
if (pdpt[virt_addr.pdpt_index].large_page)
|
||||
return (pdpt[virt_addr.pdpt_index].pfn << 12) + virt_addr.offset_1gb;
|
||||
|
||||
const auto pd =
|
||||
reinterpret_cast<pde*>(map_guest_phys(
|
||||
pdpt[virt_addr.pdpt_index].pfn << 12, map_type));
|
||||
|
||||
if (!pd || !pd[virt_addr.pd_index].present)
|
||||
return {};
|
||||
|
||||
// handle 2mb pages...
|
||||
if (pd[virt_addr.pd_index].large_page)
|
||||
return (pd[virt_addr.pd_index].pfn << 12) + virt_addr.offset_2mb;
|
||||
|
||||
const auto pt =
|
||||
reinterpret_cast<pte*>(map_guest_phys(
|
||||
pd[virt_addr.pd_index].pfn << 12, map_type));
|
||||
|
||||
if (!pt || !pt[virt_addr.pt_index].present)
|
||||
return {};
|
||||
|
||||
return (pt[virt_addr.pt_index].pfn << 12) + virt_addr.offset_4kb;
|
||||
}
|
||||
|
||||
auto mm::translate_guest_physical(guest_phys_t phys_addr, map_type_t map_type) -> u64
|
||||
{
|
||||
phys_addr_t guest_phys{ phys_addr };
|
||||
const auto vmcb = svm::get_vmcb();
|
||||
|
||||
const auto npt_pml4 =
|
||||
reinterpret_cast<pnpt_pml4e>(
|
||||
map_page(vmcb->ncr3, map_type));
|
||||
|
||||
if (!npt_pml4[guest_phys.pml4_index].present)
|
||||
return {};
|
||||
|
||||
const auto npt_pdpt =
|
||||
reinterpret_cast<pnpt_pdpte>(
|
||||
map_page(npt_pml4[guest_phys.pml4_index].pfn << 12, map_type));
|
||||
|
||||
if (!npt_pdpt[guest_phys.pdpt_index].present)
|
||||
return {};
|
||||
|
||||
const auto npt_pd =
|
||||
reinterpret_cast<pnpt_pde>(
|
||||
map_page(npt_pdpt[guest_phys.pdpt_index].pfn << 12, map_type));
|
||||
|
||||
if (!npt_pd[guest_phys.pd_index].present)
|
||||
return {};
|
||||
|
||||
// handle 2mb pages...
|
||||
if (reinterpret_cast<pnpt_pde_2mb>(npt_pd)[guest_phys.pd_index].large_page)
|
||||
return (reinterpret_cast<pnpt_pde_2mb>(npt_pd)
|
||||
[guest_phys.pd_index].pfn << 21) + guest_phys.offset_2mb;
|
||||
|
||||
const auto npt_pt =
|
||||
reinterpret_cast<pnpt_pte>(
|
||||
map_page(npt_pd[guest_phys.pd_index].pfn << 12, map_type));
|
||||
|
||||
if (!npt_pt[guest_phys.pt_index].present)
|
||||
return {};
|
||||
|
||||
return (npt_pt[guest_phys.pt_index].pfn << 12) + guest_phys.offset_4kb;
|
||||
}
|
||||
|
||||
auto mm::init() -> svm::vmxroot_error_t
|
||||
{
|
||||
const auto pdpt_phys =
|
||||
translate(reinterpret_cast<u64>(pdpt));
|
||||
|
||||
const auto pd_phys =
|
||||
translate(reinterpret_cast<u64>(pd));
|
||||
|
||||
const auto pt_phys =
|
||||
translate(reinterpret_cast<u64>(pt));
|
||||
|
||||
if (!pdpt_phys || !pd_phys || !pt_phys)
|
||||
return svm::vmxroot_error_t::invalid_host_virtual;
|
||||
|
||||
// setup mapping page table entries...
|
||||
{
|
||||
hyperv_pml4[MAPPING_PML4_IDX].present = true;
|
||||
hyperv_pml4[MAPPING_PML4_IDX].pfn = pdpt_phys >> 12;
|
||||
hyperv_pml4[MAPPING_PML4_IDX].user_supervisor = false;
|
||||
hyperv_pml4[MAPPING_PML4_IDX].writeable = true;
|
||||
|
||||
pdpt[511].present = true;
|
||||
pdpt[511].pfn = pd_phys >> 12;
|
||||
pdpt[511].user_supervisor = false;
|
||||
pdpt[511].rw = true;
|
||||
|
||||
pd[511].present = true;
|
||||
pd[511].pfn = pt_phys >> 12;
|
||||
pd[511].user_supervisor = false;
|
||||
pd[511].rw = true;
|
||||
}
|
||||
|
||||
// each core will have its own page it can use to map
|
||||
// physical memory into virtual memory :^)
|
||||
for (auto idx = 0u; idx < 512; ++idx)
|
||||
{
|
||||
pt[idx].present = true;
|
||||
pt[idx].user_supervisor = false;
|
||||
pt[idx].rw = true;
|
||||
}
|
||||
|
||||
const auto mapped_pml4 =
|
||||
reinterpret_cast<ppml4e>(
|
||||
mm::map_page(__readcr3()));
|
||||
|
||||
// check to make sure translate works...
|
||||
if (translate((u64)mapped_pml4) != __readcr3())
|
||||
return svm::vmxroot_error_t::vmxroot_translate_failure;
|
||||
|
||||
// check to make sure the self ref pml4e is valid...
|
||||
if (mapped_pml4[SELF_REF_PML4_IDX].pfn != __readcr3() >> 12)
|
||||
return svm::vmxroot_error_t::invalid_self_ref_pml4e;
|
||||
|
||||
// check to make sure the mapping pml4e is valid...
|
||||
if (mapped_pml4[MAPPING_PML4_IDX].pfn != pdpt_phys >> 12)
|
||||
return svm::vmxroot_error_t::invalid_mapping_pml4e;
|
||||
|
||||
return svm::vmxroot_error_t::error_success;
|
||||
}
|
||||
|
||||
auto mm::read_guest_phys(guest_phys_t dirbase, guest_phys_t guest_phys,
|
||||
guest_virt_t guest_virt, u64 size) -> svm::vmxroot_error_t
|
||||
{
|
||||
// handle reading over page boundaries of both src and dest...
|
||||
while (size)
|
||||
{
|
||||
auto dest_current_size = PAGE_4KB -
|
||||
virt_addr_t{ guest_virt }.offset_4kb;
|
||||
|
||||
if (size < dest_current_size)
|
||||
dest_current_size = size;
|
||||
|
||||
auto src_current_size = PAGE_4KB -
|
||||
phys_addr_t{ guest_phys }.offset_4kb;
|
||||
|
||||
if (size < src_current_size)
|
||||
src_current_size = size;
|
||||
|
||||
auto current_size =
|
||||
min(dest_current_size, src_current_size);
|
||||
|
||||
const auto mapped_dest =
|
||||
reinterpret_cast<void*>(
|
||||
map_guest_virt(dirbase, guest_virt, map_type_t::map_dest));
|
||||
|
||||
if (!mapped_dest)
|
||||
return svm::vmxroot_error_t::invalid_guest_virtual;
|
||||
|
||||
const auto mapped_src =
|
||||
reinterpret_cast<void*>(
|
||||
map_guest_phys(guest_phys, map_type_t::map_src));
|
||||
|
||||
if (!mapped_src)
|
||||
return svm::vmxroot_error_t::invalid_guest_physical;
|
||||
|
||||
memcpy(mapped_dest, mapped_src, current_size);
|
||||
guest_phys += current_size;
|
||||
guest_virt += current_size;
|
||||
size -= current_size;
|
||||
}
|
||||
|
||||
return svm::vmxroot_error_t::error_success;
|
||||
}
|
||||
|
||||
auto mm::write_guest_phys(guest_phys_t dirbase,
|
||||
guest_phys_t guest_phys, guest_virt_t guest_virt, u64 size) -> svm::vmxroot_error_t
|
||||
{
|
||||
// handle reading over page boundaries of both src and dest...
|
||||
while (size)
|
||||
{
|
||||
auto dest_current_size = PAGE_4KB -
|
||||
virt_addr_t{ guest_virt }.offset_4kb;
|
||||
|
||||
if (size < dest_current_size)
|
||||
dest_current_size = size;
|
||||
|
||||
auto src_current_size = PAGE_4KB -
|
||||
phys_addr_t{ guest_phys }.offset_4kb;
|
||||
|
||||
if (size < src_current_size)
|
||||
src_current_size = size;
|
||||
|
||||
auto current_size =
|
||||
min(dest_current_size, src_current_size);
|
||||
|
||||
const auto mapped_src =
|
||||
reinterpret_cast<void*>(
|
||||
map_guest_virt(dirbase, guest_virt, map_type_t::map_src));
|
||||
|
||||
if (!mapped_src)
|
||||
return svm::vmxroot_error_t::invalid_guest_virtual;
|
||||
|
||||
const auto mapped_dest =
|
||||
reinterpret_cast<void*>(
|
||||
map_guest_phys(guest_phys, map_type_t::map_dest));
|
||||
|
||||
if (!mapped_src)
|
||||
return svm::vmxroot_error_t::invalid_guest_physical;
|
||||
|
||||
memcpy(mapped_dest, mapped_src, current_size);
|
||||
guest_phys += current_size;
|
||||
guest_virt += current_size;
|
||||
size -= current_size;
|
||||
}
|
||||
|
||||
return svm::vmxroot_error_t::error_success;
|
||||
}
|
||||
|
||||
auto mm::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
|
||||
{
|
||||
while (size)
|
||||
{
|
||||
auto dest_size = PAGE_4KB - virt_addr_t{ virt_dest }.offset_4kb;
|
||||
if (size < dest_size)
|
||||
dest_size = size;
|
||||
|
||||
auto src_size = PAGE_4KB - virt_addr_t{ virt_src }.offset_4kb;
|
||||
if (size < src_size)
|
||||
src_size = size;
|
||||
|
||||
const auto mapped_src =
|
||||
reinterpret_cast<void*>(
|
||||
map_guest_virt(dirbase_src, virt_src, map_type_t::map_src));
|
||||
|
||||
if (!mapped_src)
|
||||
return svm::vmxroot_error_t::invalid_guest_virtual;
|
||||
|
||||
const auto mapped_dest =
|
||||
reinterpret_cast<void*>(
|
||||
map_guest_virt(dirbase_dest, virt_dest, map_type_t::map_dest));
|
||||
|
||||
if (!mapped_dest)
|
||||
return svm::vmxroot_error_t::invalid_guest_virtual;
|
||||
|
||||
auto current_size = min(dest_size, src_size);
|
||||
memcpy(mapped_dest, mapped_src, current_size);
|
||||
|
||||
virt_src += current_size;
|
||||
virt_dest += current_size;
|
||||
size -= current_size;
|
||||
}
|
||||
|
||||
return svm::vmxroot_error_t::error_success;
|
||||
}
|
@ -0,0 +1,237 @@
|
||||
#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<ppml4e>(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;
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
#include "pg_table.h"
|
||||
|
||||
namespace pg_table
|
||||
{
|
||||
void* translate(void* virtual_address, const ptable_entries entries)
|
||||
{
|
||||
virt_addr_t virt_addr{ virtual_address };
|
||||
virt_addr_t cursor{ hyperv_pml4 };
|
||||
|
||||
if (entries) entries->pml4e = reinterpret_cast<ppml4e>(cursor.value)[virt_addr.pml4_index];
|
||||
if (!reinterpret_cast<ppml4e>(cursor.value)[virt_addr.pml4_index].present)
|
||||
return nullptr;
|
||||
|
||||
// set the cursor to self reference so that when we read
|
||||
// the addresses pointed to by cursor its going to be a pdpt...
|
||||
cursor.pdpt_index = virt_addr_t{ hyperv_pml4 }.pml4_index;
|
||||
cursor.pd_index = virt_addr_t{ hyperv_pml4 }.pml4_index;
|
||||
cursor.pt_index = virt_addr.pml4_index;
|
||||
if (entries) entries->pdpte = reinterpret_cast<ppdpte>(cursor.value)[virt_addr.pdpt_index];
|
||||
|
||||
if (!reinterpret_cast<ppdpte>(cursor.value)[virt_addr.pdpt_index].present)
|
||||
return nullptr;
|
||||
|
||||
// set the cursor to self reference so that when we read
|
||||
// the addresses pointed to by cursor its going to be a pd...
|
||||
cursor.pdpt_index = virt_addr_t{ hyperv_pml4 }.pml4_index;
|
||||
cursor.pd_index = virt_addr.pml4_index;
|
||||
cursor.pt_index = virt_addr.pdpt_index;
|
||||
if (entries) entries->pde = reinterpret_cast<ppde>(cursor.value)[virt_addr.pd_index];
|
||||
|
||||
if (!reinterpret_cast<ppde>(cursor.value)[virt_addr.pd_index].present)
|
||||
return nullptr;
|
||||
|
||||
// set the cursor to self reference so that when we read
|
||||
// the addresses pointed to by cursor its going to be a pt...
|
||||
cursor.pdpt_index = virt_addr.pml4_index;
|
||||
cursor.pd_index = virt_addr.pdpt_index;
|
||||
cursor.pt_index = virt_addr.pd_index;
|
||||
if (entries) entries->pte = reinterpret_cast<ppte>(cursor.value)[virt_addr.pt_index];
|
||||
|
||||
if (!reinterpret_cast<ppte>(cursor.value)[virt_addr.pt_index].present)
|
||||
return nullptr;
|
||||
|
||||
return reinterpret_cast<void*>(
|
||||
reinterpret_cast<ppte>(cursor.value)[virt_addr.pt_index].pfn << 12);
|
||||
}
|
||||
|
||||
void* translate(void* virtual_address, u32 pml4_pfn, const ptable_entries entries)
|
||||
{
|
||||
virt_addr_t virt_addr{ virtual_address };
|
||||
const auto cursor = get_cursor_page();
|
||||
|
||||
set_cursor_page(pml4_pfn);
|
||||
if (!reinterpret_cast<ppml4e>(cursor)[virt_addr.pml4_index].present)
|
||||
return nullptr;
|
||||
|
||||
if (entries) entries->pml4e = reinterpret_cast<ppml4e>(cursor)[virt_addr.pml4_index];
|
||||
set_cursor_page(reinterpret_cast<ppml4e>(cursor)[virt_addr.pml4_index].pfn);
|
||||
if (!reinterpret_cast<ppdpte>(cursor)[virt_addr.pdpt_index].present)
|
||||
return nullptr;
|
||||
|
||||
if (entries) entries->pdpte = reinterpret_cast<ppdpte>(cursor)[virt_addr.pdpt_index];
|
||||
set_cursor_page(reinterpret_cast<ppdpte>(cursor)[virt_addr.pdpt_index].pfn);
|
||||
if (!reinterpret_cast<ppde>(cursor)[virt_addr.pd_index].present)
|
||||
return nullptr;
|
||||
|
||||
if (entries) entries->pde = reinterpret_cast<ppde>(cursor)[virt_addr.pd_index];
|
||||
set_cursor_page(reinterpret_cast<ppde>(cursor)[virt_addr.pd_index].pfn);
|
||||
if (!reinterpret_cast<ppte>(cursor)[virt_addr.pt_index].present)
|
||||
return nullptr;
|
||||
|
||||
if (entries) entries->pte = reinterpret_cast<ppte>(cursor)[virt_addr.pt_index];
|
||||
return reinterpret_cast<void*>(
|
||||
reinterpret_cast<ppte>(cursor)[virt_addr.pt_index].pfn << 12);
|
||||
}
|
||||
|
||||
void set_cursor_page(u32 phys_pfn)
|
||||
{
|
||||
cpuid_eax_01 cpuid_value;
|
||||
__cpuid((int*)&cpuid_value, 1);
|
||||
pg_table::pt[cpuid_value
|
||||
.cpuid_additional_information
|
||||
.initial_apic_id].pfn = phys_pfn;
|
||||
|
||||
// flush tlb for this page and then ensure the instruction stream
|
||||
// is seralized as to not execute instructions out of order and access the page
|
||||
// before the TLB is flushed...
|
||||
__invlpg(get_cursor_page());
|
||||
_mm_lfence();
|
||||
}
|
||||
|
||||
void* get_cursor_page()
|
||||
{
|
||||
cpuid_eax_01 cpuid_value;
|
||||
__cpuid((int*)&cpuid_value, 1);
|
||||
constexpr auto cursor_page = |