Convert IO_MEM_{RAM,ROM,UNASSIGNED,NOTDIRTY} to MemoryRegions
Convert the fixed-address IO_MEM_RAM, IO_MEM_ROM, IO_MEM_UNASSIGNED, and IO_MEM_NOTDIRTY io handlers to MemoryRegions. These aren't real regions, since they are never added to the memory hierarchy, but they allow reuse of the dispatch functionality. Signed-off-by: Avi Kivity <avi@redhat.com> Reviewed-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
d39e822265
commit
0e0df1e24d
@ -109,10 +109,10 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
|
|||||||
|
|
||||||
#define IO_MEM_SHIFT 3
|
#define IO_MEM_SHIFT 3
|
||||||
|
|
||||||
#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */
|
extern struct MemoryRegion io_mem_ram;
|
||||||
#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */
|
extern struct MemoryRegion io_mem_rom;
|
||||||
#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT)
|
extern struct MemoryRegion io_mem_unassigned;
|
||||||
#define IO_MEM_NOTDIRTY (3 << IO_MEM_SHIFT)
|
extern struct MemoryRegion io_mem_notdirty;
|
||||||
#define IO_MEM_SUBPAGE_RAM (4 << IO_MEM_SHIFT)
|
#define IO_MEM_SUBPAGE_RAM (4 << IO_MEM_SHIFT)
|
||||||
|
|
||||||
/* Acts like a ROM when read and like a device when written. */
|
/* Acts like a ROM when read and like a device when written. */
|
||||||
|
234
exec.c
234
exec.c
@ -118,6 +118,8 @@ RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) };
|
|||||||
static MemoryRegion *system_memory;
|
static MemoryRegion *system_memory;
|
||||||
static MemoryRegion *system_io;
|
static MemoryRegion *system_io;
|
||||||
|
|
||||||
|
MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CPUState *first_cpu;
|
CPUState *first_cpu;
|
||||||
@ -430,7 +432,7 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
|
|||||||
*lp = pd = g_malloc(sizeof(PhysPageDesc) * L2_SIZE);
|
*lp = pd = g_malloc(sizeof(PhysPageDesc) * L2_SIZE);
|
||||||
|
|
||||||
for (i = 0; i < L2_SIZE; i++) {
|
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;
|
pd[i].region_offset = (first_index + i) << TARGET_PAGE_BITS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -446,7 +448,7 @@ static inline PhysPageDesc phys_page_find(target_phys_addr_t index)
|
|||||||
return *p;
|
return *p;
|
||||||
} else {
|
} else {
|
||||||
return (PhysPageDesc) {
|
return (PhysPageDesc) {
|
||||||
.phys_offset = IO_MEM_UNASSIGNED,
|
.phys_offset = io_mem_unassigned.ram_addr,
|
||||||
.region_offset = index << TARGET_PAGE_BITS,
|
.region_offset = index << TARGET_PAGE_BITS,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1965,7 +1967,7 @@ static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
|
|||||||
unsigned long start, unsigned long length)
|
unsigned long start, unsigned long length)
|
||||||
{
|
{
|
||||||
unsigned long addr;
|
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;
|
addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
|
||||||
if ((addr - start) < length) {
|
if ((addr - start) < length) {
|
||||||
tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
|
tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
|
||||||
@ -2021,7 +2023,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
|
|||||||
ram_addr_t ram_addr;
|
ram_addr_t ram_addr;
|
||||||
void *p;
|
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)
|
p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
|
||||||
+ tlb_entry->addend);
|
+ tlb_entry->addend);
|
||||||
ram_addr = qemu_ram_addr_from_host_nofail(p);
|
ram_addr = qemu_ram_addr_from_host_nofail(p);
|
||||||
@ -2087,7 +2089,7 @@ static void tlb_add_large_page(CPUState *env, target_ulong vaddr,
|
|||||||
static bool is_ram_rom(ram_addr_t pd)
|
static bool is_ram_rom(ram_addr_t pd)
|
||||||
{
|
{
|
||||||
pd &= ~TARGET_PAGE_MASK;
|
pd &= ~TARGET_PAGE_MASK;
|
||||||
return pd == IO_MEM_RAM || pd == IO_MEM_ROM;
|
return pd == io_mem_ram.ram_addr || pd == io_mem_rom.ram_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_ram_rom_romd(ram_addr_t pd)
|
static bool is_ram_rom_romd(ram_addr_t pd)
|
||||||
@ -2133,10 +2135,10 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
|
|||||||
if (is_ram_rom(pd)) {
|
if (is_ram_rom(pd)) {
|
||||||
/* Normal RAM. */
|
/* Normal RAM. */
|
||||||
iotlb = pd & TARGET_PAGE_MASK;
|
iotlb = pd & TARGET_PAGE_MASK;
|
||||||
if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
|
if ((pd & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr)
|
||||||
iotlb |= IO_MEM_NOTDIRTY;
|
iotlb |= io_mem_notdirty.ram_addr;
|
||||||
else
|
else
|
||||||
iotlb |= IO_MEM_ROM;
|
iotlb |= io_mem_rom.ram_addr;
|
||||||
} else {
|
} else {
|
||||||
/* IO handlers are currently passed a physical address.
|
/* IO handlers are currently passed a physical address.
|
||||||
It would be nice to pass an offset from the base address
|
It would be nice to pass an offset from the base address
|
||||||
@ -2178,11 +2180,11 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
|
|||||||
te->addr_code = -1;
|
te->addr_code = -1;
|
||||||
}
|
}
|
||||||
if (prot & PAGE_WRITE) {
|
if (prot & PAGE_WRITE) {
|
||||||
if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
|
if ((pd & ~TARGET_PAGE_MASK) == io_mem_rom.ram_addr ||
|
||||||
(pd & IO_MEM_ROMD)) {
|
(pd & IO_MEM_ROMD)) {
|
||||||
/* Write access calls the I/O callback. */
|
/* Write access calls the I/O callback. */
|
||||||
te->addr_write = address | TLB_MMIO;
|
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)) {
|
!cpu_physical_memory_is_dirty(pd)) {
|
||||||
te->addr_write = address | TLB_NOTDIRTY;
|
te->addr_write = address | TLB_NOTDIRTY;
|
||||||
} else {
|
} else {
|
||||||
@ -2522,7 +2524,7 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
|
|||||||
|
|
||||||
assert(size);
|
assert(size);
|
||||||
|
|
||||||
if (phys_offset == IO_MEM_UNASSIGNED) {
|
if (phys_offset == io_mem_unassigned.ram_addr) {
|
||||||
region_offset = start_addr;
|
region_offset = start_addr;
|
||||||
}
|
}
|
||||||
region_offset &= TARGET_PAGE_MASK;
|
region_offset &= TARGET_PAGE_MASK;
|
||||||
@ -2532,7 +2534,7 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
|
|||||||
addr = start_addr;
|
addr = start_addr;
|
||||||
do {
|
do {
|
||||||
p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 0);
|
p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 0);
|
||||||
if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
|
if (p && p->phys_offset != io_mem_unassigned.ram_addr) {
|
||||||
ram_addr_t orig_memory = p->phys_offset;
|
ram_addr_t orig_memory = p->phys_offset;
|
||||||
target_phys_addr_t start_addr2, end_addr2;
|
target_phys_addr_t start_addr2, end_addr2;
|
||||||
int need_subpage = 0;
|
int need_subpage = 0;
|
||||||
@ -2572,7 +2574,8 @@ void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
|
|||||||
|
|
||||||
if (need_subpage) {
|
if (need_subpage) {
|
||||||
subpage = subpage_init((addr & TARGET_PAGE_MASK),
|
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);
|
addr & TARGET_PAGE_MASK);
|
||||||
subpage_register(subpage, start_addr2, end_addr2,
|
subpage_register(subpage, start_addr2, end_addr2,
|
||||||
phys_offset, region_offset);
|
phys_offset, region_offset);
|
||||||
@ -3102,93 +3105,83 @@ ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
|
|||||||
return ram_addr;
|
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
|
#ifdef DEBUG_UNASSIGNED
|
||||||
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
|
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
|
||||||
#endif
|
#endif
|
||||||
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
|
#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
|
#endif
|
||||||
return 0;
|
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
|
#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
|
#endif
|
||||||
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
|
static const MemoryRegionOps unassigned_mem_ops = {
|
||||||
{
|
.read = unassigned_mem_read,
|
||||||
#ifdef DEBUG_UNASSIGNED
|
.write = unassigned_mem_write,
|
||||||
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
#endif
|
|
||||||
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
|
|
||||||
cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 2);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void unassigned_mem_writel(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, 4);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
|
|
||||||
unassigned_mem_readb,
|
|
||||||
unassigned_mem_readw,
|
|
||||||
unassigned_mem_readl,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
|
static uint64_t error_mem_read(void *opaque, target_phys_addr_t addr,
|
||||||
unassigned_mem_writeb,
|
unsigned size)
|
||||||
unassigned_mem_writew,
|
{
|
||||||
unassigned_mem_writel,
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void error_mem_write(void *opaque, target_phys_addr_t addr,
|
||||||
|
uint64_t value, unsigned size)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MemoryRegionOps error_mem_ops = {
|
||||||
|
.read = error_mem_read,
|
||||||
|
.write = error_mem_write,
|
||||||
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
|
static const MemoryRegionOps rom_mem_ops = {
|
||||||
uint32_t val)
|
.read = error_mem_read,
|
||||||
|
.write = unassigned_mem_write,
|
||||||
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void notdirty_mem_write(void *opaque, target_phys_addr_t ram_addr,
|
||||||
|
uint64_t val, unsigned size)
|
||||||
{
|
{
|
||||||
int dirty_flags;
|
int dirty_flags;
|
||||||
dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
|
dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
|
||||||
if (!(dirty_flags & CODE_DIRTY_FLAG)) {
|
if (!(dirty_flags & CODE_DIRTY_FLAG)) {
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#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);
|
dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
stb_p(qemu_get_ram_ptr(ram_addr), val);
|
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();
|
||||||
|
}
|
||||||
dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
|
dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
|
||||||
cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
|
cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
|
||||||
/* we remove the notdirty callback only if the code has been
|
/* we remove the notdirty callback only if the code has been
|
||||||
@ -3197,56 +3190,10 @@ static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
|
|||||||
tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
|
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,
|
static const MemoryRegionOps notdirty_mem_ops = {
|
||||||
uint32_t val)
|
.read = error_mem_read,
|
||||||
{
|
.write = notdirty_mem_write,
|
||||||
int dirty_flags;
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
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
|
|
||||||
}
|
|
||||||
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
|
|
||||||
flushed */
|
|
||||||
if (dirty_flags == 0xff)
|
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Generate a debug exception if a watchpoint has been hit. */
|
/* Generate a debug exception if a watchpoint has been hit. */
|
||||||
@ -3492,7 +3439,7 @@ 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__,
|
printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
|
||||||
mmio, start, end, idx, eidx, memory);
|
mmio, start, end, idx, eidx, memory);
|
||||||
#endif
|
#endif
|
||||||
if ((memory & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
|
if ((memory & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
|
||||||
memory = IO_MEM_SUBPAGE_RAM;
|
memory = IO_MEM_SUBPAGE_RAM;
|
||||||
}
|
}
|
||||||
memory = (memory >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
memory = (memory >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
||||||
@ -3563,12 +3510,12 @@ static int cpu_register_io_memory_fixed(int io_index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 3; ++i) {
|
for (i = 0; i < 3; ++i) {
|
||||||
_io_mem_read[io_index][i]
|
assert(mem_read[i]);
|
||||||
= (mem_read[i] ? mem_read[i] : unassigned_mem_read[i]);
|
_io_mem_read[io_index][i] = mem_read[i];
|
||||||
}
|
}
|
||||||
for (i = 0; i < 3; ++i) {
|
for (i = 0; i < 3; ++i) {
|
||||||
_io_mem_write[io_index][i]
|
assert(mem_write[i]);
|
||||||
= (mem_write[i] ? mem_write[i] : unassigned_mem_write[i]);
|
_io_mem_write[io_index][i] = mem_write[i];
|
||||||
}
|
}
|
||||||
io_mem_opaque[io_index] = opaque;
|
io_mem_opaque[io_index] = opaque;
|
||||||
|
|
||||||
@ -3588,8 +3535,8 @@ void cpu_unregister_io_memory(int io_table_address)
|
|||||||
int io_index = io_table_address >> IO_MEM_SHIFT;
|
int io_index = io_table_address >> IO_MEM_SHIFT;
|
||||||
|
|
||||||
for (i=0;i < 3; i++) {
|
for (i=0;i < 3; i++) {
|
||||||
_io_mem_read[io_index][i] = unassigned_mem_read[i];
|
_io_mem_read[io_index][i] = NULL;
|
||||||
_io_mem_write[io_index][i] = unassigned_mem_write[i];
|
_io_mem_write[io_index][i] = NULL;
|
||||||
}
|
}
|
||||||
io_mem_opaque[io_index] = NULL;
|
io_mem_opaque[io_index] = NULL;
|
||||||
io_mem_used[io_index] = 0;
|
io_mem_used[io_index] = 0;
|
||||||
@ -3599,12 +3546,14 @@ static void io_mem_init(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read,
|
/* Must be first: */
|
||||||
unassigned_mem_write, NULL);
|
memory_region_init_io(&io_mem_ram, &error_mem_ops, NULL, "ram", UINT64_MAX);
|
||||||
cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read,
|
assert(io_mem_ram.ram_addr == 0);
|
||||||
unassigned_mem_write, NULL);
|
memory_region_init_io(&io_mem_rom, &rom_mem_ops, NULL, "rom", UINT64_MAX);
|
||||||
cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read,
|
memory_region_init_io(&io_mem_unassigned, &unassigned_mem_ops, NULL,
|
||||||
notdirty_mem_write, NULL);
|
"unassigned", UINT64_MAX);
|
||||||
|
memory_region_init_io(&io_mem_notdirty, ¬dirty_mem_ops, NULL,
|
||||||
|
"notdirty", UINT64_MAX);
|
||||||
cpu_register_io_memory_fixed(IO_MEM_SUBPAGE_RAM, subpage_ram_read,
|
cpu_register_io_memory_fixed(IO_MEM_SUBPAGE_RAM, subpage_ram_read,
|
||||||
subpage_ram_write, NULL);
|
subpage_ram_write, NULL);
|
||||||
for (i=0; i<5; i++)
|
for (i=0; i<5; i++)
|
||||||
@ -3698,7 +3647,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
|
|||||||
pd = p.phys_offset;
|
pd = p.phys_offset;
|
||||||
|
|
||||||
if (is_write) {
|
if (is_write) {
|
||||||
if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
|
if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) {
|
||||||
target_phys_addr_t addr1;
|
target_phys_addr_t addr1;
|
||||||
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
||||||
addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
|
addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
|
||||||
@ -3879,7 +3828,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
|
|||||||
p = phys_page_find(page >> TARGET_PAGE_BITS);
|
p = phys_page_find(page >> TARGET_PAGE_BITS);
|
||||||
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) {
|
if (todo || bounce.buffer) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4150,7 +4099,7 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
|
|||||||
p = phys_page_find(addr >> TARGET_PAGE_BITS);
|
p = phys_page_find(addr >> TARGET_PAGE_BITS);
|
||||||
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) {
|
||||||
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
||||||
addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
|
addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
|
||||||
io_mem_write(io_index, addr, val, 4);
|
io_mem_write(io_index, addr, val, 4);
|
||||||
@ -4181,7 +4130,7 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
|
|||||||
p = phys_page_find(addr >> TARGET_PAGE_BITS);
|
p = phys_page_find(addr >> TARGET_PAGE_BITS);
|
||||||
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) {
|
||||||
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
||||||
addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
|
addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
#ifdef TARGET_WORDS_BIGENDIAN
|
||||||
@ -4210,7 +4159,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
|
|||||||
p = phys_page_find(addr >> TARGET_PAGE_BITS);
|
p = phys_page_find(addr >> TARGET_PAGE_BITS);
|
||||||
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) {
|
||||||
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
||||||
addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
|
addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||||
@ -4283,7 +4232,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
|
|||||||
p = phys_page_find(addr >> TARGET_PAGE_BITS);
|
p = phys_page_find(addr >> TARGET_PAGE_BITS);
|
||||||
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) {
|
||||||
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
||||||
addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
|
addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset;
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||||
@ -4514,7 +4463,8 @@ tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
|
|||||||
ldub_code(addr);
|
ldub_code(addr);
|
||||||
}
|
}
|
||||||
pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
|
pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
|
||||||
if (pd != IO_MEM_RAM && pd != IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
|
if (pd != io_mem_ram.ram_addr && pd != io_mem_rom.ram_addr
|
||||||
|
&& !(pd & IO_MEM_ROMD)) {
|
||||||
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
|
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
|
||||||
cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
|
cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
|
||||||
#else
|
#else
|
||||||
|
7
memory.c
7
memory.c
@ -312,8 +312,7 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
|
|||||||
/* cpu_register_physical_memory_log() wants region_offset for
|
/* cpu_register_physical_memory_log() wants region_offset for
|
||||||
* mmio, but prefers offseting phys_offset for RAM. Humour it.
|
* mmio, but prefers offseting phys_offset for RAM. Humour it.
|
||||||
*/
|
*/
|
||||||
if ((phys_offset & ~TARGET_PAGE_MASK) == IO_MEM_RAM
|
if (memory_region_is_ram(fr->mr)) {
|
||||||
|| (phys_offset & ~TARGET_PAGE_MASK) == IO_MEM_ROM) {
|
|
||||||
phys_offset += region_offset;
|
phys_offset += region_offset;
|
||||||
region_offset = 0;
|
region_offset = 0;
|
||||||
}
|
}
|
||||||
@ -323,7 +322,7 @@ static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fr->readonly) {
|
if (fr->readonly) {
|
||||||
phys_offset |= IO_MEM_ROM;
|
phys_offset |= io_mem_rom.ram_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_register_physical_memory_log(int128_get64(fr->addr.start),
|
cpu_register_physical_memory_log(int128_get64(fr->addr.start),
|
||||||
@ -337,7 +336,7 @@ static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
|
|||||||
{
|
{
|
||||||
cpu_register_physical_memory(int128_get64(fr->addr.start),
|
cpu_register_physical_memory(int128_get64(fr->addr.start),
|
||||||
int128_get64(fr->addr.size),
|
int128_get64(fr->addr.size),
|
||||||
IO_MEM_UNASSIGNED);
|
io_mem_unassigned.ram_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
|
static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include "qemu-timer.h"
|
#include "qemu-timer.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#define DATA_SIZE (1 << SHIFT)
|
#define DATA_SIZE (1 << SHIFT)
|
||||||
|
|
||||||
@ -65,8 +66,9 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
|
|||||||
index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
||||||
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
|
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
|
||||||
env->mem_io_pc = (unsigned long)retaddr;
|
env->mem_io_pc = (unsigned long)retaddr;
|
||||||
if (index != IO_MEM_RAM && index != IO_MEM_ROM
|
if (index != io_mem_ram.ram_addr && index != io_mem_rom.ram_addr
|
||||||
&& index != IO_MEM_UNASSIGNED && index != IO_MEM_NOTDIRTY
|
&& index != io_mem_unassigned.ram_addr
|
||||||
|
&& index != io_mem_notdirty.ram_addr
|
||||||
&& !can_do_io(env)) {
|
&& !can_do_io(env)) {
|
||||||
cpu_io_recompile(env, retaddr);
|
cpu_io_recompile(env, retaddr);
|
||||||
}
|
}
|
||||||
@ -208,8 +210,9 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
|
|||||||
int index;
|
int index;
|
||||||
index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
|
||||||
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
|
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
|
||||||
if (index != IO_MEM_RAM && index != IO_MEM_ROM
|
if (index != io_mem_ram.ram_addr && index != io_mem_rom.ram_addr
|
||||||
&& index != IO_MEM_UNASSIGNED && index != IO_MEM_NOTDIRTY
|
&& index != io_mem_unassigned.ram_addr
|
||||||
|
&& index != io_mem_notdirty.ram_addr
|
||||||
&& !can_do_io(env)) {
|
&& !can_do_io(env)) {
|
||||||
cpu_io_recompile(env, retaddr);
|
cpu_io_recompile(env, retaddr);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user