From patchwork Fri Dec 24 08:45:29 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Michael S. Tsirkin" X-Patchwork-Id: 76627 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 58CCBB7088 for ; Fri, 24 Dec 2010 19:47:44 +1100 (EST) Received: from localhost ([127.0.0.1]:43123 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PW3JM-0002gJ-Ua for incoming@patchwork.ozlabs.org; Fri, 24 Dec 2010 03:47:40 -0500 Received: from [140.186.70.92] (port=44328 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PW3IF-0002ew-Mc for qemu-devel@nongnu.org; Fri, 24 Dec 2010 03:46:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PW3Hf-0007fP-5t for qemu-devel@nongnu.org; Fri, 24 Dec 2010 03:46:31 -0500 Received: from mx1.redhat.com ([209.132.183.28]:28100) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PW3He-0007fF-U5 for qemu-devel@nongnu.org; Fri, 24 Dec 2010 03:45:55 -0500 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oBO8joCf028515 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 24 Dec 2010 03:45:51 -0500 Received: from redhat.com (vpn-200-8.tlv.redhat.com [10.35.200.8]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id oBO8jlTs030780; Fri, 24 Dec 2010 03:45:48 -0500 Date: Fri, 24 Dec 2010 10:45:29 +0200 From: "Michael S. Tsirkin" To: Isaku Yamahata Message-ID: <20101224084529.GA23180@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: Blue Swirl , Alex Williamson , qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH repost] pci: fix migration device path for devices behind nested bridges X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org We were using bus number in the device path, which is clearly broken as this number is guest-assigned for all devices except the root. Replace this by a hierarchical list of slot/function numbers, walking the path from root down to device. Add :00 after the domain number so that if there are no nested bridges, this is compatible with what we have now. Note: as pointed out by Gleb, using openfirmware paths might be cleaner, doing this would break compatibility though, and the IDs used are not guest or user visible at all, so it probably doesn't matter what they are exactly. Signed-off-by: Michael S. Tsirkin --- OK I think I'll just apply the below, it seems better for the next release than the alternative of disabling migration completely, and the IDs used are completely transparent to the user, so it probably doesn't matter what they are exactly. hw/pci.c | 44 ++++++++++++++++++++++++++++++++++++-------- 1 files changed, 36 insertions(+), 8 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index 8f6fcf8..aed2d42 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1826,15 +1826,41 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent) static char *pcibus_get_dev_path(DeviceState *dev) { - PCIDevice *d = (PCIDevice *)dev; - char path[16]; - - snprintf(path, sizeof(path), "%04x:%02x:%02x.%x", - pci_find_domain(d->bus), - 0 /* TODO: need a persistent path for nested buses. - * Note: pci_bus_num(d->bus) is not right as it's guest - * assigned. */, - PCI_SLOT(d->devfn), PCI_FUNC(d->devfn)); - - return strdup(path); + PCIDevice *d = container_of(dev, PCIDevice, qdev); + PCIDevice *t; + int slot_depth; + /* Path format: Domain:00:Slot.Function:Slot.Function....:Slot.Function. + * 00 is added here to make this format compatible with + * domain:Bus:Slot.Func for systems without nested PCI bridges. + * Slot.Function list specifies the slot and function numbers for all + * devices on the path from root to the specific device. */ + int domain_len = strlen("DDDD:00"); + int slot_len = strlen(":SS.F"); + int path_len; + char *path, *p; + + /* Calculate # of slots on path between device and root. */; + slot_depth = 0; + for (t = d; t; t = t->bus->parent_dev) + ++slot_depth; + + path_len = domain_len + slot_len * slot_depth; + + /* Allocate memory, fill in the terminating null byte. */ + path = malloc(path_len + 1 /* For '\0' */); + path[path_len] = '\0'; + + /* First field is the domain. */ + snprintf(path, domain_len, "%04x:00", pci_find_domain(d->bus)); + + /* Fill in slot numbers. We walk up from device to root, so need to print + * them in the reverse order, last to first. */ + p = path + path_len; + for (t = d; t; t = t->bus->parent_dev) { + p -= slot_len; + snprintf(p, slot_len, ":%02x.%x", PCI_SLOT(t->devfn), PCI_FUNC(d->devfn)); + } + + return path; }