Skip to content
This repository has been archived by the owner on Jan 28, 2023. It is now read-only.

Commit

Permalink
Optimize code by using new VMCS-cache macros
Browse files Browse the repository at this point in the history
- Replaced vmcs_pending* fields, with the new automatically-generated function that updates VMCS based on vmcs_cache_w flags. Only `vmcs_pending_guest_cr3` has been preserved since it requires extra logic.

- Removed unnecessary vmread's at the end of `cpu_vmx_execute` that are not always required. Corresponding members in `vcpu_vmx_data` have been removed and function depending on them now call `vmcs_read`.

Signed-off-by: Alexandro Sanchez Bach <asanchez@kryptoslogic.com>
  • Loading branch information
AlexAltea committed Nov 18, 2018
1 parent ee3b8df commit b938039
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 88 deletions.
40 changes: 0 additions & 40 deletions core/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,36 +312,6 @@ vmx_result_t cpu_vmx_run(struct vcpu_t *vcpu, struct hax_tunnel *htun)
return result;
}

void vcpu_handle_vmcs_pending(struct vcpu_t *vcpu)
{
if (!vcpu || !vcpu->vmcs_pending)
return;
if (vcpu->vmcs_pending_entry_error_code) {
vmwrite(vcpu, VMX_ENTRY_EXCEPTION_ERROR_CODE,
vmx(vcpu, entry_exception_error_code));
vcpu->vmcs_pending_entry_error_code = 0;
}

if (vcpu->vmcs_pending_entry_instr_length) {
vmwrite(vcpu, VMX_ENTRY_INSTRUCTION_LENGTH,
vmx(vcpu, entry_instr_length));
vcpu->vmcs_pending_entry_instr_length = 0;
}

if (vcpu->vmcs_pending_entry_intr_info) {
vmwrite(vcpu, VMX_ENTRY_INTERRUPT_INFO,
vmx(vcpu, entry_intr_info).raw);
vcpu->vmcs_pending_entry_intr_info = 0;
}

if (vcpu->vmcs_pending_guest_cr3) {
vmwrite(vcpu, GUEST_CR3, vtlb_get_cr3(vcpu));
vcpu->vmcs_pending_guest_cr3 = 0;
}
vcpu->vmcs_pending = 0;
return;
}

