void hvm_enable(struct hvm_function_table *fns)
{
- if ( hvm_enabled )
- return;
+ BUG_ON(hvm_enabled);
+ printk("HVM: %s enabled\n", fns->name);
/*
* Allow direct access to the PC debug port (it is often used for I/O
}
static struct hvm_function_table svm_function_table = {
+ .name = "SVM",
.disable = stop_svm,
.vcpu_initialise = svm_vcpu_initialise,
.vcpu_destroy = svm_vcpu_destroy,
return 0;
}
- if (!hsa[cpu])
- if (!(hsa[cpu] = alloc_host_save_area()))
- return 0;
+ if ( (hsa[cpu] == NULL) && ((hsa[cpu] = alloc_host_save_area()) == NULL) )
+ return 0;
rdmsr(MSR_EFER, eax, edx);
eax |= EFER_SVME;
phys_hsa_hi = (u32) (phys_hsa >> 32);
wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);
- if (!root_vmcb[cpu])
- if (!(root_vmcb[cpu] = alloc_vmcb()))
- return 0;
+ if ( (root_vmcb[cpu] == NULL) &&
+ ((root_vmcb[cpu] = alloc_vmcb()) == NULL) )
+ return 0;
root_vmcb_pa[cpu] = virt_to_maddr(root_vmcb[cpu]);
- if (cpu == 0)
- setup_vmcb_dump();
+ if ( cpu != 0 )
+ return 1;
+
+ setup_vmcb_dump();
hvm_enable(&svm_function_table);
#include <asm/shadow.h>
/* Dynamic (run-time adjusted) execution control flags. */
-static u32 vmx_pin_based_exec_control;
-static u32 vmx_cpu_based_exec_control;
-static u32 vmx_vmexit_control;
-static u32 vmx_vmentry_control;
+u32 vmx_pin_based_exec_control;
+u32 vmx_cpu_based_exec_control;
+u32 vmx_vmexit_control;
+u32 vmx_vmentry_control;
static u32 vmcs_revision_id;
return ctl;
}
-static void disable_intercept_for_msr(u32 msr)
-{
- /*
- * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address).
- * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
- */
- if ( msr <= 0x1fff )
- {
- __clear_bit(msr, hvm_msr_bitmap + 0x000); /* read-low */
- __clear_bit(msr, hvm_msr_bitmap + 0x400); /* write-low */
- }
- else if ( (msr >= 0xc0000000) && (msr <= 0xc0001fff) )
- {
- msr &= 0x1fff;
- __clear_bit(msr, hvm_msr_bitmap + 0x800); /* read-high */
- __clear_bit(msr, hvm_msr_bitmap + 0xc00); /* write-high */
- }
-}
-
void vmx_init_vmcs_config(void)
{
u32 vmx_msr_low, vmx_msr_high, min, max;
vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control;
vmx_vmexit_control = _vmx_vmexit_control;
vmx_vmentry_control = _vmx_vmentry_control;
-
- disable_intercept_for_msr(MSR_FS_BASE);
- disable_intercept_for_msr(MSR_GS_BASE);
}
else
{
__vmwrite(CPU_BASED_VM_EXEC_CONTROL, vmx_cpu_based_exec_control);
v->arch.hvm_vcpu.u.vmx.exec_control = vmx_cpu_based_exec_control;
- if ( vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_MSR_BITMAP )
+ if ( cpu_has_vmx_msr_bitmap )
__vmwrite(MSR_BITMAP, virt_to_maddr(hvm_msr_bitmap));
/* I/O access bitmap. */
return (idtv_info_field & INTR_INFO_VALID_MASK);
}
+static void disable_intercept_for_msr(u32 msr)
+{
+ /*
+ * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
+ * have the write-low and read-high bitmap offsets the wrong way round.
+ * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
+ */
+ if ( msr <= 0x1fff )
+ {
+ __clear_bit(msr, hvm_msr_bitmap + 0x000); /* read-low */
+ __clear_bit(msr, hvm_msr_bitmap + 0x800); /* write-low */
+ }
+ else if ( (msr >= 0xc0000000) && (msr <= 0xc0001fff) )
+ {
+ msr &= 0x1fff;
+ __clear_bit(msr, hvm_msr_bitmap + 0x400); /* read-high */
+ __clear_bit(msr, hvm_msr_bitmap + 0xc00); /* write-high */
+ }
+}
+
static struct hvm_function_table vmx_function_table = {
+ .name = "VMX",
.disable = stop_vmx,
.vcpu_initialise = vmx_vcpu_initialise,
.vcpu_destroy = vmx_vcpu_destroy,
return 0;
}
- printk("VMXON is done\n");
-
vmx_save_host_msrs();
+ if ( smp_processor_id() != 0 )
+ return 1;
+
hvm_enable(&vmx_function_table);
+ if ( cpu_has_vmx_msr_bitmap )
+ {
+ printk("VMX: MSR intercept bitmap enabled\n");
+ disable_intercept_for_msr(MSR_FS_BASE);
+ disable_intercept_for_msr(MSR_GS_BASE);
+ }
+
return 1;
}
#endif
};
-#define vmx_schedule_tail(next) \
- (next)->thread.arch_vmx.arch_vmx_schedule_tail((next))
-
#define VMX_DOMAIN(v) v->arch.arch_vmx.flags
#define ARCH_VMX_IO_WAIT 3 /* Waiting for I/O completion */
* supports Intel's VT-x and AMD's SVM extensions.
*/
struct hvm_function_table {
+ char *name;
+
/*
* Disable HVM functionality
*/
unsigned long vmxassist_enabled:1;
};
-#define vmx_schedule_tail(next) \
- (next)->thread.arch_vmx.arch_vmx_schedule_tail((next))
-
struct vmcs_struct *vmx_alloc_host_vmcs(void);
void vmx_free_host_vmcs(struct vmcs_struct *vmcs);
void vmx_vmcs_enter(struct vcpu *v);
void vmx_vmcs_exit(struct vcpu *v);
-#define VMCS_USE_HOST_ENV 1
-#define VMCS_USE_SEPARATE_ENV 0
-
-extern int vmcs_version;
-
#define CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004
#define CPU_BASED_USE_TSC_OFFSETING 0x00000008
#define CPU_BASED_HLT_EXITING 0x00000080
#define CPU_BASED_ACTIVATE_MSR_BITMAP 0x10000000
#define CPU_BASED_MONITOR_EXITING 0x20000000
#define CPU_BASED_PAUSE_EXITING 0x40000000
+extern u32 vmx_cpu_based_exec_control;
#define PIN_BASED_EXT_INTR_MASK 0x00000001
#define PIN_BASED_NMI_EXITING 0x00000008
+extern u32 vmx_pin_based_exec_control;
#define VM_EXIT_IA32E_MODE 0x00000200
#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000
+extern u32 vmx_vmexit_control;
#define VM_ENTRY_IA32E_MODE 0x00000200
#define VM_ENTRY_SMM 0x00000400
#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800
+extern u32 vmx_vmentry_control;
+
+#define cpu_has_vmx_msr_bitmap \
+ (vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_MSR_BITMAP)
/* VMCS Encordings */
enum vmcs_field {
void vmx_do_resume(struct vcpu *);
void set_guest_time(struct vcpu *v, u64 gtime);
-extern unsigned int cpu_rev;
-
/*
* Exit Reasons
*/