5b4649f
diff --git a/block-raw-posix.c b/block-raw-posix.c
5b4649f
index 2364175..085f38f 100644
5b4649f
--- a/block-raw-posix.c
5b4649f
+++ b/block-raw-posix.c
5b4649f
@@ -55,6 +55,7 @@
5b4649f
 #include <sys/ioctl.h>
5b4649f
 #include <linux/cdrom.h>
5b4649f
 #include <linux/fd.h>
5b4649f
+#include <sys/mount.h>
5b4649f
 #endif
5b4649f
 #ifdef __FreeBSD__
5b4649f
 #include <sys/disk.h>
5b4649f
@@ -125,6 +126,10 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
5b4649f
         return ret;
5b4649f
     }
5b4649f
     s->fd = fd;
5b4649f
+#ifndef CONFIG_STUBDOM
5b4649f
+    /* Invalidate buffer cache for this device. */
5b4649f
+    ioctl(s->fd, BLKFLSBUF, 0);
5b4649f
+#endif
5b4649f
     return 0;
5b4649f
 }
5b4649f
 
5b4649f
@@ -505,6 +510,10 @@ static void raw_close(BlockDriverState *bs)
5b4649f
 {
5b4649f
     BDRVRawState *s = bs->opaque;
5b4649f
     if (s->fd >= 0) {
5b4649f
+#ifndef CONFIG_STUBDOM
5b4649f
+        /* Invalidate buffer cache for this device. */
5b4649f
+        ioctl(s->fd, BLKFLSBUF, 0);
5b4649f
+#endif
5b4649f
         close(s->fd);
5b4649f
         s->fd = -1;
5b4649f
     }
5b4649f
diff --git a/hw/ide.c b/hw/ide.c
5b4649f
index dae6e7f..235f5f1 100644
5b4649f
--- a/hw/ide.c
5b4649f
+++ b/hw/ide.c
5b4649f
@@ -484,6 +484,7 @@ typedef struct PCIIDEState {
5b4649f
     int type; /* see IDE_TYPE_xxx */
5b4649f
 } PCIIDEState;
5b4649f
 
5b4649f
+static PCIIDEState *principal_ide_controller;
5b4649f
 
5b4649f
 #if defined(__ia64__)
5b4649f
 #include <xen/hvm/ioreq.h>
5b4649f
@@ -2778,6 +2779,47 @@ static void ide_reset(IDEState *s)
5b4649f
     s->media_changed = 0;
5b4649f
 }
5b4649f
 
5b4649f
+/* Unplug all of the IDE hard disks, starting at index @start in the
5b4649f
+   table. */
5b4649f
+static void _ide_unplug_harddisks(int start)
5b4649f
+{
5b4649f
+    IDEState *s;
5b4649f
+    int i, j;
5b4649f
+
5b4649f
+    if (!principal_ide_controller) {
5b4649f
+        fprintf(stderr, "No principal controller?\n");
5b4649f
+        return;
5b4649f
+    }
5b4649f
+    for (i = start; i < 4; i++) {
5b4649f
+        s = principal_ide_controller->ide_if + i;
5b4649f
+        if (!s->bs)
5b4649f
+            continue; /* drive not present */
5b4649f
+        if (s->is_cdrom)
5b4649f
+            continue; /* cdrom */
5b4649f
+        /* Is a hard disk, unplug it. */
5b4649f
+        for (j = 0; j < nb_drives; j++)
5b4649f
+            if (drives_table[j].bdrv == s->bs)
5b4649f
+                drives_table[j].bdrv = NULL;
5b4649f
+        bdrv_close(s->bs);
5b4649f
+        s->bs = NULL;
5b4649f
+        ide_reset(s);
5b4649f
+    }
5b4649f
+}
5b4649f
+
5b4649f
+/* Unplug all hard disks except for the primary master (which will
5b4649f
+   almost always be the boot device). */
5b4649f
+void ide_unplug_aux_harddisks(void)
5b4649f
+{
5b4649f
+    _ide_unplug_harddisks(1);
5b4649f
+}
5b4649f
+
5b4649f
+/* Unplug all hard disks, including the boot device. */
5b4649f
+void ide_unplug_harddisks(void)
5b4649f
+{
5b4649f
+    _ide_unplug_harddisks(0);
5b4649f
+}
5b4649f
+
5b4649f
+
5b4649f
 struct partition {
5b4649f
 	uint8_t boot_ind;		/* 0x80 - active */
5b4649f
 	uint8_t head;		/* starting head */
5b4649f
@@ -3290,6 +3332,9 @@ void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
5b4649f
                                            sizeof(PCIIDEState),
5b4649f
                                            -1,
5b4649f
                                            NULL, NULL);
