From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59611) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YBNlL-0006tW-IH for qemu-devel@nongnu.org; Wed, 14 Jan 2015 08:13:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YBNlE-0002Md-HM for qemu-devel@nongnu.org; Wed, 14 Jan 2015 08:13:31 -0500 Received: from lhrrgout.huawei.com ([194.213.3.17]:42906) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YBNlE-0002MZ-5y for qemu-devel@nongnu.org; Wed, 14 Jan 2015 08:13:24 -0500 Message-ID: <54B66B57.6040305@huawei.com> Date: Wed, 14 Jan 2015 14:12:55 +0100 From: Claudio Fontana MIME-Version: 1.0 References: <1421230611-12481-1-git-send-email-a.rigo@virtualopensystems.com> <1421230611-12481-2-git-send-email-a.rigo@virtualopensystems.com> In-Reply-To: <1421230611-12481-2-git-send-email-a.rigo@virtualopensystems.com> Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 8bit Subject: Re: [Qemu-devel] [RFC v3 1/2] pci/pci-host: Add generic-pci PCI host controller device List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Alvise Rigo , qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, tech@virtualopensystems.com, agraf@suse.de, rob.herring@linaro.org On 14.01.2015 11:16, Alvise Rigo wrote: > Add a generic PCI host controller for virtual platforms, based on the > previous work by Rob Herring: > http://lists.gnu.org/archive/html/qemu-devel/2014-06/msg03482.html > > The controller relies on a configuration memory region and provides two > PCI memory regions for I/O (one port and one memory mapped). The device > needs the following qdev properties to configure the memory regions: > - cfg_win_size: size of the configuration memory > - pio_win_size: size of the port I/O space > - mmio_win_size: size of the MMIO space > - mmio_win_addr: offset of MMIO space in the system memory > > Signed-off-by: Alvise Rigo > --- > hw/pci-host/Makefile.objs | 2 +- > hw/pci-host/generic-pci.c | 140 ++++++++++++++++++++++++++++++++++++++ > include/hw/pci-host/generic-pci.h | 45 ++++++++++++ > 3 files changed, 186 insertions(+), 1 deletion(-) > create mode 100644 hw/pci-host/generic-pci.c > create mode 100644 include/hw/pci-host/generic-pci.h > > diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs > index bb65f9c..8ef9fac 100644 > --- a/hw/pci-host/Makefile.objs > +++ b/hw/pci-host/Makefile.objs > @@ -1,4 +1,4 @@ > -common-obj-y += pam.o > +common-obj-y += pam.o generic-pci.o > > # PPC devices > common-obj-$(CONFIG_PREP_PCI) += prep.o > diff --git a/hw/pci-host/generic-pci.c b/hw/pci-host/generic-pci.c > new file mode 100644 > index 0000000..54c9647 > --- /dev/null > +++ b/hw/pci-host/generic-pci.c > @@ -0,0 +1,140 @@ > +/* > + * Generic PCI host controller > + * > + * Copyright (c) 2014 Linaro, Ltd. > + * Author: Rob Herring > + * > + * Based on ARM Versatile PCI controller (hw/pci-host/versatile.c): > + * Copyright (c) 2006-2009 CodeSourcery. > + * Written by Paul Brook > + * > + * This code is licensed under the LGPL. > + */ > + > +#include "hw/sysbus.h" > +#include "hw/pci-host/generic-pci.h" > +#include "exec/address-spaces.h" > +#include "sysemu/device_tree.h" > + > +static const VMStateDescription pci_generic_host_vmstate = { > + .name = "generic-host-pci", > + .version_id = 1, > + .minimum_version_id = 1, > +}; > + > +static void pci_cam_config_write(void *opaque, hwaddr addr, > + uint64_t val, unsigned size) > +{ > + PCIGenState *s = opaque; > + pci_data_write(&s->pci_bus, addr, val, size); > +} > + > +static uint64_t pci_cam_config_read(void *opaque, hwaddr addr, unsigned size) > +{ > + PCIGenState *s = opaque; > + uint32_t val; > + val = pci_data_read(&s->pci_bus, addr, size); > + return val; > +} > + > +static const MemoryRegionOps pci_generic_config_ops = { > + .read = pci_cam_config_read, > + .write = pci_cam_config_write, > + .endianness = DEVICE_LITTLE_ENDIAN, > +}; > + > +static void pci_generic_set_irq(void *opaque, int irq_num, int level) > +{ > + qemu_irq *pic = opaque; > + qemu_set_irq(pic[irq_num], level); > +} > + > +static void pci_generic_host_realize(DeviceState *dev, Error **errp) > +{ > + PCIHostState *h = PCI_HOST_BRIDGE(dev); > + PCIGenState *s = PCI_GEN(dev); > + GenericPCIHostState *gps = &s->pci_gen; > + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); > + int i; > + > + memory_region_init(&s->pci_io_window, OBJECT(s), "pci_io", s->pio_win_size); > + memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 1ULL << 32); > + > + pci_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), dev, "pci", > + &s->pci_mem_space, &s->pci_io_window, > + PCI_DEVFN(0, 0), TYPE_PCI_BUS); > + h->bus = &s->pci_bus; > + > + object_initialize(gps, sizeof(*gps), TYPE_GENERIC_PCI_HOST); > + qdev_set_parent_bus(DEVICE(gps), BUS(&s->pci_bus)); > + > + for (i = 0; i < s->irqs; i++) { > + sysbus_init_irq(sbd, &s->irq[i]); > + } > + > + pci_bus_irqs(&s->pci_bus, pci_generic_set_irq, pci_swizzle_map_irq_fn, > + s->irq, s->irqs); > + memory_region_init_io(&s->mem_config, OBJECT(s), &pci_generic_config_ops, s, > + "pci-config", s->cfg_win_size); > + memory_region_init_alias(&s->pci_mem_window, OBJECT(s), "pci-mem-win", > + &s->pci_mem_space, s->mmio_win_addr, s->mmio_win_size); > + > + sysbus_init_mmio(sbd, &s->mem_config); > + sysbus_init_mmio(sbd, &s->pci_io_window); > + sysbus_init_mmio(sbd, &s->pci_mem_window); > +} > + > +static void pci_generic_host_class_init(ObjectClass *klass, void *data) > +{ > + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); > + DeviceClass *dc = DEVICE_CLASS(klass); > + > + k->vendor_id = PCI_VENDOR_ID_REDHAT; > + k->device_id = PCI_DEVICE_ID_REDHAT_BRIDGE; > + k->class_id = PCI_CLASS_PROCESSOR_CO; > + /* > + * PCI-facing part of the host bridge, not usable without the > + * host-facing part, which can't be device_add'ed, yet. > + */ > + dc->cannot_instantiate_with_device_add_yet = true; > +} > + > +static const TypeInfo pci_generic_host_info = { > + .name = TYPE_GENERIC_PCI_HOST, > + .parent = TYPE_PCI_DEVICE, > + .instance_size = sizeof(GenericPCIHostState), > + .class_init = pci_generic_host_class_init, > +}; > + > +static Property pci_generic_props[] = { > + DEFINE_PROP_UINT32("cfg_win_size", PCIGenState, cfg_win_size, 1ULL << 20), > + DEFINE_PROP_UINT32("pio_win_size", PCIGenState, pio_win_size, 64 * 1024), > + DEFINE_PROP_UINT64("mmio_win_size", PCIGenState, mmio_win_size, 1ULL << 32), > + DEFINE_PROP_UINT64("mmio_win_addr", PCIGenState, mmio_win_addr, 0), > + DEFINE_PROP_UINT32("irqs", PCIGenState, irqs, 4), > + DEFINE_PROP_END_OF_LIST(), > +}; > + > +static void pci_generic_class_init(ObjectClass *klass, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(klass); > + > + dc->realize = pci_generic_host_realize; > + dc->vmsd = &pci_generic_host_vmstate; > + dc->props = pci_generic_props; why do some of these assigments have the & and some not? > +} > + > +static const TypeInfo pci_generic_info = { > + .name = TYPE_GENERIC_PCI, > + .parent = TYPE_PCI_HOST_BRIDGE, > + .instance_size = sizeof(PCIGenState), > + .class_init = pci_generic_class_init, > +}; > + > +static void generic_pci_host_register_types(void) > +{ > + type_register_static(&pci_generic_info); > + type_register_static(&pci_generic_host_info); > +} > + > +type_init(generic_pci_host_register_types) > \ No newline at end of file > diff --git a/include/hw/pci-host/generic-pci.h b/include/hw/pci-host/generic-pci.h > new file mode 100644 > index 0000000..830542e > --- /dev/null > +++ b/include/hw/pci-host/generic-pci.h > @@ -0,0 +1,45 @@ > +#ifndef QEMU_GENERIC_PCI_H > +#define QEMU_GENERIC_PCI_H > + > +#include "hw/pci/pci.h" > +#include "hw/pci/pci_bus.h" > +#include "hw/pci/pci_host.h" > + > +#define MAX_PCI_DEVICES (PCI_SLOT_MAX * PCI_FUNC_MAX) > + > +typedef struct { > + /*< private >*/ > + PCIDevice parent_obj; > +} GenericPCIHostState; > + > +typedef struct PCIGenState { > + /*< private >*/ > + PCIHostState parent_obj; > + > + qemu_irq irq[MAX_PCI_DEVICES]; > + MemoryRegion mem_config; > + /* Container representing the PCI address MMIO space */ > + MemoryRegion pci_mem_space; > + /* Alias region into PCI address spaces which we expose as sysbus region */ > + MemoryRegion pci_mem_window; > + /* PCI I/O region */ > + MemoryRegion pci_io_window; > + PCIBus pci_bus; > + GenericPCIHostState pci_gen; > + > + uint32_t cfg_win_size; > + uint32_t pio_win_size; > + uint64_t mmio_win_addr; // offset of pci_mem_window inside pci_mem_space > + uint64_t mmio_win_size; > + uint32_t irqs; > +} PCIGenState; > + > +#define TYPE_GENERIC_PCI "generic_pci" > +#define PCI_GEN(obj) \ > + OBJECT_CHECK(PCIGenState, (obj), TYPE_GENERIC_PCI) > + > +#define TYPE_GENERIC_PCI_HOST "generic_pci_host" > +#define PCI_GEN_HOST(obj) \ > + OBJECT_CHECK(GenericPCIHostState, (obj), TYPE_GENERIC_PCI_HOST) > + > +#endif > \ No newline at end of file > -- Claudio Fontana Server Virtualization Architect Huawei Technologies Duesseldorf GmbH Riesstraße 25 - 80992 München office: +49 89 158834 4135 mobile: +49 15253060158