Permalink
Browse files

Merge remote-tracking branch 'mst/tags/for_anthony' into staging

virtio,pci,qom

Work by Alex to support VGA assignment,
pci and virtio fixes by Stefan, Jason and myself, and a
new qmp event for hotplug support by myself.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Tue 26 Mar 2013 02:02:24 PM CDT using RSA key ID D28D5469
# gpg: Can't check signature: public key not found

# By Alex Williamson (13) and others
# Via Michael S. Tsirkin
* mst/tags/for_anthony: (23 commits)
  pcie: Add endpoint capability initialization wrapper
  roms: switch oldnoconfig to olddefconfig
  pcie: Mangle types to match topology
  pci: Create and use API to determine root buses
  pci: Create pci_bus_is_express helper
  pci: Q35, Root Ports, and Switches create PCI Express buses
  pci: Allow PCI bus creation interfaces to specify the type of bus
  pci: Move PCI and PCIE type defines
  pci: Create and register a new PCI Express TypeInfo
  exec: assert that RAMBlock size is non-zero
  pci: refuse empty ROM files
  pci_bridge: Remove duplicate IRQ swizzle function
  pci_bridge: Use a default map_irq function
  pci: Fix INTx routing notifier recursion
  pci_bridge: drop formatting from source
  pci_bridge: factor out common code
  pci: Teach PCI Bridges about VGA routing
  pci: Add PCI VGA helpers
  virtio-pci: guest notifier mask without non-irqfd
  virtio-net: remove layout assumptions for mq ctrl
  ...
  • Loading branch information...
