Patchwork [RESEND] exec: optimize lduw_phys and stw_phys

login
register
mail settings
Submitter Bernhard Kohl
Date May 6, 2010, 1:55 p.m.
Message ID <4BE2CA41.8060701@nsn.com>
Download mbox | patch
Permalink /patch/51851/
State New
Headers show

Comments

Bernhard Kohl - May 6, 2010, 1:55 p.m.
Implementation of the optimized code for these two functions.

This is necessary for virtio which reads and writes VirtQueue index
fields using these functions. The assumption is that this are atomic
operations, which is not the case, if the memcpy() function which is
used in the non optimized code does single byte copying. This happens
for example with an older WindRiver glibc.

Signed-off-by: Bernhard Kohl <bernhard.kohl@nsn.com>
---
RESEND: This message did not reach the gmane archive and maybe others.
---
  exec.c |   67 
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
  1 files changed, 60 insertions(+), 7 deletions(-)
Bernhard Kohl - May 9, 2010, 12:36 p.m.
Am 06.05.2010 15:55, schrieb Bernhard Kohl:
> Implementation of the optimized code for these two functions.
>
> This is necessary for virtio which reads and writes VirtQueue index
> fields using these functions. The assumption is that this are atomic
> operations, which is not the case, if the memcpy() function which is
> used in the non optimized code does single byte copying. This happens
> for example with an older WindRiver glibc.
>
> Signed-off-by: Bernhard Kohl <bernhard.kohl@nsn.com>

Hi,

the same patch posted by Michael S. Tsirkin was commited one hour
after I sent this message.

topic: [PATCH] qemu: address todo comment in exec.c
commit: 733f0b02c80c3a7106d8327a83948ab68db10ea7

So this issue is closed.

Bernhard

Patch

diff --git a/exec.c b/exec.c
index 14d1fd7..fb40398 100644
--- a/exec.c
+++ b/exec.c
@@ -3739,12 +3739,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;
+    uint32_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
@@ -3861,11 +3885,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 */
+            phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
+                (0xff & ~CODE_DIRTY_FLAG);
+        }
+    }
  }

  /* XXX: optimize */