[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] Device model unplug version 2:



# HG changeset patch
# User Paul Durrant <paul.durrant@xxxxxxxxxx>
# Date 1275491143 -3600
# Node ID 636a452b175a75c79c711760846f7965cb53f14c
# Parent  166d7745fdaae8b7f1d77e024c64e5709ffc11d2
Device model unplug version 2:

Version 2 of the interface allows unplugging of individual IDE disks and/or
PCI NICs. IO ports 11 and 13 are used to control unplugging. A byte write to 
port
11 sets the unplug type (1 == IDE, 2 == NIC) and then a subsequent byte write to
port 13 tells qemu which device of the current type to unplug.

diff -r 166d7745fdaa -r 636a452b175a hw/ide.c
--- a/hw/ide.c  Wed Jun 02 16:02:01 2010 +0100
+++ b/hw/ide.c  Wed Jun 02 16:05:43 2010 +0100
@@ -3073,45 +3073,57 @@
 
 /* Unplug all of the IDE hard disks, starting at index @start in the
    table. */
-static void _ide_unplug_harddisks(int start)
+void ide_unplug_harddisk(int i)
 {
     IDEState *s;
-    int i, j;
+    int j;
 
     if (!principal_ide_controller) {
         fprintf(stderr, "No principal controller?\n");
         return;
     }
+
     /* wait for outstanding aio requests */
     qemu_aio_flush();
-    for (i = start; i < 4; i++) {
-        s = principal_ide_controller->ide_if + i;
-        if (!s->bs)
-            continue; /* drive not present */
-        if (s->is_cdrom)
-            continue; /* cdrom */
-        /* Is a hard disk, unplug it. */
-        for (j = 0; j < nb_drives; j++)
-            if (drives_table[j].bdrv == s->bs)
-                drives_table[j].bdrv = NULL;
-        bdrv_flush(s->bs);
-        bdrv_close(s->bs);
-        s->bs = NULL;
-        ide_reset(s);
-    }
+
+    s = principal_ide_controller->ide_if + i;
+    if (!s->bs)
+        return; /* drive not present */
+
+    if (s->is_cdrom)
+        return; /* cdrom */
+
+    /* Is a hard disk, unplug it. */
+    for (j = 0; j < nb_drives; j++) {
+        if (drives_table[j].bdrv == s->bs) {
+            fprintf(stderr, "%s: drive %d\n", __func__, i, j);
+            drives_table[j].bdrv = NULL;
+        }
+    }
+
+    bdrv_flush(s->bs);
+    bdrv_close(s->bs);
+    s->bs = NULL;
+    ide_reset(s);
 }
 
 /* Unplug all hard disks except for the primary master (which will
    almost always be the boot device). */
 void ide_unplug_aux_harddisks(void)
 {
-    _ide_unplug_harddisks(1);
+    int i;
+
+    for (i = 1; i < 4; i++)
+        ide_unplug_harddisk(i);
 }
 
 /* Unplug all hard disks, including the boot device. */
-void ide_unplug_harddisks(void)
-{
-    _ide_unplug_harddisks(0);
+void ide_unplug_all_harddisks(void)
+{
+    int i;
+
+    for (i = 0; i < 4; i++)
+        ide_unplug_harddisk(i);
 }
 
 static void ide_init2(IDEState *ide_state,
diff -r 166d7745fdaa -r 636a452b175a hw/pc.h
--- a/hw/pc.h   Wed Jun 02 16:02:01 2010 +0100
+++ b/hw/pc.h   Wed Jun 02 16:05:43 2010 +0100
@@ -162,7 +162,8 @@
                         qemu_irq *pic);
 void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
                         qemu_irq *pic);
-void ide_unplug_harddisks(void);
+void ide_unplug_harddisk(int i);
+void ide_unplug_all_harddisks(void);
 void ide_unplug_aux_harddisks(void);
 
 /* ne2000.c */
diff -r 166d7745fdaa -r 636a452b175a hw/pci.c
--- a/hw/pci.c  Wed Jun 02 16:02:01 2010 +0100
+++ b/hw/pci.c  Wed Jun 02 16:05:43 2010 +0100
@@ -251,6 +251,10 @@
     pci_dev->bus = bus;
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
+
+    fprintf(stderr, "%s: %02x:%02x:%02x (%s)\n", __func__, bus->bus_num,
+            devfn >> 3, devfn & 7, name);
+
     memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
     pci_set_default_subsystem_id(pci_dev);
 
@@ -823,45 +827,68 @@
     return NULL;
 }
 
