qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [6628] Fix cpu_physical_memory_rw() for 64-bit I/O accesses


From: Aurelien Jarno
Subject: [Qemu-devel] [6628] Fix cpu_physical_memory_rw() for 64-bit I/O accesses
Date: Wed, 18 Feb 2009 21:37:18 +0000

Revision: 6628
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6628
Author:   aurel32
Date:     2009-02-18 21:37:17 +0000 (Wed, 18 Feb 2009)

Log Message:
-----------
Fix cpu_physical_memory_rw() for 64-bit I/O accesses

KVM uses cpu_physical_memory_rw() to access the I/O devices. When a
read or write with a length of 8-byte is requested, it is split into 2
4-byte accesses.

This has been broken in revision 5849. After this revision, only the
first 4 bytes are actually read/write to the device, as the target
address is changed, so on the next iteration of the loop the next 4
bytes are actually read/written elsewhere (in the RAM for the graphic
card).

This patch fixes screen corruption (and most probably data corruption)
with FreeBSD/amd64. Bug #2556746 in KVM bugzilla.

Signed-off-by: Aurelien Jarno <address@hidden>

Revision Links:
--------------
    http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5849

Ticket Links:
:-----------
    http://savannah.gnu.org/bugs/?2556746

Modified Paths:
--------------
    trunk/exec.c

Modified: trunk/exec.c
===================================================================
--- trunk/exec.c        2009-02-18 20:44:04 UTC (rev 6627)
+++ trunk/exec.c        2009-02-18 21:37:17 UTC (rev 6628)
@@ -2955,25 +2955,26 @@
 
         if (is_write) {
             if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+                target_phys_addr_t addr1 = addr;
                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
                 if (p)
-                    addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
                 /* XXX: could force cpu_single_env to NULL to avoid
                    potential bugs */
-                if (l >= 4 && ((addr & 3) == 0)) {
+                if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit write access */
                     val = ldl_p(buf);
-                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr, 
val);
+                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, 
val);
                     l = 4;
-                } else if (l >= 2 && ((addr & 1) == 0)) {
+                } else if (l >= 2 && ((addr1 & 1) == 0)) {
                     /* 16 bit write access */
                     val = lduw_p(buf);
-                    io_mem_write[io_index][1](io_mem_opaque[io_index], addr, 
val);
+                    io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, 
val);
                     l = 2;
                 } else {
                     /* 8 bit write access */
                     val = ldub_p(buf);
-                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr, 
val);
+                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, 
val);
                     l = 1;
                 }
             } else {
@@ -2993,23 +2994,24 @@
         } else {
             if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
                 !(pd & IO_MEM_ROMD)) {
+                target_phys_addr_t addr1 = addr;
                 /* I/O case */
                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
                 if (p)
-                    addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
-                if (l >= 4 && ((addr & 3) == 0)) {
+                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+                if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit read access */
-                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], 
addr);
+                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], 
addr1);
                     stl_p(buf, val);
                     l = 4;
-                } else if (l >= 2 && ((addr & 1) == 0)) {
+                } else if (l >= 2 && ((addr1 & 1) == 0)) {
                     /* 16 bit read access */
-                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], 
addr);
+                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], 
addr1);
                     stw_p(buf, val);
                     l = 2;
                 } else {
                     /* 8 bit read access */
-                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], 
addr);
+                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], 
addr1);
                     stb_p(buf, val);
                     l = 1;
                 }






reply via email to

[Prev in Thread] Current Thread [Next in Thread]