qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH] 64 bit I/O v3


From: Robert Reif
Subject: Re: [Qemu-devel] [PATCH] 64 bit I/O v3
Date: Thu, 26 Feb 2009 20:24:30 -0500
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.19) Gecko/20081204 SeaMonkey/1.1.14

Blue Swirl wrote:
I think for 64 bit accesses the default should be emulation using two
32 bit accesses instead of NULL (unassigned).


This version adds emulated 64 bit i/o using 32 bit i/o for hardware devices that are not converted over to the new api.
Index: softmmu_template.h
===================================================================
--- softmmu_template.h  (revision 6643)
+++ 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 USE_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 USE_KQEMU
     env->last_io_time = cpu_get_time_fast();
 #endif
Index: exec.c
===================================================================
--- exec.c      (revision 6643)
+++ exec.c      (working copy)
@@ -176,8 +176,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];
 char io_mem_used[IO_MEM_NB_ENTRIES];
 static int io_mem_watch;
@@ -2424,6 +2424,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
@@ -2454,16 +2465,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%x\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,
@@ -2541,16 +2564,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(phys_ram_base + 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.  */
@@ -2619,6 +2669,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)
 {
@@ -2640,16 +2696,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,
@@ -2738,23 +2803,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 
%08x\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;
@@ -2766,18 +2862,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;
@@ -2792,7 +2916,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);
@@ -2821,19 +2945,65 @@
 {
     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);
     /* alloc dirty bits array */
     phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
     memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
 }
 
+/* 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
+            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
+            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
@@ -2847,8 +3017,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)
@@ -2858,37 +3058,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) */
@@ -2966,20 +3165,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 {
@@ -3004,19 +3208,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;
                 }
@@ -3237,7 +3446,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 = phys_ram_base + (pd & TARGET_PAGE_MASK) +
@@ -3269,13 +3478,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 = phys_ram_base + (pd & TARGET_PAGE_MASK) +
@@ -3322,7 +3525,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 = phys_ram_base + addr1;
@@ -3358,13 +3561,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 = phys_ram_base + (pd & TARGET_PAGE_MASK) +
             (addr & ~TARGET_PAGE_MASK);
@@ -3391,7 +3588,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 6643)
+++ 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: hw/slavio_timer.c
===================================================================
--- hw/slavio_timer.c   (revision 6643)
+++ hw/slavio_timer.c   (working copy)
@@ -137,9 +137,17 @@
         // read limit (system counter mode) or read most signifying
         // part of counter (user mode)
         if (slavio_timer_is_user(s)) {
+            uint64_t last_count = (uint64_t)(s->counthigh) << 32 | s->count;
             // read user timer MSW
             slavio_timer_get_out(s);
             ret = s->counthigh | s->reached;
+            if (last_count == TIMER_MAX_COUNT64) { 
+                uint64_t new_count = (uint64_t)ret << 32 | s->count;
+                if (new_count != last_count) {
+                    s->reached = TIMER_REACHED;
+                    ret |= TIMER_REACHED;
+                }
+            }  
         } else {
             // read limit
             // clear irq
@@ -177,6 +185,31 @@
     return ret;
 }
 
+static uint64_t slavio_timer_mem_readq(void *opaque, target_phys_addr_t addr)
+{
+    SLAVIO_TIMERState *s = opaque;
+    uint32_t saddr;
+    uint64_t ret = 0;
+
+    saddr = addr >> 2;
+    switch (saddr) {
+    case TIMER_LIMIT:
+        if (slavio_timer_is_user(s)) {
+            uint64_t last_count = (uint64_t)(s->counthigh) << 32 | s->count;
+            slavio_timer_get_out(s);
+            ret = (uint64_t)(s->counthigh | s->reached) << 32 | s->count;
+            if (last_count == TIMER_MAX_COUNT64 && ret != last_count) {
+                s->reached = TIMER_REACHED;
+                ret |= ((uint64_t)TIMER_REACHED << 32);
+            }  
+        }
+        break;
+    }
+    DPRINTF("read " TARGET_FMT_plx " = %016llx\n", addr, ret);
+
+    return ret;
+}
+
 static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
                                     uint32_t val)
 {
@@ -303,16 +336,45 @@
     }
 }
 
-static CPUReadMemoryFunc *slavio_timer_mem_read[3] = {
+static void slavio_timer_mem_writeq(void *opaque, target_phys_addr_t addr,
+                                    uint64_t val)
+{
+    SLAVIO_TIMERState *s = opaque;
+    uint32_t saddr;
+
+    DPRINTF("write " TARGET_FMT_plx " %016llx\n", addr, val);
+    saddr = addr >> 2;
+    switch (saddr) {
+    case TIMER_LIMIT:
+        if (slavio_timer_is_user(s)) {
+            uint64_t count;
+
+            s->limit = TIMER_MAX_COUNT64;
+            s->count = val & TIMER_MAX_COUNT64;
+            s->counthigh = (val & TIMER_MAX_COUNT64) >> 32;
+            s->reached = 0;
+            count = ((uint64_t)s->counthigh << 32) | s->count;
+            DPRINTF("processor %d user timer set to %016llx\n", s->slave_index,
+                    count);
+            if (s->timer)
+                ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count));
+        }
+        break;
+    }
+}
+
+static CPUReadMemoryFuncs slavio_timer_mem_read = {
     NULL,
     NULL,
     slavio_timer_mem_readl,
+    slavio_timer_mem_readq
 };
 
-static CPUWriteMemoryFunc *slavio_timer_mem_write[3] = {
+static CPUWriteMemoryFuncs slavio_timer_mem_write = {
     NULL,
     NULL,
     slavio_timer_mem_writel,
+    slavio_timer_mem_writeq
 };
 
 static void slavio_timer_save(QEMUFile *f, void *opaque)
@@ -381,8 +443,8 @@
         ptimer_set_period(s->timer, TIMER_PERIOD);
     }
 
-    slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
-                                                    slavio_timer_mem_write, s);
+    slavio_timer_io_memory = cpu_register_io_memory64(0, 
&slavio_timer_mem_read,
+                                                      &slavio_timer_mem_write, 
s);
     if (master)
         cpu_register_physical_memory(addr, CPU_TIMER_SIZE,
                                      slavio_timer_io_memory);
Index: cpu-all.h
===================================================================
--- cpu-all.h   (revision 6643)
+++ 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,
@@ -909,6 +926,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]