[Top][All Lists]
[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,
¬dirty_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);