Remove cross-vendor support now that VMs can no longer have a different vendor than the host.
While at it, refactor the function to exit early and skip initialising the emulation context when FEP is not enabled. No functional change intended. Signed-off-by: Alejandro Vallejo <[email protected]> --- The diff is annoying, but keeping prior logic is silly when it can be simplified and the emulation context initialisation removed on the overwhelming majority of cases. v2: * Fix bug introduced in v1: Don't emulate instructions when they shouldn't be emulated. * Refactor the function so it's simpler. --- xen/arch/x86/hvm/hvm.c | 77 +++++++++++++++----------------------- xen/arch/x86/hvm/svm/svm.c | 3 +- xen/arch/x86/hvm/vmx/vmx.c | 3 +- 3 files changed, 32 insertions(+), 51 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 4d37a93c57..8708af9425 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3832,69 +3832,47 @@ int hvm_descriptor_access_intercept(uint64_t exit_info, return X86EMUL_OKAY; } -static bool cf_check is_cross_vendor( - const struct x86_emulate_state *state, const struct x86_emulate_ctxt *ctxt) -{ - switch ( ctxt->opcode ) - { - case X86EMUL_OPC(0x0f, 0x05): /* syscall */ - case X86EMUL_OPC(0x0f, 0x34): /* sysenter */ - case X86EMUL_OPC(0x0f, 0x35): /* sysexit */ - return true; - } - - return false; -} - void hvm_ud_intercept(struct cpu_user_regs *regs) { struct vcpu *cur = current; - bool should_emulate = - cur->domain->arch.cpuid->x86_vendor != boot_cpu_data.x86_vendor; struct hvm_emulate_ctxt ctxt; + const struct segment_register *cs = &ctxt.seg_reg[x86_seg_cs]; + uint32_t walk = PFEC_insn_fetch; + unsigned long addr; + char sig[5]; /* ud2; .ascii "xen" */ - hvm_emulate_init_once(&ctxt, opt_hvm_fep ? NULL : is_cross_vendor, regs); + if ( !opt_hvm_fep ) + goto reinject; - if ( opt_hvm_fep ) - { - const struct segment_register *cs = &ctxt.seg_reg[x86_seg_cs]; - uint32_t walk = ((ctxt.seg_reg[x86_seg_ss].dpl == 3) - ? PFEC_user_mode : 0) | PFEC_insn_fetch; - unsigned long addr; - char sig[5]; /* ud2; .ascii "xen" */ - - if ( hvm_virtual_to_linear_addr(x86_seg_cs, cs, regs->rip, - sizeof(sig), hvm_access_insn_fetch, - cs, &addr) && - (hvm_copy_from_guest_linear(sig, addr, sizeof(sig), - walk, NULL) == HVMTRANS_okay) && - (memcmp(sig, "\xf\xb" "xen", sizeof(sig)) == 0) ) - { - regs->rip += sizeof(sig); - regs->eflags &= ~X86_EFLAGS_RF; + hvm_emulate_init_once(&ctxt, NULL, regs); - /* Zero the upper 32 bits of %rip if not in 64bit mode. */ - if ( !(hvm_long_mode_active(cur) && cs->l) ) - regs->rip = (uint32_t)regs->rip; + if ( ctxt.seg_reg[x86_seg_ss].dpl == 3 ) + walk |= PFEC_user_mode; - add_taint(TAINT_HVM_FEP); + if ( hvm_virtual_to_linear_addr(x86_seg_cs, cs, regs->rip, + sizeof(sig), hvm_access_insn_fetch, + cs, &addr) && + (hvm_copy_from_guest_linear(sig, addr, sizeof(sig), + walk, NULL) == HVMTRANS_okay) && + (memcmp(sig, "\xf\xb" "xen", sizeof(sig)) == 0) ) + { + regs->rip += sizeof(sig); + regs->eflags &= ~X86_EFLAGS_RF; - should_emulate = true; - } - } + /* Zero the upper 32 bits of %rip if not in 64bit mode. */ + if ( !(hvm_long_mode_active(cur) && cs->l) ) + regs->rip = (uint32_t)regs->rip; - if ( !should_emulate ) - { - hvm_inject_hw_exception(X86_EXC_UD, X86_EVENT_NO_EC); - return; + add_taint(TAINT_HVM_FEP); } + else + goto reinject; switch ( hvm_emulate_one(&ctxt, VIO_no_completion) ) { case X86EMUL_UNHANDLEABLE: case X86EMUL_UNIMPLEMENTED: - hvm_inject_hw_exception(X86_EXC_UD, X86_EVENT_NO_EC); - break; + goto reinject; case X86EMUL_EXCEPTION: hvm_inject_event(&ctxt.ctxt.event); /* fall through */ @@ -3902,6 +3880,11 @@ void hvm_ud_intercept(struct cpu_user_regs *regs) hvm_emulate_writeback(&ctxt); break; } + + return; + + reinject: + hvm_inject_hw_exception(X86_EXC_UD, X86_EVENT_NO_EC); } enum hvm_intblk hvm_interrupt_blocked(struct vcpu *v, struct hvm_intack intack) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 18ba837738..10d1bf350c 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -589,8 +589,7 @@ static void cf_check svm_cpuid_policy_changed(struct vcpu *v) const struct cpu_policy *cp = v->domain->arch.cpu_policy; u32 bitmap = vmcb_get_exception_intercepts(vmcb); - if ( opt_hvm_fep || - (v->domain->arch.cpuid->x86_vendor != boot_cpu_data.x86_vendor) ) + if ( opt_hvm_fep ) bitmap |= (1U << X86_EXC_UD); else bitmap &= ~(1U << X86_EXC_UD); diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 82c55f49ae..eda99e268d 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -803,8 +803,7 @@ static void cf_check vmx_cpuid_policy_changed(struct vcpu *v) const struct cpu_policy *cp = v->domain->arch.cpu_policy; int rc = 0; - if ( opt_hvm_fep || - (v->domain->arch.cpuid->x86_vendor != boot_cpu_data.x86_vendor) ) + if ( opt_hvm_fep ) v->arch.hvm.vmx.exception_bitmap |= (1U << X86_EXC_UD); else v->arch.hvm.vmx.exception_bitmap &= ~(1U << X86_EXC_UD); -- 2.43.0
