@@ -28,13 +28,18 @@ typedef unsigned long ram_addr_t;
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t, uint32_t);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t);
+typedef void CPUWriteMemory64Func(void *opaque, target_phys_addr_t, uint64_t);
+typedef uint64_t CPUReadMemory64Func(void *opaque, target_phys_addr_t);
+
typedef struct CPUIOMemoryOps {
CPUReadMemoryFunc *readb;
CPUReadMemoryFunc *readw;
CPUReadMemoryFunc *readl;
+ CPUReadMemory64Func *readq;
CPUWriteMemoryFunc *writeb;
CPUWriteMemoryFunc *writew;
CPUWriteMemoryFunc *writel;
+ CPUWriteMemory64Func *writeq;
} CPUIOMemoryOps;
void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
@@ -2930,6 +2930,17 @@ static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
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) || defined(TARGET_MICROBLAZE)
+ 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
@@ -2960,13 +2971,26 @@ static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_
#endif
}
+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" PRIx64 "\n",
+ addr, val);
+#endif
+#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
+ do_unassigned_access(addr, 1, 0, 0, 8);
+#endif
+}
+
static const CPUIOMemoryOps unassigned_mem_ops = {
.readb = unassigned_mem_readb,
.readw = unassigned_mem_readw,
.readl = unassigned_mem_readl,
+ .readq = unassigned_mem_readq,
.writeb = unassigned_mem_writeb,
.writew = unassigned_mem_writew,
.writel = unassigned_mem_writel,
+ .writeq = unassigned_mem_writeq,
};
static const CPUIOMemoryOps rom_mem_ops = {
@@ -2974,6 +2998,7 @@ static const CPUIOMemoryOps rom_mem_ops = {
.writeb = unassigned_mem_writeb,
.writew = unassigned_mem_writew,
.writel = unassigned_mem_writel,
+ .writeq = unassigned_mem_writeq,
};
static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
@@ -3036,11 +3061,32 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
}
+static void notdirty_mem_writeq(void *opaque, target_phys_addr_t ram_addr,
+ uint64_t val)
+{
+ int dirty_flags;
+ dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
+ if (!(dirty_flags & CODE_DIRTY_FLAG)) {
+#if !defined(CONFIG_USER_ONLY)
+ tb_invalidate_phys_page_fast(ram_addr, 8);
+ dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
+#endif
+ }
+ stq_p(qemu_get_ram_ptr(ram_addr), val);
+ dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
+ cpu_physical_memory_set_dirty_flags(ram_addr, 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 const CPUIOMemoryOps notdirty_mem_ops = {
/* Read functions never used. */
.writeb = notdirty_mem_writeb,
.writew = notdirty_mem_writew,
.writel = notdirty_mem_writel,
+ .writeq = notdirty_mem_writeq,
};
/* Generate a debug exception if a watchpoint has been hit. */
@@ -3109,6 +3155,12 @@ static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
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)
{
@@ -3130,13 +3182,22 @@ static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
stl_phys(addr, val);
}
+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 const CPUIOMemoryOps watch_mem_ops = {
.readb = watch_mem_readb,
.readw = watch_mem_readw,
.readl = watch_mem_readl,
+ .readq = watch_mem_readq,
.writeb = watch_mem_writeb,
.writew = watch_mem_writew,
.writel = watch_mem_writel,
+ .writeq = watch_mem_writeq,
};
static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
@@ -3226,13 +3287,44 @@ static void subpage_writel (void *opaque,
addr + mmio->region_offset[idx], value);
}
+static uint64_t subpage_readq (void *opaque, target_phys_addr_t addr)
+{
+ subpage_t *mmio = opaque;
+ unsigned int idx = SUBPAGE_IDX(addr);
+
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: subpage %p addr " TARGET_FMT_plx " idx %d\n",
+ __func__, mmio, addr, idx);
+#endif
+
+ return mmio->mem_ops[idx].readq(mmio->opaque[idx],
+ addr + mmio->region_offset[idx]);
+}
+
+static void subpage_writeq (void *opaque,
+ target_phys_addr_t addr, uint64_t value)
+{
+ subpage_t *mmio = opaque;
+ unsigned int idx = SUBPAGE_IDX(addr);
+
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: subpage %p addr " TARGET_FMT_plx " idx %d\n",
+ __func__, mmio, addr, idx);
+#endif
+
+ return mmio->mem_ops[idx].writeq(mmio->opaque[idx],
+ addr + mmio->region_offset[idx], value);
+}
+
static const CPUIOMemoryOps subpage_ops = {
.readb = subpage_readb,
.readw = subpage_readw,
.readl = subpage_readl,
+ .readq = subpage_readq,
.writeb = subpage_writeb,
.writew = subpage_writew,
.writel = subpage_writel,
+ .writeq = subpage_writeq,
};
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
@@ -3342,9 +3434,11 @@ int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
ops.readb = mem_read[0];
ops.readw = mem_read[1];
ops.readl = mem_read[2];
+ ops.readq = NULL;
ops.writeb = mem_write[0];
ops.writew = mem_write[1];
ops.writel = mem_write[2];
+ ops.writeq = NULL;
return cpu_register_io_memory_fixed(0, &ops, opaque);
}
@@ -3447,7 +3541,11 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
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 && io_mem_ops[io_index].writeq) {
+ uint64_t v64 = ldq_p(buf);
+ io_mem_ops[io_index].writeq(opaque, addr1, v64);
+ l = 8;
+ } else if (l >= 4 && ((addr1 & 3) == 0)) {
/* 32 bit write access */
val = ldl_p(buf);
io_mem_ops[io_index].writel(opaque, addr1, val);
@@ -3486,7 +3584,12 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
void *opaque = io_mem_opaque[io_index];
if (p)
addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
- if (l >= 4 && ((addr1 & 3) == 0)) {
+ if (l >= 8 && (addr1 & 7) == 0 && io_mem_ops[io_index].readq) {
+ uint64_t v64;
+ v64 = io_mem_ops[io_index].readq(opaque, addr1);
+ stq_p(buf, val);
+ l = 8;
+ } else if (l >= 4 && ((addr1 & 3) == 0)) {
/* 32 bit read access */
val = io_mem_ops[io_index].readl(opaque, addr1);
stl_p(buf, val);
@@ -3750,21 +3853,25 @@ uint64_t ldq_phys(target_phys_addr_t addr)
/* I/O case */
int io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
void *opaque = io_mem_opaque[io_index];
- CPUReadMemoryFunc *readl;
- uint32_t v1, v2;
if (p)
addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
- readl = io_mem_ops[io_index].readl;
- v1 = readl(opaque, addr);
- v2 = readl(opaque, addr + 4);
+ if (io_mem_ops[io_index].readq) {
+ val = io_mem_ops[io_index].readq(opaque, addr);
+ } else {
+ CPUReadMemoryFunc *readl = io_mem_ops[io_index].readl;
+ uint32_t v1, v2;
+
+ v1 = readl(opaque, addr);
+ v2 = readl(opaque, addr + 4);
#ifdef TARGET_WORDS_BIGENDIAN
- val = ((uint64_t)v1 << 32) | v2;
+ val = ((uint64_t)v1 << 32) | v2;
#else
- val = ((uint64_t)v2 << 32) | v1;
+ val = ((uint64_t)v2 << 32) | v1;
#endif
+ }
} else {
/* RAM case */
ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
@@ -3845,20 +3952,25 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
int io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
void *opaque = io_mem_opaque[io_index];
- CPUWriteMemoryFunc *writel;
- uint32_t v1, v2;
if (p)
addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+
+ if (io_mem_ops[io_index].writeq) {
+ io_mem_ops[io_index].writeq(opaque, addr, val);
+ } else {
+ CPUWriteMemoryFunc *writel = io_mem_ops[io_index].writel;
+ uint32_t v1, v2;
+
#ifdef TARGET_WORDS_BIGENDIAN
- v1 = val >> 32, v2 = val;
+ v1 = val >> 32, v2 = val;
#else
- v1 = val, v2 = val >> 32;
+ v1 = val, v2 = val >> 32;
#endif
- writel = io_mem_ops[io_index].writel;
- writel(opaque, addr, v1);
- writel(opaque, addr + 4, v2);
+ writel(opaque, addr, v1);
+ writel(opaque, addr + 4, v2);
+ }
} else {
ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
(addr & ~TARGET_PAGE_MASK);
@@ -72,7 +72,9 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
#if SHIFT <= 2
res = io_mem_ops[index].glue(read,SUFFIX)(opaque, physaddr);
#else
- {
+ if (io_mem_ops[index].readq) {
+ res = io_mem_ops[index].readq(opaque, physaddr);
+ } else {
CPUReadMemoryFunc *readl = io_mem_ops[index].readl;
uint32_t v1 = readl(opaque, physaddr);
uint32_t v2 = readl(opaque, physaddr + 4);
@@ -222,7 +224,9 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
#if SHIFT <= 2
io_mem_ops[index].glue(write,SUFFIX)(opaque, physaddr, val);
#else
- {
+ if (io_mem_ops[index].writeq) {
+ io_mem_ops[index].writeq(opaque, physaddr, val);
+ } else {
CPUWriteMemoryFunc *writel = io_mem_ops[index].writel;
uint32_t v1, v2;
If the device provides full 64-bit i/o routines, use them instead of forcing the i/o to be split into two 32-bit i/o calls. Signed-off-by: Richard Henderson <rth@twiddle.net> --- cpu-common.h | 5 ++ exec.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++------ softmmu_template.h | 8 ++- 3 files changed, 139 insertions(+), 18 deletions(-)