From patchwork Thu Sep 8 07:26:04 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wen Congyang X-Patchwork-Id: 113873 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id AA3A0B6F7B for ; Thu, 8 Sep 2011 17:27:46 +1000 (EST) Received: from localhost ([::1]:41648 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R1Z1Q-0006Sz-Rz for incoming@patchwork.ozlabs.org; Thu, 08 Sep 2011 03:27:40 -0400 Received: from eggs.gnu.org ([140.186.70.92]:46261) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R1Z1J-0006QH-FA for qemu-devel@nongnu.org; Thu, 08 Sep 2011 03:27:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1R1Z1G-0007P0-VU for qemu-devel@nongnu.org; Thu, 08 Sep 2011 03:27:33 -0400 Received: from [222.73.24.84] (port=50068 helo=song.cn.fujitsu.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R1Z0y-0007CP-MV for qemu-devel@nongnu.org; Thu, 08 Sep 2011 03:27:30 -0400 Received: from tang.cn.fujitsu.com (tang.cn.fujitsu.com [10.167.250.3]) by song.cn.fujitsu.com (Postfix) with ESMTP id 838F2170116; Thu, 8 Sep 2011 15:27:05 +0800 (CST) Received: from mailserver.fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id p887R2Rl002137; Thu, 8 Sep 2011 15:27:03 +0800 Received: from [10.167.225.226] ([10.167.225.226]) by mailserver.fnst.cn.fujitsu.com (Lotus Domino Release 8.5.1FP4) with ESMTP id 2011090815255513-128338 ; Thu, 8 Sep 2011 15:25:55 +0800 Message-ID: <4E686E0C.7090906@cn.fujitsu.com> Date: Thu, 08 Sep 2011 15:26:04 +0800 From: Wen Congyang User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100413 Fedora/3.0.4-2.fc13 Thunderbird/3.0.4 MIME-Version: 1.0 To: "Michael S. Tsirkin" References: <4E4D2C9F.6040805@redhat.com> <4E4DF0A0.6000108@cn.fujitsu.com> <4E4E808C.4000205@redhat.com> <4E51C945.6070103@cn.fujitsu.com> <4E51F5FD.4030905@redhat.com> <4E6045E0.2090701@cn.fujitsu.com> <4E6335E4.6040705@redhat.com> <4E658E2F.6050302@cn.fujitsu.com> <4E65CF9E.20004@redhat.com> <4E66F56D.9070709@cn.fujitsu.com> <20110907115223.GD9337@redhat.com> <4E685D85.6030806@cn.fujitsu.com> In-Reply-To: <4E685D85.6030806@cn.fujitsu.com> X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.1FP4|July 25, 2010) at 2011-09-08 15:25:55, Serialize by Router on mailserver/fnst(Release 8.5.1FP4|July 25, 2010) at 2011-09-08 15:25:57, Serialize complete at 2011-09-08 15:25:57 X-detected-operating-system: by eggs.gnu.org: FreeBSD 6.x (1) X-Received-From: 222.73.24.84 Cc: Kevin Wolf , Isaku Yamahata , Avi Kivity , qemu-devel@nongnu.org Subject: Re: [Qemu-devel] [PATCH] pci: add standard bridge device 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 At 09/08/2011 02:15 PM, Wen Congyang Write: > At 09/07/2011 07:52 PM, Michael S. Tsirkin Write: >> On Wed, Sep 07, 2011 at 12:39:09PM +0800, Wen Congyang wrote: >>> At 09/06/2011 03:45 PM, Avi Kivity Write: >>>> On 09/06/2011 06:06 AM, Wen Congyang wrote: >>>>>> Use the uio driver - >>>>>> http://docs.blackfin.uclinux.org/kernel/generated/uio-howto/. You >>>>> just >>>>>> mmap() the BAR from userspace and play with it. >>>>> >>>>> When I try to bind ivshmem to uio_pci_generic, I get the following >>>>> messages: >>>>> uio_pci_generic 0000:01:01.0: No IRQ assigned to device: no support >>>>> for interrupts? >>>>> >>>> >>>> No idea what this means. >>> >>> PCI 3.0 6.2.4 >>> For x86 based PCs, the values in this register correspond to IRQ numbers (0-15) of the standard dual >>> 8259 configuration. The value 255 is defined as meaning "unknown" or "no connection" to the interrupt >>> controller. Values between 15 and 254 are reserved. >>> >>> The register is interrupt line. >>> >>> I read the config of this device, the interrupt line is 0. It means that it uses the IRQ0. >>> >>> The following is the uio_pci_generic's code: >>> static int __devinit probe(struct pci_dev *pdev, >>> const struct pci_device_id *id) >>> { >>> struct uio_pci_generic_dev *gdev; >>> int err; >>> >>> err = pci_enable_device(pdev); >>> if (err) { >>> dev_err(&pdev->dev, "%s: pci_enable_device failed: %d\n", >>> __func__, err); >>> return err; >>> } >>> >>> if (!pdev->irq) { >>> dev_warn(&pdev->dev, "No IRQ assigned to device: " >>> "no support for interrupts?\n"); >>> pci_disable_device(pdev); >>> return -ENODEV; >>> } >>> ... >>> } >>> >>> This function will be called when we write 'domain:bus:slot.function' to /sys/bus/pci/drivers/uio_pci_generic/bind. >>> pdev->irq is 0, it means the device uses IRQ0. But we refuse it. I do not why. >>> >>> To Michael S. Tsirkin >>> This code is writen by you. Do you know why you check whether pdev->irq is 0? >>> >>> Thanks >>> Wen Congyang >>> >>>> >> >> Well I see this in linux: >> >> /* >> * Read interrupt line and base address registers. >> * The architecture-dependent code can tweak these, of course. >> */ >> static void pci_read_irq(struct pci_dev *dev) >> { >> unsigned char irq; >> >> pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq); >> dev->pin = irq; >> if (irq) >> pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); >> dev->irq = irq; >> } >> >> Thus a device without an interrupt pin will get irq set to 0, >> and this seems the right way to detect such devices. >> I don't think PCI devices really use IRQ0 in practice, >> its probably used for PC things. More likely the system is >> misconfigured. Try lspci -vv to see what went wrong. > > Yes, the PCI device shoulde not use IRQ0. I debug qemu's code, and find the > PCI_INTERRUPT_LINE register is not set by qemu: > ============= > Hardware watchpoint 6: ((uint8_t *) 0x164e410)[0x3c] > > Old value = 0 '\000' > New value = 10 '\n' > pci_default_write_config (d=0x1653ed0, addr=60, val=10, l=1) at /home/wency/source/qemu/hw/pci.c:1115 > 1115 d->config[addr + i] &= ~(val & w1cmask); /* W1C: Write 1 to Clear */ > Missing separate debuginfos, use: debuginfo-install cyrus-sasl-gssapi-2.1.23-8.el6.x86_64 cyrus-sasl-md5-2.1.23-8.el6.x86_64 cyrus-sasl-plain-2.1.23-8.el6.x86_64 db4-4.7.25-16.el6.x86_64 > (gdb) bt > #0 pci_default_write_config (d=0x1653ed0, addr=60, val=10, l=1) at /home/wency/source/qemu/hw/pci.c:1115 > #1 0x00000000004d5827 in pci_host_config_write_common (pci_dev=0x1653ed0, addr=60, limit=256, val=10, len=1) at /home/wency/source/qemu/hw/pci_host.c:54 > #2 0x00000000004d5939 in pci_data_write (s=0x15f95a0, addr=2147502140, val=10, len=1) at /home/wency/source/qemu/hw/pci_host.c:75 > #3 0x00000000004d5b19 in pci_host_data_write (handler=0x15f9570, addr=3324, val=10, len=1) at /home/wency/source/qemu/hw/pci_host.c:125 > #4 0x000000000063ee06 in ioport_simple_writeb (opaque=0x15f9570, addr=3324, value=10) at /home/wency/source/qemu/rwhandler.c:48 > #5 0x0000000000470db9 in ioport_write (index=0, address=3324, data=10) at ioport.c:81 > #6 0x00000000004717bc in cpu_outb (addr=3324, val=10 '\n') at ioport.c:273 > #7 0x00000000005ef25d in kvm_handle_io (port=3324, data=0x7ffff7ff8000, direction=1, size=1, count=1) at /home/wency/source/qemu/kvm-all.c:834 > #8 0x00000000005ef7e6 in kvm_cpu_exec (env=0x13da0d0) at /home/wency/source/qemu/kvm-all.c:976 > #9 0x00000000005c1a7b in qemu_kvm_cpu_thread_fn (arg=0x13da0d0) at /home/wency/source/qemu/cpus.c:661 > #10 0x00000032864077e1 in start_thread () from /lib64/libpthread.so.0 > #11 0x00000032858e68ed in clone () from /lib64/libc.so.6 > ============= > > If I put ivshmem on bus 0, the PCI_INTERRUPT_LINE register can be set. So I guess this register is set by bios. > I use the newest seabios, and PCI_INTERRUPT_LINE register is not set if the deivce is not on bus0. Here is the seabios's code: > > # lspci -vv > 00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02) > Subsystem: Red Hat, Inc Qemu virtual machine > Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- > Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- SERR- > 00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II] > Subsystem: Red Hat, Inc Qemu virtual machine > Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- > Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- SERR- > 00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II] (prog-if 80 [Master]) > Subsystem: Red Hat, Inc Qemu virtual machine > Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- > Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- SERR- Latency: 0 > Region 0: [virtual] Memory at 000001f0 (32-bit, non-prefetchable) [size=8] > Region 1: [virtual] Memory at 000003f0 (type 3, non-prefetchable) [size=1] > Region 2: [virtual] Memory at 00000170 (32-bit, non-prefetchable) [size=8] > Region 3: [virtual] Memory at 00000370 (type 3, non-prefetchable) [size=1] > Region 4: I/O ports at d100 [size=16] > Kernel driver in use: ata_piix > Kernel modules: ata_piix > > 00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03) > Subsystem: Red Hat, Inc Qemu virtual machine > Physical Slot: 1 > Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- > Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- SERR- Interrupt: pin A routed to IRQ 9 > Kernel driver in use: piix4_smbus > Kernel modules: i2c-piix4 > > 00:02.0 VGA compatible controller: Cirrus Logic GD 5446 (prog-if 00 [VGA controller]) > Subsystem: Red Hat, Inc Device 1100 > Physical Slot: 2 > Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- > Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- SERR- Region 0: Memory at fc000000 (32-bit, prefetchable) [size=32M] > Region 1: Memory at f8020000 (32-bit, non-prefetchable) [size=4K] > Expansion ROM at f8000000 [disabled] [size=64K] > Kernel modules: cirrusfb > > 00:03.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+ (rev 20) > Subsystem: Red Hat, Inc Device 1100 > Physical Slot: 3 > Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- > Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- SERR- Latency: 0, Cache Line Size: 64 bytes > Interrupt: pin A routed to IRQ 11 > Region 0: I/O ports at d000 [size=256] > Region 1: Memory at f8021000 (32-bit, non-prefetchable) [size=256] > Expansion ROM at f8010000 [disabled] [size=64K] > Kernel driver in use: 8139cp > Kernel modules: 8139too, 8139cp > > 00:08.0 PCI bridge: Red Hat, Inc. Device 0001 (prog-if 00 [Normal decode]) > Physical Slot: 8 > Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- > Status: Cap- 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- SERR- Latency: 0 > Bus: primary=00, secondary=01, subordinate=01, sec-latency=0 > I/O behind bridge: 0000c000-0000cfff > Memory behind bridge: f0000000-f7ffffff > Prefetchable memory behind bridge: fe000000-fe0fffff > Secondary status: 66MHz+ FastB2B+ ParErr- DEVSEL=fast >TAbort- BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- >Reset- FastB2B- > PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn- > > 01:01.0 RAM memory: Red Hat, Inc Device 1110 > Subsystem: Red Hat, Inc Device 1100 > Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- > Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- SERR- Interrupt: pin A routed to IRQ 0 > Region 0: Memory at f4000000 (32-bit, non-prefetchable) [disabled] [size=256] > Region 2: Memory at f0000000 (32-bit, non-prefetchable) [disabled] [size=32M] > Kernel modules: virtio_pci > > 01:01.1 RAM memory: Red Hat, Inc Device 1110 > Subsystem: Red Hat, Inc Device 1100 > Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- > Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- SERR- Interrupt: pin A routed to IRQ 0 > Region 0: Memory at f4001000 (32-bit, non-prefetchable) [disabled] [size=256] > Region 2: Memory at f2000000 (32-bit, non-prefetchable) [disabled] [size=32M] > Kernel modules: virtio_pci > > >> > > > ========== static void pci_bios_init_device(struct pci_device *pci) { u16 bdf = pci->bdf; int pin, pic_irq; dprintf(1, "PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n" , pci_bdf_to_bus(bdf), pci_bdf_to_devfn(bdf) , pci->vendor, pci->device); pci_init_device(pci_class_tbl, pci, NULL); /* enable memory mappings */ pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY); /* map the interrupt */ pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN); if (pin != 0) { pin = pci_slot_get_pirq(bdf, pin - 1); pic_irq = pci_irqs[pin]; pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pic_irq); } pci_init_device(pci_device_tbl, pci, NULL); } static void pci_bios_init_device_in_bus(int bus) { struct pci_device *pci; foreachpci(pci) { u8 pci_bus = pci_bdf_to_bus(pci->bdf); if (pci_bus < bus) continue; if (pci_bus > bus) break; pci_bios_init_device(pci); } } ... void pci_setup(void) { ... pci_bios_map_device_in_bus(0 /* host bus */); pci_bios_init_device_in_bus(0 /* host bus */); ... } ========== The PCI_INTERRUPT_LINE register is set in the function pci_setup() calls pci_bios_init_device_in_bus() calls pci_bios_init_device(). According to the code, it only inits the PCI device on bus 0. I modify the code like this, and the PCI_INTERRUPT_LINE register is set, and I can bind it to uio_pci_generic: diff --git a/src/pciinit.c b/src/pciinit.c index 597c8ea..c2e97d7 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -575,6 +575,8 @@ static int pci_bios_init_root_regions(u32 start, u32 end) void pci_setup(void) { + int bus; + if (CONFIG_COREBOOT || usingXen()) { // PCI setup already done by coreboot or Xen - just do probe. pci_probe(); @@ -603,9 +605,11 @@ pci_setup(void) dprintf(1, "=== PCI new allocation pass #2 ===\n"); dprintf(1, "PCI: init bases bus 0 (primary)\n"); pci_bios_init_bus_bases(&busses[0]); - pci_bios_map_device_in_bus(0 /* host bus */); + for (bus = 0; bus <= MaxPCIBus; bus++) { + pci_bios_map_device_in_bus(bus /* host bus */); - pci_bios_init_device_in_bus(0 /* host bus */); + pci_bios_init_device_in_bus(bus /* host bus */); + } struct pci_device *pci; foreachpci(pci) {