You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
2.9 KiB

#include "libvoyager.hpp"
#include <Windows.h>
#include <iostream>
// taken from hvpp (wbenny). this code runs specific code on each logical processor...
// this is required since hyper-v has its own PML4 for each core...
// https://github.com/wbenny/hvpp/blob/master/src/hvppctrl/lib/mp.cpp#L4
auto voyager::init() -> vmxroot_error_t
{
GROUP_AFFINITY orig_group_affinity;
GetThreadGroupAffinity(GetCurrentThread(), &orig_group_affinity);
const auto group_count = GetActiveProcessorGroupCount();
// each core we are going to vmexit on and ask the payload
// to setup the mapping pml4e. for some reason each core on
// hyper-v has its own pml4... Not sure why? just is...
for (auto group_number = 0u; group_number < group_count; ++group_number)
{
const auto processor_count = GetActiveProcessorCount(group_number);
for (auto processor_number = 0u; processor_number < processor_count; ++processor_number)
{
GROUP_AFFINITY group_affinity = { 0 };
group_affinity.Mask = (KAFFINITY)(1) << processor_number;
group_affinity.Group = group_number;
SetThreadGroupAffinity(GetCurrentThread(), &group_affinity, NULL);
auto result = hypercall(VMEXIT_KEY, vmexit_command_t::init_page_tables, nullptr);
if (result != vmxroot_error_t::error_success)
return result;
}
}
SetThreadGroupAffinity(GetCurrentThread(), &orig_group_affinity, NULL);
return vmxroot_error_t::error_success;
}
auto voyager::current_dirbase()->guest_phys_t
{
command_t command;
auto result = hypercall(VMEXIT_KEY, vmexit_command_t::get_dirbase, &command);
if (result != vmxroot_error_t::error_success)
return {};
return command.dirbase;
}
auto voyager::translate(guest_virt_t virt_addr) -> guest_phys_t
{
command_t command;
command.translate_virt.virt_src = virt_addr;
const auto result = hypercall(VMEXIT_KEY, vmexit_command_t::translate, &command);
if (result != vmxroot_error_t::error_success)
return {};
return command.translate_virt.phys_addr;
}
auto voyager::read_phys(guest_phys_t phys_addr, guest_virt_t buffer, u64 size) -> vmxroot_error_t
{
command_t command;
command.copy_phys = { phys_addr, buffer, size };
return hypercall(VMEXIT_KEY, vmexit_command_t::read_guest_phys, &command);
}
auto voyager::write_phys(guest_phys_t phys_addr, guest_virt_t buffer, u64 size) -> vmxroot_error_t
{
command_t command;
command.copy_phys = { phys_addr, buffer, size };
return hypercall(VMEXIT_KEY, vmexit_command_t::write_guest_phys, &command);
}
auto voyager::copy_virt(guest_phys_t dirbase_src, guest_virt_t virt_src, guest_phys_t dirbase_dest,
guest_virt_t virt_dest, u64 size) -> vmxroot_error_t
{
command_t command;
command.copy_virt = { dirbase_src, virt_src, dirbase_dest, virt_dest, size };
return hypercall(VMEXIT_KEY, vmexit_command_t::copy_guest_virt, &command);
}