Merge branch 'dev' into 'master'

virtual nmi + nmi exiting are now always enabled

See merge request _xeroxz/bluepill!2
merge-requests/3/merge
_xeroxz 4 years ago
commit 2b6bb6c7ea

Binary file not shown.

Binary file not shown.

@ -22,6 +22,13 @@ auto set_command(u64 dirbase, u64 command_ptr, const vmcall_command_t& vmcall_co
*reinterpret_cast<pvmcall_command_t>(virt_map) = vmcall_command; *reinterpret_cast<pvmcall_command_t>(virt_map) = vmcall_command;
} }
auto vmresume_failure() -> void
{
size_t value;
__vmx_vmread(VMCS_VM_INSTRUCTION_ERROR, &value);
__debugbreak();
}
auto exit_handler(hv::pguest_registers regs) -> void auto exit_handler(hv::pguest_registers regs) -> void
{ {
u64 exit_reason; u64 exit_reason;
@ -50,31 +57,19 @@ auto exit_handler(hv::pguest_registers regs) -> void
__vmx_vmwrite(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE, NULL); __vmx_vmwrite(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE, NULL);
ia32_vmx_procbased_ctls_register procbased_ctls; ia32_vmx_procbased_ctls_register procbased_ctls;
ia32_vmx_pinbased_ctls_register pinbased_ctls;
__vmx_vmread(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, &procbased_ctls.flags); __vmx_vmread(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, &procbased_ctls.flags);
__vmx_vmread(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, &pinbased_ctls.flags);
procbased_ctls.nmi_window_exiting = false; procbased_ctls.nmi_window_exiting = false;
pinbased_ctls.virtual_nmi = 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);
__vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags);
return; // dont advance rip... return; // dont advance rip...
} }
case VMX_EXIT_REASON_EXCEPTION_OR_NMI: case VMX_EXIT_REASON_EXCEPTION_OR_NMI:
{ {
ia32_vmx_procbased_ctls_register procbased_ctls; ia32_vmx_procbased_ctls_register procbased_ctls;
ia32_vmx_pinbased_ctls_register pinbased_ctls;
__vmx_vmread(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, &procbased_ctls.flags); __vmx_vmread(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, &procbased_ctls.flags);
__vmx_vmread(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, &pinbased_ctls.flags);
procbased_ctls.nmi_window_exiting = true; procbased_ctls.nmi_window_exiting = true;
pinbased_ctls.virtual_nmi = true;
__vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags);
__vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags);
return; // dont advance rip... return; // dont advance rip...
} }
case VMX_EXIT_REASON_EXECUTE_XSETBV: case VMX_EXIT_REASON_EXECUTE_XSETBV:

@ -10444,6 +10444,7 @@ typedef union
#define IA32_VMX_EXIT_CTLS 0x00000483 #define IA32_VMX_EXIT_CTLS 0x00000483
typedef union typedef union
{ {
uint64_t flags;
struct struct
{ {
uint64_t reserved1 : 2; uint64_t reserved1 : 2;
@ -10581,8 +10582,6 @@ typedef union
#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT(_) (((_) >> 24) & 0x01) #define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT(_) (((_) >> 24) & 0x01)
uint64_t reserved6 : 39; uint64_t reserved6 : 39;
}; };
uint64_t flags;
} ia32_vmx_exit_ctls_register; } ia32_vmx_exit_ctls_register;

@ -96,16 +96,10 @@ auto seh_handler(hv::pidt_regs_t regs) -> void
auto nmi_handler(hv::pidt_regs_t regs) -> void auto nmi_handler(hv::pidt_regs_t regs) -> void
{ {
ia32_vmx_procbased_ctls_register procbased_ctls; ia32_vmx_procbased_ctls_register procbased_ctls;
ia32_vmx_pinbased_ctls_register pinbased_ctls;
__vmx_vmread(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, &procbased_ctls.flags); __vmx_vmread(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, &procbased_ctls.flags);
__vmx_vmread(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, &pinbased_ctls.flags);
procbased_ctls.nmi_window_exiting = true; procbased_ctls.nmi_window_exiting = true;
pinbased_ctls.virtual_nmi = true;
__vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags);
__vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags);
} }
namespace idt namespace idt

