qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH] 64 bit I/O support v7


From: Robert Reif
Subject: [Qemu-devel] [PATCH] 64 bit I/O support v7
Date: Tue, 21 Apr 2009 07:42:01 -0400
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.21) Gecko/20090303 SeaMonkey/1.1.15 (Ubuntu-1.1.15+nobinonly-0ubuntu2)

This patch is a rebase on current svn of my previous patch.

This patch adds support for 64 bit I/O by essentially replacing an
array of 4 function pointers with a structure containing 4 function
pointers. The current array contains 4 pointers, one for 8, 16 and 32
bit function pointers which really support only 32 bits and a
forth pointer which is unused but I assume is a place holder for a
64 bit function pointer.  The current trick of passing 8, 16 or 32 bits
in a 32 bit variable doesn't extend to passing 64 bits in a 32 bit
bit variable and creating a 64 bit function would require casts to
allow being saved in the array so a sutrcture is used that can take
different function pointers.

Here are the relevant parts of the patch:

+typedef void CPUWriteMemoryFunc64(void *opaque, target_phys_addr_t addr, uint64_t value); +typedef uint64_t CPUReadMemoryFunc64(void *opaque, target_phys_addr_t addr);
+
+typedef struct CPUWriteMemoryFuncs {
+    CPUWriteMemoryFunc   *b;
+    CPUWriteMemoryFunc   *w;
+    CPUWriteMemoryFunc   *l;
+    CPUWriteMemoryFunc64 *q;
+} CPUWriteMemoryFuncs;
+
+typedef struct CPUReadMemoryFuncs {
+    CPUReadMemoryFunc   *b;
+    CPUReadMemoryFunc   *w;
+    CPUReadMemoryFunc   *l;
+    CPUReadMemoryFunc64 *q;
+} CPUReadMemoryFuncs;

-extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
-extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
+extern CPUWriteMemoryFuncs io_mem_write[IO_MEM_NB_ENTRIES];
+extern CPUReadMemoryFuncs io_mem_read[IO_MEM_NB_ENTRIES];

The rest of the patch just does the array to structure conversion and
adds the 64 bit functions.

The old array function call is supported so no existing drivers need
to be modified.  They can continue to do 2 32 bit accesses because 2
helper functions have been added to break up the accesses automatically.
However, the helper functions should only be used until all drivers are
converted to use the structure and then can be removed along
with the old array functions api.  The replacement of the arrays with
structures in the drivers is very straightforward for drivers that don't
do 64 bit I/O and the few that do can be cleaned up to remove the
work arounds for the lack of true 64 bit I/O by their maintainers.

Signed-off-by: Robert Reif <address@hidden>
Index: softmmu_template.h
===================================================================
--- softmmu_template.h  (revision 7190)
+++ softmmu_template.h  (working copy)
@@ -65,17 +65,7 @@
     }
 
     env->mem_io_vaddr = addr;
-#if SHIFT <= 2
-    res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr);
-#else
-#ifdef TARGET_WORDS_BIGENDIAN
-    res = (uint64_t)io_mem_read[index][2](io_mem_opaque[index], physaddr) << 
32;
-    res |= io_mem_read[index][2](io_mem_opaque[index], physaddr + 4);
-#else
-    res = io_mem_read[index][2](io_mem_opaque[index], physaddr);
-    res |= (uint64_t)io_mem_read[index][2](io_mem_opaque[index], physaddr + 4) 
<< 32;
-#endif
-#endif /* SHIFT > 2 */
+    res = io_mem_read[index].SUFFIX(io_mem_opaque[index], physaddr);
 #ifdef CONFIG_KQEMU
     env->last_io_time = cpu_get_time_fast();
 #endif
@@ -210,17 +200,7 @@
 
     env->mem_io_vaddr = addr;
     env->mem_io_pc = (unsigned long)retaddr;
