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

Commit 989eea9

Browse files
committed
Optimization: Cached RSP/RFLAGS reads
Signed-off-by: Alexandro Sanchez Bach <asanchez@kryptoslogic.com>
1 parent 8e49240 commit 989eea9

6 files changed

Lines changed: 35 additions & 18 deletions

File tree

core/cpu.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,6 @@ int cpu_vmx_execute(struct vcpu_t *vcpu, struct hax_tunnel *htun)
382382
vmx(vcpu, interruptibility_state).raw = vmread(
383383
vcpu, GUEST_INTERRUPTIBILITY);
384384

385-
state->_rflags = vmread(vcpu, GUEST_RFLAGS);
386-
state->_rsp = vmread(vcpu, GUEST_RSP);
387385
vmread_cr(vcpu);
388386

389387
if (vcpu->nr_pending_intrs > 0 || hax_intr_is_blocked(vcpu))

core/include/vcpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ void hax_panic_vcpu(struct vcpu_t *v, char *fmt, ...);
256256

257257
// Extension-specific operations
258258

259+
mword vcpu_get_rflags(struct vcpu_t *vcpu);
260+
mword vcpu_get_rsp(struct vcpu_t *vcpu);
259261
mword vcpu_get_rip(struct vcpu_t *vcpu);
260262
uint16_t vcpu_get_seg_selector(struct vcpu_t *vcpu, int seg);
261263
mword vcpu_get_seg_base(struct vcpu_t *vcpu, int seg);

core/include/vmx.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,8 @@ typedef enum component_index_t component_index_t;
339339
COMP(0, 0, W_UL, HOST_SYSENTER_ESP) \
340340
COMP(0, 0, W_UL, HOST_SYSENTER_EIP) \
341341
COMP(1, 0, W_UL, GUEST_RIP) \
342-
COMP(0, 0, W_UL, GUEST_RFLAGS) \
343-
COMP(0, 0, W_UL, GUEST_RSP) \
342+
COMP(1, 0, W_UL, GUEST_RFLAGS) \
343+
COMP(1, 0, W_UL, GUEST_RSP) \
344344
COMP(0, 0, W_UL, GUEST_CR0) \
345345
COMP(0, 0, W_UL, GUEST_CR3) \
346346
COMP(0, 0, W_UL, GUEST_CR4) \