@ -16,9 +16,8 @@ extern "C" void seh_handler_ecode(hv::pidt_regs_ecode_t regs);
namespace idt namespace idt
{ {
__declspec(allocate(".idt")) __declspec(allocate(".idt")) inline hv::idt_entry_t table[256];
inline hv::idt_entry_t table[256]; enum ist_idx : u8 { nmi = 3, de = 4, pf = 5, gp = 6 };
enum ist_idx : u8 { nmi = 3, de = 4, pf = 5, gp = 6};
inline void* image_base = nullptr; // used for SEH... inline void* image_base = nullptr; // used for SEH...
auto create_entry(hv::idt_addr_t idt_handler, u8 ist_index) -> hv::idt_entry_t; auto create_entry(hv::idt_addr_t idt_handler, u8 ist_index) -> hv::idt_entry_t;

@ -129,8 +129,7 @@ namespace mm
inline const ppml4e vmxroot_pml4 = reinterpret_cast<ppml4e>(0x7fbfdfeff000); inline const ppml4e vmxroot_pml4 = reinterpret_cast<ppml4e>(0x7fbfdfeff000);
// make sure this is 4kb aligned or you are going to be meeting allah... // make sure this is 4kb aligned or you are going to be meeting allah...
__declspec(allocate(".pml4")) __declspec(allocate(".pml4")) inline pml4e pml4[512];
inline pml4e pml4[512];
// translate vmxroot address's... // translate vmxroot address's...
auto translate(virt_addr_t virt_addr) -> u64; auto translate(virt_addr_t virt_addr) -> u64;

@ -144,44 +144,45 @@ namespace vmcs
auto setup_controls() -> void auto setup_controls() -> void
{ {
ia32_vmx_true_ctls_register msr_fix_value; ia32_vmx_true_ctls_register msr_fix_value{};
ia32_vmx_pinbased_ctls_register pinbased_ctls; ia32_vmx_pinbased_ctls_register pinbased_ctls{};
ia32_vmx_procbased_ctls_register procbased_ctls; ia32_vmx_procbased_ctls_register procbased_ctls{};
ia32_vmx_procbased_ctls2_register procbased_ctls2; ia32_vmx_procbased_ctls2_register procbased_ctls2{};
ia32_vmx_entry_ctls_register entry_ctls; ia32_vmx_entry_ctls_register entry_ctls{};
ia32_vmx_exit_ctls_register exit_ctls; ia32_vmx_exit_ctls_register exit_ctls{};
ia32_vmx_basic_register vmx_basic; ia32_vmx_basic_register vmx_basic{ __readmsr(IA32_VMX_BASIC) };
vmx_basic.flags = __readmsr(IA32_VMX_BASIC); pinbased_ctls.nmi_exiting = true;
pinbased_ctls.flags = NULL; pinbased_ctls.virtual_nmi = true;
procbased_ctls.flags = NULL;
procbased_ctls2.flags = NULL; procbased_ctls.activate_secondary_controls = true;
entry_ctls.flags = NULL; exit_ctls.host_address_space_size = true;
exit_ctls.flags = NULL;
entry_ctls.ia32e_mode_guest = true;
entry_ctls.conceal_vmx_from_pt = true;
procbased_ctls2.enable_rdtscp = true;
procbased_ctls2.enable_xsaves = true;
procbased_ctls2.conceal_vmx_from_pt = true;
if (vmx_basic.vmx_controls) if (vmx_basic.vmx_controls)
{ {
msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PINBASED_CTLS); msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PINBASED_CTLS);
pinbased_ctls.nmi_exiting = true;
pinbased_ctls.flags &= msr_fix_value.allowed_1_settings; pinbased_ctls.flags &= msr_fix_value.allowed_1_settings;
pinbased_ctls.flags |= msr_fix_value.allowed_0_settings; pinbased_ctls.flags |= msr_fix_value.allowed_0_settings;
__vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags); __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags);
msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PROCBASED_CTLS); msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_PROCBASED_CTLS);
procbased_ctls.activate_secondary_controls = true;
procbased_ctls.flags &= msr_fix_value.allowed_1_settings; procbased_ctls.flags &= msr_fix_value.allowed_1_settings;
procbased_ctls.flags |= msr_fix_value.allowed_0_settings; procbased_ctls.flags |= msr_fix_value.allowed_0_settings;
__vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags);
msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_ENTRY_CTLS); msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_ENTRY_CTLS);
entry_ctls.ia32e_mode_guest = true;
entry_ctls.conceal_vmx_from_pt = true;
entry_ctls.flags &= msr_fix_value.allowed_1_settings; entry_ctls.flags &= msr_fix_value.allowed_1_settings;
entry_ctls.flags |= msr_fix_value.allowed_0_settings; entry_ctls.flags |= msr_fix_value.allowed_0_settings;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags); __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags);
msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_EXIT_CTLS); msr_fix_value.flags = __readmsr(IA32_VMX_TRUE_EXIT_CTLS);
exit_ctls.host_address_space_size = true;
exit_ctls.flags &= msr_fix_value.allowed_1_settings; exit_ctls.flags &= msr_fix_value.allowed_1_settings;
exit_ctls.flags |= msr_fix_value.allowed_0_settings; exit_ctls.flags |= msr_fix_value.allowed_0_settings;
__vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags); __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags);
@ -189,36 +190,27 @@ namespace vmcs
else else
{ {
msr_fix_value.flags = __readmsr(IA32_VMX_PINBASED_CTLS); msr_fix_value.flags = __readmsr(IA32_VMX_PINBASED_CTLS);
pinbased_ctls.nmi_exiting = true;
pinbased_ctls.flags &= msr_fix_value.allowed_1_settings; pinbased_ctls.flags &= msr_fix_value.allowed_1_settings;
pinbased_ctls.flags |= msr_fix_value.allowed_0_settings; pinbased_ctls.flags |= msr_fix_value.allowed_0_settings;
__vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags); __vmx_vmwrite(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_ctls.flags);
msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS); msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS);
procbased_ctls.activate_secondary_controls = true;
procbased_ctls.flags &= msr_fix_value.allowed_1_settings; procbased_ctls.flags &= msr_fix_value.allowed_1_settings;
procbased_ctls.flags |= msr_fix_value.allowed_0_settings; procbased_ctls.flags |= msr_fix_value.allowed_0_settings;
__vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags); __vmx_vmwrite(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls.flags);
msr_fix_value.flags = __readmsr(IA32_VMX_ENTRY_CTLS); msr_fix_value.flags = __readmsr(IA32_VMX_ENTRY_CTLS);
entry_ctls.ia32e_mode_guest = true;
entry_ctls.conceal_vmx_from_pt = true;
entry_ctls.flags &= msr_fix_value.allowed_1_settings; entry_ctls.flags &= msr_fix_value.allowed_1_settings;
entry_ctls.flags |= msr_fix_value.allowed_0_settings; entry_ctls.flags |= msr_fix_value.allowed_0_settings;
__vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags); __vmx_vmwrite(VMCS_CTRL_VMENTRY_CONTROLS, entry_ctls.flags);
msr_fix_value.flags = __readmsr(IA32_VMX_EXIT_CTLS); msr_fix_value.flags = __readmsr(IA32_VMX_EXIT_CTLS);
exit_ctls.host_address_space_size = true;
exit_ctls.conceal_vmx_from_pt = true;
exit_ctls.flags &= msr_fix_value.allowed_1_settings; exit_ctls.flags &= msr_fix_value.allowed_1_settings;
exit_ctls.flags |= msr_fix_value.allowed_0_settings; exit_ctls.flags |= msr_fix_value.allowed_0_settings;
__vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags); __vmx_vmwrite(VMCS_CTRL_VMEXIT_CONTROLS, exit_ctls.flags);
} }
msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS2); msr_fix_value.flags = __readmsr(IA32_VMX_PROCBASED_CTLS2);
procbased_ctls2.enable_rdtscp = true;
procbased_ctls2.enable_xsaves = true;
procbased_ctls2.conceal_vmx_from_pt = true;
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;
__vmx_vmwrite(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls2.flags); __vmx_vmwrite(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, procbased_ctls2.flags);