-#if SHIFT <= 2
-    io_mem_write[index][SHIFT](io_mem_opaque[index], physaddr, val);
-#else
-#ifdef TARGET_WORDS_BIGENDIAN
-    io_mem_write[index][2](io_mem_opaque[index], physaddr, val >> 32);
-    io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val);
-#else
-    io_mem_write[index][2](io_mem_opaque[index], physaddr, val);
-    io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val >> 32);
-#endif
-#endif /* SHIFT > 2 */
+    io_mem_write[index].SUFFIX(io_mem_opaque[index], physaddr, val);
 #ifdef CONFIG_KQEMU
     env->last_io_time = cpu_get_time_fast();
 #endif
Index: exec.c
===================================================================
--- exec.c      (revision 7190)
+++ exec.c      (working copy)
@@ -47,6 +47,7 @@
 //#define DEBUG_FLUSH
 //#define DEBUG_TLB
 //#define DEBUG_UNASSIGNED
+//#define DEBUG_MMIO64
 
 /* make various TB consistency checks */
 //#define DEBUG_TB_CHECK
@@ -182,8 +183,8 @@
 static void io_mem_init(void);
 
 /* io memory support */
-CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
-CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
+CPUWriteMemoryFuncs io_mem_write[IO_MEM_NB_ENTRIES];
+CPUReadMemoryFuncs io_mem_read[IO_MEM_NB_ENTRIES];
 void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 static char io_mem_used[IO_MEM_NB_ENTRIES];
 static int io_mem_watch;
@@ -2588,6 +2589,17 @@
     return 0;
 }
 
+static uint64_t unassigned_mem_readq(void *opaque, target_phys_addr_t addr)
+{
+#ifdef DEBUG_UNASSIGNED
+    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
+#endif
+#if defined(TARGET_SPARC)
+    do_unassigned_access(addr, 0, 0, 0, 8);
+#endif
+    return 0;
+}
+
 static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, 
uint32_t val)
 {
 #ifdef DEBUG_UNASSIGNED
@@ -2618,16 +2630,28 @@
 #endif
 }
 
-static CPUReadMemoryFunc *unassigned_mem_read[3] = {
+static void unassigned_mem_writeq(void *opaque, target_phys_addr_t addr, 
uint64_t val)
+{
+#ifdef DEBUG_UNASSIGNED
+    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%016llx\n", addr, val);
+#endif
+#if defined(TARGET_SPARC)
+    do_unassigned_access(addr, 1, 0, 0, 8);
+#endif
+}
+
+static CPUReadMemoryFuncs unassigned_mem_read = {
     unassigned_mem_readb,
     unassigned_mem_readw,
     unassigned_mem_readl,
+    unassigned_mem_readq,
 };
 
-static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
+static CPUWriteMemoryFuncs unassigned_mem_write = {
     unassigned_mem_writeb,
     unassigned_mem_writew,
     unassigned_mem_writel,
+    unassigned_mem_writeq,
 };
 
 static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
@@ -2705,16 +2729,43 @@
         tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
 }
 
-static CPUReadMemoryFunc *error_mem_read[3] = {
+static void notdirty_mem_writeq(void *opaque, target_phys_addr_t ram_addr,
+                                uint64_t val)
+{
+    int dirty_flags;
+    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
+    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
+#if !defined(CONFIG_USER_ONLY)
+        tb_invalidate_phys_page_fast(ram_addr, 8);
+        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
+#endif
+    }
+    stq_p(qemu_get_ram_ptr(ram_addr), val);
+#ifdef USE_KQEMU
+    if (cpu_single_env->kqemu_enabled &&
+        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
+        kqemu_modify_page(cpu_single_env, ram_addr);
+#endif
+    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
+    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
+    /* we remove the notdirty callback only if the code has been
+       flushed */
+    if (dirty_flags == 0xff)
+        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
+}
+
+static CPUReadMemoryFuncs error_mem_read = {
     NULL, /* never used */
     NULL, /* never used */
     NULL, /* never used */
+    NULL, /* never used */
 };
 
-static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
+static CPUWriteMemoryFuncs notdirty_mem_write = {
     notdirty_mem_writeb,
     notdirty_mem_writew,
     notdirty_mem_writel,
+    notdirty_mem_writeq,
 };
 
 /* Generate a debug exception if a watchpoint has been hit.  */
@@ -2783,6 +2834,12 @@
     return ldl_phys(addr);
 }
 
