WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] Device model unplug version 2:
From: Paul Durrant <paul.durrant@xxxxxxxxxx>
Date: Wed, 2 Jun 2010 16:05:48 +0100
Cc: paul.durrant@xxxxxxxxxx
Delivery-date: Wed, 02 Jun 2010 08:07:14 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] Device model unplug version 2:, Paul Durrant <=