[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] Device model unplug version 2:
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |