Skip to content

Commit

Permalink
qemu: address todo comment in exec.c
Browse files Browse the repository at this point in the history
exec.c has a comment 'XXX: optimize' for lduw_phys/stw_phys,
so let's do it, along the lines of stl_phys.

The reason to address 16 bit accesses specifically is that virtio relies
on these accesses to be done atomically, using memset as we do now
breaks this assumption, which is reported to cause qemu with kvm
to read wrong index values under stress.

https://bugzilla.redhat.com/show_bug.cgi?id=525323

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
  • Loading branch information
mstsirkin authored and aurel32 committed May 6, 2010
1 parent 3e0650a commit 733f0b0
Showing 1 changed file with 60 additions and 7 deletions.
67 changes: 60 additions & 7 deletions exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -3715,12 +3715,36 @@ uint32_t ldub_phys(target_phys_addr_t addr)
return val;
}

/* XXX: optimize */
/* warning: addr must be aligned */
uint32_t lduw_phys(target_phys_addr_t addr)
{
uint16_t val;
cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
return tswap16(val);
int io_index;
uint8_t *ptr;
uint64_t val;
unsigned long pd;
PhysPageDesc *p;

p = phys_page_find(addr >> TARGET_PAGE_BITS);
if (!p) {
pd = IO_MEM_UNASSIGNED;
} else {
pd = p->phys_offset;
}

if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
!(pd & IO_MEM_ROMD)) {
/* I/O case */
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
if (p)
addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
} else {
/* RAM case */
ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
(addr & ~TARGET_PAGE_MASK);
val = lduw_p(ptr);
}
return val;
}

/* warning: addr must be aligned. The ram page is not masked as dirty
Expand Down Expand Up @@ -3837,11 +3861,40 @@ void stb_phys(target_phys_addr_t addr, uint32_t val)
cpu_physical_memory_write(addr, &v, 1);
}

/* XXX: optimize */
/* warning: addr must be aligned */
void stw_phys(target_phys_addr_t addr, uint32_t val)
{
uint16_t v = tswap16(val);
cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
int io_index;
uint8_t *ptr;
unsigned long pd;
PhysPageDesc *p;

p = phys_page_find(addr >> TARGET_PAGE_BITS);
if (!p) {
pd = IO_MEM_UNASSIGNED;
} else {
pd = p->phys_offset;
}

if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
if (p)
addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
} else {
unsigned long addr1;
addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
/* RAM case */
ptr = qemu_get_ram_ptr(addr1);
stw_p(ptr, val);
if (!cpu_physical_memory_is_dirty(addr1)) {
/* invalidate code */
tb_invalidate_phys_page_range(addr1, addr1 + 2, 0);
/* set dirty bit */
cpu_physical_memory_set_dirty_flags(addr1,
(0xff & ~CODE_DIRTY_FLAG));
}
}
}

/* XXX: optimize */
Expand Down

0 comments on commit 733f0b0

Please sign in to comment.