From patchwork Tue Mar 16 20:36:14 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 47901 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 C9DE7B7C8E for ; Wed, 17 Mar 2010 07:39:19 +1100 (EST) Received: from localhost ([127.0.0.1]:34021 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NrdWD-0006im-Bu for incoming@patchwork.ozlabs.org; Tue, 16 Mar 2010 16:37:37 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NrdUx-0006iU-4e for qemu-devel@nongnu.org; Tue, 16 Mar 2010 16:36:19 -0400 Received: from [199.232.76.173] (port=39336 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NrdUw-0006iK-ON for qemu-devel@nongnu.org; Tue, 16 Mar 2010 16:36:18 -0400 Received: from Debian-exim by monty-python.gnu.org with spam-scanned (Exim 4.60) (envelope-from ) id 1NrdUu-00066v-RP for qemu-devel@nongnu.org; Tue, 16 Mar 2010 16:36:18 -0400 Received: from cantor2.suse.de ([195.135.220.15]:44754 helo=mx2.suse.de) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NrdUu-00066l-A3 for qemu-devel@nongnu.org; Tue, 16 Mar 2010 16:36:16 -0400 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id BEB388672B; Tue, 16 Mar 2010 21:36:14 +0100 (CET) From: Alexander Graf To: qemu-devel@nongnu.org Date: Tue, 16 Mar 2010 21:36:14 +0100 Message-Id: <1268771774-27877-1-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.6.0.2 X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.4-2.6 Cc: "Michael S. Tsirkin" Subject: [Qemu-devel] [PATCH] [Also for STABLE-0.12] Don't check for bus master for old guests 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 Older Linux guests don't activate the bus master enable bit. So for those we can just try to be clever and track if they set the DEVICE_OK bit even though bus mastering is still disabled. Under that condition we can disable the windows safety check. With that logic in place both guests should work just fine. Without PCI hotplug breaks virtio-net in Linux < 2.6.34 guests. Signed-off-by: Alexander Graf CC: Michael S. Tsirkin Acked-by: Michael S. Tsirkin --- v1 -> v2: - Fix state loading - Reduce if nesting --- hw/virtio-pci.c | 24 +++++++++++++++++++++++- 1 files changed, 23 insertions(+), 1 deletions(-) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 3594152..dbbaf42 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -76,6 +76,10 @@ * 12 is historical, and due to x86 page size. */ #define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 +/* We can catch some guest bugs inside here so we continue supporting older + guests. */ +#define VIRTIO_PCI_BUG_BUS_MASTER (1 << 0) + /* QEMU doesn't strictly need write barriers since everything runs in * lock-step. We'll leave the calls to wmb() in though to make it obvious for * KVM or if kqemu gets SMP support. @@ -87,6 +91,7 @@ typedef struct { PCIDevice pci_dev; VirtIODevice *vdev; + uint32_t bugs; uint32_t addr; uint32_t class_code; uint32_t nvectors; @@ -138,6 +143,13 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f) if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) { return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector); } + + /* Try to find out if the guest has bus master disabled, but is + in ready state. Then we have a buggy guest OS. */ + if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) && + !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { + proxy->bugs |= VIRTIO_PCI_BUG_BUS_MASTER; + } return 0; } @@ -162,6 +174,7 @@ static void virtio_pci_reset(DeviceState *d) VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev); virtio_reset(proxy->vdev); msix_reset(&proxy->pci_dev); + proxy->bugs = 0; } static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) @@ -205,6 +218,14 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) virtio_reset(proxy->vdev); msix_unuse_all_vectors(&proxy->pci_dev); } + + /* Linux before 2.6.34 sets the device as OK without enabling + the PCI device bus master bit. In this case we need to disable + some safety checks. */ + if ((val & VIRTIO_CONFIG_S_DRIVER_OK) && + !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { + proxy->bugs |= VIRTIO_PCI_BUG_BUS_MASTER; + } break; case VIRTIO_MSI_CONFIG_VECTOR: msix_vector_unuse(&proxy->pci_dev, vdev->config_vector); @@ -371,7 +392,8 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); if (PCI_COMMAND == address) { - if (!(val & PCI_COMMAND_MASTER)) { + if (!(val & PCI_COMMAND_MASTER) && + !(proxy->bugs & VIRTIO_PCI_BUG_BUS_MASTER)) { proxy->vdev->status &= ~VIRTIO_CONFIG_S_DRIVER_OK; } }