+static uint64_t watch_mem_readq(void *opaque, target_phys_addr_t addr)
+{
+    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x7, BP_MEM_READ);
+    return ldq_phys(addr);
+}
+
 static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
                              uint32_t val)
 {
@@ -2804,16 +2861,25 @@
     stl_phys(addr, val);
 }
 
-static CPUReadMemoryFunc *watch_mem_read[3] = {
+static void watch_mem_writeq(void *opaque, target_phys_addr_t addr,
+                             uint64_t val)
+{
+    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x7, BP_MEM_WRITE);
+    stq_phys(addr, val);
+}
+
+static CPUReadMemoryFuncs watch_mem_read = {
     watch_mem_readb,
     watch_mem_readw,
     watch_mem_readl,
+    watch_mem_readq,
 };
 
-static CPUWriteMemoryFunc *watch_mem_write[3] = {
+static CPUWriteMemoryFuncs watch_mem_write = {
     watch_mem_writeb,
     watch_mem_writew,
     watch_mem_writel,
+    watch_mem_writeq,
 };
 
 static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t 
addr,
@@ -2902,23 +2968,54 @@
     subpage_writelen(opaque, addr, value, 2);
 }
 
-static CPUReadMemoryFunc *subpage_read[] = {
-    &subpage_readb,
-    &subpage_readw,
-    &subpage_readl,
+static uint64_t subpage_readq (void *opaque, target_phys_addr_t addr)
+{
+    subpage_t *mmio = (subpage_t *)opaque;
+    unsigned int idx;
+
+    idx = SUBPAGE_IDX(addr);
+#if defined(DEBUG_SUBPAGE)
+    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
+           mmio, 3, addr, idx);
+#endif
+    return 
((CPUReadMemoryFunc64*)(*mmio->mem_read[idx][3]))(mmio->opaque[idx][0][3],
+                                       addr + mmio->region_offset[idx][0][3]);
+}
+
+static void subpage_writeq (void *opaque,
+                         target_phys_addr_t addr, uint64_t value)
+{
+    subpage_t *mmio = (subpage_t *)opaque;
+    unsigned int idx;
+
+    idx = SUBPAGE_IDX(addr);
+#if defined(DEBUG_SUBPAGE)
+    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value 
%016llx\n", __func__,
+           mmio, 3, addr, idx, value);
+#endif
+    
((CPUWriteMemoryFunc64*)(*mmio->mem_write[idx][3]))(mmio->opaque[idx][1][3],
+                                  addr + mmio->region_offset[idx][1][3],
+                                  value);
+}
+
+static CPUReadMemoryFuncs subpage_read = {
+    subpage_readb,
+    subpage_readw,
+    subpage_readl,
+    subpage_readq,
 };
 
-static CPUWriteMemoryFunc *subpage_write[] = {
-    &subpage_writeb,
-    &subpage_writew,
-    &subpage_writel,
+static CPUWriteMemoryFuncs subpage_write = {
+    subpage_writeb,
+    subpage_writew,
+    subpage_writel,
+    subpage_writeq,
 };
 
 static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
                              ram_addr_t memory, ram_addr_t region_offset)
 {
     int idx, eidx;
-    unsigned int i;
 
     if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
         return -1;
@@ -2930,18 +3027,46 @@
 #endif
     memory >>= IO_MEM_SHIFT;
     for (; idx <= eidx; idx++) {
-        for (i = 0; i < 4; i++) {
-            if (io_mem_read[memory][i]) {
-                mmio->mem_read[idx][i] = &io_mem_read[memory][i];
-                mmio->opaque[idx][0][i] = io_mem_opaque[memory];
-                mmio->region_offset[idx][0][i] = region_offset;
-            }
-            if (io_mem_write[memory][i]) {
-                mmio->mem_write[idx][i] = &io_mem_write[memory][i];
-                mmio->opaque[idx][1][i] = io_mem_opaque[memory];
-                mmio->region_offset[idx][1][i] = region_offset;
-            }
+        if (io_mem_read[memory].b) {
+            mmio->mem_read[idx][0] = &io_mem_read[memory].b;
+            mmio->opaque[idx][0][0] = io_mem_opaque[memory];
+            mmio->region_offset[idx][0][0] = region_offset;
         }
+        if (io_mem_write[memory].b) {
+            mmio->mem_write[idx][0] = &io_mem_write[memory].b;
+            mmio->opaque[idx][1][0] = io_mem_opaque[memory];
+            mmio->region_offset[idx][1][0] = region_offset;
+        }
+        if (io_mem_read[memory].w) {
+            mmio->mem_read[idx][1] = &io_mem_read[memory].w;
+            mmio->opaque[idx][0][1] = io_mem_opaque[memory];
+            mmio->region_offset[idx][0][1] = region_offset;
+        }
+        if (io_mem_write[memory].w) {
+            mmio->mem_write[idx][1] = &io_mem_write[memory].w;
+            mmio->opaque[idx][1][1] = io_mem_opaque[memory];
+            mmio->region_offset[idx][1][1] = region_offset;
+        }
+        if (io_mem_read[memory].l) {
+            mmio->mem_read[idx][2] = &io_mem_read[memory].l;
+            mmio->opaque[idx][0][2] = io_mem_opaque[memory];
+            mmio->region_offset[idx][0][2] = region_offset;
+        }
+        if (io_mem_write[memory].l) {
+            mmio->mem_write[idx][2] = &io_mem_write[memory].l;
+            mmio->opaque[idx][1][2] = io_mem_opaque[memory];
+            mmio->region_offset[idx][1][2] = region_offset;
+        }
+        if (io_mem_read[memory].q) {
+            mmio->mem_read[idx][3] = 
(CPUReadMemoryFunc**)&io_mem_read[memory].q;
+            mmio->opaque[idx][0][3] = io_mem_opaque[memory];
+            mmio->region_offset[idx][0][3] = region_offset;
+        }
+        if (io_mem_write[memory].q) {
+            mmio->mem_write[idx][3] = 
(CPUWriteMemoryFunc**)&io_mem_write[memory].q;
+            mmio->opaque[idx][1][3] = io_mem_opaque[memory];
+            mmio->region_offset[idx][1][3] = region_offset;
+        }
     }
 
     return 0;
@@ -2956,7 +3081,7 @@
     mmio = qemu_mallocz(sizeof(subpage_t));
 
     mmio->base = base;
-    subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, 
mmio);
+    subpage_memory = cpu_register_io_memory64(0, &subpage_read, 
&subpage_write, mmio);
 #if defined(DEBUG_SUBPAGE)
     printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
            mmio, base, TARGET_PAGE_SIZE, subpage_memory);
@@ -2985,14 +3110,14 @@
 {
     int i;
 
-    cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, 
unassigned_mem_write, NULL);
-    cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, 
unassigned_mem_read, unassigned_mem_write, NULL);
-    cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, 
notdirty_mem_write, NULL);
+    cpu_register_io_memory64(IO_MEM_ROM >> IO_MEM_SHIFT, &error_mem_read, 
&unassigned_mem_write, NULL);
+    cpu_register_io_memory64(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, 
&unassigned_mem_read, &unassigned_mem_write, NULL);
+    cpu_register_io_memory64(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, &error_mem_read, 
&notdirty_mem_write, NULL);
     for (i=0; i<5; i++)
         io_mem_used[i] = 1;
 
