[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH 21/23] X86/vmsi: Hook guest MSI injection
From: Chao Gao <chao.gao@xxxxxxxxx> In two situations, hypervisor injects a msi to a hvm guest. One is when qemu sends a request to hypervisor through XEN_DMOP_inject_msi. The other is when a physical interrupt arrives and it has been binded to a msi interrupt of guest. The binding relationship is setup and updated by qemu. When interrupt remapping enabled, the binding implementation needs to be extended because some useful fields which are useless if interrupt remapping is disabled are discarded in the process. So, we add a new type guest interrupt struct hvm_gmsi_ir_info and a new type flag HVM_IRQ_DPCI_GUEST_MSI_IR which means the binding relationship is between physical interrupts and guest remappable msi. Signed-off-by: Chao Gao <chao.gao@xxxxxxxxx> Signed-off-by: Lan Tianyu <tianyu.lan@xxxxxxxxx> --- xen/arch/x86/hvm/irq.c | 10 +++++++++ xen/arch/x86/hvm/vmsi.c | 13 ++++++++++-- xen/drivers/passthrough/io.c | 50 ++++++++++++++++++++++++++++++++------------ xen/include/asm-x86/msi.h | 3 +++ 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c index ff7d288..c3d2fba 100644 --- a/xen/arch/x86/hvm/irq.c +++ b/xen/arch/x86/hvm/irq.c @@ -26,6 +26,7 @@ #include <asm/hvm/domain.h> #include <asm/hvm/support.h> #include <asm/msi.h> +#include <asm/viommu.h> /* Must be called with hvm_domain->irq_lock hold */ static void assert_gsi(struct domain *d, unsigned ioapic_gsi) @@ -288,6 +289,15 @@ int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data) >> MSI_DATA_TRIGGER_SHIFT; uint8_t vector = data & MSI_DATA_VECTOR_MASK; + if ( addr & MSI_ADDR_INTEFORMAT_MASK ) + { + struct irq_remapping_request request; + + irq_request_msi_fill(&request, 0, addr, data); + viommu_handle_irq_request(d, &request); + return 0; + } + if ( !vector ) { int pirq = ((addr >> 32) & 0xffffff00) | dest; diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c index d126498..53af07f 100644 --- a/xen/arch/x86/hvm/vmsi.c +++ b/xen/arch/x86/hvm/vmsi.c @@ -114,9 +114,18 @@ void vmsi_deliver_pirq(struct domain *d, const struct hvm_pirq_dpci *pirq_dpci) "vector=%x trig_mode=%x\n", dest, dest_mode, delivery_mode, vector, trig_mode); - ASSERT(pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI); + ASSERT(pirq_dpci->flags & (HVM_IRQ_DPCI_GUEST_MSI | HVM_IRQ_DPCI_GUEST_MSI_IR)); + if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI_IR ) + { + struct irq_remapping_request request; - vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode); + irq_request_msi_fill(&request, pirq_dpci->gmsi.intremap.source_id, + pirq_dpci->gmsi.intremap.addr, + pirq_dpci->gmsi.intremap.data); + viommu_handle_irq_request(d, &request); + } + else + vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode); } /* Return value, -1 : multi-dests, non-negative value: dest_vcpu_id */ diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c index 4557670..426f56d 100644 --- a/xen/drivers/passthrough/io.c +++ b/xen/drivers/passthrough/io.c @@ -139,7 +139,9 @@ static void pt_pirq_softirq_reset(struct hvm_pirq_dpci *pirq_dpci) bool_t pt_irq_need_timer(uint32_t flags) { - return !(flags & (HVM_IRQ_DPCI_GUEST_MSI | HVM_IRQ_DPCI_TRANSLATE)); + return !(flags & (HVM_IRQ_DPCI_GUEST_MSI_IR | + HVM_IRQ_DPCI_GUEST_MSI | + HVM_IRQ_DPCI_TRANSLATE)); } static int pt_irq_guest_eoi(struct domain *d, struct hvm_pirq_dpci *pirq_dpci, @@ -693,7 +695,8 @@ int pt_irq_destroy_bind( pirq = pirq_info(d, machine_gsi); pirq_dpci = pirq_dpci(pirq); - if ( pt_irq_bind->irq_type != PT_IRQ_TYPE_MSI ) + if ( (pt_irq_bind->irq_type != PT_IRQ_TYPE_MSI_IR) && + (pt_irq_bind->irq_type != PT_IRQ_TYPE_MSI) ) { unsigned int bus = pt_irq_bind->u.pci.bus; unsigned int device = pt_irq_bind->u.pci.device; @@ -856,20 +859,39 @@ static int _hvm_dpci_msi_eoi(struct domain *d, { int vector = (long)arg; - if ( (pirq_dpci->flags & HVM_IRQ_DPCI_MACH_MSI) && - (pirq_dpci->gmsi.legacy.gvec == vector) ) + if ( pirq_dpci->flags & HVM_IRQ_DPCI_MACH_MSI ) { - int dest = pirq_dpci->gmsi.legacy.gflags & VMSI_DEST_ID_MASK; - int dest_mode = !!(pirq_dpci->gmsi.legacy.gflags & VMSI_DM_MASK); + if ( (pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI) && + (pirq_dpci->gmsi.legacy.gvec == vector) ) + { + int dest = pirq_dpci->gmsi.legacy.gflags & VMSI_DEST_ID_MASK; + int dest_mode = !!(pirq_dpci->gmsi.legacy.gflags & VMSI_DM_MASK); - if ( vlapic_match_dest(vcpu_vlapic(current), NULL, 0, dest, - dest_mode) ) + if ( vlapic_match_dest(vcpu_vlapic(current), NULL, 0, dest, + dest_mode) ) + { + __msi_pirq_eoi(pirq_dpci); + return 1; + } + } + else if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI_IR ) { - __msi_pirq_eoi(pirq_dpci); - return 1; + int ret; + struct irq_remapping_request request; + struct irq_remapping_info irq_info; + + irq_request_msi_fill(&request, pirq_dpci->gmsi.intremap.source_id, + pirq_dpci->gmsi.intremap.addr, + pirq_dpci->gmsi.intremap.data); + ret = viommu_get_irq_info(d, &request, &irq_info); + if ( (!ret) && (irq_info.vector == vector) && vlapic_match_dest( + vcpu_vlapic(current),NULL, 0, irq_info.dest, irq_info.dest_mode) ) + { + __msi_pirq_eoi(pirq_dpci); + return 1; + } } } - return 0; } @@ -901,14 +923,16 @@ static void hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci) { send_guest_pirq(d, pirq); - if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI ) + if ( pirq_dpci->flags + & (HVM_IRQ_DPCI_GUEST_MSI | HVM_IRQ_DPCI_GUEST_MSI_IR) ) { spin_unlock(&d->event_lock); return; } } - if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI ) + if ( pirq_dpci->flags + & (HVM_IRQ_DPCI_GUEST_MSI | HVM_IRQ_DPCI_GUEST_MSI_IR) ) { vmsi_deliver_pirq(d, pirq_dpci); spin_unlock(&d->event_lock); diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h index 9c02945..2e76f6a 100644 --- a/xen/include/asm-x86/msi.h +++ b/xen/include/asm-x86/msi.h @@ -48,6 +48,9 @@ #define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) #define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) +#define MSI_ADDR_INTEFORMAT_SHIFT 4 +#define MSI_ADDR_INTEFORMAT_MASK (1 << MSI_ADDR_INTEFORMAT_SHIFT) + #define MSI_ADDR_DEST_ID_SHIFT 12 #define MSI_ADDR_DEST_ID_MASK 0x00ff000 #define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & MSI_ADDR_DEST_ID_MASK) -- 1.8.3.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |