* [Qemu-devel] [patch 00/18] acpi pci hotplug support
@ 2009-02-04 13:33 Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 01/18] qemu: add pci helper functions Marcelo Tosatti
` (17 more replies)
0 siblings, 18 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel
Support ACPI PCI hotplug. Has been included in the KVM tree for almost a
year.
Please review.
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 01/18] qemu: add pci helper functions
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 14:56 ` Paul Brook
2009-02-04 13:33 ` [Qemu-devel] [patch 02/18] qemu: return PCIDevice on net device init and record devfn Marcelo Tosatti
` (16 subsequent siblings)
17 siblings, 1 reply; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: pci-helpers --]
[-- Type: text/plain, Size: 1914 bytes --]
Add pci_find_bus/pci_find_device to be used by PCI hotplug.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/hw/pci.c
===================================================================
--- trunk.orig/hw/pci.c
+++ trunk/hw/pci.c
@@ -713,6 +713,33 @@ static void pci_bridge_write_config(PCID
pci_default_write_config(d, address, val, len);
}
+PCIBus *pci_find_bus(int bus_num)
+{
+ PCIBus *bus = first_bus;
+
+ while (bus && bus->bus_num != bus_num)
+ bus = bus->next;
+
+ return bus;
+}
+
+PCIDevice *pci_find_device(int bus_num, int slot)
+{
+ int devfn;
+ PCIDevice *d;
+ PCIBus *bus = pci_find_bus(bus_num);
+
+ if (!bus)
+ return NULL;
+
+ for(devfn = 0; devfn < 256; devfn++) {
+ d = bus->devices[devfn];
+ if (d && PCI_SLOT(devfn) == slot)
+ return d;
+ }
+ return NULL;
+}
+
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
pci_map_irq_fn map_irq, const char *name)
{
Index: trunk/hw/pci.h
===================================================================
--- trunk.orig/hw/pci.h
+++ trunk/hw/pci.h
@@ -8,6 +8,10 @@
extern target_phys_addr_t pci_mem_base;
+#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
+
/* Device classes and subclasses */
#define PCI_CLASS_STORAGE_SCSI 0x0100
@@ -222,6 +226,8 @@ void pci_data_write(void *opaque, uint32
uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
int pci_bus_num(PCIBus *s);
void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
+PCIBus *pci_find_bus(int bus_num);
+PCIDevice *pci_find_device(int bus_num, int slot);
void pci_info(void);
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 02/18] qemu: return PCIDevice on net device init and record devfn
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 01/18] qemu: add pci helper functions Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 03/18] qemu: dynamic drive/drive_opt index allocation Marcelo Tosatti
` (15 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: net-return-pcidev --]
[-- Type: text/plain, Size: 8766 bytes --]
Change the PCI network drivers init functions to return the PCIDev, to
inform which slot has been hot-plugged.
Also record PCIDevice structure on NICInfo to locate for release on
hot-removal.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/hw/e1000.c
===================================================================
--- trunk.orig/hw/e1000.c
+++ trunk/hw/e1000.c
@@ -1034,7 +1034,7 @@ e1000_mmio_map(PCIDevice *pci_dev, int r
excluded_regs[i] - 4);
}
-void
+PCIDevice *
pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
{
E1000State *d;
@@ -1092,4 +1092,6 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd,
qemu_format_nic_info_str(d->vc, d->nd->macaddr);
register_savevm(info_str, -1, 2, nic_save, nic_load, d);
+
+ return (PCIDevice *)d;
}
Index: trunk/hw/eepro100.c
===================================================================
--- trunk.orig/hw/eepro100.c
+++ trunk/hw/eepro100.c
@@ -1735,7 +1735,7 @@ static void nic_save(QEMUFile * f, void
qemu_put_buffer(f, s->configuration, sizeof(s->configuration));
}
-static void nic_init(PCIBus * bus, NICInfo * nd,
+static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd,
const char *name, uint32_t device)
{
PCIEEPRO100State *d;
@@ -1783,22 +1783,23 @@ static void nic_init(PCIBus * bus, NICIn
qemu_register_reset(nic_reset, s);
register_savevm(name, -1, 3, nic_save, nic_load, s);
+ return (PCIDevice *)d;
}
-void pci_i82551_init(PCIBus * bus, NICInfo * nd, int devfn)
+PCIDevice *pci_i82551_init(PCIBus * bus, NICInfo * nd, int devfn)
{
- nic_init(bus, nd, "i82551", i82551);
+ return nic_init(bus, nd, "i82551", i82551);
//~ uint8_t *pci_conf = d->dev.config;
}
-void pci_i82557b_init(PCIBus * bus, NICInfo * nd, int devfn)
+PCIDevice *pci_i82557b_init(PCIBus * bus, NICInfo * nd, int devfn)
{
- nic_init(bus, nd, "i82557b", i82557B);
+ return nic_init(bus, nd, "i82557b", i82557B);
}
-void pci_i82559er_init(PCIBus * bus, NICInfo * nd, int devfn)
+PCIDevice *pci_i82559er_init(PCIBus * bus, NICInfo * nd, int devfn)
{
- nic_init(bus, nd, "i82559er", i82559ER);
+ return nic_init(bus, nd, "i82559er", i82559ER);
}
/* eof */
Index: trunk/hw/ne2000.c
===================================================================
--- trunk.orig/hw/ne2000.c
+++ trunk/hw/ne2000.c
@@ -779,7 +779,7 @@ static void ne2000_map(PCIDevice *pci_de
register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
}
-void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
+PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
{
PCINE2000State *d;
NE2000State *s;
@@ -809,4 +809,6 @@ void pci_ne2000_init(PCIBus *bus, NICInf
qemu_format_nic_info_str(s->vc, s->macaddr);
register_savevm("ne2000", -1, 3, ne2000_save, ne2000_load, s);
+
+ return (PCIDevice *)d;
}
Index: trunk/hw/pci.c
===================================================================
--- trunk.orig/hw/pci.c
+++ trunk/hw/pci.c
@@ -664,7 +664,7 @@ static const char * const pci_nic_models
NULL
};
-typedef void (*PCINICInitFn)(PCIBus *, NICInfo *, int);
+typedef PCIDevice *(*PCINICInitFn)(PCIBus *, NICInfo *, int);
static PCINICInitFn pci_nic_init_fns[] = {
pci_ne2000_init,
@@ -679,16 +679,23 @@ static PCINICInitFn pci_nic_init_fns[] =
};
/* Initialize a PCI NIC. */
-void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn,
+PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn,
const char *default_model)
{
+ PCIDevice *pci_dev;
int i;
qemu_check_nic_model_list(nd, pci_nic_models, default_model);
for (i = 0; pci_nic_models[i]; i++)
- if (strcmp(nd->model, pci_nic_models[i]) == 0)
- pci_nic_init_fns[i](bus, nd, devfn);
+ if (strcmp(nd->model, pci_nic_models[i]) == 0) {
+ pci_dev = pci_nic_init_fns[i](bus, nd, devfn);
+ if (pci_dev)
+ nd->private = pci_dev;
+ return pci_dev;
+ }
+
+ return NULL;
}
typedef struct {
Index: trunk/hw/pci.h
===================================================================
--- trunk.orig/hw/pci.h
+++ trunk/hw/pci.h
@@ -220,7 +220,7 @@ typedef int (*pci_map_irq_fn)(PCIDevice
PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
qemu_irq *pic, int devfn_min, int nirq);
-void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn,
+PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn,
const char *default_model);
void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
@@ -269,23 +269,23 @@ void usb_ohci_init_pci(struct PCIBus *bu
/* eepro100.c */
-void pci_i82551_init(PCIBus *bus, NICInfo *nd, int devfn);
-void pci_i82557b_init(PCIBus *bus, NICInfo *nd, int devfn);
-void pci_i82559er_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_i82551_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_i82557b_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_i82559er_init(PCIBus *bus, NICInfo *nd, int devfn);
/* ne2000.c */
-void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn);
/* rtl8139.c */
-void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn);
/* e1000.c */
-void pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn);
/* pcnet.c */
-void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn);
/* prep_pci.c */
PCIBus *pci_prep_init(qemu_irq *pic);
Index: trunk/hw/pcnet.c
===================================================================
--- trunk.orig/hw/pcnet.c
+++ trunk/hw/pcnet.c
@@ -1985,7 +1985,7 @@ static void pci_physical_memory_read(voi
cpu_physical_memory_read(addr, buf, len);
}
-void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
+PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
{
PCNetState *d;
uint8_t *pci_conf;
@@ -2032,6 +2032,7 @@ void pci_pcnet_init(PCIBus *bus, NICInfo
d->pci_dev = &d->dev;
pcnet_common_init(d, nd);
+ return (PCIDevice *)d;
}
/* SPARC32 interface */
Index: trunk/hw/rtl8139.c
===================================================================
--- trunk.orig/hw/rtl8139.c
+++ trunk/hw/rtl8139.c
@@ -3414,7 +3414,7 @@ static void rtl8139_timer(void *opaque)
}
#endif /* RTL8139_ONBOARD_TIMER */
-void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
+PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
{
PCIRTL8139State *d;
RTL8139State *s;
@@ -3466,4 +3466,5 @@ void pci_rtl8139_init(PCIBus *bus, NICIn
qemu_mod_timer(s->timer,
rtl8139_get_next_tctr_time(s,qemu_get_clock(vm_clock)));
#endif /* RTL8139_ONBOARD_TIMER */
+ return (PCIDevice *)d;
}
Index: trunk/hw/virtio-net.c
===================================================================
--- trunk.orig/hw/virtio-net.c
+++ trunk/hw/virtio-net.c
@@ -315,7 +315,7 @@ static int virtio_net_load(QEMUFile *f,
return 0;
}
-void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
+PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
{
VirtIONet *n;
static int virtio_net_id;
@@ -329,7 +329,7 @@ void virtio_net_init(PCIBus *bus, NICInf
sizeof(struct virtio_net_config),
sizeof(VirtIONet));
if (!n)
- return;
+ return NULL;
n->vdev.get_config = virtio_net_update_config;
n->vdev.get_features = virtio_net_get_features;
@@ -350,4 +350,5 @@ void virtio_net_init(PCIBus *bus, NICInf
register_savevm("virtio-net", virtio_net_id++, 2,
virtio_net_save, virtio_net_load, n);
+ return (PCIDevice *)n;
}
Index: trunk/hw/virtio-net.h
===================================================================
--- trunk.orig/hw/virtio-net.h
+++ trunk/hw/virtio-net.h
@@ -80,6 +80,6 @@ struct virtio_net_hdr_mrg_rxbuf
uint16_t num_buffers; /* Number of merged rx buffers */
};
-void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
#endif
Index: trunk/net.h
===================================================================
--- trunk.orig/net.h
+++ trunk/net.h
@@ -64,6 +64,7 @@ struct NICInfo {
const char *model;
const char *name;
VLANState *vlan;
+ void *private;
};
extern int nb_nics;
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 03/18] qemu: dynamic drive/drive_opt index allocation
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 01/18] qemu: add pci helper functions Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 02/18] qemu: return PCIDevice on net device init and record devfn Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 04/18] qemu: dynamic nic info " Marcelo Tosatti
` (14 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: dynamic-drive-and-opt-index --]
[-- Type: text/plain, Size: 3713 bytes --]
Dynamically allocate drive options and drive table index, to reuse
indexes when devices are removed.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/sysemu.h
===================================================================
--- trunk.orig/sysemu.h
+++ trunk/sysemu.h
@@ -134,6 +134,7 @@ typedef struct DriveInfo {
BlockInterfaceType type;
int bus;
int unit;
+ int used;
BlockInterfaceErrorAction onerror;
char serial[21];
} DriveInfo;
Index: trunk/vl.c
===================================================================
--- trunk.orig/vl.c
+++ trunk/vl.c
@@ -246,6 +246,7 @@ static int nb_drives_opt;
static struct drive_opt {
const char *file;
char opt[1024];
+ int used;
} drives_opt[MAX_DRIVES];
static CPUState *cur_cpu;
@@ -2139,22 +2140,50 @@ static int bt_parse(const char *opt)
#define MTD_ALIAS "if=mtd"
#define SD_ALIAS "index=0,if=sd"
+static int drive_opt_get_free_idx(void)
+{
+ int index;
+
+ for (index = 0; index < MAX_DRIVES; index++)
+ if (!drives_opt[index].used) {
+ drives_opt[index].used = 1;
+ return index;
+ }
+
+ return -1;
+}
+
+static int drive_get_free_idx(void)
+{
+ int index;
+
+ for (index = 0; index < MAX_DRIVES; index++)
+ if (!drives_table[index].used) {
+ drives_table[index].used = 1;
+ return index;
+ }
+
+ return -1;
+}
+
static int drive_add(const char *file, const char *fmt, ...)
{
va_list ap;
+ int index = drive_opt_get_free_idx();
- if (nb_drives_opt >= MAX_DRIVES) {
+ if (nb_drives_opt >= MAX_DRIVES || index == -1) {
fprintf(stderr, "qemu: too many drives\n");
exit(1);
}
- drives_opt[nb_drives_opt].file = file;
+ drives_opt[index].file = file;
va_start(ap, fmt);
- vsnprintf(drives_opt[nb_drives_opt].opt,
+ vsnprintf(drives_opt[index].opt,
sizeof(drives_opt[0].opt), fmt, ap);
va_end(ap);
- return nb_drives_opt++;
+ nb_drives_opt++;
+ return index;
}
int drive_get_index(BlockInterfaceType type, int bus, int unit)
@@ -2163,10 +2192,11 @@ int drive_get_index(BlockInterfaceType t
/* seek interface, bus and unit */
- for (index = 0; index < nb_drives; index++)
+ for (index = 0; index < MAX_DRIVES; index++)
if (drives_table[index].type == type &&
drives_table[index].bus == bus &&
- drives_table[index].unit == unit)
+ drives_table[index].unit == unit &&
+ drives_table[index].used)
return index;
return -1;
@@ -2231,6 +2261,7 @@ static int drive_init(struct drive_opt *
int index;
int cache;
int bdrv_flags, onerror;
+ int drives_table_idx;
char *str = arg->opt;
static const char * const params[] = { "bus", "unit", "if", "index",
"cyls", "heads", "secs", "trans",
@@ -2505,11 +2536,12 @@ static int drive_init(struct drive_opt *
snprintf(buf, sizeof(buf), "%s%s%i",
devname, mediastr, unit_id);
bdrv = bdrv_new(buf);
- drives_table[nb_drives].bdrv = bdrv;
- drives_table[nb_drives].type = type;
- drives_table[nb_drives].bus = bus_id;
- drives_table[nb_drives].unit = unit_id;
- drives_table[nb_drives].onerror = onerror;
+ drives_table_idx = drive_get_free_idx();
+ drives_table[drives_table_idx].bdrv = bdrv;
+ drives_table[drives_table_idx].type = type;
+ drives_table[drives_table_idx].bus = bus_id;
+ drives_table[drives_table_idx].unit = unit_id;
+ drives_table[drives_table_idx].onerror = onerror;
strncpy(drives_table[nb_drives].serial, serial, sizeof(serial));
nb_drives++;
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 04/18] qemu: dynamic nic info index allocation
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (2 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 03/18] qemu: dynamic drive/drive_opt index allocation Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 05/18] qemu: drive removal support Marcelo Tosatti
` (13 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: dynamic-nic-info --]
[-- Type: text/plain, Size: 1899 bytes --]
Dynamically allocate nic info index, so to reuse indexes when devices are
removed.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/net.c
===================================================================
--- trunk.orig/net.c
+++ trunk/net.c
@@ -1515,6 +1515,16 @@ VLANState *qemu_find_vlan(int id)
return vlan;
}
+static int nic_get_free_idx(void)
+{
+ int index;
+
+ for (index = 0; index < MAX_NICS; index++)
+ if (!nd_table[index].used)
+ return index;
+ return -1;
+}
+
void qemu_check_nic_model(NICInfo *nd, const char *model)
{
const char *models[2];
@@ -1571,19 +1581,20 @@ int net_client_init(const char *device,
if (!strcmp(device, "nic")) {
NICInfo *nd;
uint8_t *macaddr;
+ int idx = nic_get_free_idx();
- if (nb_nics >= MAX_NICS) {
+ if (idx == -1 || nb_nics >= MAX_NICS) {
fprintf(stderr, "Too Many NICs\n");
return -1;
}
- nd = &nd_table[nb_nics];
+ nd = &nd_table[idx];
macaddr = nd->macaddr;
macaddr[0] = 0x52;
macaddr[1] = 0x54;
macaddr[2] = 0x00;
macaddr[3] = 0x12;
macaddr[4] = 0x34;
- macaddr[5] = 0x56 + nb_nics;
+ macaddr[5] = 0x56 + idx;
if (get_param_value(buf, sizeof(buf), "macaddr", p)) {
if (parse_macaddr(macaddr, buf) < 0) {
@@ -1596,6 +1607,7 @@ int net_client_init(const char *device,
}
nd->vlan = vlan;
nd->name = name;
+ nd->used = 1;
name = NULL;
nb_nics++;
vlan->nb_guest_devs++;
Index: trunk/net.h
===================================================================
--- trunk.orig/net.h
+++ trunk/net.h
@@ -65,6 +65,7 @@ struct NICInfo {
const char *name;
VLANState *vlan;
void *private;
+ int used;
};
extern int nb_nics;
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 05/18] qemu: drive removal support
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (3 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 04/18] qemu: dynamic nic info " Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 06/18] qemu: record devfn on block driver instance Marcelo Tosatti
` (12 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: drive-remove --]
[-- Type: text/plain, Size: 2154 bytes --]
To be used by hot-remove.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/sysemu.h
===================================================================
--- trunk.orig/sysemu.h
+++ trunk/sysemu.h
@@ -135,6 +135,7 @@ typedef struct DriveInfo {
int bus;
int unit;
int used;
+ int drive_opt_idx;
BlockInterfaceErrorAction onerror;
char serial[21];
} DriveInfo;
@@ -148,6 +149,8 @@ extern DriveInfo drives_table[MAX_DRIVES
extern int drive_get_index(BlockInterfaceType type, int bus, int unit);
extern int drive_get_max_bus(BlockInterfaceType type);
+extern void drive_uninit(BlockDriverState *bdrv);
+extern void drive_remove(int index);
extern const char *drive_get_serial(BlockDriverState *bdrv);
extern BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv);
Index: trunk/vl.c
===================================================================
--- trunk.orig/vl.c
+++ trunk/vl.c
@@ -2186,6 +2186,12 @@ static int drive_add(const char *file, c
return index;
}
+void drive_remove(int index)
+{
+ drives_opt[index].used = 0;
+ nb_drives_opt--;
+}
+
int drive_get_index(BlockInterfaceType type, int bus, int unit)
{
int index;
@@ -2243,6 +2249,20 @@ static void bdrv_format_print(void *opaq
fprintf(stderr, " %s", name);
}
+void drive_uninit(BlockDriverState *bdrv)
+{
+ int i;
+
+ for (i = 0; i < MAX_DRIVES; i++)
+ if (drives_table[i].bdrv == bdrv) {
+ drives_table[i].bdrv = NULL;
+ drives_table[i].used = 0;
+ drive_remove(drives_table[i].drive_opt_idx);
+ nb_drives--;
+ break;
+ }
+}
+
static int drive_init(struct drive_opt *arg, int snapshot,
QEMUMachine *machine)
{
@@ -2542,6 +2562,7 @@ static int drive_init(struct drive_opt *
drives_table[drives_table_idx].bus = bus_id;
drives_table[drives_table_idx].unit = unit_id;
drives_table[drives_table_idx].onerror = onerror;
+ drives_table[drives_table_idx].drive_opt_idx = arg - drives_opt;
strncpy(drives_table[nb_drives].serial, serial, sizeof(serial));
nb_drives++;
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 06/18] qemu: record devfn on block driver instance
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (4 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 05/18] qemu: drive removal support Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 07/18] qemu: move drives_opt for external use Marcelo Tosatti
` (11 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: record-pcidev-on-bdrv --]
[-- Type: text/plain, Size: 2416 bytes --]
Record PCIDev on the BlockDriverState structure to locate for release
on hot-removal.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/block_int.h
===================================================================
--- trunk.orig/block_int.h
+++ trunk/block_int.h
@@ -127,6 +127,7 @@ struct BlockDriverState {
int type;
char device_name[32];
BlockDriverState *next;
+ void *private;
};
struct BlockDriverAIOCB {
Index: trunk/hw/ide.c
===================================================================
--- trunk.orig/hw/ide.c
+++ trunk/hw/ide.c
@@ -28,6 +28,7 @@
#include "scsi-disk.h"
#include "pcmcia.h"
#include "block.h"
+#include "block_int.h"
#include "qemu-timer.h"
#include "sysemu.h"
#include "ppc_mac.h"
@@ -3410,6 +3411,7 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
{
PCIIDEState *d;
uint8_t *pci_conf;
+ int i;
/* register a function 1 of PIIX3 */
d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE",
@@ -3436,6 +3438,10 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+ for (i = 0; i < 4; i++)
+ if (hd_table[i])
+ hd_table[i]->private = &d->dev;
+
register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
}
Index: trunk/hw/lsi53c895a.c
===================================================================
--- trunk.orig/hw/lsi53c895a.c
+++ trunk/hw/lsi53c895a.c
@@ -13,6 +13,7 @@
#include "hw.h"
#include "pci.h"
#include "scsi-disk.h"
+#include "block_int.h"
//#define DEBUG_LSI
//#define DEBUG_LSI_REG
@@ -1958,6 +1959,7 @@ void lsi_scsi_attach(void *opaque, Block
s->scsi_dev[id] = scsi_generic_init(bd, 1, lsi_command_complete, s);
if (s->scsi_dev[id] == NULL)
s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
+ bd->private = &s->pci_dev;
}
void *lsi_scsi_init(PCIBus *bus, int devfn)
Index: trunk/hw/virtio-blk.c
===================================================================
--- trunk.orig/hw/virtio-blk.c
+++ trunk/hw/virtio-blk.c
@@ -315,6 +315,7 @@ void *virtio_blk_init(PCIBus *bus, Block
s->vdev.reset = virtio_blk_reset;
s->bs = bs;
s->rq = NULL;
+ bs->private = &s->vdev.pci_dev;
bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 07/18] qemu: move drives_opt for external use
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (5 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 06/18] qemu: record devfn on block driver instance Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 08/18] qemu: net/drive add/remove tweaks Marcelo Tosatti
` (10 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: move-drives-opt-for-external-use --]
[-- Type: text/plain, Size: 1164 bytes --]
Device hotplug will use that structure from a separate
file.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/sysemu.h
===================================================================
--- trunk.orig/sysemu.h
+++ trunk/sysemu.h
@@ -154,6 +154,15 @@ extern void drive_remove(int index);
extern const char *drive_get_serial(BlockDriverState *bdrv);
extern BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv);
+struct drive_opt {
+ const char *file;
+ char opt[1024];
+ int used;
+};
+
+extern struct drive_opt drives_opt[MAX_DRIVES];
+extern int nb_drives_opt;
+
/* serial ports */
#define MAX_SERIAL_PORTS 4
Index: trunk/vl.c
===================================================================
--- trunk.orig/vl.c
+++ trunk/vl.c
@@ -242,12 +242,8 @@ int alt_grab = 0;
unsigned int nb_prom_envs = 0;
const char *prom_envs[MAX_PROM_ENVS];
#endif
-static int nb_drives_opt;
-static struct drive_opt {
- const char *file;
- char opt[1024];
- int used;
-} drives_opt[MAX_DRIVES];
+int nb_drives_opt;
+struct drive_opt drives_opt[MAX_DRIVES];
static CPUState *cur_cpu;
static CPUState *next_cpu;
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 08/18] qemu: net/drive add/remove tweaks
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (6 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 07/18] qemu: move drives_opt for external use Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 09/18] qemu: add net_client_uninit / qemu_find_vlan_client Marcelo Tosatti
` (9 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: net-drive-add-remove-tweaks --]
[-- Type: text/plain, Size: 2860 bytes --]
Export net/drive add/remove functions for device hotplug usage.
Return the table index on add.
Return failure instead of exiting if limit has been reached
on drive_add.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/net.c
===================================================================
--- trunk.orig/net.c
+++ trunk/net.c
@@ -1611,7 +1611,7 @@ int net_client_init(const char *device,
name = NULL;
nb_nics++;
vlan->nb_guest_devs++;
- ret = 0;
+ ret = idx;
} else
if (!strcmp(device, "none")) {
/* does nothing. It is needed to signal that no network cards
Index: trunk/sysemu.h
===================================================================
--- trunk.orig/sysemu.h
+++ trunk/sysemu.h
@@ -163,6 +163,9 @@ struct drive_opt {
extern struct drive_opt drives_opt[MAX_DRIVES];
extern int nb_drives_opt;
+extern int drive_add(const char *file, const char *fmt, ...);
+extern int drive_init(struct drive_opt *arg, int snapshot, void *machine);
+
/* serial ports */
#define MAX_SERIAL_PORTS 4
Index: trunk/vl.c
===================================================================
--- trunk.orig/vl.c
+++ trunk/vl.c
@@ -2162,14 +2162,14 @@ static int drive_get_free_idx(void)
return -1;
}
-static int drive_add(const char *file, const char *fmt, ...)
+int drive_add(const char *file, const char *fmt, ...)
{
va_list ap;
int index = drive_opt_get_free_idx();
if (nb_drives_opt >= MAX_DRIVES || index == -1) {
fprintf(stderr, "qemu: too many drives\n");
- exit(1);
+ return -1;
}
drives_opt[index].file = file;
@@ -2259,8 +2259,7 @@ void drive_uninit(BlockDriverState *bdrv
}
}
-static int drive_init(struct drive_opt *arg, int snapshot,
- QEMUMachine *machine)
+int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
{
char buf[128];
char file[1024];
@@ -2273,6 +2272,7 @@ static int drive_init(struct drive_opt *
int cyls, heads, secs, translation;
BlockDriverState *bdrv;
BlockDriver *drv = NULL;
+ QEMUMachine *machine = opaque;
int max_devs;
int index;
int cache;
@@ -2539,7 +2539,7 @@ static int drive_init(struct drive_opt *
*/
if (drive_get_index(type, bus_id, unit_id) != -1)
- return 0;
+ return -2;
/* init */
@@ -2589,7 +2589,7 @@ static int drive_init(struct drive_opt *
break;
}
if (!file[0])
- return 0;
+ return -2;
bdrv_flags = 0;
if (snapshot) {
bdrv_flags |= BDRV_O_SNAPSHOT;
@@ -2606,7 +2606,7 @@ static int drive_init(struct drive_opt *
file);
return -1;
}
- return 0;
+ return drives_table_idx;
}
/***********************************************************/
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 09/18] qemu: add net_client_uninit / qemu_find_vlan_client
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (7 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 08/18] qemu: net/drive add/remove tweaks Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 10/18] qemu: add cpu_unregister_io_memory and make io mem table index dynamic Marcelo Tosatti
` (8 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: net-client-uninit --]
[-- Type: text/plain, Size: 1843 bytes --]
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/net.c
===================================================================
--- trunk.orig/net.c
+++ trunk/net.c
@@ -368,6 +368,19 @@ void qemu_del_vlan_client(VLANClientStat
pvc = &(*pvc)->next;
}
+VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque)
+{
+ VLANClientState **pvc = &vlan->first_client;
+
+ while (*pvc != NULL)
+ if ((*pvc)->opaque == opaque)
+ return *pvc;
+ else
+ pvc = &(*pvc)->next;
+
+ return NULL;
+}
+
int qemu_can_send_packet(VLANClientState *vc1)
{
VLANState *vlan = vc1->vlan;
@@ -1727,6 +1740,14 @@ int net_client_init(const char *device,
return ret;
}
+void net_client_uninit(NICInfo *nd)
+{
+ nd->vlan->nb_guest_devs--;
+ nb_nics--;
+ nd->used = 0;
+ free((void *)nd->model);
+}
+
int net_client_parse(const char *str)
{
const char *p;
Index: trunk/net.h
===================================================================
--- trunk.orig/net.h
+++ trunk/net.h
@@ -42,6 +42,7 @@ VLANClientState *qemu_new_vlan_client(VL
IOCanRWHandler *fd_can_read,
void *opaque);
void qemu_del_vlan_client(VLANClientState *vc);
+VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque);
int qemu_can_send_packet(VLANClientState *vc);
ssize_t qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov,
int iovcnt);
@@ -94,6 +95,7 @@ void net_checksum_calculate(uint8_t *dat
/* from net.c */
int net_client_init(const char *device, const char *p);
+void net_client_uninit(NICInfo *nd);
int net_client_parse(const char *str);
void net_slirp_smb(const char *exported_dir);
void net_slirp_redir(const char *redir_str);
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 10/18] qemu: add cpu_unregister_io_memory and make io mem table index dynamic
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (8 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 09/18] qemu: add net_client_uninit / qemu_find_vlan_client Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 11/18] qemu: add qemu_free_irqs Marcelo Tosatti
` (7 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: cpu-unregister-io-mem --]
[-- Type: text/plain, Size: 3021 bytes --]
So drivers can clear their mem io table entries on exit back to unassigned
state.
Also make the io mem index allocation dynamic.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/cpu-all.h
===================================================================
--- trunk.orig/cpu-all.h
+++ trunk/cpu-all.h
@@ -909,6 +909,7 @@ int cpu_register_io_memory(int io_index,
CPUReadMemoryFunc **mem_read,
CPUWriteMemoryFunc **mem_write,
void *opaque);
+void cpu_unregister_io_memory(int table_address);
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
Index: trunk/exec.c
===================================================================
--- trunk.orig/exec.c
+++ trunk/exec.c
@@ -179,7 +179,7 @@ static void io_mem_init(void);
CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
void *io_mem_opaque[IO_MEM_NB_ENTRIES];
-static int io_mem_nb;
+char io_mem_used[IO_MEM_NB_ENTRIES];
static int io_mem_watch;
#endif
@@ -2810,12 +2810,28 @@ static void *subpage_init (target_phys_a
return mmio;
}
+static int get_free_io_mem_idx(void)
+{
+ int i;
+
+ for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
+ if (!io_mem_used[i]) {
+ io_mem_used[i] = 1;
+ return i;
+ }
+
+ return -1;
+}
+
static void io_mem_init(void)
{
+ int i;
+
cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
- io_mem_nb = 5;
+ for (i=0; i<5; i++)
+ io_mem_used[i] = 1;
io_mem_watch = cpu_register_io_memory(0, watch_mem_read,
watch_mem_write, NULL);
@@ -2840,9 +2856,9 @@ int cpu_register_io_memory(int io_index,
int i, subwidth = 0;
if (io_index <= 0) {
- if (io_mem_nb >= IO_MEM_NB_ENTRIES)
- return -1;
- io_index = io_mem_nb++;
+ io_index = get_free_io_mem_idx();
+ if (io_index == -1)
+ return io_index;
} else {
if (io_index >= IO_MEM_NB_ENTRIES)
return -1;
@@ -2858,6 +2874,19 @@ int cpu_register_io_memory(int io_index,
return (io_index << IO_MEM_SHIFT) | subwidth;
}
+void cpu_unregister_io_memory(int io_table_address)
+{
+ int i;
+ int io_index = io_table_address >> IO_MEM_SHIFT;
+
+ for (i=0;i < 3; i++) {
+ io_mem_read[io_index][i] = unassigned_mem_read[i];
+ io_mem_write[io_index][i] = unassigned_mem_write[i];
+ }
+ io_mem_opaque[io_index] = NULL;
+ io_mem_used[io_index] = 0;
+}
+
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
{
return io_mem_write[io_index >> IO_MEM_SHIFT];
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 11/18] qemu: add qemu_free_irqs
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (9 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 10/18] qemu: add cpu_unregister_io_memory and make io mem table index dynamic Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 12/18] qemu: add pci_unregister_device Marcelo Tosatti
` (6 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: qemu-free-irqs --]
[-- Type: text/plain, Size: 890 bytes --]
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/hw/irq.c
===================================================================
--- trunk.orig/hw/irq.c
+++ trunk/hw/irq.c
@@ -56,6 +56,12 @@ qemu_irq *qemu_allocate_irqs(qemu_irq_ha
return s;
}
+void qemu_free_irqs(qemu_irq *s)
+{
+ qemu_free(s[0]);
+ qemu_free(s);
+}
+
static void qemu_notirq(void *opaque, int line, int level)
{
struct IRQState *irq = opaque;
Index: trunk/hw/irq.h
===================================================================
--- trunk.orig/hw/irq.h
+++ trunk/hw/irq.h
@@ -27,6 +27,7 @@ static inline void qemu_irq_pulse(qemu_i
/* Returns an array of N IRQs. */
qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
+void qemu_free_irqs(qemu_irq *s);
/* Returns a new IRQ with opposite polarity. */
qemu_irq qemu_irq_invert(qemu_irq irq);
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 12/18] qemu: add pci_unregister_device
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (10 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 11/18] qemu: add qemu_free_irqs Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 13/18] qemu: warn if PCI region is not power of two Marcelo Tosatti
` (5 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: pci-unregister --]
[-- Type: text/plain, Size: 3221 bytes --]
Unregister the pci device, unassign its IO and memory regions, and free
associated data.
Add a callback so drivers can free device state.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/hw/pci.c
===================================================================
--- trunk.orig/hw/pci.c
+++ trunk/hw/pci.c
@@ -198,6 +198,48 @@ PCIDevice *pci_register_device(PCIBus *b
return pci_dev;
}
+static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
+{
+ return addr + pci_mem_base;
+}
+
+static void pci_unregister_io_regions(PCIDevice *pci_dev)
+{
+ PCIIORegion *r;
+ int i;
+
+ for(i = 0; i < PCI_NUM_REGIONS; i++) {
+ r = &pci_dev->io_regions[i];
+ if (!r->size || r->addr == -1)
+ continue;
+ if (r->type == PCI_ADDRESS_SPACE_IO) {
+ isa_unassign_ioport(r->addr, r->size);
+ } else {
+ cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
+ r->size,
+ IO_MEM_UNASSIGNED);
+ }
+ }
+}
+
+int pci_unregister_device(PCIDevice *pci_dev)
+{
+ int ret = 0;
+
+ if (pci_dev->unregister)
+ ret = pci_dev->unregister(pci_dev);
+ if (ret)
+ return ret;
+
+ pci_unregister_io_regions(pci_dev);
+
+ qemu_free_irqs(pci_dev->irq);
+ pci_irq_index--;
+ pci_dev->bus->devices[pci_dev->devfn] = NULL;
+ qemu_free(pci_dev);
+ return 0;
+}
+
void pci_register_io_region(PCIDevice *pci_dev, int region_num,
uint32_t size, int type,
PCIMapIORegionFunc *map_func)
@@ -220,11 +262,6 @@ void pci_register_io_region(PCIDevice *p
*(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
}
-static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
-{
- return addr + pci_mem_base;
-}
-
static void pci_update_mappings(PCIDevice *d)
{
PCIIORegion *r;
Index: trunk/hw/pci.h
===================================================================
--- trunk.orig/hw/pci.h
+++ trunk/hw/pci.h
@@ -125,6 +125,7 @@ typedef uint32_t PCIConfigReadFunc(PCIDe
uint32_t address, int len);
typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
uint32_t addr, uint32_t size, int type);
+typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
#define PCI_ADDRESS_SPACE_MEM 0x00
#define PCI_ADDRESS_SPACE_IO 0x01
@@ -189,6 +190,7 @@ struct PCIDevice {
/* do not access the following fields */
PCIConfigReadFunc *config_read;
PCIConfigWriteFunc *config_write;
+ PCIUnregisterFunc *unregister;
/* ??? This is a PC-specific hack, and should be removed. */
int irq_index;
@@ -203,6 +205,7 @@ PCIDevice *pci_register_device(PCIBus *b
int instance_size, int devfn,
PCIConfigReadFunc *config_read,
PCIConfigWriteFunc *config_write);
+int pci_unregister_device(PCIDevice *pci_dev);
void pci_register_io_region(PCIDevice *pci_dev, int region_num,
uint32_t size, int type,
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 13/18] qemu: warn if PCI region is not power of two
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (11 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 12/18] qemu: add pci_unregister_device Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 14:38 ` Paul Brook
2009-02-04 13:33 ` [Qemu-devel] [patch 14/18] qemu: LSI SCSI and e1000 unregister callbacks Marcelo Tosatti
` (4 subsequent siblings)
17 siblings, 1 reply; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: pci-warning-size --]
[-- Type: text/plain, Size: 634 bytes --]
Otherwise the PCI size for such regions can be calculated erroneously.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/hw/pci.c
===================================================================
--- trunk.orig/hw/pci.c
+++ trunk/hw/pci.c
@@ -249,6 +249,11 @@ void pci_register_io_region(PCIDevice *p
if ((unsigned int)region_num >= PCI_NUM_REGIONS)
return;
+
+ if (size & (size-1))
+ term_printf("WARNING: PCI region size must be pow2 "
+ "type=0x%x, size=0x%x\n", type, size);
+
r = &pci_dev->io_regions[region_num];
r->addr = -1;
r->size = size;
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 14/18] qemu: LSI SCSI and e1000 unregister callbacks
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (12 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 13/18] qemu: warn if PCI region is not power of two Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 15/18] qemu: zero ioport_opaque on isa_unassign_ioport Marcelo Tosatti
` (3 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: lsi-and-e1000-unregister --]
[-- Type: text/plain, Size: 1599 bytes --]
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/hw/e1000.c
===================================================================
--- trunk.orig/hw/e1000.c
+++ trunk/hw/e1000.c
@@ -1034,6 +1034,16 @@ e1000_mmio_map(PCIDevice *pci_dev, int r
excluded_regs[i] - 4);
}
+static int
+pci_e1000_uninit(PCIDevice *dev)
+{
+ E1000State *d = (E1000State *) dev;
+
+ cpu_unregister_io_memory(d->mmio_index);
+
+ return 0;
+}
+
PCIDevice *
pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
{
@@ -1092,6 +1102,7 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd,
qemu_format_nic_info_str(d->vc, d->nd->macaddr);
register_savevm(info_str, -1, 2, nic_save, nic_load, d);
+ d->dev.unregister = pci_e1000_uninit;
return (PCIDevice *)d;
}
Index: trunk/hw/lsi53c895a.c
===================================================================
--- trunk.orig/hw/lsi53c895a.c
+++ trunk/hw/lsi53c895a.c
@@ -1962,6 +1962,18 @@ void lsi_scsi_attach(void *opaque, Block
bd->private = &s->pci_dev;
}
+static int lsi_scsi_uninit(PCIDevice *d)
+{
+ LSIState *s = (LSIState *) d;
+
+ cpu_unregister_io_memory(s->mmio_io_addr);
+ cpu_unregister_io_memory(s->ram_io_addr);
+
+ qemu_free(s->queue);
+
+ return 0;
+}
+
void *lsi_scsi_init(PCIBus *bus, int devfn)
{
LSIState *s;
@@ -2004,6 +2016,7 @@ void *lsi_scsi_init(PCIBus *bus, int dev
s->queue = qemu_malloc(sizeof(lsi_queue));
s->queue_len = 1;
s->active_commands = 0;
+ s->pci_dev.unregister = lsi_scsi_uninit;
lsi_soft_reset(s);
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 15/18] qemu: zero ioport_opaque on isa_unassign_ioport
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (13 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 14/18] qemu: LSI SCSI and e1000 unregister callbacks Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 16/18] qemu: initialize hot add system / acpi gpe Marcelo Tosatti
` (2 subsequent siblings)
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: zero-ioport-opaque --]
[-- Type: text/plain, Size: 542 bytes --]
If the io port is unassigned, the previous private pointer is
meaningless.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/vl.c
===================================================================
--- trunk.orig/vl.c
+++ trunk/vl.c
@@ -404,6 +404,8 @@ void isa_unassign_ioport(int start, int
ioport_write_table[0][i] = default_ioport_writeb;
ioport_write_table[1][i] = default_ioport_writew;
ioport_write_table[2][i] = default_ioport_writel;
+
+ ioport_opaque[i] = NULL;
}
}
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 16/18] qemu: initialize hot add system / acpi gpe
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (14 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 15/18] qemu: zero ioport_opaque on isa_unassign_ioport Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 17/18] qemu: pci hotplug GPE support Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove Marcelo Tosatti
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: gpe --]
[-- Type: text/plain, Size: 2776 bytes --]
ACPI GPE support, used by PCI (and CPU) hotplug.
From: Glauber Costa <gcosta@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/hw/acpi.c
===================================================================
--- trunk.orig/hw/acpi.c
+++ trunk/hw/acpi.c
@@ -561,3 +561,71 @@ void qemu_system_powerdown(void)
}
}
#endif
+
+#define GPE_BASE 0xafe0
+
+struct gpe_regs {
+ uint16_t sts; /* status */
+ uint16_t en; /* enabled */
+};
+
+static struct gpe_regs gpe;
+
+static uint32_t gpe_readb(void *opaque, uint32_t addr)
+{
+ uint32_t val = 0;
+ struct gpe_regs *g = opaque;
+ switch (addr) {
+ case GPE_BASE:
+ val = g->sts & 0xFF;
+ break;
+ case GPE_BASE + 1:
+ val = (g->sts >> 8) & 0xFF;
+ break;
+ case GPE_BASE + 2:
+ val = g->en & 0xFF;
+ break;
+ case GPE_BASE + 3:
+ val = (g->en >> 8) & 0xFF;
+ break;
+ default:
+ break;
+ }
+
+#if defined(DEBUG)
+ printf("gpe read %lx == %lx\n", addr, val);
+#endif
+ return val;
+}
+
+static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ struct gpe_regs *g = opaque;
+ switch (addr) {
+ case GPE_BASE:
+ g->sts = (g->sts & ~0xFFFF) | (val & 0xFFFF);
+ break;
+ case GPE_BASE + 1:
+ g->sts = (g->sts & 0xFFFF) | (val << 8);
+ break;
+ case GPE_BASE + 2:
+ g->en = (g->en & ~0xFFFF) | (val & 0xFFFF);
+ break;
+ case GPE_BASE + 3:
+ g->en = (g->en & 0xFFFF) | (val << 8);
+ break;
+ default:
+ break;
+ }
+
+#if defined(DEBUG)
+ printf("gpe write %lx <== %d\n", addr, val);
+#endif
+}
+
+void qemu_system_hot_add_init(void)
+{
+ register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe);
+ register_ioport_read(GPE_BASE, 4, 1, gpe_readb, &gpe);
+
+}
Index: trunk/hw/pc.c
===================================================================
--- trunk.orig/hw/pc.c
+++ trunk/hw/pc.c
@@ -1010,6 +1010,8 @@ vga_bios_error:
pci_nic_init(pci_bus, nd, -1, "ne2k_pci");
}
+ qemu_system_hot_add_init();
+
if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
fprintf(stderr, "qemu: too many IDE bus\n");
exit(1);
Index: trunk/sysemu.h
===================================================================
--- trunk.orig/sysemu.h
+++ trunk/sysemu.h
@@ -166,6 +166,9 @@ extern int nb_drives_opt;
extern int drive_add(const char *file, const char *fmt, ...);
extern int drive_init(struct drive_opt *arg, int snapshot, void *machine);
+/* acpi */
+void qemu_system_hot_add_init(void);
+
/* serial ports */
#define MAX_SERIAL_PORTS 4
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 17/18] qemu: pci hotplug GPE support
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (15 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 16/18] qemu: initialize hot add system / acpi gpe Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove Marcelo Tosatti
17 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: gpe-pci-hotplug --]
[-- Type: text/plain, Size: 3390 bytes --]
Enable the corresponding bit on the PCIST region and trigger the SCI
and handle the _EJ0 notifications.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/hw/acpi.c
===================================================================
--- trunk.orig/hw/acpi.c
+++ trunk/hw/acpi.c
@@ -563,13 +563,21 @@ void qemu_system_powerdown(void)
#endif
#define GPE_BASE 0xafe0
+#define PCI_BASE 0xae00
+#define PCI_EJ_BASE 0xae08
struct gpe_regs {
uint16_t sts; /* status */
uint16_t en; /* enabled */
};
+struct pci_status {
+ uint32_t up;
+ uint32_t down;
+};
+
static struct gpe_regs gpe;
+static struct pci_status pci0_status;
static uint32_t gpe_readb(void *opaque, uint32_t addr)
{
@@ -623,9 +631,95 @@ static void gpe_writeb(void *opaque, uin
#endif
}
+static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
+{
+ uint32_t val = 0;
+ struct pci_status *g = opaque;
+ switch (addr) {
+ case PCI_BASE:
+ val = g->up;
+ break;
+ case PCI_BASE + 4:
+ val = g->down;
+ break;
+ default:
+ break;
+ }
+
+#if defined(DEBUG)
+ printf("pcihotplug read %lx == %lx\n", addr, val);
+#endif
+ return val;
+}
+
+static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ struct pci_status *g = opaque;
+ switch (addr) {
+ case PCI_BASE:
+ g->up = val;
+ break;
+ case PCI_BASE + 4:
+ g->down = val;
+ break;
+ }
+
+#if defined(DEBUG)
+ printf("pcihotplug write %lx <== %d\n", addr, val);
+#endif
+}
+
+static uint32_t pciej_read(void *opaque, uint32_t addr)
+{
+#if defined(DEBUG)
+ printf("pciej read %lx == %lx\n", addr, val);
+#endif
+ return 0;
+}
+
+static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ int slot = ffs(val) - 1;
+
+#if defined(DEBUG)
+ printf("pciej write %lx <== %d\n", addr, val);
+#endif
+}
+
void qemu_system_hot_add_init(void)
{
register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe);
register_ioport_read(GPE_BASE, 4, 1, gpe_readb, &gpe);
+ register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status);
+ register_ioport_read(PCI_BASE, 8, 4, pcihotplug_read, &pci0_status);
+
+ register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, NULL);
+ register_ioport_read(PCI_EJ_BASE, 4, 4, pciej_read, NULL);
+}
+
+static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
+{
+ g->sts |= 2;
+ g->en |= 2;
+ p->up |= (1 << slot);
+}
+
+static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
+{
+ g->sts |= 2;
+ g->en |= 2;
+ p->down |= (1 << slot);
+}
+
+void qemu_system_device_hot_add(int bus, int slot, int state)
+{
+ qemu_set_irq(pm_state->irq, 1);
+ pci0_status.up = 0;
+ pci0_status.down = 0;
+ if (state)
+ enable_device(&pci0_status, &gpe, slot);
+ else
+ disable_device(&pci0_status, &gpe, slot);
+ qemu_set_irq(pm_state->irq, 0);
}
Index: trunk/sysemu.h
===================================================================
--- trunk.orig/sysemu.h
+++ trunk/sysemu.h
@@ -168,6 +168,7 @@ extern int drive_init(struct drive_opt *
/* acpi */
void qemu_system_hot_add_init(void);
+void qemu_system_device_hot_add(int pcibus, int slot, int state);
/* serial ports */
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
` (16 preceding siblings ...)
2009-02-04 13:33 ` [Qemu-devel] [patch 17/18] qemu: pci hotplug GPE support Marcelo Tosatti
@ 2009-02-04 13:33 ` Marcelo Tosatti
2009-02-04 14:38 ` Daniel P. Berrange
` (3 more replies)
17 siblings, 4 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-04 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
[-- Attachment #1: dev-and-disk-hotadd --]
[-- Type: text/plain, Size: 13181 bytes --]
Add monitor command to hot-add PCI devices (nic and storage).
Syntax is:
pci_add pcibus nic|storage params
It returns the bus slot and function for the newly added device on success.
It is possible to attach a disk to a device after PCI initialization via
the drive_add command. If so, a manual scan of the SCSI bus on the guest
is necessary.
Save QEMUMachine necessary for drive_init.
Add monitor command to hot-remove devices, remove device data on _EJ0 notification.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/Makefile.target
===================================================================
--- trunk.orig/Makefile.target
+++ trunk/Makefile.target
@@ -580,6 +580,7 @@ OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
+OBJS += device-hotplug.o
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
endif
ifeq ($(TARGET_BASE_ARCH), ppc)
Index: trunk/hw/boards.h
===================================================================
--- trunk.orig/hw/boards.h
+++ trunk/hw/boards.h
@@ -25,6 +25,8 @@ typedef struct QEMUMachine {
int qemu_register_machine(QEMUMachine *m);
void register_machines(void);
+extern QEMUMachine *current_machine;
+
/* Axis ETRAX. */
extern QEMUMachine bareetraxfs_machine;
extern QEMUMachine axisdev88_machine;
Index: trunk/hw/device-hotplug.c
===================================================================
--- /dev/null
+++ trunk/hw/device-hotplug.c
@@ -0,0 +1,237 @@
+#include "hw.h"
+#include "boards.h"
+#include "pci.h"
+#include "net.h"
+#include "sysemu.h"
+#include "pc.h"
+#include "console.h"
+#include "block_int.h"
+#include "virtio-blk.h"
+
+#define PCI_BASE_CLASS_STORAGE 0x01
+#define PCI_BASE_CLASS_NETWORK 0x02
+
+#if defined(TARGET_I386) || defined(TARGET_X86_64)
+static PCIDevice *qemu_system_hot_add_nic(const char *opts, int bus_nr)
+{
+ int ret;
+ PCIBus *pci_bus;
+
+ pci_bus = pci_find_bus (bus_nr);
+ if (!pci_bus) {
+ term_printf ("Can't find pci_bus %d\n", bus_nr);
+ return NULL;
+ }
+
+ ret = net_client_init ("nic", opts);
+ if (ret < 0 || !nd_table[ret].model)
+ return NULL;
+ return pci_nic_init (pci_bus, &nd_table[ret], -1, "rtl8139");
+}
+
+static int add_init_drive(const char *opts)
+{
+ int drive_opt_idx, drive_idx;
+ int ret = -1;
+
+ drive_opt_idx = drive_add(NULL, "%s", opts);
+ if (!drive_opt_idx)
+ return ret;
+
+ drive_idx = drive_init(&drives_opt[drive_opt_idx], 0, current_machine);
+ if (drive_idx == -1) {
+ drive_remove(drive_opt_idx);
+ return ret;
+ }
+
+ return drive_idx;
+}
+
+void drive_hot_add(int pcibus, const char *devfn_string, const char *opts)
+{
+ int drive_idx, type, bus;
+ int devfn;
+ int success = 0;
+ PCIDevice *dev;
+
+ devfn = strtoul(devfn_string, NULL, 0);
+
+ dev = pci_find_device(pcibus, PCI_SLOT(devfn));
+ if (!dev) {
+ term_printf("no pci device with devfn %d (slot %d)\n", devfn,
+ PCI_SLOT(devfn));
+ return;
+ }
+
+ drive_idx = add_init_drive(opts);
+ if (drive_idx < 0)
+ return;
+ type = drives_table[drive_idx].type;
+ bus = drive_get_max_bus (type);
+
+ switch (type) {
+ case IF_SCSI:
+ success = 1;
+ lsi_scsi_attach (dev, drives_table[drive_idx].bdrv,
+ drives_table[drive_idx].unit);
+ break;
+ default:
+ term_printf("Can't hot-add drive to type %d\n", type);
+ }
+
+ if (success)
+ term_printf("OK bus %d, unit %d\n", drives_table[drive_idx].bus,
+ drives_table[drive_idx].unit);
+ return;
+}
+
+static PCIDevice *qemu_system_hot_add_storage(const char *opts, int bus_nr)
+{
+ void *opaque = NULL;
+ PCIBus *pci_bus;
+ int type = -1, drive_idx = -1;
+ char buf[128];
+
+ pci_bus = pci_find_bus(bus_nr);
+ if (!pci_bus) {
+ term_printf("Can't find pci_bus %d\n", bus_nr);
+ return NULL;
+ }
+
+ if (get_param_value(buf, sizeof(buf), "if", opts)) {
+ if (!strcmp(buf, "scsi"))
+ type = IF_SCSI;
+ else if (!strcmp(buf, "virtio")) {
+ type = IF_VIRTIO;
+ }
+ } else {
+ term_printf("no if= specified\n");
+ return NULL;
+ }
+
+ if (get_param_value(buf, sizeof(buf), "file", opts)) {
+ drive_idx = add_init_drive(opts);
+ if (drive_idx < 0)
+ return NULL;
+ } else if (type == IF_VIRTIO) {
+ term_printf("virtio requires a backing file/device.\n");
+ return NULL;
+ }
+
+ switch (type) {
+ case IF_SCSI:
+ opaque = lsi_scsi_init (pci_bus, -1);
+ if (opaque && drive_idx >= 0)
+ lsi_scsi_attach (opaque, drives_table[drive_idx].bdrv,
+ drives_table[drive_idx].unit);
+ break;
+ case IF_VIRTIO:
+ opaque = virtio_blk_init (pci_bus, drives_table[drive_idx].bdrv);
+ break;
+ default:
+ term_printf ("type %s not a hotpluggable PCI device.\n", buf);
+ }
+
+ return opaque;
+}
+
+void device_hot_add(int pcibus, const char *type, const char *opts)
+{
+ PCIDevice *dev = NULL;
+
+ if (strcmp(type, "nic") == 0)
+ dev = qemu_system_hot_add_nic(opts, pcibus);
+ else if (strcmp(type, "storage") == 0)
+ dev = qemu_system_hot_add_storage(opts, pcibus);
+ else
+ term_printf("invalid type: %s\n", type);
+
+ if (dev) {
+ qemu_system_device_hot_add(pcibus, PCI_SLOT(dev->devfn), 1);
+ term_printf("OK bus %d, slot %d, function %d (devfn %d)\n",
+ pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), dev->devfn);
+ } else
+ term_printf("failed to add %s\n", opts);
+}
+#endif
+
+void device_hot_remove(int pcibus, int slot)
+{
+ PCIDevice *d = pci_find_device(pcibus, slot);
+
+ if (!d) {
+ term_printf("invalid slot %d\n", slot);
+ return;
+ }
+
+ qemu_system_device_hot_add(pcibus, slot, 0);
+}
+
+static void destroy_nic(int slot)
+{
+ int i;
+ PCIDevice *dev;
+
+ for (i = 0; i < MAX_NICS; i++)
+ if (nd_table[i].used) {
+ dev = nd_table[i].private;
+ if (dev && PCI_SLOT(dev->devfn) == slot) {
+ if (nd_table[i].vlan) {
+ VLANClientState *vc;
+ vc = qemu_find_vlan_client(nd_table[i].vlan,
+ nd_table[i].private);
+ if (vc)
+ qemu_del_vlan_client(vc);
+ }
+ net_client_uninit(&nd_table[i]);
+ }
+ }
+}
+
+static void destroy_bdrvs(int slot)
+{
+ int i;
+ struct BlockDriverState *bs;
+ PCIDevice *dev;
+
+ for (i = 0; i <= MAX_DRIVES; i++) {
+ bs = drives_table[i].bdrv;
+ if (bs) {
+ dev = bs->private;
+ if (dev && PCI_SLOT(dev->devfn) == slot) {
+ drive_uninit(bs);
+ bdrv_delete(bs);
+ }
+ }
+ }
+}
+
+/*
+ * OS has executed _EJ0 method, we now can remove the device
+ */
+void device_hot_remove_success(int pcibus, int slot)
+{
+ PCIDevice *d = pci_find_device(pcibus, slot);
+ int class_code;
+
+ if (!d) {
+ term_printf("invalid slot %d\n", slot);
+ return;
+ }
+
+ class_code = d->config_read(d, PCI_CLASS_DEVICE+1, 1);
+
+ pci_unregister_device(d);
+
+ switch(class_code) {
+ case PCI_BASE_CLASS_STORAGE:
+ destroy_bdrvs(slot);
+ break;
+ case PCI_BASE_CLASS_NETWORK:
+ destroy_nic(slot);
+ break;
+ }
+
+}
+
Index: trunk/monitor.c
===================================================================
--- trunk.orig/monitor.c
+++ trunk/monitor.c
@@ -1515,6 +1515,19 @@ static const term_cmd_t term_cmds[] = {
"", "cancel the current VM migration" },
{ "migrate_set_speed", "s", do_migrate_set_speed,
"value", "set maximum speed (in bytes) for migrations" },
+#if defined(TARGET_I386)
+ { "drive_add", "iss", drive_hot_add, "pcibus pcidevfn [file=file][,if=type][,bus=n]\n"
+ "[,unit=m][,media=d][index=i]\n"
+ "[,cyls=c,heads=h,secs=s[,trans=t]]\n"
+ "[snapshot=on|off][,cache=on|off]",
+ "add drive to PCI storage controller" },
+ { "pci_add", "iss", device_hot_add, "bus nic|storage [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]...", "hot-add PCI device" },
+ { "pci_del", "ii", device_hot_remove, "bus slot-number", "hot remove PCI device" },
+ { "host_net_add", "ss", net_host_device_add,
+ "[tap,user,socket,vde] options", "add host VLAN client" },
+ { "host_net_remove", "is", net_host_device_remove,
+ "vlan_id name", "remove host VLAN client" },
+#endif
{ "balloon", "i", do_balloon,
"target", "request VM to change it's memory allocation (in MB)" },
{ "set_link", "ss", do_set_link, "name [up|down]" },
Index: trunk/sysemu.h
===================================================================
--- trunk.orig/sysemu.h
+++ trunk/sysemu.h
@@ -170,6 +170,12 @@ extern int drive_init(struct drive_opt *
void qemu_system_hot_add_init(void);
void qemu_system_device_hot_add(int pcibus, int slot, int state);
+/* device-hotplug */
+void device_hot_add(int pcibus, const char *type, const char *opts);
+void drive_hot_add(int pcibus, const char *devfn_string, const char *opts);
+void device_hot_remove(int pcibus, int slot);
+void device_hot_remove_success(int pcibus, int slot);
+
/* serial ports */
#define MAX_SERIAL_PORTS 4
Index: trunk/vl.c
===================================================================
--- trunk.orig/vl.c
+++ trunk/vl.c
@@ -3419,6 +3419,7 @@ static void qemu_bh_update_timeout(int *
/* machine registration */
static QEMUMachine *first_machine = NULL;
+QEMUMachine *current_machine = NULL;
int qemu_register_machine(QEMUMachine *m)
{
@@ -5603,6 +5604,8 @@ int main(int argc, char **argv, char **e
machine->init(ram_size, vga_ram_size, boot_devices,
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
+ current_machine = machine;
+
/* Set KVM's vcpu state to qemu's initial CPUState. */
if (kvm_enabled()) {
int ret;
Index: trunk/hw/acpi.c
===================================================================
--- trunk.orig/hw/acpi.c
+++ trunk/hw/acpi.c
@@ -679,8 +679,12 @@ static uint32_t pciej_read(void *opaque,
static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
{
+#if defined (TARGET_I386)
int slot = ffs(val) - 1;
+ device_hot_remove_success(0, slot);
+#endif
+
#if defined(DEBUG)
printf("pciej write %lx <== %d\n", addr, val);
#endif
Index: trunk/net.c
===================================================================
--- trunk.orig/net.c
+++ trunk/net.c
@@ -1748,6 +1748,59 @@ void net_client_uninit(NICInfo *nd)
free((void *)nd->model);
}
+static int net_host_check_device(const char *device)
+{
+ int i;
+ const char *valid_param_list[] = { "tap", "user", "socket"
+#ifdef CONFIG_VDE
+ ,"vde"
+#endif
+ };
+ for (i = 0; i < sizeof(valid_param_list) / sizeof(char *); i++) {
+ if (!strncmp(valid_param_list[i], device,
+ strlen(valid_param_list[i])))
+ return 1;
+ }
+
+ return 0;
+}
+
+void net_host_device_add(const char *device, const char *opts)
+{
+ if (!net_host_check_device(device)) {
+ term_printf("invalid host network device %s\n", device);
+ return;
+ }
+ net_client_init(device, opts);
+}
+
+void net_host_device_remove(int vlan_id, const char *device)
+{
+ VLANState *vlan;
+ VLANClientState *vc;
+
+ if (!net_host_check_device(device)) {
+ term_printf("invalid host network device %s\n", device);
+ return;
+ }
+
+ vlan = qemu_find_vlan(vlan_id);
+ if (!vlan) {
+ term_printf("can't find vlan %d\n", vlan_id);
+ return;
+ }
+
+ for(vc = vlan->first_client; vc != NULL; vc = vc->next)
+ if (!strcmp(vc->name, device))
+ break;
+
+ if (!vc) {
+ term_printf("can't find device %s\n", device);
+ return;
+ }
+ qemu_del_vlan_client(vc);
+}
+
int net_client_parse(const char *str)
{
const char *p;
Index: trunk/net.h
===================================================================
--- trunk.orig/net.h
+++ trunk/net.h
@@ -102,6 +102,8 @@ void net_slirp_redir(const char *redir_s
void net_cleanup(void);
int slirp_is_inited(void);
void net_client_check(void);
+void net_host_device_add(const char *device, const char *opts);
+void net_host_device_remove(int vlan_id, const char *device);
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
--
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 13/18] qemu: warn if PCI region is not power of two
2009-02-04 13:33 ` [Qemu-devel] [patch 13/18] qemu: warn if PCI region is not power of two Marcelo Tosatti
@ 2009-02-04 14:38 ` Paul Brook
2009-02-06 17:34 ` Marcelo Tosatti
0 siblings, 1 reply; 34+ messages in thread
From: Paul Brook @ 2009-02-04 14:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
On Wednesday 04 February 2009, Marcelo Tosatti wrote:
> Otherwise the PCI size for such regions can be calculated erroneously.
>
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
> Index: trunk/hw/pci.c
> ===================================================================
> --- trunk.orig/hw/pci.c
> +++ trunk/hw/pci.c
> @@ -249,6 +249,11 @@ void pci_register_io_region(PCIDevice *p
>
> if ((unsigned int)region_num >= PCI_NUM_REGIONS)
> return;
> +
> + if (size & (size-1))
> + term_printf("WARNING: PCI region size must be pow2 "
> + "type=0x%x, size=0x%x\n", type, size);
> +
This should be an error. It is a requirement of the PCI spec, and not
something that's user configurable. Any odd sizes indicate a fairly serious
bug elsewhere in qemu.
Paul
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove
2009-02-04 13:33 ` [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove Marcelo Tosatti
@ 2009-02-04 14:38 ` Daniel P. Berrange
2009-02-04 15:21 ` Anthony Liguori
2009-02-04 14:59 ` Paul Brook
` (2 subsequent siblings)
3 siblings, 1 reply; 34+ messages in thread
From: Daniel P. Berrange @ 2009-02-04 14:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
On Wed, Feb 04, 2009 at 11:33:21AM -0200, Marcelo Tosatti wrote:
> Add monitor command to hot-add PCI devices (nic and storage).
>
> Syntax is:
>
> pci_add pcibus nic|storage params
>
> It returns the bus slot and function for the newly added device on success.
>
> It is possible to attach a disk to a device after PCI initialization via
> the drive_add command. If so, a manual scan of the SCSI bus on the guest
> is necessary.
>
> Save QEMUMachine necessary for drive_init.
>
> Add monitor command to hot-remove devices, remove device data on _EJ0 notification.
Does this allow for hot-add of host TAP devices passing a open
file descriptor across with SCM_RIGHTS (man 7 unix) on the UNIX
domain socket connection to the monitor ? This ability is
critical for libvirt, because we need to be able to allocate the
TAP devices ourselves & do various configuration tasks before giving
them to QEMU - the external script capability isn't suitable /flexible
enough for this.
Regards,
Daniel
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 01/18] qemu: add pci helper functions
2009-02-04 13:33 ` [Qemu-devel] [patch 01/18] qemu: add pci helper functions Marcelo Tosatti
@ 2009-02-04 14:56 ` Paul Brook
2009-02-04 19:15 ` Anthony Liguori
0 siblings, 1 reply; 34+ messages in thread
From: Paul Brook @ 2009-02-04 14:56 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
On Wednesday 04 February 2009, Marcelo Tosatti wrote:
> +PCIDevice *pci_find_device(int bus_num, int slot)
> +{
> + int devfn;
> + PCIDevice *d;
> + PCIBus *bus = pci_find_bus(bus_num);
> +
> + if (!bus)
> + return NULL;
> +
> + for(devfn = 0; devfn < 256; devfn++) {
> + d = bus->devices[devfn];
> + if (d && PCI_SLOT(devfn) == slot)
> + return d;
> + }
> + return NULL;
> +}
This loop is bogus. You already know the devfn from the slot.
It's also completely busted if you have multifunction devices.
Paul
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove
2009-02-04 13:33 ` [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove Marcelo Tosatti
2009-02-04 14:38 ` Daniel P. Berrange
@ 2009-02-04 14:59 ` Paul Brook
2009-02-04 16:17 ` Markus Armbruster
2009-02-04 17:47 ` Blue Swirl
3 siblings, 0 replies; 34+ messages in thread
From: Paul Brook @ 2009-02-04 14:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
On Wednesday 04 February 2009, Marcelo Tosatti wrote:
> Add monitor command to hot-add PCI devices (nic and storage).
I'd prefer to separate the PCI hotplug stuff from the generic hotplug stuff.
Paul
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove
2009-02-04 14:38 ` Daniel P. Berrange
@ 2009-02-04 15:21 ` Anthony Liguori
2009-02-04 15:37 ` Daniel P. Berrange
2009-02-04 15:59 ` Avi Kivity
0 siblings, 2 replies; 34+ messages in thread
From: Anthony Liguori @ 2009-02-04 15:21 UTC (permalink / raw)
To: Daniel P. Berrange, qemu-devel; +Cc: Marcelo Tosatti
Daniel P. Berrange wrote:
> On Wed, Feb 04, 2009 at 11:33:21AM -0200, Marcelo Tosatti wrote:
>
>> Add monitor command to hot-add PCI devices (nic and storage).
>>
>> Syntax is:
>>
>> pci_add pcibus nic|storage params
>>
>> It returns the bus slot and function for the newly added device on success.
>>
>> It is possible to attach a disk to a device after PCI initialization via
>> the drive_add command. If so, a manual scan of the SCSI bus on the guest
>> is necessary.
>>
>> Save QEMUMachine necessary for drive_init.
>>
>> Add monitor command to hot-remove devices, remove device data on _EJ0 notification.
>>
>
> Does this allow for hot-add of host TAP devices passing a open
> file descriptor across with SCM_RIGHTS (man 7 unix) on the UNIX
> domain socket connection to the monitor ? This ability is
> critical for libvirt, because we need to be able to allocate the
> TAP devices ourselves & do various configuration tasks before giving
> them to QEMU - the external script capability isn't suitable /flexible
> enough for this.
>
It doesn't support this today but additional patches to enable that are
certainly welcome. The best way would be a generic mechanism to send a
file descriptor to QEMU that could then be used anywhere fd= is valid.
For instance:
(qemu) receivefd unix:foo.sock,server
fd=5
(qemu) closefd 5
Regards,
Anthony Liguori
> Regards,
> Daniel
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove
2009-02-04 15:21 ` Anthony Liguori
@ 2009-02-04 15:37 ` Daniel P. Berrange
2009-02-04 15:59 ` Avi Kivity
1 sibling, 0 replies; 34+ messages in thread
From: Daniel P. Berrange @ 2009-02-04 15:37 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Marcelo Tosatti, qemu-devel
On Wed, Feb 04, 2009 at 09:21:03AM -0600, Anthony Liguori wrote:
> Daniel P. Berrange wrote:
> >On Wed, Feb 04, 2009 at 11:33:21AM -0200, Marcelo Tosatti wrote:
> >
> >>Add monitor command to hot-add PCI devices (nic and storage).
> >>
> >>Syntax is:
> >>
> >>pci_add pcibus nic|storage params
> >>
> >>It returns the bus slot and function for the newly added device on
> >>success.
> >>
> >>It is possible to attach a disk to a device after PCI initialization via
> >>the drive_add command. If so, a manual scan of the SCSI bus on the guest
> >>is necessary.
> >>
> >>Save QEMUMachine necessary for drive_init.
> >>
> >>Add monitor command to hot-remove devices, remove device data on _EJ0
> >>notification.
> >>
> >
> >Does this allow for hot-add of host TAP devices passing a open
> >file descriptor across with SCM_RIGHTS (man 7 unix) on the UNIX
> >domain socket connection to the monitor ? This ability is
> >critical for libvirt, because we need to be able to allocate the
> >TAP devices ourselves & do various configuration tasks before giving
> >them to QEMU - the external script capability isn't suitable /flexible
> >enough for this.
> >
>
> It doesn't support this today but additional patches to enable that are
> certainly welcome. The best way would be a generic mechanism to send a
> file descriptor to QEMU that could then be used anywhere fd= is valid.
> For instance:
>
> (qemu) receivefd unix:foo.sock,server
> fd=5
> (qemu) closefd 5
I think this is a bit of an unpleasent way to interact. There should be no
need for the user of the monitor to know or care about the FD number
from QEMU's side. When running the 'host_net_add' command QEMU should be
able to see that it is being asked to use an FD, and automatically receive
it at this time. This avoids need for user of the monitor to run separate
commands, and worry about closing the FD if something fails in the 2nd
command, and avoids having to parse the receivefd command, and splice
that into the next command. eg I'd expect that
(qemu) host_net_add tap,fd=,vlan=9,ifname=vnet3
should see the empty 'fd=' arg and just 'do the right thing' by using
SCM_RIGHTS to fetch the FD.
Or could we avoid the FD passing, and just rely on giving an 'ifname'
that already exists, and expect QEMU to open this existing named TAP
device ? Though there may be difficulties with transfering "ownership"
of the TAP device, to ensure it disappears when QEMU quits, rather
than when the monitor caller quits.
Regards,
Daniel
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove
2009-02-04 15:21 ` Anthony Liguori
2009-02-04 15:37 ` Daniel P. Berrange
@ 2009-02-04 15:59 ` Avi Kivity
2009-02-04 16:46 ` Anthony Liguori
1 sibling, 1 reply; 34+ messages in thread
From: Avi Kivity @ 2009-02-04 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
Anthony Liguori wrote:
>
> It doesn't support this today but additional patches to enable that
> are certainly welcome. The best way would be a generic mechanism to
> send a file descriptor to QEMU that could then be used anywhere fd= is
> valid. For instance:
>
> (qemu) receivefd unix:foo.sock,server
> fd=5
> (qemu) closefd 5
(qemu) receivefd myfd
// qemu receives an fd over the monitor, and attaches it to the tag 'myfd'
(qemu) closefd myfd
// qemu closes the fd attached to tag 'myfd'
Advantages:
- no runtime handshaking with a new socket
- work with names, not numbers you need to read off the monitor
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove
2009-02-04 13:33 ` [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove Marcelo Tosatti
2009-02-04 14:38 ` Daniel P. Berrange
2009-02-04 14:59 ` Paul Brook
@ 2009-02-04 16:17 ` Markus Armbruster
2009-02-04 17:47 ` Blue Swirl
3 siblings, 0 replies; 34+ messages in thread
From: Markus Armbruster @ 2009-02-04 16:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
Marcelo Tosatti <mtosatti@redhat.com> writes:
> Add monitor command to hot-add PCI devices (nic and storage).
>
> Syntax is:
>
> pci_add pcibus nic|storage params
I'd prefer a more future-proof syntax here. Eventually, we'll want to
be able to specify the full PCI device address, consisting of domain,
bus and dev (func makes no sense here). The common syntax for that is
"<domain>:<bus>:<dev>", with numbers in hexadecimal. I figure we'll
want to make parts optional for convenience, and have some syntax to
let QEMU pick the <dev>.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove
2009-02-04 15:59 ` Avi Kivity
@ 2009-02-04 16:46 ` Anthony Liguori
0 siblings, 0 replies; 34+ messages in thread
From: Anthony Liguori @ 2009-02-04 16:46 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
Avi Kivity wrote:
> Anthony Liguori wrote:
>>
>> It doesn't support this today but additional patches to enable that
>> are certainly welcome. The best way would be a generic mechanism to
>> send a file descriptor to QEMU that could then be used anywhere fd=
>> is valid. For instance:
>>
>> (qemu) receivefd unix:foo.sock,server
>> fd=5
>> (qemu) closefd 5
>
> (qemu) receivefd myfd
> // qemu receives an fd over the monitor, and attaches it to the tag
> 'myfd'
Completely reasonable, but it's going to be hard to implement in a way
that doesn't suck. You'll have to extend the character driver interface
to support receiving file descriptors, plumb that appropriately through
the monitor.
Seems like an odd abstraction to me though as unix domain sockets are
the only transport that I know of that supports sending fds.
> (qemu) closefd myfd
> // qemu closes the fd attached to tag 'myfd'
>
> Advantages:
> - no runtime handshaking with a new socket
> - work with names, not numbers you need to read off the monitor
Names are fine. I would have requested that the numbers be validated
which require them to be tracked which makes them essentially names anyway.
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove
2009-02-04 13:33 ` [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove Marcelo Tosatti
` (2 preceding siblings ...)
2009-02-04 16:17 ` Markus Armbruster
@ 2009-02-04 17:47 ` Blue Swirl
3 siblings, 0 replies; 34+ messages in thread
From: Blue Swirl @ 2009-02-04 17:47 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
On 2/4/09, Marcelo Tosatti <mtosatti@redhat.com> wrote:
> Add monitor command to hot-add PCI devices (nic and storage).
> +#define PCI_BASE_CLASS_STORAGE 0x01
> +#define PCI_BASE_CLASS_NETWORK 0x02
These belong to hw/pci.h.
> + const char *valid_param_list[] = { "tap", "user", "socket"
> +#ifdef CONFIG_VDE
> + ,"vde"
> +#endif
"user" should be conditional to CONFIG_SLIRP.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 01/18] qemu: add pci helper functions
2009-02-04 14:56 ` Paul Brook
@ 2009-02-04 19:15 ` Anthony Liguori
2009-02-06 17:35 ` Marcelo Tosatti
0 siblings, 1 reply; 34+ messages in thread
From: Anthony Liguori @ 2009-02-04 19:15 UTC (permalink / raw)
To: qemu-devel; +Cc: Marcelo Tosatti
Paul Brook wrote:
> On Wednesday 04 February 2009, Marcelo Tosatti wrote:
>
>> +PCIDevice *pci_find_device(int bus_num, int slot)
>> +{
>> + int devfn;
>> + PCIDevice *d;
>> + PCIBus *bus = pci_find_bus(bus_num);
>> +
>> + if (!bus)
>> + return NULL;
>> +
>> + for(devfn = 0; devfn < 256; devfn++) {
>> + d = bus->devices[devfn];
>> + if (d && PCI_SLOT(devfn) == slot)
>> + return d;
>> + }
>> + return NULL;
>> +}
>>
>
> This loop is bogus. You already know the devfn from the slot.
> It's also completely busted if you have multifunction devices.
>
It should probably try a bit harder to handle the multifunction case.
You know your device is bus->devices[slot * 8] but you should also check
slot * 8 + 1..slot * 8 + 7 to see if there are any sub functions and
return NULL or something.
Regards,
Anthony Liguori
> Paul
>
>
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 13/18] qemu: warn if PCI region is not power of two
2009-02-04 14:38 ` Paul Brook
@ 2009-02-06 17:34 ` Marcelo Tosatti
2009-02-08 6:08 ` malc
0 siblings, 1 reply; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-06 17:34 UTC (permalink / raw)
To: Paul Brook; +Cc: qemu-devel
On Wed, Feb 04, 2009 at 02:38:05PM +0000, Paul Brook wrote:
> This should be an error. It is a requirement of the PCI spec, and not
> something that's user configurable. Any odd sizes indicate a fairly serious
> bug elsewhere in qemu.
>
> Paul
qemu: bail out if PCI region is not power of two
Otherwise the PCI size for such regions can be calculated erroneously.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/hw/pci.c
===================================================================
--- trunk.orig/hw/pci.c
+++ trunk/hw/pci.c
@@ -249,6 +249,13 @@ void pci_register_io_region(PCIDevice *p
if ((unsigned int)region_num >= PCI_NUM_REGIONS)
return;
+
+ if (size & (size-1)) {
+ term_printf("ERROR: PCI region size must be pow2 "
+ "type=0x%x, size=0x%x\n", type, size);
+ exit(1);
+ }
+
r = &pci_dev->io_regions[region_num];
r->addr = -1;
r->size = size;
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 01/18] qemu: add pci helper functions
2009-02-04 19:15 ` Anthony Liguori
@ 2009-02-06 17:35 ` Marcelo Tosatti
0 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-06 17:35 UTC (permalink / raw)
To: Anthony Liguori; +Cc: qemu-devel
On Wed, Feb 04, 2009 at 01:15:19PM -0600, Anthony Liguori wrote:
>> This loop is bogus. You already know the devfn from the slot.
>> It's also completely busted if you have multifunction devices.
>>
> It should probably try a bit harder to handle the multifunction case.
> You know your device is bus->devices[slot * 8] but you should also check
> slot * 8 + 1..slot * 8 + 7 to see if there are any sub functions and
> return NULL or something.
qemu: add pci helper functions
Add pci_find_bus/pci_find_device to be used by PCI hotplug.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/hw/pci.c
===================================================================
--- trunk.orig/hw/pci.c
+++ trunk/hw/pci.c
@@ -713,6 +713,26 @@ static void pci_bridge_write_config(PCID
pci_default_write_config(d, address, val, len);
}
+PCIBus *pci_find_bus(int bus_num)
+{
+ PCIBus *bus = first_bus;
+
+ while (bus && bus->bus_num != bus_num)
+ bus = bus->next;
+
+ return bus;
+}
+
+PCIDevice *pci_find_device(int bus_num, int slot, int function)
+{
+ PCIBus *bus = pci_find_bus(bus_num);
+
+ if (!bus)
+ return NULL;
+
+ return bus->devices[PCI_DEVFN(slot, function)];
+}
+
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
pci_map_irq_fn map_irq, const char *name)
{
Index: trunk/hw/pci.h
===================================================================
--- trunk.orig/hw/pci.h
+++ trunk/hw/pci.h
@@ -8,6 +8,10 @@
extern target_phys_addr_t pci_mem_base;
+#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
+
/* Device classes and subclasses */
#define PCI_CLASS_STORAGE_SCSI 0x0100
@@ -222,6 +226,8 @@ void pci_data_write(void *opaque, uint32
uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
int pci_bus_num(PCIBus *s);
void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
+PCIBus *pci_find_bus(int bus_num);
+PCIDevice *pci_find_device(int bus_num, int slot, int function);
void pci_info(void);
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 13/18] qemu: warn if PCI region is not power of two
2009-02-06 17:34 ` Marcelo Tosatti
@ 2009-02-08 6:08 ` malc
2009-02-08 17:20 ` Marcelo Tosatti
0 siblings, 1 reply; 34+ messages in thread
From: malc @ 2009-02-08 6:08 UTC (permalink / raw)
To: qemu-devel; +Cc: Paul Brook
On Fri, 6 Feb 2009, Marcelo Tosatti wrote:
> On Wed, Feb 04, 2009 at 02:38:05PM +0000, Paul Brook wrote:
> > This should be an error. It is a requirement of the PCI spec, and not
> > something that's user configurable. Any odd sizes indicate a fairly serious
> > bug elsewhere in qemu.
> >
> > Paul
>
> qemu: bail out if PCI region is not power of two
>
> Otherwise the PCI size for such regions can be calculated erroneously.
>
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
> Index: trunk/hw/pci.c
> ===================================================================
> --- trunk.orig/hw/pci.c
> +++ trunk/hw/pci.c
> @@ -249,6 +249,13 @@ void pci_register_io_region(PCIDevice *p
>
> if ((unsigned int)region_num >= PCI_NUM_REGIONS)
> return;
> +
> + if (size & (size-1)) {
> + term_printf("ERROR: PCI region size must be pow2 "
> + "type=0x%x, size=0x%x\n", type, size);
> + exit(1);
> + }
> +
If monitor is on a vc the error message would never be seen, perhaps
it's better to fprintf it stderr instead?
[..snip..]
--
mailto:av1474@comtv.ru
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [Qemu-devel] [patch 13/18] qemu: warn if PCI region is not power of two
2009-02-08 6:08 ` malc
@ 2009-02-08 17:20 ` Marcelo Tosatti
0 siblings, 0 replies; 34+ messages in thread
From: Marcelo Tosatti @ 2009-02-08 17:20 UTC (permalink / raw)
To: qemu-devel
On Sun, Feb 08, 2009 at 09:08:14AM +0300, malc wrote:
> > --- trunk.orig/hw/pci.c
> > +++ trunk/hw/pci.c
> > @@ -249,6 +249,13 @@ void pci_register_io_region(PCIDevice *p
> >
> > if ((unsigned int)region_num >= PCI_NUM_REGIONS)
> > return;
> > +
> > + if (size & (size-1)) {
> > + term_printf("ERROR: PCI region size must be pow2 "
> > + "type=0x%x, size=0x%x\n", type, size);
> > + exit(1);
> > + }
> > +
>
> If monitor is on a vc the error message would never be seen, perhaps
> it's better to fprintf it stderr instead?
Agreed, will fix. Thanks.
^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2009-02-08 17:21 UTC | newest]
Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-04 13:33 [Qemu-devel] [patch 00/18] acpi pci hotplug support Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 01/18] qemu: add pci helper functions Marcelo Tosatti
2009-02-04 14:56 ` Paul Brook
2009-02-04 19:15 ` Anthony Liguori
2009-02-06 17:35 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 02/18] qemu: return PCIDevice on net device init and record devfn Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 03/18] qemu: dynamic drive/drive_opt index allocation Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 04/18] qemu: dynamic nic info " Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 05/18] qemu: drive removal support Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 06/18] qemu: record devfn on block driver instance Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 07/18] qemu: move drives_opt for external use Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 08/18] qemu: net/drive add/remove tweaks Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 09/18] qemu: add net_client_uninit / qemu_find_vlan_client Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 10/18] qemu: add cpu_unregister_io_memory and make io mem table index dynamic Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 11/18] qemu: add qemu_free_irqs Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 12/18] qemu: add pci_unregister_device Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 13/18] qemu: warn if PCI region is not power of two Marcelo Tosatti
2009-02-04 14:38 ` Paul Brook
2009-02-06 17:34 ` Marcelo Tosatti
2009-02-08 6:08 ` malc
2009-02-08 17:20 ` Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 14/18] qemu: LSI SCSI and e1000 unregister callbacks Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 15/18] qemu: zero ioport_opaque on isa_unassign_ioport Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 16/18] qemu: initialize hot add system / acpi gpe Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 17/18] qemu: pci hotplug GPE support Marcelo Tosatti
2009-02-04 13:33 ` [Qemu-devel] [patch 18/18] qemu: PCI device, disk and host network hot-add / hot-remove Marcelo Tosatti
2009-02-04 14:38 ` Daniel P. Berrange
2009-02-04 15:21 ` Anthony Liguori
2009-02-04 15:37 ` Daniel P. Berrange
2009-02-04 15:59 ` Avi Kivity
2009-02-04 16:46 ` Anthony Liguori
2009-02-04 14:59 ` Paul Brook
2009-02-04 16:17 ` Markus Armbruster
2009-02-04 17:47 ` Blue Swirl
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).