-    io_mem_watch = cpu_register_io_memory(0, watch_mem_read,
-                                          watch_mem_write, NULL);
+    io_mem_watch = cpu_register_io_memory64(0, &watch_mem_read,
+                                            &watch_mem_write, NULL);
 #ifdef CONFIG_KQEMU
     if (kqemu_phys_ram_base) {
         /* alloc dirty bits array */
@@ -3002,6 +3127,58 @@
 #endif
 }
 
+/* mem_readq and mem_writeq are helper functions that are
+   used to emulate 64 bit accesses for hardware devices
+   that are doing 64 bit mmio but have not been converted
+   to use cpu_register_io_memory64.  These functions should
+   only be used until all hardware devices are converted to
+   the new api and then removed because they are not efficient.  */
+static void mem_writeq(void *opaque, target_phys_addr_t addr, uint64_t val)
+{
+    int i;
+
+    for (i = 0; i < IO_MEM_NB_ENTRIES; i++) {
+        if (io_mem_opaque[i] == opaque && io_mem_used[i]) {
+#ifdef TARGET_WORDS_BIGENDIAN
+            io_mem_write[i].l(opaque, addr, val >> 32);
+            io_mem_write[i].l(opaque, addr + 4, val);
+#else
+            io_mem_write[i].l(opaque, addr, val);
+            io_mem_write[i].l(opaque, addr + 4, val >> 32);
+#endif
+#ifdef DEBUG_MMIO64
+            printf("FIXME: emulating 64 bit I/O using 32 bit I/O.\n");
+#endif
+            return;
+        }
+    }
+}
+
+static uint64_t mem_readq(void *opaque, target_phys_addr_t addr)
+{
+    int i;
+
+    for (i = 0; i < IO_MEM_NB_ENTRIES; i++) {
+        if (io_mem_opaque[i] == opaque && io_mem_used[i]) {
+            uint64_t val;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+            val = (uint64_t)io_mem_read[i].l(opaque, addr) << 32;
+            val |= io_mem_read[i].l(opaque, addr + 4);
+#else
+            val = io_mem_read[i].l(opaque, addr);
+            val |= (uint64_t)io_mem_read[i].l(opaque, addr + 4) << 32;
+#endif
+#ifdef DEBUG_MMIO64
+            printf("FIXME: emulating 64 bit I/O using 32 bit I/O.\n");
+#endif
+            return val;
+        }
+    }
+
+    return 0;
+}
+
 /* mem_read and mem_write are arrays of functions containing the
    function to access byte (index 0), word (index 1) and dword (index
    2). Functions can be omitted with a NULL function pointer. The
@@ -3015,8 +3192,38 @@
                            CPUWriteMemoryFunc **mem_write,
                            void *opaque)
 {
-    int i, subwidth = 0;
+    if (io_index <= 0) {
+        io_index = get_free_io_mem_idx();
+        if (io_index == -1)
+            return io_index;
+    } else {
+        if (io_index >= IO_MEM_NB_ENTRIES)
+            return -1;
+    }
 
+    io_mem_read[io_index].b = mem_read[0];
+    io_mem_write[io_index].b = mem_write[0];
+
+    io_mem_read[io_index].w = mem_read[1];
+    io_mem_write[io_index].w = mem_write[1];
+
+    io_mem_read[io_index].l = mem_read[2];
+    io_mem_write[io_index].l = mem_write[2];
+
+    io_mem_read[io_index].q = mem_readq;
+    io_mem_write[io_index].q = mem_writeq;
+
+    io_mem_opaque[io_index] = opaque;
+    return (io_index << IO_MEM_SHIFT) | IO_MEM_SUBWIDTH;
+}
+
+int cpu_register_io_memory64(int io_index,
+                             CPUReadMemoryFuncs *mem_read,
+                             CPUWriteMemoryFuncs *mem_write,
+                             void *opaque)
+{
+    int subwidth = 0;
+
     if (io_index <= 0) {
         io_index = get_free_io_mem_idx();
         if (io_index == -1)
@@ -3026,37 +3233,36 @@
             return -1;
     }
 
-    for(i = 0;i < 3; i++) {
-        if (!mem_read[i] || !mem_write[i])
-            subwidth = IO_MEM_SUBWIDTH;
-        io_mem_read[io_index][i] = mem_read[i];
-        io_mem_write[io_index][i] = mem_write[i];
-    }
+    if (!mem_read->b || !mem_write->b ||
+        !mem_read->w || !mem_write->w ||
+        !mem_read->l || !mem_write->l ||
+        !mem_read->q || !mem_write->q)
+        subwidth = IO_MEM_SUBWIDTH;
+    
+    io_mem_read[io_index] = *mem_read;
+    io_mem_write[io_index] = *mem_write;
     io_mem_opaque[io_index] = opaque;
     return (io_index << IO_MEM_SHIFT) | subwidth;
 }
 
 void cpu_unregister_io_memory(int io_table_address)
 {
-    int i;
     int io_index = io_table_address >> IO_MEM_SHIFT;
 
-    for (i=0;i < 3; i++) {
-        io_mem_read[io_index][i] = unassigned_mem_read[i];
-        io_mem_write[io_index][i] = unassigned_mem_write[i];
-    }
+    io_mem_read[io_index] = unassigned_mem_read;
+    io_mem_write[io_index] = unassigned_mem_write;
     io_mem_opaque[io_index] = NULL;
     io_mem_used[io_index] = 0;
 }
 
 CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
 {
-    return io_mem_write[io_index >> IO_MEM_SHIFT];
+    return &io_mem_write[io_index >> IO_MEM_SHIFT].b;
 }
 
 CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
 {
-    return io_mem_read[io_index >> IO_MEM_SHIFT];
+    return &io_mem_read[io_index >> IO_MEM_SHIFT].b;
 }
 
 #endif /* !defined(CONFIG_USER_ONLY) */