-void pci_unplug_netifs(void)
+void pci_dev_unplug(PCIDevice *dev)
+{
+    PCIBus *bus = dev->bus;
+
+    fprintf(stderr, "%s: %02x:%02x:%02x\n", __func__, bus->bus_num,
+            dev->devfn >> 3, dev->devfn & 7);
+
+    if (test_pci_slot(dev->devfn >> 3) == 1) {
+        fprintf(stderr, "skipping hotplug device\n");
+        return;
+    }
+
+    bus->devices[dev->devfn] = NULL;
+    pci_unregister_io_regions(dev);
+}
+
+void pci_unplug_all_netifs(void)
 {
     PCIBus *bus;
-    PCIDevice *dev;
-    PCIIORegion *region;
     int x;
-    int i;
 
     /* We only support one PCI bus */
     for (bus = first_bus; bus; bus = NULL) {
-       for (x = 0; x < 256; x++) {
-           dev = bus->devices[x];
-           if (dev &&
-               dev->config[0xa] == 0 &&
-               dev->config[0xb] == 2 &&
-               test_pci_slot(x >> 3) != 1) {
-               /* Found a netif.  Remove it from the bus.  Note that
-                  we don't free it here, since there could still be
-                  references to it floating around.  There are only
-                  ever one or two structures leaked, and it's not
-                  worth finding them all. */
-               bus->devices[x] = NULL;
-               for (i = 0; i < PCI_NUM_REGIONS; i++) {
-                   region = &dev->io_regions[i];
-                   if (region->addr == (uint32_t)-1 ||
-                       region->size == 0)
-                       continue;
-                   fprintf(logfile, "region type %d at [%x,%x).\n",
-                           region->type, region->addr,
-                           region->addr+region->size);
-                   if (region->type == PCI_ADDRESS_SPACE_IO) {
-                       isa_unassign_ioport(region->addr, region->size);
-                   } else if (region->type == PCI_ADDRESS_SPACE_MEM) {
-                       unregister_iomem(region->addr);
-                   }
-               }
-           }
-       }
+        for (x = 0; x < 256; x++) {
+            PCIDevice *dev = bus->devices[x];
+
+            if (dev &&
+                dev->config[0xa] == 0 &&
+                dev->config[0xb] == 2) {
+                pci_dev_unplug(dev);
+            }
+        }
     }
+}
+
+int pci_unplug_nic(int i)
+{
+    NICInfo *nd;
+    PCIDevice *pci_dev;
+
+    if (i >= nb_nics)
+        return -1;
+
+    nd = &nd_table[i];
+
+    if (!nd->used)
+        return -1;
+
+    fprintf(stderr, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n", __func__,
+            nd->macaddr[0], nd->macaddr[1], nd->macaddr[2],
+            nd->macaddr[3], nd->macaddr[4], nd->macaddr[5]);
+
+    pci_dev = nd->private;
+    if (!pci_dev) {
+        fprintf(stderr, "%s: not PCI\n", __func__);
+        return -1;
+    }
+
+    pci_dev_unplug(pci_dev);
+
+    nd->used = 0;
+    return nd->vlan->id;
 }
 
 typedef struct {
diff -r 166d7745fdaa -r 636a452b175a hw/pci.h
--- a/hw/pci.h  Wed Jun 02 16:02:01 2010 +0100
+++ b/hw/pci.h  Wed Jun 02 16:05:43 2010 +0100
@@ -268,6 +268,7 @@
 
 PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn,
                   const char *default_model);
+void pci_dev_unplug(PCIDevice *dev);
 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);
 int pci_bus_num(PCIBus *s);
diff -r 166d7745fdaa -r 636a452b175a hw/xen_platform.c
--- a/hw/xen_platform.c Wed Jun 02 16:02:01 2010 +0100
+++ b/hw/xen_platform.c Wed Jun 02 16:05:43 2010 +0100
@@ -49,6 +49,11 @@
 {
   PCIDevice  pci_dev;
 } PCIXenPlatformState;
+
+static uint8_t unplug_type;
+
+#define UNPLUG_TYPE_IDE 0x01
+#define UNPLUG_TYPE_NIC 0x02
 
 /* We throttle access to dom0 syslog, to avoid DOS attacks.  This is
    modelled as a token bucket, with one token for every byte of log.
@@ -144,9 +149,9 @@
            unplug, with bit 0 the IDE devices, bit 1 the network
            devices, and bit 2 the non-primary-master IDE devices. */
         if (val & UNPLUG_ALL_IDE_DISKS)
-            ide_unplug_harddisks();
+            ide_unplug_all_harddisks();
         if (val & UNPLUG_ALL_NICS) {
-            pci_unplug_netifs();
+            pci_unplug_all_netifs();
             net_tap_shutdown_all();
         }
         if (val & UNPLUG_AUX_IDE_DISKS) {
@@ -192,7 +197,8 @@
     }
 }
 
