Stefano Stabellini
2010-Oct-12 16:34 UTC
[Xen-devel] [PATCH v4 0/7] PV on HVM: receive interrupts as xen events
Hi all, this patch series introduces some performance improvements for xen PV on HVM guests: interacting with the emulated APIC is slow because it causes traps in the hypervisor while receiving xen events using the vector callback mechanism allow us to skip all that. For this reason we remap interrupts and MSIs into xen pirqs so that from that point on we can receive them as xen events instead. This series is based on Konrad''s pcifront series: http://lkml.org/lkml/2010/10/12/207 and requires a patch to xen and a patch to qemu-xen (both sent to the list). New changes in v4: - xen_hvm_register_pirq has been made static; - the functions in arch/x86/pci/xen.c that depends on CONFIG_ACPI have been ifdef''ed. The list of patches with diffstat follows: Jeremy Fitzhardinge (2): acpi: use indirect call to register gsi in different modes xen: add xen hvm acpi_register_gsi variant Stefano Stabellini (5): xen: support pirq != irq xen: get the maximum number of pirqs from xen xen: implement xen_hvm_register_pirq xen: support GSI -> pirq remapping in PV on HVM guests xen: map MSIs into pirqs arch/x86/include/asm/acpi.h | 3 + arch/x86/include/asm/xen/pci.h | 5 ++ arch/x86/kernel/acpi/boot.c | 60 ++++++++++++++----- arch/x86/pci/xen.c | 117 +++++++++++++++++++++++++++++++++++++ drivers/xen/events.c | 120 ++++++++++++++++++++++++++++++++------ include/xen/events.h | 3 + include/xen/interface/features.h | 3 + include/xen/interface/physdev.h | 36 +++++++++++ 8 files changed, 311 insertions(+), 36 deletions(-) A git tree with this series and Konrad''s pcifront series on top of Linux 2.6.36-rc6 is available here: git://xenbits.xen.org/people/sstabellini/linux-pvhvm.git 2.6.36-rc6-pvhvm-pirq-v4 Cheers, Stefano Stabellini _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
stefano.stabellini@eu.citrix.com
2010-Oct-12 16:34 UTC
[Xen-devel] [PATCH v4 1/7] xen: support pirq != irq
From: Stefano Stabellini <stefano.stabellini@eu.citrix.com> PHYSDEVOP_map_pirq might return a pirq different from what we asked if we are running as an HVM guest, so we need to be able to support pirqs that are different from linux irqs. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- drivers/xen/events.c | 64 +++++++++++++++++++++++++++++++++++++------------ include/xen/events.h | 1 + 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index adad3a9..943f140 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -90,6 +90,7 @@ struct irq_info unsigned short virq; enum ipi_vector ipi; struct { + unsigned short pirq; unsigned short gsi; unsigned char vector; unsigned char flags; @@ -100,6 +101,7 @@ struct irq_info #define PIRQ_SHAREABLE (1 << 1) static struct irq_info *irq_info; +static int *pirq_to_irq; static int *evtchn_to_irq; struct cpu_evtchn_s { @@ -147,11 +149,12 @@ static struct irq_info mk_virq_info(unsigned short evtchn, unsigned short virq) .cpu = 0, .u.virq = virq }; } -static struct irq_info mk_pirq_info(unsigned short evtchn, +static struct irq_info mk_pirq_info(unsigned short evtchn, unsigned short pirq, unsigned short gsi, unsigned short vector) { return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn, - .cpu = 0, .u.pirq = { .gsi = gsi, .vector = vector } }; + .cpu = 0, + .u.pirq = { .pirq = pirq, .gsi = gsi, .vector = vector } }; } /* @@ -193,6 +196,16 @@ static unsigned virq_from_irq(unsigned irq) return info->u.virq; } +static unsigned pirq_from_irq(unsigned irq) +{ + struct irq_info *info = info_for_irq(irq); + + BUG_ON(info == NULL); + BUG_ON(info->type != IRQT_PIRQ); + + return info->u.pirq.pirq; +} + static unsigned gsi_from_irq(unsigned irq) { struct irq_info *info = info_for_irq(irq); @@ -365,6 +378,16 @@ static int get_nr_hw_irqs(void) return ret; } +static int find_unbound_pirq(void) +{ + int i; + for (i = 0; i < nr_irqs; i++) { + if (pirq_to_irq[i] < 0) + return i; + } + return -1; +} + static int find_unbound_irq(void) { int irq; @@ -411,7 +434,7 @@ static bool identity_mapped_irq(unsigned irq) static void pirq_unmask_notify(int irq) { - struct physdev_eoi eoi = { .irq = irq }; + struct physdev_eoi eoi = { .irq = pirq_from_irq(irq) }; if (unlikely(pirq_needs_eoi(irq))) { int rc = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi); @@ -426,7 +449,7 @@ static void pirq_query_unmask(int irq) BUG_ON(info->type != IRQT_PIRQ); - irq_status.irq = irq; + irq_status.irq = pirq_from_irq(irq); if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status)) irq_status.flags = 0; @@ -454,7 +477,7 @@ static unsigned int startup_pirq(unsigned int irq) if (VALID_EVTCHN(evtchn)) goto out; - bind_pirq.pirq = irq; + bind_pirq.pirq = pirq_from_irq(irq); /* NB. We are happy to share unless we are probing. */ bind_pirq.flags = info->u.pirq.flags & PIRQ_SHAREABLE ? BIND_PIRQ__WILL_SHARE : 0; @@ -557,28 +580,32 @@ static int find_irq_by_gsi(unsigned gsi) return -1; } -/* xen_allocate_irq might allocate irqs from the top down, as a +int xen_allocate_pirq(unsigned gsi, int shareable, char *name) +{ + return xen_map_pirq_gsi(gsi, gsi, shareable, name); +} + +/* xen_map_pirq_gsi might allocate irqs from the top down, as a * consequence don''t assume that the irq number returned has a low value * or can be used as a pirq number unless you know otherwise. * - * One notable exception is when xen_allocate_irq is called passing an + * One notable exception is when xen_map_pirq_gsi is called passing an * hardware gsi as argument, in that case the irq number returned - * matches the gsi number passed as first argument. - - * Note: We don''t assign an - * event channel until the irq actually started up. Return an - * existing irq if we''ve already got one for the gsi. + * matches the gsi number passed as second argument. + * + * Note: We don''t assign an event channel until the irq actually started + * up. Return an existing irq if we''ve already got one for the gsi. */ -int xen_allocate_pirq(unsigned gsi, int shareable, char *name) +int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name) { - int irq; + int irq = 0; struct physdev_irq irq_op; spin_lock(&irq_mapping_update_lock); irq = find_irq_by_gsi(gsi); if (irq != -1) { - printk(KERN_INFO "xen_allocate_pirq: returning irq %d for gsi %u\n", + printk(KERN_INFO "xen_map_pirq_gsi: returning irq %d for gsi %u\n", irq, gsi); goto out; /* XXX need refcount? */ } @@ -608,8 +635,9 @@ int xen_allocate_pirq(unsigned gsi, int shareable, char *name) goto out; } - irq_info[irq] = mk_pirq_info(0, gsi, irq_op.vector); + irq_info[irq] = mk_pirq_info(0, pirq, gsi, irq_op.vector); irq_info[irq].u.pirq.flags |= shareable ? PIRQ_SHAREABLE : 0; + pirq_to_irq[pirq] = irq; out: spin_unlock(&irq_mapping_update_lock); @@ -1329,6 +1357,10 @@ void __init xen_init_IRQ(void) GFP_KERNEL); irq_info = kcalloc(nr_irqs, sizeof(*irq_info), GFP_KERNEL); + pirq_to_irq = kcalloc(nr_irqs, sizeof(*pirq_to_irq), GFP_KERNEL); + for (i = 0; i < nr_irqs; i++) + pirq_to_irq[i] = -1; + evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq), GFP_KERNEL); for (i = 0; i < NR_EVENT_CHANNELS; i++) diff --git a/include/xen/events.h b/include/xen/events.h index c1717ca..deec8fa 100644 --- a/include/xen/events.h +++ b/include/xen/events.h @@ -71,6 +71,7 @@ void xen_hvm_evtchn_do_upcall(void); * GSIs are identity mapped; others are dynamically allocated as * usual. */ int xen_allocate_pirq(unsigned gsi, int shareable, char *name); +int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name); /* De-allocates the above mentioned physical interrupt. */ int xen_destroy_irq(int irq); -- 1.5.6.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
stefano.stabellini@eu.citrix.com
2010-Oct-12 16:34 UTC
[Xen-devel] [PATCH v4 2/7] xen: get the maximum number of pirqs from xen
From: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Use PHYSDEVOP_get_nr_pirqs to get the maximum number of pirqs from xen. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- drivers/xen/events.c | 30 ++++++++++++++++++++++++++---- include/xen/interface/physdev.h | 6 ++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 943f140..c77a44b 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -102,6 +102,7 @@ struct irq_info static struct irq_info *irq_info; static int *pirq_to_irq; +static int nr_pirqs; static int *evtchn_to_irq; struct cpu_evtchn_s { @@ -378,10 +379,12 @@ static int get_nr_hw_irqs(void) return ret; } +/* callers of this function should make sure that PHYSDEVOP_get_nr_pirqs + * succeeded otherwise nr_pirqs won''t hold the right value */ static int find_unbound_pirq(void) { int i; - for (i = 0; i < nr_irqs; i++) { + for (i = nr_pirqs-1; i >= 0; i--) { if (pirq_to_irq[i] < 0) return i; } @@ -603,6 +606,13 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name) spin_lock(&irq_mapping_update_lock); + if ((pirq > nr_pirqs) || (gsi > nr_irqs)) { + printk(KERN_WARNING "xen_map_pirq_gsi: %s %s is incorrect!\n", + pirq > nr_pirqs ? "nr_pirqs" :"", + gsi > nr_irqs ? "nr_irqs" : ""); + goto out; + } + irq = find_irq_by_gsi(gsi); if (irq != -1) { printk(KERN_INFO "xen_map_pirq_gsi: returning irq %d for gsi %u\n", @@ -1351,14 +1361,26 @@ void xen_callback_vector(void) {} void __init xen_init_IRQ(void) { - int i; + int i, rc; + struct physdev_nr_pirqs op_nr_pirqs; cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s), GFP_KERNEL); irq_info = kcalloc(nr_irqs, sizeof(*irq_info), GFP_KERNEL); - pirq_to_irq = kcalloc(nr_irqs, sizeof(*pirq_to_irq), GFP_KERNEL); - for (i = 0; i < nr_irqs; i++) + rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_nr_pirqs, &op_nr_pirqs); + if (rc < 0) { + nr_pirqs = nr_irqs; + if (rc != -ENOSYS) + printk(KERN_WARNING "PHYSDEVOP_get_nr_pirqs returned rc=%d\n", rc); + } else { + if (xen_pv_domain() && !xen_initial_domain()) + nr_pirqs = max((int)op_nr_pirqs.nr_pirqs, nr_irqs); + else + nr_pirqs = op_nr_pirqs.nr_pirqs; + } + pirq_to_irq = kcalloc(nr_pirqs, sizeof(*pirq_to_irq), GFP_KERNEL); + for (i = 0; i < nr_pirqs; i++) pirq_to_irq[i] = -1; evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq), diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index cd69391..fbb5883 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h @@ -121,6 +121,12 @@ struct physdev_op { } u; }; +#define PHYSDEVOP_get_nr_pirqs 22 +struct physdev_nr_pirqs { + /* OUT */ + uint32_t nr_pirqs; +}; + /* * Notify that some PIRQ-bound event channels have been unmasked. * ** This command is obsolete since interface version 0x00030202 and is ** -- 1.5.6.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
stefano.stabellini@eu.citrix.com
2010-Oct-12 16:34 UTC
[Xen-devel] [PATCH v4 3/7] xen: implement xen_hvm_register_pirq
From: Stefano Stabellini <stefano.stabellini@eu.citrix.com> xen_hvm_register_pirq allows the kernel to map a GSI into a Xen pirq and receive the interrupt as an event channel from that point on. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- arch/x86/pci/xen.c | 38 ++++++++++++++++++++++++++++++++++++++ drivers/xen/events.c | 4 +++- include/xen/interface/physdev.h | 30 ++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletions(-) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index b19c873..e7f897b 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -17,6 +17,44 @@ #include <xen/events.h> #include <asm/xen/pci.h> +#ifdef CONFIG_ACPI +static int xen_hvm_register_pirq(u32 gsi, int triggering) +{ + int rc, irq; + struct physdev_map_pirq map_irq; + int shareable = 0; + char *name; + + if (!xen_hvm_domain()) + return -1; + + map_irq.domid = DOMID_SELF; + map_irq.type = MAP_PIRQ_TYPE_GSI; + map_irq.index = gsi; + map_irq.pirq = -1; + + rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); + if (rc) { + printk(KERN_WARNING "xen map irq failed %d\n", rc); + return -1; + } + + if (triggering == ACPI_EDGE_SENSITIVE) { + shareable = 0; + name = "ioapic-edge"; + } else { + shareable = 1; + name = "ioapic-level"; + } + + irq = xen_map_pirq_gsi(map_irq.pirq, gsi, shareable, name); + + printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq); + + return irq; +} +#endif + #if defined(CONFIG_PCI_MSI) #include <linux/msi.h> diff --git a/drivers/xen/events.c b/drivers/xen/events.c index c77a44b..4fed942 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -36,6 +36,7 @@ #include <asm/idle.h> #include <asm/io_apic.h> #include <asm/sync_bitops.h> +#include <asm/xen/pci.h> #include <asm/xen/hypercall.h> #include <asm/xen/hypervisor.h> @@ -75,7 +76,8 @@ enum xen_irq_type { * event channel - irq->event channel mapping * cpu - cpu this event channel is bound to * index - type-specific information: - * PIRQ - vector, with MSB being "needs EIO" + * PIRQ - vector, with MSB being "needs EIO", or physical IRQ of the HVM + * guest, or GSI (real passthrough IRQ) of the device. * VIRQ - virq number * IPI - IPI vector * EVTCHN - diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index fbb5883..69a72b9 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h @@ -106,6 +106,36 @@ struct physdev_irq { uint32_t vector; }; +#define MAP_PIRQ_TYPE_MSI 0x0 +#define MAP_PIRQ_TYPE_GSI 0x1 +#define MAP_PIRQ_TYPE_UNKNOWN 0x2 + +#define PHYSDEVOP_map_pirq 13 +struct physdev_map_pirq { + domid_t domid; + /* IN */ + int type; + /* IN */ + int index; + /* IN or OUT */ + int pirq; + /* IN */ + int bus; + /* IN */ + int devfn; + /* IN */ + int entry_nr; + /* IN */ + uint64_t table_base; +}; + +#define PHYSDEVOP_unmap_pirq 14 +struct physdev_unmap_pirq { + domid_t domid; + /* IN */ + int pirq; +}; + /* * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op() * hypercall since 0x00030202. -- 1.5.6.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
stefano.stabellini@eu.citrix.com
2010-Oct-12 16:34 UTC
[Xen-devel] [PATCH v4 4/7] acpi: use indirect call to register gsi in different modes
From: Jeremy Fitzhardinge <jeremy@goop.org> Rather than using a tree of conditionals, use function pointer for acpi_register_gsi. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- arch/x86/kernel/acpi/boot.c | 59 ++++++++++++++++++++++++++++++------------ 1 files changed, 42 insertions(+), 17 deletions(-) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index c05872a..031f0c2 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -513,35 +513,61 @@ int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi) return 0; } -/* - * success: return IRQ number (>=0) - * failure: return < 0 - */ -int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) +static int acpi_register_gsi_pic(struct device *dev, u32 gsi, + int trigger, int polarity) { - unsigned int irq; - unsigned int plat_gsi = gsi; - #ifdef CONFIG_PCI /* * Make sure all (legacy) PCI IRQs are set as level-triggered. */ - if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { - if (trigger == ACPI_LEVEL_SENSITIVE) - eisa_set_level_irq(gsi); - } + if (trigger == ACPI_LEVEL_SENSITIVE) + eisa_set_level_irq(gsi); #endif + return gsi; +} + +static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi, + int trigger, int polarity) +{ #ifdef CONFIG_X86_IO_APIC - if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { - plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); - } + gsi = mp_register_gsi(dev, gsi, trigger, polarity); #endif + + return gsi; +} + +static int (*__acpi_register_gsi)(struct device *dev, u32 gsi, int trigger, int polarity) = acpi_register_gsi_pic; + +/* + * success: return IRQ number (>=0) + * failure: return < 0 + */ +int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) +{ + unsigned int irq; + unsigned int plat_gsi = gsi; + + plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity); irq = gsi_to_irq(plat_gsi); return irq; } +void __init acpi_set_irq_model_pic(void) +{ + acpi_irq_model = ACPI_IRQ_MODEL_PIC; + __acpi_register_gsi = acpi_register_gsi_pic; + acpi_ioapic = 0; +} + +void __init acpi_set_irq_model_ioapic(void) +{ + acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; + __acpi_register_gsi = acpi_register_gsi_ioapic; + acpi_ioapic = 1; +} + /* * ACPI based hotplug support for CPU */ @@ -1259,8 +1285,7 @@ static void __init acpi_process_madt(void) */ error = acpi_parse_madt_ioapic_entries(); if (!error) { - acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; - acpi_ioapic = 1; + acpi_set_irq_model_ioapic(); smp_found_config = 1; } -- 1.5.6.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
stefano.stabellini@eu.citrix.com
2010-Oct-12 16:34 UTC
[Xen-devel] [PATCH v4 5/7] xen: add xen hvm acpi_register_gsi variant
From: Jeremy Fitzhardinge <jeremy@goop.org> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- arch/x86/include/asm/acpi.h | 3 +++ arch/x86/kernel/acpi/boot.c | 3 ++- arch/x86/pci/xen.c | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletions(-) diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 92091de..55d106b 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -93,6 +93,9 @@ extern u8 acpi_sci_flags; extern int acpi_sci_override_gsi; void acpi_pic_sci_set_trigger(unsigned int, u16); +extern int (*__acpi_register_gsi)(struct device *dev, u32 gsi, + int trigger, int polarity); + static inline void disable_acpi(void) { acpi_disabled = 1; diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 031f0c2..71232b9 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -537,7 +537,8 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi, return gsi; } -static int (*__acpi_register_gsi)(struct device *dev, u32 gsi, int trigger, int polarity) = acpi_register_gsi_pic; +int (*__acpi_register_gsi)(struct device *dev, u32 gsi, + int trigger, int polarity) = acpi_register_gsi_pic; /* * success: return IRQ number (>=0) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index e7f897b..ef9b8b2 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -53,6 +53,12 @@ static int xen_hvm_register_pirq(u32 gsi, int triggering) return irq; } + +static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, + int trigger, int polarity) +{ + return xen_hvm_register_pirq(gsi, trigger); +} #endif #if defined(CONFIG_PCI_MSI) -- 1.5.6.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
stefano.stabellini@eu.citrix.com
2010-Oct-12 16:34 UTC
[Xen-devel] [PATCH v4 6/7] xen: support GSI -> pirq remapping in PV on HVM guests
From: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Disable pcifront when running on HVM: it is meant to be used with pv guests that don''t have PCI bus. Use acpi_register_gsi_xen_hvm to remap GSIs into pirqs. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- arch/x86/include/asm/xen/pci.h | 5 +++++ arch/x86/pci/xen.c | 16 ++++++++++++++++ drivers/xen/events.c | 6 +++++- include/xen/interface/features.h | 3 +++ 4 files changed, 29 insertions(+), 1 deletions(-) diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h index 449c82f..f89a42a 100644 --- a/arch/x86/include/asm/xen/pci.h +++ b/arch/x86/include/asm/xen/pci.h @@ -3,10 +3,15 @@ #if defined(CONFIG_PCI_XEN) extern int __init pci_xen_init(void); +extern int __init pci_xen_hvm_init(void); #define pci_xen 1 #else #define pci_xen 0 #define pci_xen_init (0) +static inline int pci_xen_hvm_init(void) +{ + return -1; +} #endif #if defined(CONFIG_PCI_MSI) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index ef9b8b2..90a8f83 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -14,6 +14,7 @@ #include <asm/xen/hypervisor.h> +#include <xen/features.h> #include <xen/events.h> #include <asm/xen/pci.h> @@ -189,3 +190,18 @@ int __init pci_xen_init(void) #endif return 0; } + +int __init pci_xen_hvm_init(void) +{ + if (!xen_feature(XENFEAT_hvm_pirqs)) + return 0; + +#ifdef CONFIG_ACPI + /* + * We don''t want to change the actual ACPI delivery model, + * just how GSIs get registered. + */ + __acpi_register_gsi = acpi_register_gsi_xen_hvm; +#endif + return 0; +} diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 4fed942..5e4fe09 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -624,7 +624,8 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name) /* If we are a PV guest, we don''t have GSIs (no ACPI passed). Therefore * we are using the !xen_initial_domain() to drop in the function.*/ - if (identity_mapped_irq(gsi) || !xen_initial_domain()) { + if (identity_mapped_irq(gsi) || (!xen_initial_domain() && + xen_pv_domain())) { irq = gsi; irq_to_desc_alloc_node(irq, 0); dynamic_irq_init(irq); @@ -1399,6 +1400,9 @@ void __init xen_init_IRQ(void) if (xen_hvm_domain()) { xen_callback_vector(); native_init_IRQ(); + /* pci_xen_hvm_init must be called after native_init_IRQ so that + * __acpi_register_gsi can point at the right function */ + pci_xen_hvm_init(); } else { irq_ctx_init(smp_processor_id()); } diff --git a/include/xen/interface/features.h b/include/xen/interface/features.h index 70d2563..b6ca39a 100644 --- a/include/xen/interface/features.h +++ b/include/xen/interface/features.h @@ -47,6 +47,9 @@ /* x86: pvclock algorithm is safe to use on HVM */ #define XENFEAT_hvm_safe_pvclock 9 +/* x86: pirq can be used by HVM guests */ +#define XENFEAT_hvm_pirqs 10 + #define XENFEAT_NR_SUBMAPS 1 #endif /* __XEN_PUBLIC_FEATURES_H__ */ -- 1.5.6.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
stefano.stabellini@eu.citrix.com
2010-Oct-12 16:34 UTC
[Xen-devel] [PATCH v4 7/7] xen: map MSIs into pirqs
From: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Map MSIs into pirqs, writing 0 in the MSI vector data field and the pirq number in the MSI destination id field. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- arch/x86/pci/xen.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/xen/events.c | 22 +++++++++++++++++++ include/xen/events.h | 2 + 3 files changed, 81 insertions(+), 0 deletions(-) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 90a8f83..fb20d05 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -64,10 +64,62 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, #if defined(CONFIG_PCI_MSI) #include <linux/msi.h> +#include <asm/msidef.h> struct xen_pci_frontend_ops *xen_pci_frontend; EXPORT_SYMBOL_GPL(xen_pci_frontend); +static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq, + struct msi_msg *msg) +{ + /* We set vector == 0 to tell the hypervisor we don''t care about it, + * but we want a pirq setup instead. + * We use the dest_id field to pass the pirq that we want. */ + msg->address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(pirq); + msg->address_lo + MSI_ADDR_BASE_LO | + MSI_ADDR_DEST_MODE_PHYSICAL | + MSI_ADDR_REDIRECTION_CPU | + MSI_ADDR_DEST_ID(pirq); + + msg->data + MSI_DATA_TRIGGER_EDGE | + MSI_DATA_LEVEL_ASSERT | + /* delivery mode reserved */ + (3 << 8) | + MSI_DATA_VECTOR(0); +} + +static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +{ + int irq, pirq, ret = 0; + struct msi_desc *msidesc; + struct msi_msg msg; + + list_for_each_entry(msidesc, &dev->msi_list, list) { + xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? + "msi-x" : "msi", &irq, &pirq); + if (irq < 0 || pirq < 0) + goto error; + printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq); + xen_msi_compose_msg(dev, pirq, &msg); + ret = set_irq_msi(irq, msidesc); + if (ret < 0) + goto error_while; + write_msi_msg(irq, &msg); + } + return 0; + +error_while: + unbind_from_irqhandler(irq, NULL); +error: + if (ret == -ENODEV) + dev_err(&dev->dev, "Xen PCI frontend has not registered" \ + " MSI/MSI-X support!\n"); + + return ret; +} + /* * For MSI interrupts we have to use drivers/xen/event.s functions to * allocate an irq_desc and setup the right */ @@ -203,5 +255,10 @@ int __init pci_xen_hvm_init(void) */ __acpi_register_gsi = acpi_register_gsi_xen_hvm; #endif + +#ifdef CONFIG_PCI_MSI + x86_msi.setup_msi_irqs = xen_hvm_setup_msi_irqs; + x86_msi.teardown_msi_irq = xen_teardown_msi_irq; +#endif return 0; } diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 5e4fe09..2edbf7c 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -658,6 +658,28 @@ out: return irq; } +void xen_allocate_pirq_msi(char *name, int *irq, int *pirq) +{ + spin_lock(&irq_mapping_update_lock); + + *irq = find_unbound_irq(); + if (*irq == -1) + goto out; + + *pirq = find_unbound_pirq(); + if (*pirq == -1) + goto out; + + set_irq_chip_and_handler_name(*irq, &xen_pirq_chip, + handle_level_irq, name); + + irq_info[*irq] = mk_pirq_info(0, *pirq, 0, 0); + pirq_to_irq[*pirq] = *irq; + +out: + spin_unlock(&irq_mapping_update_lock); +} + int xen_destroy_irq(int irq) { struct irq_desc *desc; diff --git a/include/xen/events.h b/include/xen/events.h index deec8fa..0c58db6 100644 --- a/include/xen/events.h +++ b/include/xen/events.h @@ -72,6 +72,8 @@ void xen_hvm_evtchn_do_upcall(void); * usual. */ int xen_allocate_pirq(unsigned gsi, int shareable, char *name); int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name); +/* Allocate an irq and a pirq to be used with MSIs. */ +void xen_allocate_pirq_msi(char *name, int *irq, int *pirq); /* De-allocates the above mentioned physical interrupt. */ int xen_destroy_irq(int irq); -- 1.5.6.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Konrad Rzeszutek Wilk
2010-Oct-12 16:52 UTC
[Xen-devel] Re: [PATCH v4 5/7] xen: add xen hvm acpi_register_gsi variant
Hey Len, Pavel, Rafael, Stefano forgot to put you guys as CC. Is this patch OK with you guys? The full link for the patchset is: http://lkml.org/lkml/2010/10/12/246 On Tue, Oct 12, 2010 at 05:34:47PM +0100, stefano.stabellini@eu.citrix.com wrote:> From: Jeremy Fitzhardinge <jeremy@goop.org> > > Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> > --- > arch/x86/include/asm/acpi.h | 3 +++ > arch/x86/kernel/acpi/boot.c | 3 ++- > arch/x86/pci/xen.c | 6 ++++++ > 3 files changed, 11 insertions(+), 1 deletions(-) > > diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h > index 92091de..55d106b 100644 > --- a/arch/x86/include/asm/acpi.h > +++ b/arch/x86/include/asm/acpi.h > @@ -93,6 +93,9 @@ extern u8 acpi_sci_flags; > extern int acpi_sci_override_gsi; > void acpi_pic_sci_set_trigger(unsigned int, u16); > > +extern int (*__acpi_register_gsi)(struct device *dev, u32 gsi, > + int trigger, int polarity); > + > static inline void disable_acpi(void) > { > acpi_disabled = 1; > diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c > index 031f0c2..71232b9 100644 > --- a/arch/x86/kernel/acpi/boot.c > +++ b/arch/x86/kernel/acpi/boot.c > @@ -537,7 +537,8 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi, > return gsi; > } > > -static int (*__acpi_register_gsi)(struct device *dev, u32 gsi, int trigger, int polarity) = acpi_register_gsi_pic; > +int (*__acpi_register_gsi)(struct device *dev, u32 gsi, > + int trigger, int polarity) = acpi_register_gsi_pic; > > /* > * success: return IRQ number (>=0) > diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c > index e7f897b..ef9b8b2 100644 > --- a/arch/x86/pci/xen.c > +++ b/arch/x86/pci/xen.c > @@ -53,6 +53,12 @@ static int xen_hvm_register_pirq(u32 gsi, int triggering) > > return irq; > } > + > +static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, > + int trigger, int polarity) > +{ > + return xen_hvm_register_pirq(gsi, trigger); > +} > #endif > > #if defined(CONFIG_PCI_MSI) > -- > 1.5.6.5_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Konrad Rzeszutek Wilk
2010-Oct-12 16:53 UTC
[Xen-devel] Re: [PATCH v4 4/7] acpi: use indirect call to register gsi in different modes
Len, Pavel and Rafael: Adding you guys as CC. On Tue, Oct 12, 2010 at 05:34:46PM +0100, stefano.stabellini@eu.citrix.com wrote:> From: Jeremy Fitzhardinge <jeremy@goop.org> > > Rather than using a tree of conditionals, use function pointer > for acpi_register_gsi. > > Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> > Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> > --- > arch/x86/kernel/acpi/boot.c | 59 ++++++++++++++++++++++++++++++------------ > 1 files changed, 42 insertions(+), 17 deletions(-) > > diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c > index c05872a..031f0c2 100644 > --- a/arch/x86/kernel/acpi/boot.c > +++ b/arch/x86/kernel/acpi/boot.c > @@ -513,35 +513,61 @@ int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi) > return 0; > } > > -/* > - * success: return IRQ number (>=0) > - * failure: return < 0 > - */ > -int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) > +static int acpi_register_gsi_pic(struct device *dev, u32 gsi, > + int trigger, int polarity) > { > - unsigned int irq; > - unsigned int plat_gsi = gsi; > - > #ifdef CONFIG_PCI > /* > * Make sure all (legacy) PCI IRQs are set as level-triggered. > */ > - if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { > - if (trigger == ACPI_LEVEL_SENSITIVE) > - eisa_set_level_irq(gsi); > - } > + if (trigger == ACPI_LEVEL_SENSITIVE) > + eisa_set_level_irq(gsi); > #endif > > + return gsi; > +} > + > +static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi, > + int trigger, int polarity) > +{ > #ifdef CONFIG_X86_IO_APIC > - if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { > - plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); > - } > + gsi = mp_register_gsi(dev, gsi, trigger, polarity); > #endif > + > + return gsi; > +} > + > +static int (*__acpi_register_gsi)(struct device *dev, u32 gsi, int trigger, int polarity) = acpi_register_gsi_pic; > + > +/* > + * success: return IRQ number (>=0) > + * failure: return < 0 > + */ > +int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) > +{ > + unsigned int irq; > + unsigned int plat_gsi = gsi; > + > + plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity); > irq = gsi_to_irq(plat_gsi); > > return irq; > } > > +void __init acpi_set_irq_model_pic(void) > +{ > + acpi_irq_model = ACPI_IRQ_MODEL_PIC; > + __acpi_register_gsi = acpi_register_gsi_pic; > + acpi_ioapic = 0; > +} > + > +void __init acpi_set_irq_model_ioapic(void) > +{ > + acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; > + __acpi_register_gsi = acpi_register_gsi_ioapic; > + acpi_ioapic = 1; > +} > + > /* > * ACPI based hotplug support for CPU > */ > @@ -1259,8 +1285,7 @@ static void __init acpi_process_madt(void) > */ > error = acpi_parse_madt_ioapic_entries(); > if (!error) { > - acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; > - acpi_ioapic = 1; > + acpi_set_irq_model_ioapic(); > > smp_found_config = 1; > } > -- > 1.5.6.5_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Stefano Stabellini
2010-Oct-15 14:11 UTC
[Xen-devel] Re: [PATCH v4 4/7] acpi: use indirect call to register gsi in different modes
On Thu, 14 Oct 2010, Rafael J. Wysocki wrote:> On Tuesday, October 12, 2010, stefano.stabellini@eu.citrix.com wrote: > > From: Jeremy Fitzhardinge <jeremy@goop.org> > > > > Rather than using a tree of conditionals, use function pointer > > for acpi_register_gsi. > > > > Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> > > Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> > > Looks good to me. >Thank you very much for taking the time to read these two patches! _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel