memory: add address_space_translate
Using phys_page_find to translate an AddressSpace to a MemoryRegionSection is unwieldy. It requires to pass the page index rather than the address, and later memory_region_section_addr has to be called. Replace memory_region_section_addr with a function that does all of it: call phys_page_find, compute the offset within the region, and check how big the current mapping is. This way, a large flat region can be written with a single lookup rather than a page at a time. address_space_translate will also provide a single point where IOMMU forwarding is implemented. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
b018ddf633
commit
149f54b53b
20
cputlb.c
20
cputlb.c
@ -248,13 +248,18 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
|
||||
target_ulong code_address;
|
||||
uintptr_t addend;
|
||||
CPUTLBEntry *te;
|
||||
hwaddr iotlb;
|
||||
hwaddr iotlb, xlat, sz;
|
||||
|
||||
assert(size >= TARGET_PAGE_SIZE);
|
||||
if (size != TARGET_PAGE_SIZE) {
|
||||
tlb_add_large_page(env, vaddr, size);
|
||||
}
|
||||
section = phys_page_find(address_space_memory.dispatch, paddr >> TARGET_PAGE_BITS);
|
||||
|
||||
sz = size;
|
||||
section = address_space_translate(&address_space_memory, paddr, &xlat, &sz,
|
||||
false);
|
||||
assert(sz >= TARGET_PAGE_SIZE);
|
||||
|
||||
#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",
|
||||
@ -268,13 +273,12 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
|
||||
addend = 0;
|
||||
} else {
|
||||
/* TLB_MMIO for rom/romd handled below */
|
||||
addend = (uintptr_t)memory_region_get_ram_ptr(section->mr)
|
||||
+ memory_region_section_addr(section, paddr);
|
||||
addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
|
||||
}
|
||||
|
||||
code_address = address;
|
||||
iotlb = memory_region_section_get_iotlb(env, section, vaddr, paddr, prot,
|
||||
&address);
|
||||
iotlb = memory_region_section_get_iotlb(env, section, vaddr, paddr, xlat,
|
||||
prot, &address);
|
||||
|
||||
index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
env->iotlb[mmu_idx][index] = iotlb - vaddr;
|
||||
@ -297,9 +301,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
|
||||
/* Write access calls the I/O callback. */
|
||||
te->addr_write = address | TLB_MMIO;
|
||||
} else if (memory_region_is_ram(section->mr)
|
||||
&& !cpu_physical_memory_is_dirty(
|
||||
section->mr->ram_addr
|
||||
+ memory_region_section_addr(section, paddr))) {
|
||||
&& !cpu_physical_memory_is_dirty(section->mr->ram_addr + xlat)) {
|
||||
te->addr_write = address | TLB_NOTDIRTY;
|
||||
} else {
|
||||
te->addr_write = address;
|
||||
|
192
exec.c
192
exec.c
@ -182,7 +182,7 @@ static void phys_page_set(AddressSpaceDispatch *d,
|
||||
phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
|
||||
}
|
||||
|
||||
MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
|
||||
static MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
|
||||
{
|
||||
PhysPageEntry lp = d->phys_map;
|
||||
PhysPageEntry *p;
|
||||
@ -203,6 +203,25 @@ bool memory_region_is_unassigned(MemoryRegion *mr)
|
||||
return mr != &io_mem_rom && mr != &io_mem_notdirty && !mr->rom_device
|
||||
&& mr != &io_mem_watch;
|
||||
}
|
||||
|
||||
MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr,
|
||||
hwaddr *xlat, hwaddr *plen,
|
||||
bool is_write)
|
||||
{
|
||||
MemoryRegionSection *section;
|
||||
Int128 diff;
|
||||
|
||||
section = phys_page_find(as->dispatch, addr >> TARGET_PAGE_BITS);
|
||||
/* Compute offset within MemoryRegionSection */
|
||||
addr -= section->offset_within_address_space;
|
||||
|
||||
/* Compute offset within MemoryRegion */
|
||||
*xlat = addr + section->offset_within_region;
|
||||
|
||||
diff = int128_sub(section->mr->size, int128_make64(addr));
|
||||
*plen = MIN(int128_get64(diff), *plen);
|
||||
return section;
|
||||
}
|
||||
#endif
|
||||
|
||||
void cpu_exec_init_all(void)
|
||||
@ -615,11 +634,11 @@ static int cpu_physical_memory_set_dirty_tracking(int enable)
|
||||
}
|
||||
|
||||
hwaddr memory_region_section_get_iotlb(CPUArchState *env,
|
||||
MemoryRegionSection *section,
|
||||
target_ulong vaddr,
|
||||
hwaddr paddr,
|
||||
int prot,
|
||||
target_ulong *address)
|
||||
MemoryRegionSection *section,
|
||||
target_ulong vaddr,
|
||||
hwaddr paddr, hwaddr xlat,
|
||||
int prot,
|
||||
target_ulong *address)
|
||||
{
|
||||
hwaddr iotlb;
|
||||
CPUWatchpoint *wp;
|
||||
@ -627,7 +646,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env,
|
||||
if (memory_region_is_ram(section->mr)) {
|
||||
/* Normal RAM. */
|
||||
iotlb = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
|
||||
+ memory_region_section_addr(section, paddr);
|
||||
+ xlat;
|
||||
if (!section->readonly) {
|
||||
iotlb |= phys_section_notdirty;
|
||||
} else {
|
||||
@ -635,7 +654,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env,
|
||||
}
|
||||
} else {
|
||||
iotlb = section - phys_sections;
|
||||
iotlb += memory_region_section_addr(section, paddr);
|
||||
iotlb += xlat;
|
||||
}
|
||||
|
||||
/* Make accesses to pages with watchpoints go via the
|
||||
@ -1852,24 +1871,18 @@ static void invalidate_and_set_dirty(hwaddr addr,
|
||||
void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
|
||||
int len, bool is_write)
|
||||
{
|
||||
AddressSpaceDispatch *d = as->dispatch;
|
||||
int l;
|
||||
hwaddr l;
|
||||
uint8_t *ptr;
|
||||
uint32_t val;
|
||||
hwaddr page;
|
||||
hwaddr addr1;
|
||||
MemoryRegionSection *section;
|
||||
|
||||
while (len > 0) {
|
||||
page = addr & TARGET_PAGE_MASK;
|
||||
l = (page + TARGET_PAGE_SIZE) - addr;
|
||||
if (l > len)
|
||||
l = len;
|
||||
section = phys_page_find(d, page >> TARGET_PAGE_BITS);
|
||||
l = len;
|
||||
section = address_space_translate(as, addr, &addr1, &l, is_write);
|
||||
|
||||
if (is_write) {
|
||||
if (!memory_region_is_ram(section->mr)) {
|
||||
hwaddr addr1;
|
||||
addr1 = memory_region_section_addr(section, addr);
|
||||
/* XXX: could force cpu_single_env to NULL to avoid
|
||||
potential bugs */
|
||||
if (l >= 4 && ((addr1 & 3) == 0)) {
|
||||
@ -1889,9 +1902,7 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
|
||||
l = 1;
|
||||
}
|
||||
} else if (!section->readonly) {
|
||||
ram_addr_t addr1;
|
||||
addr1 = memory_region_get_ram_addr(section->mr)
|
||||
+ memory_region_section_addr(section, addr);
|
||||
addr1 += memory_region_get_ram_addr(section->mr);
|
||||
/* RAM case */
|
||||
ptr = qemu_get_ram_ptr(addr1);
|
||||
memcpy(ptr, buf, l);
|
||||
@ -1900,9 +1911,7 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
|
||||
} else {
|
||||
if (!(memory_region_is_ram(section->mr) ||
|
||||
memory_region_is_romd(section->mr))) {
|
||||
hwaddr addr1;
|
||||
/* I/O case */
|
||||
addr1 = memory_region_section_addr(section, addr);
|
||||
if (l >= 4 && ((addr1 & 3) == 0)) {
|
||||
/* 32 bit read access */
|
||||
val = io_mem_read(section->mr, addr1, 4);
|
||||
@ -1921,9 +1930,7 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
|
||||
}
|
||||
} else {
|
||||
/* RAM case */
|
||||
ptr = qemu_get_ram_ptr(section->mr->ram_addr
|
||||
+ memory_region_section_addr(section,
|
||||
addr));
|
||||
ptr = qemu_get_ram_ptr(section->mr->ram_addr + addr1);
|
||||
memcpy(buf, ptr, l);
|
||||
}
|
||||
}
|
||||
@ -1962,26 +1969,21 @@ void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
|
||||
void cpu_physical_memory_write_rom(hwaddr addr,
|
||||
const uint8_t *buf, int len)
|
||||
{
|
||||
AddressSpaceDispatch *d = address_space_memory.dispatch;
|
||||
int l;
|
||||
hwaddr l;
|
||||
uint8_t *ptr;
|
||||
hwaddr page;
|
||||
hwaddr addr1;
|
||||
MemoryRegionSection *section;
|
||||
|
||||
while (len > 0) {
|
||||
page = addr & TARGET_PAGE_MASK;
|
||||
l = (page + TARGET_PAGE_SIZE) - addr;
|
||||
if (l > len)
|
||||
l = len;
|
||||
section = phys_page_find(d, page >> TARGET_PAGE_BITS);
|
||||
l = len;
|
||||
section = address_space_translate(&address_space_memory,
|
||||
addr, &addr1, &l, true);
|
||||
|
||||
if (!(memory_region_is_ram(section->mr) ||
|
||||
memory_region_is_romd(section->mr))) {
|
||||
/* do nothing */
|
||||
} else {
|
||||
unsigned long addr1;
|
||||
addr1 = memory_region_get_ram_addr(section->mr)
|
||||
+ memory_region_section_addr(section, addr);
|
||||
addr1 += memory_region_get_ram_addr(section->mr);
|
||||
/* ROM/RAM case */
|
||||
ptr = qemu_get_ram_ptr(addr1);
|
||||
memcpy(ptr, buf, l);
|
||||
@ -2051,22 +2053,17 @@ void *address_space_map(AddressSpace *as,
|
||||
hwaddr *plen,
|
||||
bool is_write)
|
||||
{
|
||||
AddressSpaceDispatch *d = as->dispatch;
|
||||
hwaddr len = *plen;
|
||||
hwaddr todo = 0;
|
||||
int l;
|
||||
hwaddr page;
|
||||
hwaddr l, xlat;
|
||||
MemoryRegionSection *section;
|
||||
ram_addr_t raddr = RAM_ADDR_MAX;
|
||||
ram_addr_t rlen;
|
||||
void *ret;
|
||||
|
||||
while (len > 0) {
|
||||
page = addr & TARGET_PAGE_MASK;
|
||||
l = (page + TARGET_PAGE_SIZE) - addr;
|
||||
if (l > len)
|
||||
l = len;
|
||||
section = phys_page_find(d, page >> TARGET_PAGE_BITS);
|
||||
l = len;
|
||||
section = address_space_translate(as, addr, &xlat, &l, is_write);
|
||||
|
||||
if (!(memory_region_is_ram(section->mr) && !section->readonly)) {
|
||||
if (todo || bounce.buffer) {
|
||||
@ -2083,8 +2080,11 @@ void *address_space_map(AddressSpace *as,
|
||||
return bounce.buffer;
|
||||
}
|
||||
if (!todo) {
|
||||
raddr = memory_region_get_ram_addr(section->mr)
|
||||
+ memory_region_section_addr(section, addr);
|
||||
raddr = memory_region_get_ram_addr(section->mr) + xlat;
|
||||
} else {
|
||||
if (memory_region_get_ram_addr(section->mr) + xlat != raddr + todo) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
len -= l;
|
||||
@ -2150,14 +2150,16 @@ static inline uint32_t ldl_phys_internal(hwaddr addr,
|
||||
uint8_t *ptr;
|
||||
uint32_t val;
|
||||
MemoryRegionSection *section;
|
||||
hwaddr l = 4;
|
||||
hwaddr addr1;
|
||||
|
||||
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
|
||||
|
||||
if (!(memory_region_is_ram(section->mr) ||
|
||||
section = address_space_translate(&address_space_memory, addr, &addr1, &l,
|
||||
false);
|
||||
if (l < 4 ||
|
||||
!(memory_region_is_ram(section->mr) ||
|
||||
memory_region_is_romd(section->mr))) {
|
||||
/* I/O case */
|
||||
addr = memory_region_section_addr(section, addr);
|
||||
val = io_mem_read(section->mr, addr, 4);
|
||||
val = io_mem_read(section->mr, addr1, 4);
|
||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||
if (endian == DEVICE_LITTLE_ENDIAN) {
|
||||
val = bswap32(val);
|
||||
@ -2171,7 +2173,7 @@ static inline uint32_t ldl_phys_internal(hwaddr addr,
|
||||
/* RAM case */
|
||||
ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
|
||||
& TARGET_PAGE_MASK)
|
||||
+ memory_region_section_addr(section, addr));
|
||||
+ addr1);
|
||||
switch (endian) {
|
||||
case DEVICE_LITTLE_ENDIAN:
|
||||
val = ldl_le_p(ptr);
|
||||
@ -2209,28 +2211,30 @@ static inline uint64_t ldq_phys_internal(hwaddr addr,
|
||||
uint8_t *ptr;
|
||||
uint64_t val;
|
||||
MemoryRegionSection *section;
|
||||
hwaddr l = 8;
|
||||
hwaddr addr1;
|
||||
|
||||
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
|
||||
|
||||
if (!(memory_region_is_ram(section->mr) ||
|
||||
section = address_space_translate(&address_space_memory, addr, &addr1, &l,
|
||||
false);
|
||||
if (l < 8 ||
|
||||
!(memory_region_is_ram(section->mr) ||
|
||||
memory_region_is_romd(section->mr))) {
|
||||
/* I/O case */
|
||||
addr = memory_region_section_addr(section, addr);
|
||||
|
||||
/* XXX This is broken when device endian != cpu endian.
|
||||
Fix and add "endian" variable check */
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
val = io_mem_read(section->mr, addr, 4) << 32;
|
||||
val |= io_mem_read(section->mr, addr + 4, 4);
|
||||
val = io_mem_read(section->mr, addr1, 4) << 32;
|
||||
val |= io_mem_read(section->mr, addr1 + 4, 4);
|
||||
#else
|
||||
val = io_mem_read(section->mr, addr, 4);
|
||||
val |= io_mem_read(section->mr, addr + 4, 4) << 32;
|
||||
val = io_mem_read(section->mr, addr1, 4);
|
||||
val |= io_mem_read(section->mr, addr1 + 4, 4) << 32;
|
||||
#endif
|
||||
} else {
|
||||
/* RAM case */
|
||||
ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
|
||||
& TARGET_PAGE_MASK)
|
||||
+ memory_region_section_addr(section, addr));
|
||||
+ addr1);
|
||||
switch (endian) {
|
||||
case DEVICE_LITTLE_ENDIAN:
|
||||
val = ldq_le_p(ptr);
|
||||
@ -2276,14 +2280,16 @@ static inline uint32_t lduw_phys_internal(hwaddr addr,
|
||||
uint8_t *ptr;
|
||||
uint64_t val;
|
||||
MemoryRegionSection *section;
|
||||
hwaddr l = 2;
|
||||
hwaddr addr1;
|
||||
|
||||
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
|
||||
|
||||
if (!(memory_region_is_ram(section->mr) ||
|
||||
section = address_space_translate(&address_space_memory, addr, &addr1, &l,
|
||||
false);
|
||||
if (l < 2 ||
|
||||
!(memory_region_is_ram(section->mr) ||
|
||||
memory_region_is_romd(section->mr))) {
|
||||
/* I/O case */
|
||||
addr = memory_region_section_addr(section, addr);
|
||||
val = io_mem_read(section->mr, addr, 2);
|
||||
val = io_mem_read(section->mr, addr1, 2);
|
||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||
if (endian == DEVICE_LITTLE_ENDIAN) {
|
||||
val = bswap16(val);
|
||||
@ -2297,7 +2303,7 @@ static inline uint32_t lduw_phys_internal(hwaddr addr,
|
||||
/* RAM case */
|
||||
ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
|
||||
& TARGET_PAGE_MASK)
|
||||
+ memory_region_section_addr(section, addr));
|
||||
+ addr1);
|
||||
switch (endian) {
|
||||
case DEVICE_LITTLE_ENDIAN:
|
||||
val = lduw_le_p(ptr);
|
||||
@ -2335,19 +2341,18 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val)
|
||||
{
|
||||
uint8_t *ptr;
|
||||
MemoryRegionSection *section;
|
||||
hwaddr l = 4;
|
||||
hwaddr addr1;
|
||||
|
||||
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
|
||||
|
||||
if (!memory_region_is_ram(section->mr) || section->readonly) {
|
||||
addr = memory_region_section_addr(section, addr);
|
||||
section = address_space_translate(&address_space_memory, addr, &addr1, &l,
|
||||
true);
|
||||
if (l < 4 || !memory_region_is_ram(section->mr) || section->readonly) {
|
||||
if (memory_region_is_ram(section->mr)) {
|
||||
section = &phys_sections[phys_section_rom];
|
||||
}
|
||||
io_mem_write(section->mr, addr, val, 4);
|
||||
io_mem_write(section->mr, addr1, val, 4);
|
||||
} else {
|
||||
unsigned long addr1 = (memory_region_get_ram_addr(section->mr)
|
||||
& TARGET_PAGE_MASK)
|
||||
+ memory_region_section_addr(section, addr);
|
||||
addr1 += memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK;
|
||||
ptr = qemu_get_ram_ptr(addr1);
|
||||
stl_p(ptr, val);
|
||||
|
||||
@ -2369,11 +2374,12 @@ static inline void stl_phys_internal(hwaddr addr, uint32_t val,
|
||||
{
|
||||
uint8_t *ptr;
|
||||
MemoryRegionSection *section;
|
||||
hwaddr l = 4;
|
||||
hwaddr addr1;
|
||||
|
||||
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
|
||||
|
||||
if (!memory_region_is_ram(section->mr) || section->readonly) {
|
||||
addr = memory_region_section_addr(section, addr);
|
||||
section = address_space_translate(&address_space_memory, addr, &addr1, &l,
|
||||
true);
|
||||
if (l < 4 || !memory_region_is_ram(section->mr) || section->readonly) {
|
||||
if (memory_region_is_ram(section->mr)) {
|
||||
section = &phys_sections[phys_section_rom];
|
||||
}
|
||||
@ -2386,12 +2392,10 @@ static inline void stl_phys_internal(hwaddr addr, uint32_t val,
|
||||
val = bswap32(val);
|
||||
}
|
||||
#endif
|
||||
io_mem_write(section->mr, addr, val, 4);
|
||||
io_mem_write(section->mr, addr1, val, 4);
|
||||
} else {
|
||||
unsigned long addr1;
|
||||
addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
|
||||
+ memory_region_section_addr(section, addr);
|
||||
/* RAM case */
|
||||
addr1 += memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK;
|
||||
ptr = qemu_get_ram_ptr(addr1);
|
||||
switch (endian) {
|
||||
case DEVICE_LITTLE_ENDIAN:
|
||||
@ -2436,11 +2440,12 @@ static inline void stw_phys_internal(hwaddr addr, uint32_t val,
|
||||
{
|
||||
uint8_t *ptr;
|
||||
MemoryRegionSection *section;
|
||||
hwaddr l = 2;
|
||||
hwaddr addr1;
|
||||
|
||||
section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
|
||||
|
||||
if (!memory_region_is_ram(section->mr) || section->readonly) {
|
||||
addr = memory_region_section_addr(section, addr);
|
||||
section = address_space_translate(&address_space_memory, addr, &addr1, &l,
|
||||
true);
|
||||
if (l < 2 || !memory_region_is_ram(section->mr) || section->readonly) {
|
||||
if (memory_region_is_ram(section->mr)) {
|
||||
section = &phys_sections[phys_section_rom];
|
||||
}
|
||||
@ -2453,12 +2458,10 @@ static inline void stw_phys_internal(hwaddr addr, uint32_t val,
|
||||
val = bswap16(val);
|
||||
}
|
||||
#endif
|
||||
io_mem_write(section->mr, addr, val, 2);
|
||||
io_mem_write(section->mr, addr1, val, 2);
|
||||
} else {
|
||||
unsigned long addr1;
|
||||
addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
|
||||
+ memory_region_section_addr(section, addr);
|
||||
/* RAM case */
|
||||
addr1 += memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK;
|
||||
ptr = qemu_get_ram_ptr(addr1);
|
||||
switch (endian) {
|
||||
case DEVICE_LITTLE_ENDIAN:
|
||||
@ -2561,9 +2564,10 @@ bool virtio_is_big_endian(void)
|
||||
bool cpu_physical_memory_is_io(hwaddr phys_addr)
|
||||
{
|
||||
MemoryRegionSection *section;
|
||||
hwaddr l = 1;
|
||||
|
||||
section = phys_page_find(address_space_memory.dispatch,
|
||||
phys_addr >> TARGET_PAGE_BITS);
|
||||
section = address_space_translate(&address_space_memory,
|
||||
phys_addr, &phys_addr, &l, false);
|
||||
|
||||
return !(memory_region_is_ram(section->mr) ||
|
||||
memory_region_is_romd(section->mr));
|
||||
|
@ -26,8 +26,6 @@ void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
|
||||
target_ulong vaddr);
|
||||
void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start,
|
||||
uintptr_t length);
|
||||
MemoryRegionSection *phys_page_find(struct AddressSpaceDispatch *d,
|
||||
hwaddr index);
|
||||
void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length);
|
||||
void tlb_set_dirty(CPUArchState *env, target_ulong vaddr);
|
||||
extern int tlb_flush_count;
|
||||
@ -35,11 +33,11 @@ extern int tlb_flush_count;
|
||||
/* exec.c */
|
||||
void tb_flush_jmp_cache(CPUArchState *env, target_ulong addr);
|
||||
hwaddr memory_region_section_get_iotlb(CPUArchState *env,
|
||||
MemoryRegionSection *section,
|
||||
target_ulong vaddr,
|
||||
hwaddr paddr,
|
||||
int prot,
|
||||
target_ulong *address);
|
||||
MemoryRegionSection *section,
|
||||
target_ulong vaddr,
|
||||
hwaddr paddr, hwaddr xlat,
|
||||
int prot,
|
||||
target_ulong *address);
|
||||
bool memory_region_is_unassigned(MemoryRegion *mr);
|
||||
|
||||
#endif
|
||||
|
@ -751,23 +751,6 @@ void memory_region_set_alias_offset(MemoryRegion *mr,
|
||||
MemoryRegionSection memory_region_find(MemoryRegion *mr,
|
||||
hwaddr addr, uint64_t size);
|
||||
|
||||
/**
|
||||
* memory_region_section_addr: get offset within MemoryRegionSection
|
||||
*
|
||||
* Returns offset within MemoryRegionSection
|
||||
*
|
||||
* @section: the memory region section being queried
|
||||
* @addr: address in address space
|
||||
*/
|
||||
static inline hwaddr
|
||||
memory_region_section_addr(MemoryRegionSection *section,
|
||||
hwaddr addr)
|
||||
{
|
||||
addr -= section->offset_within_address_space;
|
||||
addr += section->offset_within_region;
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* address_space_sync_dirty_bitmap: synchronize the dirty log for all memory
|
||||
*
|
||||
@ -869,6 +852,20 @@ void address_space_write(AddressSpace *as, hwaddr addr,
|
||||
*/
|
||||
void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
|
||||
|
||||
/* address_space_translate: translate an address range into an address space
|
||||
* into a MemoryRegionSection and an address range into that section
|
||||
*
|
||||
* @as: #AddressSpace to be accessed
|
||||
* @addr: address within that address space
|
||||
* @xlat: pointer to address within the returned memory region section's
|
||||
* #MemoryRegion.
|
||||
* @len: pointer to length
|
||||
* @is_write: indicates the transfer direction
|
||||
*/
|
||||
MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr,
|
||||
hwaddr *xlat, hwaddr *len,
|
||||
bool is_write);
|
||||
|
||||
/* address_space_map: map a physical memory region into a host virtual address
|
||||
*
|
||||
* May map a subset of the requested range, given by and returned in @plen.
|
||||
|
@ -1354,15 +1354,15 @@ void tb_invalidate_phys_addr(hwaddr addr)
|
||||
{
|
||||
ram_addr_t ram_addr;
|
||||
MemoryRegionSection *section;
|
||||
hwaddr l = 1;
|
||||
|
||||
section = phys_page_find(address_space_memory.dispatch,
|
||||
addr >> TARGET_PAGE_BITS);
|
||||
section = address_space_translate(&address_space_memory, addr, &addr, &l, false);
|
||||
if (!(memory_region_is_ram(section->mr)
|
||||
|| memory_region_is_romd(section->mr))) {
|
||||
return;
|
||||
}
|
||||
ram_addr = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
|
||||
+ memory_region_section_addr(section, addr);
|
||||
+ addr;
|
||||
tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
|
||||
}
|
||||
#endif /* TARGET_HAS_ICE && !defined(CONFIG_USER_ONLY) */
|
||||
|
Loading…
Reference in New Issue
Block a user