From patchwork Tue Aug 26 08:22:27 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laszlo Ersek X-Patchwork-Id: 35953 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pd0-f200.google.com (mail-pd0-f200.google.com [209.85.192.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id E401620551 for ; Tue, 26 Aug 2014 08:22:49 +0000 (UTC) Received: by mail-pd0-f200.google.com with SMTP id w10sf113722843pde.11 for ; Tue, 26 Aug 2014 01:22:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:subject :precedence:reply-to:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:mime-version:errors-to:x-original-sender :x-original-authentication-results:mailing-list:content-type :content-transfer-encoding; bh=jnv7AiuyR9GB2eWrkNY+vVYXgzJdGWQt/z+5rg8cutc=; b=eXwmP2Vb9/umaSR7zk57jJb4CbE4ye/kbDPZhk41yNUuyjxuWqjI+17JtoXbzC090p /YpgflJnDPyk8qm3mWxdAPOzi/ITMDYFmFp1f5DTq9tPToi/JtqQkiR1gh3CAGxm/zHc J3uNUiK0YyHUIcT/8X9mW3mUl4QKDVtV7B04yAGPVc0CgGrycZoMHxWUddh6b/d8pwS7 rc1uj1cGwERfF3CveJfhwsPaie6jR87jqxjF/knOgBqXeATAO1n71BJPzKcP7xtmOaZN k5zcEWCf6dnAqJg5WzYik7KiHLX/yQ/EXrxfIob398909xr2jVpQPmSPbasp8oY3bBZ8 dUkQ== X-Gm-Message-State: ALoCoQk1Xh/FBzOR38CrpSHp5XX5evSQpP/q9I9MTl9M+VqrhKr1cnLheVLywV9T9B5NoaL97g1t X-Received: by 10.66.228.70 with SMTP id sg6mr16113624pac.2.1409041369176; Tue, 26 Aug 2014 01:22:49 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.84.47 with SMTP id k44ls2407371qgd.73.gmail; Tue, 26 Aug 2014 01:22:49 -0700 (PDT) X-Received: by 10.52.246.198 with SMTP id xy6mr19141716vdc.7.1409041369073; Tue, 26 Aug 2014 01:22:49 -0700 (PDT) Received: from mail-vc0-f173.google.com (mail-vc0-f173.google.com [209.85.220.173]) by mx.google.com with ESMTPS id w7si1158107vcs.17.2014.08.26.01.22.49 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 26 Aug 2014 01:22:49 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.173 as permitted sender) client-ip=209.85.220.173; Received: by mail-vc0-f173.google.com with SMTP id hy10so16488334vcb.32 for ; Tue, 26 Aug 2014 01:22:49 -0700 (PDT) X-Received: by 10.220.59.65 with SMTP id k1mr22561421vch.22.1409041368953; Tue, 26 Aug 2014 01:22:48 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.45.67 with SMTP id uj3csp179172vcb; Tue, 26 Aug 2014 01:22:48 -0700 (PDT) X-Received: by 10.42.216.135 with SMTP id hi7mr28102581icb.12.1409041368371; Tue, 26 Aug 2014 01:22:48 -0700 (PDT) Received: from lists.sourceforge.net (lists.sourceforge.net. [216.34.181.88]) by mx.google.com with ESMTPS id qo6si2287359igb.23.2014.08.26.01.22.47 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 26 Aug 2014 01:22:48 -0700 (PDT) Received-SPF: pass (google.com: domain of edk2-devel-bounces@lists.sourceforge.net designates 216.34.181.88 as permitted sender) client-ip=216.34.181.88; Received: from localhost ([127.0.0.1] helo=sfs-ml-2.v29.ch3.sourceforge.com) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1XMC1Y-0006PY-84; Tue, 26 Aug 2014 08:22:40 +0000 Received: from sog-mx-1.v43.ch3.sourceforge.com ([172.29.43.191] helo=mx.sourceforge.net) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1XMC1X-0006PM-3y for edk2-devel@lists.sourceforge.net; Tue, 26 Aug 2014 08:22:39 +0000 Received-SPF: pass (sog-mx-1.v43.ch3.sourceforge.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=lersek@redhat.com; helo=mx1.redhat.com; Received: from mx1.redhat.com ([209.132.183.28]) by sog-mx-1.v43.ch3.sourceforge.com with esmtps (TLSv1:AES256-SHA:256) (Exim 4.76) id 1XMC1V-0000wJ-RV for edk2-devel@lists.sourceforge.net; Tue, 26 Aug 2014 08:22:39 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s7Q8MUSS028768 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Tue, 26 Aug 2014 04:22:31 -0400 Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s7Q8MTqo023826; Tue, 26 Aug 2014 04:22:29 -0400 From: Laszlo Ersek To: edk2-devel@lists.sourceforge.net, kraxel@redhat.com Date: Tue, 26 Aug 2014 10:22:27 +0200 Message-Id: <1409041347-1638-1-git-send-email-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Spam-Score: -1.5 (-) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -1.5 SPF_CHECK_PASS SPF reports sender host as permitted sender for sender-domain -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain X-Headers-End: 1XMC1V-0000wJ-RV Subject: [edk2] [PATCH v2] OvmfPkg: QemuVideoDxe: work around misreported QXL framebuffer size X-BeenThere: edk2-devel@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list Reply-To: edk2-devel@lists.sourceforge.net List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.sourceforge.net X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: lersek@redhat.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.173 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 When setting up the list of GOP modes offered on QEMU's stdvga ("VGA") and QXL ("qxl-vga") video devices, QemuVideoBochsModeSetup() filters those modes against the available framebuffer size. (Refer to SVN r15288 / git commit ec88061e.) The VBE_DISPI_INDEX_VIDEO_MEMORY_64K register of both stdvga and QXL is supposed to report the size of the drawable, VGA-compatibility framebuffer. Instead, up to and including qemu-2.1, this register actually reports the full video RAM (PCI BAR 0) size. In case of stdvga, this happens to be correct, because on that card the full PCI BAR 0 is usable for drawing; there is no difference between "drawable framebuffer size" and "video RAM (PCI BAR 0) size". However, on the QXL card, only an initial portion of the video RAM is suitable for drawing, as compatibility framebuffer; and the value currently reported by VBE_DISPI_INDEX_VIDEO_MEMORY_64K overshoots the valid size. Beyond the drawable range, the video RAM contains buffers and structures for the QXL guest-host protocol. Luckily, the size of the drawable QXL framebuffer can also be read from a register in the QXL ROM BAR (PCI BAR 2), so let's retrieve it from there. Without this fix, OVMF offers too large resolutions on the QXL card (up to the full size of the video RAM). If a GOP client selects such a resolution and draws into the video RAM past the compatibility segment, then the guest corrupts its communication structures (which is invalid guest behavior). Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek Reviewed-by: Gerd Hoffmann Reviewed-by: Jordan Justen --- Notes: v2: - clarify in the commit message and the QemuVideoBochsModeSetup() comment that this is a workaround for a QEMU bug [Gerd] - Calculate IsQxl more explicitly in QemuVideoControllerDriverStart() [Jordan] OvmfPkg/QemuVideoDxe/Qemu.h | 3 ++- OvmfPkg/QemuVideoDxe/Driver.c | 9 +++++++- OvmfPkg/QemuVideoDxe/Initialize.c | 47 +++++++++++++++++++++++++++++++++++---- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h index 4bf51c7..52ee20d 100644 --- a/OvmfPkg/QemuVideoDxe/Qemu.h +++ b/OvmfPkg/QemuVideoDxe/Qemu.h @@ -499,7 +499,8 @@ QemuVideoCirrusModeSetup ( EFI_STATUS QemuVideoBochsModeSetup ( - QEMU_VIDEO_PRIVATE_DATA *Private + QEMU_VIDEO_PRIVATE_DATA *Private, + BOOLEAN IsQxl ); VOID diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c index 2194cbe..17bd4cc 100644 --- a/OvmfPkg/QemuVideoDxe/Driver.c +++ b/OvmfPkg/QemuVideoDxe/Driver.c @@ -173,6 +173,7 @@ QemuVideoControllerDriverStart ( EFI_TPL OldTpl; EFI_STATUS Status; QEMU_VIDEO_PRIVATE_DATA *Private; + BOOLEAN IsQxl; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; ACPI_ADR_DEVICE_PATH AcpiDeviceNode; PCI_TYPE00 Pci; @@ -235,6 +236,12 @@ QemuVideoControllerDriverStart ( Private->Variant = Card->Variant; // + // IsQxl is based on the detected Card->Variant, which at a later point might + // not match Private->Variant. + // + IsQxl = (BOOLEAN)(Card->Variant == QEMU_VIDEO_BOCHS); + + // // Save original PCI attributes // Status = Private->PciIo->Attributes ( @@ -354,7 +361,7 @@ QemuVideoControllerDriverStart ( break; case QEMU_VIDEO_BOCHS_MMIO: case QEMU_VIDEO_BOCHS: - Status = QemuVideoBochsModeSetup (Private); + Status = QemuVideoBochsModeSetup (Private, IsQxl); break; default: ASSERT (FALSE); diff --git a/OvmfPkg/QemuVideoDxe/Initialize.c b/OvmfPkg/QemuVideoDxe/Initialize.c index a536d47..9e0c3aa 100644 --- a/OvmfPkg/QemuVideoDxe/Initialize.c +++ b/OvmfPkg/QemuVideoDxe/Initialize.c @@ -253,7 +253,8 @@ QEMU_VIDEO_BOCHS_MODES QemuVideoBochsModes[] = { EFI_STATUS QemuVideoBochsModeSetup ( - QEMU_VIDEO_PRIVATE_DATA *Private + QEMU_VIDEO_PRIVATE_DATA *Private, + BOOLEAN IsQxl ) { UINT32 AvailableFbSize; @@ -262,10 +263,48 @@ QemuVideoBochsModeSetup ( QEMU_VIDEO_BOCHS_MODES *VideoMode; // - // fetch available framebuffer size + // Fetch the available framebuffer size. // - AvailableFbSize = BochsRead (Private, VBE_DISPI_INDEX_VIDEO_MEMORY_64K); - AvailableFbSize *= SIZE_64KB; + // VBE_DISPI_INDEX_VIDEO_MEMORY_64K is expected to return the size of the + // drawable framebuffer. Up to and including qemu-2.1 however it used to + // return the size of PCI BAR 0 (ie. the full video RAM size). + // + // On stdvga the two concepts coincide with each other; the full memory size + // is usable for drawing. + // + // On QXL however, only a leading segment, "surface 0", can be used for + // drawing; the rest of the video memory is used for the QXL guest-host + // protocol. VBE_DISPI_INDEX_VIDEO_MEMORY_64K should report the size of + // "surface 0", but since it doesn't (up to and including qemu-2.1), we + // retrieve the size of the drawable portion from a field in the QXL ROM BAR, + // where it is also available. + // + if (IsQxl) { + UINT32 Signature; + UINT32 DrawStart; + + Signature = 0; + DrawStart = 0xFFFFFFFF; + AvailableFbSize = 0; + if (EFI_ERROR ( + Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32, + PCI_BAR_IDX2, 0, 1, &Signature)) || + Signature != SIGNATURE_32 ('Q', 'X', 'R', 'O') || + EFI_ERROR ( + Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32, + PCI_BAR_IDX2, 36, 1, &DrawStart)) || + DrawStart != 0 || + EFI_ERROR ( + Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32, + PCI_BAR_IDX2, 40, 1, &AvailableFbSize))) { + DEBUG ((EFI_D_ERROR, "%a: can't read size of drawable buffer from QXL " + "ROM\n", __FUNCTION__)); + return EFI_NOT_FOUND; + } + } else { + AvailableFbSize = BochsRead (Private, VBE_DISPI_INDEX_VIDEO_MEMORY_64K); + AvailableFbSize *= SIZE_64KB; + } DEBUG ((EFI_D_VERBOSE, "%a: AvailableFbSize=0x%x\n", __FUNCTION__, AvailableFbSize));