5b4649f
+    if (principal_ide_controller)
5b4649f
+	abort();
5b4649f
+    principal_ide_controller = d;
5b4649f
     d->type = IDE_TYPE_CMD646;
5b4649f
     pci_conf = d->dev.config;
5b4649f
     pci_conf[0x00] = 0x95; // CMD646
5b4649f
@@ -3419,6 +3464,9 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
5b4649f
                                            sizeof(PCIIDEState),
5b4649f
                                            devfn,
5b4649f
                                            NULL, NULL);
5b4649f
+    if (principal_ide_controller)
5b4649f
+	abort();
5b4649f
+    principal_ide_controller = d;
5b4649f
     d->type = IDE_TYPE_PIIX3;
5b4649f
 
5b4649f
     pci_conf = d->dev.config;
5b4649f
diff --git a/hw/pc.h b/hw/pc.h
5b4649f
index a78e039..3d46046 100644
5b4649f
--- a/hw/pc.h
5b4649f
+++ b/hw/pc.h
5b4649f
@@ -146,6 +146,8 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
5b4649f
                         qemu_irq *pic);
5b4649f
 void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
5b4649f
                         qemu_irq *pic);
5b4649f
+void ide_unplug_harddisks(void);
5b4649f
+void ide_unplug_aux_harddisks(void);
5b4649f
 
5b4649f
 /* ne2000.c */
5b4649f
 
5b4649f
diff --git a/hw/pci.c b/hw/pci.c
5b4649f
index 1de68fd..aace3a4 100644
5b4649f
--- a/hw/pci.c
5b4649f
+++ b/hw/pci.c
5b4649f
@@ -26,6 +26,9 @@
5b4649f
 #include "console.h"
5b4649f
 #include "net.h"
5b4649f
 
5b4649f
+#include "exec-all.h"
5b4649f
+#include "qemu-xen.h"
5b4649f
+
5b4649f
 //#define DEBUG_PCI
5b4649f
 
5b4649f
 struct PCIBus {
5b4649f
@@ -648,6 +651,46 @@ void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
5b4649f
     }
5b4649f
 }
5b4649f
 