core/intr_exc.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,11 @@ static void hax_enable_intr_window(struct vcpu_t *vcpu)
119119
*/
120120
uint hax_intr_is_blocked(struct vcpu_t *vcpu)
121121
{
122-
struct vcpu_state_t *state = vcpu->state;
123122
uint32_t intr_status;
123+
uint64_t rflags;
124124

125-
if (!(state->_eflags & EFLAGS_IF))
125+
rflags = vcpu_get_rflags(vcpu);
126+
if (!(rflags & EFLAGS_IF))
126127
return 1;
127128

128129
intr_status = vmx(vcpu, interruptibility_state).raw;

core/vcpu.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,7 @@ static void load_dirty_vmcs_fields(struct vcpu_t *vcpu)
10621062
// rflags
10631063
if (vcpu->debug_control_dirty) {
10641064
// Single-stepping
1065+
state->_rflags = vcpu_get_rflags(vcpu);
10651066
if (vcpu->debug_control & HAX_DEBUG_STEP) {
10661067
state->_rflags |= EFLAGS_TF;
10671068
} else {
@@ -2173,12 +2174,20 @@ static int vcpu_emulate_insn(struct vcpu_t *vcpu)
21732174
static uint64_t vcpu_read_gpr(void *obj, uint32_t reg_index, uint32_t size)
21742175
{
21752176
struct vcpu_t *vcpu = obj;
2177+
uint64_t value;
2178+
21762179
if (reg_index >= 16) {
21772180
hax_panic_vcpu(vcpu, "vcpu_read_gpr: Invalid register index\n");
21782181
return 0;
21792182
}
2180-
uint64_t value = 0;
2181-
memcpy(&value, &vcpu->state->_regs[reg_index], size);
2183+
switch (reg_index) {
2184+
case REG_RSP:
2185+
value = vcpu_get_rsp(vcpu);
2186+
break;
2187+
default:
2188+
value = 0;
2189+
memcpy(&value, &vcpu->state->_regs[reg_index], size);
2190+
}
21822191
return value;
21832192
}
21842193

@@ -2196,7 +2205,7 @@ static void vcpu_write_gpr(void *obj, uint32_t reg_index, uint64_t value,
21962205
uint64_t vcpu_read_rflags(void *obj)
21972206
{
21982207
struct vcpu_t *vcpu = obj;
2199-
return vcpu->state->_rflags;
2208+
return vcpu_get_rflags(vcpu);
22002209
}
22012210

22022211
void vcpu_write_rflags(void *obj, uint64_t value)
@@ -3042,6 +3051,7 @@ static int handle_string_io(struct vcpu_t *vcpu, exit_qualification_t *qual,
30423051
{
30433052
struct vcpu_state_t *state = vcpu->state;
30443053
uint64_t count, total_size;
3054+
uint64_t rflags;
30453055
uint elem_size, n, copy_size;
30463056
hax_vaddr_t gla, start_gva;
30473057

@@ -3065,7 +3075,8 @@ static int handle_string_io(struct vcpu_t *vcpu, exit_qualification_t *qual,
30653075
// attribute of the instruction, or to check the presence of a segment
30663076
// override prefix that can make OUTS read from ES:ESI instead of DS:ESI).
30673077
gla = vmread(vcpu, VM_EXIT_INFO_GUEST_LINEAR_ADDRESS);
3068-
if (state->_rflags & EFLAGS_DF) {
3078+
rflags = vcpu_get_rflags(vcpu);
3079+
if (rflags & EFLAGS_DF) {
30693080
start_gva = gla - (n - 1) * elem_size;
30703081
htun->io._df = 1;
30713082
} else {
@@ -3091,7 +3102,7 @@ static int handle_string_io(struct vcpu_t *vcpu, exit_qualification_t *qual,
30913102
advance_rip(vcpu);
30923103
}
30933104

3094-
if (state->_rflags & EFLAGS_DF) {
3105+
if (rflags & EFLAGS_DF) {
30953106
if (qual->io.direction == HAX_IO_OUT) {
30963107
state->_rsi -= copy_size;
30973108
} else {
@@ -3843,13 +3854,8 @@ int vcpu_set_regs(struct vcpu_t *vcpu, struct vcpu_state_t *ustate)
38433854
int i;
38443855
int cr_dirty = 0, dr_dirty = 0;
38453856
preempt_flag flags;
3846-
int rsp_dirty = 0;
38473857
uint32_t vmcs_err = 0;
38483858

3849-
if (state->_rsp != ustate->_rsp) {
3850-
rsp_dirty = 1;
3851-
}
3852-
38533859
for (i = 0; i < 16; i++) {
38543860
state->_regs[i] = ustate->_regs[i];
38553861
}
@@ -3865,11 +3871,11 @@ int vcpu_set_regs(struct vcpu_t *vcpu, struct vcpu_state_t *ustate)
38653871
state->_rip = ustate->_rip;
38663872
vcpu->rip_dirty = 1;
38673873
}
3868-
if (state->_rflags != ustate->_rflags) {
3874+
if (vcpu_get_rflags(vcpu) != ustate->_rflags) {
38693875
state->_rflags = ustate->_rflags;
38703876
vcpu->rflags_dirty = 1;
38713877
}
3872-
if (rsp_dirty) {
3878+
if (vcpu_get_rsp(vcpu) != ustate->_rsp) {
38733879
state->_rsp = ustate->_rsp;
38743880
vmwrite(vcpu, GUEST_RSP, state->_rsp);
38753881
}

core/vmx.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,16 @@ void vcpu_vmcs_flush_cache_w(struct vcpu_t *vcpu)
327327
vcpu->vmx.vmcs_cache_w.dirty = 0;
328328
}
329329

330+
mword vcpu_get_rflags(struct vcpu_t *vcpu)
331+
{
332+
return vmcs_read(vcpu, GUEST_RFLAGS);
333+
}
334+
335+
mword vcpu_get_rsp(struct vcpu_t *vcpu)
336+
{
337+
return vmcs_read(vcpu, GUEST_RSP);
338+
}
339+
330340
mword vcpu_get_rip(struct vcpu_t *vcpu)
331341
{
332342
return vmcs_read(vcpu, GUEST_RIP);

0 commit comments

Comments
 (0)