[Top][All Lists]
[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;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [6628] Fix cpu_physical_memory_rw() for 64-bit I/O accesses,
Aurelien Jarno <=