Index: xen-3.3.0-testing/tools/ioemu-remote/hw/ide.c =================================================================== --- xen-3.3.0-testing.orig/tools/ioemu-remote/hw/ide.c +++ xen-3.3.0-testing/tools/ioemu-remote/hw/ide.c @@ -485,6 +485,9 @@ typedef struct PCIIDEState { } PCIIDEState; +static PCIIDEState *principal_ide_controller; +extern FILE *logfile; + #if defined(__ia64__) #include @@ -2778,6 +2781,27 @@ static void ide_reset(IDEState *s) s->media_changed = 0; } +void ide_unplug_harddisks(void) +{ + IDEState *s; + int i; + + if (!principal_ide_controller) { + fprintf(logfile, "No principal controller?\n"); + return; + } + for (i = 0; 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. */ + s->bs = NULL; + ide_reset(s); + } +} + struct partition { uint8_t boot_ind; /* 0x80 - active */ uint8_t head; /* starting head */ @@ -3290,6 +3314,10 @@ void pci_cmd646_ide_init(PCIBus *bus, Bl 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 @@ -3421,6 +3449,10 @@ void pci_piix3_ide_init(PCIBus *bus, Blo NULL, NULL); d->type = IDE_TYPE_PIIX3; + if (principal_ide_controller) + abort(); + principal_ide_controller = d; + pci_conf = d->dev.config; pci_conf[0x00] = 0x86; // Intel pci_conf[0x01] = 0x80; Index: xen-3.3.0-testing/tools/ioemu-remote/hw/pci.c =================================================================== --- xen-3.3.0-testing.orig/tools/ioemu-remote/hw/pci.c +++ xen-3.3.0-testing/tools/ioemu-remote/hw/pci.c @@ -653,6 +653,28 @@ void pci_nic_init(PCIBus *bus, NICInfo * } } +void pci_unplug_netifs(void) +{ + PCIBus *bus; + int x; + + /* We only support one PCI bus */ + for (bus = first_bus; bus; bus = NULL) { + for (x = 0; x < 256; x++) { + if (bus->devices[x] && + bus->devices[x]->config[0xa] == 0 && + bus->devices[x]->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; + } + } + } +} + typedef struct { PCIDevice dev; PCIBus *bus; Index: xen-3.3.0-testing/tools/ioemu-remote/hw/xen_platform.c =================================================================== --- xen-3.3.0-testing.orig/tools/ioemu-remote/hw/xen_platform.c +++ xen-3.3.0-testing/tools/ioemu-remote/hw/xen_platform.c @@ -26,6 +26,8 @@ #include "hw.h" #include "pci.h" #include "irq.h" +#include "sysemu.h" +#include #include @@ -71,12 +73,53 @@ static void xen_platform_ioport_writeb(v } } +static uint32_t ioport_base; + +static void platform_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + DECLARE_DOMCTL; + int rc; + + if (val == 0) + qemu_invalidate_map_cache(); + + switch (addr - ioport_base) { + case 0: + fprintf(logfile, "Init hypercall page %x, addr %x.\n", val, addr); + domctl.domain = (domid_t)domid; + domctl.u.hypercall_init.gmfn = val; + domctl.cmd = XEN_DOMCTL_hypercall_init; + rc = xc_domctl(xc_handle, &domctl); + fprintf(logfile, "result -> %d.\n", rc); + break; + case 4: + fprintf(logfile, "Disconnect IDE hard disk...\n"); + ide_unplug_harddisks(); + fprintf(logfile, "Disconnect netifs...\n"); + pci_unplug_netifs(); + fprintf(logfile, "Shutdown taps...\n"); + net_tap_shutdown_all(); + fprintf(logfile, "Done.\n"); + break; + default: + fprintf(logfile, "Write to bad port %x (base %x) on evtchn device.\n", + addr, ioport_base); + break; + } +} + static void platform_ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type) { + ioport_base = addr; + + register_ioport_write(addr, 16, 4, platform_ioport_write, NULL); +/* PCIXenPlatformState *d = (PCIXenPlatformState *)pci_dev; + register_ioport_write(addr, size, 1, xen_platform_ioport_writeb, d); register_ioport_read(addr, size, 1, xen_platform_ioport_readb, d); +*/ } static uint32_t platform_mmio_read(void *opaque, target_phys_addr_t addr) Index: xen-3.3.0-testing/tools/ioemu-remote/vl.c =================================================================== --- xen-3.3.0-testing.orig/tools/ioemu-remote/vl.c +++ xen-3.3.0-testing/tools/ioemu-remote/vl.c @@ -259,6 +259,20 @@ static int event_pending = 1; #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 */ @@ -4054,6 +4068,7 @@ typedef struct TAPState { int fd; char down_script[1024]; char script_arg[1024]; + struct TAPState *next; } TAPState; static void tap_receive(void *opaque, const uint8_t *buf, int size) @@ -4089,6 +4104,36 @@ static void tap_send(void *opaque) } } +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) @@ -4100,6 +4145,8 @@ static TAPState *net_tap_fd_init(VLANSta 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; @@ -5672,20 +5719,6 @@ static void dumb_display_init(DisplaySta #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: xen-3.3.0-testing/tools/ioemu-remote/sysemu.h =================================================================== --- xen-3.3.0-testing.orig/tools/ioemu-remote/sysemu.h +++ xen-3.3.0-testing/tools/ioemu-remote/sysemu.h @@ -49,6 +49,9 @@ void do_loadvm(const char *name); void do_delvm(const char *name); void do_info_snapshots(void); +void net_tap_shutdown_all(void); +void pci_unplug_netifs(void); + void main_loop_wait(int timeout); /* Polling handling */