5b4649f
+void pci_unplug_netifs(void)
5b4649f
+{
5b4649f
+    PCIBus *bus;
5b4649f
+    PCIDevice *dev;
5b4649f
+    PCIIORegion *region;
5b4649f
+    int x;
5b4649f
+    int i;
5b4649f
+
5b4649f
+    /* We only support one PCI bus */
5b4649f
+    for (bus = first_bus; bus; bus = NULL) {
5b4649f
+       for (x = 0; x < 256; x++) {
5b4649f
+           dev = bus->devices[x];
5b4649f
+           if (dev &&
5b4649f
+               dev->config[0xa] == 0 &&
5b4649f
+               dev->config[0xb] == 2) {
5b4649f
+               /* Found a netif.  Remove it from the bus.  Note that
5b4649f
+                  we don't free it here, since there could still be
5b4649f
+                  references to it floating around.  There are only
5b4649f
+                  ever one or two structures leaked, and it's not
5b4649f
+                  worth finding them all. */
5b4649f
+               bus->devices[x] = NULL;
5b4649f
+               for (i = 0; i < PCI_NUM_REGIONS; i++) {
5b4649f
+                   region = &dev->io_regions[i];
5b4649f
+                   if (region->addr == (uint32_t)-1 ||
5b4649f
+                       region->size == 0)
5b4649f
+                       continue;
5b4649f
+                   fprintf(logfile, "region type %d at [%x,%x).\n",
5b4649f
+                           region->type, region->addr,
5b4649f
+                           region->addr+region->size);
5b4649f
+                   if (region->type == PCI_ADDRESS_SPACE_IO) {
5b4649f
+                       isa_unassign_ioport(region->addr, region->size);
5b4649f
+                   } else if (region->type == PCI_ADDRESS_SPACE_MEM) {
5b4649f
+                       unregister_iomem(region->addr);
5b4649f
+                   }
5b4649f
+               }
5b4649f
+           }
5b4649f
+       }
5b4649f
+    }
5b4649f
+}
5b4649f
+
5b4649f
 typedef struct {
5b4649f
     PCIDevice dev;
5b4649f
     PCIBus *bus;
5b4649f
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
5b4649f
index 430e603..36df8f8 100644
5b4649f
--- a/hw/xen_platform.c
5b4649f
+++ b/hw/xen_platform.c
5b4649f
@@ -24,12 +24,20 @@
5b4649f
  */
5b4649f
 
5b4649f
 #include "hw.h"
5b4649f
+#include "pc.h"
5b4649f
 #include "pci.h"
5b4649f
 #include "irq.h"
5b4649f
+#include "../qemu-xen.h"
5b4649f
 
5b4649f
+#include <assert.h>
5b4649f
 #include <xenguest.h>
5b4649f
 
5b4649f
+static int drivers_blacklisted;
5b4649f
+static uint16_t driver_product_version;
5b4649f
+static int throttling_disabled;
5b4649f
 extern FILE *logfile;
5b4649f
+static char log_buffer[4096];
5b4649f
+static int log_buffer_off;
5b4649f
 
5b4649f
 #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
5b4649f
 
5b4649f
@@ -39,6 +47,88 @@ typedef struct PCIXenPlatformState
5b4649f
   uint8_t    platform_flags;
5b4649f
 } PCIXenPlatformState;
5b4649f
 
