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 v3


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

This is the third version of adding 64 bit I/O support to QEMU.

This version uses a 4 member structure to hold the mmio
callbacks but presents the old 3 element array interface for
existing hardware drivers.  Only hardware drivers that need
64 bit I/O will need to be converted to the new interface.
Sparc32 slavio_timer has been converted to use the new
interface and 64 bit accesses to it's 64 bit timer have been
verified to work properly using the built in self test for the
64 bit user timer in a sun openboot prom image for an
SS5-170.

This patch still has some issues that need to be addressed:

The subpage code has not been converted to a structure
so some pointer conversion casts are necessary.

The VGA hack functions still return an array pointer
rather than a structure pointer but can be easily changed
later along with the hardware driver that uses them.

Please test this on systems other than sparc with
DEBUG_UNASSIGNED enabled in exec.c to
see if 64 bit mmio is being performed so those
hardware drivers can be converted.  They will
complain of an unassigned access with a size of 8.
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,34 +2945,64 @@
 {
     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_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
-   registered functions may be modified dynamically later.
-   If io_index is non zero, the corresponding io zone is
-   modified. If it is zero, a new io zone is allocated. The return
-   value can be used with cpu_register_physical_memory(). (-1) is
-   returned if error. */
+   function to access byte (index 0), word (index 1), dword (index
+   2) and qword (index 3). Functions can be omitted with a NULL
+   function pointer. The registered functions may be modified
+   dynamically later.  If io_index is non zero, the corresponding
+   io zone is modified. If it is zero, a new io zone is allocated.
+   The return value can be used with cpu_register_physical_memory().
+   (-1) is returned if error. */
 int cpu_register_io_memory(int io_index,
                            CPUReadMemoryFunc **mem_read,
                            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 = NULL;
+    io_mem_write[io_index].q = NULL;
+
+    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 +3012,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 +3119,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 +3162,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 +3400,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 +3432,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 +3479,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 +3515,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 +3542,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]