Merge branch 'dev' into 'master'

added some event injection fixes, NMI injection was causing loops...

See merge request _xeroxz/bluepill!4
merge-requests/5/merge
_xeroxz 4 years ago
commit 5e6ded4cbc

@ -85,8 +85,10 @@
<FilesToPackage Include="$(TargetPath)" /> <FilesToPackage Include="$(TargetPath)" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="command.cpp" />
<ClCompile Include="debug.cpp" /> <ClCompile Include="debug.cpp" />
<ClCompile Include="drv_entry.cpp" /> <ClCompile Include="drv_entry.cpp" />
<ClCompile Include="exception.cpp" />
<ClCompile Include="exit_handler.cpp" /> <ClCompile Include="exit_handler.cpp" />
<ClCompile Include="gdt.cpp" /> <ClCompile Include="gdt.cpp" />
<ClCompile Include="idt.cpp" /> <ClCompile Include="idt.cpp" />
@ -96,11 +98,12 @@
<ClCompile Include="vmxon.cpp" /> <ClCompile Include="vmxon.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="command.hpp" />
<ClInclude Include="debug.hpp" /> <ClInclude Include="debug.hpp" />
<ClInclude Include="exception.hpp" />
<ClInclude Include="gdt.hpp" /> <ClInclude Include="gdt.hpp" />
<ClInclude Include="ia32.hpp" /> <ClInclude Include="ia32.hpp" />
<ClInclude Include="idt.hpp" /> <ClInclude Include="idt.hpp" />
<ClInclude Include="invd.hpp" />
<ClInclude Include="mm.hpp" /> <ClInclude Include="mm.hpp" />
<ClInclude Include="segment_intrin.h" /> <ClInclude Include="segment_intrin.h" />
<ClInclude Include="hv_types.hpp" /> <ClInclude Include="hv_types.hpp" />
@ -111,7 +114,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<MASM Include="idt_handlers.asm" /> <MASM Include="idt_handlers.asm" />
<MASM Include="invd.asm" />
<MASM Include="segment_intrin.asm" /> <MASM Include="segment_intrin.asm" />
<MASM Include="vmxexit_handler.asm" /> <MASM Include="vmxexit_handler.asm" />
</ItemGroup> </ItemGroup>

@ -38,6 +38,12 @@
<ClCompile Include="gdt.cpp"> <ClCompile Include="gdt.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="command.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="exception.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="vmxon.hpp"> <ClInclude Include="vmxon.hpp">
@ -67,15 +73,18 @@
<ClInclude Include="idt.hpp"> <ClInclude Include="idt.hpp">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="invd.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="debug.hpp"> <ClInclude Include="debug.hpp">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="gdt.hpp"> <ClInclude Include="gdt.hpp">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="command.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="exception.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<MASM Include="segment_intrin.asm"> <MASM Include="segment_intrin.asm">
@ -84,9 +93,6 @@
<MASM Include="vmxexit_handler.asm"> <MASM Include="vmxexit_handler.asm">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</MASM> </MASM>
<MASM Include="invd.asm">
<Filter>Source Files</Filter>
</MASM>
<MASM Include="idt_handlers.asm"> <MASM Include="idt_handlers.asm">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</MASM> </MASM>

@ -0,0 +1,26 @@
#include "command.hpp"
namespace command
{
auto get(u64 dirbase, u64 command_ptr) -> vmcall_command_t
{
const auto virt_map =
mm::map_virt(dirbase, command_ptr);
if (!virt_map)
return {};
return *reinterpret_cast<pvmcall_command_t>(virt_map);
}
auto set(u64 dirbase, u64 command_ptr, const vmcall_command_t& vmcall_command) -> void
{
const auto virt_map =
mm::map_virt(dirbase, command_ptr);
if (!virt_map)
return;
*reinterpret_cast<pvmcall_command_t>(virt_map) = vmcall_command;
}
}

