----- Original Message -----
On Wed, 2012-05-09 at 15:24 +0800, Amos Kong wrote:
Boot up a Linux VM with 8 pci block devices which are the 8 functions in one pci slot. | # qemu-kvm ... | -drive file=images/u0,if=none,id=drv0,format=qcow2,cache=none \ | -device | virtio-blk-pci,drive=drv0,id=v0,multifunction=on,addr=0x03.0 \ | .... | -drive file=images/u7,if=none,id=drv7,format=qcow2,cache=none \ | -device | virtio-blk-pci,drive=drv7,id=v7,multifunction=on,addr=0x03.7 \
Check devices in guest. | vm)# ls /dev/vd* | vda vdb vdc vde vdf vdg vdh | vm)# lspci |grep block | 00:03.0 SCSI storage controller: Red Hat, Inc Virtio block device | ... | 00:03.7 SCSI storage controller: Red Hat, Inc Virtio block device |
Func1~7 still exist in guest after hot-removing the whole slot through qemu monitor. | vm)# lspci |grep block (00:03.0 disappeared) | 00:03.1 SCSI storage controller: Red Hat, Inc Virtio block device | (rev ff) | ... | 00:03.7 SCSI storage controller: Red Hat, Inc Virtio block device | (rev ff) | vm)# ls /dev/vd* (vda disappeared) | vdb vdc vde vdf vdg vdh | vm)# mkfs /dev/vdb | INFO: task mkfs.ext2:1784 blocked for more than 120 seconds. | (task hung)
Currently only func0 is defined in ACPI DSDT table of seabios, and only hot-adding func0 would cause a ACPI event for notification. Other funcs except func0 wouldn't be registered in linux pci driver. (we can only found func0 in slot->funcs list of pci driver).
When VM pci driver receives an ACPI event for hot-removing, it will only clean functions in slot->funcs list, the other funcs could not be cleaned.
This patch adds device per function in ACPI DSDT tables, then all funcs will be registered in slot->funcs list. It's coincident with microsoft's example: http://www.microsoft.com/china/whdc/system/pnppwr/hotadd/hotplugpci.mspx#EUH
Have tested with linux/winxp/win7, hot-adding/hot-remving, single/multiple function devices, they are all fine(all added devices can be removed).
This patch includes some bits mst wrote, thanks!
old discussion: http://marc.info/?l=kvm&m=132428400917405&w=2
Signed-off-by: Amos Kong akong@redhat.com CC: Michael S. Tsirkin mst@redhat.com
src/ssdt-pcihp.dsl | 17 src/ssdt-pcihp.hex | 8869 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 8781 insertions(+), 105 deletions(-)
diff --git a/src/ssdt-pcihp.dsl b/src/ssdt-pcihp.dsl index 4b435b8..2a3c326 100644 --- a/src/ssdt-pcihp.dsl +++ b/src/ssdt-pcihp.dsl @@ -17,14 +17,23 @@ DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1) // at runtime, if the slot is detected to not support hotplug. // Extract the offset of the address dword and the // _EJ0 name to allow this patching. -#define hotplug_slot(slot) \
Device (S##slot) { \
+#define hotplug_func(slot, fn) \
Device (S##slot##fn) { \ ACPI_EXTRACT_NAME_DWORD_CONST aml_adr_dword \
Name (_ADR, 0x##slot##0000) \
I would have guessed it to be sufficient to change _ADR to 0x##slot##ffff, does that not work?
No, changing this to "0x##slot##ffff" doesn't resolve the bug. (tested)
I'm trying to fix this problem in guest pci driver. http://marc.info/?l=linux-pci&m=133657729118731&w=2
Thanks, Amos
Name (_ADR, 0x##slot##000##fn) \ ACPI_EXTRACT_METHOD_STRING aml_ej0_name \ Method (_EJ0, 1) { Return(PCEJ(0x##slot)) } \ Name (_SUN, 0x##slot) \ }
+#define hotplug_slot(slot) \
hotplug_func(slot, 0) \
hotplug_func(slot, 1) \
hotplug_func(slot, 2) \
hotplug_func(slot, 3) \
hotplug_func(slot, 4) \
hotplug_func(slot, 5) \
hotplug_func(slot, 6) \
hotplug_func(slot, 7) hotplug_slot(01) hotplug_slot(02)
@@ -59,7 +68,7 @@ DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1) hotplug_slot(1f)
#define gen_pci_hotplug(slot) \
If (LEqual(Arg0, 0x##slot)) { Notify(S##slot, Arg1) }
If (LEqual(Arg0, 0x##slot)) { Notify(S##slot##0, Arg1)
}
Method(PCNT, 2) { gen_pci_hotplug(01)