2 parents 18501ae + 6214e73 commit 404e7a4f4af753bd2aef649adf79e7434fb6dc31 Anthony Liguori committed Mar 26, 2013
View
@@ -136,6 +136,24 @@ Example:
Note: The "ready to complete" status is always reset by a BLOCK_JOB_ERROR
event.
+DEVICE_DELETED
+-----------------
+
+Emitted whenever the device removal completion is acknowledged
+by the guest.
+At this point, it's safe to reuse the specified device ID.
+Device removal can be initiated by the guest or by HMP/QMP commands.
+
+Data:
+
+- "device": device name (json-string, optional)
+- "path": device path (json-string)
+
+{ "event": "DEVICE_DELETED",
+ "data": { "device": "virtio-net-pci-0",
+ "path": "/machine/peripheral/virtio-net-pci-0" },
+ "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
+
DEVICE_TRAY_MOVED
-----------------
View
2 exec.c
@@ -925,6 +925,8 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
RAMBlock *block, *next_block;
ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX;
+ assert(size != 0); /* it would hand out same offset multiple times */
+
if (QTAILQ_EMPTY(&ram_list.blocks))
return 0;
View
@@ -775,7 +775,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
b = pci_register_bus(dev, "pci",
typhoon_set_irq, sys_map_irq, s,
- &s->pchip.reg_mem, addr_space_io, 0, 64);
+ &s->pchip.reg_mem, addr_space_io, 0, 64, TYPE_PCI_BUS);
phb->bus = b;
/* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */
View
@@ -329,7 +329,7 @@ static int apb_pci_bridge_initfn(PCIDevice *dev)
{
int rc;
- rc = pci_bridge_initfn(dev);
+ rc = pci_bridge_initfn(dev, TYPE_PCI_BUS);
if (rc < 0) {
return rc;
}
@@ -381,7 +381,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
pci_apb_set_irq, pci_pbm_map_irq, d,
&d->pci_mmio,
get_system_io(),
- 0, 32);
+ 0, 32, TYPE_PCI_BUS);
*pbm_irqs = d->pbm_irqs;
d->ivec_irqs = ivec_irqs;
View
@@ -707,7 +707,7 @@ static int bonito_pcihost_initfn(SysBusDevice *dev)
phb->bus = pci_register_bus(DEVICE(dev), "pci",
pci_bonito_set_irq, pci_bonito_map_irq, dev,
get_system_memory(), get_system_io(),
- 0x28, 32);
+ 0x28, 32, TYPE_PCI_BUS);
return 0;
}
View
@@ -51,12 +51,17 @@ static int dec_map_irq(PCIDevice *pci_dev, int irq_num)
return irq_num;
}
+static int dec_pci_bridge_initfn(PCIDevice *pci_dev)
+{
+ return pci_bridge_initfn(pci_dev, TYPE_PCI_BUS);
+}
+
static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->init = pci_bridge_initfn;
+ k->init = dec_pci_bridge_initfn;
k->exit = pci_bridge_exitfn;
k->vendor_id = PCI_VENDOR_ID_DEC;
k->device_id = PCI_DEVICE_ID_DEC_21154;
View
@@ -88,7 +88,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
pic,
&d->pci_mmio,
address_space_io,
- 0, 4);
+ 0, 4, TYPE_PCI_BUS);
pci_create_simple(phb->bus, 0, "grackle");
View
@@ -1107,7 +1107,7 @@ PCIBus *gt64120_register(qemu_irq *pic)
pic,
get_system_memory(),
get_system_io(),
- PCI_DEVFN(18, 0), 4);
+ PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS);
memory_region_init_io(&d->ISD_mem, &isd_mem_ops, d, "isd-mem", 0x1000);
pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
View
@@ -59,7 +59,7 @@ static int i82801b11_bridge_initfn(PCIDevice *d)
{
int rc;
- rc = pci_bridge_initfn(d);
+ rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
if (rc < 0) {
return rc;
}
View
@@ -97,7 +97,7 @@ static int ioh3420_initfn(PCIDevice *d)
PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
int rc;
- rc = pci_bridge_initfn(d);
+ rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
if (rc < 0) {
return rc;
}
View
@@ -75,6 +75,11 @@ static const TypeInfo pci_bus_info = {
.class_init = pci_bus_class_init,
};
+static const TypeInfo pcie_bus_info = {
+ .name = TYPE_PCIE_BUS,
+ .parent = TYPE_PCI_BUS,
+};
+
static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
static void pci_update_mappings(PCIDevice *d);
static void pci_set_irq(void *opaque, int irq_num, int level);
@@ -292,25 +297,35 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent,
vmstate_register(NULL, -1, &vmstate_pcibus, bus);
}
+bool pci_bus_is_express(PCIBus *bus)
+{
+ return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS);
+}
+
+bool pci_bus_is_root(PCIBus *bus)
+{
+ return !bus->parent_dev;
+}
+
void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
const char *name,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
- uint8_t devfn_min)
+ uint8_t devfn_min, const char *typename)
{
- qbus_create_inplace(bus, TYPE_PCI_BUS, parent, name);
+ qbus_create_inplace(bus, typename, parent, name);
pci_bus_init(bus, parent, name, address_space_mem,
address_space_io, devfn_min);
}
PCIBus *pci_bus_new(DeviceState *parent, const char *name,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
- uint8_t devfn_min)
+ uint8_t devfn_min, const char *typename)
{
PCIBus *bus;
- bus = PCI_BUS(qbus_create(TYPE_PCI_BUS, parent, name));
+ bus = PCI_BUS(qbus_create(typename, parent, name));
pci_bus_init(bus, parent, name, address_space_mem,
address_space_io, devfn_min);
return bus;
@@ -338,19 +353,19 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
void *irq_opaque,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
- uint8_t devfn_min, int nirq)
+ uint8_t devfn_min, int nirq, const char *typename)
{
PCIBus *bus;
bus = pci_bus_new(parent, name, address_space_mem,
- address_space_io, devfn_min);
+ address_space_io, devfn_min, typename);
pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
return bus;
}
int pci_bus_num(PCIBus *s)
{
- if (!s->parent_dev)
+ if (pci_bus_is_root(s))
return 0; /* pci host bridge */
return s->parent_dev->config[PCI_SECONDARY_BUS];
}
@@ -668,12 +683,10 @@ static void pci_init_mask_bridge(PCIDevice *d)
pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_LIMIT,
PCI_PREF_RANGE_TYPE_64);
-/* TODO: add this define to pci_regs.h in linux and then in qemu. */
-#define PCI_BRIDGE_CTL_VGA_16BIT 0x10 /* VGA 16-bit decode */
-#define PCI_BRIDGE_CTL_DISCARD 0x100 /* Primary discard timer */
-#define PCI_BRIDGE_CTL_SEC_DISCARD 0x200 /* Secondary discard timer */
-#define PCI_BRIDGE_CTL_DISCARD_STATUS 0x400 /* Discard timer status */
-#define PCI_BRIDGE_CTL_DISCARD_SERR 0x800 /* Discard timer SERR# enable */
+ /*
+ * TODO: Bridges default to 10-bit VGA decoding but we currently only
+ * implement 16-bit decoding (no alias support).
+ */
pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
PCI_BRIDGE_CTL_PARITY |
PCI_BRIDGE_CTL_SERR |
@@ -875,6 +888,8 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
continue;
memory_region_del_subregion(r->address_space, r->memory);
}
+
+ pci_unregister_vga(pci_dev);
}
static int pci_unregister_device(DeviceState *dev)
@@ -937,6 +952,63 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
: pci_dev->bus->address_space_mem;
}
+static void pci_update_vga(PCIDevice *pci_dev)
+{
+ uint16_t cmd;
+
+ if (!pci_dev->has_vga) {
+ return;
+ }
+
+ cmd = pci_get_word(pci_dev->config + PCI_COMMAND);
+
+ memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_MEM],
+ cmd & PCI_COMMAND_MEMORY);
+ memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO],
+ cmd & PCI_COMMAND_IO);
+ memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI],
+ cmd & PCI_COMMAND_IO);
+}
+
+void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem,
+ MemoryRegion *io_lo, MemoryRegion *io_hi)
+{
+ assert(!pci_dev->has_vga);
+
+ assert(memory_region_size(mem) == QEMU_PCI_VGA_MEM_SIZE);
+ pci_dev->vga_regions[QEMU_PCI_VGA_MEM] = mem;
+ memory_region_add_subregion_overlap(pci_dev->bus->address_space_mem,
+ QEMU_PCI_VGA_MEM_BASE, mem, 1);
+
+ assert(memory_region_size(io_lo) == QEMU_PCI_VGA_IO_LO_SIZE);
+ pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO] = io_lo;
+ memory_region_add_subregion_overlap(pci_dev->bus->address_space_io,
+ QEMU_PCI_VGA_IO_LO_BASE, io_lo, 1);
+
+ assert(memory_region_size(io_hi) == QEMU_PCI_VGA_IO_HI_SIZE);
+ pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI] = io_hi;
+ memory_region_add_subregion_overlap(pci_dev->bus->address_space_io,
+ QEMU_PCI_VGA_IO_HI_BASE, io_hi, 1);
+ pci_dev->has_vga = true;
+
+ pci_update_vga(pci_dev);
+}
+
+void pci_unregister_vga(PCIDevice *pci_dev)
+{
+ if (!pci_dev->has_vga) {
+ return;
+ }
+
+ memory_region_del_subregion(pci_dev->bus->address_space_mem,
+ pci_dev->vga_regions[QEMU_PCI_VGA_MEM]);
+ memory_region_del_subregion(pci_dev->bus->address_space_io,
+ pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO]);
+ memory_region_del_subregion(pci_dev->bus->address_space_io,
+ pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI]);
+ pci_dev->has_vga = false;
+}
+
pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num)
{
return pci_dev->io_regions[region_num].addr;
@@ -1036,6 +1108,8 @@ static void pci_update_mappings(PCIDevice *d)
r->addr, r->memory, 1);
}
}
+
+ pci_update_vga(d);
}
static inline int pci_irq_disabled(PCIDevice *d)
@@ -1117,7 +1191,7 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
/* Special hooks used by device assignment */
void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq)
{
- assert(!bus->parent_dev);
+ assert(pci_bus_is_root(bus));
bus->route_intx_to_irq = route_intx_to_irq;
}
@@ -1156,9 +1230,10 @@ void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
if (dev && dev->intx_routing_notifier) {
dev->intx_routing_notifier(dev);
}
- QLIST_FOREACH(sec, &bus->child, sibling) {
- pci_bus_fire_intx_routing_notifier(sec);
- }
+ }
+
+ QLIST_FOREACH(sec, &bus->child, sibling) {
+ pci_bus_fire_intx_routing_notifier(sec);
}
}
@@ -1581,15 +1656,15 @@ static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num)
}
/* Consider all bus numbers in range for the host pci bridge. */
- if (bus->parent_dev &&
+ if (!pci_bus_is_root(bus) &&
!pci_secondary_bus_in_range(bus->parent_dev, bus_num)) {
return NULL;
}
/* try child bus */
for (; bus; bus = sec) {
QLIST_FOREACH(sec, &bus->child, sibling) {
- assert(sec->parent_dev);
+ assert(!pci_bus_is_root(sec));
if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) {
return sec;
}
@@ -1852,7 +1927,12 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
size = get_image_size(path);
if (size < 0) {
error_report("%s: failed to find romfile \"%s\"",
- __FUNCTION__, pdev->romfile);
+ __func__, pdev->romfile);
+ g_free(path);
+ return -1;
+ } else if (size == 0) {
+ error_report("%s: ignoring empty romfile \"%s\"",
+ __func__, pdev->romfile);
g_free(path);
return -1;
}
@@ -2171,6 +2251,7 @@ static const TypeInfo pci_device_type_info = {
static void pci_register_types(void)
{
type_register_static(&pci_bus_info);
+ type_register_static(&pcie_bus_info);
type_register_static(&pci_device_type_info);
}
Oops, something went wrong.

0 comments on commit 404e7a4

Please sign in to comment.