qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3/6] pci: Add notifier for device probing


From: Alex Williamson
Subject: [Qemu-devel] [PATCH 3/6] pci: Add notifier for device probing
Date: Tue, 06 Mar 2012 17:14:33 -0700
User-agent: StGIT/0.14.3

It's sometimes useful to know when the guest probes a device.  For
example, during PCI hotplug once the guest accesses the device, we
can no longer remove it without guest permission.  Add a notifier
list that gets called when the vendor ID of a device is read.  The
PCI spec mandates that configuration software must read this
register when probing the slot.  Ideally we'd notify only on the
first vendor ID read, but this requires state, which has migration
implications.  For now, notify on every read of the vendor ID.

Signed-off-by: Alex Williamson <address@hidden>
---

 hw/pci_host.c |   19 +++++++++++++++++++
 hw/pci_host.h |    2 ++
 2 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/hw/pci_host.c b/hw/pci_host.c
index 44c6c20..7eb1eca 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -20,6 +20,7 @@
 
 #include "pci.h"
 #include "pci_host.h"
+#include "notify.h"
 
 /* debug PCI */
 //#define DEBUG_PCI
@@ -31,6 +32,19 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while 
(0)
 #define PCI_DPRINTF(fmt, ...)
 #endif
 
+static NotifierList pci_host_dev_probe_notifiers =
+    NOTIFIER_LIST_INITIALIZER(pci_host_dev_probe_notifiers);
+
+void pci_host_add_dev_probe_notifier(Notifier *notify)
+{
+    notifier_list_add(&pci_host_dev_probe_notifiers, notify);
+}
+
+void pci_host_remove_dev_probe_notifier(Notifier *notify)
+{
+    notifier_list_remove(&pci_host_dev_probe_notifiers, notify);
+}
+
 /*
  * PCI address
  * bit 16 - 24: bus number
@@ -58,6 +72,11 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, 
uint32_t addr,
                                      uint32_t limit, uint32_t len)
 {
     assert(len <= 4);
+
+    if (addr == PCI_VENDOR_ID) {
+        notifier_list_notify(&pci_host_dev_probe_notifiers, pci_dev);
+    }
+
     return pci_dev->config_read(pci_dev, addr, MIN(len, limit - addr));
 }
 
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 359e38f..c5491ca 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -45,6 +45,8 @@ void pci_host_config_write_common(PCIDevice *pci_dev, 
uint32_t addr,
                                   uint32_t limit, uint32_t val, uint32_t len);
 uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
                                      uint32_t limit, uint32_t len);
+void pci_host_add_dev_probe_notifier(Notifier *notify);
+void pci_host_remove_dev_probe_notifier(Notifier *notify);
 
 void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]