@ -0,0 +1,62 @@
#pragma once
#include "mm.hpp"
namespace command
{
enum class vmcall_option
{
translate,
copy_virt,
write_phys,
read_phys,
dirbase
};
typedef struct _vmcall_command_t
{
bool present;
bool result;
vmcall_option option;
union
{
struct
{
u64 dirbase;
u64 virt_addr;
u64 phys_addr;
} translate;
struct
{
u64 virt_src;
u64 dirbase_src;
u64 virt_dest;
u64 dirbase_dest;
u64 size;
} copy_virt;
struct
{
u64 virt_src;
u64 dirbase_src;
u64 phys_dest;
u64 size;
} write_phys;
struct
{
u64 phys_src;
u64 dirbase_dest;
u64 virt_dest;
u64 size;
} read_phys;
u64 dirbase;
};
} vmcall_command_t, * pvmcall_command_t;
auto get(u64 dirbase, u64 command_ptr)->vmcall_command_t;
auto set(u64 dirbase, u64 command_ptr, const vmcall_command_t& vmcall_command) -> void;
}

@ -0,0 +1,48 @@
#include "exception.hpp"
namespace exception
{
auto handle_debug() -> void
{
rflags g_rflags;
ia32_debugctl_register debugctl;
__vmx_vmread(VMCS_GUEST_RFLAGS, &g_rflags.flags);
__vmx_vmread(VMCS_GUEST_DEBUGCTL, &debugctl.flags);
// should also check: if ((g_rflags.trap_flag && (debugctl.btf && instruction.type == branching))
if (g_rflags.trap_flag && !debugctl.btf)
{
vmx_exit_qualification_debug_exception pending_db;
__vmx_vmread(VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, &pending_db.flags);
pending_db.single_instruction = true;
__vmx_vmwrite(VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, pending_db.flags);
}
vmx_interruptibility_state interrupt_state;
__vmx_vmread(VMCS_GUEST_INTERRUPTIBILITY_STATE,
reinterpret_cast<size_t*>(&interrupt_state.flags));
// not going to clear blocked by NMI or
// SMI stuff as IRETQ should unblock that...
// im not emulating IRETQ instruction either...
interrupt_state.blocking_by_mov_ss = false;
interrupt_state.blocking_by_sti = false;
__vmx_vmwrite(VMCS_GUEST_INTERRUPTIBILITY_STATE, interrupt_state.flags);
}
auto injection(interruption_type type, u8 vector, ecode_t error_code) -> void
{
vmentry_interrupt_information interrupt{};
interrupt.interruption_type = type;
interrupt.vector = vector;
interrupt.valid = true;
if (error_code.valid)
{
interrupt.deliver_error_code = error_code.valid;
__vmx_vmwrite(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE, error_code.valid);
}
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
}
}

@ -0,0 +1,11 @@
#pragma once
#include "hv_types.hpp"
namespace exception
{
using ecode_t = struct { bool valid; u64 value; };
auto injection(interruption_type type, u8 vector, ecode_t error_code = {}) -> void;
// https://howtohypervise.blogspot.com/2019/01/a-common-missight-in-most-hypervisors.html
auto handle_debug() -> void;
}

