From patchwork Fri Apr 22 12:23:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Richard W.M. Jones" X-Patchwork-Id: 8911531 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 4B27F9F1D3 for ; Fri, 22 Apr 2016 12:23:23 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6A1DA20225 for ; Fri, 22 Apr 2016 12:23:22 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3404020221 for ; Fri, 22 Apr 2016 12:23:21 +0000 (UTC) Received: from localhost ([::1]:60506 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ata7E-0003sG-5K for patchwork-qemu-devel@patchwork.kernel.org; Fri, 22 Apr 2016 08:23:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42365) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ata73-0003mh-Lu for qemu-devel@nongnu.org; Fri, 22 Apr 2016 08:23:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ata6z-0003X3-L6 for qemu-devel@nongnu.org; Fri, 22 Apr 2016 08:23:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48316) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ata6z-0003V9-Da for qemu-devel@nongnu.org; Fri, 22 Apr 2016 08:23:05 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F2A6481106; Fri, 22 Apr 2016 12:23:03 +0000 (UTC) Received: from localhost (ovpn-204-22.brq.redhat.com [10.40.204.22]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u3MCN2DL012486; Fri, 22 Apr 2016 08:23:03 -0400 Date: Fri, 22 Apr 2016 13:23:02 +0100 From: "Richard W.M. Jones" To: Gerd Hoffmann Message-ID: <20160422122302.GK19398@redhat.com> References: <1459514627-23867-1-git-send-email-rjones@redhat.com> <1459514627-23867-2-git-send-email-rjones@redhat.com> <20160404150204.GB13632@stefanha-x1.localdomain> <20160404152112.GT32728@redhat.com> <1459841368.2037.9.camel@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1459841368.2037.9.camel@redhat.com> User-Agent: Mutt/1.5.20 (2009-12-10) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: Re: [Qemu-devel] [PATCH v4.1] Add optionrom compatible with fw_cfg DMA version X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: marc.mari.barcelo@gmail.com, ehabkost@redhat.com, mst@redhat.com, Stefan Hajnoczi , qemu-devel@nongnu.org, pbonzini@redhat.com, rth@twiddle.net Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On Tue, Apr 05, 2016 at 09:29:28AM +0200, Gerd Hoffmann wrote: > On Mo, 2016-04-04 at 16:21 +0100, Richard W.M. Jones wrote: > > On Mon, Apr 04, 2016 at 04:02:04PM +0100, Stefan Hajnoczi wrote: > > > (1) initrd loading is broken, kernel complains it finds only gibberish: > > > > > > [ 0.934582] Unpacking initramfs... > > > [ 1.166983] Initramfs unpacking failed: junk in compressed archive > > > [ 1.168458] Freeing initrd memory: 32812k freed > > > > That's strange. I certainly never saw anything like this. I wonder > > if it's because your initrd is particularly large? > > I've simply used /boot/initramfs-$version from the host. It's 33M. Not > exactly small, but given this is a standard RHEL-7 install I also > wouldn't rate this as unusual big. The problem here was the GCC asm statement that calls the 0xE801 BIOS function. It wasn't actually reading %bx, %cx, %dx, and so the whole calculation of where to put the initrd was wrong. The attached patch fixes things for me. I also rewrote the get_e801_addr function to make it a little bit cleaner and clearer. However don't consider this patch for now. I'm going to post a new version of the whole patch with these changes integrated and the whole lot retested properly, hopefully later today. Rich. diff --git a/pc-bios/optionrom/linuxboot_dma.c b/pc-bios/optionrom/linuxboot_dma.c index b0026aa..604ff3f 100644 --- a/pc-bios/optionrom/linuxboot_dma.c +++ b/pc-bios/optionrom/linuxboot_dma.c @@ -174,36 +174,39 @@ static void bios_cfg_read_entry(void *buf, uint16_t entry, uint32_t len) } } +/* Return top of memory using BIOS function E801. */ static uint32_t get_e801_addr(void) { - uint32_t eax, ebx, ecx, edx; + uint16_t eax, ebx, ecx, edx; uint32_t ret; - eax = 0xe801; ebx = 0; ecx = 0; edx = 0; asm("int $0x15\n" - : "+a"(eax) - : "b"(ebx), "c"(ecx), "d"(edx)); + : "=a"(eax), "+b"(ebx), "+c"(ecx), "+d"(edx) + : "a"(0xe801)); - /* Output could be in AX/BX or CX/DX */ - if ((uint16_t)ecx || (uint16_t)edx) { - if (!(uint16_t)edx) { - /* Add 1 MB and convert to bytes */ - ret = (ecx + 1024) << 10; - } else { - /* Add 16 MB and convert to bytes */ - ret = (edx + 256) << 16; - } + /* Not SeaBIOS, but in theory a BIOS could return CX=DX=0 in which case + * we need to use the result from AX & BX instead. + */ + if (ecx == 0 && edx == 0) { + ecx = eax; + edx = ebx; + } + + if (edx == 0) { + /* This is for machines with <= 16MB of RAM, which probably + * would never be the case, but deal with it anyway. + * ECX = extended memory between 1M and 16M, in kilobytes + * Convert it to bytes and return. + */ + ret = ((uint32_t)ecx + 1024 /* 1M in K */) << 10; } else { - if (!(uint16_t)ebx) { - /* Add 1 MB and convert to bytes */ - ret = (eax + 1024) << 10; - } else { - /* Add 16 MB and convert to bytes */ - ret = (ebx + 256) << 16; - } + /* EDX = extended memory above 16M, in 64K units. + * Convert it to bytes and return. + */ + ret = ((uint32_t)edx + 256 /* 16M in 64K units */) << 16; } return ret;