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

Commit

Permalink
Browse files Browse the repository at this point in the history
core: save/restore FPU registers in VM entry/exit
Guest OS kernel/app might use SSE instruction and registers.
When Guest OS VM exits, these registers should be saved, or else
it might be corrupted by host OS/app. In next time VM entry,
guest's SSE registers context might be corrupted.

Guest app segfault and kernel panic were reported which should
be related with this issue.

This change is to remove is_fpu_used flag so guest FPU registers
could be saved in VM exit and restored in VM entry unconditionally.

Fixes #39, fixes #74.
  • Loading branch information
junxiaoc committed Aug 1, 2018
1 parent af8f9f5 commit 6c2cd4d
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 28 deletions.
3 changes: 1 addition & 2 deletions core/include/vcpu.h
Expand Up @@ -178,7 +178,6 @@ struct vcpu_t {
uint64 paused : 1;
uint64 panicked : 1;
uint64 is_running : 1;
uint64 is_fpu_used : 1;
uint64 is_vmcs_loaded : 1;
uint64 event_injected : 1;
/* vcpu->state is valid or not */
Expand All @@ -190,7 +189,7 @@ struct vcpu_t {
uint64 vmcs_pending_entry_instr_length : 1;
uint64 vmcs_pending_entry_intr_info : 1;
uint64 vmcs_pending_guest_cr3 : 1;
uint64 padding : 52;
uint64 padding : 53;
};

/* For TSC offseting feature*/
Expand Down
31 changes: 5 additions & 26 deletions core/vcpu.c
Expand Up @@ -1198,7 +1198,7 @@ static void fill_common_vmcs(struct vcpu_t *vcpu)
}
}

exc_bitmap = (1u << VECTOR_MC) | (1u << VECTOR_NM);
exc_bitmap = 1u << VECTOR_MC;

#ifdef __x86_64__
exit_ctls = EXIT_CONTROL_HOST_ADDR_SPACE_SIZE | EXIT_CONTROL_LOAD_EFER |
Expand Down Expand Up @@ -1895,10 +1895,8 @@ static void vcpu_enter_fpu_state(struct vcpu_t *vcpu)
struct fx_layout *hfx = (struct fx_layout *)hax_page_va(hstate->hfxpage);
struct fx_layout *gfx = (struct fx_layout *)hax_page_va(gstate->gfxpage);

if (vcpu->is_fpu_used) {
fxsave((mword *)hfx);
fxrstor((mword *)gfx);
}
fxsave((mword *)hfx);
fxrstor((mword *)gfx);
}

static void vcpu_exit_fpu_state(struct vcpu_t *vcpu)
Expand All @@ -1908,10 +1906,8 @@ static void vcpu_exit_fpu_state(struct vcpu_t *vcpu)
struct fx_layout *hfx = (struct fx_layout *)hax_page_va(hstate->hfxpage);
struct fx_layout *gfx = (struct fx_layout *)hax_page_va(gstate->gfxpage);

if (vcpu->is_fpu_used) {
fxsave((mword *)gfx);
fxrstor((mword *)hfx);
}
fxsave((mword *)gfx);
fxrstor((mword *)hfx);
}

// Instructions are never longer than 15 bytes:
Expand Down Expand Up @@ -2169,7 +2165,6 @@ 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;
uint64 cr0;

exit_intr_info.raw = vmx(vcpu, exit_intr_info).raw;
htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason;
Expand All @@ -2193,19 +2188,6 @@ static int exit_exc_nmi(struct vcpu_t *vcpu, struct hax_tunnel *htun)
}
break;
}
case VECTOR_NM: {
cr0 = vcpu_read_cr(state, 0);
if (cr0 & CR0_TS) {
uint32 exc_bitmap = vmx(vcpu, exc_bitmap);
if (!vcpu->is_fpu_used) {
vcpu->is_fpu_used = 1;
}
exc_bitmap &= ~(1u << VECTOR_NM);
vmwrite(vcpu, VMX_EXCEPTION_BITMAP,
vmx(vcpu, exc_bitmap) = exc_bitmap);
}
return HAX_RESUME;
}
case VECTOR_MC: {
hax_panic_vcpu(vcpu, "Machine check happens!\n");
dump_vmcs(vcpu);
Expand Down Expand Up @@ -2757,9 +2739,6 @@ static int exit_cr_access(struct vcpu_t *vcpu, struct hax_tunnel *htun)
case 2: { // CLTS
hax_info("CLTS\n");
state->_cr0 &= ~(uint64)CR0_TS;
if (!vcpu->is_fpu_used) {
vcpu->is_fpu_used = 1;
}
if ((vmcs_err = load_vmcs(vcpu, &flags))) {
hax_panic_vcpu(vcpu, "load_vmcs failed while CLTS: %x\n",
vmcs_err);
Expand Down

0 comments on commit 6c2cd4d

Please sign in to comment.