From patchwork Wed May 10 14:31:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Druzhinin X-Patchwork-Id: 9720001 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2763860236 for ; Wed, 10 May 2017 14:39:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1919F285FE for ; Wed, 10 May 2017 14:39:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0DAD228607; Wed, 10 May 2017 14:39:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 40E1A285FE for ; Wed, 10 May 2017 14:39:45 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1d8Sk9-0004hd-9l; Wed, 10 May 2017 14:37:33 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1d8Sk7-0004hL-QV for xen-devel@lists.xen.org; Wed, 10 May 2017 14:37:31 +0000 Received: from [85.158.139.211] by server-4.bemta-5.messagelabs.com id 8C/5D-02181-BA523195; Wed, 10 May 2017 14:37:31 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmplkeJIrShJLcpLzFFi42LZKekoobtcVTj SoGMrh8WSj4tZHBg9ju7+zRTAGMWamZeUX5HAmnG1Yx5zwX77ihNPrrA0MD426WLk5JAQ8JNY 8uMIC4jNJmAgcWrTIjBbREBWYnXXHPYuRi4OZoEjjBJ/Hz9iB0kIC0RKPD6yG6yIRUBVYun6P cwgNq+Ap8T/zQ+ZIIbKSdw81wkVF5Q4OfMJWD2zgITEwRcvwOJCAmoSR7t2sUDUp0scmPeNcQ IjzywkLbOQtCxgZFrFqF6cWlSWWqRrqJdUlJmeUZKbmJmja2hgqpebWlycmJ6ak5hUrJecn7u JERgk9QwMjDsYm3qdDzFKcjApifLq7hKKFOJLyk+pzEgszogvKs1JLT7EKMPBoSTBG6UiHCkk WJSanlqRlpkDDFeYtAQHj5IIbzNImre4IDG3ODMdInWKUZfj3dIP75mEWPLy81KlxHmlQYoEQ IoySvPgRsBi5xKjrJQwLyMDA4MQT0FqUW5mCar8K0ZxDkYlYd5IkCk8mXklcJteAR3BBHREII MAyBEliQgpqQbG8rrS87WhNl+LlT/rZS9uCxTpWfQv6LpabmXsu2URj2eIz0zbvYrltVfFD+8 fZ2395I96/041MityqJcN+zJ10aW5r0u+pK6T0jhgn3aY11a4yi3Ymb1gt0Pf7CXCjWI33/59 W3Za8NP8STy5WyZtPrtFL7Dk8N+TvE9Nl/AVXn368PAMxVJPJZbijERDLeai4kQAA3GVz5gCA AA= X-Env-Sender: prvs=296f43a01=igor.druzhinin@citrix.com X-Msg-Ref: server-16.tower-206.messagelabs.com!1494427046!81449502!1 X-Originating-IP: [185.25.65.24] X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.4.12; banners=-,-,- X-VirusChecked: Checked Received: (qmail 43274 invoked from network); 10 May 2017 14:37:27 -0000 Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24) by server-16.tower-206.messagelabs.com with RC4-SHA encrypted SMTP; 10 May 2017 14:37:27 -0000 X-IronPort-AV: E=Sophos;i="5.38,319,1491264000"; d="scan'208";a="45768805" From: Igor Druzhinin To: Date: Wed, 10 May 2017 15:31:18 +0100 Message-ID: <1494426678-30346-1-git-send-email-igor.druzhinin@citrix.com> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 X-ClientProxiedBy: FTLPEX02CAS01.citrite.net (10.13.99.120) To AMSPEX02CL03.citrite.net (10.69.22.127) Cc: Igor Druzhinin , Ian Jackson , Wei Liu , Jan Beulich , Andrew Cooper Subject: [Xen-devel] [PATCH] firmware/vgabios: Port PCI based VBE LFB discovery method from QEMU fork X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP QEMU-traditional implements non-standard VBE registers for getting LFB physical address from inside of VGA BIOS code. QEMU doesn't have those registers implemented and returns 0 when an HVM guest is trying to access them from the existing ROMBIOS code. This eventually leads to a triple fault inside a guest which happened to use ROMBIOS instead of SeaBIOS when in stdvga mode. QEMU maintains its own fork of VGA BIOS where the VBE LFB discovery is implemented through a regular PCI BAR reading. In order to support that we need to build a PCI compliant VGA BIOS version for stdvga and include it into ROMBIOS instead of the old one. Signed-off-by: Igor Druzhinin --- CC: Jan Beulich CC: Andrew Cooper CC: Ian Jackson CC: Wei Liu --- tools/firmware/hvmloader/Makefile | 2 +- tools/firmware/vgabios/Makefile | 29 +++++++++++++++-- tools/firmware/vgabios/vbe.c | 9 ++++++ tools/firmware/vgabios/vgabios.c | 68 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 3 deletions(-) diff --git a/tools/firmware/hvmloader/Makefile b/tools/firmware/hvmloader/Makefile index 80d7b44..5f6eacd 100644 --- a/tools/firmware/hvmloader/Makefile +++ b/tools/firmware/hvmloader/Makefile @@ -45,7 +45,7 @@ CIRRUSVGA_DEBUG ?= n ROMBIOS_DIR := ../rombios ifeq ($(CONFIG_ROMBIOS),y) -STDVGA_ROM := ../vgabios/VGABIOS-lgpl-latest.bin +STDVGA_ROM := ../vgabios/VGABIOS-lgpl-latest.stdvga.bin ifeq ($(CIRRUSVGA_DEBUG),y) CIRRUSVGA_ROM := ../vgabios/VGABIOS-lgpl-latest.cirrus.debug.bin else diff --git a/tools/firmware/vgabios/Makefile b/tools/firmware/vgabios/Makefile index 3284812..0f4026e 100644 --- a/tools/firmware/vgabios/Makefile +++ b/tools/firmware/vgabios/Makefile @@ -11,7 +11,7 @@ RELVERS = `pwd | sed "s-.*/--" | sed "s/vgabios//" | sed "s/-//"` VGABIOS_DATE = "-DVGABIOS_DATE=\"$(VGABIOS_REL_DATE)\"" .PHONY: all -all: bios cirrus-bios +all: bios cirrus-bios stdvga-bios .PHONY: bios bios: biossums vgabios.bin vgabios.debug.bin @@ -19,6 +19,9 @@ bios: biossums vgabios.bin vgabios.debug.bin .PHONY: cirrus-bios cirrus-bios: vgabios-cirrus.bin vgabios-cirrus.debug.bin +.PHONY: stdvga-bios +stdvga-bios: vgabios-stdvga.bin vgabios-stdvga.debug.bin + .PHONY: clean clean: rm -f biossums vbetables-gen vbetables.h *.o *.s *.ld86 \ @@ -30,13 +33,15 @@ distclean: clean .PHONY: release release: - VGABIOS_VERS=\"-DVGABIOS_VERS=\\\"$(RELVERS)\\\"\" make bios cirrus-bios + VGABIOS_VERS=\"-DVGABIOS_VERS=\\\"$(RELVERS)\\\"\" make bios cirrus-bios stdvga-bios /bin/rm -f *.o *.s *.ld86 \ temp.awk.* vgabios.*.orig _vgabios_.*.c core *.bak .#* cp VGABIOS-lgpl-latest.bin ../$(RELEASE).bin cp VGABIOS-lgpl-latest.debug.bin ../$(RELEASE).debug.bin cp VGABIOS-lgpl-latest.cirrus.bin ../$(RELEASE).cirrus.bin cp VGABIOS-lgpl-latest.cirrus.debug.bin ../$(RELEASE).cirrus.debug.bin + cp VGABIOS-lgpl-latest.stdvga.bin ../$(RELEASE).stdvga.bin + cp VGABIOS-lgpl-latest.stdvga.debug.bin ../$(RELEASE).stdvga.debug.bin tar czvf ../$(RELEASE).tgz --exclude CVS -C .. $(RELEASE)/ vgabios.bin: biossums vgabios.c vgabios.h vgafonts.h vgatables.h vbe.h vbe.c vbetables.h @@ -59,6 +64,26 @@ vgabios.debug.bin: biossums vgabios.c vgabios.h vgafonts.h vgatables.h vbe.h vbe ./biossums VGABIOS-lgpl-latest.debug.bin ls -l VGABIOS-lgpl-latest.debug.bin +vgabios-stdvga.bin: biossums vgabios.c vgabios.h vgafonts.h vgatables.h vbe.h vbe.c vbetables.h + $(GCC) -E -P vgabios.c $(VGABIOS_VERS) -DVBE -DPCIBIOS -DPCI_VID=0x1234 -DPCI_DID=0x1111 $(VGABIOS_DATE) > _vgabios-stdvga_.c + $(BCC) -o vgabios-stdvga.s -C-c -D__i86__ -S -0 _vgabios-stdvga_.c + sed -e 's/^\.text//' -e 's/^\.data//' vgabios-stdvga.s > _vgabios-stdvga_.s + $(AS86) _vgabios-stdvga_.s -b vgabios-stdvga.bin -u -w- -g -0 -j -O -l vgabios-stdvga.txt + rm -f _vgabios-stdvga_.s _vgabios-stdvga_.c vgabios-stdvga.s + cp vgabios-stdvga.bin VGABIOS-lgpl-latest.stdvga.bin + ./biossums VGABIOS-lgpl-latest.stdvga.bin + ls -l VGABIOS-lgpl-latest.stdvga.bin + +vgabios-stdvga.debug.bin: biossums vgabios.c vgabios.h vgafonts.h vgatables.h vbe.h vbe.c vbetables.h + $(GCC) -E -P vgabios.c $(VGABIOS_VERS) -DVBE -DPCIBIOS -DPCI_VID=0x1234 -DPCI_DID=0x1111 -DDEBUG $(VGABIOS_DATE) > _vgabios-stdvga-debug_.c + $(BCC) -o vgabios-stdvga-debug.s -C-c -D__i86__ -S -0 _vgabios-stdvga-debug_.c + sed -e 's/^\.text//' -e 's/^\.data//' vgabios-stdvga-debug.s > _vgabios-stdvga-debug_.s + $(AS86) _vgabios-stdvga-debug_.s -b vgabios-stdvga-debug.bin -u -w- -g -0 -j -O -l vgabios-stdvga-debug.txt + rm -f _vgabios-stdvga-debug_.s _vgabios-stdvga-debug_.c vgabios-stdvga-debug.s + cp vgabios-stdvga-debug.bin VGABIOS-lgpl-latest.stdvga.debug.bin + ./biossums VGABIOS-lgpl-latest.stdvga.debug.bin + ls -l VGABIOS-lgpl-latest.stdvga.debug.bin + vgabios-cirrus.bin: biossums vgabios.c vgabios.h vgafonts.h vgatables.h clext.c $(GCC) -E -P vgabios.c $(VGABIOS_VERS) -DCIRRUS -DPCIBIOS $(VGABIOS_DATE) > _vgabios-cirrus_.c $(BCC) -o vgabios-cirrus.s -C-c -D__i86__ -S -0 _vgabios-cirrus_.c diff --git a/tools/firmware/vgabios/vbe.c b/tools/firmware/vgabios/vbe.c index c506690..d7706f5 100644 --- a/tools/firmware/vgabios/vbe.c +++ b/tools/firmware/vgabios/vbe.c @@ -914,6 +914,7 @@ Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI; ModeInfoListItem *cur_info; Boolean using_lfb; ModeInfoBlockCompact info; + Bit16u lfb_addr=0; #ifdef DEBUG printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX); @@ -957,6 +958,14 @@ Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI; outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_LFB_ADDRESS_L); info.PhysBasePtr |= inw(VBE_DISPI_IOPORT_DATA); #endif +#ifdef PCI_VID + if ((Bit16u)(info.PhysBasePtr >> 16) == 0 && + (Bit16u)info.PhysBasePtr == 0) + lfb_addr = pci_get_lfb_addr(PCI_VID); + + if (lfb_addr > 0) + info.PhysBasePtr = ((Bit32u)lfb_addr << 16); +#endif result = 0x4f; // copy updates in mode_info_block back diff --git a/tools/firmware/vgabios/vgabios.c b/tools/firmware/vgabios/vgabios.c index 1c75b7d..22471c5 100644 --- a/tools/firmware/vgabios/vgabios.c +++ b/tools/firmware/vgabios/vgabios.c @@ -209,8 +209,13 @@ vgabios_pci_data: .word 0x1013 .word 0x00b8 // CLGD5446 #else +#ifdef PCI_VID +.word PCI_VID +.word PCI_DID +#else #error "Unknown PCI vendor and device id" #endif +#endif .word 0 // reserved .word 0x18 // dlen .byte 0 // revision @@ -3829,6 +3834,69 @@ void printf(s) } #endif +ASM_START + ; get LFB address from PCI + ; in - ax: PCI device vendor + ; out - ax: LFB address (high 16 bit) + ;; NOTE - may be called in protected mode +_pci_get_lfb_addr: + push bx + push cx + push dx + push eax + mov bx, ax + xor cx, cx + mov dl, #0x00 + call pci_read_reg + cmp ax, #0xffff + jz pci_get_lfb_addr_fail + pci_get_lfb_addr_next_dev: + mov dl, #0x00 + call pci_read_reg + cmp ax, bx ;; check vendor + jz pci_get_lfb_addr_found + add cx, #0x8 + cmp cx, #0x200 ;; search bus #0 and #1 + jb pci_get_lfb_addr_next_dev + pci_get_lfb_addr_fail: + xor dx, dx ;; no LFB + jmp pci_get_lfb_addr_return + pci_get_lfb_addr_found: + mov dl, #0x10 ;; I/O space #0 + call pci_read_reg + test ax, #0xfff1 + jz pci_get_lfb_addr_success + mov dl, #0x14 ;; I/O space #1 + call pci_read_reg + test ax, #0xfff1 + jnz pci_get_lfb_addr_fail + pci_get_lfb_addr_success: + shr eax, #16 + mov dx, ax ;; LFB address + pci_get_lfb_addr_return: + pop eax + mov ax, dx + pop dx + pop cx + pop bx + ret + + ; read PCI register + ; in - cx: device/function + ; in - dl: register + ; out - eax: value +pci_read_reg: + mov eax, #0x00800000 + mov ax, cx + shl eax, #8 + mov al, dl + mov dx, #0xcf8 + out dx, eax + add dl, #4 + in eax, dx + ret +ASM_END + #ifdef VBE #include "vbe.c" #endif