Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 361

kvm-83-270.el5_11.src.rpm

From 87161e4922a633e8dabfd2f39ff52ec0a75945f5 Mon Sep 17 00:00:00 2001
From: Gleb Natapov <gleb@redhat.com>
Date: Mon, 13 Apr 2009 16:58:07 +0300
Subject: [PATCH 02/15] fix extboot from boot with cache=off

Upstream commit: 1bfe3993ecf8cb4b3d63d204520c8f7e89b7741e

The patch also fix possible migration problem. Currently code calls
cpu_physical_memory_set_dirty() on a disk write, but it should do it
on a read.

    Extboot submits requests with whatever buffer alignment the guest gave
    to the BIOS.  This breaks with O_DIRECT disks, as they require 512 byte
    alignment.

    Most guest bootloaders sector align their requests out of paranoia, but
    the OpenBSD bootloader does not.

    This patch always copies.  Since extboot is only used at boot time to
    load limited amounts of data, the overhead is not problematic.  I also
    switched to using cpu_physical_memory_* instead of groveling around with
    phys_ram_base directly.

Signed-off-by: Nolan Leake <nolan@sigbus.net>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com
Message-ID: <20090413135807.GN25543@redhat.com>
Bugzilla: 500263
RH-Upstream-status: applied(kvm/master)
Acked-by: Zachary Amsden <zamsden@redhat.com>
Acked-by: Kevin Wolf <kwolf@redhat.com>
Acked-by: Gleb Natapov <gleb@redhat.com>
---
 qemu/hw/extboot.c |   35 +++++++++++++++++------------------
 1 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/qemu/hw/extboot.c b/qemu/hw/extboot.c
index 056fb59..c601353 100644
--- a/qemu/hw/extboot.c
+++ b/qemu/hw/extboot.c
@@ -77,19 +77,19 @@ static void extboot_write_cmd(void *opaque, uint32_t addr, uint32_t value)
     BlockDriverState *bs = opaque;
     int cylinders, heads, sectors, err;
     int64_t nb_sectors;
-
-    get_translated_chs(bs, &cylinders, &heads, &sectors);
+    target_phys_addr_t pa;
+    int blen;
+    void *buf = NULL;
 
     if (cmd->type == 0x01 || cmd->type == 0x02) {
-	target_ulong pa = cmd->xfer.segment * 16 + cmd->xfer.segment;
-
-	/* possible buffer overflow */
-	if ((pa + cmd->xfer.nb_sectors * 512) > phys_ram_size)
-	    return;
+	pa = cmd->xfer.segment * 16 + cmd->xfer.offset;
+        blen = cmd->xfer.nb_sectors * 512;
+        buf = qemu_memalign(512, blen);
     }
 
     switch (cmd->type) {
     case 0x00:
+        get_translated_chs(bs, &cylinders, &heads, &sectors);
 	bdrv_get_geometry(bs, &nb_sectors);
 	cmd->query_geometry.cylinders = cylinders;
 	cmd->query_geometry.heads = heads;
@@ -98,22 +98,25 @@ static void extboot_write_cmd(void *opaque, uint32_t addr, uint32_t value)
 	cpu_physical_memory_set_dirty((value & 0xFFFF) << 4);
 	break;
     case 0x01:
-	err = bdrv_read(bs, cmd->xfer.sector, phys_ram_base +
-			cmd->xfer.segment * 16 + cmd->xfer.offset,
-			cmd->xfer.nb_sectors);
+	err = bdrv_read(bs, cmd->xfer.sector, buf, cmd->xfer.nb_sectors);
 	if (err)
 	    printf("Read failed\n");
+
+        cpu_physical_memory_write(pa, buf, blen);
+
 	break;
     case 0x02:
-	err = bdrv_write(bs, cmd->xfer.sector, phys_ram_base +
-			 cmd->xfer.segment * 16 + cmd->xfer.offset,
-			 cmd->xfer.nb_sectors);
+        cpu_physical_memory_read(pa, buf, blen);
+
+	err = bdrv_write(bs, cmd->xfer.sector, buf, cmd->xfer.nb_sectors);
 	if (err)
 	    printf("Write failed\n");
 
-	cpu_physical_memory_set_dirty(cmd->xfer.segment * 16 + cmd->xfer.offset);
 	break;
     }
+
+    if (buf)
+        qemu_free(buf);
 }
 
 void extboot_init(BlockDriverState *bs, int cmd)
@@ -121,10 +124,6 @@ void extboot_init(BlockDriverState *bs, int cmd)
     int *pcmd;
 
     pcmd = qemu_mallocz(sizeof(int));
-    if (!pcmd) {
-	fprintf(stderr, "Error allocating memory\n");
-	exit(1);
-    }
 
     *pcmd = cmd;
     register_ioport_read(0x404, 1, 1, extboot_read, pcmd);
-- 
1.6.3.rc4.29.g8146