/* Return the value same as ioctl value */
int cpu_vmx_execute(struct vcpu_t *vcpu, struct hax_tunnel *htun)
{
Expand Down Expand Up @@ -416,16 +386,6 @@ int cpu_vmx_execute(struct vcpu_t *vcpu, struct hax_tunnel *htun)

vmx(vcpu, exit_qualification).raw = vmread(
vcpu, VM_EXIT_INFO_QUALIFICATION);
vmx(vcpu, exit_intr_info).raw = vmread(
vcpu, VM_EXIT_INFO_INTERRUPT_INFO);
vmx(vcpu, exit_exception_error_code) = vmread(
vcpu, VM_EXIT_INFO_EXCEPTION_ERROR_CODE);
vmx(vcpu, exit_idt_vectoring) = vmread(
vcpu, VM_EXIT_INFO_IDT_VECTORING);
vmx(vcpu, exit_instr_length) = vmread(
vcpu, VM_EXIT_INFO_INSTRUCTION_LENGTH);
vmx(vcpu, exit_gpa) = vmread(
vcpu, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS);
vmx(vcpu, interruptibility_state).raw = vmread(
vcpu, GUEST_INTERRUPTIBILITY);

Expand Down
4 changes: 0 additions & 4 deletions core/include/vcpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,6 @@ struct vcpu_t {
#define GS_STALE 0
#define GS_VALID 1
uint64_t cur_state : 1;
uint64_t vmcs_pending : 1;
uint64_t vmcs_pending_entry_error_code : 1;
uint64_t vmcs_pending_entry_instr_length : 1;
uint64_t vmcs_pending_entry_intr_info : 1;
uint64_t vmcs_pending_guest_cr3 : 1;
uint64_t debug_control_dirty : 1;
uint64_t dr_dirty : 1;
Expand Down
31 changes: 13 additions & 18 deletions core/include/vmx.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ typedef enum component_index_t component_index_t;
*/
#define VMCS_COMPS \
/* 64-bit components */ \
COMP(1, 1, W_64, VMX_IO_BITMAP_A) \
COMP(0, 0, W_64, VMX_IO_BITMAP_A) \
COMP(0, 0, W_64, VMX_IO_BITMAP_B) \
COMP(0, 0, W_64, VMX_MSR_BITMAP) \
COMP(0, 0, W_64, VMX_EXIT_MSR_STORE_ADDRESS) \
Expand All @@ -301,7 +301,7 @@ typedef enum component_index_t component_index_t;
COMP(0, 0, W_64, VMX_VAPIC_PAGE) \
COMP(0, 0, W_64, VMX_APIC_ACCESS_PAGE) \
COMP(0, 0, W_64, VMX_EPTP) \
COMP(0, 0, W_64, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS) \
COMP(1, 0, W_64, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS) \
COMP(0, 0, W_64, HOST_PAT) \
COMP(0, 0, W_64, HOST_EFER) \
COMP(0, 0, W_64, HOST_PERF_GLOBAL_CTRL) \
Expand Down Expand Up @@ -370,19 +370,19 @@ typedef enum component_index_t component_index_t;
COMP(0, 0, W_32, VMX_EXIT_MSR_LOAD_COUNT) \
COMP(0, 0, W_32, VMX_ENTRY_CONTROLS) \
COMP(0, 0, W_32, VMX_ENTRY_MSR_LOAD_COUNT) \
COMP(0, 0, W_32, VMX_ENTRY_INTERRUPT_INFO) \
COMP(0, 0, W_32, VMX_ENTRY_EXCEPTION_ERROR_CODE) \
COMP(0, 0, W_32, VMX_ENTRY_INSTRUCTION_LENGTH) \
COMP(0, 1, W_32, VMX_ENTRY_INTERRUPT_INFO) \
COMP(0, 1, W_32, VMX_ENTRY_EXCEPTION_ERROR_CODE) \
COMP(0, 1, W_32, VMX_ENTRY_INSTRUCTION_LENGTH) \
COMP(0, 0, W_32, VMX_TPR_THRESHOLD) \
COMP(0, 0, W_32, VMX_CR3_TARGET_COUNT) \
COMP(0, 0, W_32, VMX_PREEMPTION_TIMER) \
COMP(0, 0, W_32, VMX_INSTRUCTION_ERROR_CODE) \
COMP(0, 0, W_32, VM_EXIT_INFO_REASON) \
COMP(0, 0, W_32, VM_EXIT_INFO_INTERRUPT_INFO) \
COMP(0, 0, W_32, VM_EXIT_INFO_EXCEPTION_ERROR_CODE) \
COMP(0, 0, W_32, VM_EXIT_INFO_IDT_VECTORING) \
COMP(1, 0, W_32, VM_EXIT_INFO_INTERRUPT_INFO) \
COMP(1, 0, W_32, VM_EXIT_INFO_EXCEPTION_ERROR_CODE) \
COMP(1, 0, W_32, VM_EXIT_INFO_IDT_VECTORING) \
COMP(0, 0, W_32, VM_EXIT_INFO_IDT_VECTORING_ERROR_CODE) \
COMP(0, 0, W_32, VM_EXIT_INFO_INSTRUCTION_LENGTH) \
COMP(1, 0, W_32, VM_EXIT_INFO_INSTRUCTION_LENGTH) \
COMP(0, 0, W_32, VM_EXIT_INFO_INSTRUCTION_INFO) \
COMP(0, 0, W_32, HOST_SYSENTER_CS) \
COMP(0, 0, W_32, GUEST_ES_AR) \
Expand Down Expand Up @@ -880,18 +880,12 @@ struct vcpu_vmx_data {
uint32_t entry_exception_vector;
uint32_t entry_exception_error_code;

uint32_t exit_exception_error_code;
interruption_info_t exit_intr_info;
interruption_info_t entry_intr_info;
uint32_t exit_idt_vectoring;
uint32_t exit_instr_length;
uint32_t entry_instr_length;

exit_reason_t exit_reason;
exit_qualification_t exit_qualification;
interruptibility_state_t interruptibility_state;

uint64_t exit_gpa;
};

vmx_result_t ASMCALL asm_invept(uint type, struct invept_desc *desc);
Expand Down Expand Up @@ -946,11 +940,12 @@ void vmx_vmwrite(struct vcpu_t *vcpu, const char *name,
static inline void vmcs_write_##name(struct vcpu_vmx_data* vcpu_vmx, \
COMP_TYPE_##width value) { \
vcpu_vmx->vmcs.name##_value = value; \
vcpu_vmx->vmcs_cache_r.name##_cache = 1; \
/*vcpu_vmx->vmcs_cache_r.name##_cache = 1;*/ \
vcpu_vmx->vmcs_cache_w.name##_dirty = 1; \
vcpu_vmx->vmcs_cache_w.dirty = 1; \
}

// Declarations
// Declarations
#define COMP_R(cache_r, cache_w, width, name) \
COMP_R_##cache_r(width, name);
#define COMP_W(cache_r, cache_w, width, name) \
Expand All @@ -970,7 +965,7 @@ VMCS_COMPS
#define vmcs_write(vcpu, name, value) \
vmcs_write_##name(&vcpu->vmx, value)

void vmcs_write_pending(struct vcpu_t *vcpu);
void vcpu_handle_vmcs_pending(struct vcpu_t *vcpu);

#define VMREAD_SEG(vcpu, seg, val) \
((val).selector = vmread(vcpu, GUEST_##seg##_SELECTOR), \
Expand Down
18 changes: 7 additions & 11 deletions core/intr_exc.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ uint hax_intr_is_blocked(struct vcpu_t *vcpu)
void hax_handle_idt_vectoring(struct vcpu_t *vcpu)
{
uint8_t vector;
uint32_t idt_vec = vmread(vcpu, VM_EXIT_INFO_IDT_VECTORING);
uint32_t idt_vec = vmcs_read(vcpu, VM_EXIT_INFO_IDT_VECTORING);

if (idt_vec & 0x80000000) {
if (!(idt_vec & 0x700)) {
Expand All @@ -149,7 +149,7 @@ void hax_handle_idt_vectoring(struct vcpu_t *vcpu)
hax_debug("VM Exit @ IDT vectoring, type:%d, vector:%d,"
" error code:%llx\n",
(idt_vec & 0x700) >> 8, idt_vec & 0xff,
vmread(vcpu, VM_EXIT_INFO_IDT_VECTORING_ERROR_CODE));
vmcs_read(vcpu, VM_EXIT_INFO_IDT_VECTORING_ERROR_CODE));
}
}
}
Expand Down Expand Up @@ -198,8 +198,8 @@ void hax_inject_exception(struct vcpu_t *vcpu, uint8_t vector, uint32_t error_co
{
uint32_t intr_info = 0;
uint8_t first_vec;
uint32_t vect_info = vmx(vcpu, exit_idt_vectoring);
uint32_t exit_instr_length = vmx(vcpu, exit_instr_length);
uint32_t vect_info = vmcs_read(vcpu, VM_EXIT_INFO_IDT_VECTORING);
uint32_t exit_instr_length = vmcs_read(vcpu, VM_EXIT_INFO_INSTRUCTION_LENGTH);

if (vcpu->event_injected == 1)
hax_debug("Event is injected already!!:\n");
Expand All @@ -218,20 +218,16 @@ void hax_inject_exception(struct vcpu_t *vcpu, uint8_t vector, uint32_t error_co
if (error_code != NO_ERROR_CODE) {
intr_info |= 1 << 11;
if (vector == VECTOR_PF) {
vcpu->vmcs_pending_entry_error_code = 1;
vmx(vcpu, entry_exception_error_code) = error_code;
vmcs_write(vcpu, VMX_ENTRY_EXCEPTION_ERROR_CODE, error_code);
} else {
vmwrite(vcpu, VMX_ENTRY_EXCEPTION_ERROR_CODE, error_code);
}
}
}

if (vector == VECTOR_PF) {
vcpu->vmcs_pending_entry_instr_length = 1;
vmx(vcpu, entry_instr_length) = exit_instr_length;
vcpu->vmcs_pending_entry_intr_info = 1;
vmx(vcpu, entry_intr_info).raw = intr_info;
vcpu->vmcs_pending = 1;
vmcs_write(vcpu, VMX_ENTRY_INSTRUCTION_LENGTH, exit_instr_length);
vmcs_write(vcpu, VMX_ENTRY_INTERRUPT_INFO, intr_info);
} else {
vmwrite(vcpu, VMX_ENTRY_INSTRUCTION_LENGTH, exit_instr_length);
vmwrite(vcpu, VMX_ENTRY_INTERRUPT_INFO, intr_info);
Expand Down
28 changes: 15 additions & 13 deletions core/vcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1748,7 +1748,7 @@ static void advance_rip(struct vcpu_t *vcpu)
vcpu->interruptibility_dirty = 1;
}

state->_rip += vmx(vcpu, exit_instr_length);
state->_rip += vmcs_read(vcpu, VM_EXIT_INFO_INSTRUCTION_LENGTH);
vcpu->rip_dirty = 1;
}

Expand Down Expand Up @@ -2092,6 +2092,7 @@ static int vcpu_emulate_insn(struct vcpu_t *vcpu)
em_mode_t mode;
em_context_t *em_ctxt = &vcpu->emulate_ctxt;
uint8_t instr[INSTR_MAX_LEN] = {0};
uint32_t exit_instr_length = vmcs_read(vcpu, VM_EXIT_INFO_INSTRUCTION_LENGTH);
uint64_t cs_base = vcpu->state->_cs.base;
uint64_t rip = vcpu->state->_rip;
uint64_t va;
Expand Down Expand Up @@ -2138,25 +2139,25 @@ static int vcpu_emulate_insn(struct vcpu_t *vcpu)
hax_panic_vcpu(vcpu, "em_decode_insn() failed: vcpu_id=%u,"
" len=%u, CS:IP=0x%llx:0x%llx, instr[0..5]="
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", vcpu->vcpu_id,
vcpu->vmx.exit_instr_length, cs_base, rip, instr[0],
instr[1], instr[2], instr[3], instr[4], instr[5]);
exit_instr_length, cs_base, rip, instr[0], instr[1],
instr[2], instr[3], instr[4], instr[5]);
dump_vmcs(vcpu);
return HAX_RESUME;
}
if (em_ctxt->len != vcpu->vmx.exit_instr_length) {
if (em_ctxt->len != exit_instr_length) {
hax_debug("Inferred instruction length %u does not match VM-exit"
" instruction length %u (CS:IP=0x%llx:0x%llx, instr[0..5]="
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x)\n", em_ctxt->len,
vcpu->vmx.exit_instr_length, cs_base, rip, instr[0], instr[1],
exit_instr_length, cs_base, rip, instr[0], instr[1],
instr[2], instr[3], instr[4], instr[5]);
}
rc = em_emulate_insn(em_ctxt);
if (rc < 0) {
hax_panic_vcpu(vcpu, "em_emulate_insn() failed: vcpu_id=%u,"
" len=%u, CS:IP=0x%llx:0x%llx, instr[0..5]="
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", vcpu->vcpu_id,
vcpu->vmx.exit_instr_length, cs_base, rip, instr[0],
instr[1], instr[2], instr[3], instr[4], instr[5]);
exit_instr_length, cs_base, rip, instr[0], instr[1],
instr[2], instr[3], instr[4], instr[5]);
dump_vmcs(vcpu);
return HAX_RESUME;
}
Expand Down Expand Up @@ -2233,7 +2234,7 @@ static em_status_t vcpu_read_memory(void *obj, uint64_t ea, uint64_t *value,
uint64_t pa;

if (flags & EM_OPS_NO_TRANSLATION) {
pa = vmx(vcpu, exit_gpa);
pa = vmcs_read(vcpu, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS);
} else {
vcpu_translate(vcpu, ea, 0, &pa, NULL, false);
}
Expand Down Expand Up @@ -2271,7 +2272,7 @@ static em_status_t vcpu_write_memory(void *obj, uint64_t ea, uint64_t *value,
uint64_t pa;

if (flags & EM_OPS_NO_TRANSLATION) {
pa = vmx(vcpu, exit_gpa);
pa = vmcs_read(vcpu, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS);
} else {
vcpu_translate(vcpu, ea, 0, &pa, NULL, false);
}
Expand Down Expand Up @@ -2321,7 +2322,7 @@ static int exit_exc_nmi(struct vcpu_t *vcpu, struct hax_tunnel *htun)
struct vcpu_state_t *state = vcpu->state;
interruption_info_t exit_intr_info;

exit_intr_info.raw = vmx(vcpu, exit_intr_info).raw;
exit_intr_info.raw = vmcs_read(vcpu, VM_EXIT_INFO_INTERRUPT_INFO);
htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason;
hax_debug("exception vmexit vector:%x\n", exit_intr_info.vector);

Expand Down Expand Up @@ -3680,7 +3681,7 @@ static int exit_ept_misconfiguration(struct vcpu_t *vcpu,

htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason;
#ifdef CONFIG_HAX_EPT2
gpa = vmx(vcpu, exit_gpa);
gpa = vmcs_read(vcpu, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS);
ret = ept_handle_misconfiguration(&vcpu->vm->gpa_space, &vcpu->vm->ept_tree,
gpa);
if (ret > 0) {
Expand Down Expand Up @@ -3712,7 +3713,7 @@ static int exit_ept_violation(struct vcpu_t *vcpu, struct hax_tunnel *htun)
return HAX_RESUME;
}

gpa = vmx(vcpu, exit_gpa);
gpa = vmcs_read(vcpu, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS);

#ifdef CONFIG_HAX_EPT2
ret = ept_handle_access_violation(&vcpu->vm->gpa_space, &vcpu->vm->ept_tree,
Expand All @@ -3736,7 +3737,8 @@ static int exit_ept_violation(struct vcpu_t *vcpu, struct hax_tunnel *htun)
* TODO: Handle this case properly.
*/
hax_warning("%s: Unexpected EPT violation cause. Skipping instruction"
" (len=%u)\n", __func__, vcpu->vmx.exit_instr_length);
" (len=%u)\n", __func__,
vmcs_read(vcpu, VM_EXIT_INFO_INSTRUCTION_LENGTH));
advance_rip(vcpu);
return HAX_EXIT;
}
Expand Down
8 changes: 7 additions & 1 deletion core/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "include/hax_core_interface.h"
#include "include/ia32.h"
#include "include/ia32_defs.h"
#include "include/vtlb.h"

static void _vmx_vmwrite(struct vcpu_t *vcpu, const char *name,
component_index_t component,
Expand Down Expand Up @@ -304,12 +305,17 @@ void get_interruption_info_t(interruption_info_t *info, uint8_t v, uint8_t t)
#define COMP_PENDING(cache_r, cache_w, width, name) \
COMP_PENDING_##cache_w(name)

void vmcs_write_pending(struct vcpu_t* vcpu)
void vcpu_handle_vmcs_pending(struct vcpu_t* vcpu)
{
if (!vcpu || !vcpu->vmx.vmcs_cache_w.dirty)
return;

#define COMP COMP_PENDING
VMCS_COMPS
#undef COMP
if (vcpu->vmcs_pending_guest_cr3) {
vmwrite(vcpu, GUEST_CR3, vtlb_get_cr3(vcpu));
vcpu->vmcs_pending_guest_cr3 = 0;
}
vcpu->vmx.vmcs_cache_w.dirty = 0;
}
2 changes: 1 addition & 1 deletion core/vtlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ static uint32_t vcpu_mmu_walk(struct vcpu_t *vcpu, vaddr_t va, uint32_t access,

bool handle_vtlb(struct vcpu_t *vcpu)
{
uint32_t access = vmx(vcpu, exit_exception_error_code);
uint32_t access = vmcs_read(vcpu, VM_EXIT_INFO_EXCEPTION_ERROR_CODE);
pagemode_t mode = vcpu_get_pagemode(vcpu);
paddr_t pdir = vcpu->state->_cr3 & (mode == PM_PAE ? ~0x1fULL : ~0xfffULL);
vaddr_t cr2 = vmx(vcpu, exit_qualification).address;
Expand Down

0 comments on commit b938039

Please sign in to comment.