KVM: nVMX: Move host-state field setup to a function
Move the setting of constant host-state fields (fields that do not change throughout the life of the guest) from vmx_vcpu_setup to a new common function vmx_set_constant_host_state(). This function will also be used to set the host state when running L2 guests. Signed-off-by: Nadav Har'El <nyh@il.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
This commit is contained in:
parent
49f705c532
commit
a3a8ff8ebf
@ -3394,18 +3394,52 @@ static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only)
|
||||
__vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode, msr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the vmcs's constant host-state fields, i.e., host-state fields that
|
||||
* will not change in the lifetime of the guest.
|
||||
* Note that host-state that does change is set elsewhere. E.g., host-state
|
||||
* that is set differently for each CPU is set in vmx_vcpu_load(), not here.
|
||||
*/
|
||||
static void vmx_set_constant_host_state(void)
|
||||
{
|
||||
u32 low32, high32;
|
||||
unsigned long tmpl;
|
||||
struct desc_ptr dt;
|
||||
|
||||
vmcs_writel(HOST_CR0, read_cr0() | X86_CR0_TS); /* 22.2.3 */
|
||||
vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */
|
||||
vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */
|
||||
|
||||
vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
|
||||
vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
|
||||
vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
|
||||
vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
|
||||
vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8); /* 22.2.4 */
|
||||
|
||||
native_store_idt(&dt);
|
||||
vmcs_writel(HOST_IDTR_BASE, dt.address); /* 22.2.4 */
|
||||
|
||||
asm("mov $.Lkvm_vmx_return, %0" : "=r"(tmpl));
|
||||
vmcs_writel(HOST_RIP, tmpl); /* 22.2.5 */
|
||||
|
||||
rdmsr(MSR_IA32_SYSENTER_CS, low32, high32);
|
||||
vmcs_write32(HOST_IA32_SYSENTER_CS, low32);
|
||||
rdmsrl(MSR_IA32_SYSENTER_EIP, tmpl);
|
||||
vmcs_writel(HOST_IA32_SYSENTER_EIP, tmpl); /* 22.2.3 */
|
||||
|
||||
if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) {
|
||||
rdmsr(MSR_IA32_CR_PAT, low32, high32);
|
||||
vmcs_write64(HOST_IA32_PAT, low32 | ((u64) high32 << 32));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets up the vmcs for emulated real mode.
|
||||
*/
|
||||
static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
|
||||
{
|
||||
u32 host_sysenter_cs, msr_low, msr_high;
|
||||
u32 junk;
|
||||
u64 host_pat;
|
||||
unsigned long a;
|
||||
struct desc_ptr dt;
|
||||
int i;
|
||||
unsigned long kvm_vmx_return;
|
||||
u32 exec_control;
|
||||
|
||||
/* I/O */
|
||||
@ -3462,16 +3496,9 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
|
||||
vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, !!bypass_guest_pf);
|
||||
vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */
|
||||
|
||||
vmcs_writel(HOST_CR0, read_cr0() | X86_CR0_TS); /* 22.2.3 */
|
||||
vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */
|
||||
vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */
|
||||
|
||||
vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
|
||||
vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
|
||||
vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
|
||||
vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */
|
||||
vmcs_write16(HOST_GS_SELECTOR, 0); /* 22.2.4 */
|
||||
vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
|
||||
vmx_set_constant_host_state();
|
||||
#ifdef CONFIG_X86_64
|
||||
rdmsrl(MSR_FS_BASE, a);
|
||||
vmcs_writel(HOST_FS_BASE, a); /* 22.2.4 */
|
||||
@ -3482,32 +3509,15 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
|
||||
vmcs_writel(HOST_GS_BASE, 0); /* 22.2.4 */
|
||||
#endif
|
||||
|
||||
vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8); /* 22.2.4 */
|
||||
|
||||
native_store_idt(&dt);
|
||||
vmcs_writel(HOST_IDTR_BASE, dt.address); /* 22.2.4 */
|
||||
|
||||
asm("mov $.Lkvm_vmx_return, %0" : "=r"(kvm_vmx_return));
|
||||
vmcs_writel(HOST_RIP, kvm_vmx_return); /* 22.2.5 */
|
||||
vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
|
||||
vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0);
|
||||
vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host));
|
||||
vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0);
|
||||
vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest));
|
||||
|
||||
rdmsr(MSR_IA32_SYSENTER_CS, host_sysenter_cs, junk);
|
||||
vmcs_write32(HOST_IA32_SYSENTER_CS, host_sysenter_cs);
|
||||
rdmsrl(MSR_IA32_SYSENTER_ESP, a);
|
||||
vmcs_writel(HOST_IA32_SYSENTER_ESP, a); /* 22.2.3 */
|
||||
rdmsrl(MSR_IA32_SYSENTER_EIP, a);
|
||||
vmcs_writel(HOST_IA32_SYSENTER_EIP, a); /* 22.2.3 */
|
||||
|
||||
if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) {
|
||||
rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
|
||||
host_pat = msr_low | ((u64) msr_high << 32);
|
||||
vmcs_write64(HOST_IA32_PAT, host_pat);
|
||||
}
|
||||
if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
|
||||
u32 msr_low, msr_high;
|
||||
u64 host_pat;
|
||||
rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
|
||||
host_pat = msr_low | ((u64) msr_high << 32);
|
||||
/* Write the default value follow host pat */
|
||||
|
Loading…
Reference in New Issue
Block a user