@ -1,4 +1,5 @@
extern exit_handler : proc extern exit_handler : proc
extern vmresume_failure : proc
.code .code
vmxlaunch_processor proc vmxlaunch_processor proc
@ -99,5 +100,7 @@ vmxexit_handler proc
pop rax pop rax
vmresume vmresume
call vmresume_failure
hlt
vmxexit_handler endp vmxexit_handler endp
end end

@ -60,6 +60,7 @@ typedef struct _vmcall_command_t
} vmcall_command_t, * pvmcall_command_t; } 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 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 get_command(u64 dirbase, u64 command_ptr) -> vmcall_command_t;

@ -33,10 +33,15 @@ auto vmxlaunch::init_vmcs(cr3 cr3_value) -> void
reinterpret_cast<u64>(ExAllocatePool(NonPagedPool, reinterpret_cast<u64>(ExAllocatePool(NonPagedPool,
PAGE_SIZE * HOST_STACK_PAGES)) + (PAGE_SIZE * HOST_STACK_PAGES); PAGE_SIZE * HOST_STACK_PAGES)) + (PAGE_SIZE * HOST_STACK_PAGES);
vcpu->gdt[segment_selector{ readtr() }.idx].base_address_upper = tss.upper; vcpu->tss.interrupt_stack_table[idt::ist_idx::nmi] =
vcpu->gdt[segment_selector{ readtr() }.idx].base_address_high = tss.high; reinterpret_cast<u64>(ExAllocatePool(NonPagedPool,
vcpu->gdt[segment_selector{ readtr() }.idx].base_address_middle = tss.middle; PAGE_SIZE * HOST_STACK_PAGES)) + (PAGE_SIZE * HOST_STACK_PAGES);
vcpu->gdt[segment_selector{ readtr() }.idx].base_address_low = tss.low;
const auto tr_idx = segment_selector{ readtr() }.idx;
vcpu->gdt[tr_idx].base_address_upper = tss.upper;
vcpu->gdt[tr_idx].base_address_high = tss.high;
vcpu->gdt[tr_idx].base_address_middle = tss.middle;
vcpu->gdt[tr_idx].base_address_low = tss.low;
vmcs::setup_host(&vmxexit_handler, vmcs::setup_host(&vmxexit_handler,
vcpu->host_stack, cr3_value, (u64)vcpu->gdt); vcpu->host_stack, cr3_value, (u64)vcpu->gdt);
@ -48,9 +53,6 @@ auto vmxlaunch::init_vmcs(cr3 cr3_value) -> void
auto vmxlaunch::launch() -> void auto vmxlaunch::launch() -> void
{ {
const auto vmlaunch_result = vmxlaunch_processor(); const auto vmlaunch_result = vmxlaunch_processor();
DBG_PRINT("vmxlaunch for processor: %d\n", KeGetCurrentProcessorNumber());
DBG_PRINT(" - vmxlaunch result: 0x%x\n", vmlaunch_result);
if (vmlaunch_result != VMX_LAUNCH_SUCCESS) if (vmlaunch_result != VMX_LAUNCH_SUCCESS)
{ {
u64 vmxerror; u64 vmxerror;

Loading…
Cancel
Save