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

Commit b938039

Browse files
committed
Optimize code by using new VMCS-cache macros
- 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 <[email protected]>
1 parent ee3b8df commit b938039

File tree

7 files changed

+43
-88
lines changed

7 files changed

+43
-88
lines changed

core/cpu.c

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -312,36 +312,6 @@ vmx_result_t cpu_vmx_run(struct vcpu_t *vcpu, struct hax_tunnel *htun)
312312
return result;
313313
}
314314

315-
void vcpu_handle_vmcs_pending(struct vcpu_t *vcpu)
316-
{
317-
if (!vcpu || !vcpu->vmcs_pending)
318-
return;
319-
if (vcpu->vmcs_pending_entry_error_code) {
320-
vmwrite(vcpu, VMX_ENTRY_EXCEPTION_ERROR_CODE,
321-
vmx(vcpu, entry_exception_error_code));
322-
vcpu->vmcs_pending_entry_error_code = 0;
323-
}
324-
325-
if (vcpu->vmcs_pending_entry_instr_length) {
326-
vmwrite(vcpu, VMX_ENTRY_INSTRUCTION_LENGTH,
327-
vmx(vcpu, entry_instr_length));
328-
vcpu->vmcs_pending_entry_instr_length = 0;
329-
}
330-
331-
if (vcpu->vmcs_pending_entry_intr_info) {
332-
vmwrite(vcpu, VMX_ENTRY_INTERRUPT_INFO,
333-
vmx(vcpu, entry_intr_info).raw);
334-
vcpu->vmcs_pending_entry_intr_info = 0;
335-
}
336-
337-
if (vcpu->vmcs_pending_guest_cr3) {
338-
vmwrite(vcpu, GUEST_CR3, vtlb_get_cr3(vcpu));
339-
vcpu->vmcs_pending_guest_cr3 = 0;
340-
}
341-
vcpu->vmcs_pending = 0;
342-
return;
343-
}
344-
345315
/* Return the value same as ioctl value */
346316
int cpu_vmx_execute(struct vcpu_t *vcpu, struct hax_tunnel *htun)
347317
{
@@ -416,16 +386,6 @@ int cpu_vmx_execute(struct vcpu_t *vcpu, struct hax_tunnel *htun)
416386

417387
vmx(vcpu, exit_qualification).raw = vmread(
418388
vcpu, VM_EXIT_INFO_QUALIFICATION);
419-
vmx(vcpu, exit_intr_info).raw = vmread(
420-
vcpu, VM_EXIT_INFO_INTERRUPT_INFO);
421-
vmx(vcpu, exit_exception_error_code) = vmread(
422-
vcpu, VM_EXIT_INFO_EXCEPTION_ERROR_CODE);
423-
vmx(vcpu, exit_idt_vectoring) = vmread(
424-
vcpu, VM_EXIT_INFO_IDT_VECTORING);
425-
vmx(vcpu, exit_instr_length) = vmread(
426-
vcpu, VM_EXIT_INFO_INSTRUCTION_LENGTH);
427-
vmx(vcpu, exit_gpa) = vmread(
428-
vcpu, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS);
429389
vmx(vcpu, interruptibility_state).raw = vmread(
430390
vcpu, GUEST_INTERRUPTIBILITY);
431391

core/include/vcpu.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,6 @@ struct vcpu_t {
154154
#define GS_STALE 0
155155
#define GS_VALID 1
156156
uint64_t cur_state : 1;
157-
uint64_t vmcs_pending : 1;
158-
uint64_t vmcs_pending_entry_error_code : 1;
159-
uint64_t vmcs_pending_entry_instr_length : 1;
160-
uint64_t vmcs_pending_entry_intr_info : 1;
161157
uint64_t vmcs_pending_guest_cr3 : 1;
162158
uint64_t debug_control_dirty : 1;
163159
uint64_t dr_dirty : 1;

core/include/vmx.h

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ typedef enum component_index_t component_index_t;
291291
*/
292292
#define VMCS_COMPS \
293293
/* 64-bit components */ \
294-
COMP(1, 1, W_64, VMX_IO_BITMAP_A) \
294+
COMP(0, 0, W_64, VMX_IO_BITMAP_A) \
295295
COMP(0, 0, W_64, VMX_IO_BITMAP_B) \
296296
COMP(0, 0, W_64, VMX_MSR_BITMAP) \
297297
COMP(0, 0, W_64, VMX_EXIT_MSR_STORE_ADDRESS) \
@@ -301,7 +301,7 @@ typedef enum component_index_t component_index_t;
301301
COMP(0, 0, W_64, VMX_VAPIC_PAGE) \
302302
COMP(0, 0, W_64, VMX_APIC_ACCESS_PAGE) \
303303
COMP(0, 0, W_64, VMX_EPTP) \
304-
COMP(0, 0, W_64, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS) \
304+
COMP(1, 0, W_64, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS) \
305305
COMP(0, 0, W_64, HOST_PAT) \
306306
COMP(0, 0, W_64, HOST_EFER) \
307307
COMP(0, 0, W_64, HOST_PERF_GLOBAL_CTRL) \
@@ -370,19 +370,19 @@ typedef enum component_index_t component_index_t;
370370
COMP(0, 0, W_32, VMX_EXIT_MSR_LOAD_COUNT) \
371371
COMP(0, 0, W_32, VMX_ENTRY_CONTROLS) \
372372
COMP(0, 0, W_32, VMX_ENTRY_MSR_LOAD_COUNT) \
373-
COMP(0, 0, W_32, VMX_ENTRY_INTERRUPT_INFO) \
374-
COMP(0, 0, W_32, VMX_ENTRY_EXCEPTION_ERROR_CODE) \
375-
COMP(0, 0, W_32, VMX_ENTRY_INSTRUCTION_LENGTH) \
373+
COMP(0, 1, W_32, VMX_ENTRY_INTERRUPT_INFO) \
374+
COMP(0, 1, W_32, VMX_ENTRY_EXCEPTION_ERROR_CODE) \
375+
COMP(0, 1, W_32, VMX_ENTRY_INSTRUCTION_LENGTH) \
376376
COMP(0, 0, W_32, VMX_TPR_THRESHOLD) \
377377
COMP(0, 0, W_32, VMX_CR3_TARGET_COUNT) \
378378
COMP(0, 0, W_32, VMX_PREEMPTION_TIMER) \
379379
COMP(0, 0, W_32, VMX_INSTRUCTION_ERROR_CODE) \
380380
COMP(0, 0, W_32, VM_EXIT_INFO_REASON) \
381-
COMP(0, 0, W_32, VM_EXIT_INFO_INTERRUPT_INFO) \
382-
COMP(0, 0, W_32, VM_EXIT_INFO_EXCEPTION_ERROR_CODE) \
383-
COMP(0, 0, W_32, VM_EXIT_INFO_IDT_VECTORING) \
381+
COMP(1, 0, W_32, VM_EXIT_INFO_INTERRUPT_INFO) \
382+
COMP(1, 0, W_32, VM_EXIT_INFO_EXCEPTION_ERROR_CODE) \
383+
COMP(1, 0, W_32, VM_EXIT_INFO_IDT_VECTORING) \
384384
COMP(0, 0, W_32, VM_EXIT_INFO_IDT_VECTORING_ERROR_CODE) \
385-
COMP(0, 0, W_32, VM_EXIT_INFO_INSTRUCTION_LENGTH) \
385+
COMP(1, 0, W_32, VM_EXIT_INFO_INSTRUCTION_LENGTH) \
386386
COMP(0, 0, W_32, VM_EXIT_INFO_INSTRUCTION_INFO) \
387387
COMP(0, 0, W_32, HOST_SYSENTER_CS) \
388388
COMP(0, 0, W_32, GUEST_ES_AR) \
@@ -880,18 +880,12 @@ struct vcpu_vmx_data {
880880
uint32_t entry_exception_vector;
881881
uint32_t entry_exception_error_code;
882882

883-
uint32_t exit_exception_error_code;
884-
interruption_info_t exit_intr_info;
885883
interruption_info_t entry_intr_info;
886-
uint32_t exit_idt_vectoring;
887-
uint32_t exit_instr_length;
888884
uint32_t entry_instr_length;
889885

890886
exit_reason_t exit_reason;
891887
exit_qualification_t exit_qualification;
892888
interruptibility_state_t interruptibility_state;
893-
894-
uint64_t exit_gpa;
895889
};
896890

897891
vmx_result_t ASMCALL asm_invept(uint type, struct invept_desc *desc);
@@ -946,11 +940,12 @@ void vmx_vmwrite(struct vcpu_t *vcpu, const char *name,
946940
static inline void vmcs_write_##name(struct vcpu_vmx_data* vcpu_vmx, \
947941
COMP_TYPE_##width value) { \
948942
vcpu_vmx->vmcs.name##_value = value; \
949-
vcpu_vmx->vmcs_cache_r.name##_cache = 1; \
943+
/*vcpu_vmx->vmcs_cache_r.name##_cache = 1;*/ \
950944
vcpu_vmx->vmcs_cache_w.name##_dirty = 1; \
945+
vcpu_vmx->vmcs_cache_w.dirty = 1; \
951946
}
952947

953-
// Declarations
948+
// Declarations
954949
#define COMP_R(cache_r, cache_w, width, name) \
955950
COMP_R_##cache_r(width, name);
956951
#define COMP_W(cache_r, cache_w, width, name) \
@@ -970,7 +965,7 @@ VMCS_COMPS
970965
#define vmcs_write(vcpu, name, value) \
971966
vmcs_write_##name(&vcpu->vmx, value)
972967

973-
void vmcs_write_pending(struct vcpu_t *vcpu);
968+
void vcpu_handle_vmcs_pending(struct vcpu_t *vcpu);
974969

975970
#define VMREAD_SEG(vcpu, seg, val) \
976971
((val).selector = vmread(vcpu, GUEST_##seg##_SELECTOR), \

core/intr_exc.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ uint hax_intr_is_blocked(struct vcpu_t *vcpu)
137137
void hax_handle_idt_vectoring(struct vcpu_t *vcpu)
138138
{
139139
uint8_t vector;
140-
uint32_t idt_vec = vmread(vcpu, VM_EXIT_INFO_IDT_VECTORING);
140+
uint32_t idt_vec = vmcs_read(vcpu, VM_EXIT_INFO_IDT_VECTORING);
141141

142142
if (idt_vec & 0x80000000) {
143143
if (!(idt_vec & 0x700)) {
@@ -149,7 +149,7 @@ void hax_handle_idt_vectoring(struct vcpu_t *vcpu)
149149
hax_debug("VM Exit @ IDT vectoring, type:%d, vector:%d,"
150150
" error code:%llx\n",
151151
(idt_vec & 0x700) >> 8, idt_vec & 0xff,
152-
vmread(vcpu, VM_EXIT_INFO_IDT_VECTORING_ERROR_CODE));
152+
vmcs_read(vcpu, VM_EXIT_INFO_IDT_VECTORING_ERROR_CODE));
153153
}
154154
}
155155
}
@@ -198,8 +198,8 @@ void hax_inject_exception(struct vcpu_t *vcpu, uint8_t vector, uint32_t error_co
198198
{
199199
uint32_t intr_info = 0;
200200
uint8_t first_vec;
201-
uint32_t vect_info = vmx(vcpu, exit_idt_vectoring);
202-
uint32_t exit_instr_length = vmx(vcpu, exit_instr_length);
201+
uint32_t vect_info = vmcs_read(vcpu, VM_EXIT_INFO_IDT_VECTORING);
202+
uint32_t exit_instr_length = vmcs_read(vcpu, VM_EXIT_INFO_INSTRUCTION_LENGTH);
203203

204204
if (vcpu->event_injected == 1)
205205
hax_debug("Event is injected already!!:\n");
@@ -218,20 +218,16 @@ void hax_inject_exception(struct vcpu_t *vcpu, uint8_t vector, uint32_t error_co
218218
if (error_code != NO_ERROR_CODE) {
219219
intr_info |= 1 << 11;
220220
if (vector == VECTOR_PF) {
221-
vcpu->vmcs_pending_entry_error_code = 1;
222-
vmx(vcpu, entry_exception_error_code) = error_code;
221+
vmcs_write(vcpu, VMX_ENTRY_EXCEPTION_ERROR_CODE, error_code);
223222
} else {
224223
vmwrite(vcpu, VMX_ENTRY_EXCEPTION_ERROR_CODE, error_code);
225224
}
226225
}
227226
}
228227

229228
if (vector == VECTOR_PF) {
230-
vcpu->vmcs_pending_entry_instr_length = 1;
231-
vmx(vcpu, entry_instr_length) = exit_instr_length;
232-
vcpu->vmcs_pending_entry_intr_info = 1;
233-
vmx(vcpu, entry_intr_info).raw = intr_info;
234-
vcpu->vmcs_pending = 1;
229+
vmcs_write(vcpu, VMX_ENTRY_INSTRUCTION_LENGTH, exit_instr_length);
230+
vmcs_write(vcpu, VMX_ENTRY_INTERRUPT_INFO, intr_info);
235231
} else {
236232
vmwrite(vcpu, VMX_ENTRY_INSTRUCTION_LENGTH, exit_instr_length);
237233
vmwrite(vcpu, VMX_ENTRY_INTERRUPT_INFO, intr_info);

core/vcpu.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,7 +1748,7 @@ static void advance_rip(struct vcpu_t *vcpu)
17481748
vcpu->interruptibility_dirty = 1;
17491749
}
17501750

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

@@ -2092,6 +2092,7 @@ static int vcpu_emulate_insn(struct vcpu_t *vcpu)
20922092
em_mode_t mode;
20932093
em_context_t *em_ctxt = &vcpu->emulate_ctxt;
20942094
uint8_t instr[INSTR_MAX_LEN] = {0};
2095+
uint32_t exit_instr_length = vmcs_read(vcpu, VM_EXIT_INFO_INSTRUCTION_LENGTH);
20952096
uint64_t cs_base = vcpu->state->_cs.base;
20962097
uint64_t rip = vcpu->state->_rip;
20972098
uint64_t va;
@@ -2138,25 +2139,25 @@ static int vcpu_emulate_insn(struct vcpu_t *vcpu)
21382139
hax_panic_vcpu(vcpu, "em_decode_insn() failed: vcpu_id=%u,"
21392140
" len=%u, CS:IP=0x%llx:0x%llx, instr[0..5]="
21402141
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", vcpu->vcpu_id,
2141-
vcpu->vmx.exit_instr_length, cs_base, rip, instr[0],
2142-
instr[1], instr[2], instr[3], instr[4], instr[5]);
2142+
exit_instr_length, cs_base, rip, instr[0], instr[1],
2143+
instr[2], instr[3], instr[4], instr[5]);
21432144
dump_vmcs(vcpu);
21442145
return HAX_RESUME;
21452146
}
2146-
if (em_ctxt->len != vcpu->vmx.exit_instr_length) {
2147+
if (em_ctxt->len != exit_instr_length) {
21472148
hax_debug("Inferred instruction length %u does not match VM-exit"
21482149
" instruction length %u (CS:IP=0x%llx:0x%llx, instr[0..5]="
21492150
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x)\n", em_ctxt->len,
2150-
vcpu->vmx.exit_instr_length, cs_base, rip, instr[0], instr[1],
2151+
exit_instr_length, cs_base, rip, instr[0], instr[1],
21512152
instr[2], instr[3], instr[4], instr[5]);
21522153
}
21532154
rc = em_emulate_insn(em_ctxt);
21542155
if (rc < 0) {
21552156
hax_panic_vcpu(vcpu, "em_emulate_insn() failed: vcpu_id=%u,"
21562157
" len=%u, CS:IP=0x%llx:0x%llx, instr[0..5]="
21572158
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", vcpu->vcpu_id,
2158-
vcpu->vmx.exit_instr_length, cs_base, rip, instr[0],
2159-
instr[1], instr[2], instr[3], instr[4], instr[5]);
2159+
exit_instr_length, cs_base, rip, instr[0], instr[1],
2160+
instr[2], instr[3], instr[4], instr[5]);
21602161
dump_vmcs(vcpu);
21612162
return HAX_RESUME;
21622163
}
@@ -2233,7 +2234,7 @@ static em_status_t vcpu_read_memory(void *obj, uint64_t ea, uint64_t *value,
22332234
uint64_t pa;
22342235

22352236
if (flags & EM_OPS_NO_TRANSLATION) {
2236-
pa = vmx(vcpu, exit_gpa);
2237+
pa = vmcs_read(vcpu, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS);
22372238
} else {
22382239
vcpu_translate(vcpu, ea, 0, &pa, NULL, false);
22392240
}
@@ -2271,7 +2272,7 @@ static em_status_t vcpu_write_memory(void *obj, uint64_t ea, uint64_t *value,
22712272
uint64_t pa;
22722273

22732274
if (flags & EM_OPS_NO_TRANSLATION) {
2274-
pa = vmx(vcpu, exit_gpa);
2275+
pa = vmcs_read(vcpu, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS);
22752276
} else {
22762277
vcpu_translate(vcpu, ea, 0, &pa, NULL, false);
22772278
}
@@ -2321,7 +2322,7 @@ static int exit_exc_nmi(struct vcpu_t *vcpu, struct hax_tunnel *htun)
23212322
struct vcpu_state_t *state = vcpu->state;
23222323
interruption_info_t exit_intr_info;
23232324

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

@@ -3680,7 +3681,7 @@ static int exit_ept_misconfiguration(struct vcpu_t *vcpu,
36803681

36813682
htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason;
36823683
#ifdef CONFIG_HAX_EPT2
3683-
gpa = vmx(vcpu, exit_gpa);
3684+
gpa = vmcs_read(vcpu, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS);
36843685
ret = ept_handle_misconfiguration(&vcpu->vm->gpa_space, &vcpu->vm->ept_tree,
36853686
gpa);
36863687
if (ret > 0) {
@@ -3712,7 +3713,7 @@ static int exit_ept_violation(struct vcpu_t *vcpu, struct hax_tunnel *htun)
37123713
return HAX_RESUME;
37133714
}
37143715

3715-
gpa = vmx(vcpu, exit_gpa);
3716+
gpa = vmcs_read(vcpu, VM_EXIT_INFO_GUEST_PHYSICAL_ADDRESS);
37163717

37173718
#ifdef CONFIG_HAX_EPT2
37183719
ret = ept_handle_access_violation(&vcpu->vm->gpa_space, &vcpu->vm->ept_tree,
@@ -3736,7 +3737,8 @@ static int exit_ept_violation(struct vcpu_t *vcpu, struct hax_tunnel *htun)
37363737
* TODO: Handle this case properly.
37373738
*/
37383739
hax_warning("%s: Unexpected EPT violation cause. Skipping instruction"
3739-
" (len=%u)\n", __func__, vcpu->vmx.exit_instr_length);
3740+
" (len=%u)\n", __func__,
3741+
vmcs_read(vcpu, VM_EXIT_INFO_INSTRUCTION_LENGTH));
37403742
advance_rip(vcpu);
37413743
return HAX_EXIT;
37423744
}

core/vmx.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "include/hax_core_interface.h"
3636
#include "include/ia32.h"
3737
#include "include/ia32_defs.h"
38+
#include "include/vtlb.h"
3839

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

307-
void vmcs_write_pending(struct vcpu_t* vcpu)
308+
void vcpu_handle_vmcs_pending(struct vcpu_t* vcpu)
308309
{
309310
if (!vcpu || !vcpu->vmx.vmcs_cache_w.dirty)
310311
return;
311312

312313
#define COMP COMP_PENDING
313314
VMCS_COMPS
314315
#undef COMP
316+
if (vcpu->vmcs_pending_guest_cr3) {
317+
vmwrite(vcpu, GUEST_CR3, vtlb_get_cr3(vcpu));
318+
vcpu->vmcs_pending_guest_cr3 = 0;
319+
}
320+
vcpu->vmx.vmcs_cache_w.dirty = 0;
315321
}

core/vtlb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ static uint32_t vcpu_mmu_walk(struct vcpu_t *vcpu, vaddr_t va, uint32_t access,
781781

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

0 commit comments

Comments
 (0)