Index: xen-unstable/tools/ioemu/hw/ide.c =================================================================== --- xen-unstable.orig/tools/ioemu/hw/ide.c +++ xen-unstable/tools/ioemu/hw/ide.c @@ -392,6 +392,9 @@ typedef struct PCIIDEState { int type; /* see IDE_TYPE_xxx */ } PCIIDEState; +static PCIIDEState *principal_ide_controller; +extern FILE *logfile; + #define DMA_MULTI_THREAD #ifdef DMA_MULTI_THREAD @@ -2165,6 +2168,27 @@ static void ide_reset(IDEState *s) ide_dummy_transfer_stop(s); } +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 */ @@ -2600,6 +2624,9 @@ 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 @@ -2771,6 +2798,9 @@ 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-unstable/tools/ioemu/hw/pci.c =================================================================== --- xen-unstable.orig/tools/ioemu/hw/pci.c +++ xen-unstable/tools/ioemu/hw/pci.c @@ -517,3 +517,24 @@ 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; + } + } + } +} Index: xen-unstable/tools/ioemu/hw/xen_platform.c =================================================================== --- xen-unstable.orig/tools/ioemu/hw/xen_platform.c +++ xen-unstable/tools/ioemu/hw/xen_platform.c @@ -29,15 +29,46 @@ extern FILE *logfile; +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, 1, 1, platform_ioport_write, NULL); } Index: xen-unstable/tools/ioemu/vl.c =================================================================== --- xen-unstable.orig/tools/ioemu/vl.c +++ xen-unstable/tools/ioemu/vl.c @@ -170,6 +170,19 @@ time_t timeoffset = 0; char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'}; extern int domid; +typedef struct IOHandlerRecord { + int fd; + IOCanRWHandler *fd_read_poll; + IOHandler *fd_read; + IOHandler *fd_write; + void *opaque; + /* temporary data */ + struct pollfd *ufd; + struct IOHandlerRecord *next; +} IOHandlerRecord; + +static IOHandlerRecord *first_io_handler; + char vncpasswd[64]; unsigned char challenge[AUTHCHALLENGESIZE]; @@ -3139,6 +3152,7 @@ void net_slirp_smb(const char *exported_ typedef struct TAPState { VLANClientState *vc; int fd; + struct TAPState *next; } TAPState; static void tap_receive(void *opaque, const uint8_t *buf, int size) @@ -3166,6 +3180,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) @@ -3177,6 +3221,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; @@ -4117,19 +4163,6 @@ void dumb_display_init(DisplayState *ds) #define MAX_IO_HANDLERS 64 -typedef struct IOHandlerRecord { - int fd; - IOCanRWHandler *fd_read_poll; - IOHandler *fd_read; - IOHandler *fd_write; - 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-unstable/tools/ioemu/vl.h =================================================================== --- xen-unstable.orig/tools/ioemu/vl.h +++ xen-unstable/tools/ioemu/vl.h @@ -844,6 +844,7 @@ void pci_piix3_ide_init(PCIBus *bus, Blo int pmac_ide_init (BlockDriverState **hd_table, SetIRQFunc *set_irq, void *irq_opaque, int irq); void ide_stop_dma_thread(void); +void ide_unplug_harddisks(void); /* cdrom.c */ int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track); @@ -1286,6 +1287,8 @@ void kqemu_record_dump(void); extern char domain_name[]; void destroy_hvm_domain(void); +void net_tap_shutdown_all(void); +void pci_unplug_netifs(void); /* VNC Authentication */ #define AUTHCHALLENGESIZE 16