|
@@ -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 */
|