From patchwork Tue Feb 2 04:15:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 576975 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 2D70E140BAF for ; Tue, 2 Feb 2016 15:16:16 +1100 (AEDT) Received: from localhost ([::1]:55122 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aQSNx-000671-V2 for incoming@patchwork.ozlabs.org; Mon, 01 Feb 2016 23:16:13 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35995) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aQSNi-0005pp-R4 for qemu-devel@nongnu.org; Mon, 01 Feb 2016 23:16:00 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aQSNf-0002Qg-LY for qemu-devel@nongnu.org; Mon, 01 Feb 2016 23:15:58 -0500 Received: from mx1.redhat.com ([209.132.183.28]:47644) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aQSNf-0002QS-Dl for qemu-devel@nongnu.org; Mon, 01 Feb 2016 23:15:55 -0500 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 0AB188EA20; Tue, 2 Feb 2016 04:15:53 +0000 (UTC) Received: from gimli.home (ovpn-113-102.phx2.redhat.com [10.3.113.102]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u124FqdF022228; Mon, 1 Feb 2016 23:15:52 -0500 From: Alex Williamson To: seabios@seabios.org Date: Mon, 01 Feb 2016 21:15:52 -0700 Message-ID: <20160202041510.32092.58972.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: qemu-devel@nongnu.org, kraxel@redhat.com Subject: [Qemu-devel] [RFC PATCH] fw/pci: Add support for mapping Intel IGD OpRegion via QEMU 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 proposed IGD OpRegion support in QEMU via vfio maps the host OpRegion into VM system memory at the address written to the ASL Storage register (0xFC). The OpRegion contains a 16-byte signature followed by a 4-byte size field. Therefore SeaBIOS can allocate a buffer of the typical size (8KB), this results in a matching e820 reserved entry for the range, then write the buffer address to the ASL Storage register, blinking the OpRegion into the VM address space. At that point SeaBIOS can validate the signature and size and remap if necessary. If the OpRegion is larger than 8KB, this would result in any conflicting ranges being temporarily mapped with the OpRegion, which probably needs further discussion on what that could break. Other options might be to use the same algorithm with an obscenely sized initial buffer to make sure we do not overlap, always re-allocating the proper sized buffer, or perhaps we could pass the OpRegion itself or information about the OpRegion through fw_cfg. With the posted kernel series[1] and QEMU series[2] (on top of Gerd's IGD patches[3]), this makes the OpRegion available to the VM and tracing shows that the guest driver does access it. [1] https://lkml.org/lkml/2016/2/1/884 [2] https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg00202.html [3] https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg00244.html Signed-off-by: Alex Williamson --- src/fw/pciinit.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index c31c2fa..4f3251e 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -257,6 +257,52 @@ static void ich9_smbus_setup(struct pci_device *dev, void *arg) pci_config_writeb(bdf, ICH9_SMB_HOSTC, ICH9_SMB_HOSTC_HST_EN); } +static void intel_igd_opregion_setup(struct pci_device *dev, void *arg) +{ + u16 bdf = dev->bdf; + u32 orig; + void *opregion; + int size = 8; + + if (!CONFIG_QEMU) + return; + + orig = pci_config_readl(bdf, 0xFC); + +realloc: + opregion = malloc_high(size * 1024); + if (!opregion) { + warn_noalloc(); + return; + } + + /* + * QEMU maps the OpRegion into system memory at the address written here, + * this overlaps our malloc, which marks the range e820 reserved. + */ + pci_config_writel(bdf, 0xFC, cpu_to_le32((u32)opregion)); + + if (memcmp(opregion, "IntelGraphicsMem", 16)) { + pci_config_writel(bdf, 0xFC, orig); + free(opregion); + return; /* the opregion didn't magically appear, not supported */ + } + + if (size == le32_to_cpu(*(u32 *)(opregion + 16))) { + dprintf(1, "Intel IGD OpRegion enabled on %02x:%02x.%x\n", + pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf)); + return; /* success! */ + } + + pci_config_writel(bdf, 0xFC, orig); + free(opregion); + + if (size == 8) { /* try once more with a new size */ + size = le32_to_cpu(*(u32 *)(opregion + 16)); + goto realloc; + } +} + static const struct pci_device_id pci_device_tbl[] = { /* PIIX3/PIIX4 PCI to ISA bridge */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, @@ -290,6 +336,10 @@ static const struct pci_device_id pci_device_tbl[] = { PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_setup), PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_setup), + /* Intel IGD OpRegion setup */ + PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA, + intel_igd_opregion_setup), + PCI_DEVICE_END, };