parent
06af7e9dab
commit
84cee2e610
@ -0,0 +1,38 @@
|
||||
#include "segment_intrin.h"
|
||||
|
||||
namespace segment
|
||||
{
|
||||
auto get_access_rights(segment_descriptor_64* segment_descriptor) -> vmx_segment_access_rights
|
||||
{
|
||||
vmx_segment_access_rights result;
|
||||
result.granularity = segment_descriptor->granularity;
|
||||
result.type = segment_descriptor->type;
|
||||
result.descriptor_type = segment_descriptor->descriptor_type;
|
||||
result.present = segment_descriptor->present;
|
||||
result.long_mode = segment_descriptor->long_mode;
|
||||
result.available_bit = segment_descriptor->system;
|
||||
result.default_big = segment_descriptor->default_big;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto get_info(segment_descriptor_register_64 gdt_value, segment_selector segment_selector) -> hv::segment_info_ctx
|
||||
{
|
||||
hv::segment_info_ctx segment_info;
|
||||
const auto segment_descriptor =
|
||||
reinterpret_cast<segment_descriptor_64*>(
|
||||
gdt_value.base_address + (segment_selector.index << SEGMENT_SELECTOR_INDEX_BIT));
|
||||
|
||||
segment_info.limit = __segmentlimit(segment_selector.flags);
|
||||
segment_info.rights = get_access_rights(segment_descriptor);
|
||||
|
||||
segment_info.base_addr = (u32)((segment_descriptor->base_address_high << SEGMENT__BASE_ADDRESS_HIGH_BIT) |
|
||||
(segment_descriptor->base_address_middle << SEGMENT__BASE_ADDRESS_MIDDLE_BIT) |
|
||||
(segment_descriptor->base_address_low));
|
||||
|
||||
segment_info.base_addr &= 0xFFFFFFFF;
|
||||
if (!segment_descriptor->descriptor_type)
|
||||
segment_info.base_addr |= ((u64)segment_descriptor->base_address_upper << SEGMENT__BASE_ADDRESS_SHIFT);
|
||||
|
||||
return segment_info;
|
||||
}
|
||||
}
|
@ -1,9 +1,17 @@
|
||||
#pragma once
|
||||
#include "hv_types.hpp"
|
||||
|
||||
extern "C" u64 readfs(void);
|
||||
extern "C" u64 readgs(void);
|
||||
extern "C" u64 reades(void);
|
||||
extern "C" u64 readds(void);
|
||||
extern "C" u64 readss(void);
|
||||
extern "C" u64 readcs(void);
|
||||
extern "C" u16 readfs(void);
|
||||
extern "C" u16 readgs(void);
|
||||
extern "C" u16 reades(void);
|
||||
extern "C" u16 readds(void);
|
||||
extern "C" u16 readss(void);
|
||||
extern "C" u16 readcs(void);
|
||||
extern "C" u16 readtr(void);
|
||||
extern "C" u16 readldt(void);
|
||||
|
||||
namespace segment
|
||||
{
|
||||
auto get_info(segment_descriptor_register_64 gdt_value, segment_selector segment_selector) -> hv::segment_info_ctx;
|
||||
auto get_access_rights(segment_descriptor_64* segment_descriptor) -> vmx_segment_access_rights;
|
||||
}
|
@ -0,0 +1,216 @@
|
||||
#include "vmcs.hpp"
|
||||
|
||||
namespace vmcs
|
||||
{
|
||||
auto setup_host(void* host_rip, u64 host_rsp) -> void
|
||||
{
|
||||
segment_descriptor_register_64 gdt_value;
|
||||
segment_descriptor_register_64 idt_value;
|
||||
|
||||
__sidt(&idt_value);
|
||||
_sgdt(&gdt_value);
|
||||
|
||||
__vmx_vmwrite(VMCS_HOST_CR0, __readcr0());
|
||||
__vmx_vmwrite(VMCS_HOST_CR3, __readcr3());
|
||||
__vmx_vmwrite(VMCS_HOST_CR4, __readcr4());
|
||||
|
||||
__vmx_vmwrite(VMCS_HOST_RIP, reinterpret_cast<u64>(host_rip));
|
||||
__vmx_vmwrite(VMCS_HOST_RSP, host_rsp);
|
||||
|
||||
__vmx_vmwrite(VMCS_HOST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS));
|
||||
__vmx_vmwrite(VMCS_HOST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP));
|
||||
__vmx_vmwrite(VMCS_HOST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP));
|
||||
|
||||
__vmx_vmwrite(VMCS_HOST_GDTR_BASE, gdt_value.base_address);
|
||||
__vmx_vmwrite(VMCS_HOST_IDTR_BASE, idt_value.base_address);
|
||||
|
||||
__vmx_vmwrite(VMCS_HOST_ES_SELECTOR, reades());
|
||||
__vmx_vmwrite(VMCS_HOST_CS_SELECTOR, readcs());
|
||||
__vmx_vmwrite(VMCS_HOST_DS_SELECTOR, readds());
|
||||
__vmx_vmwrite(VMCS_HOST_FS_SELECTOR, readfs());
|
||||
__vmx_vmwrite(VMCS_HOST_GS_SELECTOR, readgs());
|
||||
__vmx_vmwrite(VMCS_HOST_SS_SELECTOR, readss());
|
||||
__vmx_vmwrite(VMCS_HOST_TR_SELECTOR, readtr());
|
||||
|
||||
__vmx_vmwrite(VMCS_HOST_GS_BASE, __readmsr(IA32_GS_BASE));
|
||||
__vmx_vmwrite(VMCS_HOST_FS_BASE, __readmsr(IA32_FS_BASE));
|
||||
}
|
||||
|
||||
auto setup_guest() -> void
|
||||
{
|
||||
segment_descriptor_register_64 gdt_value;
|
||||
segment_descriptor_register_64 idt_value;
|
||||
|
||||
__sidt(&idt_value);
|
||||
_sgdt(&gdt_value);
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_CR0, __readcr0());
|
||||
__vmx_vmwrite(VMCS_GUEST_CR3, __readcr3());
|
||||
__vmx_vmwrite(VMCS_GUEST_CR4, __readcr4());
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_VMCS_LINK_POINTER, ~0ULL);
|
||||
__vmx_vmwrite(VMCS_GUEST_DEBUGCTL, __readmsr(IA32_DEBUGCTL));
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_DEBUGCTL, __readmsr(IA32_DEBUGCTL));
|
||||
__vmx_vmwrite(VMCS_GUEST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS));
|
||||
__vmx_vmwrite(VMCS_GUEST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP));
|
||||
__vmx_vmwrite(VMCS_GUEST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP));
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_GDTR_BASE, gdt_value.base_address);
|
||||
__vmx_vmwrite(VMCS_GUEST_GDTR_LIMIT, gdt_value.limit);
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_IDTR_BASE, idt_value.base_address);
|
||||
__vmx_vmwrite(VMCS_GUEST_IDTR_LIMIT, idt_value.limit);
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_RFLAGS, __readeflags());
|
||||
__vmx_vmwrite(VMCS_GUEST_DR7, __readdr(7));
|
||||
|
||||
const auto [es_rights, es_limit, es_base] =
|
||||
segment::get_info(gdt_value, segment_selector{ reades() });
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_ES_BASE, es_base);
|
||||
__vmx_vmwrite(VMCS_GUEST_ES_LIMIT, es_limit);
|
||||
__vmx_vmwrite(VMCS_GUEST_ES_SELECTOR, reades());
|
||||
__vmx_vmwrite(VMCS_GUEST_ES_ACCESS_RIGHTS, es_rights.flags);
|
||||
|
||||
const auto [ds_rights, ds_limit, ds_base] =
|
||||
segment::get_info(gdt_value, segment_selector{ readds() });
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_DS_BASE, ds_base);
|
||||
__vmx_vmwrite(VMCS_GUEST_DS_LIMIT, ds_limit);
|
||||
__vmx_vmwrite(VMCS_GUEST_DS_SELECTOR, readds());
|
||||
__vmx_vmwrite(VMCS_GUEST_DS_ACCESS_RIGHTS, ds_rights.flags);
|
||||
|
||||
const auto [fs_rights, fs_limit, fs_base] =
|
||||
segment::get_info(gdt_value, segment_selector{ readfs() });
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_FS_BASE, fs_base);
|
||||
__vmx_vmwrite(VMCS_GUEST_FS_LIMIT, fs_limit);
|
||||
__vmx_vmwrite(VMCS_GUEST_FS_SELECTOR, readfs());
|
||||
__vmx_vmwrite(VMCS_GUEST_FS_ACCESS_RIGHTS, fs_rights.flags);
|
||||
|
||||
const auto [gs_rights, gs_limit, gs_base] =
|
||||
segment::get_info(gdt_value, segment_selector{ readgs() });
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_GS_BASE, gs_base);
|
||||
__vmx_vmwrite(VMCS_GUEST_GS_LIMIT, gs_limit);
|
||||
__vmx_vmwrite(VMCS_GUEST_GS_SELECTOR, readgs());
|
||||
__vmx_vmwrite(VMCS_GUEST_GS_ACCESS_RIGHTS, gs_rights.flags);
|
||||
|
||||
const auto [ss_rights, ss_limit, ss_base] =
|
||||
segment::get_info(gdt_value, segment_selector{ readss() });
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_SS_BASE, ss_base);
|
||||
__vmx_vmwrite(VMCS_GUEST_SS_LIMIT, ss_limit);
|
||||
__vmx_vmwrite(VMCS_GUEST_SS_SELECTOR, readss());
|
||||
__vmx_vmwrite(VMCS_GUEST_SS_ACCESS_RIGHTS, ss_rights.flags);
|
||||
|
||||
const auto [cs_rights, cs_limit, cs_base] =
|
||||
segment::get_info(gdt_value, segment_selector{ readcs() });
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_CS_BASE, cs_base);
|
||||
__vmx_vmwrite(VMCS_GUEST_CS_LIMIT, cs_limit);
|
||||
__vmx_vmwrite(VMCS_GUEST_CS_SELECTOR, readcs());
|
||||
__vmx_vmwrite(VMCS_GUEST_CS_ACCESS_RIGHTS, cs_rights.flags);
|
||||
|
||||
const auto [tr_rights, tr_limit, tr_base] =
|
||||
segment::get_info(gdt_value, segment_selector{ readtr() });
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_TR_BASE, tr_base);
|
||||
__vmx_vmwrite(VMCS_GUEST_TR_LIMIT, tr_limit);
|
||||
__vmx_vmwrite(VMCS_GUEST_TR_SELECTOR, readtr());
|
||||
__vmx_vmwrite(VMCS_GUEST_TR_ACCESS_RIGHTS, tr_rights.flags);
|
||||
|
||||
const auto [ldt_rights, ldt_limit, ldt_base] =
|
||||
segment::get_info(gdt_value, segment_selector{ readldt() });
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_LDTR_BASE, ldt_base);
|
||||
__vmx_vmwrite(VMCS_GUEST_LDTR_LIMIT, ldt_limit);
|
||||
__vmx_vmwrite(VMCS_GUEST_LDTR_SELECTOR, readldt());
|
||||
__vmx_vmwrite(VMCS_GUEST_LDTR_ACCESS_RIGHTS, ldt_rights.flags);
|
||||
|
||||
__vmx_vmwrite(VMCS_GUEST_GS_BASE, __readmsr(IA32_GS_BASE));
|
||||
__vmx_vmwrite(VMCS_GUEST_FS_BASE, __readmsr(IA32_FS_BASE));
|
||||
}
|
||||
|
||||
auto setup_controls() -> void
|
||||
{
|
||||
ia32_vmx_true_ctls_register msr_fix_value;
|
||||
ia32_vmx_pinbased_ctls_register pinbased_ctls;
|
||||
ia32_vmx_procbased_ctls_register procbased_ctls;
|
||||
ia32_vmx_procbased_ctls2_register procbased_ctls2;
|
||||
ia32_vmx_entry_ctls_register entry_ctls;
|
||||
ia32_vmx_exit_ctls_register exit_ctls;
|
||||
ia32_vmx_basic_register vmx_basic;
|
||||
|
||||
vmx_basic.flags = __readmsr(IA32_VMX_BASIC);
|
||||
pinbased_ctls.flags = NULL;
|
||||
procbased_ctls.flags = NULL;
|
||||
procbased_ctls2.flags = NULL;
|
||||
entry_ctls.flags = NULL;
|
||||
exit_ctls.flags = NULL;
|
||||
|
||||
if (vmx_basic.vmx_controls)
|
||||
{
|
||||
msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PINBASED_CTLS);
|
||||
pinbased_ctls.flags &= msr_fix_value.allowed_1_settings;
|
||||
pinbased_ctls.flags |= msr_fix_value.allowed_0_settings;
|
||||
__vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags);
|
||||
|
||||
msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PROCBASED_CTLS);
|
||||
procbased_ctls.flags &= msr_fix_value.allowed_1_settings;
|
||||
procbased_ctls.flags |= msr_fix_value.allowed_0_settings;
|
||||
procbased_ctls.activate_secondary_controls = true;
|
||||
__vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags);
|
||||
|
||||
msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_ENTRY_CTLS);
|
||||
entry_ctls.flags &= msr_fix_value.allowed_1_settings;
|
||||
entry_ctls.flags |= msr_fix_value.allowed_0_settings;
|
||||
entry_ctls.ia32e_mode_guest = true;
|
||||
entry_ctls.conceal_vmx_from_pt = true;
|
||||
__vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags);
|
||||
|
||||
msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_EXIT_CTLS);
|
||||
exit_ctls.flags &= msr_fix_value.allowed_1_settings;
|
||||
exit_ctls.flags |= msr_fix_value.allowed_0_settings;
|
||||
exit_ctls.host_address_space_size = true;
|
||||
exit_ctls.conceal_vmx_from_pt = true;
|
||||
__vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
msr_fix_value.flags = __readmsr(IA32_VMX_PINBASED_CTLS);
|
||||
pinbased_ctls.flags &= msr_fix_value.allowed_1_settings;
|
||||
pinbased_ctls.flags |= msr_fix_value.allowed_0_settings;
|
||||
__vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags);
|
||||
|
||||
msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS);
|
||||
procbased_ctls.flags &= msr_fix_value.allowed_1_settings;
|
||||
procbased_ctls.flags |= msr_fix_value.allowed_0_settings;
|
||||
procbased_ctls.activate_secondary_controls = true;
|
||||
__vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags);
|
||||
|
||||
msr_fix_value.flags = __readmsr(IA32_VMX_ENTRY_CTLS);
|
||||
entry_ctls.flags &= msr_fix_value.allowed_1_settings;
|
||||
entry_ctls.flags |= msr_fix_value.allowed_0_settings;
|
||||
entry_ctls.ia32e_mode_guest = true;
|
||||
entry_ctls.conceal_vmx_from_pt = true;
|
||||
__vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags);
|
||||
|
||||
msr_fix_value.flags = __readmsr(IA32_VMX_EXIT_CTLS);
|
||||
exit_ctls.flags &= msr_fix_value.allowed_1_settings;
|
||||
exit_ctls.flags |= msr_fix_value.allowed_0_settings;
|
||||
exit_ctls.host_address_space_size = true;
|
||||
exit_ctls.conceal_vmx_from_pt = true;
|
||||
__vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags);
|
||||
}
|
||||
|
||||
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_0_settings;
|
||||
procbased_ctls2.enable_rdtscp = true;
|
||||
procbased_ctls2.enable_xsaves = true;
|
||||
procbased_ctls2.conceal_vmx_from_pt = true;
|
||||
__vmx_vmwrite(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls2.flags);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "hv_types.hpp"
|
||||
#include "segment_intrin.h"
|
||||
#include "vmxexit_handler.h"
|
||||
|
||||
namespace vmcs
|
||||
{
|
||||
auto setup_host(void* host_rip, u64 host_rsp) -> void;
|
||||
auto setup_guest() -> void;
|
||||
auto setup_controls() -> void;
|
||||
}
|
Loading…
Reference in new issue