5b4649f
+/* We throttle access to dom0 syslog, to avoid DOS attacks.  This is
5b4649f
+   modelled as a token bucket, with one token for every byte of log.
5b4649f
+   The bucket size is 128KB (->1024 lines of 128 bytes each) and
5b4649f
+   refills at 256B/s.  It starts full.  The guest is blocked if no
5b4649f
+   tokens are available when it tries to generate a log message. */
5b4649f
+#define BUCKET_MAX_SIZE (128*1024)
5b4649f
+#define BUCKET_FILL_RATE 256
5b4649f
+
5b4649f
+static void throttle(unsigned count)
5b4649f
+{
5b4649f
+    static unsigned available;
5b4649f
+    static struct timespec last_refil;
5b4649f
+    static int started;
5b4649f
+    static int warned;
5b4649f
+
5b4649f
+    struct timespec waiting_for, now;
5b4649f
+    double delay;
5b4649f
+    struct timespec ts;
5b4649f
+
5b4649f
+    if (throttling_disabled)
5b4649f
+        return;
5b4649f
+
5b4649f
+    if (!started) {
5b4649f
+        clock_gettime(CLOCK_MONOTONIC, &last_refil);
5b4649f
+        available = BUCKET_MAX_SIZE;
5b4649f
+        started = 1;
5b4649f
+    }
5b4649f
+
5b4649f
+    if (count > BUCKET_MAX_SIZE) {
5b4649f
+        fprintf(logfile, "tried to get %d tokens, but bucket size is %d\n",
5b4649f
+                BUCKET_MAX_SIZE, count);
5b4649f
+        exit(1);
5b4649f
+    }
5b4649f
+
5b4649f
+    if (available < count) {
5b4649f
+        /* The bucket is empty.  Refil it */
5b4649f
+
5b4649f
+        /* When will it be full enough to handle this request? */
5b4649f
+        delay = (double)(count - available) / BUCKET_FILL_RATE;
5b4649f
+        waiting_for = last_refil;
5b4649f
+        waiting_for.tv_sec += delay;
5b4649f
+        waiting_for.tv_nsec += (delay - (int)delay) * 1e9;
5b4649f
+        if (waiting_for.tv_nsec >= 1000000000) {
5b4649f
+            waiting_for.tv_nsec -= 1000000000;
5b4649f
+            waiting_for.tv_sec++;
5b4649f
+        }
5b4649f
+
5b4649f
+        /* How long do we have to wait? (might be negative) */
5b4649f
+        clock_gettime(CLOCK_MONOTONIC, &now;;
5b4649f
+        ts.tv_sec = waiting_for.tv_sec - now.tv_sec;
5b4649f
+        ts.tv_nsec = waiting_for.tv_nsec - now.tv_nsec;
5b4649f
+        if (ts.tv_nsec < 0) {
5b4649f
+            ts.tv_sec--;
5b4649f
+            ts.tv_nsec += 1000000000;
5b4649f
+        }
5b4649f
+
5b4649f
+        /* Wait for it. */
5b4649f
+        if (ts.tv_sec > 0 ||
5b4649f
+            (ts.tv_sec == 0 && ts.tv_nsec > 0)) {
5b4649f
+            if (!warned) {
5b4649f
+                fprintf(logfile, "throttling guest access to syslog");
5b4649f
+                warned = 1;
5b4649f
+            }
5b4649f
+            while (nanosleep(&ts, &ts) < 0 && errno == EINTR)
5b4649f
+                ;
5b4649f
+        }
5b4649f
+
5b4649f
+        /* Refil */
5b4649f
+        clock_gettime(CLOCK_MONOTONIC, &now;;
5b4649f
+        delay = (now.tv_sec - last_refil.tv_sec) +
5b4649f
+            (now.tv_nsec - last_refil.tv_nsec) * 1.0e-9;
5b4649f
+        available += BUCKET_FILL_RATE * delay;
5b4649f
+        if (available > BUCKET_MAX_SIZE)
5b4649f
+            available = BUCKET_MAX_SIZE;
5b4649f
+        last_refil = now;
5b4649f
+    }
5b4649f
+
5b4649f
+    assert(available >= count);
5b4649f
+
5b4649f
+    available -= count;
5b4649f
+}
5b4649f
+
5b4649f
 static uint32_t xen_platform_ioport_readb(void *opaque, uint32_t addr)
5b4649f
 {
5b4649f
     PCIXenPlatformState *s = opaque;
5b4649f
@@ -66,6 +156,19 @@ static void xen_platform_ioport_writeb(void *opaque, uint32_t addr, uint32_t val
5b4649f
             d->platform_flags = val & PFFLAG_ROM_LOCK;
5b4649f
         break;
5b4649f
     }
5b4649f
+    case 8:
5b4649f
+        {
5b4649f
+            if (val == '\n' || log_buffer_off == sizeof(log_buffer) - 1) {
5b4649f
+                /* Flush buffer */
5b4649f
+                log_buffer[log_buffer_off] = 0;
5b4649f
+                throttle(log_buffer_off);
5b4649f
+                fprintf(logfile, "%s\n", log_buffer);
5b4649f
+                log_buffer_off = 0;
5b4649f
+                break;
5b4649f
+            }
5b4649f
+            log_buffer[log_buffer_off++] = val;
5b4649f
+        }
5b4649f
+        break;
5b4649f
     default:
5b4649f
         break;
5b4649f
     }
5b4649f
@@ -126,6 +229,116 @@ static void platform_mmio_map(PCIDevice *d, int region_num,
5b4649f
     cpu_register_physical_memory(addr, 0x1000000, mmio_io_addr);
5b4649f
 }
5b4649f
 
5b4649f
+#define UNPLUG_ALL_IDE_DISKS 1
5b4649f
+#define UNPLUG_ALL_NICS 2
5b4649f
+#define UNPLUG_AUX_IDE_DISKS 4
5b4649f
+
5b4649f
+static void platform_fixed_ioport_write2(void *opaque, uint32_t addr, uint32_t val)
5b4649f
+{
5b4649f
+    switch (addr - 0x10) {
5b4649f
+    case 0:
5b4649f
+        /* Unplug devices.  Value is a bitmask of which devices to
5b4649f
+           unplug, with bit 0 the IDE devices, bit 1 the network
5b4649f
+           devices, and bit 2 the non-primary-master IDE devices. */
5b4649f
+        if (val & UNPLUG_ALL_IDE_DISKS)
5b4649f
+            ide_unplug_harddisks();
5b4649f
+        if (val & UNPLUG_ALL_NICS) {
5b4649f
+            pci_unplug_netifs();
5b4649f
+            net_tap_shutdown_all();
5b4649f
+        }
5b4649f
+        if (val & UNPLUG_AUX_IDE_DISKS) {
5b4649f
+            ide_unplug_aux_harddisks();
5b4649f
+        }
5b4649f
+        break;
5b4649f
+    case 2:
5b4649f
+        switch (val) {
5b4649f
+        case 1:
5b4649f
+            fprintf(logfile, "Citrix Windows PV drivers loaded in guest\n");
5b4649f
+            break;
5b4649f
+        case 2:
5b4649f
+            fprintf(logfile, "GPLPV drivers loaded in guest\n");
5b4649f
+            break;
5b4649f
+        case 0:
5b4649f
+            fprintf(logfile, "Guest claimed to be running PV product 0?\n");
5b4649f
+            break;
5b4649f
+        default:
5b4649f
+            fprintf(logfile, "Unknown PV product %d loaded in guest\n", val);
5b4649f
+            break;
5b4649f
+        }
5b4649f
+        driver_product_version = val;
5b4649f
+        break;
5b4649f
+    }
5b4649f
+}
5b4649f
+
5b4649f
+static void platform_fixed_ioport_write4(void *opaque, uint32_t addr,
5b4649f
+                                         uint32_t val)
5b4649f
+{
5b4649f
+    switch (addr - 0x10) {
5b4649f
+    case 0:
5b4649f
+        /* PV driver version */
5b4649f
+        if (driver_product_version == 0) {
5b4649f
+            fprintf(logfile,
5b4649f
+                    "Drivers tried to set their version number (%d) before setting the product number?\n",
5b4649f
+                    val);
5b4649f
+            return;
5b4649f
+        }
5b4649f
+        fprintf(logfile, "PV driver build %d\n", val);
5b4649f
+        if (xenstore_pv_driver_build_blacklisted(driver_product_version,
5b4649f
+                                                 val)) {
5b4649f
+            fprintf(logfile, "Drivers are blacklisted!\n");
5b4649f
+            drivers_blacklisted = 1;
5b4649f
+        }
5b4649f
+        break;
5b4649f
+    }
5b4649f
+}
5b4649f
+
5b4649f
+
5b4649f
+static void platform_fixed_ioport_write1(void *opaque, uint32_t addr, uint32_t val)
5b4649f
+{
5b4649f
+    switch (addr - 0x10) {
5b4649f
+    case 2:
5b4649f
+        /* Send bytes to syslog */
5b4649f
+        if (val == '\n' || log_buffer_off == sizeof(log_buffer) - 1) {
5b4649f
+            /* Flush buffer */
5b4649f
+            log_buffer[log_buffer_off] = 0;
5b4649f
+            throttle(log_buffer_off);
5b4649f
+            fprintf(logfile, "%s\n", log_buffer);
5b4649f
+            log_buffer_off = 0;
5b4649f
+            break;
5b4649f
+        }
5b4649f
+        log_buffer[log_buffer_off++] = val;
5b4649f
+        break;
5b4649f
+    }
5b4649f
+}
5b4649f
+
5b4649f
+static uint32_t platform_fixed_ioport_read2(void *opaque, uint32_t addr)
5b4649f
+{
5b4649f
+    switch (addr - 0x10) {
5b4649f
+    case 0:
5b4649f
+        if (drivers_blacklisted) {
5b4649f
+            /* The drivers will recognise this magic number and refuse
5b4649f
+             * to do anything. */
5b4649f
+            return 0xd249;
5b4649f
+        } else {
5b4649f
+            /* Magic value so that you can identify the interface. */
5b4649f
+            return 0x49d2;
5b4649f
+        }
5b4649f
+    default:
5b4649f
+        return 0xffff;
5b4649f
+    }
5b4649f
+}
5b4649f
+
5b4649f
+static uint32_t platform_fixed_ioport_read1(void *opaque, uint32_t addr)
5b4649f
+{
5b4649f
+    switch (addr - 0x10) {
5b4649f
+    case 2:
5b4649f
+        /* Version number */
5b4649f
+        return 1;
5b4649f
+    default:
5b4649f
+        return 0xff;
5b4649f
+    }
5b4649f
+}
5b4649f
+
5b4649f
 struct pci_config_header {
5b4649f
     uint16_t vendor_id;
5b4649f
     uint16_t device_id;
5b4649f
@@ -185,6 +398,7 @@ void pci_xen_platform_init(PCIBus *bus)
5b4649f
 {
5b4649f
     PCIXenPlatformState *d;
5b4649f
     struct pci_config_header *pch;
5b4649f
+    struct stat stbuf;
5b4649f
 
5b4649f
     printf("Register xen platform.\n");
5b4649f
     d = (PCIXenPlatformState *)pci_register_device(
5b4649f
@@ -216,4 +430,13 @@ void pci_xen_platform_init(PCIBus *bus)
5b4649f
 
5b4649f
     register_savevm("platform", 0, 2, xen_pci_save, xen_pci_load, d);
5b4649f
     printf("Done register platform.\n");
5b4649f
+    register_ioport_write(0x10, 16, 4, platform_fixed_ioport_write4, NULL);
5b4649f
+    register_ioport_write(0x10, 16, 2, platform_fixed_ioport_write2, NULL);
5b4649f
+    register_ioport_write(0x10, 16, 1, platform_fixed_ioport_write1, NULL);
5b4649f
+    register_ioport_read(0x10, 16, 2, platform_fixed_ioport_read2, NULL);
5b4649f
+    register_ioport_read(0x10, 16, 1, platform_fixed_ioport_read1, NULL);
5b4649f
+
5b4649f
+    if (stat("/etc/disable-guest-log-throttle", &stbuf) == 0)
5b4649f
+        throttling_disabled = 1;
5b4649f
+
5b4649f
 }
5b4649f
diff --git a/i386-dm/exec-dm.c b/i386-dm/exec-dm.c
5b4649f
index d511021..283f225 100644
5b4649f
--- a/i386-dm/exec-dm.c
5b4649f
+++ b/i386-dm/exec-dm.c
5b4649f
@@ -267,7 +267,7 @@ void cpu_abort(CPUState *env, const char *fmt, ...)
5b4649f
 
5b4649f
 /* XXX: Simple implementation. Fix later */
5b4649f
 #define MAX_MMIO 32
5b4649f
-struct mmio_space {
5b4649f
+static struct mmio_space {
5b4649f
         target_phys_addr_t start;
5b4649f
         unsigned long size;
5b4649f
         unsigned long io_index;
5b4649f
@@ -413,6 +413,17 @@ int iomem_index(target_phys_addr_t addr)
5b4649f
         return 0;
5b4649f
 }
5b4649f
 
5b4649f
+void unregister_iomem(target_phys_addr_t start)
5b4649f
+{
5b4649f
+    int index = iomem_index(start);
5b4649f
+    if (index) {
5b4649f
+        fprintf(logfile, "squash iomem [%lx, %lx).\n", mmio[index].start,
5b4649f
+                mmio[index].start + mmio[index].size);
5b4649f
+        mmio[index].start = mmio[index].size = 0;
5b4649f
+    }
5b4649f
+}
5b4649f
+
5b4649f
+
5b4649f
 #if defined(__i386__) || defined(__x86_64__)
5b4649f
 #define phys_ram_addr(x) (qemu_map_cache(x))
5b4649f
 #elif defined(__ia64__)
5b4649f
diff --git a/qemu-xen.h b/qemu-xen.h
5b4649f
index 06d8ec9..86f646a 100644
5b4649f
--- a/qemu-xen.h
5b4649f
+++ b/qemu-xen.h
5b4649f
@@ -23,8 +23,11 @@ void timeoffset_get(void);
5b4649f
 void pci_xen_platform_init(PCIBus *bus);
5b4649f
 #endif
5b4649f
 
5b4649f
-
5b4649f
+void ide_unplug_harddisks(void);
5b4649f
+void net_tap_shutdown_all(void);
5b4649f
+void pci_unplug_netifs(void);
5b4649f
 void destroy_hvm_domain(void);
5b4649f
+void unregister_iomem(target_phys_addr_t start);
5b4649f
 
5b4649f
 #ifdef __ia64__
5b4649f
 static inline void xc_domain_shutdown_hook(int xc_handle, uint32_t domid)
5b4649f
@@ -69,4 +72,8 @@ int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle,
5b4649f
 int xenstore_vm_write(int domid, char *key, char *val);
5b4649f
 char *xenstore_vm_read(int domid, char *key, unsigned int *len);
5b4649f
 
5b4649f
+int xenstore_pv_driver_build_blacklisted(uint16_t product_number,
5b4649f
+                                         uint32_t build_nr);
5b4649f
+
5b4649f
+
5b4649f
 #endif /*QEMU_XEN_H*/
5b4649f
diff --git a/vl.c b/vl.c
5b4649f
index 57b88f3..a6c7dff 100644
5b4649f
--- a/vl.c
5b4649f
+++ b/vl.c
5b4649f
@@ -259,6 +259,20 @@ static int event_pending = 1;
5b4649f
 
5b4649f
 #include "xen-vl-extra.c"
5b4649f
 
5b4649f
+typedef struct IOHandlerRecord {
5b4649f
+    int fd;
5b4649f
+    IOCanRWHandler *fd_read_poll;
5b4649f
+    IOHandler *fd_read;
5b4649f
+    IOHandler *fd_write;
5b4649f
+    int deleted;
5b4649f
+    void *opaque;
5b4649f
+    /* temporary data */
5b4649f
+    struct pollfd *ufd;
5b4649f
+    struct IOHandlerRecord *next;
5b4649f
+} IOHandlerRecord;
5b4649f
+
5b4649f
+static IOHandlerRecord *first_io_handler;
5b4649f
+
5b4649f
 /***********************************************************/
5b4649f
 /* x86 ISA bus support */
5b4649f
 
5b4649f
@@ -4052,6 +4066,7 @@ void do_info_slirp(void)
5b4649f
 typedef struct TAPState {
5b4649f
     VLANClientState *vc;
5b4649f
     int fd;
5b4649f
+    struct TAPState *next;
5b4649f
     char down_script[1024];
5b4649f
     char script_arg[1024];
5b4649f
 } TAPState;
5b4649f
@@ -4089,6 +4104,34 @@ static void tap_send(void *opaque)
5b4649f
     }
5b4649f
 }
5b4649f
 
5b4649f
+static TAPState *head_net_tap;
5b4649f
+
5b4649f
+void net_tap_shutdown_all(void)
5b4649f
+{
5b4649f
+    struct IOHandlerRecord **pioh, *ioh;
5b4649f
+
5b4649f
+    while (head_net_tap) {
5b4649f
+       pioh = &first_io_handler;
5b4649f
+       for (;;) {
5b4649f
+           ioh = *pioh;
5b4649f
+           if (ioh == NULL)
5b4649f
+               break;
5b4649f
+           if (ioh->fd == head_net_tap->fd) {
5b4649f
+               *pioh = ioh->next;
5b4649f
+               qemu_free(ioh);
5b4649f
+               break;
5b4649f
+           }
5b4649f
+           pioh = &ioh->next;
5b4649f
+       }
5b4649f
+       if (!ioh)
5b4649f
+           fprintf(stderr,
5b4649f
+                   "warning: can't find iohandler for %d to close it properly.\n",
5b4649f
+                   head_net_tap->fd);
5b4649f
+       close(head_net_tap->fd);
5b4649f
+       head_net_tap = head_net_tap->next;
5b4649f
+    }
5b4649f
+}
5b4649f
+
5b4649f
 /* fd support */
5b4649f
 
5b4649f
 static TAPState *net_tap_fd_init(VLANState *vlan, int fd)
5b4649f
@@ -4100,6 +4143,8 @@ static TAPState *net_tap_fd_init(VLANState *vlan, int fd)
5b4649f
         return NULL;
5b4649f
     s->fd = fd;
5b4649f
     s->vc = qemu_new_vlan_client(vlan, tap_receive, NULL, s);
5b4649f
+    s->next = head_net_tap;
5b4649f
+    head_net_tap = s;
5b4649f
     qemu_set_fd_handler(s->fd, tap_send, NULL, s);
5b4649f
     snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: fd=%d", fd);
5b4649f
     return s;
5b4649f
@@ -5662,20 +5707,6 @@ static void dumb_display_init(DisplayState *ds)
5b4649f
 
5b4649f
 #define MAX_IO_HANDLERS 64
5b4649f
 
5b4649f
-typedef struct IOHandlerRecord {
5b4649f
-    int fd;
5b4649f
-    IOCanRWHandler *fd_read_poll;
5b4649f
-    IOHandler *fd_read;
5b4649f
-    IOHandler *fd_write;
5b4649f
-    int deleted;
5b4649f
-    void *opaque;
5b4649f
-    /* temporary data */
5b4649f
-    struct pollfd *ufd;
5b4649f
-    struct IOHandlerRecord *next;
5b4649f
-} IOHandlerRecord;
5b4649f
-
5b4649f
-static IOHandlerRecord *first_io_handler;
5b4649f
-
5b4649f
 /* XXX: fd_read_poll should be suppressed, but an API change is
5b4649f
    necessary in the character devices to suppress fd_can_read(). */
5b4649f
 int qemu_set_fd_handler2(int fd,
5b4649f
diff --git a/xenstore.c b/xenstore.c
5b4649f
index dd487dd..d76e42b 100644
5b4649f
--- a/xenstore.c
5b4649f
+++ b/xenstore.c
5b4649f
@@ -626,6 +626,34 @@ void xenstore_record_dm(char *subpath, char *state)
5b4649f
     free(path);
5b4649f
 }
5b4649f
 
5b4649f
+int
5b4649f
+xenstore_pv_driver_build_blacklisted(uint16_t product_nr,
5b4649f
+                                     uint32_t build_nr)
5b4649f
+{
5b4649f
+    char *buf = NULL;
5b4649f
+    char *tmp;
5b4649f
+    const char *product;
5b4649f
+
5b4649f
+    switch (product_nr) {
5b4649f
+    case 1:
5b4649f
+        product = "xensource-windows";
5b4649f
+        break;
5b4649f
+    default:
5b4649f
+        /* Don't know what product this is -> we can't blacklist
5b4649f
+         * it. */
5b4649f
+        return 0;
5b4649f
+    }
5b4649f
+    if (asprintf(&buf, "/mh/driver-blacklist/%s/%d", product, build_nr) < 0)
5b4649f
+        return 0;
5b4649f
+    tmp = xs_read(xsh, XBT_NULL, buf, NULL);
5b4649f
+    free(tmp);
5b4649f
+    free(buf);
5b4649f
+    if (tmp == NULL)
5b4649f
+        return 0;
5b4649f
+    else
5b4649f
+        return 1;
5b4649f
+}
5b4649f
+
5b4649f
 void xenstore_record_dm_state(char *state)
5b4649f
 {
5b4649f
     xenstore_record_dm("state", state);