From patchwork Mon May 21 13:13:47 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 160357 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 367CCB6FA1 for ; Mon, 21 May 2012 23:14:15 +1000 (EST) Received: from localhost ([::1]:54315 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SWSRB-0004x8-14 for incoming@patchwork.ozlabs.org; Mon, 21 May 2012 09:14:13 -0400 Received: from eggs.gnu.org ([208.118.235.92]:52732) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SWSQy-0004wf-Lf for qemu-devel@nongnu.org; Mon, 21 May 2012 09:14:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SWSQs-0001GB-RL for qemu-devel@nongnu.org; Mon, 21 May 2012 09:14:00 -0400 Received: from thoth.sbs.de ([192.35.17.2]:31110) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SWSQs-0001Ff-Dx for qemu-devel@nongnu.org; Mon, 21 May 2012 09:13:54 -0400 Received: from mail1.siemens.de (localhost [127.0.0.1]) by thoth.sbs.de (8.13.6/8.13.6) with ESMTP id q4LDDpTM009646; Mon, 21 May 2012 15:13:51 +0200 Received: from mchn199C.mchp.siemens.de ([139.22.123.132]) by mail1.siemens.de (8.13.6/8.13.6) with SMTP id q4LDDmj2027959; Mon, 21 May 2012 15:13:49 +0200 Message-ID: <4FBA3F8B.9060103@siemens.com> Date: Mon, 21 May 2012 10:13:47 -0300 From: Jan Kiszka User-Agent: Mozilla/5.0 (X11; U; Linux i686 (x86_64); de; rv:1.8.1.12) Gecko/20080226 SUSE/2.0.0.12-1.1 Thunderbird/2.0.0.12 Mnenhy/0.7.5.666 MIME-Version: 1.0 To: "Michael S. Tsirkin" , qemu-devel X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 192.35.17.2 Cc: Alex Williamson , Marcelo Tosatti , Avi Kivity Subject: [Qemu-devel] [PATCH 1/2] pci: Add pci_device_get_host_irq X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add a PCI IRQ path discovery function that walks from a given device to the host bridge, returning the IRQ number that is reported to the attached interrupt controller. For this purpose, another PCI bridge callback function is introduced: map_host_irq. It is so far only implemented by the PIIX3, other host bridges can be added later on as required. Will be used for KVM PCI device assignment. Signed-off-by: Jan Kiszka Acked-by: Alex Williamson --- hw/alpha_typhoon.c | 2 +- hw/apb_pci.c | 2 +- hw/bonito.c | 2 +- hw/grackle_pci.c | 1 + hw/gt64xxx.c | 2 +- hw/pci.c | 23 ++++++++++++++++++++--- hw/pci.h | 7 +++++-- hw/pci_internals.h | 1 + hw/piix_pci.c | 15 ++++++++++++--- hw/ppc4xx_pci.c | 2 +- hw/ppce500_pci.c | 2 +- hw/prep_pci.c | 2 +- hw/sh_pci.c | 2 +- hw/spapr_pci.c | 2 +- hw/unin_pci.c | 4 ++-- hw/versatile_pci.c | 2 +- 16 files changed, 51 insertions(+), 20 deletions(-) diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index 872e112..fc2e4b3 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -764,7 +764,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, &s->pchip.reg_io); b = pci_register_bus(&s->host.busdev.qdev, "pci", - typhoon_set_irq, sys_map_irq, s, + typhoon_set_irq, sys_map_irq, NULL, s, &s->pchip.reg_mem, addr_space_io, 0, 64); s->host.bus = b; diff --git a/hw/apb_pci.c b/hw/apb_pci.c index 7e28808..819bf1d 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -366,7 +366,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base, memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); d->bus = pci_register_bus(&d->busdev.qdev, "pci", - pci_apb_set_irq, pci_pbm_map_irq, d, + pci_apb_set_irq, pci_pbm_map_irq, NULL, d, &d->pci_mmio, get_system_io(), 0, 32); diff --git a/hw/bonito.c b/hw/bonito.c index 77786f8..7ce5993 100644 --- a/hw/bonito.c +++ b/hw/bonito.c @@ -750,7 +750,7 @@ PCIBus *bonito_init(qemu_irq *pic) dev = qdev_create(NULL, "Bonito-pcihost"); pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev)); b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq, - pci_bonito_map_irq, pic, get_system_memory(), + pci_bonito_map_irq, NULL, pic, get_system_memory(), get_system_io(), 0x28, 32); pcihost->bus = b; diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index 81ff3a3..f47d9fe 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -85,6 +85,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci", pci_grackle_set_irq, pci_grackle_map_irq, + NULL, pic, &d->pci_mmio, address_space_io, diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c index a2d0e5a..a97bbf0 100644 --- a/hw/gt64xxx.c +++ b/hw/gt64xxx.c @@ -1093,7 +1093,7 @@ PCIBus *gt64120_register(qemu_irq *pic) d = FROM_SYSBUS(GT64120State, s); d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci", gt64120_pci_set_irq, gt64120_pci_map_irq, - pic, + NULL, pic, get_system_memory(), get_system_io(), PCI_DEVFN(18, 0), 4); diff --git a/hw/pci.c b/hw/pci.c index 439f3ce..df4d93e 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -298,10 +298,11 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, } void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *irq_opaque, int nirq) + pci_map_host_irq_fn map_host_irq, void *irq_opaque, int nirq) { bus->set_irq = set_irq; bus->map_irq = map_irq; + bus->map_host_irq = map_host_irq; bus->irq_opaque = irq_opaque; bus->nirq = nirq; bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0])); @@ -316,7 +317,7 @@ void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev) PCIBus *pci_register_bus(DeviceState *parent, const char *name, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *irq_opaque, + pci_map_host_irq_fn map_host_irq, void *irq_opaque, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, uint8_t devfn_min, int nirq) @@ -325,7 +326,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name, bus = pci_bus_new(parent, name, address_space_mem, address_space_io, devfn_min); - pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq); + pci_bus_irqs(bus, set_irq, map_irq, map_host_irq, irq_opaque, nirq); return bus; } @@ -1067,6 +1068,22 @@ static void pci_set_irq(void *opaque, int irq_num, int level) pci_change_irq_level(pci_dev, irq_num, change); } +int pci_device_get_host_irq(PCIDevice *pci_dev, int irq_num) +{ + PCIBus *bus; + + for (;;) { + bus = pci_dev->bus; + irq_num = bus->map_irq(pci_dev, irq_num); + if (bus->map_host_irq) { + break; + } + pci_dev = bus->parent_dev; + assert(pci_dev); + } + return bus->map_host_irq(bus->irq_opaque, irq_num); +} + /***********************************************************/ /* monitor info on PCI */ diff --git a/hw/pci.h b/hw/pci.h index c3cacce..29bc8bf 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -276,6 +276,7 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev); typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); +typedef int (*pci_map_host_irq_fn)(void *opaque, int irq_num); typedef enum { PCI_HOTPLUG_DISABLED, @@ -295,15 +296,17 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, MemoryRegion *address_space_io, uint8_t devfn_min); void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *irq_opaque, int nirq); + pci_map_host_irq_fn map_host_irq, void *irq_opaque, + int nirq); int pci_bus_get_irq_level(PCIBus *bus, int irq_num); void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev); PCIBus *pci_register_bus(DeviceState *parent, const char *name, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *irq_opaque, + pci_map_host_irq_fn map_host_irq, void *irq_opaque, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, uint8_t devfn_min, int nirq); +int pci_device_get_host_irq(PCIDevice *pci_dev, int irq_num); void pci_device_reset(PCIDevice *dev); void pci_bus_reset(PCIBus *bus); diff --git a/hw/pci_internals.h b/hw/pci_internals.h index 96690b7..a92353e 100644 --- a/hw/pci_internals.h +++ b/hw/pci_internals.h @@ -19,6 +19,7 @@ struct PCIBus { uint8_t devfn_min; pci_set_irq_fn set_irq; pci_map_irq_fn map_irq; + pci_map_host_irq_fn map_host_irq; pci_hotplug_fn hotplug; DeviceState *hotplug_qdev; void *irq_opaque; diff --git a/hw/piix_pci.c b/hw/piix_pci.c index 09e84f5..cfea97c 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -89,6 +89,7 @@ struct PCII440FXState { #define I440FX_SMRAM 0x72 static void piix3_set_irq(void *opaque, int pirq, int level); +static int piix3_map_host_irq(void *opaque, int pci_intx); static void piix3_write_config_xen(PCIDevice *dev, uint32_t address, uint32_t val, int len); @@ -308,13 +309,13 @@ static PCIBus *i440fx_common_init(const char *device_name, if (xen_enabled()) { piix3 = DO_UPCAST(PIIX3State, dev, pci_create_simple_multifunction(b, -1, true, "PIIX3-xen")); - pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq, + pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq, NULL, piix3, XEN_PIIX_NUM_PIRQS); } else { piix3 = DO_UPCAST(PIIX3State, dev, pci_create_simple_multifunction(b, -1, true, "PIIX3")); - pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, - PIIX_NUM_PIRQS); + pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3_map_host_irq, + piix3, PIIX_NUM_PIRQS); } piix3->pic = pic; *isa_bus = DO_UPCAST(ISABus, qbus, @@ -386,6 +387,14 @@ static void piix3_set_irq(void *opaque, int pirq, int level) piix3_set_irq_level(piix3, pirq, level); } +static int piix3_map_host_irq(void *opaque, int pci_intx) +{ + PIIX3State *piix3 = opaque; + int host_irq = piix3->dev.config[PIIX_PIRQC + pci_intx]; + + return host_irq < PIIX_NUM_PIC_IRQS ? host_irq : -1; +} + /* irq routing is changed. so rebuild bitmap */ static void piix3_update_irq_levels(PIIX3State *piix3) { diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index 203c3cd..224c4a0 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -343,7 +343,7 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev) } b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, ppc4xx_pci_set_irq, - ppc4xx_pci_map_irq, s->irq, get_system_memory(), + ppc4xx_pci_map_irq, NULL, s->irq, get_system_memory(), get_system_io(), 0, 4); s->pci_state.bus = b; diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 0f60b24..dd924ae 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -318,7 +318,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev) } b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq, - mpc85xx_pci_map_irq, s->irq, address_space_mem, + mpc85xx_pci_map_irq, NULL, s->irq, address_space_mem, address_space_io, PCI_DEVFN(0x11, 0), 4); s->pci_state.bus = b; diff --git a/hw/prep_pci.c b/hw/prep_pci.c index 38dbff4..9d7bec7 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -108,7 +108,7 @@ static int raven_pcihost_init(SysBusDevice *dev) } bus = pci_register_bus(&h->busdev.qdev, NULL, - prep_set_irq, prep_map_irq, s->irq, + prep_set_irq, prep_map_irq, NULL, s->irq, address_space_mem, address_space_io, 0, 4); h->bus = bus; diff --git a/hw/sh_pci.c b/hw/sh_pci.c index 0cfac46..1cea12b 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -120,7 +120,7 @@ static int sh_pci_device_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[i]); } s->bus = pci_register_bus(&s->busdev.qdev, "pci", - sh_pci_set_irq, sh_pci_map_irq, + sh_pci_set_irq, sh_pci_map_irq, NULL, s->irq, get_system_memory(), get_system_io(), diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 25b400a..4a43062 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -306,7 +306,7 @@ static int spapr_phb_init(SysBusDevice *s) bus = pci_register_bus(&phb->busdev.qdev, phb->busname ? phb->busname : phb->dtbusname, - pci_spapr_set_irq, pci_spapr_map_irq, phb, + pci_spapr_set_irq, pci_spapr_map_irq, NULL, phb, &phb->memspace, &phb->iospace, PCI_DEVFN(0, 0), PCI_NUM_PINS); phb->host_state.bus = bus; diff --git a/hw/unin_pci.c b/hw/unin_pci.c index 409bcd4..056e3bc 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -227,7 +227,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic, d->host_state.bus = pci_register_bus(dev, "pci", pci_unin_set_irq, pci_unin_map_irq, - pic, + NULL, pic, &d->pci_mmio, address_space_io, PCI_DEVFN(11, 0), 4); @@ -293,7 +293,7 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic, d->host_state.bus = pci_register_bus(dev, "pci", pci_unin_set_irq, pci_unin_map_irq, - pic, + NULL, pic, &d->pci_mmio, address_space_io, PCI_DEVFN(11, 0), 4); diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c index ae53a8b..90c400e 100644 --- a/hw/versatile_pci.c +++ b/hw/versatile_pci.c @@ -68,7 +68,7 @@ static int pci_vpb_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[i]); } bus = pci_register_bus(&dev->qdev, "pci", - pci_vpb_set_irq, pci_vpb_map_irq, s->irq, + pci_vpb_set_irq, pci_vpb_map_irq, NULL, s->irq, get_system_memory(), get_system_io(), PCI_DEVFN(11, 0), 4);