From 5fb75513e25e9a135df3fd92b35ad749ec7cf7cb Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 16 Sep 2014 13:56:45 +0200 Subject: [PATCH 1/3] passthrough: streamline _hvm_dirq_assist() The loop inside this function was calling two functions with loop- invariable arguments which clearly don't need calling more than once: send_guest_pirq() and __msi_pirq_eoi(). After moving these out of the loop it further became apparent that folding the hvm_pci_msi_assert() helper into the main function can further help readability. In the course of this I noticed that __hvm_dpci_eoi() called hvm_pci_intx_deassert() unconditionally, whereas hvm_pci_intx_assert() (correctly) got called only when !hvm_domain_use_pirq(), so the former is being made conditional now too. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- xen/drivers/passthrough/io.c | 50 ++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c index ef75b94dc4..4cd32b5985 100644 --- a/xen/drivers/passthrough/io.c +++ b/xen/drivers/passthrough/io.c @@ -513,45 +513,39 @@ void hvm_dpci_msi_eoi(struct domain *d, int vector) spin_unlock(&d->event_lock); } -static void hvm_pci_msi_assert( - struct domain *d, struct hvm_pirq_dpci *pirq_dpci) -{ - struct pirq *pirq = dpci_pirq(pirq_dpci); - - if ( hvm_domain_use_pirq(d, pirq) ) - send_guest_pirq(d, pirq); - else - vmsi_deliver_pirq(d, pirq_dpci); -} - static int _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci, void *arg) { if ( test_and_clear_bool(pirq_dpci->masked) ) { + struct pirq *pirq = dpci_pirq(pirq_dpci); const struct dev_intx_gsi_link *digl; + if ( hvm_domain_use_pirq(d, pirq) ) + { + send_guest_pirq(d, pirq); + + if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI ) + return 0; + } + if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI ) { - hvm_pci_msi_assert(d, pirq_dpci); + vmsi_deliver_pirq(d, pirq_dpci); return 0; } list_for_each_entry ( digl, &pirq_dpci->digl_list, list ) { - struct pirq *info = dpci_pirq(pirq_dpci); - - if ( hvm_domain_use_pirq(d, info) ) - send_guest_pirq(d, info); - else - hvm_pci_intx_assert(d, digl->device, digl->intx); + hvm_pci_intx_assert(d, digl->device, digl->intx); pirq_dpci->pending++; + } - if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE ) - { - /* for translated MSI to INTx interrupt, eoi as early as possible */ - __msi_pirq_eoi(pirq_dpci); - } + if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE ) + { + /* for translated MSI to INTx interrupt, eoi as early as possible */ + __msi_pirq_eoi(pirq_dpci); + return 0; } /* @@ -561,8 +555,8 @@ static int _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci, * guest will never deal with the irq, then the physical interrupt line * will never be deasserted. */ - if ( pt_irq_need_timer(pirq_dpci->flags) ) - set_timer(&pirq_dpci->timer, NOW() + PT_IRQ_TIME_OUT); + ASSERT(pt_irq_need_timer(pirq_dpci->flags)); + set_timer(&pirq_dpci->timer, NOW() + PT_IRQ_TIME_OUT); } return 0; @@ -583,12 +577,12 @@ static void __hvm_dpci_eoi(struct domain *d, const struct hvm_girq_dpci_mapping *girq, const union vioapic_redir_entry *ent) { - struct pirq *pirq; + struct pirq *pirq = pirq_info(d, girq->machine_gsi); struct hvm_pirq_dpci *pirq_dpci; - hvm_pci_intx_deassert(d, girq->device, girq->intx); + if ( !hvm_domain_use_pirq(d, pirq) ) + hvm_pci_intx_deassert(d, girq->device, girq->intx); - pirq = pirq_info(d, girq->machine_gsi); pirq_dpci = pirq_dpci(pirq); /* From d268f6ae2d191cc945f3492e8797fa8444877c10 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 16 Sep 2014 13:57:44 +0200 Subject: [PATCH 2/3] x86: show page walk when create_bounce_frame() encounters a fault ... getting the native code in sync with the compat mode one. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- xen/arch/x86/x86_64/entry.S | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 42835d0341..ade555b655 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -442,19 +442,30 @@ UNLIKELY_START(z, create_bounce_frame_bad_bounce_ip) __UNLIKELY_END(create_bounce_frame_bad_bounce_ip) movq %rax,UREGS_rip+8(%rsp) ret - _ASM_EXTABLE(.Lft2, dom_crash_sync_extable) - _ASM_EXTABLE(.Lft3, dom_crash_sync_extable) - _ASM_EXTABLE(.Lft4, dom_crash_sync_extable) - _ASM_EXTABLE(.Lft5, dom_crash_sync_extable) - _ASM_EXTABLE(.Lft6, dom_crash_sync_extable) - _ASM_EXTABLE(.Lft7, dom_crash_sync_extable) - _ASM_EXTABLE(.Lft8, dom_crash_sync_extable) - _ASM_EXTABLE(.Lft9, dom_crash_sync_extable) - _ASM_EXTABLE(.Lft10, dom_crash_sync_extable) - _ASM_EXTABLE(.Lft11, dom_crash_sync_extable) - _ASM_EXTABLE(.Lft12, dom_crash_sync_extable) - _ASM_EXTABLE(.Lft13, dom_crash_sync_extable) + _ASM_EXTABLE(.Lft2, domain_crash_page_fault_32) + _ASM_EXTABLE(.Lft3, domain_crash_page_fault_24) + _ASM_EXTABLE(.Lft4, domain_crash_page_fault_8) + _ASM_EXTABLE(.Lft5, domain_crash_page_fault_16) + _ASM_EXTABLE(.Lft6, domain_crash_page_fault) + _ASM_EXTABLE(.Lft7, domain_crash_page_fault) + _ASM_EXTABLE(.Lft8, domain_crash_page_fault_24) + _ASM_EXTABLE(.Lft9, domain_crash_page_fault_16) + _ASM_EXTABLE(.Lft10, domain_crash_page_fault_8) + _ASM_EXTABLE(.Lft11, domain_crash_page_fault) + _ASM_EXTABLE(.Lft12, domain_crash_page_fault_8) + _ASM_EXTABLE(.Lft13, domain_crash_page_fault) +domain_crash_page_fault_32: + addq $8,%rsi +domain_crash_page_fault_24: + addq $8,%rsi +domain_crash_page_fault_16: + addq $8,%rsi +domain_crash_page_fault_8: + addq $8,%rsi +domain_crash_page_fault: + movq %rsi,%rdi + call show_page_walk ENTRY(dom_crash_sync_extable) # Get out of the guest-save area of the stack. GET_STACK_BASE(%rax) From 72af6f455ac6afcd46d9a556f90349f2397507e8 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 16 Sep 2014 13:58:20 +0200 Subject: [PATCH 3/3] VMX: don't unintentionally leave x2APIC MSR intercepts disabled These should be re-enabled in particular when the virtualized APIC transitions to HW-disabled state. Signed-off-by: Jan Beulich Acked-by: Kevin Tian --- xen/arch/x86/hvm/vmx/vmx.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 26b1ad59f6..d3e7ac91c7 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -2167,6 +2167,7 @@ void vmx_vlapic_msr_changed(struct vcpu *v) { int virtualize_x2apic_mode; struct vlapic *vlapic = vcpu_vlapic(v); + unsigned int msr; virtualize_x2apic_mode = ( (cpu_has_vmx_apic_reg_virt || cpu_has_vmx_virtual_intr_delivery) && @@ -2183,8 +2184,6 @@ void vmx_vlapic_msr_changed(struct vcpu *v) if ( !vlapic_hw_disabled(vlapic) && (vlapic_base_address(vlapic) == APIC_DEFAULT_PHYS_BASE) ) { - unsigned int msr; - if ( virtualize_x2apic_mode && vlapic_x2apic_mode(vlapic) ) { v->arch.hvm_vmx.secondary_exec_control |= @@ -2213,15 +2212,15 @@ void vmx_vlapic_msr_changed(struct vcpu *v) } } else - { v->arch.hvm_vmx.secondary_exec_control |= SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; - for ( msr = MSR_IA32_APICBASE_MSR; - msr <= MSR_IA32_APICBASE_MSR + 0xff; msr++ ) - vmx_enable_intercept_for_msr(v, msr, - MSR_TYPE_R | MSR_TYPE_W); - } } + if ( !(v->arch.hvm_vmx.secondary_exec_control & + SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE) ) + for ( msr = MSR_IA32_APICBASE_MSR; + msr <= MSR_IA32_APICBASE_MSR + 0xff; msr++ ) + vmx_enable_intercept_for_msr(v, msr, MSR_TYPE_R | MSR_TYPE_W); + vmx_update_secondary_exec_control(v); vmx_vmcs_exit(v); }