[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [patch 16/24] QEMU/KVM: device and disk hot-add
From: |
Marcelo Tosatti |
Subject: |
[Qemu-devel] [patch 16/24] QEMU/KVM: device and disk hot-add |
Date: |
Tue, 11 Mar 2008 17:12:07 -0300 |
User-agent: |
quilt/0.46-1 |
Add monitor command to hot-add PCI devices (nic and storage).
Syntax is:
pci_add pcibus nic|storage params
It returns the bus slot and function for the newly added device on success.
It is possible to attach a disk to a device after PCI initialization via
the drive_add command. If so, a manual scan of the SCSI bus on the guest
is necessary.
Save QEMUMachine necessary for drive_init.
Signed-off-by: Marcelo Tosatti <address@hidden>
Index: kvm-userspace.hotplug2/qemu/Makefile.target
===================================================================
--- kvm-userspace.hotplug2.orig/qemu/Makefile.target
+++ kvm-userspace.hotplug2/qemu/Makefile.target
@@ -579,6 +579,8 @@ OBJS+= hypercall.o
# virtio devices
OBJS += virtio.o virtio-net.o virtio-blk.o
+OBJS += device-hotplug.o
+
ifeq ($(TARGET_BASE_ARCH), i386)
# Hardware support
OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o
Index: kvm-userspace.hotplug2/qemu/hw/device-hotplug.c
===================================================================
--- /dev/null
+++ kvm-userspace.hotplug2/qemu/hw/device-hotplug.c
@@ -0,0 +1,158 @@
+#include "hw.h"
+#include "boards.h"
+#include "pci.h"
+#include "net.h"
+#include "sysemu.h"
+#include "pc.h"
+#include "console.h"
+
+static PCIDevice *qemu_system_hot_add_nic(const char *opts, int bus_nr)
+{
+ int ret;
+ char buf[4096];
+ PCIBus *pci_bus;
+
+ pci_bus = pci_find_bus (bus_nr);
+ if (!pci_bus) {
+ term_printf ("Can't find pci_bus %d\n", bus_nr);
+ return NULL;
+ }
+
+ memset (buf, 0, sizeof (buf));
+
+ strcpy (buf, "nic,");
+ strncat (buf, opts, sizeof (buf) - strlen (buf) - 1);
+
+ ret = net_client_init (buf);
+ if (ret < 0 || !nd_table[ret].model)
+ return NULL;
+ return pci_nic_init (pci_bus, &nd_table[ret], -1);
+}
+
+static int add_init_drive(const char *opts)
+{
+ int drive_opt_idx, drive_idx;
+ int ret = -1;
+
+ drive_opt_idx = drive_add(NULL, "%s", opts);
+ if (!drive_opt_idx)
+ return ret;
+
+ drive_idx = drive_init(&drives_opt[drive_opt_idx], 0, current_machine);
+ if (drive_idx == -1) {
+ drive_remove(drive_opt_idx);
+ return ret;
+ }
+
+ return drive_idx;
+}
+
+void drive_hot_add(int pcibus, const char *devfn_string, const char *opts)
+{
+ int drive_idx, type, bus;
+ int devfn;
+ int success = 0;
+ PCIDevice *dev;
+
+ devfn = strtoul(devfn_string, NULL, 0);
+
+ dev = pci_find_device(pcibus, PCI_SLOT(devfn));
+ if (!dev) {
+ term_printf("no pci device with devfn %d (slot %d)\n", devfn,
+ PCI_SLOT(devfn));
+ return;
+ }
+
+ drive_idx = add_init_drive(opts);
+ if (drive_idx < 0)
+ return;
+ type = drives_table[drive_idx].type;
+ bus = drive_get_max_bus (type);
+
+ switch (type) {
+ case IF_SCSI:
+ success = 1;
+ lsi_scsi_attach (dev, drives_table[drive_idx].bdrv,
+ drives_table[drive_idx].unit);
+ break;
+ default:
+ term_printf("Can't hot-add drive to type %d\n", type);
+ }
+
+ if (success)
+ term_printf("OK bus %d, unit %d\n", drives_table[drive_idx].bus,
+ drives_table[drive_idx].unit);
+ return;
+}
+
+static PCIDevice *qemu_system_hot_add_storage(const char *opts, int bus_nr)
+{
+ void *opaque = NULL;
+ PCIBus *pci_bus;
+ int type = -1, drive_idx = -1;
+ char buf[128];
+
+ pci_bus = pci_find_bus(bus_nr);
+ if (!pci_bus) {
+ term_printf("Can't find pci_bus %d\n", bus_nr);
+ return NULL;
+ }
+
+ if (get_param_value(buf, sizeof(buf), "if", opts)) {
+ if (!strcmp(buf, "scsi"))
+ type = IF_SCSI;
+ else if (!strcmp(buf, "virtio")) {
+ type = IF_VIRTIO;
+ }
+ } else {
+ term_printf("no if= specified\n");
+ return NULL;
+ }
+
+ if (get_param_value(buf, sizeof(buf), "file", opts)) {
+ drive_idx = add_init_drive(opts);
+ if (drive_idx < 0)
+ return NULL;
+ } else if (type == IF_VIRTIO) {
+ term_printf("virtio requires a backing file/device.\n");
+ return NULL;
+ }
+
+ switch (type) {
+ case IF_SCSI:
+ opaque = lsi_scsi_init (pci_bus, -1);
+ if (drive_idx >= 0)
+ lsi_scsi_attach (opaque, drives_table[drive_idx].bdrv,
+ drives_table[drive_idx].unit);
+ break;
+ case IF_VIRTIO:
+ opaque = virtio_blk_init (pci_bus, 0x1AF4, 0x1001,
+ drives_table[drive_idx].bdrv);
+ break;
+ default:
+ term_printf ("type %s not a hotpluggable PCI device.\n", buf);
+ }
+
+ return opaque;
+}
+
+void device_hot_add(int pcibus, const char *type, const char *opts)
+{
+ PCIDevice *dev = NULL;
+
+ if (strcmp(type, "nic") == 0)
+ dev = qemu_system_hot_add_nic(opts, pcibus);
+ else if (strcmp(type, "storage") == 0)
+ dev = qemu_system_hot_add_storage(opts, pcibus);
+ else
+ term_printf("invalid type: %s\n", type);
+
+ if (dev) {
+ qemu_system_device_hot_add(PCI_SLOT(dev->devfn), 1);
+ term_printf("OK bus %d, slot %d, function %d (devfn %d)\n",
+ pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), dev->devfn);
+ } else
+ term_printf("failed to add %s\n", opts);
+}
+
Index: kvm-userspace.hotplug2/qemu/monitor.c
===================================================================
--- kvm-userspace.hotplug2.orig/qemu/monitor.c
+++ kvm-userspace.hotplug2/qemu/monitor.c
@@ -1359,6 +1359,12 @@ static term_cmd_t term_cmds[] = {
{ "migrate_set_speed", "s", do_migrate_set_speed,
"value", "set maximum speed (in bytes) for migrations" },
{ "cpu_set", "is", do_cpu_set_nr, "cpu [online|offline]", "change cpu
state" },
+ { "drive_add", "iss", drive_hot_add, "pcibus pcidevfn
[file=file][,if=type][,bus=n]\n"
+ "[,unit=m][,media=d][index=i]\n"
+ "[,cyls=c,heads=h,secs=s[,trans=t]]\n"
+ "[snapshot=on|off][,cache=on|off]",
+ "add drive to PCI storage controller"
},
+ { "pci_add", "iss", device_hot_add, "bus nic|storage
[[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]...",
"hot-add PCI device" },
{ NULL, NULL, },
};
Index: kvm-userspace.hotplug2/qemu/hw/boards.h
===================================================================
--- kvm-userspace.hotplug2.orig/qemu/hw/boards.h
+++ kvm-userspace.hotplug2/qemu/hw/boards.h
@@ -19,6 +19,8 @@ typedef struct QEMUMachine {
int qemu_register_machine(QEMUMachine *m);
+extern QEMUMachine *current_machine;
+
/* Axis ETRAX. */
extern QEMUMachine bareetraxfs_machine;
Index: kvm-userspace.hotplug2/qemu/sysemu.h
===================================================================
--- kvm-userspace.hotplug2.orig/qemu/sysemu.h
+++ kvm-userspace.hotplug2/qemu/sysemu.h
@@ -176,6 +176,11 @@ extern int drive_init(struct drive_opt *
/* acpi */
void qemu_system_cpu_hot_add(int cpu, int state);
void qemu_system_hot_add_init(char *cpu_model);
+void qemu_system_device_hot_add(int slot, int state);
+
+/* device-hotplug */
+void device_hot_add(int pcibus, const char *type, const char *opts);
+void drive_hot_add(int pcibus, const char *devfn_string, const char *opts);
/* vmchannel devices */
Index: kvm-userspace.hotplug2/qemu/vl.c
===================================================================
--- kvm-userspace.hotplug2.orig/qemu/vl.c
+++ kvm-userspace.hotplug2/qemu/vl.c
@@ -7610,6 +7610,7 @@ void qemu_bh_delete(QEMUBH *bh)
/* machine registration */
QEMUMachine *first_machine = NULL;
+QEMUMachine *current_machine = NULL;
int qemu_register_machine(QEMUMachine *m)
{
@@ -9767,6 +9768,8 @@ int main(int argc, char **argv)
machine->init(ram_size, vga_ram_size, boot_devices, ds,
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
+ current_machine = machine;
+
/* init USB devices */
if (usb_enabled) {
for(i = 0; i < usb_devices_index; i++) {
--
- [Qemu-devel] Re: [kvm-devel] [patch 17/24] QEMU/KVM: add cpu_unregister_io_memory and make io mem table index dynamic, (continued)
[Qemu-devel] [patch 19/24] QEMU/KVM: handle SEJ notifications, Marcelo Tosatti, 2008/03/12
[Qemu-devel] [patch 20/24] QEMU/KVM: add qemu_free_irqs, Marcelo Tosatti, 2008/03/12
[Qemu-devel] [patch 22/24] QEMU/KVM: LSI SCSI and e1000 unregister callbacks, Marcelo Tosatti, 2008/03/12
[Qemu-devel] [patch 23/24] QEMU/KVM: zero ioport_opaque on isa_unassign_ioport, Marcelo Tosatti, 2008/03/12
[Qemu-devel] [patch 24/24] QEMU/KVM: device hot-remove, Marcelo Tosatti, 2008/03/12
[Qemu-devel] [patch 08/24] QEMU/KVM: drive removal support, Marcelo Tosatti, 2008/03/12
[Qemu-devel] [patch 16/24] QEMU/KVM: device and disk hot-add,
Marcelo Tosatti <=
[Qemu-devel] [patch 21/24] QEMU/KVM: add pci_unregister_device, Marcelo Tosatti, 2008/03/12
[Qemu-devel] [patch 18/24] QEMU/KVM: notify _EJ0 through _SEJ OperationRegion, Marcelo Tosatti, 2008/03/12
[Qemu-devel] Re: [kvm-devel] [patch 00/24] QEMU ACPI PCI hotplug support, Avi Kivity, 2008/03/16