diff -r 47c05f13d036 -r c3afa05c3cb5 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Tue Nov 30 13:49:59 2010 -0600 +++ b/xen/arch/x86/hvm/hvm.c Thu Dec 02 11:08:21 2010 -0600 @@ -1144,6 +1144,31 @@ return 0; } +int hvm_handle_xsetbv(u64 new_bv) +{ + struct vcpu *v = current; + struct segment_register sreg; + + hvm_get_segment_register(v, x86_seg_ss, &sreg); + if ( sreg.attr.fields.dpl != 0 ) + goto err; + + if ( ((new_bv ^ xfeature_mask) & ~xfeature_mask) || !(new_bv & 1) ) + goto err; + + if ( (xfeature_mask & XSTATE_YMM & new_bv) && !(new_bv & XSTATE_SSE) ) + goto err; + + v->arch.xcr0 = new_bv; + v->arch.xcr0_accum |= new_bv; + set_xcr0(new_bv); + + return 0; +err: + hvm_inject_exception(TRAP_gp_fault, 0, 0); + return -1; +} + int hvm_set_efer(uint64_t value) { struct vcpu *v = current; diff -r 47c05f13d036 -r c3afa05c3cb5 xen/arch/x86/hvm/svm/emulate.c --- a/xen/arch/x86/hvm/svm/emulate.c Tue Nov 30 13:49:59 2010 -0600 +++ b/xen/arch/x86/hvm/svm/emulate.c Thu Dec 02 11:08:21 2010 -0600 @@ -101,6 +101,7 @@ MAKE_INSTR(INT3, 1, 0xcc); MAKE_INSTR(RDTSC, 2, 0x0f, 0x31); MAKE_INSTR(PAUSE, 1, 0x90); +MAKE_INSTR(XSETBV, 3, 0x0f, 0x01, 0xd1); static const u8 *opc_bytes[INSTR_MAX_COUNT] = { @@ -114,6 +115,7 @@ [INSTR_INT3] = OPCODE_INT3, [INSTR_RDTSC] = OPCODE_RDTSC, [INSTR_PAUSE] = OPCODE_PAUSE, + [INSTR_XSETBV] = OPCODE_XSETBV, }; static int fetch(struct vcpu *v, u8 *buf, unsigned long addr, int len) diff -r 47c05f13d036 -r c3afa05c3cb5 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Tue Nov 30 13:49:59 2010 -0600 +++ b/xen/arch/x86/hvm/svm/svm.c Thu Dec 02 11:08:21 2010 -0600 @@ -1603,6 +1603,13 @@ hvm_inject_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE, 0); break; + case VMEXIT_XSETBV: + if ( (inst_len = __get_instruction_length(current, INSTR_XSETBV))==0 ) + break; + if ( hvm_handle_xsetbv((((u64)regs->edx) << 32) | regs->eax) == 0 ) + __update_guest_eip(regs, inst_len); + break; + case VMEXIT_NPF: perfc_incra(svmexits, VMEXIT_NPF_PERFC); regs->error_code = vmcb->exitinfo1; diff -r 47c05f13d036 -r c3afa05c3cb5 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Tue Nov 30 13:49:59 2010 -0600 +++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Dec 02 11:08:21 2010 -0600 @@ -2197,30 +2197,6 @@ return 0; } -static int vmx_handle_xsetbv(u64 new_bv) -{ - struct vcpu *v = current; - struct segment_register sreg; - - hvm_get_segment_register(v, x86_seg_ss, &sreg); - if ( sreg.attr.fields.dpl != 0 ) - goto err; - - if ( ((new_bv ^ xfeature_mask) & ~xfeature_mask) || !(new_bv & 1) ) - goto err; - - if ( (xfeature_mask & XSTATE_YMM & new_bv) && !(new_bv & XSTATE_SSE) ) - goto err; - - v->arch.xcr0 = new_bv; - v->arch.xcr0_accum |= new_bv; - set_xcr0(new_bv); - return 0; -err: - vmx_inject_hw_exception(TRAP_gp_fault, 0); - return -1; -} - asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs) { unsigned int exit_reason, idtv_info, intr_info = 0, vector = 0; @@ -2613,7 +2589,7 @@ case EXIT_REASON_XSETBV: { u64 new_bv = (((u64)regs->edx) << 32) | regs->eax; - if ( vmx_handle_xsetbv(new_bv) == 0 ) + if ( hvm_handle_xsetbv(new_bv) == 0 ) update_guest_eip(); /* Safe: XSETBV */ break; } diff -r 47c05f13d036 -r c3afa05c3cb5 xen/include/asm-x86/hvm/support.h --- a/xen/include/asm-x86/hvm/support.h Tue Nov 30 13:49:59 2010 -0600 +++ b/xen/include/asm-x86/hvm/support.h Thu Dec 02 11:08:21 2010 -0600 @@ -128,6 +128,8 @@ void hvm_rdtsc_intercept(struct cpu_user_regs *regs); +int hvm_handle_xsetbv(u64 new_bv); + /* These functions all return X86EMUL return codes. */ int hvm_set_efer(uint64_t value); int hvm_set_cr0(unsigned long value); diff -r 47c05f13d036 -r c3afa05c3cb5 xen/include/asm-x86/hvm/svm/emulate.h --- a/xen/include/asm-x86/hvm/svm/emulate.h Tue Nov 30 13:49:59 2010 -0600 +++ b/xen/include/asm-x86/hvm/svm/emulate.h Thu Dec 02 11:08:21 2010 -0600 @@ -32,6 +32,7 @@ INSTR_INT3, INSTR_RDTSC, INSTR_PAUSE, + INSTR_XSETBV, INSTR_MAX_COUNT /* Must be last - Number of instructions supported */ }; diff -r 47c05f13d036 -r c3afa05c3cb5 xen/include/asm-x86/hvm/svm/vmcb.h --- a/xen/include/asm-x86/hvm/svm/vmcb.h Tue Nov 30 13:49:59 2010 -0600 +++ b/xen/include/asm-x86/hvm/svm/vmcb.h Thu Dec 02 11:08:21 2010 -0600 @@ -299,6 +299,7 @@ VMEXIT_MONITOR = 138, /* 0x8a */ VMEXIT_MWAIT = 139, /* 0x8b */ VMEXIT_MWAIT_CONDITIONAL= 140, /* 0x8c */ + VMEXIT_XSETBV = 141, /* 0x8d */ VMEXIT_NPF = 1024, /* 0x400, nested paging fault */ VMEXIT_INVALID = -1 };