@ -1,32 +1,10 @@
#include "vmxexit_handler.h" #include "vmxexit_handler.h"
auto get_command(u64 dirbase, u64 command_ptr) -> vmcall_command_t
{
const auto virt_map =
mm::map_virt(dirbase, command_ptr);
if (!virt_map)
return {};
return *reinterpret_cast<pvmcall_command_t>(virt_map);
}
auto set_command(u64 dirbase, u64 command_ptr, const vmcall_command_t& vmcall_command) -> void
{
const auto virt_map =
mm::map_virt(dirbase, command_ptr);
if (!virt_map)
return;
*reinterpret_cast<pvmcall_command_t>(virt_map) = vmcall_command;
}
auto vmresume_failure() -> void auto vmresume_failure() -> void
{ {
size_t value; size_t value;
__vmx_vmread(VMCS_VM_INSTRUCTION_ERROR, &value); __vmx_vmread(VMCS_VM_INSTRUCTION_ERROR, &value);
__debugbreak(); dbg::print("> vmresume error... reason = 0x%x\n", value);
} }
auto exit_handler(hv::pguest_registers regs) -> void auto exit_handler(hv::pguest_registers regs) -> void
@ -44,19 +22,13 @@ auto exit_handler(hv::pguest_registers regs) -> void
regs->rbx = result[1]; regs->rbx = result[1];
regs->rcx = result[2]; regs->rcx = result[2];
regs->rdx = result[3]; regs->rdx = result[3];
break; goto advance_rip;
} }
// shouldnt get an exit when the LP is already executing an NMI... // shouldnt get an exit when the LP is already executing an NMI...
// so it should be safe to inject an NMI here... // so it should be safe to inject an NMI here...
case VMX_EXIT_REASON_NMI_WINDOW: case VMX_EXIT_REASON_NMI_WINDOW:
{ {
vmentry_interrupt_information interrupt{}; exception::injection(interruption_type::non_maskable_interrupt, EXCEPTION_NMI);
interrupt.interruption_type = interruption_type::non_maskable_interrupt;
interrupt.vector = EXCEPTION_NMI;
interrupt.valid = true;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
__vmx_vmwrite(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE, NULL);
// turn off NMI window exiting since we handled the NMI... // turn off NMI window exiting since we handled the NMI...
ia32_vmx_procbased_ctls_register procbased_ctls; ia32_vmx_procbased_ctls_register procbased_ctls;
@ -64,16 +36,7 @@ auto exit_handler(hv::pguest_registers regs) -> void
procbased_ctls.nmi_window_exiting = false; procbased_ctls.nmi_window_exiting = false;
__vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags);
return; // dont advance rip... goto dont_advance;
}
case VMX_EXIT_REASON_EXCEPTION_OR_NMI:
{
ia32_vmx_procbased_ctls_register procbased_ctls;
__vmx_vmread(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, &procbased_ctls.flags);
procbased_ctls.nmi_window_exiting = true;
__vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags);
return; // dont advance rip...
} }
case VMX_EXIT_REASON_EXECUTE_XSETBV: case VMX_EXIT_REASON_EXECUTE_XSETBV:
{ {
@ -96,21 +59,14 @@ auto exit_handler(hv::pguest_registers regs) -> void
If the LOCK prefix is used. If the LOCK prefix is used.
*/ */
_xsetbv(regs->rcx, value.value); _xsetbv(regs->rcx, value.value);
break; goto advance_rip;
} }
__except (EXCEPTION_EXECUTE_HANDLER) __except (EXCEPTION_EXECUTE_HANDLER)
{ {
vmentry_interrupt_information interrupt{}; exception::injection(interruption_type::hardware_exception,
interrupt.interruption_type = interruption_type::hardware_exception; EXCEPTION_GP_FAULT, { true, g_vcpu.error_code });
interrupt.vector = EXCEPTION_GP_FAULT; goto dont_advance;
interrupt.valid = true;
interrupt.deliver_error_code = true;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
__vmx_vmwrite(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE, g_vcpu.error_code);
} }
return; // dont advance rip...
} }
case VMX_EXIT_REASON_EXECUTE_RDMSR: case VMX_EXIT_REASON_EXECUTE_RDMSR:
{ {
@ -127,21 +83,14 @@ auto exit_handler(hv::pguest_registers regs) -> void
regs->rdx = result.high; regs->rdx = result.high;
regs->rax = result.low; regs->rax = result.low;
break; goto advance_rip;
} }
__except (EXCEPTION_EXECUTE_HANDLER) __except (EXCEPTION_EXECUTE_HANDLER)
{ {
vmentry_interrupt_information interrupt{}; exception::injection(interruption_type::hardware_exception,
interrupt.interruption_type = interruption_type::hardware_exception; EXCEPTION_GP_FAULT, { true, g_vcpu.error_code });
interrupt.vector = EXCEPTION_GP_FAULT; goto dont_advance;
interrupt.valid = true;
interrupt.deliver_error_code = true;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
__vmx_vmwrite(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE, g_vcpu.error_code);
} }
return; // dont advance rip...
} }
case VMX_EXIT_REASON_EXECUTE_WRMSR: case VMX_EXIT_REASON_EXECUTE_WRMSR:
{ {
@ -158,28 +107,19 @@ auto exit_handler(hv::pguest_registers regs) -> void
#UD If the LOCK prefix is used. #UD If the LOCK prefix is used.
*/ */
__writemsr(regs->rcx, value.value); __writemsr(regs->rcx, value.value);
break; goto advance_rip;
} }
__except (EXCEPTION_EXECUTE_HANDLER) __except (EXCEPTION_EXECUTE_HANDLER)
{ {
vmentry_interrupt_information interrupt{}; exception::injection(interruption_type::hardware_exception,
interrupt.interruption_type = interruption_type::hardware_exception; EXCEPTION_GP_FAULT, { true, g_vcpu.error_code });
interrupt.vector = EXCEPTION_GP_FAULT; goto dont_advance;
interrupt.valid = true;
interrupt.deliver_error_code = true;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
__vmx_vmwrite(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE, g_vcpu.error_code);
} }
return; // dont advance rip...
} }
case VMX_EXIT_REASON_EXECUTE_INVD: case VMX_EXIT_REASON_EXECUTE_INVD:
{ {
// couldnt find the intrin for this so i just made one... __wbinvd();
// probably could have used __wbinvd? goto advance_rip;
__invd();
break;
} }
case VMX_EXIT_REASON_EXECUTE_VMCALL: case VMX_EXIT_REASON_EXECUTE_VMCALL:
{ {
@ -188,82 +128,78 @@ auto exit_handler(hv::pguest_registers regs) -> void
cr3 dirbase; cr3 dirbase;
__vmx_vmread(VMCS_GUEST_CR3, &dirbase.flags); __vmx_vmread(VMCS_GUEST_CR3, &dirbase.flags);
auto command = get_command( auto command = command::get(
dirbase.pml4_pfn << 12, regs->rdx); dirbase.pml4_pfn << 12, regs->rdx);
if (command.present) if (!command.present)
{ {
switch (command.option) exception::injection(interruption_type::hardware_exception, EXCEPTION_INVALID_OPCODE);
{ goto dont_advance;
case vmcall_option::copy_virt: }
{
command.result =
mm::copy_virt(
command.copy_virt.dirbase_src,
command.copy_virt.virt_src,
command.copy_virt.dirbase_dest,
command.copy_virt.virt_dest,
command.copy_virt.size);
break;
}
case vmcall_option::translate:
{
command.translate.phys_addr =
mm::translate(mm::virt_addr_t{
command.translate.virt_addr },
command.translate.dirbase);
// true if address is not null...
command.result = command.translate.phys_addr;
break;
}
case vmcall_option::read_phys:
{
command.result =
mm::read_phys(
command.read_phys.dirbase_dest,
command.read_phys.phys_src,
command.read_phys.virt_dest,
command.read_phys.size);
break;
}
case vmcall_option::write_phys:
{
command.result =
mm::write_phys(
command.write_phys.dirbase_src,
command.write_phys.phys_dest,
command.write_phys.virt_src,
command.write_phys.size);
break;
}
case vmcall_option::dirbase:
{
command.result = true;
command.dirbase = dirbase.pml4_pfn << 12;
break;
}
default:
// check to see why the option was invalid...
__debugbreak();
break;
}
set_command(dirbase.pml4_pfn << 12, regs->rdx, command); switch (command.option)
{
case command::vmcall_option::copy_virt:
{
command.result =
mm::copy_virt(
command.copy_virt.dirbase_src,
command.copy_virt.virt_src,
command.copy_virt.dirbase_dest,
command.copy_virt.virt_dest,
command.copy_virt.size);
break;
}
case command::vmcall_option::translate:
{
command.translate.phys_addr =
mm::translate(mm::virt_addr_t{
command.translate.virt_addr },
command.translate.dirbase);
// true if address is not null...
command.result = command.translate.phys_addr;
break;
}
case command::vmcall_option::read_phys:
{
command.result =
mm::read_phys(
command.read_phys.dirbase_dest,
command.read_phys.phys_src,
command.read_phys.virt_dest,
command.read_phys.size);
break;
} }
case command::vmcall_option::write_phys:
{
command.result =
mm::write_phys(
command.write_phys.dirbase_src,
command.write_phys.phys_dest,
command.write_phys.virt_src,
command.write_phys.size);
break;
}
case command::vmcall_option::dirbase:
{
command.result = true;
command.dirbase = dirbase.pml4_pfn << 12;
break;
}
default:
// check to see why the option was invalid...
__debugbreak();
}
command::set(dirbase.pml4_pfn << 12, regs->rdx, command);
goto advance_rip;
} }
else else
{ {
vmentry_interrupt_information interrupt{}; exception::injection(interruption_type::hardware_exception, EXCEPTION_INVALID_OPCODE);
interrupt.interruption_type = interruption_type::hardware_exception; goto dont_advance;
interrupt.vector = EXCEPTION_INVALID_OPCODE;
interrupt.valid = true;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
__vmx_vmwrite(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE, NULL);
return; // dont advance rip...
} }
break;
} }
case VMX_EXIT_REASON_EXECUTE_VMWRITE: case VMX_EXIT_REASON_EXECUTE_VMWRITE:
case VMX_EXIT_REASON_EXECUTE_VMREAD: case VMX_EXIT_REASON_EXECUTE_VMREAD:
@ -272,24 +208,27 @@ auto exit_handler(hv::pguest_registers regs) -> void
case VMX_EXIT_REASON_EXECUTE_VMCLEAR: case VMX_EXIT_REASON_EXECUTE_VMCLEAR:
case VMX_EXIT_REASON_EXECUTE_VMXOFF: case VMX_EXIT_REASON_EXECUTE_VMXOFF:
case VMX_EXIT_REASON_EXECUTE_VMXON: case VMX_EXIT_REASON_EXECUTE_VMXON:
case VMX_EXIT_REASON_EXECUTE_VMFUNC:
{ {
vmentry_interrupt_information interrupt{}; exception::injection(interruption_type::hardware_exception, EXCEPTION_INVALID_OPCODE);
interrupt.interruption_type = interruption_type::hardware_exception; goto dont_advance;
interrupt.vector = EXCEPTION_INVALID_OPCODE;
interrupt.valid = true;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interrupt.flags);
__vmx_vmwrite(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE, NULL);
return; // dont advance rip...
} }
default: default:
// TODO: check out the vmexit reason and add support for it... // TODO: check out the vmexit reason and add support for it...
__debugbreak(); __debugbreak();
break;
} }
advance_rip:
size_t rip, exec_len; size_t rip, exec_len;
__vmx_vmread(VMCS_GUEST_RIP, &rip); __vmx_vmread(VMCS_GUEST_RIP, &rip);
__vmx_vmread(VMCS_VMEXIT_INSTRUCTION_LENGTH, &exec_len); __vmx_vmread(VMCS_VMEXIT_INSTRUCTION_LENGTH, &exec_len);
__vmx_vmwrite(VMCS_GUEST_RIP, rip + exec_len); __vmx_vmwrite(VMCS_GUEST_RIP, rip + exec_len);
// since we are advancing RIP, also check if TF = 1, if so, set pending #DB...
// otherwise this #DB will fire on the wrong instruction... please refer to:
// https://howtohypervise.blogspot.com/2019/01/a-common-missight-in-most-hypervisors.html
exception::handle_debug();
dont_advance:
return;
} }