@@ -3134,20 +3340,25 @@
                     addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
                 /* XXX: could force cpu_single_env to NULL to avoid
                    potential bugs */
-                if (l >= 4 && ((addr1 & 3) == 0)) {
+                if (l >= 8 && ((addr1 & 7) == 0)) {
+                    /* 64 bit write access */
+                    uint64_t val64 = ldq_p(buf);
+                    io_mem_write[io_index].q(io_mem_opaque[io_index], addr1, 
val64);
+                    l = 8;
+                } else 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], addr1, 
val);
+                    io_mem_write[io_index].l(io_mem_opaque[io_index], addr1, 
val);
                     l = 4;
                 } 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], addr1, 
val);
+                    io_mem_write[io_index].w(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], addr1, 
val);
+                    io_mem_write[io_index].b(io_mem_opaque[io_index], addr1, 
val);
                     l = 1;
                 }
             } else {
@@ -3172,19 +3383,24 @@
                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
                 if (p)
                     addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
-                if (l >= 4 && ((addr1 & 3) == 0)) {
+                if (l >= 8 && ((addr1 & 7) == 0)) {
+                    /* 64 bit read access */
+                    uint64_t val64 = 
io_mem_read[io_index].q(io_mem_opaque[io_index], addr1);
+                    stq_p(buf, val64);
+                    l = 8;
+                } else if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit read access */
-                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], 
addr1);
+                    val = io_mem_read[io_index].l(io_mem_opaque[io_index], 
addr1);
                     stl_p(buf, val);
                     l = 4;
                 } else if (l >= 2 && ((addr1 & 1) == 0)) {
                     /* 16 bit read access */
-                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], 
addr1);
+                    val = io_mem_read[io_index].w(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], 
addr1);
+                    val = io_mem_read[io_index].b(io_mem_opaque[io_index], 
addr1);
                     stb_p(buf, val);
                     l = 1;
                 }
