Skip to contentSkip to conversation

QEMU ACPI PCI hotplug support

PATCH Applied Marcelo Tosatti 4 participants 30 messages Mar 11, 2008 – Mar 18, 2008 KVM

lore
Share & tools
lore
#0 lore raw

cover QEMU ACPI PCI hotplug support

The following patchset allows PCI hot add/remove through ACPI (handled by the acpiphp driver on Linux guests).

Comments are welcome.

Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#1 lore raw

PATCH 1/24 QEMU/KVM: add devices to represent PCI slots with _EJ0 method

Presence of _EJ0 method indicates that slots are hot-pluggable.

bios/acpi-dsdt.dsl +155 -0
Index: kvm-userspace.hotplug2/bios/acpi-dsdt.dsl
===================================================================
@@ -407,6 +407,161 @@ DefinitionBlock (
                 Package() {0x001fffff, 3, LNKB, 0},
             })
 
+            Device (S1) {              // Slot 1
+               Name (_ADR, 0x00010000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S2) {              // Slot 2
+               Name (_ADR, 0x00020000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S3) {              // Slot 3
+               Name (_ADR, 0x00030000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S4) {              // Slot 4
+               Name (_ADR, 0x00040000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S5) {              // Slot 5
+               Name (_ADR, 0x00050000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S6) {              // Slot 6
+               Name (_ADR, 0x00060000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S7) {              // Slot 7
+               Name (_ADR, 0x00070000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S8) {              // Slot 8
+               Name (_ADR, 0x00080000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S9) {              // Slot 9
+               Name (_ADR, 0x00090000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S10) {              // Slot 10
+               Name (_ADR, 0x000A0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S11) {              // Slot 11
+               Name (_ADR, 0x000B0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S12) {              // Slot 12
+               Name (_ADR, 0x000C0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S13) {              // Slot 13
+               Name (_ADR, 0x000D0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S14) {              // Slot 14
+               Name (_ADR, 0x000E0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S15) {              // Slot 15
+               Name (_ADR, 0x000F0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S16) {              // Slot 16
+               Name (_ADR, 0x00100000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S17) {              // Slot 17
+               Name (_ADR, 0x00110000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S18) {              // Slot 18
+               Name (_ADR, 0x00120000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S19) {              // Slot 19
+               Name (_ADR, 0x00130000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S20) {              // Slot 20
+               Name (_ADR, 0x00140000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S21) {              // Slot 21
+               Name (_ADR, 0x00150000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S22) {              // Slot 22
+               Name (_ADR, 0x00160000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S23) {              // Slot 23
+               Name (_ADR, 0x00170000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S24) {              // Slot 24
+               Name (_ADR, 0x00180000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S25) {              // Slot 25
+               Name (_ADR, 0x00190000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S26) {              // Slot 26
+               Name (_ADR, 0x001A0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S27) {              // Slot 27
+               Name (_ADR, 0x001B0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S28) {              // Slot 28
+               Name (_ADR, 0x001C0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S29) {              // Slot 29
+               Name (_ADR, 0x001D0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S30) {              // Slot 30
+               Name (_ADR, 0x001E0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
+            Device (S31) {              // Slot 31
+               Name (_ADR, 0x001F0000)
+               Method (_EJ0,1) { Return (0x0) }
+            }
+
             Method (_CRS, 0, NotSerialized)
             {
             Name (MEMP, ResourceTemplate ()
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#2 lore raw

PATCH 2/24 QEMU/KVM: add OperationRegion and GPE handler for add/removal notification

In reply to Marcelo Tosatti

Use GPE _L01 to notify OSPM.

bios/acpi-dsdt.dsl +257 -0
Index: kvm-userspace.hotplug2/bios/acpi-dsdt.dsl
===================================================================
@@ -407,6 +407,13 @@ DefinitionBlock (
                 Package() {0x001fffff, 3, LNKB, 0},
             })
 
+            OperationRegion(PCST, SystemIO, 0xae00, 0x08)
+            Field (PCST, DWordAcc, NoLock, WriteAsZeros)
+ 	    {
+ 		PCIU, 32,
+ 		PCID, 32,
+ 	    }
+
             Device (S1) {              // Slot 1
                Name (_ADR, 0x00010000)
                Method (_EJ0,1) { Return (0x0) }
@@ -1142,6 +1149,256 @@ DefinitionBlock (
             Return(0x01)
         }
         Method(_L01) {
+            /* Up status */
+            If (And(\_SB.PCI0.PCIU, 0x2)) {
+                Notify(\_SB.PCI0.S1, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x4)) {
+                Notify(\_SB.PCI0.S2, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x8)) {
+                Notify(\_SB.PCI0.S3, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x10)) {
+                Notify(\_SB.PCI0.S4, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x20)) {
+                Notify(\_SB.PCI0.S5, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x40)) {
+                Notify(\_SB.PCI0.S6, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x80)) {
+                Notify(\_SB.PCI0.S7, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x0100)) {
+                Notify(\_SB.PCI0.S8, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x0200)) {
+                Notify(\_SB.PCI0.S9, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x0400)) {
+                Notify(\_SB.PCI0.S10, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x0800)) {
+                Notify(\_SB.PCI0.S11, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x1000)) {
+                Notify(\_SB.PCI0.S12, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x2000)) {
+                Notify(\_SB.PCI0.S13, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x4000)) {
+                Notify(\_SB.PCI0.S14, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x8000)) {
+                Notify(\_SB.PCI0.S15, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x10000)) {
+                Notify(\_SB.PCI0.S16, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x20000)) {
+                Notify(\_SB.PCI0.S17, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x40000)) {
+                Notify(\_SB.PCI0.S18, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x80000)) {
+                Notify(\_SB.PCI0.S19, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x100000)) {
+                Notify(\_SB.PCI0.S20, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x200000)) {
+                Notify(\_SB.PCI0.S21, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x400000)) {
+                Notify(\_SB.PCI0.S22, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x800000)) {
+                Notify(\_SB.PCI0.S23, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x1000000)) {
+                Notify(\_SB.PCI0.S24, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x2000000)) {
+                Notify(\_SB.PCI0.S25, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x4000000)) {
+                Notify(\_SB.PCI0.S26, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x8000000)) {
+                Notify(\_SB.PCI0.S27, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x10000000)) {
+                Notify(\_SB.PCI0.S28, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x20000000)) {
+                Notify(\_SB.PCI0.S29, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x40000000)) {
+                Notify(\_SB.PCI0.S30, 0x1)
+            }
+
+            If (And(\_SB.PCI0.PCIU, 0x80000000)) {
+                Notify(\_SB.PCI0.S31, 0x1)
+            }
+
+            /* Down status */
+            If (And(\_SB.PCI0.PCID, 0x2)) {
+                Notify(\_SB.PCI0.S1, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x4)) {
+                Notify(\_SB.PCI0.S2, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x8)) {
+                Notify(\_SB.PCI0.S3, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x10)) {
+                Notify(\_SB.PCI0.S4, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x20)) {
+                Notify(\_SB.PCI0.S5, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x40)) {
+                Notify(\_SB.PCI0.S6, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x80)) {
+                Notify(\_SB.PCI0.S7, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x0100)) {
+                Notify(\_SB.PCI0.S8, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x0200)) {
+                Notify(\_SB.PCI0.S9, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x0400)) {
+                Notify(\_SB.PCI0.S10, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x0800)) {
+                Notify(\_SB.PCI0.S11, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x1000)) {
+                Notify(\_SB.PCI0.S12, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x2000)) {
+                Notify(\_SB.PCI0.S13, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x4000)) {
+                Notify(\_SB.PCI0.S14, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x8000)) {
+                Notify(\_SB.PCI0.S15, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x10000)) {
+                Notify(\_SB.PCI0.S16, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x20000)) {
+                Notify(\_SB.PCI0.S17, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x40000)) {
+                Notify(\_SB.PCI0.S18, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x80000)) {
+                Notify(\_SB.PCI0.S19, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x100000)) {
+                Notify(\_SB.PCI0.S20, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x200000)) {
+                Notify(\_SB.PCI0.S21, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x400000)) {
+                Notify(\_SB.PCI0.S22, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x800000)) {
+                Notify(\_SB.PCI0.S23, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x1000000)) {
+                Notify(\_SB.PCI0.S24, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x2000000)) {
+                Notify(\_SB.PCI0.S25, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x4000000)) {
+                Notify(\_SB.PCI0.S26, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x8000000)) {
+                Notify(\_SB.PCI0.S27, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x10000000)) {
+                Notify(\_SB.PCI0.S28, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x20000000)) {
+                Notify(\_SB.PCI0.S29, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x40000000)) {
+                Notify(\_SB.PCI0.S30, 0x3)
+            }
+
+            If (And(\_SB.PCI0.PCID, 0x80000000)) {
+                Notify(\_SB.PCI0.S31, 0x3)
+            }
+
             Return(0x01)
         }
         Method(_L02) {
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#3 lore raw

PATCH 3/24 QEMU/KVM: add pci_find_bus

In reply to Marcelo Tosatti

Return PCIBus pointer from bus number integer.

qemu/hw/pci.c +10 -0
Index: kvm-userspace.hotplug2/qemu/hw/pci.c
===================================================================
@@ -675,6 +675,16 @@ static void pci_bridge_write_config(PCID
     pci_default_write_config(d, address, val, len);
 }
 
+PCIBus *pci_find_bus(int bus_num)
+{
+    PCIBus *bus = first_bus;
+
+    while (bus && bus->bus_num != bus_num)
+        bus = bus->next;
+
+    return bus;
+}
+
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
                         pci_map_irq_fn map_irq, const char *name)
 {
qemu/hw/pci.h +2 -0
Index: kvm-userspace.hotplug2/qemu/hw/pci.h
===================================================================
@@ -3,6 +3,7 @@
 
 /* PCI includes legacy ISA access.  */
 #include "isa.h"
+#include <linux/pci.h>
 
 /* PCI bus */
 
@@ -91,6 +92,7 @@ void pci_data_write(void *opaque, uint32
 uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
 int pci_bus_num(PCIBus *s);
 void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
+PCIBus *pci_find_bus(int bus_num);
 
 void pci_info(void);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#4 lore raw

PATCH 4/24 QEMU/KVM: return PCIDevice on net device init and record devfn

In reply to Marcelo Tosatti

Change the PCI network drivers init functions to return the PCIDev, to inform which slot has been hot-plugged.

Also record devfn on the NICInfo structure to locate for release on hot-removal.

qemu/hw/e1000.c +3 -1
Index: kvm-userspace.hotplug2/qemu/hw/e1000.c
===================================================================
@@ -930,7 +930,7 @@ e1000_mmio_map(PCIDevice *pci_dev, int r
     cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
 }
 
-void
+PCIDevice *
 pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     E1000State *d;
@@ -994,4 +994,6 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd,
              d->nd->macaddr[3], d->nd->macaddr[4], d->nd->macaddr[5]);
 
     register_savevm(info_str, d->instance, 1, nic_save, nic_load, d);
+
+    return (PCIDevice *)d;
 }
qemu/hw/eepro100.c +8 -7
Index: kvm-userspace.hotplug2/qemu/hw/eepro100.c
===================================================================
@@ -1742,7 +1742,7 @@ static void nic_save(QEMUFile * f, void 
     qemu_put_buffer(f, s->configuration, sizeof(s->configuration));
 }
 
-static void nic_init(PCIBus * bus, NICInfo * nd,
+static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd,
                      const char *name, uint32_t device)
 {
     PCIEEPRO100State *d;
@@ -1794,22 +1794,23 @@ static void nic_init(PCIBus * bus, NICIn
 
     /* XXX: instance number ? */
     register_savevm(name, 0, 3, nic_save, nic_load, s);
+    return (PCIDevice *)d;
 }
 
-void pci_i82551_init(PCIBus * bus, NICInfo * nd, int devfn)
+PCIDevice *pci_i82551_init(PCIBus * bus, NICInfo * nd, int devfn)
 {
-    nic_init(bus, nd, "i82551", i82551);
+    return nic_init(bus, nd, "i82551", i82551);
     //~ uint8_t *pci_conf = d->dev.config;
 }
 
-void pci_i82557b_init(PCIBus * bus, NICInfo * nd, int devfn)
+PCIDevice *pci_i82557b_init(PCIBus * bus, NICInfo * nd, int devfn)
 {
-    nic_init(bus, nd, "i82557b", i82557B);
+    return nic_init(bus, nd, "i82557b", i82557B);
 }
 
-void pci_i82559er_init(PCIBus * bus, NICInfo * nd, int devfn)
+PCIDevice *pci_i82559er_init(PCIBus * bus, NICInfo * nd, int devfn)
 {
-    nic_init(bus, nd, "i82559er", i82559ER);
+    return nic_init(bus, nd, "i82559er", i82559ER);
 }
 
 /* eof */
qemu/hw/ne2000.c +3 -1
Index: kvm-userspace.hotplug2/qemu/hw/ne2000.c
===================================================================
@@ -786,7 +786,7 @@ static void ne2000_map(PCIDevice *pci_de
     register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
 }
 
-void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
+PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCINE2000State *d;
     NE2000State *s;
@@ -827,4 +827,6 @@ void pci_ne2000_init(PCIBus *bus, NICInf
 
     /* XXX: instance number ? */
     register_savevm("ne2000", ne2000_id++, 3, ne2000_save, ne2000_load, s);
+
+    return (PCIDevice *)d;
 }
qemu/hw/pc.h +1 -1
Index: kvm-userspace.hotplug2/qemu/hw/pc.h
===================================================================
@@ -146,7 +146,7 @@ void isa_ne2000_init(int base, qemu_irq 
 
 /* virtio-net.c */
 
-void *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
 void virtio_net_poll(void);
 
 /* virtio-blk.h */
qemu/hw/pci.c +13 -9
Index: kvm-userspace.hotplug2/qemu/hw/pci.c
===================================================================
@@ -625,24 +625,26 @@ void pci_info(void)
 }
 
 /* Initialize a PCI NIC.  */
-void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
+PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
+    PCIDevice *pci_dev;
+
     if (strcmp(nd->model, "ne2k_pci") == 0) {
-        pci_ne2000_init(bus, nd, devfn);
+        pci_dev = pci_ne2000_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "i82551") == 0) {
-        pci_i82551_init(bus, nd, devfn);
+        pci_dev = pci_i82551_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "i82557b") == 0) {
-        pci_i82557b_init(bus, nd, devfn);
+        pci_dev = pci_i82557b_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "i82559er") == 0) {
-        pci_i82559er_init(bus, nd, devfn);
+        pci_dev = pci_i82559er_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "rtl8139") == 0) {
-        pci_rtl8139_init(bus, nd, devfn);
+        pci_dev = pci_rtl8139_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "e1000") == 0) {
-        pci_e1000_init(bus, nd, devfn);
+        pci_dev = pci_e1000_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "pcnet") == 0) {
-        pci_pcnet_init(bus, nd, devfn);
+        pci_dev = pci_pcnet_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "virtio") == 0) {
-	virtio_net_init(bus, nd, devfn);
+	pci_dev = virtio_net_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "?") == 0) {
         fprintf(stderr, "qemu: Supported PCI NICs: i82551 i82557b i82559er"
                         " ne2k_pci pcnet rtl8139 e1000 virtio\n");
@@ -651,6 +653,8 @@ void pci_nic_init(PCIBus *bus, NICInfo *
         fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
         exit (1);
     }
+    nd->devfn = pci_dev->devfn;
+    return pci_dev;
 }
 
 typedef struct {
qemu/hw/pci.h +8 -8
Index: kvm-userspace.hotplug2/qemu/hw/pci.h
===================================================================
@@ -87,7 +87,7 @@ typedef int (*pci_map_irq_fn)(PCIDevice 
 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          qemu_irq *pic, int devfn_min, int nirq);
 
-void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn);
 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);
@@ -116,23 +116,23 @@ void usb_ohci_init_pci(struct PCIBus *bu
 
 /* eepro100.c */
 
-void pci_i82551_init(PCIBus *bus, NICInfo *nd, int devfn);
-void pci_i82557b_init(PCIBus *bus, NICInfo *nd, int devfn);
-void pci_i82559er_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_i82551_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_i82557b_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_i82559er_init(PCIBus *bus, NICInfo *nd, int devfn);
 
 /* ne2000.c */
 
-void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn);
 
 /* rtl8139.c */
 
-void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn);
 
 /* e1000.c */
-void pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn);
 
 /* pcnet.c */
-void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn);
 
 /* prep_pci.c */
 PCIBus *pci_prep_init(qemu_irq *pic);
qemu/hw/pcnet.c +2 -1
Index: kvm-userspace.hotplug2/qemu/hw/pcnet.c
===================================================================
@@ -1958,7 +1958,7 @@ static void pci_physical_memory_read(voi
     cpu_physical_memory_read(addr, buf, len);
 }
 
-void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
+PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCNetState *d;
     uint8_t *pci_conf;
@@ -2006,6 +2006,7 @@ void pci_pcnet_init(PCIBus *bus, NICInfo
     d->pci_dev = &d->dev;
 
     pcnet_common_init(d, nd, "pcnet");
+    return (PCIDevice *)d;
 }
 
 /* SPARC32 interface */
qemu/hw/rtl8139.c +2 -1
Index: kvm-userspace.hotplug2/qemu/hw/rtl8139.c
===================================================================
@@ -3410,7 +3410,7 @@ static void rtl8139_timer(void *opaque)
 }
 #endif /* RTL8139_ONBOARD_TIMER */
 
-void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
+PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCIRTL8139State *d;
     RTL8139State *s;
@@ -3474,5 +3474,6 @@ void pci_rtl8139_init(PCIBus *bus, NICIn
     qemu_mod_timer(s->timer,
         rtl8139_get_next_tctr_time(s,qemu_get_clock(vm_clock)));
 #endif /* RTL8139_ONBOARD_TIMER */
+    return (PCIDevice *)d;
 }
 
qemu/hw/virtio-net.c +2 -2
Index: kvm-userspace.hotplug2/qemu/hw/virtio-net.c
===================================================================
@@ -279,7 +279,7 @@ static void virtio_net_tx_timer(void *op
     virtio_net_flush_tx(n, n->tx_vq);
 }
 
-void *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
+PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     VirtIONet *n;
 
@@ -306,5 +306,5 @@ void *virtio_net_init(PCIBus *bus, NICIn
     n->tx_timer = qemu_new_timer(vm_clock, virtio_net_tx_timer, n);
     n->tx_timer_active = 0;
 
-    return &n->vdev;
+    return (PCIDevice *)n;
 }
qemu/net.h +1 -0
Index: kvm-userspace.hotplug2/qemu/net.h
===================================================================
@@ -45,6 +45,7 @@ struct NICInfo {
     uint8_t macaddr[6];
     const char *model;
     VLANState *vlan;
+    int devfn;
 };
 
 extern int nb_nics;
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#5 lore raw

PATCH 5/24 QEMU/KVM: pci hotplug GPE support

In reply to Marcelo Tosatti

Enable the corresponding bit on the PCIST region and trigger the SCI.

qemu/hw/acpi.c +75 -0
Index: kvm-userspace.hotplug2/qemu/hw/acpi.c
===================================================================
@@ -538,6 +538,7 @@ void qemu_system_powerdown(void)
 #endif
 #define GPE_BASE 0xafe0
 #define PROC_BASE 0xaf00
+#define PCI_BASE 0xae00
 
 struct gpe_regs {
     uint16_t sts; /* status */
@@ -546,7 +547,13 @@ struct gpe_regs {
     uint8_t down;
 };
 
+struct pci_status {
+    uint32_t up;
+    uint32_t down;
+};
+
 static struct gpe_regs gpe;
+static struct pci_status pci0_status;
 
 static uint32_t gpe_readb(void *opaque, uint32_t addr)
 {
@@ -614,6 +621,45 @@ static void gpe_writeb(void *opaque, uin
 #endif
 }
 
+static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    struct pci_status *g = opaque;
+    switch (addr) {
+        case PCI_BASE:
+            val = g->up;
+            break;
+        case PCI_BASE + 4:
+            val = g->down;
+            break;
+        default:
+            break;
+    }
+
+#if defined(DEBUG)
+    printf("pcihotplug read %lx == %lx\n", addr, val);
+#endif
+    return val;
+}
+
+static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    struct pci_status *g = opaque;
+    switch (addr) {
+        case PCI_BASE:
+            g->up = val;
+            break;
+        case PCI_BASE + 4:
+            g->down = val;
+            break;
+   }
+
+#if defined(DEBUG)
+    printf("pcihotplug write %lx <== %d\n", addr, val);
+#endif
+}
+
+
 static char *model;
 
 void qemu_system_hot_add_init(char *cpu_model)
@@ -624,6 +670,9 @@ void qemu_system_hot_add_init(char *cpu_
     register_ioport_write(PROC_BASE, 4, 1, gpe_writeb, &gpe);
     register_ioport_read(PROC_BASE, 4, 1,  gpe_readb, &gpe);
 
+    register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status);
+    register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, &pci0_status);
+
     model = cpu_model;
 }
 
@@ -665,3 +714,29 @@ void qemu_system_cpu_hot_add(int cpu, in
         disable_processor(&gpe, cpu);
     qemu_set_irq(pm_state->irq, 0);
 }
+
+static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
+{
+    g->sts |= 2;
+    g->en |= 2;
+    p->up |= (1 << slot);
+}
+
+static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
+{
+    g->sts |= 2;
+    g->en |= 2;
+    p->down |= (1 << slot);
+}
+
+void qemu_system_device_hot_add(int slot, int state)
+{
+    qemu_set_irq(pm_state->irq, 1);
+    pci0_status.up = 0;
+    pci0_status.down = 0;
+    if (state)
+        enable_device(&pci0_status, &gpe, slot);
+    else
+        disable_device(&pci0_status, &gpe, slot);
+    qemu_set_irq(pm_state->irq, 0);
+}
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#6 lore raw

PATCH 6/24 QEMU/KVM: dynamic drive/drive_opt index allocation

In reply to Marcelo Tosatti

Dynamically allocate drive options and drive table index, so to reused indexes when devices are removed.

qemu/sysemu.h +1 -0
Index: kvm-userspace.hotplug2/qemu/sysemu.h
===================================================================
@@ -139,6 +139,7 @@ typedef struct DriveInfo {
     BlockInterfaceType type;
     int bus;
     int unit;
+    int used;
 } DriveInfo;
 
 #define MAX_IDE_DEVS	2
qemu/vl.c +46 -12

108 lines not on this page · raw message

Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#7 lore raw

PATCH 7/24 QEMU/KVM: dynamic nic info index allocation

In reply to Marcelo Tosatti

The same, but for nics.

qemu/net.h +1 -0
Index: kvm-userspace.hotplug2/qemu/net.h
===================================================================
@@ -46,6 +46,7 @@ struct NICInfo {
     const char *model;
     VLANState *vlan;
     int devfn;
+    int used;
 };
 
 extern int nb_nics;
qemu/vl.c +14 -3
Index: kvm-userspace.hotplug2/qemu/vl.c
===================================================================
@@ -4791,6 +4791,15 @@ static int check_params(char *buf, int b
     return 0;
 }
 
+static int nic_get_free_idx(void)
+{
+    int index;
+
+    for (index = 0; index < MAX_NICS; index++)
+        if (!nd_table[index].used)
+            return index;
+    return -1;
+}
 
 static int net_client_init(const char *str)
 {
@@ -4823,19 +4832,20 @@ static int net_client_init(const char *s
     if (!strcmp(device, "nic")) {
         NICInfo *nd;
         uint8_t *macaddr;
+        int idx = nic_get_free_idx();
 
-        if (nb_nics >= MAX_NICS) {
+        if (idx == -1 || nb_nics >= MAX_NICS) {
             fprintf(stderr, "Too Many NICs\n");
             return -1;
         }
-        nd = &nd_table[nb_nics];
+        nd = &nd_table[idx];
         macaddr = nd->macaddr;
         macaddr[0] = 0x52;
         macaddr[1] = 0x54;
         macaddr[2] = 0x00;
         macaddr[3] = 0x12;
         macaddr[4] = 0x34;
-        macaddr[5] = 0x56 + nb_nics;
+        macaddr[5] = 0x56 + idx;
 
         if (get_param_value(buf, sizeof(buf), "macaddr", p)) {
             if (parse_macaddr(macaddr, buf) < 0) {
@@ -4847,6 +4857,7 @@ static int net_client_init(const char *s
             nd->model = strdup(buf);
         }
         nd->vlan = vlan;
+        nd->used = 1;
         nb_nics++;
         vlan->nb_guest_devs++;
         ret = 0;
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#8 lore raw

PATCH 8/24 QEMU/KVM: drive removal support

In reply to Marcelo Tosatti

To be used by hot-remove.

qemu/vl.c +21 -0
Index: kvm-userspace.hotplug2/qemu/vl.c
===================================================================
@@ -5010,6 +5010,12 @@ static int drive_add(const char *file, c
     return index;
 }
 
+void drive_remove(int index)
+{
+    drives_opt[index].used = 0;
+    nb_drives_opt--;
+}
+
 int drive_get_index(BlockInterfaceType type, int bus, int unit)
 {
     int index;
@@ -5040,6 +5046,20 @@ int drive_get_max_bus(BlockInterfaceType
     return max_bus;
 }
 
+void drive_uninit(BlockDriverState *bdrv)
+{
+    int i;
+
+    for (i = 0; i < MAX_DRIVES; i++)
+        if (drives_table[i].bdrv == bdrv) {
+            drives_table[i].bdrv = NULL;
+            drives_table[i].used = 0;
+            drive_remove(drives_table[i].drive_opt_idx);
+            nb_drives--;
+            break;
+        }
+}
+
 static int drive_init(struct drive_opt *arg, int snapshot,
                       QEMUMachine *machine)
 {
@@ -5313,6 +5333,7 @@ static int drive_init(struct drive_opt *
     drives_table[drives_table_idx].type = type;
     drives_table[drives_table_idx].bus = bus_id;
     drives_table[drives_table_idx].unit = unit_id;
+    drives_table[drives_table_idx].drive_opt_idx = arg - drives_opt;
     nb_drives++;
 
     switch(type) {
qemu/sysemu.h +4 -0
Index: kvm-userspace.hotplug2/qemu/sysemu.h
===================================================================
@@ -140,6 +140,7 @@ typedef struct DriveInfo {
     int bus;
     int unit;
     int used;
+    int drive_opt_idx;
 } DriveInfo;
 
 #define MAX_IDE_DEVS	2
@@ -153,6 +154,9 @@ int extboot_drive;
 extern int drive_get_index(BlockInterfaceType type, int bus, int unit);
 extern int drive_get_max_bus(BlockInterfaceType type);
 
+extern void drive_uninit(BlockDriverState *bdrv);
+extern void drive_remove(int index);
+
 /* acpi */
 void qemu_system_cpu_hot_add(int cpu, int state);
 void qemu_system_hot_add_init(char *cpu_model);
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#9 lore raw

PATCH 9/24 QEMU/KVM: record devfn on block driver instance

In reply to Marcelo Tosatti

Record devfn on the BlockDriverState structure to locate for release on hot-removal.

qemu/block_int.h +2 -0
Index: kvm-userspace.hotplug2/qemu/block_int.h
===================================================================
@@ -129,6 +129,8 @@ struct BlockDriverState {
     int cyls, heads, secs, translation;
     int type;
     char device_name[32];
+    /* PCI devfn of parent */
+    int devfn;
     BlockDriverState *next;
 };
 
qemu/hw/lsi53c895a.c +2 -0
Index: kvm-userspace.hotplug2/qemu/hw/lsi53c895a.c
===================================================================
@@ -13,6 +13,7 @@
 #include "hw.h"
 #include "pci.h"
 #include "scsi-disk.h"
+#include "block_int.h"
 
 //#define DEBUG_LSI
 //#define DEBUG_LSI_REG
@@ -1845,6 +1846,7 @@ void lsi_scsi_attach(void *opaque, Block
     s->scsi_dev[id] = scsi_generic_init(bd, 1, lsi_command_complete, s);
     if (s->scsi_dev[id] == NULL)
         s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
+    bd->devfn = s->pci_dev.devfn;
 }
 
 void *lsi_scsi_init(PCIBus *bus, int devfn)
qemu/hw/virtio-blk.c +2 -0
Index: kvm-userspace.hotplug2/qemu/hw/virtio-blk.c
===================================================================
@@ -13,6 +13,7 @@
 
 #include "virtio.h"
 #include "block.h"
+#include "block_int.h"
 #include "pc.h"
 
 /* from Linux's linux/virtio_blk.h */
@@ -156,6 +157,7 @@ void *virtio_blk_init(PCIBus *bus, uint1
     s->vdev.update_config = virtio_blk_update_config;
     s->vdev.get_features = virtio_blk_get_features;
     s->bs = bs;
+    bs->devfn = s->vdev.pci_dev.devfn;
 
     virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
 
qemu/hw/ide.c +6 -0
Index: kvm-userspace.hotplug2/qemu/hw/ide.c
===================================================================
@@ -28,6 +28,7 @@
 #include "scsi-disk.h"
 #include "pcmcia.h"
 #include "block.h"
+#include "block_int.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
 #include "ppc_mac.h"
@@ -2938,6 +2939,7 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
 {
     PCIIDEState *d;
     uint8_t *pci_conf;
+    int i;
 
     /* register a function 1 of PIIX3 */
     d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE",
@@ -2966,6 +2968,10 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
 
+    for (i = 0; i < 4; i++)
+        if (hd_table[i])
+            hd_table[i]->devfn = d->dev.devfn;
+
     register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
 }
 
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#10 lore raw

PATCH 10/24 QEMU/KVM: move drives_opt for external use

In reply to Marcelo Tosatti

Device hotplug will use that structure from a separate file.

qemu/sysemu.h +9 -0
Index: kvm-userspace.hotplug2/qemu/sysemu.h
===================================================================
@@ -157,6 +157,15 @@ extern int drive_get_max_bus(BlockInterf
 extern void drive_uninit(BlockDriverState *bdrv);
 extern void drive_remove(int index);
 
+struct drive_opt {
+    const char *file;
+    char opt[1024];
+    int used;
+};
+
+extern struct drive_opt drives_opt[MAX_DRIVES];
+extern int nb_drives_opt;
+
 /* acpi */
 void qemu_system_cpu_hot_add(int cpu, int state);
 void qemu_system_hot_add_init(char *cpu_model);
qemu/vl.c +1 -5
Index: kvm-userspace.hotplug2/qemu/vl.c
===================================================================
@@ -251,11 +251,7 @@ unsigned int nb_prom_envs = 0;
 const char *prom_envs[MAX_PROM_ENVS];
 #endif
 int nb_drives_opt;
-struct drive_opt {
-    const char *file;
-    char opt[1024];
-    int used;
-} drives_opt[MAX_DRIVES];
+struct drive_opt drives_opt[MAX_DRIVES];
 
 static CPUState *cur_cpu;
 static CPUState *next_cpu;
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#11 lore raw

PATCH 11/24 QEMU/KVM: net/drive add/remove tweaks

In reply to Marcelo Tosatti

Export net/drive add/remove functions for device hotplug usage.

Return the table index on add.

Return failure instead of exiting if limit has been reached on drive_add.

qemu/vl.c +10 -9
Index: kvm-userspace.hotplug2/qemu/vl.c
===================================================================
@@ -4797,7 +4797,7 @@ static int nic_get_free_idx(void)
     return -1;
 }
 
-static int net_client_init(const char *str)
+int net_client_init(const char *str)
 {
     const char *p;
     char *q;
@@ -4856,7 +4856,7 @@ static int net_client_init(const char *s
         nd->used = 1;
         nb_nics++;
         vlan->nb_guest_devs++;
-        ret = 0;
+        ret = idx;
     } else
     if (!strcmp(device, "none")) {
         /* does nothing. It is needed to signal that no network cards
@@ -4986,14 +4986,14 @@ static int drive_get_free_idx(void)
     return -1;
 }
 
-static int drive_add(const char *file, const char *fmt, ...)
+int drive_add(const char *file, const char *fmt, ...)
 {
     va_list ap;
     int index = drive_opt_get_free_idx();
 
     if (nb_drives_opt >= MAX_DRIVES || index == -1) {
         fprintf(stderr, "qemu: too many drives\n");
-        exit(1);
+        return -1;
     }
 
     drives_opt[index].file = file;
@@ -5056,9 +5056,10 @@ void drive_uninit(BlockDriverState *bdrv
         }
 }
 
-static int drive_init(struct drive_opt *arg, int snapshot,
-                      QEMUMachine *machine)
+int drive_init(struct drive_opt *arg, int snapshot,
+                      void *opaque)
 {
+    QEMUMachine *machine = opaque;
     char buf[128];
     char file[1024];
     char devname[128];
@@ -5311,7 +5312,7 @@ static int drive_init(struct drive_opt *
      */
 
     if (drive_get_index(type, bus_id, unit_id) != -1)
-        return 0;
+        return -2;
 
     /* init */
 
@@ -5359,7 +5360,7 @@ static int drive_init(struct drive_opt *
         break;
     }
     if (!file[0])
-        return 0;
+        return -2;
     bdrv_flags = 0;
     if (snapshot)
         bdrv_flags |= BDRV_O_SNAPSHOT;
@@ -5370,7 +5371,7 @@ static int drive_init(struct drive_opt *
                         file);
         return -1;
     }
-    return 0;
+    return drives_table_idx;
 }
 
 /***********************************************************/
qemu/net.h +2 -0
Index: kvm-userspace.hotplug2/qemu/net.h
===================================================================
@@ -37,6 +37,8 @@ void do_info_network(void);
 /* virtio hack for zero copy receive */
 int hack_around_tap(void *opaque);
 
+int net_client_init(const char *str);
+
 /* NIC info */
 
 #define MAX_NICS 8
qemu/sysemu.h +3 -0
Index: kvm-userspace.hotplug2/qemu/sysemu.h
===================================================================
@@ -166,6 +166,9 @@ struct drive_opt {
 extern struct drive_opt drives_opt[MAX_DRIVES];
 extern int nb_drives_opt;
 
+extern int drive_add(const char *file, const char *fmt, ...);
+extern int drive_init(struct drive_opt *arg, int snapshot, void *machine);
+
 /* acpi */
 void qemu_system_cpu_hot_add(int cpu, int state);
 void qemu_system_hot_add_init(char *cpu_model);
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#12 lore raw

PATCH 12/24 QEMU/KVM: add net_client_uninit

In reply to Marcelo Tosatti
qemu/net.h +1 -0
Index: kvm-userspace.hotplug2/qemu/net.h
===================================================================
@@ -38,6 +38,7 @@ void do_info_network(void);
 int hack_around_tap(void *opaque);
 
 int net_client_init(const char *str);
+void net_client_uninit(NICInfo *nd);
 
 /* NIC info */
 
qemu/vl.c +8 -0
Index: kvm-userspace.hotplug2/qemu/vl.c
===================================================================
@@ -4937,6 +4937,14 @@ int net_client_init(const char *str)
     return ret;
 }
 
+void net_client_uninit(NICInfo *nd)
+{
+    nd->vlan->nb_guest_devs--; /* XXX: free vlan on last reference */
+    nb_nics--;
+    nd->used = 0;
+    free(nd->model);
+}
+
 void do_info_network(void)
 {
     VLANState *vlan;
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#13 lore raw

PATCH 13/24 QEMU/KVM: export get_param_value/check_params

In reply to Marcelo Tosatti
qemu/sysemu.h +4 -0
Index: kvm-userspace.hotplug2/qemu/sysemu.h
===================================================================
@@ -57,6 +57,10 @@ int qemu_live_loadvm_state(QEMUFile *f);
 
 void main_loop_wait(int timeout);
 
+int check_params(char *buf, int buf_size, char **params, const char *str);
+int get_param_value(char *buf, int buf_size, const char *tag,
+                    const char *str);
+
 /* Polling handling */
 
 /* return TRUE if no sleep should be done afterwards */
qemu/vl.c +4 -4
Index: kvm-userspace.hotplug2/qemu/vl.c
===================================================================
@@ -4737,8 +4737,8 @@ static const char *get_opt_value(char *b
     return p;
 }
 
-static int get_param_value(char *buf, int buf_size,
-                           const char *tag, const char *str)
+int get_param_value(char *buf, int buf_size,
+                    const char *tag, const char *str)
 {
     const char *p;
     char option[128];
@@ -4762,8 +4762,8 @@ static int get_param_value(char *buf, in
     return 0;
 }
 
-static int check_params(char *buf, int buf_size,
-                        char **params, const char *str)
+int check_params(char *buf, int buf_size,
+                 char **params, const char *str)
 {
     const char *p;
     int i;
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#14 lore raw

PATCH 14/24 QEMU/KVM: add pci_find_device

In reply to Marcelo Tosatti

Return PCIDevice from bus number and slot.

qemu/hw/pci.c +17 -0
Index: kvm-userspace.hotplug/qemu/hw/pci.c
===================================================================
@@ -689,6 +689,23 @@ PCIBus *pci_find_bus(int bus_num)
     return bus;
 }
 
+PCIDevice *pci_find_device(int bus_num, int slot)
+{
+    int devfn;
+    PCIDevice *d;
+    PCIBus *bus = pci_find_bus(bus_num);
+
+    if (!bus)
+        return NULL;
+
+    for(devfn = 0; devfn < 256; devfn++) {
+        d = bus->devices[devfn];
+            if (d && PCI_SLOT(devfn) == slot)
+                return d;
+    }
+    return NULL;
+}
+
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
                         pci_map_irq_fn map_irq, const char *name)
 {
qemu/hw/pci.h +1 -0
Index: kvm-userspace.hotplug/qemu/hw/pci.h
===================================================================
@@ -93,6 +93,7 @@ uint32_t pci_data_read(void *opaque, uin
 int pci_bus_num(PCIBus *s);
 void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
 PCIBus *pci_find_bus(int bus_num);
+PCIDevice *pci_find_device(int bus_num, int slot);
 
 void pci_info(void);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#15 lore raw

PATCH 15/24 QEMU/KVM: virtio_blk_init return PCIDevice pointer

In reply to Marcelo Tosatti
qemu/hw/virtio-blk.c +1 -1
Index: kvm-userspace.hotplug2/qemu/hw/virtio-blk.c
===================================================================
@@ -161,5 +161,5 @@ void *virtio_blk_init(PCIBus *bus, uint1
 
     virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
 
-    return &s->vdev;
+    return s;
 }
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#16 lore raw

PATCH 16/24 QEMU/KVM: device and disk hot-add

In reply to Marcelo Tosatti

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.

qemu/Makefile.target +2 -0
Index: 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
qemu/hw/device-hotplug.c new file +158 -0

158 lines not on this page · raw message

qemu/monitor.c +6 -0
Index: 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, },
 };
 
qemu/hw/boards.h +2 -0
Index: 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;
 
qemu/sysemu.h +5 -0
Index: 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 */
 
qemu/vl.c +3 -0
Index: 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++) {
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#17 lore raw

PATCH 17/24 QEMU/KVM: add cpu_unregister_io_memory and make io mem table index dynamic

In reply to Marcelo Tosatti

So drivers can clear their mem io table entries on exit back to unassigned state.

Also make the io mem index allocation dynamic.

qemu/cpu-all.h +1 -0
Index: kvm-userspace.hotplug2/qemu/cpu-all.h
===================================================================
@@ -837,6 +837,7 @@ int cpu_register_io_memory(int io_index,
                            CPUReadMemoryFunc **mem_read,
                            CPUWriteMemoryFunc **mem_write,
                            void *opaque);
+void cpu_unregister_io_memory(int table_address);
 CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
 CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
 
qemu/exec.c +34 -5
Index: kvm-userspace.hotplug2/qemu/exec.c
===================================================================
@@ -158,7 +158,7 @@ PhysPageDesc **l1_phys_map;
 CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
 CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
 void *io_mem_opaque[IO_MEM_NB_ENTRIES];
-static int io_mem_nb;
+char io_mem_used[IO_MEM_NB_ENTRIES];
 #if defined(CONFIG_SOFTMMU)
 static int io_mem_watch;
 #endif
@@ -2498,12 +2498,28 @@ static void *subpage_init (target_phys_a
     return mmio;
 }
 
+static int get_free_io_mem_idx(void)
+{
+    int i;
+
+    for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
+        if (!io_mem_used[i]) {
+            io_mem_used[i] = 1;
+            return i;
+        }
+
+    return -1;
+}
+
 static void io_mem_init(void)
 {
+    int i;
+
     cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
     cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
     cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
-    io_mem_nb = 5;
+    for (i=0; i<5; i++)
+        io_mem_used[i] = 0;
 
 #if defined(CONFIG_SOFTMMU)
     io_mem_watch = cpu_register_io_memory(-1, watch_mem_read,
@@ -2530,9 +2546,9 @@ int cpu_register_io_memory(int io_index,
     int i, subwidth = 0;
 
     if (io_index <= 0) {
-        if (io_mem_nb >= IO_MEM_NB_ENTRIES)
-            return -1;
-        io_index = io_mem_nb++;
+        io_index = get_free_io_mem_idx();
+        if (io_index == -1)
+            return io_index;
     } else {
         if (io_index >= IO_MEM_NB_ENTRIES)
             return -1;
@@ -2548,6 +2564,19 @@ int cpu_register_io_memory(int io_index,
     return (io_index << IO_MEM_SHIFT) | subwidth;
 }
 
+void cpu_unregister_io_memory(int io_table_address)
+{
+    int i;
+    int io_index = io_table_address >> IO_MEM_SHIFT;
+
+    for (i=0;i < 3; i++) {
+        io_mem_read[io_index][i] = unassigned_mem_read[i];
+        io_mem_write[io_index][i] = unassigned_mem_write[i];
+    }
+    io_mem_opaque[io_index] = NULL;
+    io_mem_used[io_index] = 0;
+}
+
 CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
 {
     return io_mem_write[io_index >> IO_MEM_SHIFT];
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#18 lore raw

Re: [patch 17/24] QEMU/KVM: add cpu_unregister_io_memory and make io mem table index dynamic

This patch broke -no-kvm-irqchip:

Quoted 58 lines · * On Wednesday 12 March 2008 01:42:08 Marcelo Tosatti wrote:

So drivers can clear their mem io table entries on exit back to unassigned state.

Also make the io mem index allocation dynamic.

Index: kvm-userspace.hotplug2/qemu/cpu-all.h
===================================================================

qemu/cpu-all.h +1 -0
@@ -837,6 +837,7 @@ int cpu_register_io_memory(int io_index,
                            CPUReadMemoryFunc **mem_read,
                            CPUWriteMemoryFunc **mem_write,
                            void *opaque);
+void cpu_unregister_io_memory(int table_address);
 CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
 CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
 

Index: kvm-userspace.hotplug2/qemu/exec.c
===================================================================

qemu/exec.c +16 -1
@@ -158,7 +158,7 @@ PhysPageDesc **l1_phys_map;
 CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
 CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
 void *io_mem_opaque[IO_MEM_NB_ENTRIES];
-static int io_mem_nb;
+char io_mem_used[IO_MEM_NB_ENTRIES];
 #if defined(CONFIG_SOFTMMU)
 static int io_mem_watch;
 #endif
@@ -2498,12 +2498,28 @@ static void *subpage_init (target_phys_a
     return mmio;
 }
 
+static int get_free_io_mem_idx(void)
+{
+    int i;
+
+    for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
+        if (!io_mem_used[i]) {
+            io_mem_used[i] = 1;
+            return i;
+        }
+
+    return -1;
+}
+
 static void io_mem_init(void)
 {
+    int i;
+
     cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read,

unassigned_mem_write, NULL); cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL); cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read,
notdirty_mem_write, NULL); - io_mem_nb = 5;

qemu/exec.c

Quoted 2 lines
qemu/exec.c +2 -0
+    for (i=0; i<5; i++)
+        io_mem_used[i] = 0;

The remaining bits (5..IO_MEM_NB_ENTRIES) aren't initialised.

qemu/exec.c int cpu_register_io_memory(int io_index, · line 2551

Quoted 13 lines

#if defined(CONFIG_SOFTMMU)
io_mem_watch = cpu_register_io_memory(-1, watch_mem_read,

qemu/exec.c +3 -3
@@ -2530,9 +2546,9 @@ int cpu_register_io_memory(int io_index,
     int i, subwidth = 0;
 
     if (io_index <= 0) {
-        if (io_mem_nb >= IO_MEM_NB_ENTRIES)
-            return -1;
-        io_index = io_mem_nb++;
+        io_index = get_free_io_mem_idx();
+        if (io_index == -1)
+            return io_index;

io_mem_nb was initialised to 5 earlier; we now trample over the first 0..4 bits.

This fixes the issue; please check for correctness.

From: Amit Shah <[email protected]>
Date: Tue, 18 Mar 2008 18:01:05 +0530
Subject: [PATCH] QEMU/KVM: fix initialization of IO memory regions

---
 qemu/exec.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
qemu/exec.c +1 -1
index edeb21a..be15433 100644
@@ -2502,7 +2502,7 @@ static int get_free_io_mem_idx(void)
 {
     int i;
 
-    for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
+    for (i = 5; i<IO_MEM_NB_ENTRIES; i++)
         if (!io_mem_used[i]) {
             io_mem_used[i] = 1;
             return i;
@@ -2518,7 +2518,7 @@ static void io_mem_init(void)
     cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, 

unassigned_mem_write, NULL);
cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT,
unassigned_mem_read, unassigned_mem_write, NULL);
cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read,
notdirty_mem_write, NULL);
- for (i=0; i<5; i++)
+ for (i=5; i<IO_MEM_NB_ENTRIES; i++)

         io_mem_used[i] = 0;

#if defined(CONFIG_SOFTMMU)

Signature · 7 lines
1.4.4.2


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#19 lore raw

Re: [patch 17/24] QEMU/KVM: add cpu_unregister_io_memory and make io mem table index dynamic

Quoted 118 lines · Amit Shah

This patch broke -no-kvm-irqchip:

Quoted 58 lines · * On Wednesday 12 March 2008 01:42:08 Marcelo Tosatti wrote:

So drivers can clear their mem io table entries on exit back to unassigned state.

Also make the io mem index allocation dynamic.

Index: kvm-userspace.hotplug2/qemu/cpu-all.h
===================================================================

qemu/cpu-all.h +1 -0
@@ -837,6 +837,7 @@ int cpu_register_io_memory(int io_index,
                            CPUReadMemoryFunc **mem_read,
                            CPUWriteMemoryFunc **mem_write,
                            void *opaque);
+void cpu_unregister_io_memory(int table_address);
 CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
 CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
 

Index: kvm-userspace.hotplug2/qemu/exec.c
===================================================================

qemu/exec.c +16 -1
@@ -158,7 +158,7 @@ PhysPageDesc **l1_phys_map;
 CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
 CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
 void *io_mem_opaque[IO_MEM_NB_ENTRIES];
-static int io_mem_nb;
+char io_mem_used[IO_MEM_NB_ENTRIES];
 #if defined(CONFIG_SOFTMMU)
 static int io_mem_watch;
 #endif
@@ -2498,12 +2498,28 @@ static void *subpage_init (target_phys_a
     return mmio;
 }
 
+static int get_free_io_mem_idx(void)
+{
+    int i;
+
+    for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
+        if (!io_mem_used[i]) {
+            io_mem_used[i] = 1;
+            return i;
+        }
+
+    return -1;
+}
+
 static void io_mem_init(void)
 {
+    int i;
+
     cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read,

unassigned_mem_write, NULL); cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL); cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read,
notdirty_mem_write, NULL); - io_mem_nb = 5;

qemu/exec.c

Quoted 2 lines
qemu/exec.c +2 -0
+    for (i=0; i<5; i++)
+        io_mem_used[i] = 0;

The remaining bits (5..IO_MEM_NB_ENTRIES) aren't initialised.

qemu/exec.c int cpu_register_io_memory(int io_index, · line 2551

Quoted 13 lines

#if defined(CONFIG_SOFTMMU)
io_mem_watch = cpu_register_io_memory(-1, watch_mem_read,

qemu/exec.c +3 -3
@@ -2530,9 +2546,9 @@ int cpu_register_io_memory(int io_index,
     int i, subwidth = 0;
 
     if (io_index <= 0) {
-        if (io_mem_nb >= IO_MEM_NB_ENTRIES)
-            return -1;
-        io_index = io_mem_nb++;
+        io_index = get_free_io_mem_idx();
+        if (io_index == -1)
+            return io_index;

io_mem_nb was initialised to 5 earlier; we now trample over the first 0..4 bits.

This fixes the issue; please check for correctness.

From: Amit Shah <[email protected]>
Date: Tue, 18 Mar 2008 18:01:05 +0530
Subject: [PATCH] QEMU/KVM: fix initialization of IO memory regions

---
 qemu/exec.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
qemu/exec.c +2 -2
index edeb21a..be15433 100644
@@ -2502,7 +2502,7 @@ static int get_free_io_mem_idx(void)
 {
     int i;
 
-    for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
+    for (i = 5; i<IO_MEM_NB_ENTRIES; i++)
         if (!io_mem_used[i]) {
             io_mem_used[i] = 1;
             return i;
@@ -2518,7 +2518,7 @@ static void io_mem_init(void)
     cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, 
 unassigned_mem_write, NULL);
     cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, 
 unassigned_mem_read, unassigned_mem_write, NULL);
     cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, 
 notdirty_mem_write, NULL);
-    for (i=0; i<5; i++)
+    for (i=5; i<IO_MEM_NB_ENTRIES; i++)
         io_mem_used[i] = 0;
Quoted 1 line

#if defined(CONFIG_SOFTMMU)

Hi Amit,

There is no need to zero io_mem_used since its in the BSS. The loop in io_mem_init() was meant to allocate the slots from 0 to 4, not free them.

So does the following fix the problem?

qemu/exec.c +1 -1
index edeb21a..e5199cf 100644
@@ -2519,7 +2519,7 @@ static void io_mem_init(void)
     cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_re     cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, not     for (i=0; i<5; i++)
-        io_mem_used[i] = 0;
+        io_mem_used[i] = 1;
 
 #if defined(CONFIG_SOFTMMU)
     io_mem_watch = cpu_register_io_memory(-1, watch_mem_read,
#20 lore raw

Re: [patch 17/24] QEMU/KVM: add cpu_unregister_io_memory and make io mem table index dynamic

Quoted 2 lines · Marcelo Tosatti
Quoted 1 line · Amit Shah

This patch broke -no-kvm-irqchip:

...

Quoted 5 lines

Hi Amit,

There is no need to zero io_mem_used since its in the BSS. The loop in io_mem_init() was meant to allocate the slots from 0 to 4, not free them.

Of course.

Quoted 13 lines

So does the following fix the problem?

qemu/exec.c +0 -0
index edeb21a..e5199cf 100644
@@ -2519,7 +2519,7 @@ static void io_mem_init(void)
     cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT,

unassigned_mem_re cpu_register_io_memory(IO_MEM_NOTDIRTY >>
IO_MEM_SHIFT, error_mem_read, not for (i=0; i<5; i++) -
io_mem_used[i] = 0;
+ io_mem_used[i] = 1;

Quoted 2 lines

#if defined(CONFIG_SOFTMMU)
io_mem_watch = cpu_register_io_memory(-1, watch_mem_read,

Yes, it does. Thanks.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

_______________________________________________
kvm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

#21 lore raw

Re: [patch 17/24] QEMU/KVM: add cpu_unregister_io_memory and make io mem table index dynamic

Quoted 6 lines · Amit Shah
Quoted 4 lines

So does the following fix the problem?

Yes, it does. Thanks.

Okay, applied.

Signature · 7 lines
Do not meddle in the internals of kernels, for they are subtle and quick to panic.


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#22 lore raw

PATCH 18/24 QEMU/KVM: notify _EJ0 through _SEJ OperationRegion

In reply to Marcelo Tosatti

The _EJ0 method is executed by the OS once it has successfully finished device removal. Inform that event through IO port space so QEMU can free the associated data.

bios/acpi-dsdt.dsl +130 -31
Index: kvm-userspace.hotplug2/bios/acpi-dsdt.dsl
===================================================================
@@ -414,159 +414,258 @@ DefinitionBlock (
  		PCID, 32,
  	    }
 
+            OperationRegion(SEJ, SystemIO, 0xae08, 0x04)
+            Field (SEJ, DWordAcc, NoLock, WriteAsZeros)
+            {
+                B0EJ, 32,
+            }
+
             Device (S1) {              // Slot 1
                Name (_ADR, 0x00010000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x2, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S2) {              // Slot 2
                Name (_ADR, 0x00020000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x4, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S3) {              // Slot 3
                Name (_ADR, 0x00030000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store (0x8, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S4) {              // Slot 4
                Name (_ADR, 0x00040000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x10, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S5) {              // Slot 5
                Name (_ADR, 0x00050000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x20, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S6) {              // Slot 6
                Name (_ADR, 0x00060000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x40, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S7) {              // Slot 7
                Name (_ADR, 0x00070000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x80, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S8) {              // Slot 8
                Name (_ADR, 0x00080000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x100, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S9) {              // Slot 9
                Name (_ADR, 0x00090000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x200, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S10) {              // Slot 10
                Name (_ADR, 0x000A0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x400, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S11) {              // Slot 11
                Name (_ADR, 0x000B0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x800, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S12) {              // Slot 12
                Name (_ADR, 0x000C0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x1000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S13) {              // Slot 13
                Name (_ADR, 0x000D0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x2000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S14) {              // Slot 14
                Name (_ADR, 0x000E0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x4000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S15) {              // Slot 15
                Name (_ADR, 0x000F0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x8000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S16) {              // Slot 16
                Name (_ADR, 0x00100000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x10000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S17) {              // Slot 17
                Name (_ADR, 0x00110000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x20000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S18) {              // Slot 18
                Name (_ADR, 0x00120000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x40000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S19) {              // Slot 19
                Name (_ADR, 0x00130000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x80000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S20) {              // Slot 20
                Name (_ADR, 0x00140000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x100000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S21) {              // Slot 21
                Name (_ADR, 0x00150000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x200000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S22) {              // Slot 22
                Name (_ADR, 0x00160000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x400000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S23) {              // Slot 23
                Name (_ADR, 0x00170000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x800000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S24) {              // Slot 24
                Name (_ADR, 0x00180000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x1000000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S25) {              // Slot 25
                Name (_ADR, 0x00190000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x2000000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S26) {              // Slot 26
                Name (_ADR, 0x001A0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x4000000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S27) {              // Slot 27
                Name (_ADR, 0x001B0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x8000000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S28) {              // Slot 28
                Name (_ADR, 0x001C0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x10000000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S29) {              // Slot 29
                Name (_ADR, 0x001D0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x20000000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S30) {              // Slot 30
                Name (_ADR, 0x001E0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x40000000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Device (S31) {              // Slot 31
                Name (_ADR, 0x001F0000)
-               Method (_EJ0,1) { Return (0x0) }
+               Method (_EJ0,1) {
+                    Store(0x80000000, B0EJ)
+                    Return (0x0)
+               }
             }
 
             Method (_CRS, 0, NotSerialized)
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#23 lore raw

PATCH 19/24 QEMU/KVM: handle SEJ notifications

In reply to Marcelo Tosatti

Handle the _EJ0 notifications.

qemu/hw/acpi.c +22 -0
Index: kvm-userspace.hotplug2/qemu/hw/acpi.c
===================================================================
@@ -26,6 +26,7 @@
 #ifdef USE_KVM
 #include "qemu-kvm.h"
 #endif
+#include "string.h"
 
 //#define DEBUG
 
@@ -539,6 +540,7 @@ void qemu_system_powerdown(void)
 #define GPE_BASE 0xafe0
 #define PROC_BASE 0xaf00
 #define PCI_BASE 0xae00
+#define PCI_EJ_BASE 0xae08
 
 struct gpe_regs {
     uint16_t sts; /* status */
@@ -659,6 +661,23 @@ static void pcihotplug_write(void *opaqu
 #endif
 }
 
+static uint32_t pciej_read(void *opaque, uint32_t addr)
+{
+#if defined(DEBUG)
+    printf("pciej read %lx == %lx\n", addr, val);
+#endif
+    return 0;
+}
+
+static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    int slot = ffs(val) - 1;
+
+#if defined(DEBUG)
+    printf("pciej write %lx <== %d\n", addr, val);
+#endif
+}
+
 
 static char *model;
 
@@ -673,6 +692,9 @@ void qemu_system_hot_add_init(char *cpu_
     register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status);
     register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, &pci0_status);
 
+    register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, NULL);
+    register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, NULL);
+
     model = cpu_model;
 }
 
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#24 lore raw

PATCH 20/24 QEMU/KVM: add qemu_free_irqs

In reply to Marcelo Tosatti
qemu/hw/irq.c +6 -0
Index: kvm-userspace.hotplug2/qemu/hw/irq.c
===================================================================
@@ -56,6 +56,12 @@ qemu_irq *qemu_allocate_irqs(qemu_irq_ha
     return s;
 }
 
+void qemu_free_irqs(qemu_irq *s)
+{
+    qemu_free(s[0]);
+    qemu_free(s);
+}
+
 static void qemu_notirq(void *opaque, int line, int level)
 {
     struct IRQState *irq = opaque;
qemu/hw/irq.h +2 -0
Index: kvm-userspace.hotplug2/qemu/hw/irq.h
===================================================================
@@ -28,6 +28,8 @@ static inline void qemu_irq_pulse(qemu_i
 /* Returns an array of N IRQs.  */
 qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
 
+void qemu_free_irqs(qemu_irq *s);
+
 /* Returns a new IRQ with opposite polarity.  */
 qemu_irq qemu_irq_invert(qemu_irq irq);
 
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#25 lore raw

PATCH 21/24 QEMU/KVM: add pci_unregister_device

In reply to Marcelo Tosatti

Unregister the pci device, unassign its IO and memory regions, and free associated data.

Add a callback so drivers can free device state.

qemu/hw/pci.c +42 -4
Index: kvm-userspace.hotplug2/qemu/hw/pci.c
===================================================================
@@ -185,6 +185,48 @@ PCIDevice *pci_register_device(PCIBus *b
     return pci_dev;
 }
 
+static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
+{
+    return addr + pci_mem_base;
+}
+
+static void pci_unregister_io_regions(PCIDevice *pci_dev)
+{
+    PCIIORegion *r;
+    int i;
+
+    for(i = 0; i < PCI_NUM_REGIONS; i++) {
+        r = &pci_dev->io_regions[i];
+        if (!r->size)
+            continue;
+        if (r->type == PCI_ADDRESS_SPACE_IO) {
+            isa_unassign_ioport(r->addr, r->size);
+        } else {
+            cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
+                                                     r->size,
+                                                     IO_MEM_UNASSIGNED);
+        }
+    }
+}
+
+int pci_unregister_device(PCIDevice *pci_dev)
+{
+    int ret = 0;
+
+    if (pci_dev->unregister)
+        ret = pci_dev->unregister(pci_dev);
+    if (ret)
+        return ret;
+
+    pci_unregister_io_regions(pci_dev);
+
+    qemu_free_irqs(pci_dev->irq);
+    pci_irq_index--;
+    pci_dev->bus->devices[pci_dev->devfn] = NULL;
+    qemu_free(pci_dev);
+    return 0;
+}
+
 void pci_register_io_region(PCIDevice *pci_dev, int region_num,
                             uint32_t size, int type,
                             PCIMapIORegionFunc *map_func)
@@ -207,10 +249,6 @@ void pci_register_io_region(PCIDevice *p
     *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
 }
 
-static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
-{
-    return addr + pci_mem_base;
-}
 
 static void pci_update_mappings(PCIDevice *d)
 {
qemu/hw/pci.h +4 -0
Index: kvm-userspace.hotplug2/qemu/hw/pci.h
===================================================================
@@ -15,6 +15,7 @@ typedef uint32_t PCIConfigReadFunc(PCIDe
                                    uint32_t address, int len);
 typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
                                 uint32_t addr, uint32_t size, int type);
+typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
 #define PCI_ADDRESS_SPACE_MEM		0x00
 #define PCI_ADDRESS_SPACE_IO		0x01
@@ -56,6 +57,7 @@ struct PCIDevice {
     /* do not access the following fields */
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
+    PCIUnregisterFunc *unregister;
     /* ??? This is a PC-specific hack, and should be removed.  */
     int irq_index;
 
@@ -71,6 +73,8 @@ PCIDevice *pci_register_device(PCIBus *b
                                PCIConfigReadFunc *config_read,
                                PCIConfigWriteFunc *config_write);
 
+int pci_unregister_device(PCIDevice *pci_dev);
+
 void pci_register_io_region(PCIDevice *pci_dev, int region_num,
                             uint32_t size, int type,
                             PCIMapIORegionFunc *map_func);
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#26 lore raw

PATCH 22/24 QEMU/KVM: LSI SCSI and e1000 unregister callbacks

In reply to Marcelo Tosatti
qemu/hw/lsi53c895a.c +13 -0
Index: kvm-userspace.hotplug2/qemu/hw/lsi53c895a.c
===================================================================
@@ -1849,6 +1849,18 @@ void lsi_scsi_attach(void *opaque, Block
     bd->devfn = s->pci_dev.devfn;
 }
 
+int lsi_scsi_uninit(PCIDevice *d)
+{
+    LSIState *s = (LSIState *) d;
+
+    cpu_unregister_io_memory(s->mmio_io_addr);
+    cpu_unregister_io_memory(s->ram_io_addr);
+
+    qemu_free(s->queue);
+
+    return 0;
+}
+
 void *lsi_scsi_init(PCIBus *bus, int devfn)
 {
     LSIState *s;
@@ -1881,6 +1893,7 @@ void *lsi_scsi_init(PCIBus *bus, int dev
     s->queue = qemu_malloc(sizeof(lsi_queue));
     s->queue_len = 1;
     s->active_commands = 0;
+    s->pci_dev.unregister = lsi_scsi_uninit;
 
     lsi_soft_reset(s);
 
qemu/hw/e1000.c +11 -0
Index: kvm-userspace.hotplug2/qemu/hw/e1000.c
===================================================================
@@ -930,6 +930,16 @@ e1000_mmio_map(PCIDevice *pci_dev, int r
     cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
 }
 
+static int
+pci_e1000_uninit(PCIDevice *dev)
+{
+    E1000State *d = (E1000State *) dev;
+
+    cpu_unregister_io_memory(d->mmio_index);
+
+    return 0;
+}
+
 PCIDevice *
 pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
@@ -994,6 +1004,7 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd,
              d->nd->macaddr[3], d->nd->macaddr[4], d->nd->macaddr[5]);
 
     register_savevm(info_str, d->instance, 1, nic_save, nic_load, d);
+    d->dev.unregister = pci_e1000_uninit;
 
     return (PCIDevice *)d;
 }
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#27 lore raw

PATCH 23/24 QEMU/KVM: zero ioport_opaque on isa_unassign_ioport

In reply to Marcelo Tosatti

If the io port is unassigned, the previous private pointer is meaningless.

qemu/vl.c +2 -0
Index: kvm-userspace.hotplug2/qemu/vl.c
===================================================================
@@ -399,6 +399,8 @@ void isa_unassign_ioport(int start, int 
         ioport_write_table[0][i] = default_ioport_writeb;
         ioport_write_table[1][i] = default_ioport_writew;
         ioport_write_table[2][i] = default_ioport_writel;
+
+        ioport_opaque[i] = NULL;
     }
 }
 
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#28 lore raw

PATCH 24/24 QEMU/KVM: device hot-remove

In reply to Marcelo Tosatti

Add monitor command to hot-remove devices.

Remove device data on _EJ0 notification.

qemu/monitor.c +1 -0
Index: kvm-userspace.hotplug2/qemu/monitor.c
===================================================================
@@ -1365,6 +1365,7 @@ static term_cmd_t term_cmds[] = {
                                         "[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" },
+    { "pci_del", "ii", device_hot_remove, "bus slot-number", "hot remove PCI device" },
     { NULL, NULL, },
 };
 
qemu/hw/device-hotplug.c +67 -1

83 lines not on this page · raw message

qemu/sysemu.h +3 -1
Index: kvm-userspace.hotplug2/qemu/sysemu.h
===================================================================
@@ -176,11 +176,13 @@ 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);
+void qemu_system_device_hot_add(int pcibus, 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);
+void device_hot_remove(int pcibus, int slot);
+void device_hot_remove_success(int pcibus, int slot);
 
 /* vmchannel devices */
 
qemu/hw/acpi.c +3 -1
Index: kvm-userspace.hotplug2/qemu/hw/acpi.c
===================================================================
@@ -673,6 +673,8 @@ static void pciej_write(void *opaque, ui
 {
     int slot = ffs(val) - 1;
 
+    device_hot_remove_success(0, slot);
+
 #if defined(DEBUG)
     printf("pciej write %lx <== %d\n", addr, val);
 #endif
@@ -751,7 +753,7 @@ static void disable_device(struct pci_st
     p->down |= (1 << slot);
 }
 
-void qemu_system_device_hot_add(int slot, int state)
+void qemu_system_device_hot_add(int pcibus, int slot, int state)
 {
     qemu_set_irq(pm_state->irq, 1);
     pci0_status.up = 0;
Signature · 4 lines
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
Applied
#29 lore raw
In reply to Marcelo Tosatti
Quoted 6 lines · Marcelo Tosatti

The following patchset allows PCI hot add/remove through ACPI (handled by the acpiphp driver on Linux guests).

Comments are welcome.

Applied all, thanks.

Signature · 7 lines
error compiling committee.c: too many arguments to function


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/