From patchwork Wed Oct 3 16:04:02 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avi Kivity X-Patchwork-Id: 188853 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 6DC442C00C1 for ; Thu, 4 Oct 2012 03:20:00 +1000 (EST) Received: from localhost ([::1]:51293 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TJRSU-0008Ld-8n for incoming@patchwork.ozlabs.org; Wed, 03 Oct 2012 12:06:02 -0400 Received: from eggs.gnu.org ([208.118.235.92]:33949) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TJRRZ-0007RO-Re for qemu-devel@nongnu.org; Wed, 03 Oct 2012 12:05:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TJRRO-0007vQ-HF for qemu-devel@nongnu.org; Wed, 03 Oct 2012 12:05:05 -0400 Received: from mx1.redhat.com ([209.132.183.28]:61403) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TJRRO-0007vF-5o for qemu-devel@nongnu.org; Wed, 03 Oct 2012 12:04:54 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q93G4onP008520 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 3 Oct 2012 12:04:51 -0400 Received: from s01.tlv.redhat.com (s01.tlv.redhat.com [10.35.255.8]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q93G47J3016728; Wed, 3 Oct 2012 12:04:49 -0400 From: Avi Kivity To: qemu-devel@nongnu.org, Anthony Liguori , liu ping fan , "Michael S. Tsirkin" , Paolo Bonzini , Blue Swirl Date: Wed, 3 Oct 2012 18:04:02 +0200 Message-Id: <1349280245-16341-20-git-send-email-avi@redhat.com> In-Reply-To: <1349280245-16341-1-git-send-email-avi@redhat.com> References: <1349280245-16341-1-git-send-email-avi@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC v1 19/22] memory: per-AddressSpace dispatch X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Currently we use a global radix tree to dispatch memory access. This only works with a single address space; to support multiple address spaces we make the radix tree a member of AddressSpace (via an intermediate structure AddressSpaceDispatch to avoid exposing too many internals). A side effect is that address_space_io also gains a dispatch table. When we remove all the pre-memory-API I/O registrations, we can use that for dispatching I/O and get rid of the original I/O dispatch. Signed-off-by: Avi Kivity --- cputlb.c | 3 +- cputlb.h | 3 +- exec.c | 176 +++++++++++++++++++++++++++++++++--------------------- memory-internal.h | 22 ++++++- memory.c | 1 + memory.h | 62 +++++++++++++++++++ 6 files changed, 196 insertions(+), 71 deletions(-) diff --git a/cputlb.c b/cputlb.c index 0627f32..9027557 100644 --- a/cputlb.c +++ b/cputlb.c @@ -21,6 +21,7 @@ #include "cpu.h" #include "exec-all.h" #include "memory.h" +#include "exec-memory.h" #include "cputlb.h" @@ -251,7 +252,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, if (size != TARGET_PAGE_SIZE) { tlb_add_large_page(env, vaddr, size); } - section = phys_page_find(paddr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, 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", diff --git a/cputlb.h b/cputlb.h index 2dc2c96..d537b77 100644 --- a/cputlb.h +++ b/cputlb.h @@ -26,7 +26,8 @@ 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(target_phys_addr_t index); +MemoryRegionSection *phys_page_find(struct AddressSpaceDispatch *d, + target_phys_addr_t 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; diff --git a/exec.c b/exec.c index 7a76efa..42f9ad1 100644 --- a/exec.c +++ b/exec.c @@ -187,7 +187,6 @@ static void *l1_map[V_L1_SIZE]; #if !defined(CONFIG_USER_ONLY) -typedef struct PhysPageEntry PhysPageEntry; static MemoryRegionSection *phys_sections; static unsigned phys_sections_nb, phys_sections_nb_alloc; @@ -196,22 +195,12 @@ static uint16_t phys_section_rom; static uint16_t phys_section_watch; -struct PhysPageEntry { - uint16_t is_leaf : 1; - /* index into phys_sections (is_leaf) or phys_map_nodes (!is_leaf) */ - uint16_t ptr : 15; -}; - /* Simple allocator for PhysPageEntry nodes */ static PhysPageEntry (*phys_map_nodes)[L2_SIZE]; static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc; #define PHYS_MAP_NODE_NIL (((uint16_t)~0) >> 1) -/* This is a multi-level map on the physical address space. - The bottom level has pointers to MemoryRegionSections. */ -static PhysPageEntry phys_map = { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 }; - static void io_mem_init(void); static void memory_map_init(void); @@ -459,18 +448,19 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index, } } -static void phys_page_set(target_phys_addr_t index, target_phys_addr_t nb, +static void phys_page_set(AddressSpaceDispatch *d, + target_phys_addr_t index, target_phys_addr_t nb, uint16_t leaf) { /* Wildly overreserve - it doesn't matter much. */ phys_map_node_reserve(3 * P_L2_LEVELS); - phys_page_set_level(&phys_map, &index, &nb, leaf, P_L2_LEVELS - 1); + phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1); } -MemoryRegionSection *phys_page_find(target_phys_addr_t index) +MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, target_phys_addr_t index) { - PhysPageEntry lp = phys_map; + PhysPageEntry lp = d->phys_map; PhysPageEntry *p; int i; uint16_t s_index = phys_section_unassigned; @@ -1472,7 +1462,7 @@ void tb_invalidate_phys_addr(target_phys_addr_t addr) ram_addr_t ram_addr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || (section->mr->rom_device && section->mr->readable))) { return; @@ -2218,9 +2208,9 @@ static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level) lp->ptr = PHYS_MAP_NODE_NIL; } -static void destroy_all_mappings(void) +static void destroy_all_mappings(AddressSpaceDispatch *d) { - destroy_l2_mapping(&phys_map, P_L2_LEVELS - 1); + destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1); phys_map_nodes_reset(); } @@ -2240,12 +2230,12 @@ static void phys_sections_clear(void) phys_sections_nb = 0; } -static void register_subpage(MemoryRegionSection *section) +static void register_subpage(AddressSpaceDispatch *d, 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 *existing = phys_page_find(d, base >> TARGET_PAGE_BITS); MemoryRegionSection subsection = { .offset_within_address_space = base, .size = TARGET_PAGE_SIZE, @@ -2257,7 +2247,7 @@ static void register_subpage(MemoryRegionSection *section) if (!(existing->mr->subpage)) { subpage = subpage_init(base); subsection.mr = &subpage->iomem; - phys_page_set(base >> TARGET_PAGE_BITS, 1, + phys_page_set(d, base >> TARGET_PAGE_BITS, 1, phys_section_add(&subsection)); } else { subpage = container_of(existing->mr, subpage_t, iomem); @@ -2268,7 +2258,7 @@ static void register_subpage(MemoryRegionSection *section) } -static void register_multipage(MemoryRegionSection *section) +static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *section) { target_phys_addr_t start_addr = section->offset_within_address_space; ram_addr_t size = section->size; @@ -2278,13 +2268,13 @@ static void register_multipage(MemoryRegionSection *section) assert(size); addr = start_addr; - phys_page_set(addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS, + phys_page_set(d, addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS, section_index); } -void cpu_register_physical_memory_log(MemoryRegionSection *section, - bool readonly) +static void mem_add(MemoryListener *listener, MemoryRegionSection *section) { + AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener); MemoryRegionSection now = *section, remain = *section; if ((now.offset_within_address_space & ~TARGET_PAGE_MASK) @@ -2292,7 +2282,7 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, now.size = MIN(TARGET_PAGE_ALIGN(now.offset_within_address_space) - now.offset_within_address_space, now.size); - register_subpage(&now); + register_subpage(d, &now); remain.size -= now.size; remain.offset_within_address_space += now.size; remain.offset_within_region += now.size; @@ -2301,10 +2291,10 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, now = remain; if (remain.offset_within_region & ~TARGET_PAGE_MASK) { now.size = TARGET_PAGE_SIZE; - register_subpage(&now); + register_subpage(d, &now); } else { now.size &= TARGET_PAGE_MASK; - register_multipage(&now); + register_multipage(d, &now); } remain.size -= now.size; remain.offset_within_address_space += now.size; @@ -2312,7 +2302,7 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, } now = remain; if (now.size) { - register_subpage(&now); + register_subpage(d, &now); } } @@ -3163,11 +3153,17 @@ static void io_mem_init(void) "watch", UINT64_MAX); } +static void mem_begin(MemoryListener *listener) +{ + AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener); + + destroy_all_mappings(d); + d->phys_map.ptr = PHYS_MAP_NODE_NIL; +} + static void core_begin(MemoryListener *listener) { - destroy_all_mappings(); phys_sections_clear(); - phys_map.ptr = PHYS_MAP_NODE_NIL; phys_section_unassigned = dummy_section(&io_mem_unassigned); phys_section_notdirty = dummy_section(&io_mem_notdirty); phys_section_rom = dummy_section(&io_mem_rom); @@ -3186,18 +3182,6 @@ static void tcg_commit(MemoryListener *listener) } } -static void core_region_add(MemoryListener *listener, - MemoryRegionSection *section) -{ - cpu_register_physical_memory_log(section, section->readonly); -} - -static void core_region_nop(MemoryListener *listener, - MemoryRegionSection *section) -{ - cpu_register_physical_memory_log(section, section->readonly); -} - static void core_log_global_start(MemoryListener *listener) { cpu_physical_memory_set_dirty_tracking(1); @@ -3229,11 +3213,9 @@ static void io_region_del(MemoryListener *listener, static MemoryListener core_memory_listener = { MEMORY_LISTENER_DEFAULT_OPS, .begin = core_begin, - .region_add = core_region_add, - .region_nop = core_region_nop, .log_global_start = core_log_global_start, .log_global_stop = core_log_global_stop, - .priority = 0, + .priority = 1, }; static MemoryListener io_memory_listener = { @@ -3248,6 +3230,22 @@ static void io_region_del(MemoryListener *listener, .commit = tcg_commit, }; +void address_space_init_dispatch(AddressSpace *as) +{ + AddressSpaceDispatch *d = g_new(AddressSpaceDispatch, 1); + + d->phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 }; + d->listener = (MemoryListener) { + MEMORY_LISTENER_DEFAULT_OPS, + .begin = mem_begin, + .region_add = mem_add, + .region_nop = mem_add, + .priority = 0, + }; + as->dispatch = d; + memory_listener_register(&d->listener, as); +} + static void memory_map_init(void) { system_memory = g_malloc(sizeof(*system_memory)); @@ -3319,9 +3317,11 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr, } #else -void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, - int len, int is_write) + +void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, + int len, bool is_write) { + AddressSpaceDispatch *d = as->dispatch; int l; uint8_t *ptr; uint32_t val; @@ -3333,7 +3333,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - section = phys_page_find(page >> TARGET_PAGE_BITS); + section = phys_page_find(d, page >> TARGET_PAGE_BITS); if (is_write) { if (!memory_region_is_ram(section->mr)) { @@ -3410,10 +3410,36 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, } } +void address_space_write(AddressSpace *as, target_phys_addr_t addr, + const uint8_t *buf, int len) +{ + address_space_rw(as, addr, (uint8_t *)buf, len, true); +} + +/** + * address_space_read: read from an address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + */ +void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, int len) +{ + address_space_rw(as, addr, buf, len, false); +} + + +void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, + int len, int is_write) +{ + return address_space_rw(&address_space_memory, addr, buf, len, is_write); +} + /* used for ROM loading : can write in RAM and ROM */ void cpu_physical_memory_write_rom(target_phys_addr_t addr, const uint8_t *buf, int len) { + AddressSpaceDispatch *d = address_space_memory.dispatch; int l; uint8_t *ptr; target_phys_addr_t page; @@ -3424,7 +3450,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - section = phys_page_find(page >> TARGET_PAGE_BITS); + section = phys_page_find(d, page >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3504,10 +3530,12 @@ static void cpu_notify_map_clients(void) * Use cpu_register_map_client() to know when retrying the map operation is * likely to succeed. */ -void *cpu_physical_memory_map(target_phys_addr_t addr, - target_phys_addr_t *plen, - int is_write) +void *address_space_map(AddressSpace *as, + target_phys_addr_t addr, + target_phys_addr_t *plen, + bool is_write) { + AddressSpaceDispatch *d = as->dispatch; target_phys_addr_t len = *plen; target_phys_addr_t todo = 0; int l; @@ -3522,7 +3550,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; - section = phys_page_find(page >> TARGET_PAGE_BITS); + section = phys_page_find(d, page >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) && !section->readonly)) { if (todo || bounce.buffer) { @@ -3532,7 +3560,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, bounce.addr = addr; bounce.len = l; if (!is_write) { - cpu_physical_memory_read(addr, bounce.buffer, l); + address_space_read(as, addr, bounce.buffer, l); } *plen = l; @@ -3553,12 +3581,12 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, return ret; } -/* Unmaps a memory region previously mapped by cpu_physical_memory_map(). +/* Unmaps a memory region previously mapped by address_space_map(). * Will also mark the memory as dirty if is_write == 1. access_len gives * the amount of memory that was actually read or written by the caller. */ -void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, - int is_write, target_phys_addr_t access_len) +void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len, + int is_write, target_phys_addr_t access_len) { if (buffer != bounce.buffer) { if (is_write) { @@ -3585,13 +3613,26 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, return; } if (is_write) { - cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len); + address_space_write(as, bounce.addr, bounce.buffer, access_len); } qemu_vfree(bounce.buffer); bounce.buffer = NULL; cpu_notify_map_clients(); } +void *cpu_physical_memory_map(target_phys_addr_t addr, + target_phys_addr_t *plen, + int is_write) +{ + return address_space_map(&address_space_memory, addr, plen, is_write); +} + +void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, + int is_write, target_phys_addr_t access_len) +{ + return address_space_unmap(&address_space_memory, buffer, len, is_write, access_len); +} + /* warning: addr must be aligned */ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr, enum device_endian endian) @@ -3600,7 +3641,7 @@ static inline uint32_t ldl_phys_internal(target_phys_addr_t addr, uint32_t val; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3659,7 +3700,7 @@ static inline uint64_t ldq_phys_internal(target_phys_addr_t addr, uint64_t val; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3726,7 +3767,7 @@ static inline uint32_t lduw_phys_internal(target_phys_addr_t addr, uint64_t val; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr))) { @@ -3785,7 +3826,7 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val) uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + 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); @@ -3817,7 +3858,7 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val) uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + 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); @@ -3846,7 +3887,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val, uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + 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); @@ -3919,7 +3960,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val, uint8_t *ptr; MemoryRegionSection *section; - section = phys_page_find(addr >> TARGET_PAGE_BITS); + 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); @@ -4161,7 +4202,8 @@ bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr) { MemoryRegionSection *section; - section = phys_page_find(phys_addr >> TARGET_PAGE_BITS); + section = phys_page_find(address_space_memory.dispatch, + phys_addr >> TARGET_PAGE_BITS); return !(memory_region_is_ram(section->mr) || memory_region_is_romd(section->mr)); diff --git a/memory-internal.h b/memory-internal.h index 655f71f..a9d914e 100644 --- a/memory-internal.h +++ b/memory-internal.h @@ -21,6 +21,26 @@ #ifndef CONFIG_USER_ONLY +typedef struct PhysPageEntry PhysPageEntry; + +struct PhysPageEntry { + uint16_t is_leaf : 1; + /* index into phys_sections (is_leaf) or phys_map_nodes (!is_leaf) */ + uint16_t ptr : 15; +}; + +typedef struct AddressSpaceDispatch AddressSpaceDispatch; + +struct AddressSpaceDispatch { + /* This is a multi-level map on the physical address space. + * The bottom level has pointers to MemoryRegionSections. + */ + PhysPageEntry phys_map; + MemoryListener listener; +}; + +void address_space_init_dispatch(AddressSpace *as); + ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr); ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr); @@ -29,8 +49,6 @@ void qemu_ram_free_from_ptr(ram_addr_t addr); struct MemoryRegion; struct MemoryRegionSection; -void cpu_register_physical_memory_log(struct MemoryRegionSection *section, - bool readonly); 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); diff --git a/memory.c b/memory.c index f829d84..28a79ae 100644 --- a/memory.c +++ b/memory.c @@ -1550,6 +1550,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root) QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link); as->name = NULL; memory_region_transaction_commit(); + address_space_init_dispatch(as); } uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) diff --git a/memory.h b/memory.h index 6115f48..84f7439 100644 --- a/memory.h +++ b/memory.h @@ -169,6 +169,7 @@ struct AddressSpace { struct FlatView *current_map; int ioeventfd_nb; struct MemoryRegionIoeventfd *ioeventfds; + struct AddressSpaceDispatch *dispatch; QTAILQ_ENTRY(AddressSpace) address_spaces_link; }; @@ -830,6 +831,67 @@ void mtree_info(fprintf_function mon_printf, void *f); */ void address_space_init(AddressSpace *as, MemoryRegion *root); +/** + * address_space_rw: read from or write to an address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + * @is_write: indicates the transfer direction + */ +void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, + int len, bool is_write); + +/** + * address_space_write: write to address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + */ +void address_space_write(AddressSpace *as, target_phys_addr_t addr, + const uint8_t *buf, int len); + +/** + * address_space_read: read from an address space. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + */ +void address_space_read(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf, int len); + +/* 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. + * May return %NULL if resources needed to perform the mapping are exhausted. + * Use only for reads OR writes - not for read-modify-write operations. + * Use cpu_register_map_client() to know when retrying the map operation is + * likely to succeed. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @plen: pointer to length of buffer; updated on return + * @is_write: indicates the transfer direction + */ +void *address_space_map(AddressSpace *as, target_phys_addr_t addr, + target_phys_addr_t *plen, bool is_write); + +/* address_space_unmap: Unmaps a memory region previously mapped by address_space_map() + * + * Will also mark the memory as dirty if @is_write == %true. @access_len gives + * the amount of memory that was actually read or written by the caller. + * + * @as: #AddressSpace used + * @addr: address within that address space + * @len: buffer length as returned by address_space_map() + * @access_len: amount of data actually transferred + * @is_write: indicates the transfer direction + */ +void address_space_unmap(AddressSpace *as, void *buffer, target_phys_addr_t len, + int is_write, target_phys_addr_t access_len); + + #endif #endif