From patchwork Wed Mar 7 00:14:33 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 145118 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D1319B6EEC for ; Wed, 7 Mar 2012 11:14:53 +1100 (EST) Received: from localhost ([::1]:56392 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S54Wp-0005mY-K6 for incoming@patchwork.ozlabs.org; Tue, 06 Mar 2012 19:14:51 -0500 Received: from eggs.gnu.org ([208.118.235.92]:43094) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S54Wb-0005RE-EK for qemu-devel@nongnu.org; Tue, 06 Mar 2012 19:14:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S54WZ-0005Xc-Il for qemu-devel@nongnu.org; Tue, 06 Mar 2012 19:14:36 -0500 Received: from mx1.redhat.com ([209.132.183.28]:30421) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S54WZ-0005XX-A0 for qemu-devel@nongnu.org; Tue, 06 Mar 2012 19:14:35 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q270EX9J005493 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 6 Mar 2012 19:14:34 -0500 Received: from bling.home ([10.3.113.14]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q270EX5G001680; Tue, 6 Mar 2012 19:14:33 -0500 From: Alex Williamson To: qemu-devel@nongnu.org Date: Tue, 06 Mar 2012 17:14:33 -0700 Message-ID: <20120307001419.3079.96413.stgit@bling.home> In-Reply-To: <20120307000340.3079.87515.stgit@bling.home> References: <20120307000340.3079.87515.stgit@bling.home> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: alex.williamson@redhat.com, ddutile@redhat.com, gleb@redhat.com, mst@redhat.com Subject: [Qemu-devel] [PATCH 3/6] pci: Add notifier for device probing X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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);