From 61bc0b1ef553b2f687ff8e9d28e17dd2b419c0fc Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Fri, 30 May 2008 17:18:08 +0100 Subject: [PATCH] Enable HVM guest VT-d device hotplug via a simple ACPI hotplug device model. 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 --- hw/pc.c | 6 ++++-- hw/pc.h | 3 +++ hw/pci.h | 23 +++++++++++++++++++++++ monitor.c | 6 ++++++ vl.c | 24 ++++++++++++++++++++---- 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index aebf1b7d5..9e4f5c467 100644 --- 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 acbb9fc82..a472a2b30 100644 --- 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); diff --git a/hw/pci.h b/hw/pci.h index e870987fe..14f673a77 100644 --- 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); diff --git a/monitor.c b/monitor.c index ce4855935..38d552db2 100644 --- 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 2d35281c5..b459d5a0e 100644 --- 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 */ -- 2.39.5