All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Richard W.M. Jones" <rjones@redhat.com>
To: Gerd Hoffmann <kraxel@redhat.com>
Cc: marc.mari.barcelo@gmail.com, ehabkost@redhat.com, mst@redhat.com,
	Stefan Hajnoczi <stefanha@gmail.com>,
	qemu-devel@nongnu.org, pbonzini@redhat.com, rth@twiddle.net
Subject: Re: [Qemu-devel] [PATCH v4.1] Add optionrom compatible with fw_cfg DMA version
Date: Fri, 22 Apr 2016 13:23:02 +0100	[thread overview]
Message-ID: <20160422122302.GK19398@redhat.com> (raw)
In-Reply-To: <1459841368.2037.9.camel@redhat.com>

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;
 


-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-builder quickly builds VMs from scratch
http://libguestfs.org/virt-builder.1.html

  reply	other threads:[~2016-04-22 12:23 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-01 12:43 [Qemu-devel] [PATCH v4.1] Add optionrom compatible with fw_cfg DMA version Richard W.M. Jones
2016-04-01 12:43 ` Richard W.M. Jones
2016-04-04 15:02   ` Stefan Hajnoczi
2016-04-04 15:21     ` Richard W.M. Jones
2016-04-05  7:29       ` Gerd Hoffmann
2016-04-22 12:23         ` Richard W.M. Jones [this message]
2016-04-05 12:51       ` Laszlo Ersek
2016-04-05 13:09         ` Paolo Bonzini
2016-04-07  8:54     ` Marc Marí
2016-04-04 15:12 ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160422122302.GK19398@redhat.com \
    --to=rjones@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=marc.mari.barcelo@gmail.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    --cc=stefanha@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.