X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/117712c3e48e64c763d981b0d72603ef703031fe..f7bf546118837a64d4b04dd650e3f64eaa25e623:/exec.c diff --git a/exec.c b/exec.c index 2171eba487..f4cd867d51 100644 --- a/exec.c +++ b/exec.c @@ -186,12 +186,6 @@ unsigned long qemu_host_page_mask; static void *l1_map[V_L1_SIZE]; #if !defined(CONFIG_USER_ONLY) -typedef struct PhysPageDesc { - /* offset in host memory of the page + io_index in the low bits */ - ram_addr_t phys_offset; - ram_addr_t region_offset; -} PhysPageDesc; - typedef struct PhysPageEntry PhysPageEntry; static MemoryRegionSection *phys_sections; @@ -212,7 +206,7 @@ static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc; #define PHYS_MAP_NODE_NIL ((uint16_t)~0) /* This is a multi-level map on the physical address space. - The bottom level has pointers to PhysPageDesc. */ + The bottom level has pointers to MemoryRegionSections. */ static PhysPageEntry phys_map = { .u.node = PHYS_MAP_NODE_NIL }; static void io_mem_init(void); @@ -410,24 +404,30 @@ static inline PageDesc *page_find(tb_page_addr_t index) #if !defined(CONFIG_USER_ONLY) -static PhysPageEntry *phys_map_node_alloc(uint16_t *ptr) +static void phys_map_node_reserve(unsigned nodes) { - unsigned i; - uint16_t ret; - - /* Assign early to avoid the pointer being invalidated by g_renew() */ - *ptr = ret = phys_map_nodes_nb++; - assert(ret != PHYS_MAP_NODE_NIL); - if (ret == phys_map_nodes_nb_alloc) { + if (phys_map_nodes_nb + nodes > phys_map_nodes_nb_alloc) { typedef PhysPageEntry Node[L2_SIZE]; phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc * 2, 16); + phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc, + phys_map_nodes_nb + nodes); phys_map_nodes = g_renew(Node, phys_map_nodes, phys_map_nodes_nb_alloc); } +} + +static uint16_t phys_map_node_alloc(void) +{ + unsigned i; + uint16_t ret; + + ret = phys_map_nodes_nb++; + assert(ret != PHYS_MAP_NODE_NIL); + assert(ret != phys_map_nodes_nb_alloc); for (i = 0; i < L2_SIZE; ++i) { phys_map_nodes[ret][i].u.node = PHYS_MAP_NODE_NIL; } - return phys_map_nodes[ret]; + return ret; } static void phys_map_nodes_reset(void) @@ -435,61 +435,68 @@ static void phys_map_nodes_reset(void) phys_map_nodes_nb = 0; } -static uint16_t *phys_page_find_alloc(target_phys_addr_t index, int alloc) -{ - PhysPageEntry *lp, *p; - int i, j; - lp = &phys_map; +static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t index, + uint16_t leaf, int level) +{ + PhysPageEntry *p; + int i; - /* Level 1..N. */ - for (i = P_L2_LEVELS - 1; i >= 0; i--) { - if (lp->u.node == PHYS_MAP_NODE_NIL) { - if (!alloc) { - return NULL; - } - p = phys_map_node_alloc(&lp->u.node); - if (i == 0) { - for (j = 0; j < L2_SIZE; j++) { - p[j].u.leaf = phys_section_unassigned; - } + if (lp->u.node == PHYS_MAP_NODE_NIL) { + lp->u.node = phys_map_node_alloc(); + p = phys_map_nodes[lp->u.node]; + if (level == 0) { + for (i = 0; i < L2_SIZE; i++) { + p[i].u.leaf = phys_section_unassigned; } - } else { - p = phys_map_nodes[lp->u.node]; } - lp = &p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)]; + } else { + p = phys_map_nodes[lp->u.node]; + } + lp = &p[(index >> (level * L2_BITS)) & (L2_SIZE - 1)]; + + if (level == 0) { + lp->u.leaf = leaf; + } else { + phys_page_set_level(lp, index, leaf, level - 1); } +} + +static void phys_page_set(target_phys_addr_t index, uint16_t leaf) +{ + phys_map_node_reserve(P_L2_LEVELS); - return &lp->u.leaf; + phys_page_set_level(&phys_map, index, leaf, P_L2_LEVELS - 1); } -static inline PhysPageDesc phys_page_find(target_phys_addr_t index) +static MemoryRegionSection phys_page_find(target_phys_addr_t index) { - uint16_t *p = phys_page_find_alloc(index, 0); + PhysPageEntry lp = phys_map; + PhysPageEntry *p; + int i; + MemoryRegionSection section; + target_phys_addr_t delta; uint16_t s_index = phys_section_unassigned; - MemoryRegionSection *section; - PhysPageDesc pd; - if (p) { - s_index = *p; + for (i = P_L2_LEVELS - 1; i >= 0; i--) { + if (lp.u.node == PHYS_MAP_NODE_NIL) { + goto not_found; + } + p = phys_map_nodes[lp.u.node]; + lp = p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)]; } - section = &phys_sections[s_index]; + + s_index = lp.u.leaf; +not_found: + section = phys_sections[s_index]; index <<= TARGET_PAGE_BITS; - assert(section->offset_within_address_space <= index - && index <= section->offset_within_address_space + section->size-1); - pd.phys_offset = section->mr->ram_addr; - pd.region_offset = (index - section->offset_within_address_space) - + section->offset_within_region; - if (memory_region_is_ram(section->mr)) { - pd.phys_offset += pd.region_offset; - pd.region_offset = 0; - } else if (section->mr->rom_device) { - pd.phys_offset += pd.region_offset; - } - if (section->readonly) { - pd.phys_offset |= io_mem_rom.ram_addr; - } - return pd; + assert(section.offset_within_address_space <= index + && index <= section.offset_within_address_space + section.size-1); + delta = index - section.offset_within_address_space; + section.offset_within_address_space += delta; + section.offset_within_region += delta; + section.size -= delta; + return section; } static void tlb_protect_code(ram_addr_t ram_addr); @@ -1449,14 +1456,18 @@ static void breakpoint_invalidate(CPUState *env, target_ulong pc) static void breakpoint_invalidate(CPUState *env, target_ulong pc) { target_phys_addr_t addr; - target_ulong pd; ram_addr_t ram_addr; - PhysPageDesc p; + MemoryRegionSection section; addr = cpu_get_phys_page_debug(env, pc); - p = phys_page_find(addr >> TARGET_PAGE_BITS); - pd = p.phys_offset; - ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK); + section = phys_page_find(addr >> TARGET_PAGE_BITS); + if (!(memory_region_is_ram(section.mr) + || (section.mr->rom_device && section.mr->readable))) { + return; + } + ram_addr = (memory_region_get_ram_addr(section.mr) + + section.offset_within_region) & TARGET_PAGE_MASK; + ram_addr |= (pc & ~TARGET_PAGE_MASK); tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0); } #endif @@ -2134,24 +2145,21 @@ 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) +static bool is_ram_rom(MemoryRegionSection *s) { - pd &= ~TARGET_PAGE_MASK; - return pd == io_mem_ram.ram_addr || pd == io_mem_rom.ram_addr; + return memory_region_is_ram(s->mr); } -static bool is_romd(ram_addr_t pd) +static bool is_romd(MemoryRegionSection *s) { - MemoryRegion *mr; + MemoryRegion *mr = s->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) +static bool is_ram_rom_romd(MemoryRegionSection *s) { - return is_ram_rom(pd) || is_romd(pd); + return is_ram_rom(s) || is_romd(s); } /* Add a new TLB entry. At most one entry for a given virtual address @@ -2161,8 +2169,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; - unsigned long pd; + MemoryRegionSection section; unsigned int index; target_ulong address; target_ulong code_address; @@ -2175,8 +2182,7 @@ void tlb_set_page(CPUState *env, target_ulong vaddr, if (size != TARGET_PAGE_SIZE) { tlb_add_large_page(env, vaddr, size); } - p = phys_page_find(paddr >> TARGET_PAGE_BITS); - pd = p.phys_offset; + section = phys_page_find(paddr >> TARGET_PAGE_BITS); #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", @@ -2184,15 +2190,21 @@ void tlb_set_page(CPUState *env, target_ulong vaddr, #endif address = vaddr; - if (!is_ram_rom_romd(pd)) { + if (!is_ram_rom_romd(§ion)) { /* IO memory case (romd handled later) */ address |= TLB_MMIO; } - addend = (unsigned long)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK); - if (is_ram_rom(pd)) { + if (is_ram_rom_romd(§ion)) { + addend = (unsigned long)(memory_region_get_ram_ptr(section.mr) + + section.offset_within_region); + } else { + addend = 0; + } + if (is_ram_rom(§ion)) { /* Normal RAM. */ - iotlb = pd & TARGET_PAGE_MASK; - if ((pd & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) + iotlb = (memory_region_get_ram_addr(section.mr) + + section.offset_within_region) & TARGET_PAGE_MASK; + if (!section.readonly) iotlb |= io_mem_notdirty.ram_addr; else iotlb |= io_mem_rom.ram_addr; @@ -2203,8 +2215,8 @@ void tlb_set_page(CPUState *env, target_ulong vaddr, and avoid full address decoding in every device. 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); - iotlb += p.region_offset; + iotlb = memory_region_get_ram_addr(section.mr) & ~TARGET_PAGE_MASK; + iotlb += section.offset_within_region; } code_address = address; @@ -2237,11 +2249,14 @@ 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.ram_addr || is_romd(pd)) { + if ((memory_region_is_ram(section.mr) && section.readonly) + || is_romd(§ion)) { /* Write access calls the I/O callback. */ te->addr_write = address | TLB_MMIO; - } else if ((pd & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr && - !cpu_physical_memory_is_dirty(pd)) { + } else if (memory_region_is_ram(section.mr) + && !cpu_physical_memory_is_dirty( + section.mr->ram_addr + + section.offset_within_region)) { te->addr_write = address | TLB_NOTDIRTY; } else { te->addr_write = address; @@ -2535,28 +2550,7 @@ typedef struct subpage_t { static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, uint16_t section); -static subpage_t *subpage_init (target_phys_addr_t base, uint16_t *section, - uint16_t orig_section); -#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \ - need_subpage) \ - do { \ - if (addr > start_addr) \ - start_addr2 = 0; \ - else { \ - start_addr2 = start_addr & ~TARGET_PAGE_MASK; \ - if (start_addr2 > 0) \ - need_subpage = 1; \ - } \ - \ - if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \ - end_addr2 = TARGET_PAGE_SIZE - 1; \ - else { \ - end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \ - if (end_addr2 < TARGET_PAGE_SIZE - 1) \ - need_subpage = 1; \ - } \ - } while (0) - +static subpage_t *subpage_init(target_phys_addr_t base); static void destroy_page_desc(uint16_t section_index) { MemoryRegionSection *section = &phys_sections[section_index]; @@ -2619,47 +2613,81 @@ static void phys_sections_clear(void) 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(MemoryRegionSection *section, - bool readonly) +static void register_subpage(MemoryRegionSection *section) +{ + subpage_t *subpage; + target_phys_addr_t base = section->offset_within_address_space + & TARGET_PAGE_MASK; + MemoryRegionSection existing = phys_page_find(base >> TARGET_PAGE_BITS); + MemoryRegionSection subsection = { + .offset_within_address_space = base, + .size = TARGET_PAGE_SIZE, + }; + target_phys_addr_t start, end; + + assert(existing.mr->subpage || existing.mr == &io_mem_unassigned); + + if (!(existing.mr->subpage)) { + subpage = subpage_init(base); + subsection.mr = &subpage->iomem; + phys_page_set(base >> TARGET_PAGE_BITS, phys_section_add(&subsection)); + } else { + subpage = container_of(existing.mr, subpage_t, iomem); + } + start = section->offset_within_address_space & ~TARGET_PAGE_MASK; + end = start + section->size; + subpage_register(subpage, start, end, phys_section_add(section)); +} + + +static void register_multipage(MemoryRegionSection *section) { target_phys_addr_t start_addr = section->offset_within_address_space; ram_addr_t size = section->size; target_phys_addr_t addr, end_addr; - ram_addr_t orig_size = size; - subpage_t *subpage; uint16_t section_index = phys_section_add(section); assert(size); - size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; end_addr = start_addr + (target_phys_addr_t)size; addr = start_addr; do { - uint16_t *p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1); - uint16_t orig_memory = *p; - target_phys_addr_t start_addr2, end_addr2; - int need_subpage = 0; - MemoryRegion *mr = phys_sections[orig_memory].mr; - - CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, - need_subpage); - if (need_subpage) { - if (!(mr->subpage)) { - subpage = subpage_init((addr & TARGET_PAGE_MASK), - p, orig_memory); - } else { - subpage = container_of(mr, subpage_t, iomem); - } - subpage_register(subpage, start_addr2, end_addr2, - section_index); - } else { - *p = section_index; - } + phys_page_set(addr >> TARGET_PAGE_BITS, section_index); addr += TARGET_PAGE_SIZE; } while (addr != end_addr); } +void cpu_register_physical_memory_log(MemoryRegionSection *section, + bool readonly) +{ + MemoryRegionSection now = *section, remain = *section; + + if ((now.offset_within_address_space & ~TARGET_PAGE_MASK) + || (now.size < TARGET_PAGE_SIZE)) { + now.size = MIN(TARGET_PAGE_ALIGN(now.offset_within_address_space) + - now.offset_within_address_space, + now.size); + register_subpage(&now); + remain.size -= now.size; + remain.offset_within_address_space += now.size; + remain.offset_within_region += now.size; + } + now = remain; + now.size &= TARGET_PAGE_MASK; + if (now.size) { + register_multipage(&now); + remain.size -= now.size; + remain.offset_within_address_space += now.size; + remain.offset_within_region += now.size; + } + now = remain; + if (now.size) { + register_subpage(&now); + } +} + + void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size) { if (kvm_enabled()) @@ -3439,14 +3467,9 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, return 0; } -static subpage_t *subpage_init (target_phys_addr_t base, uint16_t *section_ind, - uint16_t orig_section) +static subpage_t *subpage_init(target_phys_addr_t base) { subpage_t *mmio; - MemoryRegionSection section = { - .offset_within_address_space = base, - .size = TARGET_PAGE_SIZE, - }; mmio = g_malloc0(sizeof(subpage_t)); @@ -3454,13 +3477,11 @@ static subpage_t *subpage_init (target_phys_addr_t base, uint16_t *section_ind, memory_region_init_io(&mmio->iomem, &subpage_ops, mmio, "subpage", TARGET_PAGE_SIZE); mmio->iomem.subpage = true; - section.mr = &mmio->iomem; #if defined(DEBUG_SUBPAGE) printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__, mmio, base, TARGET_PAGE_SIZE, subpage_memory); #endif - *section_ind = phys_section_add(§ion); - subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, orig_section); + subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, phys_section_unassigned); return mmio; } @@ -3788,22 +3809,22 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, uint8_t *ptr; uint32_t val; target_phys_addr_t page; - ram_addr_t pd; - PhysPageDesc p; + MemoryRegionSection section; while (len > 0) { page = addr & TARGET_PAGE_MASK; l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - p = phys_page_find(page >> TARGET_PAGE_BITS); - pd = p.phys_offset; + section = phys_page_find(page >> TARGET_PAGE_BITS); if (is_write) { - if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) { + if (!memory_region_is_ram(section.mr)) { target_phys_addr_t addr1; - io_index = pd & (IO_MEM_NB_ENTRIES - 1); - addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset; + io_index = memory_region_get_ram_addr(section.mr) + & (IO_MEM_NB_ENTRIES - 1); + addr1 = (addr & ~TARGET_PAGE_MASK) + + section.offset_within_region; /* XXX: could force cpu_single_env to NULL to avoid potential bugs */ if (l >= 4 && ((addr1 & 3) == 0)) { @@ -3822,9 +3843,11 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, io_mem_write(io_index, addr1, val, 1); l = 1; } - } else { + } else if (!section.readonly) { ram_addr_t addr1; - addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); + addr1 = (memory_region_get_ram_addr(section.mr) + + section.offset_within_region) + | (addr & ~TARGET_PAGE_MASK); /* RAM case */ ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); @@ -3838,11 +3861,13 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, qemu_put_ram_ptr(ptr); } } else { - if (!is_ram_rom_romd(pd)) { + if (!is_ram_rom_romd(§ion)) { target_phys_addr_t addr1; /* I/O case */ - io_index = pd & (IO_MEM_NB_ENTRIES - 1); - addr1 = (addr & ~TARGET_PAGE_MASK) + p.region_offset; + io_index = memory_region_get_ram_addr(section.mr) + & (IO_MEM_NB_ENTRIES - 1); + addr1 = (addr & ~TARGET_PAGE_MASK) + + section.offset_within_region; if (l >= 4 && ((addr1 & 3) == 0)) { /* 32 bit read access */ val = io_mem_read(io_index, addr1, 4); @@ -3861,7 +3886,8 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, } } else { /* RAM case */ - ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK); + ptr = qemu_get_ram_ptr(section.mr->ram_addr + + section.offset_within_region); memcpy(buf, ptr + (addr & ~TARGET_PAGE_MASK), l); qemu_put_ram_ptr(ptr); } @@ -3879,22 +3905,22 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, int l; uint8_t *ptr; target_phys_addr_t page; - unsigned long pd; - PhysPageDesc p; + MemoryRegionSection section; while (len > 0) { page = addr & TARGET_PAGE_MASK; l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - p = phys_page_find(page >> TARGET_PAGE_BITS); - pd = p.phys_offset; + section = phys_page_find(page >> TARGET_PAGE_BITS); - if (!is_ram_rom_romd(pd)) { + if (!is_ram_rom_romd(§ion)) { /* do nothing */ } else { unsigned long addr1; - addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); + addr1 = (memory_region_get_ram_addr(section.mr) + + section.offset_within_region) + + (addr & ~TARGET_PAGE_MASK); /* ROM/RAM case */ ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); @@ -3967,8 +3993,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, target_phys_addr_t todo = 0; int l; target_phys_addr_t page; - unsigned long pd; - PhysPageDesc p; + MemoryRegionSection section; ram_addr_t raddr = RAM_ADDR_MAX; ram_addr_t rlen; void *ret; @@ -3978,10 +4003,9 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - p = phys_page_find(page >> TARGET_PAGE_BITS); - pd = p.phys_offset; + section = phys_page_find(page >> TARGET_PAGE_BITS); - if ((pd & ~TARGET_PAGE_MASK) != io_mem_ram.ram_addr) { + if (!(memory_region_is_ram(section.mr) && !section.readonly)) { if (todo || bounce.buffer) { break; } @@ -3996,7 +4020,9 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, return bounce.buffer; } if (!todo) { - raddr = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); + raddr = memory_region_get_ram_addr(section.mr) + + section.offset_within_region + + (addr & ~TARGET_PAGE_MASK); } len -= l; @@ -4055,16 +4081,15 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr, int io_index; uint8_t *ptr; uint32_t val; - unsigned long pd; - PhysPageDesc p; + MemoryRegionSection section; - p = phys_page_find(addr >> TARGET_PAGE_BITS); - pd = p.phys_offset; + section = phys_page_find(addr >> TARGET_PAGE_BITS); - if (!is_ram_rom_romd(pd)) { + if (!is_ram_rom_romd(§ion)) { /* I/O case */ - io_index = pd & (IO_MEM_NB_ENTRIES - 1); - addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset; + io_index = memory_region_get_ram_addr(section.mr) + & (IO_MEM_NB_ENTRIES - 1); + addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region; val = io_mem_read(io_index, addr, 4); #if defined(TARGET_WORDS_BIGENDIAN) if (endian == DEVICE_LITTLE_ENDIAN) { @@ -4077,7 +4102,9 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr, #endif } else { /* RAM case */ - ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) + + ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr) + & TARGET_PAGE_MASK) + + section.offset_within_region) + (addr & ~TARGET_PAGE_MASK); switch (endian) { case DEVICE_LITTLE_ENDIAN: @@ -4116,16 +4143,15 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr, int io_index; uint8_t *ptr; uint64_t val; - unsigned long pd; - PhysPageDesc p; + MemoryRegionSection section; - p = phys_page_find(addr >> TARGET_PAGE_BITS); - pd = p.phys_offset; + section = phys_page_find(addr >> TARGET_PAGE_BITS); - if (!is_ram_rom_romd(pd)) { + if (!is_ram_rom_romd(§ion)) { /* I/O case */ - io_index = pd & (IO_MEM_NB_ENTRIES - 1); - addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset; + io_index = memory_region_get_ram_addr(section.mr) + & (IO_MEM_NB_ENTRIES - 1); + addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region; /* XXX This is broken when device endian != cpu endian. Fix and add "endian" variable check */ @@ -4138,8 +4164,10 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr, #endif } else { /* RAM case */ - ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) + - (addr & ~TARGET_PAGE_MASK); + ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr) + & TARGET_PAGE_MASK) + + section.offset_within_region) + + (addr & ~TARGET_PAGE_MASK); switch (endian) { case DEVICE_LITTLE_ENDIAN: val = ldq_le_p(ptr); @@ -4185,16 +4213,15 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr, int io_index; uint8_t *ptr; uint64_t val; - unsigned long pd; - PhysPageDesc p; + MemoryRegionSection section; - p = phys_page_find(addr >> TARGET_PAGE_BITS); - pd = p.phys_offset; + section = phys_page_find(addr >> TARGET_PAGE_BITS); - if (!is_ram_rom_romd(pd)) { + if (!is_ram_rom_romd(§ion)) { /* I/O case */ - io_index = pd & (IO_MEM_NB_ENTRIES - 1); - addr = (addr & ~TARGET_PAGE_MASK) + p.region_offset; + io_index = memory_region_get_ram_addr(section.mr) + & (IO_MEM_NB_ENTRIES - 1); + addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region; val = io_mem_read(io_index, addr, 2); #if defined(TARGET_WORDS_BIGENDIAN) if (endian == DEVICE_LITTLE_ENDIAN) { @@ -4207,8 +4234,10 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr, #endif } else { /* RAM case */ - ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) + - (addr & ~TARGET_PAGE_MASK); + ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr) + & TARGET_PAGE_MASK) + + section.offset_within_region) + + (addr & ~TARGET_PAGE_MASK); switch (endian) { case DEVICE_LITTLE_ENDIAN: val = lduw_le_p(ptr); @@ -4246,18 +4275,23 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val) { int io_index; uint8_t *ptr; - unsigned long pd; - PhysPageDesc p; + MemoryRegionSection section; - p = phys_page_find(addr >> TARGET_PAGE_BITS); - pd = p.phys_offset; + section = phys_page_find(addr >> TARGET_PAGE_BITS); - 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 (!memory_region_is_ram(section.mr) || section.readonly) { + if (memory_region_is_ram(section.mr)) { + io_index = io_mem_rom.ram_addr; + } else { + io_index = memory_region_get_ram_addr(section.mr); + } + addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region; io_mem_write(io_index, addr, val, 4); } else { - unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); + unsigned long addr1 = (memory_region_get_ram_addr(section.mr) + & TARGET_PAGE_MASK) + + section.offset_within_region + + (addr & ~TARGET_PAGE_MASK); ptr = qemu_get_ram_ptr(addr1); stl_p(ptr, val); @@ -4277,15 +4311,18 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val) { int io_index; uint8_t *ptr; - unsigned long pd; - PhysPageDesc p; + MemoryRegionSection section; - p = phys_page_find(addr >> TARGET_PAGE_BITS); - pd = p.phys_offset; + section = phys_page_find(addr >> TARGET_PAGE_BITS); - 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 (!memory_region_is_ram(section.mr) || section.readonly) { + if (memory_region_is_ram(section.mr)) { + io_index = io_mem_rom.ram_addr; + } else { + io_index = memory_region_get_ram_addr(section.mr) + & (IO_MEM_NB_ENTRIES - 1); + } + addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region; #ifdef TARGET_WORDS_BIGENDIAN io_mem_write(io_index, addr, val >> 32, 4); io_mem_write(io_index, addr + 4, (uint32_t)val, 4); @@ -4294,8 +4331,10 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val) io_mem_write(io_index, addr + 4, val >> 32, 4); #endif } else { - ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) + - (addr & ~TARGET_PAGE_MASK); + ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section.mr) + & TARGET_PAGE_MASK) + + section.offset_within_region) + + (addr & ~TARGET_PAGE_MASK); stq_p(ptr, val); } } @@ -4306,15 +4345,18 @@ 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; + MemoryRegionSection section; - p = phys_page_find(addr >> TARGET_PAGE_BITS); - pd = p.phys_offset; + section = phys_page_find(addr >> TARGET_PAGE_BITS); - 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 (!memory_region_is_ram(section.mr) || section.readonly) { + if (memory_region_is_ram(section.mr)) { + io_index = io_mem_rom.ram_addr; + } else { + io_index = memory_region_get_ram_addr(section.mr) + & (IO_MEM_NB_ENTRIES - 1); + } + addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region; #if defined(TARGET_WORDS_BIGENDIAN) if (endian == DEVICE_LITTLE_ENDIAN) { val = bswap32(val); @@ -4327,7 +4369,9 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val, io_mem_write(io_index, addr, val, 4); } else { unsigned long addr1; - addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); + addr1 = (memory_region_get_ram_addr(section.mr) & TARGET_PAGE_MASK) + + section.offset_within_region + + (addr & ~TARGET_PAGE_MASK); /* RAM case */ ptr = qemu_get_ram_ptr(addr1); switch (endian) { @@ -4379,15 +4423,18 @@ 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; + MemoryRegionSection section; - p = phys_page_find(addr >> TARGET_PAGE_BITS); - pd = p.phys_offset; + section = phys_page_find(addr >> TARGET_PAGE_BITS); - 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 (!memory_region_is_ram(section.mr) || section.readonly) { + if (memory_region_is_ram(section.mr)) { + io_index = io_mem_rom.ram_addr; + } else { + io_index = memory_region_get_ram_addr(section.mr) + & (IO_MEM_NB_ENTRIES - 1); + } + addr = (addr & ~TARGET_PAGE_MASK) + section.offset_within_region; #if defined(TARGET_WORDS_BIGENDIAN) if (endian == DEVICE_LITTLE_ENDIAN) { val = bswap16(val); @@ -4400,7 +4447,8 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val, io_mem_write(io_index, addr, val, 2); } else { unsigned long addr1; - addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); + addr1 = (memory_region_get_ram_addr(section.mr) & TARGET_PAGE_MASK) + + section.offset_within_region + (addr & ~TARGET_PAGE_MASK); /* RAM case */ ptr = qemu_get_ram_ptr(addr1); switch (endian) { @@ -4617,7 +4665,7 @@ tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong 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)) { + && !io_mem_region[pd]->rom_device) { #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC) cpu_unassigned_access(env1, addr, 0, 1, 0, 4); #else