Skip to content

Commit

Permalink
KVM: VMX: Split segments reload in vmx_load_host_state()
Browse files Browse the repository at this point in the history
vmx_load_host_state() bundles fs, gs, ldt, and tss reloading into
one in the hope that it is infrequent. With smp guests, fs reloading is
frequent due to fs being used by threads.

Unbundle the reloads so reduce expensive gs reloads.

Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
Signed-off-by: Avi Kivity <avi@qumranet.com>
  • Loading branch information
Laurent Vivier authored and Avi Kivity committed Oct 13, 2007
1 parent d39dba5 commit 152d3f2
Showing 1 changed file with 12 additions and 10 deletions.
22 changes: 12 additions & 10 deletions drivers/kvm/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ struct vcpu_vmx {
struct {
int loaded;
u16 fs_sel, gs_sel, ldt_sel;
int fs_gs_ldt_reload_needed;
int gs_ldt_reload_needed;
int fs_reload_needed;
}host_state;

};
Expand Down Expand Up @@ -353,20 +354,21 @@ static void vmx_save_host_state(struct vcpu_vmx *vmx)
* allow segment selectors with cpl > 0 or ti == 1.
*/
vmx->host_state.ldt_sel = read_ldt();
vmx->host_state.fs_gs_ldt_reload_needed = vmx->host_state.ldt_sel;
vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel;
vmx->host_state.fs_sel = read_fs();
if (!(vmx->host_state.fs_sel & 7))
if (!(vmx->host_state.fs_sel & 7)) {
vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel);
else {
vmx->host_state.fs_reload_needed = 0;
} else {
vmcs_write16(HOST_FS_SELECTOR, 0);
vmx->host_state.fs_gs_ldt_reload_needed = 1;
vmx->host_state.fs_reload_needed = 1;
}
vmx->host_state.gs_sel = read_gs();
if (!(vmx->host_state.gs_sel & 7))
vmcs_write16(HOST_GS_SELECTOR, vmx->host_state.gs_sel);
else {
vmcs_write16(HOST_GS_SELECTOR, 0);
vmx->host_state.fs_gs_ldt_reload_needed = 1;
vmx->host_state.gs_ldt_reload_needed = 1;
}

#ifdef CONFIG_X86_64
Expand Down Expand Up @@ -396,9 +398,10 @@ static void vmx_load_host_state(struct vcpu_vmx *vmx)
return;

vmx->host_state.loaded = 0;
if (vmx->host_state.fs_gs_ldt_reload_needed) {
load_ldt(vmx->host_state.ldt_sel);
if (vmx->host_state.fs_reload_needed)
load_fs(vmx->host_state.fs_sel);
if (vmx->host_state.gs_ldt_reload_needed) {
load_ldt(vmx->host_state.ldt_sel);
/*
* If we have to reload gs, we must take care to
* preserve our gs base.
Expand All @@ -409,9 +412,8 @@ static void vmx_load_host_state(struct vcpu_vmx *vmx)
wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
#endif
local_irq_restore(flags);

reload_tss();
}
reload_tss();
save_msrs(vmx->guest_msrs, vmx->save_nmsrs);
load_msrs(vmx->host_msrs, vmx->save_nmsrs);
if (msr_efer_need_save_restore(vmx))
Expand Down

0 comments on commit 152d3f2

Please sign in to comment.