@ -16605,6 +16605,7 @@ typedef struct
*/ */
typedef union typedef union
{ {
uint64_t flags;
struct struct
{ {
/** /**
@ -16644,8 +16645,6 @@ typedef union
#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION(_) (((_) >> 14) & 0x01) #define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION(_) (((_) >> 14) & 0x01)
uint64_t reserved2 : 49; uint64_t reserved2 : 49;
}; };
uint64_t flags;
} vmx_exit_qualification_debug_exception; } vmx_exit_qualification_debug_exception;
/** /**

@ -1,6 +0,0 @@
.code
__invd proc
invd
ret
__invd endp
end

@ -1,2 +0,0 @@
#pragma once
extern "C" void __invd(void);

@ -145,14 +145,8 @@ namespace mm
if (!mapped_src) if (!mapped_src)
return false; return false;
__try __try { memcpy(mapped_dest, mapped_src, current_size); }
{ __except (EXCEPTION_EXECUTE_HANDLER) { return false; }
memcpy(mapped_dest, mapped_src, current_size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return false;
}
guest_phys += current_size; guest_phys += current_size;
guest_virt += current_size; guest_virt += current_size;
@ -196,14 +190,8 @@ namespace mm
if (!mapped_src) if (!mapped_src)
return false; return false;
__try __try { memcpy(mapped_dest, mapped_src, current_size); }
{ __except (EXCEPTION_EXECUTE_HANDLER){ return false; }
memcpy(mapped_dest, mapped_src, current_size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return false;
}
guest_phys += current_size; guest_phys += current_size;
guest_virt += current_size; guest_virt += current_size;
@ -242,14 +230,8 @@ namespace mm
// copy directly between the two pages... // copy directly between the two pages...
auto current_size = min(dest_size, src_size); auto current_size = min(dest_size, src_size);
__try __try{ memcpy(mapped_dest, mapped_src, current_size); }
{ __except (EXCEPTION_EXECUTE_HANDLER){ return false; }
memcpy(mapped_dest, mapped_src, current_size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return false;
}
virt_src += current_size; virt_src += current_size;
virt_dest += current_size; virt_dest += current_size;

@ -152,9 +152,7 @@ namespace vmcs
ia32_vmx_exit_ctls_register exit_ctls{}; ia32_vmx_exit_ctls_register exit_ctls{};
ia32_vmx_basic_register vmx_basic{ __readmsr(IA32_VMX_BASIC) }; ia32_vmx_basic_register vmx_basic{ __readmsr(IA32_VMX_BASIC) };
pinbased_ctls.nmi_exiting = true;
pinbased_ctls.virtual_nmi = true; pinbased_ctls.virtual_nmi = true;
procbased_ctls.activate_secondary_controls = true; procbased_ctls.activate_secondary_controls = true;
exit_ctls.host_address_space_size = true; exit_ctls.host_address_space_size = true;
@ -164,7 +162,6 @@ namespace vmcs
procbased_ctls2.enable_rdtscp = true; procbased_ctls2.enable_rdtscp = true;
procbased_ctls2.enable_xsaves = true; procbased_ctls2.enable_xsaves = true;
procbased_ctls2.conceal_vmx_from_pt = true; procbased_ctls2.conceal_vmx_from_pt = true;
//procbased_ctls2.enable_ept = true;
if (vmx_basic.vmx_controls) if (vmx_basic.vmx_controls)
{ {
@ -211,13 +208,6 @@ namespace vmcs
__vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags); __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags);
} }
/*ept_pointer eptp{};
eptp.memory_type = MEMORY_TYPE_WRITE_BACK;
eptp.enable_access_and_dirty_flags = true;
eptp.page_walk_length = EPT_PAGE_WALK_LENGTH_4;
eptp.page_frame_number = reinterpret_cast<u64>(&mm::epml4) >> 12;
__vmx_vmwrite(VMCS_CTRL_EPT_POINTER, eptp.flags);*/
msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS2); msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS2);
procbased_ctls2.flags &= msr_fix_value.allowed_1_settings; procbased_ctls2.flags &= msr_fix_value.allowed_1_settings;
procbased_ctls2.flags |= msr_fix_value.allowed_0_settings; procbased_ctls2.flags |= msr_fix_value.allowed_0_settings;

@ -101,6 +101,6 @@ vmxexit_handler proc
vmresume vmresume
call vmresume_failure call vmresume_failure
hlt int 3
vmxexit_handler endp vmxexit_handler endp
end end

@ -1,67 +1,11 @@
#pragma once #pragma once
#include "hv_types.hpp" #include "hv_types.hpp"
#include "debug.hpp" #include "debug.hpp"
#include "invd.hpp"
#include "mm.hpp" #include "mm.hpp"
#include "vmxon.hpp" #include "vmxon.hpp"
#include "command.hpp"
enum class vmcall_option #include "exception.hpp"
{
translate,
copy_virt,
write_phys,
read_phys,
dirbase
};
typedef struct _vmcall_command_t
{
bool present;
bool result;
vmcall_option option;
union
{
struct
{
u64 dirbase;
u64 virt_addr;
u64 phys_addr;
} translate;
struct
{
u64 virt_src;
u64 dirbase_src;
u64 virt_dest;
u64 dirbase_dest;
u64 size;
} copy_virt;
struct
{
u64 virt_src;
u64 dirbase_src;
u64 phys_dest;
u64 size;
} write_phys;
struct
{
u64 phys_src;
u64 dirbase_dest;
u64 virt_dest;
u64 size;
} read_phys;
u64 dirbase;
};
} vmcall_command_t, * pvmcall_command_t;
extern "C" auto vmxexit_handler() -> void; extern "C" auto vmxexit_handler() -> void;
extern "C" auto vmresume_failure() -> void; extern "C" auto vmresume_failure() -> void;
extern "C" auto exit_handler(hv::pguest_registers regs) -> void; extern "C" auto exit_handler(hv::pguest_registers regs) -> void;
auto get_command(u64 dirbase, u64 command_ptr) -> vmcall_command_t;
auto set_command(u64 dirbase, u64 command_ptr, const vmcall_command_t& vmcall_command) -> void;
Loading…
Cancel
Save