# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1194609927 0
# Node ID fc8be8f3707bd1ffeab55efea5f9804fa570177e
# Parent 1dcb24e6c4e42ecdb7f1944a431e68c4509757eb
x86, hvm: Better handling of INVD/WBINVD on VMX and SVM.
Also better handling of MONITOR/MWAIT on VMX.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/svm/emulate.c | 2 +
xen/arch/x86/hvm/svm/svm.c | 35 +++++++++++++++++-----------------
xen/arch/x86/hvm/svm/vmcb.c | 3 +-
xen/arch/x86/hvm/vmx/vmcs.c | 1
xen/arch/x86/hvm/vmx/vmx.c | 14 +++++++++----
xen/include/asm-x86/hvm/svm/emulate.h | 1
xen/include/asm-x86/hvm/svm/vmcb.h | 10 ++++++++-
xen/include/asm-x86/perfc_defn.h | 4 +--
8 files changed, 45 insertions(+), 25 deletions(-)
diff -r 1dcb24e6c4e4 -r fc8be8f3707b xen/arch/x86/hvm/svm/emulate.c
--- a/xen/arch/x86/hvm/svm/emulate.c Thu Nov 08 18:15:36 2007 +0000
+++ b/xen/arch/x86/hvm/svm/emulate.c Fri Nov 09 12:05:27 2007 +0000
@@ -344,6 +344,7 @@ unsigned long svm_rip2pointer(struct vcp
* Special case: Last byte, if zero, doesn't need to match.
*/
MAKE_INSTR(INVD, 2, 0x0f, 0x08);
+MAKE_INSTR(WBINVD, 2, 0x0f, 0x09);
MAKE_INSTR(CPUID, 2, 0x0f, 0xa2);
MAKE_INSTR(RDMSR, 2, 0x0f, 0x32);
MAKE_INSTR(WRMSR, 2, 0x0f, 0x30);
@@ -378,6 +379,7 @@ static const u8 *opc_bytes[INSTR_MAX_COU
static const u8 *opc_bytes[INSTR_MAX_COUNT] =
{
[INSTR_INVD] = OPCODE_INVD,
+ [INSTR_WBINVD] = OPCODE_WBINVD,
[INSTR_CPUID] = OPCODE_CPUID,
[INSTR_RDMSR] = OPCODE_RDMSR,
[INSTR_WRMSR] = OPCODE_WRMSR,
diff -r 1dcb24e6c4e4 -r fc8be8f3707b xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Thu Nov 08 18:15:36 2007 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c Fri Nov 09 12:05:27 2007 +0000
@@ -1942,24 +1942,24 @@ static void svm_vmexit_do_hlt(struct vmc
hvm_hlt(regs->eflags);
}
-static void svm_vmexit_do_invd(struct cpu_user_regs *regs)
-{
+static void svm_vmexit_do_invalidate_cache(struct cpu_user_regs *regs)
+{
+ enum instruction_index list[] = { INSTR_INVD, INSTR_WBINVD };
+ struct vcpu *curr = current;
+ struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb;
int inst_len;
-
- /* Invalidate the cache - we can't really do that safely - maybe we should
- * WBINVD, but I think it's just fine to completely ignore it - we should
- * have cache-snooping that solves it anyways. -- Mats P.
- */
-
- /* Tell the user that we did this - just in case someone runs some really
- * weird operating system and wants to know why it's not working...
- */
- gdprintk(XENLOG_WARNING, "INVD instruction intercepted - ignored\n");
-
- inst_len = __get_instruction_length(current, INSTR_INVD, NULL);
+
+ if ( !list_empty(&(domain_hvm_iommu(curr->domain)->pdev_list)) )
+ {
+ vmcb->general2_intercepts &= ~GENERAL2_INTERCEPT_WBINVD;
+ wbinvd();
+ }
+
+ inst_len = __get_instruction_length_from_list(
+ curr, list, ARRAY_SIZE(list), NULL, NULL);
__update_guest_eip(regs, inst_len);
-}
-
+}
+
void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
{
struct vcpu *v = current;
@@ -2205,7 +2205,8 @@ asmlinkage void svm_vmexit_handler(struc
break;
case VMEXIT_INVD:
- svm_vmexit_do_invd(regs);
+ case VMEXIT_WBINVD:
+ svm_vmexit_do_invalidate_cache(regs);
break;
case VMEXIT_TASK_SWITCH: {
diff -r 1dcb24e6c4e4 -r fc8be8f3707b xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c Thu Nov 08 18:15:36 2007 +0000
+++ b/xen/arch/x86/hvm/svm/vmcb.c Fri Nov 09 12:05:27 2007 +0000
@@ -127,7 +127,8 @@ static int construct_vmcb(struct vcpu *v
GENERAL2_INTERCEPT_VMRUN | GENERAL2_INTERCEPT_VMMCALL |
GENERAL2_INTERCEPT_VMLOAD | GENERAL2_INTERCEPT_VMSAVE |
GENERAL2_INTERCEPT_STGI | GENERAL2_INTERCEPT_CLGI |
- GENERAL2_INTERCEPT_SKINIT | GENERAL2_INTERCEPT_RDTSCP;
+ GENERAL2_INTERCEPT_SKINIT | GENERAL2_INTERCEPT_RDTSCP |
+ GENERAL2_INTERCEPT_WBINVD;
/* Intercept all debug-register writes. */
vmcb->dr_intercepts = ~0u;
diff -r 1dcb24e6c4e4 -r fc8be8f3707b xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c Thu Nov 08 18:15:36 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/vmcs.c Fri Nov 09 12:05:27 2007 +0000
@@ -84,6 +84,7 @@ static void vmx_init_vmcs_config(void)
min = (CPU_BASED_HLT_EXITING |
CPU_BASED_INVLPG_EXITING |
+ CPU_BASED_MONITOR_EXITING |
CPU_BASED_MWAIT_EXITING |
CPU_BASED_MOV_DR_EXITING |
CPU_BASED_ACTIVATE_IO_BITMAP |
diff -r 1dcb24e6c4e4 -r fc8be8f3707b xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Thu Nov 08 18:15:36 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c Fri Nov 09 12:05:27 2007 +0000
@@ -2881,10 +2881,9 @@ asmlinkage void vmx_vmexit_handler(struc
if ( vmx_do_msr_write(regs) )
__update_guest_eip(inst_len);
break;
+
case EXIT_REASON_MWAIT_INSTRUCTION:
case EXIT_REASON_MONITOR_INSTRUCTION:
- case EXIT_REASON_PAUSE_INSTRUCTION:
- goto exit_and_crash;
case EXIT_REASON_VMCLEAR:
case EXIT_REASON_VMLAUNCH:
case EXIT_REASON_VMPTRLD:
@@ -2894,8 +2893,6 @@ asmlinkage void vmx_vmexit_handler(struc
case EXIT_REASON_VMWRITE:
case EXIT_REASON_VMXOFF:
case EXIT_REASON_VMXON:
- /* Report invalid opcode exception when a VMX guest tries to execute
- any of the VMX instructions */
vmx_inject_hw_exception(v, TRAP_invalid_op, VMX_DELIVER_NO_ERROR_CODE);
break;
@@ -2908,6 +2905,15 @@ asmlinkage void vmx_vmexit_handler(struc
exit_qualification = __vmread(EXIT_QUALIFICATION);
offset = exit_qualification & 0x0fffUL;
handle_mmio(APIC_DEFAULT_PHYS_BASE | offset);
+ break;
+ }
+
+ case EXIT_REASON_INVD:
+ {
+ inst_len = __get_instruction_length(); /* Safe: INVD */
+ __update_guest_eip(inst_len);
+ if ( !list_empty(&(domain_hvm_iommu(v->domain)->pdev_list)) )
+ wbinvd();
break;
}
diff -r 1dcb24e6c4e4 -r fc8be8f3707b xen/include/asm-x86/hvm/svm/emulate.h
--- a/xen/include/asm-x86/hvm/svm/emulate.h Thu Nov 08 18:15:36 2007 +0000
+++ b/xen/include/asm-x86/hvm/svm/emulate.h Fri Nov 09 12:05:27 2007 +0000
@@ -43,6 +43,7 @@ typedef enum OPERATING_MODE_ {
/* Enumerate some standard instructions that we support */
enum instruction_index {
INSTR_INVD,
+ INSTR_WBINVD,
INSTR_CPUID,
INSTR_RDMSR,
INSTR_WRMSR,
diff -r 1dcb24e6c4e4 -r fc8be8f3707b xen/include/asm-x86/hvm/svm/vmcb.h
--- a/xen/include/asm-x86/hvm/svm/vmcb.h Thu Nov 08 18:15:36 2007 +0000
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h Fri Nov 09 12:05:27 2007 +0000
@@ -72,7 +72,11 @@ enum GenericIntercept2bits
GENERAL2_INTERCEPT_CLGI = 1 << 5,
GENERAL2_INTERCEPT_SKINIT = 1 << 6,
GENERAL2_INTERCEPT_RDTSCP = 1 << 7,
- GENERAL2_INTERCEPT_ICEBP = 1 << 8
+ GENERAL2_INTERCEPT_ICEBP = 1 << 8,
+ GENERAL2_INTERCEPT_WBINVD = 1 << 9,
+ GENERAL2_INTERCEPT_MONITOR = 1 << 10,
+ GENERAL2_INTERCEPT_MWAIT = 1 << 11,
+ GENERAL2_INTERCEPT_MWAIT_CONDITIONAL = 1 << 12
};
@@ -291,6 +295,10 @@ enum VMEXIT_EXITCODE
VMEXIT_SKINIT = 134,
VMEXIT_RDTSCP = 135,
VMEXIT_ICEBP = 136,
+ VMEXIT_WBINVD = 137,
+ VMEXIT_MONITOR = 138,
+ VMEXIT_MWAIT = 139,
+ VMEXIT_MWAIT_CONDITIONAL= 140,
VMEXIT_NPF = 1024, /* nested paging fault */
VMEXIT_INVALID = -1
};
diff -r 1dcb24e6c4e4 -r fc8be8f3707b xen/include/asm-x86/perfc_defn.h
--- a/xen/include/asm-x86/perfc_defn.h Thu Nov 08 18:15:36 2007 +0000
+++ b/xen/include/asm-x86/perfc_defn.h Fri Nov 09 12:05:27 2007 +0000
@@ -9,8 +9,8 @@ PERFCOUNTER_ARRAY(vmexits,
PERFCOUNTER_ARRAY(vmexits, "vmexits", VMX_PERF_EXIT_REASON_SIZE)
PERFCOUNTER_ARRAY(cause_vector, "cause vector", VMX_PERF_VECTOR_SIZE)
-#define VMEXIT_NPF_PERFC 137
-#define SVM_PERF_EXIT_REASON_SIZE (1+137)
+#define VMEXIT_NPF_PERFC 141
+#define SVM_PERF_EXIT_REASON_SIZE (1+141)
PERFCOUNTER_ARRAY(svmexits, "SVMexits", SVM_PERF_EXIT_REASON_SIZE)
PERFCOUNTER(seg_fixups, "segmentation fixups")
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|