-Message-ID: <20081215171059.GA2574@weybridge.uk.xensource.com>
-From: Steven Smith <steven.smith@eu.citrix.com>
-To: Keir Fraser <keir.fraser@eu.citrix.com>
-Cc: James Harper <james.harper@bendigoit.com.au>,
- Ian Jackson <Ian.Jackson@eu.citrix.com>,
- xen-devel@lists.xensource.com
-Subject: Re: [Xen-devel] disable qemu PCI devices in HVM domains
-Date: Mon, 15 Dec 2008 17:10:59 +0000
-
-> >> I like the principle of disabling the drivers via an instruction to
-> >> qemu rather than by attempting to wrestle with the Windows driver
-> >> machinery to try to hide the devices. But couldn't we simulate a PCI
-> >> unplug or a medium change or something instead ? Then you could do it
-> >> later in the boot after your own drivers have properly bound.
-> >>
-> >
-> > Is the 'pci unplug' as simple as making a call somewhere like
-> > pci_unplug(id of ide adapter)? I'm concerned that Windows may not like
-> > this.
-> My own opinion is that the ioports are fine, but they should be offsets from
-> the xen-platform-pci device's ioport bar. Also we ought to document the
-> ports in xen-platform-pci's source file, as it's going to start getting
-> messy in there.
->
-> I'm not sure if the approach taken by the Citrix drivers could be at all
-> useful. Cc'ing Steven Smith in case he has any comments to make.
-I can't see any reason why the approach we take in our closed-source
-drivers wouldn't work here as well. I've attached the appropriate
-patches from our product qemu patchqueue, tidied up and stripped of
-the most obviously XenServer-specific bits, and made to apply to
-current ioemu-remote.
-
+MAGIC IOPORT 0x10 PROTOCOL
The protocol covers three basic things:
4) The drivers write a four-byte build number to IO port 0x10.
5) The drivers check the magic number by reading two bytes from 0x10
- again. If it's changed from 0x49d2, the drivers are blacklisted
- and should not load.
+ again. If it's changed from 0x49d2 to 0xd249, the drivers are
+ blacklisted and should not load.
6) The drivers write a two-byte bitmask of devices to unplug to IO
port 0x10. The defined fields are:
buses. For most guest operating systems, you want to do this
before device enumeration happens.
-...) Once the drivers have checked the magic number (and the
- blacklist, if appropriate), they can send log messages to qemu
- which will be logged to wherever qemu's logs go
+...) Once the drivers have checked the magic number, they can send log
+ messages to qemu which will be logged to wherever qemu's logs go
(/var/log/xen/qemu-dm.log on normal Xen, dom0 syslog on
XenServer). These messages are written to IO port 0x12 a byte at
a time, and are terminated by newlines. There's a fairly
used for anything even vaguely high-volume, but they're rather
useful for debugging and support.
+ It is still permitted for a driver to use this logging feature if
+ it is blacklisted, but ONLY if it has checked the magic number
+ and found it to be 0x49d2 or 0xd249.
+
This isn't exactly a pretty protocol, but it does solve the problem.
/mh/driver-blacklist/{product_name}/{build_number} exists and is
readable, where {build_number} is the build number from step 4 as a
decimal number. {product_name} is a string corresponding to the
-product number in step 3; at present, the only product number is 1,
-which has a product_name of xensource-windows.
-
-
-A previous version of the protocol put the IO ports on the PCI
-platform device. Unfortunately, that makes it difficult to get at
-them before PCI bus enumeration happens, which complicates removal of
-the emulated NICs. It is possible to work around these but (at least
-on Windows) it's complicated and messy, and generally best avoided.
+product number in step 3.
-Steven.
-support-hvm-pv-drivers-ioemu-support
-hvm-log-to-dom0
-rate_limit_guest_syslog
-pv-driver-version
-Index: ioemu-remote/hw/ide.c
-===================================================================
---- ioemu-remote.orig/hw/ide.c 2008-12-15 16:02:19.000000000 +0000
-+++ ioemu-remote/hw/ide.c 2008-12-15 16:02:35.000000000 +0000
-@@ -484,6 +484,7 @@
- int type; /* see IDE_TYPE_xxx */
- } PCIIDEState;
-
-+static PCIIDEState *principal_ide_controller;
-
- #if defined(__ia64__)
- #include <xen/hvm/ioreq.h>
-@@ -2778,6 +2779,47 @@
- s->media_changed = 0;
- }
-
-+/* Unplug all of the IDE hard disks, starting at index @start in the
-+ table. */
-+static void _ide_unplug_harddisks(int start)
-+{
-+ IDEState *s;
-+ int i, j;
-+
-+ if (!principal_ide_controller) {
-+ fprintf(stderr, "No principal controller?\n");
-+ return;
-+ }
-+ 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_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);
-+}
-+
-+/* Unplug all hard disks, including the boot device. */
-+void ide_unplug_harddisks(void)
-+{
-+ _ide_unplug_harddisks(0);
-+}
-+
-+
- struct partition {
- uint8_t boot_ind; /* 0x80 - active */
- uint8_t head; /* starting head */
-@@ -3290,6 +3332,9 @@
- sizeof(PCIIDEState),
- -1,
- NULL, NULL);
-+ if (principal_ide_controller)
-+ abort();
-+ principal_ide_controller = d;
- d->type = IDE_TYPE_CMD646;
- pci_conf = d->dev.config;
- pci_conf[0x00] = 0x95; // CMD646
-@@ -3419,6 +3464,9 @@
- sizeof(PCIIDEState),
- devfn,
- NULL, NULL);
-+ if (principal_ide_controller)
-+ abort();
-+ principal_ide_controller = d;
- d->type = IDE_TYPE_PIIX3;
-
- pci_conf = d->dev.config;
-Index: ioemu-remote/hw/pci.c
-===================================================================
---- ioemu-remote.orig/hw/pci.c 2008-12-15 16:02:19.000000000 +0000
-+++ ioemu-remote/hw/pci.c 2008-12-15 16:02:22.000000000 +0000
-@@ -26,6 +26,9 @@
- #include "console.h"
- #include "net.h"
-
-+#include "exec-all.h"
-+#include "qemu-xen.h"
-+
- //#define DEBUG_PCI
-
- struct PCIBus {
-@@ -648,6 +651,46 @@
- }
- }
-
-+void pci_unplug_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) {
-+ /* 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);
-+ }
-+ }
-+ }
-+ }
-+ }
-+}
-+
- typedef struct {
- PCIDevice dev;
- PCIBus *bus;
-Index: ioemu-remote/qemu-xen.h
-===================================================================
---- ioemu-remote.orig/qemu-xen.h 2008-12-15 16:02:19.000000000 +0000
-+++ ioemu-remote/qemu-xen.h 2008-12-15 16:02:22.000000000 +0000
-@@ -26,8 +26,11 @@
- void xen_vga_vram_map(uint64_t vram_addr, int copy);
- #endif
-
--
-+void ide_unplug_harddisks(void);
-+void net_tap_shutdown_all(void);
-+void pci_unplug_netifs(void);
- void destroy_hvm_domain(void);
-+void unregister_iomem(target_phys_addr_t start);
-
- #ifdef __ia64__
- static inline void xc_domain_shutdown_hook(int xc_handle, uint32_t domid)
-Index: ioemu-remote/vl.c
-===================================================================
---- ioemu-remote.orig/vl.c 2008-12-15 16:02:19.000000000 +0000
-+++ ioemu-remote/vl.c 2008-12-15 16:02:22.000000000 +0000
-@@ -262,6 +262,20 @@
-
- #include "xen-vl-extra.c"
-
-+typedef struct IOHandlerRecord {
-+ int fd;
-+ IOCanRWHandler *fd_read_poll;
-+ IOHandler *fd_read;
-+ IOHandler *fd_write;
-+ int deleted;
-+ void *opaque;
-+ /* temporary data */
-+ struct pollfd *ufd;
-+ struct IOHandlerRecord *next;
-+} IOHandlerRecord;
-+
-+static IOHandlerRecord *first_io_handler;
-+
- /***********************************************************/
- /* x86 ISA bus support */
-
-@@ -4055,6 +4069,7 @@
- typedef struct TAPState {
- VLANClientState *vc;
- int fd;
-+ struct TAPState *next;
- char down_script[1024];
- char script_arg[1024];
- } TAPState;
-@@ -4092,6 +4107,34 @@
- }
- }
-
-+static TAPState *head_net_tap;
-+
-+void net_tap_shutdown_all(void)
-+{
-+ struct IOHandlerRecord **pioh, *ioh;
-+
-+ while (head_net_tap) {
-+ pioh = &first_io_handler;
-+ for (;;) {
-+ ioh = *pioh;
-+ if (ioh == NULL)
-+ break;
-+ if (ioh->fd == head_net_tap->fd) {
-+ *pioh = ioh->next;
-+ qemu_free(ioh);
-+ break;
-+ }
-+ pioh = &ioh->next;
-+ }
-+ if (!ioh)
-+ fprintf(stderr,
-+ "warning: can't find iohandler for %d to close it properly.\n",
-+ head_net_tap->fd);
-+ close(head_net_tap->fd);
-+ head_net_tap = head_net_tap->next;
-+ }
-+}
-+
- /* fd support */
-
- static TAPState *net_tap_fd_init(VLANState *vlan, int fd)
-@@ -4103,6 +4146,8 @@
- return NULL;
- s->fd = fd;
- s->vc = qemu_new_vlan_client(vlan, tap_receive, NULL, s);
-+ s->next = head_net_tap;
-+ head_net_tap = s;
- qemu_set_fd_handler(s->fd, tap_send, NULL, s);
- snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: fd=%d", fd);
- return s;
-@@ -5666,20 +5711,6 @@
-
- #define MAX_IO_HANDLERS 64
-
--typedef struct IOHandlerRecord {
-- int fd;
-- IOCanRWHandler *fd_read_poll;
-- IOHandler *fd_read;
-- IOHandler *fd_write;
-- int deleted;
-- void *opaque;
-- /* temporary data */
-- struct pollfd *ufd;
-- struct IOHandlerRecord *next;
--} IOHandlerRecord;
--
--static IOHandlerRecord *first_io_handler;
--
- /* XXX: fd_read_poll should be suppressed, but an API change is
- necessary in the character devices to suppress fd_can_read(). */
- int qemu_set_fd_handler2(int fd,
-Index: ioemu-remote/block-raw-posix.c
-===================================================================
---- ioemu-remote.orig/block-raw-posix.c 2008-12-15 16:02:19.000000000 +0000
-+++ ioemu-remote/block-raw-posix.c 2008-12-15 16:02:22.000000000 +0000
-@@ -55,6 +55,7 @@
- #include <sys/ioctl.h>
- #include <linux/cdrom.h>
- #include <linux/fd.h>
-+#include <sys/mount.h>
- #endif
- #ifdef __FreeBSD__
- #include <sys/disk.h>
-@@ -125,6 +126,10 @@
- return ret;
- }
- s->fd = fd;
-+#ifndef CONFIG_STUBDOM
-+ /* Invalidate buffer cache for this device. */
-+ ioctl(s->fd, BLKFLSBUF, 0);
-+#endif
- return 0;
- }
-
-@@ -505,6 +510,10 @@
- {
- BDRVRawState *s = bs->opaque;
- if (s->fd >= 0) {
-+#ifndef CONFIG_STUBDOM
-+ /* Invalidate buffer cache for this device. */
-+ ioctl(s->fd, BLKFLSBUF, 0);
-+#endif
- close(s->fd);
- s->fd = -1;
- }
-Index: ioemu-remote/i386-dm/exec-dm.c
-===================================================================
---- ioemu-remote.orig/i386-dm/exec-dm.c 2008-12-15 16:02:19.000000000 +0000
-+++ ioemu-remote/i386-dm/exec-dm.c 2008-12-15 16:02:22.000000000 +0000
-@@ -267,7 +267,7 @@
-
- /* XXX: Simple implementation. Fix later */
- #define MAX_MMIO 32
--struct mmio_space {
-+static struct mmio_space {
- target_phys_addr_t start;
- unsigned long size;
- unsigned long io_index;
-@@ -413,6 +413,17 @@
- return 0;
- }
-
-+void unregister_iomem(target_phys_addr_t start)
-+{
-+ int index = iomem_index(start);
-+ if (index) {
-+ fprintf(logfile, "squash iomem [%lx, %lx).\n", mmio[index].start,
-+ mmio[index].start + mmio[index].size);
-+ mmio[index].start = mmio[index].size = 0;
-+ }
-+}
-+
-+
- #if defined(__i386__) || defined(__x86_64__)
- #define phys_ram_addr(x) (qemu_map_cache(x))
- #elif defined(__ia64__)
-Index: ioemu-remote/hw/xen_platform.c
-===================================================================
---- ioemu-remote.orig/hw/xen_platform.c 2008-12-15 16:02:19.000000000 +0000
-+++ ioemu-remote/hw/xen_platform.c 2008-12-15 16:02:35.000000000 +0000
-@@ -24,6 +24,7 @@
- */
-
- #include "hw.h"
-+#include "pc.h"
- #include "pci.h"
- #include "irq.h"
- #include "qemu-xen.h"
-@@ -163,6 +164,52 @@
- cpu_register_physical_memory(addr, 0x1000000, mmio_io_addr);
- }
-
-+#define UNPLUG_ALL_IDE_DISKS 1
-+#define UNPLUG_ALL_NICS 2
-+#define UNPLUG_AUX_IDE_DISKS 4
-+
-+static void platform_fixed_ioport_write2(void *opaque, uint32_t addr, uint32_t val)
-+{
-+ switch (addr - 0x10) {
-+ case 0:
-+ /* Unplug devices. Value is a bitmask of which devices to
-+ 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();
-+ if (val & UNPLUG_ALL_NICS) {
-+ pci_unplug_netifs();
-+ net_tap_shutdown_all();
-+ }
-+ if (val & UNPLUG_AUX_IDE_DISKS) {
-+ ide_unplug_aux_harddisks();
-+ }
-+ break;
-+ }
-+}
-+
-+static uint32_t platform_fixed_ioport_read2(void *opaque, uint32_t addr)
-+{
-+ switch (addr - 0x10) {
-+ case 0:
-+ return 0x49d2; /* Magic value so that you can identify the
-+ interface. */
-+ default:
-+ return 0xffff;
-+ }
-+}
-+
-+static uint32_t platform_fixed_ioport_read1(void *opaque, uint32_t addr)
-+{
-+ switch (addr - 0x10) {
-+ case 2:
-+ /* Version number */
-+ return 0;
-+ default:
-+ return 0xff;
-+ }
-+}
-+
- struct pci_config_header {
- uint16_t vendor_id;
- uint16_t device_id;
-@@ -255,4 +302,7 @@
-
- register_savevm("platform", 0, 2, xen_pci_save, xen_pci_load, d);
- printf("Done register platform.\n");
-+ register_ioport_write(0x10, 16, 2, platform_fixed_ioport_write2, NULL);
-+ register_ioport_read(0x10, 16, 2, platform_fixed_ioport_read2, NULL);
-+ register_ioport_read(0x10, 16, 1, platform_fixed_ioport_read1, NULL);
- }
-Index: ioemu-remote/hw/pc.h
-===================================================================
---- ioemu-remote.orig/hw/pc.h 2008-12-15 16:02:19.000000000 +0000
-+++ ioemu-remote/hw/pc.h 2008-12-15 16:02:35.000000000 +0000
-@@ -146,6 +146,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_aux_harddisks(void);
-
- /* ne2000.c */
-
-Index: ioemu-remote/hw/xen_platform.c
-===================================================================
---- ioemu-remote.orig/hw/xen_platform.c 2008-12-15 15:57:04.000000000 +0000
-+++ ioemu-remote/hw/xen_platform.c 2008-12-15 16:00:19.000000000 +0000
-@@ -31,6 +31,8 @@
- #include <xenguest.h>
-
- extern FILE *logfile;
-+static char log_buffer[4096];
-+static int log_buffer_off;
-
- #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
-
-@@ -68,6 +70,18 @@
- d->platform_flags = val & PFFLAG_ROM_LOCK;
- break;
- }
-+ case 8:
-+ {
-+ if (val == '\n' || log_buffer_off == sizeof(log_buffer) - 1) {
-+ /* Flush buffer */
-+ log_buffer[log_buffer_off] = 0;
-+ fprintf(logfile, "%s\n", log_buffer);
-+ log_buffer_off = 0;
-+ break;
-+ }
-+ log_buffer[log_buffer_off++] = val;
-+ }
-+ break;
- default:
- break;
- }
-@@ -180,6 +194,24 @@
- }
- }
-
-+
-+static void platform_fixed_ioport_write1(void *opaque, uint32_t addr, uint32_t val)
-+{
-+ switch (addr - 0x10) {
-+ case 2:
-+ /* Send bytes to syslog */
-+ if (val == '\n' || log_buffer_off == sizeof(log_buffer) - 1) {
-+ /* Flush buffer */
-+ log_buffer[log_buffer_off] = 0;
-+ fprintf(logfile, "%s\n", log_buffer);
-+ log_buffer_off = 0;
-+ break;
-+ }
-+ log_buffer[log_buffer_off++] = val;
-+ break;
-+ }
-+}
-+
- static uint32_t platform_fixed_ioport_read2(void *opaque, uint32_t addr)
- {
- switch (addr - 0x10) {
-@@ -295,6 +327,7 @@
- register_savevm("platform", 0, 2, xen_pci_save, xen_pci_load, d);
- printf("Done register platform.\n");
- register_ioport_write(0x10, 16, 2, platform_fixed_ioport_write2, NULL);
-+ register_ioport_write(0x10, 16, 1, platform_fixed_ioport_write1, NULL);
- register_ioport_read(0x10, 16, 2, platform_fixed_ioport_read2, NULL);
- register_ioport_read(0x10, 16, 1, platform_fixed_ioport_read1, NULL);
- }
-Index: ioemu-remote/hw/xen_platform.c
-===================================================================
---- ioemu-remote.orig/hw/xen_platform.c 2008-12-15 15:02:53.000000000 +0000
-+++ ioemu-remote/hw/xen_platform.c 2008-12-15 15:03:34.000000000 +0000
-@@ -29,8 +29,10 @@
- #include "irq.h"
- #include "qemu-xen.h"
-
-+#include <assert.h>
- #include <xenguest.h>
-
-+static int throttling_disabled;
- extern FILE *logfile;
- static char log_buffer[4096];
- static int log_buffer_off;
-@@ -44,6 +46,88 @@
- uint64_t vga_stolen_ram;
- } PCIXenPlatformState;
-
-+/* 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.
-+ The bucket size is 128KB (->1024 lines of 128 bytes each) and
-+ refills at 256B/s. It starts full. The guest is blocked if no
-+ tokens are available when it tries to generate a log message. */
-+#define BUCKET_MAX_SIZE (128*1024)
-+#define BUCKET_FILL_RATE 256
-+
-+static void throttle(unsigned count)
-+{
-+ static unsigned available;
-+ static struct timespec last_refil;
-+ static int started;
-+ static int warned;
-+
-+ struct timespec waiting_for, now;
-+ double delay;
-+ struct timespec ts;
-+
-+ if (throttling_disabled)
-+ return;
-+
-+ if (!started) {
-+ clock_gettime(CLOCK_MONOTONIC, &last_refil);
-+ available = BUCKET_MAX_SIZE;
-+ started = 1;
-+ }
-+
-+ if (count > BUCKET_MAX_SIZE) {
-+ fprintf(logfile, "tried to get %d tokens, but bucket size is %d\n",
-+ BUCKET_MAX_SIZE, count);
-+ exit(1);
-+ }
-+
-+ if (available < count) {
-+ /* The bucket is empty. Refil it */
-+
-+ /* When will it be full enough to handle this request? */
-+ delay = (double)(count - available) / BUCKET_FILL_RATE;
-+ waiting_for = last_refil;
-+ waiting_for.tv_sec += delay;
-+ waiting_for.tv_nsec += (delay - (int)delay) * 1e9;
-+ if (waiting_for.tv_nsec >= 1000000000) {
-+ waiting_for.tv_nsec -= 1000000000;
-+ waiting_for.tv_sec++;
-+ }
-+
-+ /* How long do we have to wait? (might be negative) */
-+ clock_gettime(CLOCK_MONOTONIC, &now);
-+ ts.tv_sec = waiting_for.tv_sec - now.tv_sec;
-+ ts.tv_nsec = waiting_for.tv_nsec - now.tv_nsec;
-+ if (ts.tv_nsec < 0) {
-+ ts.tv_sec--;
-+ ts.tv_nsec += 1000000000;
-+ }
-+
-+ /* Wait for it. */
-+ if (ts.tv_sec > 0 ||
-+ (ts.tv_sec == 0 && ts.tv_nsec > 0)) {
-+ if (!warned) {
-+ fprintf(logfile, "throttling guest access to syslog");
-+ warned = 1;
-+ }
-+ while (nanosleep(&ts, &ts) < 0 && errno == EINTR)
-+ ;
-+ }
-+
-+ /* Refil */
-+ clock_gettime(CLOCK_MONOTONIC, &now);
-+ delay = (now.tv_sec - last_refil.tv_sec) +
-+ (now.tv_nsec - last_refil.tv_nsec) * 1.0e-9;
-+ available += BUCKET_FILL_RATE * delay;
-+ if (available > BUCKET_MAX_SIZE)
-+ available = BUCKET_MAX_SIZE;
-+ last_refil = now;
-+ }
-+
-+ assert(available >= count);
-+
-+ available -= count;
-+}
-+
- static uint32_t xen_platform_ioport_readb(void *opaque, uint32_t addr)
- {
- PCIXenPlatformState *s = opaque;
-@@ -76,6 +160,7 @@
- if (val == '\n' || log_buffer_off == sizeof(log_buffer) - 1) {
- /* Flush buffer */
- log_buffer[log_buffer_off] = 0;
-+ throttle(log_buffer_off);
- fprintf(logfile, "%s\n", log_buffer);
- log_buffer_off = 0;
- break;
-@@ -278,6 +363,7 @@
- if (val == '\n' || log_buffer_off == sizeof(log_buffer) - 1) {
- /* Flush buffer */
- log_buffer[log_buffer_off] = 0;
-+ throttle(log_buffer_off);
- fprintf(logfile, "%s\n", log_buffer);
- log_buffer_off = 0;
- break;
-@@ -302,6 +388,7 @@
- {
- PCIXenPlatformState *d;
- struct pci_config_header *pch;
-+ struct stat stbuf;
-
- printf("Register xen platform.\n");
- d = (PCIXenPlatformState *)pci_register_device(
-@@ -337,4 +424,8 @@
- register_ioport_write(0x10, 16, 1, platform_fixed_ioport_write1, NULL);
- register_ioport_read(0x10, 16, 2, platform_fixed_ioport_read2, NULL);
- register_ioport_read(0x10, 16, 1, platform_fixed_ioport_read1, NULL);
-+
-+ if (stat("/etc/disable-guest-log-throttle", &stbuf) == 0)
-+ throttling_disabled = 1;
-+
- }
-Index: ioemu-remote/hw/xen_platform.c
-===================================================================
---- ioemu-remote.orig/hw/xen_platform.c 2008-12-15 15:03:34.000000000 +0000
-+++ ioemu-remote/hw/xen_platform.c 2008-12-15 15:06:08.000000000 +0000
-@@ -32,6 +32,8 @@
- #include <assert.h>
- #include <xenguest.h>
-
-+static int drivers_blacklisted;
-+static uint16_t driver_product_version;
- static int throttling_disabled;
- extern FILE *logfile;
- static char log_buffer[4096];
-@@ -341,6 +343,42 @@
- ide_unplug_aux_harddisks();
- }
- break;
-+ case 2:
-+ switch (val) {
-+ case 1:
-+ fprintf(logfile, "Citrix Windows PV drivers loaded in guest\n");
-+ break;
-+ case 0:
-+ fprintf(logfile, "Guest claimed to be running PV product 0?\n");
-+ break;
-+ default:
-+ fprintf(logfile, "Unknown PV product %d loaded in guest\n", val);
-+ break;
-+ }
-+ driver_product_version = val;
-+ break;
-+ }
-+}
-+
-+static void platform_fixed_ioport_write4(void *opaque, uint32_t addr,
-+ uint32_t val)
-+{
-+ switch (addr - 0x10) {
-+ case 0:
-+ /* PV driver version */
-+ if (driver_product_version == 0) {
-+ fprintf(logfile,
-+ "Drivers tried to set their version number (%d) before setting the product number?\n",
-+ val);
-+ return;
-+ }
-+ fprintf(logfile, "PV driver build %d\n", val);
-+ if (xenstore_pv_driver_build_blacklisted(driver_product_version,
-+ val)) {
-+ fprintf(logfile, "Drivers are blacklisted!\n");
-+ drivers_blacklisted = 1;
-+ }
-+ break;
- }
- }
-
-@@ -348,8 +386,14 @@
- {
- switch (addr - 0x10) {
- case 0:
-- return 0x49d2; /* Magic value so that you can identify the
-- interface. */
-+ if (drivers_blacklisted) {
-+ /* The drivers will recognise this magic number and refuse
-+ * to do anything. */
-+ return 0xd249;
-+ } else {
-+ /* Magic value so that you can identify the interface. */
-+ return 0x49d2;
-+ }
- default:
- return 0xffff;
- }
-@@ -378,7 +422,7 @@
- switch (addr - 0x10) {
- case 2:
- /* Version number */
-- return 0;
-+ return 1;
- default:
- return 0xff;
- }
-@@ -420,6 +464,7 @@
-
- register_savevm("platform", 0, 2, xen_pci_save, xen_pci_load, d);
- printf("Done register platform.\n");
-+ register_ioport_write(0x10, 16, 4, platform_fixed_ioport_write4, NULL);
- register_ioport_write(0x10, 16, 2, platform_fixed_ioport_write2, NULL);
- register_ioport_write(0x10, 16, 1, platform_fixed_ioport_write1, NULL);
- register_ioport_read(0x10, 16, 2, platform_fixed_ioport_read2, NULL);
-Index: ioemu-remote/qemu-xen.h
-===================================================================
---- ioemu-remote.orig/qemu-xen.h 2008-12-15 15:02:53.000000000 +0000
-+++ ioemu-remote/qemu-xen.h 2008-12-15 15:06:39.000000000 +0000
-@@ -91,6 +91,8 @@
- char *xenstore_device_model_read(int domid, char *key, unsigned int *len);
- char *xenstore_read_battery_data(int battery_status);
- int xenstore_refresh_battery_status(void);
-+int xenstore_pv_driver_build_blacklisted(uint16_t product_number,
-+ uint32_t build_nr);
-
- /* xenfbfront.c */
- int xenfb_pv_display_init(DisplayState *ds);
-Index: ioemu-remote/xenstore.c
-===================================================================
---- ioemu-remote.orig/xenstore.c 2008-12-15 14:30:47.000000000 +0000
-+++ ioemu-remote/xenstore.c 2008-12-15 15:06:08.000000000 +0000
-@@ -782,6 +782,34 @@
- free(path);
- }
-
-+int
-+xenstore_pv_driver_build_blacklisted(uint16_t product_nr,
-+ uint32_t build_nr)
-+{
-+ char *buf = NULL;
-+ char *tmp;
-+ const char *product;
-+
-+ switch (product_nr) {
-+ case 1:
-+ product = "xensource-windows";
-+ break;
-+ default:
-+ /* Don't know what product this is -> we can't blacklist
-+ * it. */
-+ return 0;
-+ }
-+ if (asprintf(&buf, "/mh/driver-blacklist/%s/%d", product, build_nr) < 0)
-+ return 0;
-+ tmp = xs_read(xsh, XBT_NULL, buf, NULL);
-+ free(tmp);
-+ free(buf);
-+ if (tmp == NULL)
-+ return 0;
-+ else
-+ return 1;
-+}
-+
- void xenstore_record_dm_state(char *state)
- {
- xenstore_record_dm("state", state);
-application/pgp-signature [Press RETURN to save to a file]
+The master registry of product names and numbers is in
+qemu-xen-unstable's xenstore.c.