diff options
83 files changed, 1200 insertions, 1149 deletions
diff --git a/Makefile.objs b/Makefile.objs index 8813673584..47fdc827c3 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -109,7 +109,7 @@ common-obj-$(CONFIG_SD) += sd.o common-obj-y += bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o common-obj-y += bt-hci-csr.o common-obj-y += buffered_file.o migration.o migration-tcp.o -common-obj-y += qemu-char.o savevm.o #aio.o +common-obj-y += qemu-char.o #aio.o common-obj-y += msmouse.o ps2.o common-obj-y += qdev.o qdev-properties.o common-obj-y += block-migration.o iohandler.o diff --git a/Makefile.target b/Makefile.target index 3261383fd3..18be6243f7 100644 --- a/Makefile.target +++ b/Makefile.target @@ -196,7 +196,7 @@ obj-$(CONFIG_VHOST_NET) += vhost.o obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o obj-$(CONFIG_KVM) += kvm.o kvm-all.o obj-$(CONFIG_NO_KVM) += kvm-stub.o -obj-y += memory.o +obj-y += memory.o savevm.o LIBS+=-lz QEMU_CFLAGS += $(VNC_TLS_CFLAGS) @@ -336,6 +336,7 @@ obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o obj-arm-y += versatile_pci.o obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o +obj-arm-y += arm_l2x0.o obj-arm-y += arm_mptimer.o obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o obj-arm-y += pl061.o diff --git a/arch_init.c b/arch_init.c index 847bf4edd6..66f7a3fe5f 100644 --- a/arch_init.c +++ b/arch_init.c @@ -117,24 +117,22 @@ static int ram_save_block(QEMUFile *f) { RAMBlock *block = last_block; ram_addr_t offset = last_offset; - ram_addr_t current_addr; int bytes_sent = 0; + MemoryRegion *mr; if (!block) block = QLIST_FIRST(&ram_list.blocks); - current_addr = block->offset + offset; - do { - if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) { + mr = block->mr; + if (memory_region_get_dirty(mr, offset, DIRTY_MEMORY_MIGRATION)) { uint8_t *p; int cont = (block == last_block) ? RAM_SAVE_FLAG_CONTINUE : 0; - cpu_physical_memory_reset_dirty(current_addr, - current_addr + TARGET_PAGE_SIZE, - MIGRATION_DIRTY_FLAG); + memory_region_reset_dirty(mr, offset, TARGET_PAGE_SIZE, + DIRTY_MEMORY_MIGRATION); - p = block->host + offset; + p = memory_region_get_ram_ptr(mr) + offset; if (is_dup_page(p, *p)) { qemu_put_be64(f, offset | cont | RAM_SAVE_FLAG_COMPRESS); @@ -166,10 +164,7 @@ static int ram_save_block(QEMUFile *f) if (!block) block = QLIST_FIRST(&ram_list.blocks); } - - current_addr = block->offset + offset; - - } while (current_addr != last_block->offset + last_offset); + } while (block != last_block || offset != last_offset); last_block = block; last_offset = offset; @@ -186,9 +181,9 @@ static ram_addr_t ram_save_remaining(void) QLIST_FOREACH(block, &ram_list.blocks, next) { ram_addr_t addr; - for (addr = block->offset; addr < block->offset + block->length; - addr += TARGET_PAGE_SIZE) { - if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) { + for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) { + if (memory_region_get_dirty(block->mr, addr, + DIRTY_MEMORY_MIGRATION)) { count++; } } @@ -222,12 +217,8 @@ static int block_compar(const void *a, const void *b) { RAMBlock * const *ablock = a; RAMBlock * const *bblock = b; - if ((*ablock)->offset < (*bblock)->offset) { - return -1; - } else if ((*ablock)->offset > (*bblock)->offset) { - return 1; - } - return 0; + + return strcmp((*ablock)->idstr, (*bblock)->idstr); } static void sort_ram_list(void) @@ -260,7 +251,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) int ret; if (stage < 0) { - cpu_physical_memory_set_dirty_tracking(0); + memory_global_dirty_log_stop(); return 0; } @@ -275,17 +266,15 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) /* Make sure all dirty bits are set */ QLIST_FOREACH(block, &ram_list.blocks, next) { - for (addr = block->offset; addr < block->offset + block->length; - addr += TARGET_PAGE_SIZE) { - if (!cpu_physical_memory_get_dirty(addr, - MIGRATION_DIRTY_FLAG)) { - cpu_physical_memory_set_dirty(addr); + for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) { + if (!memory_region_get_dirty(block->mr, addr, + DIRTY_MEMORY_MIGRATION)) { + memory_region_set_dirty(block->mr, addr); } } } - /* Enable dirty memory tracking */ - cpu_physical_memory_set_dirty_tracking(1); + memory_global_dirty_log_start(); qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE); @@ -330,7 +319,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) while ((bytes_sent = ram_save_block(f)) != 0) { bytes_transferred += bytes_sent; } - cpu_physical_memory_set_dirty_tracking(0); + memory_global_dirty_log_stop(); } qemu_put_be64(f, RAM_SAVE_FLAG_EOS); @@ -354,7 +343,7 @@ static inline void *host_from_stream_offset(QEMUFile *f, return NULL; } - return block->host + offset; + return memory_region_get_ram_ptr(block->mr) + offset; } len = qemu_get_byte(f); @@ -363,7 +352,7 @@ static inline void *host_from_stream_offset(QEMUFile *f, QLIST_FOREACH(block, &ram_list.blocks, next) { if (!strncmp(id, block->idstr, sizeof(id))) - return block->host + offset; + return memory_region_get_ram_ptr(block->mr) + offset; } fprintf(stderr, "Can't find block %s!\n", id); @@ -376,7 +365,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id) int flags; int error; - if (version_id < 3 || version_id > 4) { + if (version_id < 4 || version_id > 4) { return -EINVAL; } @@ -387,11 +376,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id) addr &= TARGET_PAGE_MASK; if (flags & RAM_SAVE_FLAG_MEM_SIZE) { - if (version_id == 3) { - if (addr != ram_bytes_total()) { - return -EINVAL; - } - } else { + if (version_id == 4) { /* Synchronize RAM block list */ char id[256]; ram_addr_t length; @@ -429,10 +414,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id) void *host; uint8_t ch; - if (version_id == 3) - host = qemu_get_ram_ptr(addr); - else - host = host_from_stream_offset(f, addr, flags); + host = host_from_stream_offset(f, addr, flags); if (!host) { return -EINVAL; } @@ -448,10 +430,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id) } else if (flags & RAM_SAVE_FLAG_PAGE) { void *host; - if (version_id == 3) - host = qemu_get_ram_ptr(addr); - else - host = host_from_stream_offset(f, addr, flags); + host = host_from_stream_offset(f, addr, flags); qemu_get_buffer(f, host, TARGET_PAGE_SIZE); } @@ -476,6 +476,7 @@ extern ram_addr_t ram_size; #define RAM_PREALLOC_MASK (1 << 0) typedef struct RAMBlock { + struct MemoryRegion *mr; uint8_t *host; ram_addr_t offset; ram_addr_t length; @@ -502,7 +503,7 @@ extern int mem_prealloc; 3 flags. The ROMD code stores the page ram offset in iotlb entry, so only a limited number of ids are avaiable. */ -#define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT)) +#define IO_MEM_NB_ENTRIES (1 << TARGET_PAGE_BITS) /* Flags stored in the low bits of the TLB virtual address. These are defined so that fast path ram access is all zeros. */ @@ -514,61 +515,8 @@ extern int mem_prealloc; /* Set if TLB entry is an IO callback. */ #define TLB_MMIO (1 << 5) -#define VGA_DIRTY_FLAG 0x01 -#define CODE_DIRTY_FLAG 0x02 -#define MIGRATION_DIRTY_FLAG 0x08 - -/* read dirty bit (return 0 or 1) */ -static inline int cpu_physical_memory_is_dirty(ram_addr_t addr) -{ - return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] == 0xff; -} - -static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr) -{ - return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS]; -} - -static inline int cpu_physical_memory_get_dirty(ram_addr_t addr, - int dirty_flags) -{ - return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags; -} - -static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) -{ - ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] = 0xff; -} - -static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr, - int dirty_flags) -{ - return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags; -} - -static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start, - int length, - int dirty_flags) -{ - int i, mask, len; - uint8_t *p; - - len = length >> TARGET_PAGE_BITS; - mask = ~dirty_flags; - p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS); - for (i = 0; i < len; i++) { - p[i] &= mask; - } -} - -void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, - int dirty_flags); void cpu_tlb_update_dirty(CPUState *env); -int cpu_physical_memory_set_dirty_tracking(int enable); - -int cpu_physical_memory_get_dirty_tracking(void); - void dump_exec_info(FILE *f, fprintf_function cpu_fprintf); #endif /* !CONFIG_USER_ONLY */ diff --git a/cpu-common.h b/cpu-common.h index 3fe44d25d1..a40c57dc1f 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -49,6 +49,7 @@ void qemu_put_ram_ptr(void *addr); /* This should not be used by devices. */ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr); ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr); +void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev); void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, int len, int is_write); @@ -106,17 +107,10 @@ void stq_phys(target_phys_addr_t addr, uint64_t val); void cpu_physical_memory_write_rom(target_phys_addr_t addr, const uint8_t *buf, int len); -#define IO_MEM_SHIFT 3 - -#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */ -#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ -#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT) -#define IO_MEM_NOTDIRTY (3 << IO_MEM_SHIFT) -#define IO_MEM_SUBPAGE_RAM (4 << IO_MEM_SHIFT) - -/* Acts like a ROM when read and like a device when written. */ -#define IO_MEM_ROMD (1) -#define IO_MEM_SUBPAGE (2) +extern struct MemoryRegion io_mem_ram; +extern struct MemoryRegion io_mem_rom; +extern struct MemoryRegion io_mem_unassigned; +extern struct MemoryRegion io_mem_notdirty; #endif diff --git a/exec-all.h b/exec-all.h index c211242bab..51d01f260b 100644 --- a/exec-all.h +++ b/exec-all.h @@ -299,9 +299,10 @@ extern void *tci_tb_ptr; #if !defined(CONFIG_USER_ONLY) -extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; -extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; -extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; +uint64_t io_mem_read(int index, target_phys_addr_t addr, unsigned size); +void io_mem_write(int index, target_phys_addr_t addr, uint64_t value, + unsigned size); +extern struct MemoryRegion *io_mem_region[IO_MEM_NB_ENTRIES]; void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx, void *retaddr); @@ -336,31 +337,7 @@ static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong add return addr; } #else -/* NOTE: this function can trigger an exception */ -/* NOTE2: the returned address is not exactly the physical address: it - is the offset relative to phys_ram_base */ -static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr) -{ - int mmu_idx, page_index, pd; - void *p; - - page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - mmu_idx = cpu_mmu_index(env1); - if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code != - (addr & TARGET_PAGE_MASK))) { - ldub_code(addr); - } - pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK; - if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { -#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC) - cpu_unassigned_access(env1, addr, 0, 1, 0, 4); -#else - cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr); -#endif - } - p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend); - return qemu_ram_addr_from_host_nofail(p); -} +tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr); #endif typedef void (CPUDebugExcpHandler)(CPUState *env); diff --git a/exec-obsolete.h b/exec-obsolete.h index 34b9fc56bd..f8af27ed1a 100644 --- a/exec-obsolete.h +++ b/exec-obsolete.h @@ -25,44 +25,74 @@ #ifndef CONFIG_USER_ONLY -ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name, - ram_addr_t size, void *host, +ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr); -ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size, - MemoryRegion *mr); +ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr); void qemu_ram_free(ram_addr_t addr); void qemu_ram_free_from_ptr(ram_addr_t addr); -int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read, - CPUWriteMemoryFunc * const *mem_write, - void *opaque, enum device_endian endian); +struct MemoryRegion; +int cpu_register_io_memory(MemoryRegion *mr); void cpu_unregister_io_memory(int table_address); -void cpu_register_physical_memory_log(target_phys_addr_t start_addr, - ram_addr_t size, - ram_addr_t phys_offset, - ram_addr_t region_offset, - bool log_dirty); +struct MemoryRegionSection; +void cpu_register_physical_memory_log(struct MemoryRegionSection *section, + bool readable, bool readonly); -static inline void cpu_register_physical_memory_offset(target_phys_addr_t start_addr, - ram_addr_t size, - ram_addr_t phys_offset, - ram_addr_t region_offset) +void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); +void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); + +int cpu_physical_memory_set_dirty_tracking(int enable); + +#define VGA_DIRTY_FLAG 0x01 +#define CODE_DIRTY_FLAG 0x02 +#define MIGRATION_DIRTY_FLAG 0x08 + +/* read dirty bit (return 0 or 1) */ +static inline int cpu_physical_memory_is_dirty(ram_addr_t addr) { - cpu_register_physical_memory_log(start_addr, size, phys_offset, - region_offset, false); + return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] == 0xff; } -static inline void cpu_register_physical_memory(target_phys_addr_t start_addr, - ram_addr_t size, - ram_addr_t phys_offset) +static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr) { - cpu_register_physical_memory_offset(start_addr, size, phys_offset, 0); + return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS]; } -void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); -void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); +static inline int cpu_physical_memory_get_dirty(ram_addr_t addr, + int dirty_flags) +{ + return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags; +} + +static inline void cpu_physical_memory_set_dirty(ram_addr_t addr) +{ + ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] = 0xff; +} + +static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr, + int dirty_flags) +{ + return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags; +} + +static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start, + int length, + int dirty_flags) +{ + int i, mask, len; + uint8_t *p; + + len = length >> TARGET_PAGE_BITS; + mask = ~dirty_flags; + p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS); + for (i = 0; i < len; i++) { + p[i] &= mask; + } +} +void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, + int dirty_flags); #endif #endif @@ -118,6 +118,9 @@ RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) }; static MemoryRegion *system_memory; static MemoryRegion *system_io; +MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty; +static MemoryRegion io_mem_subpage_ram; + #endif CPUState *first_cpu; @@ -205,11 +208,9 @@ static void io_mem_init(void); static void memory_map_init(void); /* io memory support */ -CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; -CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; -void *io_mem_opaque[IO_MEM_NB_ENTRIES]; +MemoryRegion *io_mem_region[IO_MEM_NB_ENTRIES]; static char io_mem_used[IO_MEM_NB_ENTRIES]; -static int io_mem_watch; +static MemoryRegion io_mem_watch; #endif /* log support */ @@ -430,7 +431,7 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc) *lp = pd = g_malloc(sizeof(PhysPageDesc) * L2_SIZE); for (i = 0; i < L2_SIZE; i++) { - pd[i].phys_offset = IO_MEM_UNASSIGNED; + pd[i].phys_offset = io_mem_unassigned.ram_addr; pd[i].region_offset = (first_index + i) << TARGET_PAGE_BITS; } } @@ -438,9 +439,18 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc) return pd + (index & (L2_SIZE - 1)); } -static inline PhysPageDesc *phys_page_find(target_phys_addr_t index) +static inline PhysPageDesc phys_page_find(target_phys_addr_t index) { - return phys_page_find_alloc(index, 0); + PhysPageDesc *p = phys_page_find_alloc(index, 0); + + if (p) { + return *p; + } else { + return (PhysPageDesc) { + .phys_offset = io_mem_unassigned.ram_addr, + .region_offset = index << TARGET_PAGE_BITS, + }; + } } static void tlb_protect_code(ram_addr_t ram_addr); @@ -1402,15 +1412,11 @@ static void breakpoint_invalidate(CPUState *env, target_ulong pc) target_phys_addr_t addr; target_ulong pd; ram_addr_t ram_addr; - PhysPageDesc *p; + PhysPageDesc p; addr = cpu_get_phys_page_debug(env, pc); p = phys_page_find(addr >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK); tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0); } @@ -1960,7 +1966,7 @@ static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, unsigned long start, unsigned long length) { unsigned long addr; - if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { + if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) { addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend; if ((addr - start) < length) { tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY; @@ -2008,25 +2014,15 @@ int cpu_physical_memory_set_dirty_tracking(int enable) { int ret = 0; in_migration = enable; - if (enable) { - memory_global_dirty_log_start(); - } else { - memory_global_dirty_log_stop(); - } return ret; } -int cpu_physical_memory_get_dirty_tracking(void) -{ - return in_migration; -} - static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry) { ram_addr_t ram_addr; void *p; - if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { + if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) { p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend); ram_addr = qemu_ram_addr_from_host_nofail(p); @@ -2089,6 +2085,26 @@ static void tlb_add_large_page(CPUState *env, target_ulong vaddr, env->tlb_flush_mask = mask; } +static bool is_ram_rom(ram_addr_t pd) +{ + pd &= ~TARGET_PAGE_MASK; + return pd == io_mem_ram.ram_addr || pd == io_mem_rom.ram_addr; +} + +static bool is_romd(ram_addr_t pd) +{ + MemoryRegion *mr; + + pd &= ~TARGET_PAGE_MASK; + mr = io_mem_region[pd]; + return mr->rom_device && mr->readable; +} + +static bool is_ram_rom_romd(ram_addr_t pd) +{ + return is_ram_rom(pd) || is_romd(pd); +} + /* Add a new TLB entry. At most one entry for a given virtual address is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the supplied size is only used by tlb_flush_page. */ @@ -2096,7 +2112,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr, target_phys_addr_t paddr, int prot, int mmu_idx, target_ulong size) { - PhysPageDesc *p; + PhysPageDesc p; unsigned long pd; unsigned int index; target_ulong address; @@ -2111,11 +2127,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr, tlb_add_large_page(env, vaddr, size); } p = phys_page_find(paddr >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; #if defined(DEBUG_TLB) printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx " prot=%x idx=%d pd=0x%08lx\n", @@ -2123,18 +2135,18 @@ void tlb_set_page(CPUState *env, target_ulong vaddr, #endif address = vaddr; - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { + if (!is_ram_rom_romd(pd)) { /* IO memory case (romd handled later) */ address |= TLB_MMIO; } addend = (unsigned long)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK); - if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) { + if (is_ram_rom(pd)) { /* Normal RAM. */ iotlb = pd & TARGET_PAGE_MASK; - if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM) - iotlb |= IO_MEM_NOTDIRTY; + if ((pd & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) + iotlb |= io_mem_notdirty.ram_addr; else - iotlb |= IO_MEM_ROM; + iotlb |= io_mem_rom.ram_addr; } else { /* IO handlers are currently passed a physical address. It would be nice to pass an offset from the base address @@ -2143,11 +2155,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr, We can't use the high bits of pd for this because IO_MEM_ROMD uses these as a ram address. */ iotlb = (pd & ~TARGET_PAGE_MASK); - if (p) { - iotlb += p->region_offset; - } else { - iotlb += paddr; - } + iotlb += p.region_offset; } code_address = address; @@ -2157,7 +2165,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr, if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) { /* Avoid trapping reads of pages with a write breakpoint. */ if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) { - iotlb = io_mem_watch + paddr; + iotlb = io_mem_watch.ram_addr + paddr; address |= TLB_MMIO; break; } @@ -2180,11 +2188,10 @@ void tlb_set_page(CPUState *env, target_ulong vaddr, te->addr_code = -1; } if (prot & PAGE_WRITE) { - if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM || - (pd & IO_MEM_ROMD)) { + if ((pd & ~TARGET_PAGE_MASK) == io_mem_rom.ram_addr || is_romd(pd)) { /* Write access calls the I/O callback. */ te->addr_write = address | TLB_MMIO; - } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && + } else if ((pd & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr && !cpu_physical_memory_is_dirty(pd)) { te->addr_write = address | TLB_NOTDIRTY; } else { @@ -2472,6 +2479,7 @@ static inline void tlb_set_dirty(CPUState *env, #define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK) typedef struct subpage_t { + MemoryRegion iomem; target_phys_addr_t base; ram_addr_t sub_io_index[TARGET_PAGE_SIZE]; ram_addr_t region_offset[TARGET_PAGE_SIZE]; @@ -2510,21 +2518,31 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys, start_addr and region_offset are rounded down to a page boundary before calculating this offset. This should not be a problem unless the low bits of start_addr and region_offset differ. */ -void cpu_register_physical_memory_log(target_phys_addr_t start_addr, - ram_addr_t size, - ram_addr_t phys_offset, - ram_addr_t region_offset, - bool log_dirty) +void cpu_register_physical_memory_log(MemoryRegionSection *section, + bool readable, bool readonly) { + target_phys_addr_t start_addr = section->offset_within_address_space; + ram_addr_t size = section->size; + ram_addr_t phys_offset = section->mr->ram_addr; + ram_addr_t region_offset = section->offset_within_region; target_phys_addr_t addr, end_addr; PhysPageDesc *p; CPUState *env; ram_addr_t orig_size = size; subpage_t *subpage; + if (memory_region_is_ram(section->mr)) { + phys_offset += region_offset; + region_offset = 0; + } + + if (readonly) { + phys_offset |= io_mem_rom.ram_addr; + } + assert(size); - if (phys_offset == IO_MEM_UNASSIGNED) { + if (phys_offset == io_mem_unassigned.ram_addr) { region_offset = start_addr; } region_offset &= TARGET_PAGE_MASK; @@ -2533,38 +2551,37 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr, addr = start_addr; do { - p = phys_page_find(addr >> TARGET_PAGE_BITS); - if (p && p->phys_offset != IO_MEM_UNASSIGNED) { + p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 0); + if (p && p->phys_offset != io_mem_unassigned.ram_addr) { ram_addr_t orig_memory = p->phys_offset; target_phys_addr_t start_addr2, end_addr2; int need_subpage = 0; + MemoryRegion *mr = io_mem_region[orig_memory & ~TARGET_PAGE_MASK]; CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, need_subpage); if (need_subpage) { - if (!(orig_memory & IO_MEM_SUBPAGE)) { + if (!(mr->subpage)) { subpage = subpage_init((addr & TARGET_PAGE_MASK), &p->phys_offset, orig_memory, p->region_offset); } else { - subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK) - >> IO_MEM_SHIFT]; + subpage = container_of(mr, subpage_t, iomem); } subpage_register(subpage, start_addr2, end_addr2, phys_offset, region_offset); p->region_offset = 0; } else { p->phys_offset = phys_offset; - if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM || - (phys_offset & IO_MEM_ROMD)) + p->region_offset = region_offset; + if (is_ram_rom_romd(phys_offset)) phys_offset += TARGET_PAGE_SIZE; } } else { p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1); p->phys_offset = phys_offset; p->region_offset = region_offset; - if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM || - (phys_offset & IO_MEM_ROMD)) { + if (is_ram_rom_romd(phys_offset)) { phys_offset += TARGET_PAGE_SIZE; } else { target_phys_addr_t start_addr2, end_addr2; @@ -2575,7 +2592,8 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr, if (need_subpage) { subpage = subpage_init((addr & TARGET_PAGE_MASK), - &p->phys_offset, IO_MEM_UNASSIGNED, + &p->phys_offset, + io_mem_unassigned.ram_addr, addr & TARGET_PAGE_MASK); subpage_register(subpage, start_addr2, end_addr2, phys_offset, region_offset); @@ -2753,14 +2771,19 @@ static ram_addr_t last_ram_offset(void) return last; } -ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name, - ram_addr_t size, void *host, - MemoryRegion *mr) +void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) { RAMBlock *new_block, *block; - size = TARGET_PAGE_ALIGN(size); - new_block = g_malloc0(sizeof(*new_block)); + new_block = NULL; + QLIST_FOREACH(block, &ram_list.blocks, next) { + if (block->offset == addr) { + new_block = block; + break; + } + } + assert(new_block); + assert(!new_block->idstr[0]); if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) { char *id = dev->parent_bus->info->get_dev_path(dev); @@ -2772,13 +2795,23 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name, pstrcat(new_block->idstr, sizeof(new_block->idstr), name); QLIST_FOREACH(block, &ram_list.blocks, next) { - if (!strcmp(block->idstr, new_block->idstr)) { + if (block != new_block && !strcmp(block->idstr, new_block->idstr)) { fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n", new_block->idstr); abort(); } } +} + +ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, + MemoryRegion *mr) +{ + RAMBlock *new_block; + + size = TARGET_PAGE_ALIGN(size); + new_block = g_malloc0(sizeof(*new_block)); + new_block->mr = mr; new_block->offset = find_ram_offset(size); if (host) { new_block->host = host; @@ -2834,10 +2867,9 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name, return new_block->offset; } -ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size, - MemoryRegion *mr) +ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr) { - return qemu_ram_alloc_from_ptr(dev, name, size, NULL, mr); + return qemu_ram_alloc_from_ptr(size, NULL, mr); } void qemu_ram_free_from_ptr(ram_addr_t addr) @@ -3091,133 +3123,83 @@ ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr) return ram_addr; } -static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) +static uint64_t unassigned_mem_read(void *opaque, target_phys_addr_t addr, + unsigned size) { #ifdef DEBUG_UNASSIGNED printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); #endif #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 1); + cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size); #endif return 0; } -static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr) +static void unassigned_mem_write(void *opaque, target_phys_addr_t addr, + uint64_t val, unsigned size) { #ifdef DEBUG_UNASSIGNED - printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); + printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val); #endif #if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 2); + cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size); #endif - return 0; } -static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr) -{ -#ifdef DEBUG_UNASSIGNED - printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); -#endif -#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 4); -#endif - return 0; -} - -static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) -{ -#ifdef DEBUG_UNASSIGNED - printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); -#endif -#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 1); -#endif -} +static const MemoryRegionOps unassigned_mem_ops = { + .read = unassigned_mem_read, + .write = unassigned_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; -static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +static uint64_t error_mem_read(void *opaque, target_phys_addr_t addr, + unsigned size) { -#ifdef DEBUG_UNASSIGNED - printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); -#endif -#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 2); -#endif + abort(); } -static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +static void error_mem_write(void *opaque, target_phys_addr_t addr, + uint64_t value, unsigned size) { -#ifdef DEBUG_UNASSIGNED - printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val); -#endif -#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) - cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 4); -#endif + abort(); } -static CPUReadMemoryFunc * const unassigned_mem_read[3] = { - unassigned_mem_readb, - unassigned_mem_readw, - unassigned_mem_readl, +static const MemoryRegionOps error_mem_ops = { + .read = error_mem_read, + .write = error_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, }; -static CPUWriteMemoryFunc * const unassigned_mem_write[3] = { - unassigned_mem_writeb, - unassigned_mem_writew, - unassigned_mem_writel, +static const MemoryRegionOps rom_mem_ops = { + .read = error_mem_read, + .write = unassigned_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, }; -static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr, - uint32_t val) +static void notdirty_mem_write(void *opaque, target_phys_addr_t ram_addr, + uint64_t val, unsigned size) { 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, 1); + tb_invalidate_phys_page_fast(ram_addr, size); dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr); #endif } - stb_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 void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr, - uint32_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, 2); - dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr); -#endif - } - stw_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 void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr, - uint32_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, 4); - dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr); -#endif + switch (size) { + case 1: + stb_p(qemu_get_ram_ptr(ram_addr), val); + break; + case 2: + stw_p(qemu_get_ram_ptr(ram_addr), val); + break; + case 4: + stl_p(qemu_get_ram_ptr(ram_addr), val); + break; + default: + abort(); } - stl_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 @@ -3226,16 +3208,10 @@ 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 CPUReadMemoryFunc * const error_mem_read[3] = { - NULL, /* never used */ - NULL, /* never used */ - NULL, /* never used */ -}; - -static CPUWriteMemoryFunc * const notdirty_mem_write[3] = { - notdirty_mem_writeb, - notdirty_mem_writew, - notdirty_mem_writel, +static const MemoryRegionOps notdirty_mem_ops = { + .read = error_mem_read, + .write = notdirty_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, }; /* Generate a debug exception if a watchpoint has been hit. */ @@ -3286,61 +3262,40 @@ static void check_watchpoint(int offset, int len_mask, int flags) /* Watchpoint access routines. Watchpoints are inserted using TLB tricks, so these check for a hit then pass through to the normal out-of-line phys routines. */ -static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr) -{ - check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ); - return ldub_phys(addr); -} - -static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr) +static uint64_t watch_mem_read(void *opaque, target_phys_addr_t addr, + unsigned size) { - check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ); - return lduw_phys(addr); -} - -static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr) -{ - check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ); - return ldl_phys(addr); -} - -static void watch_mem_writeb(void *opaque, target_phys_addr_t addr, - uint32_t val) -{ - check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE); - stb_phys(addr, val); -} - -static void watch_mem_writew(void *opaque, target_phys_addr_t addr, - uint32_t val) -{ - check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE); - stw_phys(addr, val); + check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_READ); + switch (size) { + case 1: return ldub_phys(addr); + case 2: return lduw_phys(addr); + case 4: return ldl_phys(addr); + default: abort(); + } } -static void watch_mem_writel(void *opaque, target_phys_addr_t addr, - uint32_t val) +static void watch_mem_write(void *opaque, target_phys_addr_t addr, + uint64_t val, unsigned size) { - check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE); - stl_phys(addr, val); + check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_WRITE); + switch (size) { + case 1: stb_phys(addr, val); + case 2: stw_phys(addr, val); + case 4: stl_phys(addr, val); + default: abort(); + } } -static CPUReadMemoryFunc * const watch_mem_read[3] = { - watch_mem_readb, - watch_mem_readw, - watch_mem_readl, -}; - -static CPUWriteMemoryFunc * const watch_mem_write[3] = { - watch_mem_writeb, - watch_mem_writew, - watch_mem_writel, +static const MemoryRegionOps watch_mem_ops = { + .read = watch_mem_read, + .write = watch_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, }; -static inline uint32_t subpage_readlen (subpage_t *mmio, - target_phys_addr_t addr, - unsigned int len) +static uint64_t subpage_read(void *opaque, target_phys_addr_t addr, + unsigned len) { + subpage_t *mmio = opaque; unsigned int idx = SUBPAGE_IDX(addr); #if defined(DEBUG_SUBPAGE) printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__, @@ -3349,123 +3304,61 @@ static inline uint32_t subpage_readlen (subpage_t *mmio, addr += mmio->region_offset[idx]; idx = mmio->sub_io_index[idx]; - return io_mem_read[idx][len](io_mem_opaque[idx], addr); + return io_mem_read(idx, addr, len); } -static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr, - uint32_t value, unsigned int len) +static void subpage_write(void *opaque, target_phys_addr_t addr, + uint64_t value, unsigned len) { + subpage_t *mmio = opaque; unsigned int idx = SUBPAGE_IDX(addr); #if defined(DEBUG_SUBPAGE) - printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", + printf("%s: subpage %p len %d addr " TARGET_FMT_plx + " idx %d value %"PRIx64"\n", __func__, mmio, len, addr, idx, value); #endif addr += mmio->region_offset[idx]; idx = mmio->sub_io_index[idx]; - io_mem_write[idx][len](io_mem_opaque[idx], addr, value); -} - -static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr) -{ - return subpage_readlen(opaque, addr, 0); -} - -static void subpage_writeb (void *opaque, target_phys_addr_t addr, - uint32_t value) -{ - subpage_writelen(opaque, addr, value, 0); -} - -static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr) -{ - return subpage_readlen(opaque, addr, 1); -} - -static void subpage_writew (void *opaque, target_phys_addr_t addr, - uint32_t value) -{ - subpage_writelen(opaque, addr, value, 1); + io_mem_write(idx, addr, value, len); } -static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr) -{ - return subpage_readlen(opaque, addr, 2); -} - -static void subpage_writel (void *opaque, target_phys_addr_t addr, - uint32_t value) -{ - subpage_writelen(opaque, addr, value, 2); -} - -static CPUReadMemoryFunc * const subpage_read[] = { - &subpage_readb, - &subpage_readw, - &subpage_readl, -}; - -static CPUWriteMemoryFunc * const subpage_write[] = { - &subpage_writeb, - &subpage_writew, - &subpage_writel, +static const MemoryRegionOps subpage_ops = { + .read = subpage_read, + .write = subpage_write, + .endianness = DEVICE_NATIVE_ENDIAN, }; -static uint32_t subpage_ram_readb(void *opaque, target_phys_addr_t addr) -{ - ram_addr_t raddr = addr; - void *ptr = qemu_get_ram_ptr(raddr); - return ldub_p(ptr); -} - -static void subpage_ram_writeb(void *opaque, target_phys_addr_t addr, - uint32_t value) -{ - ram_addr_t raddr = addr; - void *ptr = qemu_get_ram_ptr(raddr); - stb_p(ptr, value); -} - -static uint32_t subpage_ram_readw(void *opaque, target_phys_addr_t addr) +static uint64_t subpage_ram_read(void *opaque, target_phys_addr_t addr, + unsigned size) { ram_addr_t raddr = addr; void *ptr = qemu_get_ram_ptr(raddr); - return lduw_p(ptr); -} - -static void subpage_ram_writew(void *opaque, target_phys_addr_t addr, - uint32_t value) -{ - ram_addr_t raddr = addr; - void *ptr = qemu_get_ram_ptr(raddr); - stw_p(ptr, value); -} - -static uint32_t subpage_ram_readl(void *opaque, target_phys_addr_t addr) -{ - ram_addr_t raddr = addr; - void *ptr = qemu_get_ram_ptr(raddr); - return ldl_p(ptr); + switch (size) { + case 1: return ldub_p(ptr); + case 2: return lduw_p(ptr); + case 4: return ldl_p(ptr); + default: abort(); + } } -static void subpage_ram_writel(void *opaque, target_phys_addr_t addr, - uint32_t value) +static void subpage_ram_write(void *opaque, target_phys_addr_t addr, + uint64_t value, unsigned size) { ram_addr_t raddr = addr; void *ptr = qemu_get_ram_ptr(raddr); - stl_p(ptr, value); + switch (size) { + case 1: return stb_p(ptr, value); + case 2: return stw_p(ptr, value); + case 4: return stl_p(ptr, value); + default: abort(); + } } -static CPUReadMemoryFunc * const subpage_ram_read[] = { - &subpage_ram_readb, - &subpage_ram_readw, - &subpage_ram_readl, -}; - -static CPUWriteMemoryFunc * const subpage_ram_write[] = { - &subpage_ram_writeb, - &subpage_ram_writew, - &subpage_ram_writel, +static const MemoryRegionOps subpage_ram_ops = { + .read = subpage_ram_read, + .write = subpage_ram_write, + .endianness = DEVICE_NATIVE_ENDIAN, }; static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, @@ -3481,10 +3374,10 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__, mmio, start, end, idx, eidx, memory); #endif - if ((memory & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { - memory = IO_MEM_SUBPAGE_RAM; + if ((memory & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) { + memory = io_mem_subpage_ram.ram_addr; } - memory = (memory >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); + memory &= IO_MEM_NB_ENTRIES - 1; for (; idx <= eidx; idx++) { mmio->sub_io_index[idx] = memory; mmio->region_offset[idx] = region_offset; @@ -3503,13 +3396,15 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys, mmio = g_malloc0(sizeof(subpage_t)); mmio->base = base; - subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio, - DEVICE_NATIVE_ENDIAN); + memory_region_init_io(&mmio->iomem, &subpage_ops, mmio, + "subpage", TARGET_PAGE_SIZE); + mmio->iomem.subpage = true; + subpage_memory = mmio->iomem.ram_addr; #if defined(DEBUG_SUBPAGE) printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__, mmio, base, TARGET_PAGE_SIZE, subpage_memory); #endif - *phys = subpage_memory | IO_MEM_SUBPAGE; + *phys = subpage_memory; subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, orig_memory, region_offset); return mmio; @@ -3528,106 +3423,6 @@ static int get_free_io_mem_idx(void) return -1; } -/* - * Usually, devices operate in little endian mode. There are devices out - * there that operate in big endian too. Each device gets byte swapped - * mmio if plugged onto a CPU that does the other endianness. - * - * CPU Device swap? - * - * little little no - * little big yes - * big little yes - * big big no - */ - -typedef struct SwapEndianContainer { - CPUReadMemoryFunc *read[3]; - CPUWriteMemoryFunc *write[3]; - void *opaque; -} SwapEndianContainer; - -static uint32_t swapendian_mem_readb (void *opaque, target_phys_addr_t addr) -{ - uint32_t val; - SwapEndianContainer *c = opaque; - val = c->read[0](c->opaque, addr); - return val; -} - -static uint32_t swapendian_mem_readw(void *opaque, target_phys_addr_t addr) -{ - uint32_t val; - SwapEndianContainer *c = opaque; - val = bswap16(c->read[1](c->opaque, addr)); - return val; -} - -static uint32_t swapendian_mem_readl(void *opaque, target_phys_addr_t addr) -{ - uint32_t val; - SwapEndianContainer *c = opaque; - val = bswap32(c->read[2](c->opaque, addr)); - return val; -} - -static CPUReadMemoryFunc * const swapendian_readfn[3]={ - swapendian_mem_readb, - swapendian_mem_readw, - swapendian_mem_readl -}; - -static void swapendian_mem_writeb(void *opaque, target_phys_addr_t addr, - uint32_t val) -{ - SwapEndianContainer *c = opaque; - c->write[0](c->opaque, addr, val); -} - -static void swapendian_mem_writew(void *opaque, target_phys_addr_t addr, - uint32_t val) -{ - SwapEndianContainer *c = opaque; - c->write[1](c->opaque, addr, bswap16(val)); -} - -static void swapendian_mem_writel(void *opaque, target_phys_addr_t addr, - uint32_t val) -{ - SwapEndianContainer *c = opaque; - c->write[2](c->opaque, addr, bswap32(val)); -} - -static CPUWriteMemoryFunc * const swapendian_writefn[3]={ - swapendian_mem_writeb, - swapendian_mem_writew, - swapendian_mem_writel -}; - -static void swapendian_init(int io_index) -{ - SwapEndianContainer *c = g_malloc(sizeof(SwapEndianContainer)); - int i; - - /* Swap mmio for big endian targets */ - c->opaque = io_mem_opaque[io_index]; - for (i = 0; i < 3; i++) { - c->read[i] = io_mem_read[io_index][i]; - c->write[i] = io_mem_write[io_index][i]; - - io_mem_read[io_index][i] = swapendian_readfn[i]; - io_mem_write[io_index][i] = swapendian_writefn[i]; - } - io_mem_opaque[io_index] = c; -} - -static void swapendian_del(int io_index) -{ - if (io_mem_read[io_index][0] == swapendian_readfn[0]) { - g_free(io_mem_opaque[io_index]); - } -} - /* 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. @@ -3635,71 +3430,30 @@ static void swapendian_del(int io_index) 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. */ -static int cpu_register_io_memory_fixed(int io_index, - CPUReadMemoryFunc * const *mem_read, - CPUWriteMemoryFunc * const *mem_write, - void *opaque, enum device_endian endian) +static int cpu_register_io_memory_fixed(int io_index, MemoryRegion *mr) { - int i; - if (io_index <= 0) { io_index = get_free_io_mem_idx(); if (io_index == -1) return io_index; } else { - io_index >>= IO_MEM_SHIFT; if (io_index >= IO_MEM_NB_ENTRIES) return -1; } - for (i = 0; i < 3; ++i) { - io_mem_read[io_index][i] - = (mem_read[i] ? mem_read[i] : unassigned_mem_read[i]); - } - for (i = 0; i < 3; ++i) { - io_mem_write[io_index][i] - = (mem_write[i] ? mem_write[i] : unassigned_mem_write[i]); - } - io_mem_opaque[io_index] = opaque; + io_mem_region[io_index] = mr; - switch (endian) { - case DEVICE_BIG_ENDIAN: -#ifndef TARGET_WORDS_BIGENDIAN - swapendian_init(io_index); -#endif - break; - case DEVICE_LITTLE_ENDIAN: -#ifdef TARGET_WORDS_BIGENDIAN - swapendian_init(io_index); -#endif - break; - case DEVICE_NATIVE_ENDIAN: - default: - break; - } - - return (io_index << IO_MEM_SHIFT); + return io_index; } -int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read, - CPUWriteMemoryFunc * const *mem_write, - void *opaque, enum device_endian endian) +int cpu_register_io_memory(MemoryRegion *mr) { - return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque, endian); + return cpu_register_io_memory_fixed(0, mr); } -void cpu_unregister_io_memory(int io_table_address) +void cpu_unregister_io_memory(int io_index) { - int i; - int io_index = io_table_address >> IO_MEM_SHIFT; - - swapendian_del(io_index); - - 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_opaque[io_index] = NULL; + io_mem_region[io_index] = NULL; io_mem_used[io_index] = 0; } @@ -3707,24 +3461,21 @@ static void io_mem_init(void) { int i; - cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, - unassigned_mem_write, NULL, - DEVICE_NATIVE_ENDIAN); - cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, - unassigned_mem_write, NULL, - DEVICE_NATIVE_ENDIAN); - cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, - notdirty_mem_write, NULL, - DEVICE_NATIVE_ENDIAN); - cpu_register_io_memory_fixed(IO_MEM_SUBPAGE_RAM, subpage_ram_read, - subpage_ram_write, NULL, - DEVICE_NATIVE_ENDIAN); + /* Must be first: */ + memory_region_init_io(&io_mem_ram, &error_mem_ops, NULL, "ram", UINT64_MAX); + assert(io_mem_ram.ram_addr == 0); + memory_region_init_io(&io_mem_rom, &rom_mem_ops, NULL, "rom", UINT64_MAX); + memory_region_init_io(&io_mem_unassigned, &unassigned_mem_ops, NULL, + "unassigned", UINT64_MAX); + memory_region_init_io(&io_mem_notdirty, ¬dirty_mem_ops, NULL, + "notdirty", UINT64_MAX); + memory_region_init_io(&io_mem_subpage_ram, &subpage_ram_ops, NULL, + "subpage-ram", UINT64_MAX); for (i=0; i<5; i++) io_mem_used[i] = 1; - io_mem_watch = cpu_register_io_memory(watch_mem_read, - watch_mem_write, NULL, - DEVICE_NATIVE_ENDIAN); + memory_region_init_io(&io_mem_watch, &watch_mem_ops, NULL, + "watch", UINT64_MAX); } static void memory_map_init(void) @@ -3800,7 +3551,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, uint32_t val; target_phys_addr_t page; ram_addr_t pd; - PhysPageDesc *p; + PhysPageDesc p; while (len > 0) { page = addr & TARGET_PAGE_MASK; @@ -3808,34 +3559,29 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, if (l > len) l = len; p = phys_page_find(page >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; if (is_write) { - if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { - target_phys_addr_t addr1 = addr; - io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); - if (p) - addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset; + if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) { + target_phys_addr_t addr1; + io_index = pd & (IO_MEM_NB_ENTRIES - 1); + 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)) { /* 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, addr1, val, 4); 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, addr1, val, 2); 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, addr1, val, 1); l = 1; } } else { @@ -3854,26 +3600,24 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, qemu_put_ram_ptr(ptr); } } else { - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && - !(pd & IO_MEM_ROMD)) { - target_phys_addr_t addr1 = addr; + if (!is_ram_rom_romd(pd)) { + target_phys_addr_t addr1; /* I/O case */ - io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); - if (p) - addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset; + io_index = pd & (IO_MEM_NB_ENTRIES - 1); + addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset; 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, addr1, 4); 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, addr1, 2); 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, addr1, 1); stb_p(buf, val); l = 1; } @@ -3898,7 +3642,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, uint8_t *ptr; target_phys_addr_t page; unsigned long pd; - PhysPageDesc *p; + PhysPageDesc p; while (len > 0) { page = addr & TARGET_PAGE_MASK; @@ -3906,15 +3650,9 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, if (l > len) l = len; p = phys_page_find(page >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; - if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM && - (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM && - !(pd & IO_MEM_ROMD)) { + if (!is_ram_rom_romd(pd)) { /* do nothing */ } else { unsigned long addr1; @@ -3992,7 +3730,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, int l; target_phys_addr_t page; unsigned long pd; - PhysPageDesc *p; + PhysPageDesc p; ram_addr_t raddr = RAM_ADDR_MAX; ram_addr_t rlen; void *ret; @@ -4003,13 +3741,9 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, if (l > len) l = len; p = phys_page_find(page >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; - if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { + if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) { if (todo || bounce.buffer) { break; } @@ -4084,22 +3818,16 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr, uint8_t *ptr; uint32_t val; unsigned long pd; - PhysPageDesc *p; + PhysPageDesc p; p = phys_page_find(addr >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && - !(pd & IO_MEM_ROMD)) { + if (!is_ram_rom_romd(pd)) { /* I/O case */ - 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); + io_index = pd & (IO_MEM_NB_ENTRIES - 1); + addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset; + val = io_mem_read(io_index, addr, 4); #if defined(TARGET_WORDS_BIGENDIAN) if (endian == DEVICE_LITTLE_ENDIAN) { val = bswap32(val); @@ -4151,30 +3879,24 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr, uint8_t *ptr; uint64_t val; unsigned long pd; - PhysPageDesc *p; + PhysPageDesc p; p = phys_page_find(addr >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && - !(pd & IO_MEM_ROMD)) { + if (!is_ram_rom_romd(pd)) { /* I/O case */ - io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); - if (p) - addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset; + io_index = pd & (IO_MEM_NB_ENTRIES - 1); + addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset; /* XXX This is broken when device endian != cpu endian. Fix and add "endian" variable check */ #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); + val = io_mem_read(io_index, addr, 4) << 32; + val |= io_mem_read(io_index, addr + 4, 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; + val = io_mem_read(io_index, addr, 4); + val |= io_mem_read(io_index, addr + 4, 4) << 32; #endif } else { /* RAM case */ @@ -4226,22 +3948,16 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr, uint8_t *ptr; uint64_t val; unsigned long pd; - PhysPageDesc *p; + PhysPageDesc p; p = phys_page_find(addr >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && - !(pd & IO_MEM_ROMD)) { + if (!is_ram_rom_romd(pd)) { /* I/O case */ - 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][1](io_mem_opaque[io_index], addr); + io_index = pd & (IO_MEM_NB_ENTRIES - 1); + addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset; + val = io_mem_read(io_index, addr, 2); #if defined(TARGET_WORDS_BIGENDIAN) if (endian == DEVICE_LITTLE_ENDIAN) { val = bswap16(val); @@ -4293,20 +4009,15 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val) int io_index; uint8_t *ptr; unsigned long pd; - PhysPageDesc *p; + PhysPageDesc p; p = phys_page_find(addr >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; - if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { - 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); + if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) { + io_index = pd & (IO_MEM_NB_ENTRIES - 1); + addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset; + io_mem_write(io_index, addr, val, 4); } else { unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); ptr = qemu_get_ram_ptr(addr1); @@ -4329,25 +4040,20 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val) int io_index; uint8_t *ptr; unsigned long pd; - PhysPageDesc *p; + PhysPageDesc p; p = phys_page_find(addr >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; - if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { - io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); - if (p) - addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset; + if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) { + io_index = pd & (IO_MEM_NB_ENTRIES - 1); + 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); + io_mem_write(io_index, addr, val >> 32, 4); + io_mem_write(io_index, addr + 4, (uint32_t)val, 4); #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); + io_mem_write(io_index, addr, (uint32_t)val, 4); + io_mem_write(io_index, addr + 4, val >> 32, 4); #endif } else { ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) + @@ -4363,19 +4069,14 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val, int io_index; uint8_t *ptr; unsigned long pd; - PhysPageDesc *p; + PhysPageDesc p; p = phys_page_find(addr >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; - if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { - io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); - if (p) - addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset; + if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) { + io_index = pd & (IO_MEM_NB_ENTRIES - 1); + addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset; #if defined(TARGET_WORDS_BIGENDIAN) if (endian == DEVICE_LITTLE_ENDIAN) { val = bswap32(val); @@ -4385,7 +4086,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val, val = bswap32(val); } #endif - io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val); + io_mem_write(io_index, addr, val, 4); } else { unsigned long addr1; addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); @@ -4441,19 +4142,14 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val, int io_index; uint8_t *ptr; unsigned long pd; - PhysPageDesc *p; + PhysPageDesc p; p = phys_page_find(addr >> TARGET_PAGE_BITS); - if (!p) { - pd = IO_MEM_UNASSIGNED; - } else { - pd = p->phys_offset; - } + pd = p.phys_offset; - if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { - io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); - if (p) - addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset; + if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) { + io_index = pd & (IO_MEM_NB_ENTRIES - 1); + addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset; #if defined(TARGET_WORDS_BIGENDIAN) if (endian == DEVICE_LITTLE_ENDIAN) { val = bswap16(val); @@ -4463,7 +4159,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val, val = bswap16(val); } #endif - io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val); + io_mem_write(io_index, addr, val, 2); } else { unsigned long addr1; addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); @@ -4667,6 +4363,33 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) tcg_dump_info(f, cpu_fprintf); } +/* NOTE: this function can trigger an exception */ +/* NOTE2: the returned address is not exactly the physical address: it + is the offset relative to phys_ram_base */ +tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr) +{ + int mmu_idx, page_index, pd; + void *p; + + page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); + mmu_idx = cpu_mmu_index(env1); + if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code != + (addr & TARGET_PAGE_MASK))) { + ldub_code(addr); + } + pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK; + if (pd != io_mem_ram.ram_addr && pd != io_mem_rom.ram_addr + && !is_romd(pd)) { +#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC) + cpu_unassigned_access(env1, addr, 0, 1, 0, 4); +#else + cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr); +#endif + } + p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend); + return qemu_ram_addr_from_host_nofail(p); +} + #define MMUSUFFIX _cmmu #undef GETPC #define GETPC() NULL diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c index cd2985f421..3ef0e138c4 100644 --- a/hw/a9mpcore.c +++ b/hw/a9mpcore.c @@ -29,6 +29,7 @@ gic_get_current_cpu(void) typedef struct a9mp_priv_state { gic_state gic; uint32_t scu_control; + uint32_t scu_status; uint32_t old_timer_status[8]; uint32_t num_cpu; qemu_irq *timer_irq; @@ -48,7 +49,13 @@ static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset, case 0x04: /* Configuration */ return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1); case 0x08: /* CPU Power Status */ - return 0; + return s->scu_status; + case 0x09: /* CPU status. */ + return s->scu_status >> 8; + case 0x0a: /* CPU status. */ + return s->scu_status >> 16; + case 0x0b: /* CPU status. */ + return s->scu_status >> 24; case 0x0c: /* Invalidate All Registers In Secure State */ return 0; case 0x40: /* Filtering Start Address Register */ @@ -67,12 +74,35 @@ static void a9_scu_write(void *opaque, target_phys_addr_t offset, uint64_t value, unsigned size) { a9mp_priv_state *s = (a9mp_priv_state *)opaque; + uint32_t mask; + uint32_t shift; + switch (size) { + case 1: + mask = 0xff; + break; + case 2: + mask = 0xffff; + break; + case 4: + mask = 0xffffffff; + break; + default: + fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n", + size, offset); + return; + } + switch (offset) { case 0x00: /* Control */ s->scu_control = value & 1; break; case 0x4: /* Configuration: RO */ break; + case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */ + shift = (offset - 0x8) * 8; + s->scu_status &= ~(mask << shift); + s->scu_status |= ((value & mask) << shift); + break; case 0x0c: /* Invalidate All Registers In Secure State */ /* no-op as we do not implement caches */ break; @@ -80,7 +110,6 @@ static void a9_scu_write(void *opaque, target_phys_addr_t offset, case 0x44: /* Filtering End Address Register */ /* RAZ/WI, like an implementation with only one AXI master */ break; - case 0x8: /* CPU Power Status */ case 0x50: /* SCU Access Control Register */ case 0x54: /* SCU Non-secure Access Control Register */ /* unimplemented, fall through */ @@ -169,11 +198,12 @@ static int a9mp_priv_init(SysBusDevice *dev) static const VMStateDescription vmstate_a9mp_priv = { .name = "a9mpcore_priv", - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(scu_control, a9mp_priv_state), VMSTATE_UINT32_ARRAY(old_timer_status, a9mp_priv_state, 8), + VMSTATE_UINT32_V(scu_status, a9mp_priv_state, 2), VMSTATE_END_OF_LIST() } }; diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index adf738272e..7d924a3f08 100644 --- a/hw/alpha_typhoon.c +++ b/hw/alpha_typhoon.c @@ -726,7 +726,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, /* Main memory region, 0x00.0000.0000. Real hardware supports 32GB, but the address space hole reserved at this point is 8TB. */ - memory_region_init_ram(&s->ram_region, NULL, "ram", ram_size); + memory_region_init_ram(&s->ram_region, "ram", ram_size); + vmstate_register_ram_global(&s->ram_region); memory_region_add_subregion(addr_space, 0, &s->ram_region); /* TIGbus, 0x801.0000.0000, 1GB. */ diff --git a/hw/an5206.c b/hw/an5206.c index 319a40e1d2..d57306d3ad 100644 --- a/hw/an5206.c +++ b/hw/an5206.c @@ -46,11 +46,13 @@ static void an5206_init(ram_addr_t ram_size, env->rambar0 = AN5206_RAMBAR_ADDR | 1; /* DRAM at address zero */ - memory_region_init_ram(ram, NULL, "an5206.ram", ram_size); + memory_region_init_ram(ram, "an5206.ram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); /* Internal SRAM. */ - memory_region_init_ram(sram, NULL, "an5206.sram", 512); + memory_region_init_ram(sram, "an5206.sram", 512); + vmstate_register_ram_global(sram); memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram); mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, env); diff --git a/hw/arm_gic.c b/hw/arm_gic.c index 9b521195a5..0339cf59fb 100644 --- a/hw/arm_gic.c +++ b/hw/arm_gic.c @@ -282,6 +282,10 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset) return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5); if (offset < 0x08) return 0; + if (offset >= 0x80) { + /* Interrupt Security , RAZ/WI */ + return 0; + } #endif goto bad_reg; } else if (offset < 0x200) { @@ -413,6 +417,8 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset, DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis"); } else if (offset < 4) { /* ignored. */ + } else if (offset >= 0x80) { + /* Interrupt Security Registers, RAZ/WI */ } else { goto bad_reg; } diff --git a/hw/arm_l2x0.c b/hw/arm_l2x0.c new file mode 100644 index 0000000000..2faed39f0f --- /dev/null +++ b/hw/arm_l2x0.c @@ -0,0 +1,181 @@ +/* + * ARM dummy L210, L220, PL310 cache controller. + * + * Copyright (c) 2010-2012 Calxeda + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or any later version, as published by the Free Software + * Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "sysbus.h" + +/* L2C-310 r3p2 */ +#define CACHE_ID 0x410000c8 + +typedef struct l2x0_state { + SysBusDevice busdev; + MemoryRegion iomem; + uint32_t cache_type; + uint32_t ctrl; + uint32_t aux_ctrl; + uint32_t data_ctrl; + uint32_t tag_ctrl; + uint32_t filter_start; + uint32_t filter_end; +} l2x0_state; + +static const VMStateDescription vmstate_l2x0 = { + .name = "l2x0", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(ctrl, l2x0_state), + VMSTATE_UINT32(aux_ctrl, l2x0_state), + VMSTATE_UINT32(data_ctrl, l2x0_state), + VMSTATE_UINT32(tag_ctrl, l2x0_state), + VMSTATE_UINT32(filter_start, l2x0_state), + VMSTATE_UINT32(filter_end, l2x0_state), + VMSTATE_END_OF_LIST() + } +}; + + +static uint64_t l2x0_priv_read(void *opaque, target_phys_addr_t offset, + unsigned size) +{ + uint32_t cache_data; + l2x0_state *s = (l2x0_state *)opaque; + offset &= 0xfff; + if (offset >= 0x730 && offset < 0x800) { + return 0; /* cache ops complete */ + } + switch (offset) { + case 0: + return CACHE_ID; + case 0x4: + /* aux_ctrl values affect cache_type values */ + cache_data = (s->aux_ctrl & (7 << 17)) >> 15; + cache_data |= (s->aux_ctrl & (1 << 16)) >> 16; + return s->cache_type |= (cache_data << 18) | (cache_data << 6); + case 0x100: + return s->ctrl; + case 0x104: + return s->aux_ctrl; + case 0x108: + return s->tag_ctrl; + case 0x10C: + return s->data_ctrl; + case 0xC00: + return s->filter_start; + case 0xC04: + return s->filter_end; + case 0xF40: + return 0; + case 0xF60: + return 0; + case 0xF80: + return 0; + default: + fprintf(stderr, "l2x0_priv_read: Bad offset %x\n", (int)offset); + break; + } + return 0; +} + +static void l2x0_priv_write(void *opaque, target_phys_addr_t offset, + uint64_t value, unsigned size) +{ + l2x0_state *s = (l2x0_state *)opaque; + offset &= 0xfff; + if (offset >= 0x730 && offset < 0x800) { + /* ignore */ + return; + } + switch (offset) { + case 0x100: + s->ctrl = value & 1; + break; + case 0x104: + s->aux_ctrl = value; + break; + case 0x108: + s->tag_ctrl = value; + break; + case 0x10C: + s->data_ctrl = value; + break; + case 0xC00: + s->filter_start = value; + break; + case 0xC04: + s->filter_end = value; + break; + case 0xF40: + return; + case 0xF60: + return; + case 0xF80: + return; + default: + fprintf(stderr, "l2x0_priv_write: Bad offset %x\n", (int)offset); + break; + } +} + +static void l2x0_priv_reset(DeviceState *dev) +{ + l2x0_state *s = DO_UPCAST(l2x0_state, busdev.qdev, dev); + + s->ctrl = 0; + s->aux_ctrl = 0x02020000; + s->tag_ctrl = 0; + s->data_ctrl = 0; + s->filter_start = 0; + s->filter_end = 0; +} + +static const MemoryRegionOps l2x0_mem_ops = { + .read = l2x0_priv_read, + .write = l2x0_priv_write, + .endianness = DEVICE_NATIVE_ENDIAN, + }; + +static int l2x0_priv_init(SysBusDevice *dev) +{ + l2x0_state *s = FROM_SYSBUS(l2x0_state, dev); + + memory_region_init_io(&s->iomem, &l2x0_mem_ops, s, "l2x0_cc", 0x1000); + sysbus_init_mmio(dev, &s->iomem); + return 0; +} + +static SysBusDeviceInfo l2x0_info = { + .init = l2x0_priv_init, + .qdev.name = "l2x0", + .qdev.size = sizeof(l2x0_state), + .qdev.vmsd = &vmstate_l2x0, + .qdev.no_user = 1, + .qdev.props = (Property[]) { + DEFINE_PROP_UINT32("type", l2x0_state, cache_type, 0x1c100100), + DEFINE_PROP_END_OF_LIST(), + }, + .qdev.reset = l2x0_priv_reset, +}; + +static void l2x0_register_device(void) +{ + sysbus_register_withprop(&l2x0_info); +} + +device_init(l2x0_register_device) diff --git a/hw/arm_timer.c b/hw/arm_timer.c index 0a5b9d2cd3..60e1c63ab6 100644 --- a/hw/arm_timer.c +++ b/hw/arm_timer.c @@ -9,6 +9,8 @@ #include "sysbus.h" #include "qemu-timer.h" +#include "qemu-common.h" +#include "qdev.h" /* Common timer implementation. */ @@ -178,6 +180,7 @@ typedef struct { SysBusDevice busdev; MemoryRegion iomem; arm_timer_state *timer[2]; + uint32_t freq0, freq1; int level[2]; qemu_irq irq; } sp804_state; @@ -269,10 +272,11 @@ static int sp804_init(SysBusDevice *dev) qi = qemu_allocate_irqs(sp804_set_irq, s, 2); sysbus_init_irq(dev, &s->irq); - /* ??? The timers are actually configurable between 32kHz and 1MHz, but - we don't implement that. */ - s->timer[0] = arm_timer_init(1000000); - s->timer[1] = arm_timer_init(1000000); + /* The timers are configurable between 32kHz and 1MHz + * defaulting to 1MHz but overrideable as individual properties */ + s->timer[0] = arm_timer_init(s->freq0); + s->timer[1] = arm_timer_init(s->freq1); + s->timer[0]->irq = qi[0]; s->timer[1]->irq = qi[1]; memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000); @@ -281,6 +285,16 @@ static int sp804_init(SysBusDevice *dev) return 0; } +static SysBusDeviceInfo sp804_info = { + .init = sp804_init, + .qdev.name = "sp804", + .qdev.size = sizeof(sp804_state), + .qdev.props = (Property[]) { + DEFINE_PROP_UINT32("freq0", sp804_state, freq0, 1000000), + DEFINE_PROP_UINT32("freq1", sp804_state, freq1, 1000000), + DEFINE_PROP_END_OF_LIST(), + } +}; /* Integrator/CP timer module. */ @@ -349,7 +363,7 @@ static int icp_pit_init(SysBusDevice *dev) static void arm_timer_register_devices(void) { sysbus_register_dev("integrator_pit", sizeof(icp_pit_state), icp_pit_init); - sysbus_register_dev("sp804", sizeof(sp804_state), sp804_init); + sysbus_register_withprop(&sp804_info); } device_init(arm_timer_register_devices) diff --git a/hw/armv7m.c b/hw/armv7m.c index eb8c0d68d6..5c7a9502c6 100644 --- a/hw/armv7m.c +++ b/hw/armv7m.c @@ -198,10 +198,12 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, #endif /* Flash programming is done via the SCU, so pretend it is ROM. */ - memory_region_init_ram(flash, NULL, "armv7m.flash", flash_size); + memory_region_init_ram(flash, "armv7m.flash", flash_size); + vmstate_register_ram_global(flash); memory_region_set_readonly(flash, true); memory_region_add_subregion(address_space_mem, 0, flash); - memory_region_init_ram(sram, NULL, "armv7m.sram", sram_size); + memory_region_init_ram(sram, "armv7m.sram", sram_size); + vmstate_register_ram_global(sram); memory_region_add_subregion(address_space_mem, 0x20000000, sram); armv7m_bitband_init(); @@ -235,7 +237,8 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, /* Hack to map an additional page of ram at the top of the address space. This stops qemu complaining about executing code outside RAM when returning from an exception. */ - memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000); + memory_region_init_ram(hack, "armv7m.hack", 0x1000); + vmstate_register_ram_global(hack); memory_region_add_subregion(address_space_mem, 0xfffff000, hack); qemu_register_reset(armv7m_reset, env); diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index c5405ceb3d..c9301fda1d 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -266,12 +266,14 @@ void axisdev88_init (ram_addr_t ram_size, env = cpu_init(cpu_model); /* allocate RAM */ - memory_region_init_ram(phys_ram, NULL, "axisdev88.ram", ram_size); + memory_region_init_ram(phys_ram, "axisdev88.ram", ram_size); + vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram); /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the internal memory. */ - memory_region_init_ram(phys_intmem, NULL, "axisdev88.chipram", INTMEM_SIZE); + memory_region_init_ram(phys_intmem, "axisdev88.chipram", INTMEM_SIZE); + vmstate_register_ram_global(phys_intmem); memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem); /* Attach a NAND flash to CS1. */ diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c index 30146b9c9d..e3c574008f 100644 --- a/hw/dummy_m68k.c +++ b/hw/dummy_m68k.c @@ -40,7 +40,8 @@ static void dummy_m68k_init(ram_addr_t ram_size, env->vbr = 0; /* RAM at address zero */ - memory_region_init_ram(ram, NULL, "dummy_m68k.ram", ram_size); + memory_region_init_ram(ram, "dummy_m68k.ram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); /* Load kernel. */ diff --git a/hw/g364fb.c b/hw/g364fb.c index 34fb08c097..33ec149e0f 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -524,8 +524,9 @@ static void g364fb_init(DeviceState *dev, G364State *s) g364fb_screen_dump, NULL, s); memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000); - memory_region_init_ram_ptr(&s->mem_vram, dev, "vram", + memory_region_init_ram_ptr(&s->mem_vram, "vram", s->vram_size, s->vram); + vmstate_register_ram(&s->mem_vram, dev); memory_region_set_coalescing(&s->mem_vram); } @@ -949,4 +949,9 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id, int required_for_version); void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd, void *opaque); +struct MemoryRegion; +void vmstate_register_ram(struct MemoryRegion *memory, DeviceState *dev); +void vmstate_unregister_ram(struct MemoryRegion *memory, DeviceState *dev); +void vmstate_register_ram_global(struct MemoryRegion *memory); + #endif diff --git a/hw/integratorcp.c b/hw/integratorcp.c index 2551236d5c..c8f3955af8 100644 --- a/hw/integratorcp.c +++ b/hw/integratorcp.c @@ -261,7 +261,8 @@ static int integratorcm_init(SysBusDevice *dev) } memcpy(integrator_spd + 73, "QEMU-MEMORY", 11); s->cm_init = 0x00000112; - memory_region_init_ram(&s->flash, NULL, "integrator.flash", 0x100000); + memory_region_init_ram(&s->flash, "integrator.flash", 0x100000); + vmstate_register_ram_global(&s->flash); s->flash_mapped = false; memory_region_init_io(&s->iomem, &integratorcm_ops, s, @@ -471,7 +472,8 @@ static void integratorcp_init(ram_addr_t ram_size, fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } - memory_region_init_ram(ram, NULL, "integrator.ram", ram_size); + memory_region_init_ram(ram, "integrator.ram", ram_size); + vmstate_register_ram_global(ram); /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */ /* ??? RAM should repeat to fill physical memory space. */ /* SDRAM at address zero*/ diff --git a/hw/ivshmem.c b/hw/ivshmem.c index 7b4dbf66a9..1aa9e3bfa1 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -335,8 +335,9 @@ static void create_shared_memory_BAR(IVShmemState *s, int fd) { ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - memory_region_init_ram_ptr(&s->ivshmem, &s->dev.qdev, "ivshmem.bar2", + memory_region_init_ram_ptr(&s->ivshmem, "ivshmem.bar2", s->ivshmem_size, ptr); + vmstate_register_ram(&s->ivshmem, &s->dev.qdev); memory_region_add_subregion(&s->bar, 0, &s->ivshmem); /* region for shared memory */ @@ -451,8 +452,9 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags) /* mmap the region and map into the BAR2 */ map_ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, incoming_fd, 0); - memory_region_init_ram_ptr(&s->ivshmem, &s->dev.qdev, + memory_region_init_ram_ptr(&s->ivshmem, "ivshmem.bar2", s->ivshmem_size, map_ptr); + vmstate_register_ram(&s->ivshmem, &s->dev.qdev); IVSHMEM_DPRINTF("guest h/w addr = %" PRIu64 ", size = %" PRIu64 "\n", s->ivshmem_offset, s->ivshmem_size); @@ -753,6 +755,7 @@ static int pci_ivshmem_uninit(PCIDevice *dev) memory_region_destroy(&s->ivshmem_mmio); memory_region_del_subregion(&s->bar, &s->ivshmem); + vmstate_unregister_ram(&s->ivshmem, &s->dev.qdev); memory_region_destroy(&s->ivshmem); memory_region_destroy(&s->bar); unregister_savevm(&dev->qdev, "ivshmem", s); diff --git a/hw/leon3.c b/hw/leon3.c index 607ec852fe..e25bb046a7 100644 --- a/hw/leon3.c +++ b/hw/leon3.c @@ -142,12 +142,14 @@ static void leon3_generic_hw_init(ram_addr_t ram_size, exit(1); } - memory_region_init_ram(ram, NULL, "leon3.ram", ram_size); + memory_region_init_ram(ram, "leon3.ram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0x40000000, ram); /* Allocate BIOS */ prom_size = 8 * 1024 * 1024; /* 8Mb */ - memory_region_init_ram(prom, NULL, "Leon3.bios", prom_size); + memory_region_init_ram(prom, "Leon3.bios", prom_size); + vmstate_register_ram_global(prom); memory_region_set_readonly(prom, true); memory_region_add_subregion(address_space_mem, 0x00000000, prom); diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c index 97e1c001b9..3cdf120a14 100644 --- a/hw/lm32_boards.c +++ b/hw/lm32_boards.c @@ -106,7 +106,8 @@ static void lm32_evr_init(ram_addr_t ram_size_not_used, reset_info->flash_base = flash_base; - memory_region_init_ram(phys_ram, NULL, "lm32_evr.sdram", ram_size); + memory_region_init_ram(phys_ram, "lm32_evr.sdram", ram_size); + vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, ram_base, phys_ram); dinfo = drive_get(IF_PFLASH, 0, 0); @@ -200,7 +201,8 @@ static void lm32_uclinux_init(ram_addr_t ram_size_not_used, reset_info->flash_base = flash_base; - memory_region_init_ram(phys_ram, NULL, "lm32_uclinux.sdram", ram_size); + memory_region_init_ram(phys_ram, "lm32_uclinux.sdram", ram_size); + vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, ram_base, phys_ram); dinfo = drive_get(IF_PFLASH, 0, 0); diff --git a/hw/mainstone.c b/hw/mainstone.c index 3ed6649204..c914a4ef7d 100644 --- a/hw/mainstone.c +++ b/hw/mainstone.c @@ -111,7 +111,8 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, /* Setup CPU & memory */ cpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model); - memory_region_init_ram(rom, NULL, "mainstone.rom", MAINSTONE_ROM); + memory_region_init_ram(rom, "mainstone.rom", MAINSTONE_ROM); + vmstate_register_ram_global(rom); memory_region_set_readonly(rom, true); memory_region_add_subregion(address_space_mem, 0, rom); diff --git a/hw/mcf5208.c b/hw/mcf5208.c index ec608a1a38..3b0636dc2f 100644 --- a/hw/mcf5208.c +++ b/hw/mcf5208.c @@ -213,11 +213,13 @@ static void mcf5208evb_init(ram_addr_t ram_size, /* TODO: Configure BARs. */ /* DRAM at 0x40000000 */ - memory_region_init_ram(ram, NULL, "mcf5208.ram", ram_size); + memory_region_init_ram(ram, "mcf5208.ram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0x40000000, ram); /* Internal SRAM. */ - memory_region_init_ram(sram, NULL, "mcf5208.sram", 16384); + memory_region_init_ram(sram, "mcf5208.sram", 16384); + vmstate_register_ram_global(sram); memory_region_add_subregion(address_space_mem, 0x80000000, sram); /* Internal peripherals. */ diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c index b5e0dac116..7006d29788 100644 --- a/hw/milkymist-minimac2.c +++ b/hw/milkymist-minimac2.c @@ -468,8 +468,9 @@ static int milkymist_minimac2_init(SysBusDevice *dev) sysbus_init_mmio(dev, &s->regs_region); /* register buffers memory */ - memory_region_init_ram(&s->buffers, NULL, "milkymist-minimac2.buffers", + memory_region_init_ram(&s->buffers, "milkymist-minimac2.buffers", buffers_size); + vmstate_register_ram_global(&s->buffers); s->rx0_buf = memory_region_get_ram_ptr(&s->buffers); s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE; s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE; diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c index 6dd953ce9f..83bd1c4c6b 100644 --- a/hw/milkymist-softusb.c +++ b/hw/milkymist-softusb.c @@ -267,11 +267,13 @@ static int milkymist_softusb_init(SysBusDevice *dev) sysbus_init_mmio(dev, &s->regs_region); /* register pmem and dmem */ - memory_region_init_ram(&s->pmem, NULL, "milkymist-softusb.pmem", + memory_region_init_ram(&s->pmem, "milkymist-softusb.pmem", s->pmem_size); + vmstate_register_ram_global(&s->pmem); sysbus_add_memory(dev, s->pmem_base, &s->pmem); - memory_region_init_ram(&s->dmem, NULL, "milkymist-softusb.dmem", + memory_region_init_ram(&s->dmem, "milkymist-softusb.dmem", s->dmem_size); + vmstate_register_ram_global(&s->dmem); sysbus_add_memory(dev, s->dmem_base, &s->dmem); hid_init(&s->hid_kbd, HID_KEYBOARD, softusb_kbd_hid_datain); diff --git a/hw/milkymist.c b/hw/milkymist.c index b7a8c1c256..eaef0c24c3 100644 --- a/hw/milkymist.c +++ b/hw/milkymist.c @@ -110,7 +110,8 @@ milkymist_init(ram_addr_t ram_size_not_used, cpu_lm32_set_phys_msb_ignore(env, 1); - memory_region_init_ram(phys_sdram, NULL, "milkymist.sdram", sdram_size); + memory_region_init_ram(phys_sdram, "milkymist.sdram", sdram_size); + vmstate_register_ram_global(phys_sdram); memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram); dinfo = drive_get(IF_PFLASH, 0, 0); diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index 5e87665188..94ef1dfd37 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -291,8 +291,10 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device, bios_size = 1024 * 1024; /* allocate RAM */ - memory_region_init_ram(ram, NULL, "fulong2e.ram", ram_size); - memory_region_init_ram(bios, NULL, "fulong2e.bios", bios_size); + memory_region_init_ram(ram, "fulong2e.ram", ram_size); + vmstate_register_ram_global(ram); + memory_region_init_ram(bios, "fulong2e.bios", bios_size); + vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); memory_region_add_subregion(address_space_mem, 0, ram); diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index da0498201a..63165b9a38 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -146,10 +146,12 @@ static void mips_jazz_init(MemoryRegion *address_space, qemu_register_reset(main_cpu_reset, env); /* allocate RAM */ - memory_region_init_ram(ram, NULL, "mips_jazz.ram", ram_size); + memory_region_init_ram(ram, "mips_jazz.ram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(address_space, 0, ram); - memory_region_init_ram(bios, NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE); + memory_region_init_ram(bios, "mips_jazz.bios", MAGNUM_BIOS_SIZE); + vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); memory_region_init_alias(bios2, "mips_jazz.bios", bios, 0, MAGNUM_BIOS_SIZE); @@ -208,7 +210,8 @@ static void mips_jazz_init(MemoryRegion *address_space, { /* Simple ROM, so user doesn't have to provide one */ MemoryRegion *rom_mr = g_new(MemoryRegion, 1); - memory_region_init_ram(rom_mr, NULL, "g364fb.rom", 0x80000); + memory_region_init_ram(rom_mr, "g364fb.rom", 0x80000); + vmstate_register_ram_global(rom_mr); memory_region_set_readonly(rom_mr, true); uint8_t *rom = memory_region_get_ram_ptr(rom_mr); memory_region_add_subregion(address_space, 0x60000000, rom_mr); diff --git a/hw/mips_malta.c b/hw/mips_malta.c index d94ad1d8c1..6b72cf2508 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -826,7 +826,8 @@ void mips_malta_init (ram_addr_t ram_size, ((unsigned int)ram_size / (1 << 20))); exit(1); } - memory_region_init_ram(ram, NULL, "mips_malta.ram", ram_size); + memory_region_init_ram(ram, "mips_malta.ram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(system_memory, 0, ram); #ifdef TARGET_WORDS_BIGENDIAN @@ -841,7 +842,8 @@ void mips_malta_init (ram_addr_t ram_size, if (kernel_filename) { /* Write a small bootloader to the flash location. */ bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE); + memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE); + vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE); /* Map the bios at two physical locations, as on the real board. */ @@ -878,7 +880,8 @@ void mips_malta_init (ram_addr_t ram_size, fl_idx++; } else { bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE); + memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE); + vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE); diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c index b56cba619e..76c95b2ec0 100644 --- a/hw/mips_mipssim.c +++ b/hw/mips_mipssim.c @@ -163,8 +163,10 @@ mips_mipssim_init (ram_addr_t ram_size, qemu_register_reset(main_cpu_reset, reset_info); /* Allocate RAM. */ - memory_region_init_ram(ram, NULL, "mips_mipssim.ram", ram_size); - memory_region_init_ram(bios, NULL, "mips_mipssim.bios", BIOS_SIZE); + memory_region_init_ram(ram, "mips_mipssim.ram", ram_size); + vmstate_register_ram_global(ram); + memory_region_init_ram(bios, "mips_mipssim.bios", BIOS_SIZE); + vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); memory_region_add_subregion(address_space_mem, 0, ram); diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index c078078264..1c0615c1da 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -195,7 +195,8 @@ void mips_r4k_init (ram_addr_t ram_size, ((unsigned int)ram_size / (1 << 20))); exit(1); } - memory_region_init_ram(ram, NULL, "mips_r4k.ram", ram_size); + memory_region_init_ram(ram, "mips_r4k.ram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); @@ -221,7 +222,8 @@ void mips_r4k_init (ram_addr_t ram_size, #endif if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) { bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE); + memory_region_init_ram(bios, "mips_r4k.bios", BIOS_SIZE); + vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios); diff --git a/hw/musicpal.c b/hw/musicpal.c index 3c6cefe908..a01e3d2d92 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -1472,10 +1472,12 @@ static void musicpal_init(ram_addr_t ram_size, cpu_pic = arm_pic_init_cpu(env); /* For now we use a fixed - the original - RAM size */ - memory_region_init_ram(ram, NULL, "musicpal.ram", MP_RAM_DEFAULT_SIZE); + memory_region_init_ram(ram, "musicpal.ram", MP_RAM_DEFAULT_SIZE); + vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); - memory_region_init_ram(sram, NULL, "musicpal.sram", MP_SRAM_SIZE); + memory_region_init_ram(sram, "musicpal.sram", MP_SRAM_SIZE); + vmstate_register_ram_global(sram); memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram); dev = sysbus_create_simple("mv88w8618_pic", MP_PIC_BASE, @@ -672,10 +672,6 @@ void omap_uart_reset(struct omap_uart_s *s); void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr); struct omap_mpuio_s; -struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *system_memory, - target_phys_addr_t base, - qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup, - omap_clk clk); qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s); void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler); void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down); @@ -833,8 +829,6 @@ struct omap_mpu_state_s { MemoryRegion tcmi_iomem; MemoryRegion clkm_iomem; MemoryRegion clkdsp_iomem; - MemoryRegion pwl_iomem; - MemoryRegion pwt_iomem; MemoryRegion mpui_io_iomem; MemoryRegion tap_iomem; MemoryRegion imif_ram; @@ -871,20 +865,8 @@ struct omap_mpu_state_s { struct omap_uwire_s *microwire; - struct { - uint8_t output; - uint8_t level; - uint8_t enable; - int clk; - } pwl; - - struct { - uint8_t frc; - uint8_t vrc; - uint8_t gcr; - omap_clk clk; - } pwt; - + struct omap_pwl_s *pwl; + struct omap_pwt_s *pwt; struct omap_i2c_s *i2c[2]; struct omap_rtc_s *rtc; @@ -922,11 +904,7 @@ struct omap_mpu_state_s { uint32_t tcmi_regs[17]; - struct dpll_ctl_s { - MemoryRegion iomem; - uint16_t mode; - omap_clk dpll; - } dpll[3]; + struct dpll_ctl_s *dpll[3]; omap_clk clks; struct { diff --git a/hw/omap1.c b/hw/omap1.c index 53cde76116..1aa5f2388b 100644 --- a/hw/omap1.c +++ b/hw/omap1.c @@ -20,11 +20,7 @@ #include "arm-misc.h" #include "omap.h" #include "sysemu.h" -#include "qemu-timer.h" -#include "qemu-char.h" #include "soc_dma.h" -/* We use pc-style serial ports. */ -#include "pc.h" #include "blockdev.h" #include "range.h" #include "sysbus.h" @@ -1344,6 +1340,12 @@ static void omap_tcmi_init(MemoryRegion *memory, target_phys_addr_t base, } /* Digital phase-locked loops control */ +struct dpll_ctl_s { + MemoryRegion iomem; + uint16_t mode; + omap_clk dpll; +}; + static uint64_t omap_dpll_read(void *opaque, target_phys_addr_t addr, unsigned size) { @@ -1409,15 +1411,17 @@ static void omap_dpll_reset(struct dpll_ctl_s *s) omap_clk_setrate(s->dpll, 1, 1); } -static void omap_dpll_init(MemoryRegion *memory, struct dpll_ctl_s *s, +static struct dpll_ctl_s *omap_dpll_init(MemoryRegion *memory, target_phys_addr_t base, omap_clk clk) { + struct dpll_ctl_s *s = g_malloc0(sizeof(*s)); memory_region_init_io(&s->iomem, &omap_dpll_ops, s, "omap-dpll", 0x100); s->dpll = clk; omap_dpll_reset(s); memory_region_add_subregion(memory, base, &s->iomem); + return s; } /* MPU Clock/Reset/Power Mode Control */ @@ -2066,7 +2070,7 @@ static void omap_mpuio_onoff(void *opaque, int line, int on) omap_mpuio_kbd_update(s); } -struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory, +static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory, target_phys_addr_t base, qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup, omap_clk clk) @@ -2289,12 +2293,20 @@ void omap_uwire_attach(struct omap_uwire_s *s, } /* Pseudonoise Pulse-Width Light Modulator */ -static void omap_pwl_update(struct omap_mpu_state_s *s) +struct omap_pwl_s { + MemoryRegion iomem; + uint8_t output; + uint8_t level; + uint8_t enable; + int clk; +}; + +static void omap_pwl_update(struct omap_pwl_s *s) { - int output = (s->pwl.clk && s->pwl.enable) ? s->pwl.level : 0; + int output = (s->clk && s->enable) ? s->level : 0; - if (output != s->pwl.output) { - s->pwl.output = output; + if (output != s->output) { + s->output = output; printf("%s: Backlight now at %i/256\n", __FUNCTION__, output); } } @@ -2302,7 +2314,7 @@ static void omap_pwl_update(struct omap_mpu_state_s *s) static uint64_t omap_pwl_read(void *opaque, target_phys_addr_t addr, unsigned size) { - struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; + struct omap_pwl_s *s = (struct omap_pwl_s *) opaque; int offset = addr & OMAP_MPUI_REG_MASK; if (size != 1) { @@ -2311,9 +2323,9 @@ static uint64_t omap_pwl_read(void *opaque, target_phys_addr_t addr, switch (offset) { case 0x00: /* PWL_LEVEL */ - return s->pwl.level; + return s->level; case 0x04: /* PWL_CTRL */ - return s->pwl.enable; + return s->enable; } OMAP_BAD_REG(addr); return 0; @@ -2322,7 +2334,7 @@ static uint64_t omap_pwl_read(void *opaque, target_phys_addr_t addr, static void omap_pwl_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { - struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; + struct omap_pwl_s *s = (struct omap_pwl_s *) opaque; int offset = addr & OMAP_MPUI_REG_MASK; if (size != 1) { @@ -2331,11 +2343,11 @@ static void omap_pwl_write(void *opaque, target_phys_addr_t addr, switch (offset) { case 0x00: /* PWL_LEVEL */ - s->pwl.level = value; + s->level = value; omap_pwl_update(s); break; case 0x04: /* PWL_CTRL */ - s->pwl.enable = value & 1; + s->enable = value & 1; omap_pwl_update(s); break; default: @@ -2350,41 +2362,52 @@ static const MemoryRegionOps omap_pwl_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void omap_pwl_reset(struct omap_mpu_state_s *s) +static void omap_pwl_reset(struct omap_pwl_s *s) { - s->pwl.output = 0; - s->pwl.level = 0; - s->pwl.enable = 0; - s->pwl.clk = 1; + s->output = 0; + s->level = 0; + s->enable = 0; + s->clk = 1; omap_pwl_update(s); } static void omap_pwl_clk_update(void *opaque, int line, int on) { - struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; + struct omap_pwl_s *s = (struct omap_pwl_s *) opaque; - s->pwl.clk = on; + s->clk = on; omap_pwl_update(s); } -static void omap_pwl_init(MemoryRegion *system_memory, - target_phys_addr_t base, struct omap_mpu_state_s *s, - omap_clk clk) +static struct omap_pwl_s *omap_pwl_init(MemoryRegion *system_memory, + target_phys_addr_t base, + omap_clk clk) { + struct omap_pwl_s *s = g_malloc0(sizeof(*s)); + omap_pwl_reset(s); - memory_region_init_io(&s->pwl_iomem, &omap_pwl_ops, s, + memory_region_init_io(&s->iomem, &omap_pwl_ops, s, "omap-pwl", 0x800); - memory_region_add_subregion(system_memory, base, &s->pwl_iomem); + memory_region_add_subregion(system_memory, base, &s->iomem); omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]); + return s; } /* Pulse-Width Tone module */ +struct omap_pwt_s { + MemoryRegion iomem; + uint8_t frc; + uint8_t vrc; + uint8_t gcr; + omap_clk clk; +}; + static uint64_t omap_pwt_read(void *opaque, target_phys_addr_t addr, unsigned size) { - struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; + struct omap_pwt_s *s = (struct omap_pwt_s *) opaque; int offset = addr & OMAP_MPUI_REG_MASK; if (size != 1) { @@ -2393,11 +2416,11 @@ static uint64_t omap_pwt_read(void *opaque, target_phys_addr_t addr, switch (offset) { case 0x00: /* FRC */ - return s->pwt.frc; + return s->frc; case 0x04: /* VCR */ - return s->pwt.vrc; + return s->vrc; case 0x08: /* GCR */ - return s->pwt.gcr; + return s->gcr; } OMAP_BAD_REG(addr); return 0; @@ -2406,7 +2429,7 @@ static uint64_t omap_pwt_read(void *opaque, target_phys_addr_t addr, static void omap_pwt_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { - struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; + struct omap_pwt_s *s = (struct omap_pwt_s *) opaque; int offset = addr & OMAP_MPUI_REG_MASK; if (size != 1) { @@ -2415,16 +2438,16 @@ static void omap_pwt_write(void *opaque, target_phys_addr_t addr, switch (offset) { case 0x00: /* FRC */ - s->pwt.frc = value & 0x3f; + s->frc = value & 0x3f; break; case 0x04: /* VRC */ - if ((value ^ s->pwt.vrc) & 1) { + if ((value ^ s->vrc) & 1) { if (value & 1) printf("%s: %iHz buzz on\n", __FUNCTION__, (int) /* 1.5 MHz from a 12-MHz or 13-MHz PWT_CLK */ - ((omap_clk_getrate(s->pwt.clk) >> 3) / + ((omap_clk_getrate(s->clk) >> 3) / /* Pre-multiplexer divider */ - ((s->pwt.gcr & 2) ? 1 : 154) / + ((s->gcr & 2) ? 1 : 154) / /* Octave multiplexer */ (2 << (value & 3)) * /* 101/107 divider */ @@ -2439,10 +2462,10 @@ static void omap_pwt_write(void *opaque, target_phys_addr_t addr, else printf("%s: silence!\n", __FUNCTION__); } - s->pwt.vrc = value & 0x7f; + s->vrc = value & 0x7f; break; case 0x08: /* GCR */ - s->pwt.gcr = value & 3; + s->gcr = value & 3; break; default: OMAP_BAD_REG(addr); @@ -2456,23 +2479,25 @@ static const MemoryRegionOps omap_pwt_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void omap_pwt_reset(struct omap_mpu_state_s *s) +static void omap_pwt_reset(struct omap_pwt_s *s) { - s->pwt.frc = 0; - s->pwt.vrc = 0; - s->pwt.gcr = 0; + s->frc = 0; + s->vrc = 0; + s->gcr = 0; } -static void omap_pwt_init(MemoryRegion *system_memory, - target_phys_addr_t base, struct omap_mpu_state_s *s, - omap_clk clk) +static struct omap_pwt_s *omap_pwt_init(MemoryRegion *system_memory, + target_phys_addr_t base, + omap_clk clk) { - s->pwt.clk = clk; + struct omap_pwt_s *s = g_malloc0(sizeof(*s)); + s->clk = clk; omap_pwt_reset(s); - memory_region_init_io(&s->pwt_iomem, &omap_pwt_ops, s, + memory_region_init_io(&s->iomem, &omap_pwt_ops, s, "omap-pwt", 0x800); - memory_region_add_subregion(system_memory, base, &s->pwt_iomem); + memory_region_add_subregion(system_memory, base, &s->iomem); + return s; } /* Real-time Clock module */ @@ -3658,17 +3683,17 @@ static void omap1_mpu_reset(void *opaque) omap_mpui_reset(mpu); omap_tipb_bridge_reset(mpu->private_tipb); omap_tipb_bridge_reset(mpu->public_tipb); - omap_dpll_reset(&mpu->dpll[0]); - omap_dpll_reset(&mpu->dpll[1]); - omap_dpll_reset(&mpu->dpll[2]); + omap_dpll_reset(mpu->dpll[0]); + omap_dpll_reset(mpu->dpll[1]); + omap_dpll_reset(mpu->dpll[2]); omap_uart_reset(mpu->uart[0]); omap_uart_reset(mpu->uart[1]); omap_uart_reset(mpu->uart[2]); omap_mmc_reset(mpu->mmc); omap_mpuio_reset(mpu->mpuio); omap_uwire_reset(mpu->microwire); - omap_pwl_reset(mpu); - omap_pwt_reset(mpu); + omap_pwl_reset(mpu->pwl); + omap_pwt_reset(mpu->pwt); omap_i2c_reset(mpu->i2c[0]); omap_rtc_reset(mpu->rtc); omap_mcbsp_reset(mpu->mcbsp1); @@ -3819,9 +3844,11 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, omap_clk_init(s); /* Memory-mapped stuff */ - memory_region_init_ram(&s->emiff_ram, NULL, "omap1.dram", s->sdram_size); + memory_region_init_ram(&s->emiff_ram, "omap1.dram", s->sdram_size); + vmstate_register_ram_global(&s->emiff_ram); memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram); - memory_region_init_ram(&s->imif_ram, NULL, "omap1.sram", s->sram_size); + memory_region_init_ram(&s->imif_ram, "omap1.sram", s->sram_size); + vmstate_register_ram_global(&s->imif_ram); memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram); omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s); @@ -3926,12 +3953,12 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, "uart3", serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL); - omap_dpll_init(system_memory, - &s->dpll[0], 0xfffecf00, omap_findclk(s, "dpll1")); - omap_dpll_init(system_memory, - &s->dpll[1], 0xfffed000, omap_findclk(s, "dpll2")); - omap_dpll_init(system_memory, - &s->dpll[2], 0xfffed100, omap_findclk(s, "dpll3")); + s->dpll[0] = omap_dpll_init(system_memory, 0xfffecf00, + omap_findclk(s, "dpll1")); + s->dpll[1] = omap_dpll_init(system_memory, 0xfffed000, + omap_findclk(s, "dpll2")); + s->dpll[2] = omap_dpll_init(system_memory, 0xfffed100, + omap_findclk(s, "dpll3")); dinfo = drive_get(IF_SD, 0, 0); if (!dinfo) { @@ -3961,8 +3988,10 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireRX), s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck")); - omap_pwl_init(system_memory, 0xfffb5800, s, omap_findclk(s, "armxor_ck")); - omap_pwt_init(system_memory, 0xfffb6000, s, omap_findclk(s, "armxor_ck")); + s->pwl = omap_pwl_init(system_memory, 0xfffb5800, + omap_findclk(s, "armxor_ck")); + s->pwt = omap_pwt_init(system_memory, 0xfffb6000, + omap_findclk(s, "armxor_ck")); s->i2c[0] = omap_i2c_init(system_memory, 0xfffb3800, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C), diff --git a/hw/omap2.c b/hw/omap2.c index c09c04a50f..a6851b0fb0 100644 --- a/hw/omap2.c +++ b/hw/omap2.c @@ -2269,9 +2269,11 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem, omap_clk_init(s); /* Memory-mapped stuff */ - memory_region_init_ram(&s->sdram, NULL, "omap2.dram", s->sdram_size); + memory_region_init_ram(&s->sdram, "omap2.dram", s->sdram_size); + vmstate_register_ram_global(&s->sdram); memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram); - memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size); + memory_region_init_ram(&s->sram, "omap2.sram", s->sram_size); + vmstate_register_ram_global(&s->sram); memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram); s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54); diff --git a/hw/omap_gpmc.c b/hw/omap_gpmc.c index 414f9f5c37..2fc4137203 100644 --- a/hw/omap_gpmc.c +++ b/hw/omap_gpmc.c @@ -443,6 +443,12 @@ void omap_gpmc_reset(struct omap_gpmc_s *s) s->irqst = 0; s->irqen = 0; omap_gpmc_int_update(s); + for (i = 0; i < 8; i++) { + /* This has to happen before we change any of the config + * used to determine which memory regions are mapped or unmapped. + */ + omap_gpmc_cs_unmap(s, i); + } s->timeout = 0; s->config = 0xa00; s->prefetch.config1 = 0x00004000; @@ -451,7 +457,6 @@ void omap_gpmc_reset(struct omap_gpmc_s *s) s->prefetch.fifopointer = 0; s->prefetch.count = 0; for (i = 0; i < 8; i ++) { - omap_gpmc_cs_unmap(s, i); s->cs_file[i].config[1] = 0x101001; s->cs_file[i].config[2] = 0x020201; s->cs_file[i].config[3] = 0x10031003; @@ -716,24 +721,31 @@ static void omap_gpmc_write(void *opaque, target_phys_addr_t addr, case 0x1e0: /* GPMC_PREFETCH_CONFIG1 */ if (!s->prefetch.startengine) { - uint32_t oldconfig1 = s->prefetch.config1; + uint32_t newconfig1 = value & 0x7f8f7fbf; uint32_t changed; - s->prefetch.config1 = value & 0x7f8f7fbf; - changed = oldconfig1 ^ s->prefetch.config1; + changed = newconfig1 ^ s->prefetch.config1; if (changed & (0x80 | 0x7000000)) { /* Turning the engine on or off, or mapping it somewhere else. * cs_map() and cs_unmap() check the prefetch config and * overall CSVALID bits, so it is sufficient to unmap-and-map - * both the old cs and the new one. + * both the old cs and the new one. Note that we adhere to + * the "unmap/change config/map" order (and not unmap twice + * if newcs == oldcs), otherwise we'll try to delete the wrong + * memory region. */ - int oldcs = prefetch_cs(oldconfig1); - int newcs = prefetch_cs(s->prefetch.config1); + int oldcs = prefetch_cs(s->prefetch.config1); + int newcs = prefetch_cs(newconfig1); omap_gpmc_cs_unmap(s, oldcs); - omap_gpmc_cs_map(s, oldcs); - if (newcs != oldcs) { + if (oldcs != newcs) { omap_gpmc_cs_unmap(s, newcs); + } + s->prefetch.config1 = newconfig1; + omap_gpmc_cs_map(s, oldcs); + if (oldcs != newcs) { omap_gpmc_cs_map(s, newcs); } + } else { + s->prefetch.config1 = newconfig1; } } break; diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c index 8e58645dc0..4e8ec4a990 100644 --- a/hw/omap_sx1.c +++ b/hw/omap_sx1.c @@ -124,7 +124,8 @@ static void sx1_init(ram_addr_t ram_size, cpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, cpu_model); /* External Flash (EMIFS) */ - memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size); + memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size); + vmstate_register_ram_global(flash); memory_region_set_readonly(flash, true); memory_region_add_subregion(address_space, OMAP_CS0_BASE, flash); @@ -165,7 +166,8 @@ static void sx1_init(ram_addr_t ram_size, if ((version == 1) && (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) { - memory_region_init_ram(flash_1, NULL, "omap_sx1.flash1-0", flash1_size); + memory_region_init_ram(flash_1, "omap_sx1.flash1-0", flash1_size); + vmstate_register_ram_global(flash_1); memory_region_set_readonly(flash_1, true); memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1); diff --git a/hw/onenand.c b/hw/onenand.c index a9d8d677ee..33c9718629 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -781,7 +781,8 @@ static int onenand_initfn(SysBusDevice *dev) } s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT), 0xff, (64 + 2) << PAGE_SHIFT); - memory_region_init_ram(&s->ram, NULL, "onenand.ram", 0xc000 << s->shift); + memory_region_init_ram(&s->ram, "onenand.ram", 0xc000 << s->shift); + vmstate_register_ram_global(&s->ram); ram = memory_region_get_ram_ptr(&s->ram); s->boot[0] = ram + (0x0000 << s->shift); s->boot[1] = ram + (0x8000 << s->shift); @@ -211,7 +211,8 @@ static void palmte_init(ram_addr_t ram_size, cpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model); /* External Flash (EMIFS) */ - memory_region_init_ram(flash, NULL, "palmte.flash", flash_size); + memory_region_init_ram(flash, "palmte.flash", flash_size); + vmstate_register_ram_global(flash); memory_region_set_readonly(flash, true); memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash); @@ -987,8 +987,9 @@ void pc_memory_init(MemoryRegion *system_memory, * with older qemus that used qemu_ram_alloc(). */ ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, NULL, "pc.ram", + memory_region_init_ram(ram, "pc.ram", below_4g_mem_size + above_4g_mem_size); + vmstate_register_ram_global(ram); *ram_memory = ram; ram_below_4g = g_malloc(sizeof(*ram_below_4g)); memory_region_init_alias(ram_below_4g, "ram-below-4g", ram, @@ -1016,7 +1017,8 @@ void pc_memory_init(MemoryRegion *system_memory, goto bios_error; } bios = g_malloc(sizeof(*bios)); - memory_region_init_ram(bios, NULL, "pc.bios", bios_size); + memory_region_init_ram(bios, "pc.bios", bios_size); + vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1); if (ret != 0) { @@ -1041,7 +1043,8 @@ void pc_memory_init(MemoryRegion *system_memory, memory_region_set_readonly(isa_bios, true); option_rom_mr = g_malloc(sizeof(*option_rom_mr)); - memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE); + memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE); + vmstate_register_ram_global(option_rom_mr); memory_region_add_subregion_overlap(rom_memory, PC_ROM_MIN_VGA, option_rom_mr, @@ -1765,7 +1765,8 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) else snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->name); pdev->has_rom = true; - memory_region_init_ram(&pdev->rom, &pdev->qdev, name, size); + memory_region_init_ram(&pdev->rom, name, size); + vmstate_register_ram(&pdev->rom, &pdev->qdev); ptr = memory_region_get_ram_ptr(&pdev->rom); load_image(path, ptr); g_free(path); @@ -1787,6 +1788,7 @@ static void pci_del_option_rom(PCIDevice *pdev) if (!pdev->has_rom) return; + vmstate_unregister_ram(&pdev->rom, &pdev->qdev); memory_region_destroy(&pdev->rom); pdev->has_rom = false; } diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c index fb4ba29bf8..98978f89b6 100644 --- a/hw/petalogix_ml605_mmu.c +++ b/hw/petalogix_ml605_mmu.c @@ -162,11 +162,13 @@ petalogix_ml605_init(ram_addr_t ram_size, qemu_register_reset(main_cpu_reset, env); /* Attach emulated BRAM through the LMB. */ - memory_region_init_ram(phys_lmb_bram, NULL, "petalogix_ml605.lmb_bram", + memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram", LMB_BRAM_SIZE); + vmstate_register_ram_global(phys_lmb_bram); memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram); - memory_region_init_ram(phys_ram, NULL, "petalogix_ml605.ram", ram_size); + memory_region_init_ram(phys_ram, "petalogix_ml605.ram", ram_size); + vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, ddr_base, phys_ram); dinfo = drive_get(IF_PFLASH, 0, 0); diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c index 17da2fd87c..d448a41f68 100644 --- a/hw/petalogix_s3adsp1800_mmu.c +++ b/hw/petalogix_s3adsp1800_mmu.c @@ -141,12 +141,13 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size, qemu_register_reset(main_cpu_reset, env); /* Attach emulated BRAM through the LMB. */ - memory_region_init_ram(phys_lmb_bram, NULL, + memory_region_init_ram(phys_lmb_bram, "petalogix_s3adsp1800.lmb_bram", LMB_BRAM_SIZE); + vmstate_register_ram_global(phys_lmb_bram); memory_region_add_subregion(sysmem, 0x00000000, phys_lmb_bram); - memory_region_init_ram(phys_ram, NULL, "petalogix_s3adsp1800.ram", - ram_size); + memory_region_init_ram(phys_ram, "petalogix_s3adsp1800.ram", ram_size); + vmstate_register_ram_global(phys_ram); memory_region_add_subregion(sysmem, ddr_base, phys_ram); dinfo = drive_get(IF_PFLASH, 0, 0); diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 69b8e3d539..ee0c3baab1 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -589,7 +589,8 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, memory_region_init_rom_device( &pfl->mem, be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl, - qdev, name, size); + name, size); + vmstate_register_ram(&pfl->mem, qdev); pfl->storage = memory_region_get_ram_ptr(&pfl->mem); memory_region_add_subregion(get_system_memory(), base, &pfl->mem); @@ -599,6 +600,7 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9); if (ret < 0) { memory_region_del_subregion(get_system_memory(), &pfl->mem); + vmstate_unregister_ram(&pfl->mem, qdev); memory_region_destroy(&pfl->mem); g_free(pfl); return NULL; diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c index e5a63da595..a9e88b9b3c 100644 --- a/hw/pflash_cfi02.c +++ b/hw/pflash_cfi02.c @@ -628,7 +628,8 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, pfl = g_malloc0(sizeof(pflash_t)); memory_region_init_rom_device( &pfl->orig_mem, be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, pfl, - qdev, name, size); + name, size); + vmstate_register_ram(&pfl->orig_mem, qdev); pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem); pfl->base = base; pfl->chip_len = chip_len; diff --git a/hw/pl110.c b/hw/pl110.c index 303a9bcdbd..0e1f415aeb 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -60,10 +60,13 @@ typedef struct { qemu_irq irq; } pl110_state; +static int vmstate_pl110_post_load(void *opaque, int version_id); + static const VMStateDescription vmstate_pl110 = { .name = "pl110", .version_id = 2, .minimum_version_id = 1, + .post_load = vmstate_pl110_post_load, .fields = (VMStateField[]) { VMSTATE_INT32(version, pl110_state), VMSTATE_UINT32_ARRAY(timing, pl110_state, 4), @@ -430,6 +433,14 @@ static void pl110_mux_ctrl_set(void *opaque, int line, int level) s->mux_ctrl = level; } +static int vmstate_pl110_post_load(void *opaque, int version_id) +{ + pl110_state *s = opaque; + /* Make sure we redraw, and at the right size */ + pl110_invalidate_display(s); + return 0; +} + static int pl110_init(SysBusDevice *dev) { pl110_state *s = FROM_SYSBUS(pl110_state, dev); diff --git a/hw/pl181.c b/hw/pl181.c index d05bc191be..b79aa418fa 100644 --- a/hw/pl181.c +++ b/hw/pl181.c @@ -38,20 +38,45 @@ typedef struct { uint32_t datacnt; uint32_t status; uint32_t mask[2]; - int fifo_pos; - int fifo_len; + int32_t fifo_pos; + int32_t fifo_len; /* The linux 2.6.21 driver is buggy, and misbehaves if new data arrives while it is reading the FIFO. We hack around this be defering subsequent transfers until after the driver polls the status word. http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4446/1 */ - int linux_hack; + int32_t linux_hack; uint32_t fifo[PL181_FIFO_LEN]; qemu_irq irq[2]; /* GPIO outputs for 'card is readonly' and 'card inserted' */ qemu_irq cardstatus[2]; } pl181_state; +static const VMStateDescription vmstate_pl181 = { + .name = "pl181", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(clock, pl181_state), + VMSTATE_UINT32(power, pl181_state), + VMSTATE_UINT32(cmdarg, pl181_state), + VMSTATE_UINT32(cmd, pl181_state), + VMSTATE_UINT32(datatimer, pl181_state), + VMSTATE_UINT32(datalength, pl181_state), + VMSTATE_UINT32(respcmd, pl181_state), + VMSTATE_UINT32_ARRAY(response, pl181_state, 4), + VMSTATE_UINT32(datactrl, pl181_state), + VMSTATE_UINT32(datacnt, pl181_state), + VMSTATE_UINT32(status, pl181_state), + VMSTATE_UINT32_ARRAY(mask, pl181_state, 2), + VMSTATE_INT32(fifo_pos, pl181_state), + VMSTATE_INT32(fifo_len, pl181_state), + VMSTATE_INT32(linux_hack, pl181_state), + VMSTATE_UINT32_ARRAY(fifo, pl181_state, PL181_FIFO_LEN), + VMSTATE_END_OF_LIST() + } +}; + #define PL181_CMD_INDEX 0x3f #define PL181_CMD_RESPONSE (1 << 6) #define PL181_CMD_LONGRESP (1 << 7) @@ -420,9 +445,9 @@ static const MemoryRegionOps pl181_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void pl181_reset(void *opaque) +static void pl181_reset(DeviceState *d) { - pl181_state *s = (pl181_state *)opaque; + pl181_state *s = DO_UPCAST(pl181_state, busdev.qdev, d); s->power = 0; s->cmdarg = 0; @@ -459,15 +484,21 @@ static int pl181_init(SysBusDevice *dev) qdev_init_gpio_out(&s->busdev.qdev, s->cardstatus, 2); dinfo = drive_get_next(IF_SD); s->card = sd_init(dinfo ? dinfo->bdrv : NULL, 0); - qemu_register_reset(pl181_reset, s); - pl181_reset(s); - /* ??? Save/restore. */ return 0; } +static SysBusDeviceInfo pl181_info = { + .init = pl181_init, + .qdev.name = "pl181", + .qdev.size = sizeof(pl181_state), + .qdev.vmsd = &vmstate_pl181, + .qdev.reset = pl181_reset, + .qdev.no_user = 1, +}; + static void pl181_register_devices(void) { - sysbus_register_dev("pl181", sizeof(pl181_state), pl181_init); + sysbus_register_withprop(&pl181_info); } device_init(pl181_register_devices) diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c index 672e9347ac..476775d05b 100644 --- a/hw/ppc405_boards.c +++ b/hw/ppc405_boards.c @@ -198,7 +198,8 @@ static void ref405ep_init (ram_addr_t ram_size, MemoryRegion *sysmem = get_system_memory(); /* XXX: fix this */ - memory_region_init_ram(&ram_memories[0], NULL, "ef405ep.ram", 0x08000000); + memory_region_init_ram(&ram_memories[0], "ef405ep.ram", 0x08000000); + vmstate_register_ram_global(&ram_memories[0]); ram_bases[0] = 0; ram_sizes[0] = 0x08000000; memory_region_init(&ram_memories[1], "ef405ep.ram1", 0); @@ -212,7 +213,8 @@ static void ref405ep_init (ram_addr_t ram_size, 33333333, &pic, kernel_filename == NULL ? 0 : 1); /* allocate SRAM */ sram_size = 512 * 1024; - memory_region_init_ram(sram, NULL, "ef405ep.sram", sram_size); + memory_region_init_ram(sram, "ef405ep.sram", sram_size); + vmstate_register_ram_global(sram); memory_region_add_subregion(sysmem, 0xFFF00000, sram); /* allocate and load BIOS */ #ifdef DEBUG_BOARD_INIT @@ -243,7 +245,8 @@ static void ref405ep_init (ram_addr_t ram_size, printf("Load BIOS from file\n"); #endif bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE); + memory_region_init_ram(bios, "ef405ep.bios", BIOS_SIZE); + vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = BIOS_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); @@ -513,12 +516,14 @@ static void taihu_405ep_init(ram_addr_t ram_size, DriveInfo *dinfo; /* RAM is soldered to the board so the size cannot be changed */ - memory_region_init_ram(&ram_memories[0], NULL, + memory_region_init_ram(&ram_memories[0], "taihu_405ep.ram-0", 0x04000000); + vmstate_register_ram_global(&ram_memories[0]); ram_bases[0] = 0; ram_sizes[0] = 0x04000000; - memory_region_init_ram(&ram_memories[1], NULL, + memory_region_init_ram(&ram_memories[1], "taihu_405ep.ram-1", 0x04000000); + vmstate_register_ram_global(&ram_memories[1]); ram_bases[1] = 0x04000000; ram_sizes[1] = 0x04000000; ram_size = 0x08000000; @@ -560,7 +565,8 @@ static void taihu_405ep_init(ram_addr_t ram_size, if (bios_name == NULL) bios_name = BIOS_FILENAME; bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE); + memory_region_init_ram(bios, "taihu_405ep.bios", BIOS_SIZE); + vmstate_register_ram_global(bios); filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { bios_size = load_image(filename, memory_region_get_ram_ptr(bios)); diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index a6e7431882..98079fa23f 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -966,7 +966,8 @@ static void ppc405_ocm_init(CPUState *env) ocm = g_malloc0(sizeof(ppc405_ocm_t)); /* XXX: Size is 4096 or 0x04000000 */ - memory_region_init_ram(&ocm->isarc_ram, NULL, "ppc405.ocm", 4096); + memory_region_init_ram(&ocm->isarc_ram, "ppc405.ocm", 4096); + vmstate_register_ram_global(&ocm->isarc_ram); memory_region_init_alias(&ocm->dsarc_ram, "ppc405.dsarc", &ocm->isarc_ram, 0, 4096); qemu_register_reset(&ocm_reset, ocm); diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c index d18caa4192..26040ac3ad 100644 --- a/hw/ppc4xx_devs.c +++ b/hw/ppc4xx_devs.c @@ -686,7 +686,8 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks, if (bank_size <= size_left) { char name[32]; snprintf(name, sizeof(name), "ppc4xx.sdram%d", i); - memory_region_init_ram(&ram_memories[i], NULL, name, bank_size); + memory_region_init_ram(&ram_memories[i], name, bank_size); + vmstate_register_ram_global(&ram_memories[i]); ram_bases[i] = base; ram_sizes[i] = bank_size; base += ram_size; diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 8c84f9e9a5..a746c9c3c6 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -171,11 +171,13 @@ static void ppc_core99_init (ram_addr_t ram_size, } /* allocate RAM */ - memory_region_init_ram(ram, NULL, "ppc_core99.ram", ram_size); + memory_region_init_ram(ram, "ppc_core99.ram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(get_system_memory(), 0, ram); /* allocate and load BIOS */ - memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE); + memory_region_init_ram(bios, "ppc_core99.bios", BIOS_SIZE); + vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index aac3526f55..9295a34f59 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -116,11 +116,13 @@ static void ppc_heathrow_init (ram_addr_t ram_size, exit(1); } - memory_region_init_ram(ram, NULL, "ppc_heathrow.ram", ram_size); + memory_region_init_ram(ram, "ppc_heathrow.ram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); /* allocate and load BIOS */ - memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE); + memory_region_init_ram(bios, "ppc_heathrow.bios", BIOS_SIZE); + vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index a7d73bfcc7..47dab3f184 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -554,11 +554,13 @@ static void ppc_prep_init (ram_addr_t ram_size, } /* allocate RAM */ - memory_region_init_ram(ram, NULL, "ppc_prep.ram", ram_size); + memory_region_init_ram(ram, "ppc_prep.ram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); /* allocate and load BIOS */ - memory_region_init_ram(bios, NULL, "ppc_prep.bios", BIOS_SIZE); + memory_region_init_ram(bios, "ppc_prep.bios", BIOS_SIZE); + vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = BIOS_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 51b6abddd3..d69f78cf33 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -292,7 +292,8 @@ static void mpc8544ds_init(ram_addr_t ram_size, ram_size &= ~(RAM_SIZES_ALIGN - 1); /* Register Memory */ - memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size); + memory_region_init_ram(ram, "mpc8544ds.ram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); /* MPIC */ diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index bd177b76d4..6ddd5005de 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -2046,9 +2046,11 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space, s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0]; /* SDRAM & Internal Memory Storage */ - memory_region_init_ram(&s->sdram, NULL, "pxa270.sdram", sdram_size); + memory_region_init_ram(&s->sdram, "pxa270.sdram", sdram_size); + vmstate_register_ram_global(&s->sdram); memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram); - memory_region_init_ram(&s->internal, NULL, "pxa270.internal", 0x40000); + memory_region_init_ram(&s->internal, "pxa270.internal", 0x40000); + vmstate_register_ram_global(&s->internal); memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE, &s->internal); @@ -2175,10 +2177,12 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size) s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0]; /* SDRAM & Internal Memory Storage */ - memory_region_init_ram(&s->sdram, NULL, "pxa255.sdram", sdram_size); + memory_region_init_ram(&s->sdram, "pxa255.sdram", sdram_size); + vmstate_register_ram_global(&s->sdram); memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram); - memory_region_init_ram(&s->internal, NULL, "pxa255.internal", + memory_region_init_ram(&s->internal, "pxa255.internal", PXA2XX_INTERNAL_SIZE); + vmstate_register_ram_global(&s->internal); memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE, &s->internal); @@ -1554,8 +1554,8 @@ static int qxl_init_common(PCIQXLDevice *qxl) pci_set_byte(&config[PCI_INTERRUPT_PIN], 1); qxl->rom_size = qxl_rom_size(); - memory_region_init_ram(&qxl->rom_bar, &qxl->pci.qdev, "qxl.vrom", - qxl->rom_size); + memory_region_init_ram(&qxl->rom_bar, "qxl.vrom", qxl->rom_size); + vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev); init_qxl_rom(qxl); init_qxl_ram(qxl); @@ -1566,8 +1566,8 @@ static int qxl_init_common(PCIQXLDevice *qxl) qxl->vram_size = 4096; } qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1); - memory_region_init_ram(&qxl->vram_bar, &qxl->pci.qdev, "qxl.vram", - qxl->vram_size); + memory_region_init_ram(&qxl->vram_bar, "qxl.vram", qxl->vram_size); + vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev); io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1); if (qxl->revision == 1) { @@ -1643,8 +1643,8 @@ static int qxl_init_secondary(PCIDevice *dev) ram_size = 16 * 1024 * 1024; } qxl->vga.vram_size = ram_size; - memory_region_init_ram(&qxl->vga.vram, &qxl->pci.qdev, "qxl.vgavram", - qxl->vga.vram_size); + memory_region_init_ram(&qxl->vga.vram, "qxl.vgavram", qxl->vga.vram_size); + vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev); qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram); return qxl_init_common(qxl); @@ -249,7 +249,8 @@ static void r2d_init(ram_addr_t ram_size, qemu_register_reset(main_cpu_reset, reset_info); /* Allocate memory space */ - memory_region_init_ram(sdram, NULL, "r2d.sdram", SDRAM_SIZE); + memory_region_init_ram(sdram, "r2d.sdram", SDRAM_SIZE); + vmstate_register_ram_global(sdram); memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram); /* Register peripherals */ s = sh7750_init(env, address_space_mem); diff --git a/hw/realview.c b/hw/realview.c index 750a279b76..d4191e91c8 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -183,11 +183,13 @@ static void realview_init(ram_addr_t ram_size, /* Core tile RAM. */ low_ram_size = ram_size - 0x20000000; ram_size = 0x20000000; - memory_region_init_ram(ram_lo, NULL, "realview.lowmem", low_ram_size); + memory_region_init_ram(ram_lo, "realview.lowmem", low_ram_size); + vmstate_register_ram_global(ram_lo); memory_region_add_subregion(sysmem, 0x20000000, ram_lo); } - memory_region_init_ram(ram_hi, NULL, "realview.highmem", ram_size); + memory_region_init_ram(ram_hi, "realview.highmem", ram_size); + vmstate_register_ram_global(ram_hi); low_ram_size = ram_size; if (low_ram_size > 0x10000000) low_ram_size = 0x10000000; @@ -377,7 +379,8 @@ static void realview_init(ram_addr_t ram_size, startup code. I guess this works on real hardware because the BootROM happens to be in ROM/flash or in memory that isn't clobbered until after Linux boots the secondary CPUs. */ - memory_region_init_ram(ram_hack, NULL, "realview.hack", 0x1000); + memory_region_init_ram(ram_hack, "realview.hack", 0x1000); + vmstate_register_ram_global(ram_hack); memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack); realview_binfo.ram_size = ram_size; diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 61b67e8c3a..2210b8ac7e 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -184,7 +184,8 @@ static void s390_init(ram_addr_t my_ram_size, s390_bus = s390_virtio_bus_init(&my_ram_size); /* allocate RAM */ - memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size); + memory_region_init_ram(ram, "s390.ram", my_ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); /* clear virtio region */ @@ -57,14 +57,17 @@ static void shix_init(ram_addr_t ram_size, /* Allocate memory space */ printf("Allocating ROM\n"); - memory_region_init_ram(rom, NULL, "shix.rom", 0x4000); + memory_region_init_ram(rom, "shix.rom", 0x4000); + vmstate_register_ram_global(rom); memory_region_set_readonly(rom, true); memory_region_add_subregion(sysmem, 0x00000000, rom); printf("Allocating SDRAM 1\n"); - memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000); + memory_region_init_ram(&sdram[0], "shix.sdram1", 0x01000000); + vmstate_register_ram_global(&sdram[0]); memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]); printf("Allocating SDRAM 2\n"); - memory_region_init_ram(&sdram[1], NULL, "shix.sdram2", 0x01000000); + memory_region_init_ram(&sdram[1], "shix.sdram2", 0x01000000); + vmstate_register_ram_global(&sdram[1]); memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]); /* Load BIOS in 0 (and access it through P2, 0xA0000000) */ diff --git a/hw/sm501.c b/hw/sm501.c index 297bc9c318..326531c57e 100644 --- a/hw/sm501.c +++ b/hw/sm501.c @@ -1405,8 +1405,9 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base, s->dc_crt_control = 0x00010000; /* allocate local memory */ - memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local", + memory_region_init_ram(&s->local_mem_region, "sm501.local", local_mem_bytes); + vmstate_register_ram_global(&s->local_mem_region); s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region); memory_region_add_subregion(address_space_mem, base, &s->local_mem_region); diff --git a/hw/spapr.c b/hw/spapr.c index 2b901f105e..161b5858ae 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -457,7 +457,8 @@ static void ppc_spapr_init(ram_addr_t ram_size, ram_addr_t nonrma_base = rma_alloc_size; ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size; - memory_region_init_ram(ram, NULL, "ppc_spapr.ram", nonrma_size); + memory_region_init_ram(ram, "ppc_spapr.ram", nonrma_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, nonrma_base, ram); } diff --git a/hw/spitz.c b/hw/spitz.c index df0e1466a2..82a133dfa8 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -894,7 +894,8 @@ static void spitz_common_init(ram_addr_t ram_size, sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M); - memory_region_init_ram(rom, NULL, "spitz.rom", SPITZ_ROM); + memory_region_init_ram(rom, "spitz.rom", SPITZ_ROM); + vmstate_register_ram_global(rom); memory_region_set_readonly(rom, true); memory_region_add_subregion(address_space_mem, 0, rom); diff --git a/hw/strongarm.c b/hw/strongarm.c index 7c75bb912d..69c117906c 100644 --- a/hw/strongarm.c +++ b/hw/strongarm.c @@ -1511,7 +1511,8 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem, exit(1); } - memory_region_init_ram(&s->sdram, NULL, "strongarm.sdram", sdram_size); + memory_region_init_ram(&s->sdram, "strongarm.sdram", sdram_size); + vmstate_register_ram_global(&s->sdram); memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram); pic = arm_pic_init_cpu(s->env); diff --git a/hw/sun4m.c b/hw/sun4m.c index 3f172ad062..941cc98b9b 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -602,7 +602,8 @@ static int idreg_init1(SysBusDevice *dev) { IDRegState *s = FROM_SYSBUS(IDRegState, dev); - memory_region_init_ram(&s->mem, NULL, "sun4m.idreg", sizeof(idreg_data)); + memory_region_init_ram(&s->mem, "sun4m.idreg", sizeof(idreg_data)); + vmstate_register_ram_global(&s->mem); memory_region_set_readonly(&s->mem, true); sysbus_init_mmio(dev, &s->mem); return 0; @@ -643,7 +644,8 @@ static int afx_init1(SysBusDevice *dev) { AFXState *s = FROM_SYSBUS(AFXState, dev); - memory_region_init_ram(&s->mem, NULL, "sun4m.afx", 4); + memory_region_init_ram(&s->mem, "sun4m.afx", 4); + vmstate_register_ram_global(&s->mem); sysbus_init_mmio(dev, &s->mem); return 0; } @@ -711,7 +713,8 @@ static int prom_init1(SysBusDevice *dev) { PROMState *s = FROM_SYSBUS(PROMState, dev); - memory_region_init_ram(&s->prom, NULL, "sun4m.prom", PROM_SIZE_MAX); + memory_region_init_ram(&s->prom, "sun4m.prom", PROM_SIZE_MAX); + vmstate_register_ram_global(&s->prom); memory_region_set_readonly(&s->prom, true); sysbus_init_mmio(dev, &s->prom); return 0; @@ -745,7 +748,8 @@ static int ram_init1(SysBusDevice *dev) { RamDevice *d = FROM_SYSBUS(RamDevice, dev); - memory_region_init_ram(&d->ram, NULL, "sun4m.ram", d->size); + memory_region_init_ram(&d->ram, "sun4m.ram", d->size); + vmstate_register_ram_global(&d->ram); sysbus_init_mmio(dev, &d->ram); return 0; } diff --git a/hw/sun4u.c b/hw/sun4u.c index e3e8ddebca..2dc3d0439f 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -629,7 +629,8 @@ static int prom_init1(SysBusDevice *dev) { PROMState *s = FROM_SYSBUS(PROMState, dev); - memory_region_init_ram(&s->prom, NULL, "sun4u.prom", PROM_SIZE_MAX); + memory_region_init_ram(&s->prom, "sun4u.prom", PROM_SIZE_MAX); + vmstate_register_ram_global(&s->prom); memory_region_set_readonly(&s->prom, true); sysbus_init_mmio(dev, &s->prom); return 0; @@ -664,7 +665,8 @@ static int ram_init1(SysBusDevice *dev) { RamDevice *d = FROM_SYSBUS(RamDevice, dev); - memory_region_init_ram(&d->ram, NULL, "sun4u.ram", d->size); + memory_region_init_ram(&d->ram, "sun4u.ram", d->size); + vmstate_register_ram_global(&d->ram); sysbus_init_mmio(dev, &d->ram); return 0; } diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c index c144dcf5ff..b75fa603cf 100644 --- a/hw/tc6393xb.c +++ b/hw/tc6393xb.c @@ -568,7 +568,8 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq) memory_region_init_io(&s->iomem, &tc6393xb_ops, s, "tc6393xb", 0x10000); memory_region_add_subregion(sysmem, base, &s->iomem); - memory_region_init_ram(&s->vram, NULL, "tc6393xb.vram", 0x100000); + memory_region_init_ram(&s->vram, "tc6393xb.vram", 0x100000); + vmstate_register_ram_global(&s->vram); s->vram_ptr = memory_region_get_ram_ptr(&s->vram); memory_region_add_subregion(sysmem, base + 0x100000, &s->vram); s->scr_width = 480; @@ -520,8 +520,9 @@ static int tcx_init1(SysBusDevice *dev) int size; uint8_t *vram_base; - memory_region_init_ram(&s->vram_mem, NULL, "tcx.vram", + memory_region_init_ram(&s->vram_mem, "tcx.vram", s->vram_size * (1 + 4 + 4)); + vmstate_register_ram_global(&s->vram_mem); vram_base = memory_region_get_ram_ptr(&s->vram_mem); /* 8-bit plane */ @@ -218,7 +218,8 @@ static void tosa_init(ram_addr_t ram_size, cpu = pxa255_init(address_space_mem, tosa_binfo.ram_size); - memory_region_init_ram(rom, NULL, "tosa.rom", TOSA_ROM); + memory_region_init_ram(rom, "tosa.rom", TOSA_ROM); + vmstate_register_ram_global(rom); memory_region_set_readonly(rom, true); memory_region_add_subregion(address_space_mem, 0, rom); diff --git a/hw/versatilepb.c b/hw/versatilepb.c index a6315fce5d..0312b7564a 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -190,7 +190,8 @@ static void versatile_init(ram_addr_t ram_size, fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } - memory_region_init_ram(ram, NULL, "versatile.ram", ram_size); + memory_region_init_ram(ram, "versatile.ram", ram_size); + vmstate_register_ram_global(ram); /* ??? RAM should repeat to fill physical memory space. */ /* SDRAM at address zero. */ memory_region_add_subregion(sysmem, 0, ram); diff --git a/hw/vexpress.c b/hw/vexpress.c index 08c93d5544..c9ca43c89b 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -77,7 +77,8 @@ static void vexpress_a9_init(ram_addr_t ram_size, exit(1); } - memory_region_init_ram(ram, NULL, "vexpress.highmem", ram_size); + memory_region_init_ram(ram, "vexpress.highmem", ram_size); + vmstate_register_ram_global(ram); low_ram_size = ram_size; if (low_ram_size > 0x4000000) { low_ram_size = 0x4000000; @@ -181,14 +182,16 @@ static void vexpress_a9_init(ram_addr_t ram_size, /* CS4: NOR1 flash : 0x44000000 .. 0x48000000 */ /* CS2: SRAM : 0x48000000 .. 0x4a000000 */ sram_size = 0x2000000; - memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size); + memory_region_init_ram(sram, "vexpress.sram", sram_size); + vmstate_register_ram_global(sram); memory_region_add_subregion(sysmem, 0x48000000, sram); /* CS3: USB, ethernet, VRAM : 0x4c000000 .. 0x50000000 */ /* 0x4c000000 Video RAM */ vram_size = 0x800000; - memory_region_init_ram(vram, NULL, "vexpress.vram", vram_size); + memory_region_init_ram(vram, "vexpress.vram", vram_size); + vmstate_register_ram_global(vram); memory_region_add_subregion(sysmem, 0x4c000000, vram); /* 0x4e000000 LAN9118 Ethernet */ @@ -202,7 +205,8 @@ static void vexpress_a9_init(ram_addr_t ram_size, startup code. I guess this works on real hardware because the BootROM happens to be in ROM/flash or in memory that isn't clobbered until after Linux boots the secondary CPUs. */ - memory_region_init_ram(hackram, NULL, "vexpress.hack", 0x1000); + memory_region_init_ram(hackram, "vexpress.hack", 0x1000); + vmstate_register_ram_global(hackram); memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, hackram); vexpress_binfo.ram_size = ram_size; @@ -2222,7 +2222,8 @@ void vga_common_init(VGACommonState *s, int vga_ram_size) #else s->is_vbe_vmstate = 0; #endif - memory_region_init_ram(&s->vram, NULL, "vga.vram", vga_ram_size); + memory_region_init_ram(&s->vram, "vga.vram", vga_ram_size); + vmstate_register_ram_global(&s->vram); xen_register_framebuffer(&s->vram); s->vram_ptr = memory_region_get_ram_ptr(&s->vram); s->vram_size = vga_ram_size; diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index 6ffb896b7b..bd16b97934 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -205,7 +205,8 @@ static void virtex_init(ram_addr_t ram_size, env = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000); qemu_register_reset(main_cpu_reset, env); - memory_region_init_ram(phys_ram, NULL, "ram", ram_size); + memory_region_init_ram(phys_ram, "ram", ram_size); + vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, ram_base, phys_ram); dinfo = drive_get(IF_PFLASH, 0, 0); diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index af70bdee09..b1885c3c19 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1091,7 +1091,8 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size, s->fifo_size = SVGA_FIFO_SIZE; - memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size); + memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size); + vmstate_register_ram_global(&s->fifo_ram); s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram); vga_common_init(&s->vga, vga_ram_size); diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c index 8947157bfc..26112c3eb0 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -136,7 +136,8 @@ static void lx60_net_init(MemoryRegion *address_space, sysbus_mmio_get_region(s, 1)); ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, NULL, "open_eth.ram", 16384); + memory_region_init_ram(ram, "open_eth.ram", 16384); + vmstate_register_ram_global(ram); memory_region_add_subregion(address_space, buffers, ram); } @@ -186,7 +187,8 @@ static void lx_init(const LxBoardDesc *board, } ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, NULL, "lx60.dram", ram_size); + memory_region_init_ram(ram, "lx60.dram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(system_memory, 0, ram); system_io = g_malloc(sizeof(*system_io)); @@ -221,7 +223,8 @@ static void lx_init(const LxBoardDesc *board, /* Use presence of kernel file name as 'boot from SRAM' switch. */ if (kernel_filename) { rom = g_malloc(sizeof(*rom)); - memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size); + memory_region_init_ram(rom, "lx60.sram", board->sram_size); + vmstate_register_ram_global(rom); memory_region_add_subregion(system_memory, 0xfe000000, rom); /* Put kernel bootparameters to the end of that SRAM */ diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c index a94e4e561e..104e5dc619 100644 --- a/hw/xtensa_sim.c +++ b/hw/xtensa_sim.c @@ -66,11 +66,13 @@ static void sim_init(ram_addr_t ram_size, } ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size); + memory_region_init_ram(ram, "xtensa.sram", ram_size); + vmstate_register_ram_global(ram); memory_region_add_subregion(get_system_memory(), 0, ram); rom = g_malloc(sizeof(*rom)); - memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000); + memory_region_init_ram(rom, "xtensa.rom", 0x1000); + vmstate_register_ram_global(rom); memory_region_add_subregion(get_system_memory(), 0xfe000000, rom); if (kernel_filename) { @@ -303,44 +303,28 @@ static void access_with_adjusted_size(target_phys_addr_t addr, } } -static void memory_region_prepare_ram_addr(MemoryRegion *mr); - static void as_memory_range_add(AddressSpace *as, FlatRange *fr) { - ram_addr_t phys_offset, region_offset; - - memory_region_prepare_ram_addr(fr->mr); - - phys_offset = fr->mr->ram_addr; - region_offset = fr->offset_in_region; - /* cpu_register_physical_memory_log() wants region_offset for - * mmio, but prefers offseting phys_offset for RAM. Humour it. - */ - if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) { - phys_offset += region_offset; - region_offset = 0; - } - - if (!fr->readable) { - phys_offset &= ~TARGET_PAGE_MASK & ~IO_MEM_ROMD; - } - - if (fr->readonly) { - phys_offset |= IO_MEM_ROM; - } + MemoryRegionSection section = { + .mr = fr->mr, + .offset_within_address_space = int128_get64(fr->addr.start), + .offset_within_region = fr->offset_in_region, + .size = int128_get64(fr->addr.size), + }; - cpu_register_physical_memory_log(int128_get64(fr->addr.start), - int128_get64(fr->addr.size), - phys_offset, - region_offset, - fr->dirty_log_mask); + cpu_register_physical_memory_log(§ion, fr->readable, fr->readonly); } static void as_memory_range_del(AddressSpace *as, FlatRange *fr) { - cpu_register_physical_memory(int128_get64(fr->addr.start), - int128_get64(fr->addr.size), - IO_MEM_UNASSIGNED); + MemoryRegionSection section = { + .mr = &io_mem_unassigned, + .offset_within_address_space = int128_get64(fr->addr.start), + .offset_within_region = int128_get64(fr->addr.start), + .size = int128_get64(fr->addr.size), + }; + + cpu_register_physical_memory_log(§ion, true, false); } static void as_memory_log_start(AddressSpace *as, FlatRange *fr) @@ -854,7 +838,16 @@ static void memory_region_destructor_iomem(MemoryRegion *mr) static void memory_region_destructor_rom_device(MemoryRegion *mr) { qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK); - cpu_unregister_io_memory(mr->ram_addr & ~(TARGET_PAGE_MASK | IO_MEM_ROMD)); + cpu_unregister_io_memory(mr->ram_addr & ~TARGET_PAGE_MASK); +} + +static bool memory_region_wrong_endianness(MemoryRegion *mr) +{ +#ifdef TARGET_BIG_ENDIAN + return mr->ops->endianness == DEVICE_LITTLE_ENDIAN; +#else + return mr->ops->endianness == DEVICE_BIG_ENDIAN; +#endif } void memory_region_init(MemoryRegion *mr, @@ -869,11 +862,13 @@ void memory_region_init(MemoryRegion *mr, } mr->addr = 0; mr->offset = 0; + mr->subpage = false; mr->enabled = true; mr->terminates = false; mr->ram = false; mr->readable = true; mr->readonly = false; + mr->rom_device = false; mr->destructor = memory_region_destructor_none; mr->priority = 0; mr->may_overlap = false; @@ -913,11 +908,10 @@ static bool memory_region_access_valid(MemoryRegion *mr, return true; } -static uint32_t memory_region_read_thunk_n(void *_mr, - target_phys_addr_t addr, - unsigned size) +static uint64_t memory_region_dispatch_read1(MemoryRegion *mr, + target_phys_addr_t addr, + unsigned size) { - MemoryRegion *mr = _mr; uint64_t data = 0; if (!memory_region_access_valid(mr, addr, size, false)) { @@ -937,17 +931,45 @@ static uint32_t memory_region_read_thunk_n(void *_mr, return data; } -static void memory_region_write_thunk_n(void *_mr, - target_phys_addr_t addr, - unsigned size, - uint64_t data) +static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size) +{ + if (memory_region_wrong_endianness(mr)) { + switch (size) { + case 1: + break; + case 2: + *data = bswap16(*data); + break; + case 4: + *data = bswap32(*data); + default: + abort(); + } + } +} + +static uint64_t memory_region_dispatch_read(MemoryRegion *mr, + target_phys_addr_t addr, + unsigned size) { - MemoryRegion *mr = _mr; + uint64_t ret; + + ret = memory_region_dispatch_read1(mr, addr, size); + adjust_endianness(mr, &ret, size); + return ret; +} +static void memory_region_dispatch_write(MemoryRegion *mr, + target_phys_addr_t addr, + uint64_t data, + unsigned size) +{ if (!memory_region_access_valid(mr, addr, size, true)) { return; /* FIXME: better signalling */ } + adjust_endianness(mr, &data, size); + if (!mr->ops->write) { mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data); return; @@ -960,65 +982,6 @@ static void memory_region_write_thunk_n(void *_mr, memory_region_write_accessor, mr); } -static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr) -{ - return memory_region_read_thunk_n(mr, addr, 1); -} - -static uint32_t memory_region_read_thunk_w(void *mr, target_phys_addr_t addr) -{ - return memory_region_read_thunk_n(mr, addr, 2); -} - -static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr) -{ - return memory_region_read_thunk_n(mr, addr, 4); -} - -static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr, - uint32_t data) -{ - memory_region_write_thunk_n(mr, addr, 1, data); -} - -static void memory_region_write_thunk_w(void *mr, target_phys_addr_t addr, - uint32_t data) -{ - memory_region_write_thunk_n(mr, addr, 2, data); -} - -static void memory_region_write_thunk_l(void *mr, target_phys_addr_t addr, - uint32_t data) -{ - memory_region_write_thunk_n(mr, addr, 4, data); -} - -static CPUReadMemoryFunc * const memory_region_read_thunk[] = { - memory_region_read_thunk_b, - memory_region_read_thunk_w, - memory_region_read_thunk_l, -}; - -static CPUWriteMemoryFunc * const memory_region_write_thunk[] = { - memory_region_write_thunk_b, - memory_region_write_thunk_w, - memory_region_write_thunk_l, -}; - -static void memory_region_prepare_ram_addr(MemoryRegion *mr) -{ - if (mr->backend_registered) { - return; - } - - mr->destructor = memory_region_destructor_iomem; - mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk, - memory_region_write_thunk, - mr, - mr->ops->endianness); - mr->backend_registered = true; -} - void memory_region_init_io(MemoryRegion *mr, const MemoryRegionOps *ops, void *opaque, @@ -1029,11 +992,11 @@ void memory_region_init_io(MemoryRegion *mr, mr->ops = ops; mr->opaque = opaque; mr->terminates = true; - mr->backend_registered = false; + mr->destructor = memory_region_destructor_iomem; + mr->ram_addr = cpu_register_io_memory(mr); } void memory_region_init_ram(MemoryRegion *mr, - DeviceState *dev, const char *name, uint64_t size) { @@ -1041,12 +1004,10 @@ void memory_region_init_ram(MemoryRegion *mr, mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - mr->ram_addr = qemu_ram_alloc(dev, name, size, mr); - mr->backend_registered = true; + mr->ram_addr = qemu_ram_alloc(size, mr); } void memory_region_init_ram_ptr(MemoryRegion *mr, - DeviceState *dev, const char *name, uint64_t size, void *ptr) @@ -1055,8 +1016,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram_from_ptr; - mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr, mr); - mr->backend_registered = true; + mr->ram_addr = qemu_ram_alloc_from_ptr(size, ptr, mr); } void memory_region_init_alias(MemoryRegion *mr, @@ -1073,7 +1033,6 @@ void memory_region_init_alias(MemoryRegion *mr, void memory_region_init_rom_device(MemoryRegion *mr, const MemoryRegionOps *ops, void *opaque, - DeviceState *dev, const char *name, uint64_t size) { @@ -1081,14 +1040,10 @@ void memory_region_init_rom_device(MemoryRegion *mr, mr->ops = ops; mr->opaque = opaque; mr->terminates = true; + mr->rom_device = true; mr->destructor = memory_region_destructor_rom_device; - mr->ram_addr = qemu_ram_alloc(dev, name, size, mr); - mr->ram_addr |= cpu_register_io_memory(memory_region_read_thunk, - memory_region_write_thunk, - mr, - mr->ops->endianness); - mr->ram_addr |= IO_MEM_ROMD; - mr->backend_registered = true; + mr->ram_addr = qemu_ram_alloc(size, mr); + mr->ram_addr |= cpu_register_io_memory(mr); } void memory_region_destroy(MemoryRegion *mr) @@ -1108,6 +1063,11 @@ uint64_t memory_region_size(MemoryRegion *mr) return int128_get64(mr->size); } +const char *memory_region_name(MemoryRegion *mr) +{ + return mr->name; +} + bool memory_region_is_ram(MemoryRegion *mr) { return mr->ram; @@ -1426,7 +1386,6 @@ void memory_region_set_alias_offset(MemoryRegion *mr, target_phys_addr_t offset) ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr) { - assert(mr->backend_registered); return mr->ram_addr; } @@ -1491,6 +1450,7 @@ void memory_global_dirty_log_start(void) { MemoryListener *listener; + cpu_physical_memory_set_dirty_tracking(1); global_dirty_log = true; QLIST_FOREACH(listener, &memory_listeners, link) { listener->log_global_start(listener); @@ -1505,6 +1465,7 @@ void memory_global_dirty_log_stop(void) QLIST_FOREACH(listener, &memory_listeners, link) { listener->log_global_stop(listener); } + cpu_physical_memory_set_dirty_tracking(0); } static void listener_add_address_space(MemoryListener *listener, @@ -1551,6 +1512,17 @@ void set_system_io_map(MemoryRegion *mr) memory_region_update_topology(NULL); } +uint64_t io_mem_read(int io_index, target_phys_addr_t addr, unsigned size) +{ + return memory_region_dispatch_read(io_mem_region[io_index], addr, size); +} + +void io_mem_write(int io_index, target_phys_addr_t addr, + uint64_t val, unsigned size) +{ + memory_region_dispatch_write(io_mem_region[io_index], addr, val, size); +} + typedef struct MemoryRegionList MemoryRegionList; struct MemoryRegionList { @@ -116,15 +116,16 @@ struct MemoryRegion { Int128 size; target_phys_addr_t addr; target_phys_addr_t offset; - bool backend_registered; void (*destructor)(MemoryRegion *mr); ram_addr_t ram_addr; IORange iorange; + bool subpage; bool terminates; bool readable; bool ram; bool readonly; /* For RAM regions */ bool enabled; + bool rom_device; MemoryRegion *alias; target_phys_addr_t alias_offset; unsigned priority; @@ -224,14 +225,10 @@ void memory_region_init_io(MemoryRegion *mr, * region will modify memory directly. * * @mr: the #MemoryRegion to be initialized. - * @dev: a device associated with the region; may be %NULL. - * @name: the name of the region; the pair (@dev, @name) must be globally - * unique. The name is part of the save/restore ABI and so cannot be - * changed. + * @name: the name of the region. * @size: size of the region. */ void memory_region_init_ram(MemoryRegion *mr, - DeviceState *dev, /* FIXME: layering violation */ const char *name, uint64_t size); @@ -241,15 +238,11 @@ void memory_region_init_ram(MemoryRegion *mr, * memory directly. * * @mr: the #MemoryRegion to be initialized. - * @dev: a device associated with the region; may be %NULL. - * @name: the name of the region; the pair (@dev, @name) must be globally - * unique. The name is part of the save/restore ABI and so cannot be - * changed. + * @name: the name of the region. * @size: size of the region. * @ptr: memory to be mapped; must contain at least @size bytes. */ void memory_region_init_ram_ptr(MemoryRegion *mr, - DeviceState *dev, /* FIXME: layering violation */ const char *name, uint64_t size, void *ptr); @@ -277,16 +270,12 @@ void memory_region_init_alias(MemoryRegion *mr, * * @mr: the #MemoryRegion to be initialized. * @ops: callbacks for write access handling. - * @dev: a device associated with the region; may be %NULL. - * @name: the name of the region; the pair (@dev, @name) must be globally - * unique. The name is part of the save/restore ABI and so cannot be - * changed. + * @name: the name of the region. * @size: size of the region. */ void memory_region_init_rom_device(MemoryRegion *mr, const MemoryRegionOps *ops, void *opaque, - DeviceState *dev, /* FIXME: layering violation */ const char *name, uint64_t size); @@ -316,6 +305,15 @@ uint64_t memory_region_size(MemoryRegion *mr); bool memory_region_is_ram(MemoryRegion *mr); /** + * memory_region_name: get a memory region's name + * + * Returns the string that was used to initialize the memory region. + * + * @mr: the memory region being queried + */ +const char *memory_region_name(MemoryRegion *mr); + +/** * memory_region_is_logging: return whether a memory region is logging writes * * Returns %true if the memory region is logging writes @@ -83,6 +83,7 @@ #include "qemu-queue.h" #include "qemu-timer.h" #include "cpus.h" +#include "memory.h" #define SELF_ANNOUNCE_ROUNDS 5 @@ -2280,3 +2281,19 @@ void do_info_snapshots(Monitor *mon) g_free(available_snapshots); } + +void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev) +{ + qemu_ram_set_idstr(memory_region_get_ram_addr(mr), + memory_region_name(mr), dev); +} + +void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev) +{ + /* Nothing do to while the implementation is in RAMBlock */ +} + +void vmstate_register_ram_global(MemoryRegion *mr) +{ + vmstate_register_ram(mr, NULL); +} diff --git a/softmmu_template.h b/softmmu_template.h index 36eb2e8fc0..97020f8185 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -22,6 +22,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "qemu-timer.h" +#include "memory.h" #define DATA_SIZE (1 << SHIFT) @@ -62,24 +63,26 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr, { DATA_TYPE res; int index; - index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); + index = physaddr & (IO_MEM_NB_ENTRIES - 1); physaddr = (physaddr & TARGET_PAGE_MASK) + addr; env->mem_io_pc = (unsigned long)retaddr; - if (index > (IO_MEM_NOTDIRTY >> IO_MEM_SHIFT) + if (index != io_mem_ram.ram_addr && index != io_mem_rom.ram_addr + && index != io_mem_unassigned.ram_addr + && index != io_mem_notdirty.ram_addr && !can_do_io(env)) { cpu_io_recompile(env, retaddr); } env->mem_io_vaddr = addr; #if SHIFT <= 2 - res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr); + res = io_mem_read(index, physaddr, 1 << SHIFT); #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); + res = io_mem_read(index, physaddr, 4) << 32; + res |= io_mem_read(index, physaddr + 4, 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; + res = io_mem_read(index, physaddr, 4); + res |= io_mem_read(index, physaddr + 4, 4) << 32; #endif #endif /* SHIFT > 2 */ return res; @@ -205,9 +208,11 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr, void *retaddr) { int index; - index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); + index = physaddr & (IO_MEM_NB_ENTRIES - 1); physaddr = (physaddr & TARGET_PAGE_MASK) + addr; - if (index > (IO_MEM_NOTDIRTY >> IO_MEM_SHIFT) + if (index != io_mem_ram.ram_addr && index != io_mem_rom.ram_addr + && index != io_mem_unassigned.ram_addr + && index != io_mem_notdirty.ram_addr && !can_do_io(env)) { cpu_io_recompile(env, retaddr); } @@ -215,14 +220,14 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr, 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); + io_mem_write(index, physaddr, val, 1 << SHIFT); #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); + io_mem_write(index, physaddr, (val >> 32), 4); + io_mem_write(index, physaddr + 4, (uint32_t)val, 4); #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); + io_mem_write(index, physaddr, (uint32_t)val, 4); + io_mem_write(index, physaddr + 4, val >> 32, 4); #endif #endif /* SHIFT > 2 */ } @@ -154,7 +154,8 @@ static void xen_ram_init(ram_addr_t ram_size) */ block_len += HVM_BELOW_4G_MMIO_LENGTH; } - memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len); + memory_region_init_ram(&ram_memory, "xen.ram", block_len); + vmstate_register_ram_global(&ram_memory); if (ram_size >= HVM_BELOW_4G_RAM_END) { above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END; @@ -408,7 +409,6 @@ static int xen_sync_dirty_bitmap(XenIOState *state, ram_addr_t size) { target_phys_addr_t npages = size >> TARGET_PAGE_BITS; - target_phys_addr_t vram_offset = 0; const int width = sizeof(unsigned long) * 8; unsigned long bitmap[(npages + width - 1) / width]; int rc, i, j; @@ -425,7 +425,6 @@ static int xen_sync_dirty_bitmap(XenIOState *state, } else if (state->log_for_dirtybit != physmap) { return -1; } - vram_offset = physmap->phys_offset; rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid, start_addr >> TARGET_PAGE_BITS, npages, @@ -439,7 +438,8 @@ static int xen_sync_dirty_bitmap(XenIOState *state, while (map != 0) { j = ffsl(map) - 1; map &= ~(1ul << j); - cpu_physical_memory_set_dirty(vram_offset + (i * width + j) * TARGET_PAGE_SIZE); + memory_region_set_dirty(framebuffer, + (i * width + j) * TARGET_PAGE_SIZE); }; } |