From patchwork Thu Jul 23 19:06:35 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 499498 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 2A8251402B3 for ; Fri, 24 Jul 2015 05:07:17 +1000 (AEST) Received: from localhost ([::1]:42506 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZILpr-00054M-2y for incoming@patchwork.ozlabs.org; Thu, 23 Jul 2015 15:07:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37435) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZILpM-0004EB-BT for qemu-devel@nongnu.org; Thu, 23 Jul 2015 15:06:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZILpE-00050R-Ko for qemu-devel@nongnu.org; Thu, 23 Jul 2015 15:06:44 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58651) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZILpE-00050F-82 for qemu-devel@nongnu.org; Thu, 23 Jul 2015 15:06:36 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id EEC05C12E9 for ; Thu, 23 Jul 2015 19:06:35 +0000 (UTC) Received: from gimli.home (ovpn-113-117.phx2.redhat.com [10.3.113.117]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t6NJ6ZIb009343; Thu, 23 Jul 2015 15:06:35 -0400 From: Alex Williamson To: qemu-devel@nongnu.org Date: Thu, 23 Jul 2015 13:06:35 -0600 Message-ID: <20150723190627.28669.75319.stgit@gimli.home> In-Reply-To: <20150723190414.28669.75130.stgit@gimli.home> References: <20150723190414.28669.75130.stgit@gimli.home> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: alex.williamson@redhat.com Subject: [Qemu-devel] [PULL 1/2] vfio/pci: Fix RTL8168 NIC quirks 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 The RTL8168 quirk correctly describes using bit 31 as a signal to mark a latch/completion, but the code mistakenly uses bit 28. This causes the Realtek driver to spin on this register for quite a while, 20k cycles on Windows 7 v7.092 driver. Then it gets frustrated and tries to set the bit itself and spins for another 20k cycles. For some this still results in a working driver, for others not. About the only thing the code really does in its current form is protect the guest from sneaking in writes to the real hardware MSI-X table. The fix is obviously to use bit 31 as we document that we should. The other problem doesn't seem to affect current drivers as nobody seems to use these window registers for writes to the MSI-X table, but we need to use the stored data when a write is triggered, not the value of the current write, which only provides the offset. Note that only the Windows drivers from Realtek seem to use these registers, the Microsoft drivers provided with Windows 8.1 do not access them, nor do Linux in-kernel drivers. Link: https://bugs.launchpad.net/qemu/+bug/1384892 Signed-off-by: Alex Williamson Cc: qemu-stable@nongnu.org # v2.1+ --- hw/vfio/pci.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 2ed877f..0af762a 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1517,7 +1517,7 @@ static uint64_t vfio_rtl8168_window_quirk_read(void *opaque, memory_region_name(&quirk->mem), vdev->vbasedev.name); - return quirk->data.address_match ^ 0x10000000U; + return quirk->data.address_match ^ 0x80000000U; } break; case 0: /* data */ @@ -1558,7 +1558,7 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr, switch (addr) { case 4: /* address */ if ((data & 0x7fff0000) == 0x10000) { - if (data & 0x10000000U && + if (data & 0x80000000U && vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX) { trace_vfio_rtl8168_window_quirk_write_table( @@ -1566,11 +1566,9 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr, vdev->vbasedev.name); memory_region_dispatch_write(&vdev->pdev.msix_table_mmio, - (hwaddr)(quirk->data.address_match - & 0xfff), - data, - size, - MEMTXATTRS_UNSPECIFIED); + (hwaddr)(data & 0xfff), + (uint64_t)quirk->data.address_mask, + size, MEMTXATTRS_UNSPECIFIED); } quirk->data.flags = 1;