Patchwork [3/6] pci: Add notifier for device probing

login
register
mail settings
Submitter Alex Williamson
Date March 7, 2012, 12:14 a.m.
Message ID <20120307001419.3079.96413.stgit@bling.home>
Download mbox | patch
Permalink /patch/145118/
State New
Headers show

Comments

Alex Williamson - March 7, 2012, 12:14 a.m.
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 <alex.williamson@redhat.com>
---

 hw/pci_host.c |   19 +++++++++++++++++++
 hw/pci_host.h |    2 ++
 2 files changed, 21 insertions(+), 0 deletions(-)
Paolo Bonzini - March 7, 2012, 9:19 a.m.
Il 07/03/2012 01:14, Alex Williamson ha scritto:
> +void pci_host_remove_dev_probe_notifier(Notifier *notify)
> +{
> +    notifier_list_remove(&pci_host_dev_probe_notifiers, notify);
> +}
> +

Looks like qemu-kvm needs a merge. :)

Upstream has notifier_remove, not notifier_list_remove.

Paolo
Alex Williamson - March 7, 2012, 8:12 p.m.
On Wed, 2012-03-07 at 10:19 +0100, Paolo Bonzini wrote:
> Il 07/03/2012 01:14, Alex Williamson ha scritto:
> > +void pci_host_remove_dev_probe_notifier(Notifier *notify)
> > +{
> > +    notifier_list_remove(&pci_host_dev_probe_notifiers, notify);
> > +}
> > +
> 
> Looks like qemu-kvm needs a merge. :)
> 
> Upstream has notifier_remove, not notifier_list_remove.

Thanks Paolo,

Alex

Patch

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);