-static void platform_fixed_ioport_write1(void *opaque, uint32_t addr, uint32_t 
val)
+static void platform_fixed_ioport_write1(void *opaque, uint32_t addr,
+                                         uint32_t val)
 {
     switch (addr - 0x10) {
     case 0: /* Platform flags */ {
@@ -209,8 +215,10 @@
         }
         break;
     }
-    case 2:
-        /* Send bytes to syslog */
+    case 1: /* Unplug type */
+        unplug_type = (uint8_t)val;
+        break;
+    case 2: /* Send bytes to syslog */
         if (val == '\n' || log_buffer_off == sizeof(log_buffer) - 1) {
             /* Flush buffer */
             log_buffer[log_buffer_off] = 0;
@@ -221,6 +229,24 @@
         }
         log_buffer[log_buffer_off++] = val;
         break;
+    case 3: /* Unplug index */
+        switch (unplug_type) {
+        case UNPLUG_TYPE_IDE:
+            ide_unplug_harddisk(val);
+            break;
+        case UNPLUG_TYPE_NIC: {
+            int id;
+
+            if ((id = pci_unplug_nic(val)) >= 0)
+                net_tap_shutdown_vlan(id);
+
+            break;
+        }
+        default:
+            fprintf(logfile, "unrecognized unplug type %02x\n",
+                    unplug_type);
+            break;
+        }
     }
 }
 
@@ -249,7 +275,7 @@
         return platform_flags;
     case 2:
         /* Version number */
-        return 1;
+        return 2;
     default:
         return 0xff;
     }
diff -r 166d7745fdaa -r 636a452b175a i386-dm/helper2.c
--- a/i386-dm/helper2.c Wed Jun 02 16:02:01 2010 +0100
+++ b/i386-dm/helper2.c Wed Jun 02 16:05:43 2010 +0100
@@ -580,8 +580,8 @@
         do_savevm(qemu_file);
         free(qemu_file);
 
-        ide_unplug_harddisks();
-        pci_unplug_netifs();
+        ide_unplug_all_harddisks();
+        pci_unplug_all_netifs();
         net_tap_shutdown_all();
 
         xenstore_record_dm_state("paused");
diff -r 166d7745fdaa -r 636a452b175a net.c
--- a/net.c     Wed Jun 02 16:02:01 2010 +0100
+++ b/net.c     Wed Jun 02 16:05:43 2010 +0100
@@ -1992,13 +1992,36 @@
     }
 }
 
+static void net_tap_shutdown(struct TAPState *tap)
+{
+    VLANClientState *vc = tap->vc;
+
+    fprintf(stderr, "%s: model=%s,name=%s\n", __func__, vc->model, vc->name);
+
+    qemu_set_fd_handler2(tap->fd, 0,0,0,0);
+    close(tap->fd);
+}
+
 void net_tap_shutdown_all(void)
 {
-    struct IOHandlerRecord **pioh, *ioh;
+    struct TAPState *tap;
 
-    while (head_net_tap) {
-        qemu_set_fd_handler2(head_net_tap->fd, 0,0,0,0);
-        close(head_net_tap->fd);
-        head_net_tap = head_net_tap->next;
+    for (tap = head_net_tap; tap; tap = tap->next)
+        net_tap_shutdown(tap);
+}
+
+void net_tap_shutdown_vlan(int id)
+{
+    struct TAPState *tap;
+
+    for (tap = head_net_tap; tap; tap = tap->next) {
+        VLANClientState *vc = tap->vc;
+        VLANState *vlan = vc->vlan;
+
+        if (vlan->id != id)
+            continue;
+        
+        net_tap_shutdown(tap);
     }
 }
+
diff -r 166d7745fdaa -r 636a452b175a net.h
--- a/net.h     Wed Jun 02 16:02:01 2010 +0100
+++ b/net.h     Wed Jun 02 16:05:43 2010 +0100
@@ -103,6 +103,7 @@
 int slirp_is_inited(void);
 void net_client_check(void);
 void net_tap_shutdown_all(void);
+void net_tap_shutdown_vlan(int id);
 void net_host_device_add(const char *device, const char *opts);
 void net_host_device_remove(int vlan_id, const char *device);
 
diff -r 166d7745fdaa -r 636a452b175a qemu-xen.h
--- a/qemu-xen.h        Wed Jun 02 16:02:01 2010 +0100
+++ b/qemu-xen.h        Wed Jun 02 16:05:43 2010 +0100
@@ -46,7 +46,8 @@
 void unset_vram_mapping(void *opaque);
 #endif
 
-void pci_unplug_netifs(void);
+void pci_unplug_all_netifs(void);
+int pci_unplug_nic(int i);
 void destroy_hvm_domain(void);
 void unregister_iomem(target_phys_addr_t start);
 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.