@@ -3405,7 +3621,7 @@
         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][2](io_mem_opaque[io_index], addr);
+        val = io_mem_read[io_index].l(io_mem_opaque[io_index], addr);
     } else {
         /* RAM case */
         ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
@@ -3437,13 +3653,7 @@
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
-#ifdef TARGET_WORDS_BIGENDIAN
-        val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], 
addr) << 32;
-        val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
-#else
-        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
-        val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], 
addr + 4) << 32;
-#endif
+        val = io_mem_read[io_index].q(io_mem_opaque[io_index], addr);
     } else {
         /* RAM case */
         ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
@@ -3490,7 +3700,7 @@
         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][2](io_mem_opaque[io_index], addr, val);
+        io_mem_write[io_index].l(io_mem_opaque[io_index], addr, val);
     } else {
         unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & 
~TARGET_PAGE_MASK);
         ptr = qemu_get_ram_ptr(addr1);
@@ -3526,13 +3736,7 @@
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
-#ifdef TARGET_WORDS_BIGENDIAN
-        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
-        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
-#else
-        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
-        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 
32);
-#endif
+        io_mem_write[io_index].q(io_mem_opaque[io_index], addr, val);
     } else {
         ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
             (addr & ~TARGET_PAGE_MASK);
@@ -3559,7 +3763,7 @@
         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][2](io_mem_opaque[io_index], addr, val);
+        io_mem_write[io_index].l(io_mem_opaque[io_index], addr, val);
     } else {
         unsigned long addr1;
         addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
Index: exec-all.h
===================================================================
--- exec-all.h  (revision 7190)
+++ exec-all.h  (working copy)
@@ -265,8 +265,8 @@
 
 TranslationBlock *tb_find_pc(unsigned long pc_ptr);
 
-extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
-extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
+extern CPUWriteMemoryFuncs io_mem_write[IO_MEM_NB_ENTRIES];
+extern CPUReadMemoryFuncs io_mem_read[IO_MEM_NB_ENTRIES];
 extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 
 #include "qemu-lock.h"
Index: cpu-all.h
===================================================================
--- cpu-all.h   (revision 7190)
+++ cpu-all.h   (working copy)
@@ -891,6 +891,23 @@
 typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, 
uint32_t value);
 typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
 
+typedef void CPUWriteMemoryFunc64(void *opaque, target_phys_addr_t addr, 
uint64_t value);
+typedef uint64_t CPUReadMemoryFunc64(void *opaque, target_phys_addr_t addr);
+
+typedef struct CPUWriteMemoryFuncs {
+    CPUWriteMemoryFunc   *b;
+    CPUWriteMemoryFunc   *w;
+    CPUWriteMemoryFunc   *l;
+    CPUWriteMemoryFunc64 *q;
+} CPUWriteMemoryFuncs;
+
+typedef struct CPUReadMemoryFuncs {
+    CPUReadMemoryFunc   *b;
+    CPUReadMemoryFunc   *w;
+    CPUReadMemoryFunc   *l;
+    CPUReadMemoryFunc64 *q;
+} CPUReadMemoryFuncs;
+
 void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
                                          ram_addr_t size,
                                          ram_addr_t phys_offset,
@@ -914,6 +931,10 @@
                            CPUReadMemoryFunc **mem_read,
                            CPUWriteMemoryFunc **mem_write,
                            void *opaque);
+int cpu_register_io_memory64(int io_index,
+                             CPUReadMemoryFuncs *mem_read,
+                             CPUWriteMemoryFuncs *mem_write,
+                             void *opaque);
 void cpu_unregister_io_memory(int table_address);
 CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
 CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);

reply via email to

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