]> xenbits.xensource.com Git - qemu-xen-4.5-testing.git/commitdiff
Enable HVM guest VT-d device hotplug via a simple ACPI hotplug device model.
authorIan Jackson <ian@davenant.greenend.org.uk>
Fri, 30 May 2008 16:18:08 +0000 (17:18 +0100)
committerIan Jackson <iwj@mariner.uk.xensource.com>
Fri, 30 May 2008 16:18:08 +0000 (17:18 +0100)
Finish merge of remaining parts of xen-unstable c/s
17056:c6eeb71a85cffe917bc8d6738fd36e6694dba4d6:

    Enable HVM guest VT-d device hotplug via a simple ACPI hotplug device model.

    ** Currently only 2 virtual hotplug pci slots(6~7) are created so more
       than 2 vtd dev can't be hotplugged, but we can easily extend it in
       future.

    Three new commands are added:
    "xm pci-list domid" show the current assigned vtd device, like:
    VSlt  domain   bus   slot   func
    0x6      0x0  0x02   0x00    0x0

    "xm pci-detach" hot remove the specified vtd device by the virtual
    slot, like:
    xm pci-detach EdwinHVMDomainVtd 6

    "xm pci-attach DomainID dom bus dev func [vslot]" hot add a new vtd
    device in the vslot. If no vslot specified, a free slot will be picked
    up. e.g. to insert '0000:03:00.0':
    xm pci-attach EdwinHVMDomainVtd 0 3 0 0

    ** guest pci hotplug
    linux: pls. use 2.6.X and enable ACPI PCI hotplug ( Bus options=> PCI
    hotplug => ACPI PCI hotplug driver )
    windows: 2000/xp/2003/vista are all okay

Signed-off-by: Zhai Edwin <edwin.zhai@intel.com>
hw/pc.c
hw/pc.h
hw/pci.h
monitor.c
vl.c

diff --git a/hw/pc.c b/hw/pc.c
index aebf1b7d5faf5bf75e2cb99ef69288e08a9e17e1..9e4f5c467355977612b28a17bd530ef697a90034 100644 (file)
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -947,8 +947,10 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
     }
 
 #ifdef CONFIG_PASSTHROUGH
-    /* Pass-through Initialization */
-    if ( pci_enabled && direct_pci )
+    /* Pass-through Initialization
+     * init libpci even direct_pci is null, as can hotplug a dev runtime
+     */
+    if ( pci_enabled )
     {
         rc = pt_init(pci_bus, direct_pci); 
         if ( rc < 0 )
diff --git a/hw/pc.h b/hw/pc.h
index acbb9fc82fc8bf5c9edd4c26c665422371d0ad93..a472a2b304b953a2a0cb0a4e97177694f63cf279 100644 (file)
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -97,6 +97,9 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
 void acpi_bios_init(void);
 
+void acpi_php_add(int);
+void acpi_php_del(int);
+
 /* pcspk.c */
 void pcspk_init(PITState *);
 int pcspk_audio_init(AudioState *, qemu_irq *pic);
index e870987fe9aa1c2d3a2b12e429f3c9fcb8d92f18..14f673a776916df9f2183a0169ea84545a3a7b81 100644 (file)
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -65,11 +65,15 @@ struct PCIDevice {
     int irq_state[4];
 };
 
+extern char direct_pci_str[];
+
 PCIDevice *pci_register_device(PCIBus *bus, const char *name,
                                int instance_size, int devfn,
                                PCIConfigReadFunc *config_read,
                                PCIConfigWriteFunc *config_write);
 
+void pci_hide_device(PCIDevice *pci_dev);
+
 void pci_register_io_region(PCIDevice *pci_dev, int region_num,
                             uint32_t size, int type,
                             PCIMapIORegionFunc *map_func);
@@ -96,6 +100,25 @@ void pci_info(void);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
                         pci_map_irq_fn map_irq, const char *name);
 
+/* PCI slot 6~7 support ACPI PCI hot plug */
+#define PHP_SLOT_START  (6)
+#define PHP_SLOT_END    (8)
+#define PHP_SLOT_LEN    (PHP_SLOT_END - PHP_SLOT_START)
+#define PHP_TO_PCI_SLOT(x) (x + PHP_SLOT_START)
+#define PCI_TO_PHP_SLOT(x) (x - PHP_SLOT_START)
+#define PHP_DEVFN_START (PHP_SLOT_START << 3)
+#define PHP_DEVFN_END   (PHP_SLOT_END << 3)
+
+int insert_to_pci_slot(char*);
+int test_pci_slot(int);
+int bdf_to_slot(char*);
+int power_on_php_slot(int);
+int power_off_php_slot(int);
+void pt_uninit(void);
+
+void do_pci_add(char *devname);
+void do_pci_del(char *devname);
+
 /* lsi53c895a.c */
 #define LSI_MAX_DEVS 7
 void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id);
index ce4855935710dd4c77140ca54e98a95b96c69eba..38d552db25d7e710b51267ce40d78b980919d3a1 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -1365,6 +1365,12 @@ static term_cmd_t term_cmds[] = {
       "device", "add USB device (e.g. 'host:bus.addr' or 'host:vendor_id:product_id')" },
     { "usb_del", "s", do_usb_del,
       "device", "remove USB device 'bus.addr'" },
+#ifdef CONFIG_PHP_DEBUG
+    { "pci_add", "s", do_pci_add,
+      "device", "insert PCI pass-through device by BDF,e.g. (dom, bus, dev, func) by hex '0x0, 0x3, 0x0, 0x0'" },
+    { "pci_del", "s", do_pci_del,
+      "device", "remove PCI pass-through device by BDF,e.g. (dom, bus, dev, func) by hex '0x0, 0x3, 0x0, 0x0'" },
+#endif
     { "cpu", "i", do_cpu_set,
       "index", "set the default CPU" },
     { "mouse_move", "sss?", do_mouse_move,
diff --git a/vl.c b/vl.c
index 2d35281c525b5e86b43721c4fae10bddc4325e27..b459d5a0e234cabbbcd6c01dd888b5a9aefed8e6 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -3539,6 +3539,24 @@ void qemu_chr_close(CharDriverState *chr)
     qemu_free(chr);
 }
 
+void do_pci_del(char *devname)
+{
+    int pci_slot;
+    pci_slot = bdf_to_slot(devname);
+
+    acpi_php_del(pci_slot);
+}
+
+void do_pci_add(char *devname)
+{
+    int pci_slot;
+
+    pci_slot = insert_to_pci_slot(devname);
+
+    acpi_php_add(pci_slot);
+}
+
+
 /***********************************************************/
 /* network device redirectors */
 
@@ -7748,7 +7766,7 @@ int main(int argc, char **argv)
     const char *pid_file = NULL;
     VLANState *vlan;
 
-    const char *direct_pci = NULL;
+    const char *direct_pci = direct_pci_str;
 
 #if !defined(__sun__) && !defined(CONFIG_STUBDOM)
     /* Maximise rlimits. Needed where default constraints are tight (*BSD). */
@@ -8119,9 +8137,6 @@ int main(int argc, char **argv)
                 }
                 ram_size = value;
                 break;
-            case QEMU_OPTION_pci:
-                direct_pci = optarg;
-                break;
             }
             case QEMU_OPTION_d:
                 {
@@ -8734,6 +8749,7 @@ int main(int argc, char **argv)
 
     main_loop();
     quit_timers();
+    pt_uninit();
 
 #if !defined(_WIN32)
     /* close network clients */