From a29ac16632aec6065c72985b9f7eeb1ca6fbef4a Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 6 Nov 2015 19:20:04 -0200 Subject: exec: Eliminate qemu_ram_free_from_ptr() Replace qemu_ram_free_from_ptr() with qemu_ram_free(). The only difference between qemu_ram_free_from_ptr() and qemu_ram_free() is that g_free_rcu() is used instead of call_rcu(reclaim_ramblock). We can safely replace it because: * RAM blocks allocated by qemu_ram_alloc_from_ptr() always have RAM_PREALLOC set; * reclaim_ramblock(block) will do nothing except g_free(block) if RAM_PREALLOC is set at block->flags. Signed-off-by: Eduardo Habkost Message-Id: <1446844805-14492-2-git-send-email-ehabkost@redhat.com> Signed-off-by: Paolo Bonzini --- include/exec/ram_addr.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/exec') diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 7115154bc1..d1d9963680 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -75,7 +75,6 @@ int qemu_get_ram_fd(ram_addr_t addr); void *qemu_get_ram_block_host_ptr(ram_addr_t addr); void *qemu_get_ram_ptr(ram_addr_t addr); void qemu_ram_free(ram_addr_t addr); -void qemu_ram_free_from_ptr(ram_addr_t addr); int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp); -- cgit v1.2.3-55-g7522 From 49b24afcb11d682d82747f706e3bd6174fe84062 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 16 Dec 2015 10:30:47 +0100 Subject: exec: always call qemu_get_ram_ptr within rcu_read_lock Simplify the code and document the assumption. The only caller that is not within rcu_read_lock is memory_region_get_ram_ptr. Signed-off-by: Paolo Bonzini --- exec.c | 22 +++++----------------- include/exec/memory.h | 9 +++++++-- memory.c | 14 ++++++++++---- 3 files changed, 22 insertions(+), 23 deletions(-) (limited to 'include/exec') diff --git a/exec.c b/exec.c index dd11ef9e34..af954388f5 100644 --- a/exec.c +++ b/exec.c @@ -1786,19 +1786,11 @@ void *qemu_get_ram_block_host_ptr(ram_addr_t addr) * or address_space_rw instead. For local memory (e.g. video ram) that the * device owns, use memory_region_get_ram_ptr. * - * By the time this function returns, the returned pointer is not protected - * by RCU anymore. If the caller is not within an RCU critical section and - * does not hold the iothread lock, it must have other means of protecting the - * pointer, such as a reference to the region that includes the incoming - * ram_addr_t. + * Called within RCU critical section. */ void *qemu_get_ram_ptr(ram_addr_t addr) { - RAMBlock *block; - void *ptr; - - rcu_read_lock(); - block = qemu_get_ram_block(addr); + RAMBlock *block = qemu_get_ram_block(addr); if (xen_enabled() && block->host == NULL) { /* We need to check if the requested address is in the RAM @@ -1806,17 +1798,12 @@ void *qemu_get_ram_ptr(ram_addr_t addr) * In that case just map until the end of the page. */ if (block->offset == 0) { - ptr = xen_map_cache(addr, 0, 0); - goto unlock; + return xen_map_cache(addr, 0, 0); } block->host = xen_map_cache(block->offset, block->max_length, 1); } - ptr = ramblock_ptr(block, addr - block->offset); - -unlock: - rcu_read_unlock(); - return ptr; + return ramblock_ptr(block, addr - block->offset); } /* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr @@ -1954,6 +1941,7 @@ MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr) return block->mr; } +/* Called within RCU critical section. */ static void notdirty_mem_write(void *opaque, hwaddr ram_addr, uint64_t val, unsigned size) { diff --git a/include/exec/memory.h b/include/exec/memory.h index 0f07159bb4..9bbd247c38 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -656,8 +656,13 @@ int memory_region_get_fd(MemoryRegion *mr); * memory_region_get_ram_ptr: Get a pointer into a RAM memory region. * * Returns a host pointer to a RAM memory region (created with - * memory_region_init_ram() or memory_region_init_ram_ptr()). Use with - * care. + * memory_region_init_ram() or memory_region_init_ram_ptr()). + * + * Use with care; by the time this function returns, the returned pointer is + * not protected by RCU anymore. If the caller is not within an RCU critical + * section and does not hold the iothread lock, it must have other means of + * protecting the pointer, such as a reference to the region that includes + * the incoming ram_addr_t. * * @mr: the memory region being queried. */ diff --git a/memory.c b/memory.c index 1c1c19234b..f666c77823 100644 --- a/memory.c +++ b/memory.c @@ -1577,13 +1577,19 @@ int memory_region_get_fd(MemoryRegion *mr) void *memory_region_get_ram_ptr(MemoryRegion *mr) { - if (mr->alias) { - return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset; - } + void *ptr; + uint64_t offset = 0; + rcu_read_lock(); + while (mr->alias) { + offset += mr->alias_offset; + mr = mr->alias; + } assert(mr->ram_addr != RAM_ADDR_INVALID); + ptr = qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK); + rcu_read_unlock(); - return qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK); + return ptr + offset; } void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, Error **errp) -- cgit v1.2.3-55-g7522 From a676854f3447019c7c4b005ab6aece905fccfddd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 9 Dec 2015 11:40:14 +0100 Subject: memory: reorder MemoryRegion fields Order fields so that all fields accessed during a RAM read/write fit in the same cache line. Signed-off-by: Paolo Bonzini --- include/exec/memory.h | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory.h b/include/exec/memory.h index 9bbd247c38..5b1fd123cd 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -159,27 +159,32 @@ typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd; struct MemoryRegion { Object parent_obj; + /* All fields are private - violators will be prosecuted */ - const MemoryRegionOps *ops; + + /* The following fields should fit in a cache line */ + bool romd_mode; + bool ram; + bool subpage; + bool readonly; /* For RAM regions */ + bool rom_device; + bool flush_coalesced_mmio; + bool global_locking; + uint8_t dirty_log_mask; + ram_addr_t ram_addr; const MemoryRegionIOMMUOps *iommu_ops; + + const MemoryRegionOps *ops; void *opaque; MemoryRegion *container; Int128 size; hwaddr addr; void (*destructor)(MemoryRegion *mr); - ram_addr_t ram_addr; uint64_t align; - bool subpage; bool terminates; - bool romd_mode; - bool ram; bool skip_dump; - bool readonly; /* For RAM regions */ bool enabled; - bool rom_device; bool warning_printed; /* For reservations */ - bool flush_coalesced_mmio; - bool global_locking; uint8_t vga_logging_count; MemoryRegion *alias; hwaddr alias_offset; @@ -189,7 +194,6 @@ struct MemoryRegion { QTAILQ_ENTRY(MemoryRegion) subregions_link; QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced; const char *name; - uint8_t dirty_log_mask; unsigned ioeventfd_nb; MemoryRegionIoeventfd *ioeventfds; NotifierList iommu_notify; -- cgit v1.2.3-55-g7522 From 612263cf33062f7441a5d0e3b37c65991fdc3210 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 9 Dec 2015 11:44:25 +0100 Subject: memory: avoid unnecessary object_ref/unref For the common case of DMA into non-hotplugged RAM, it is unnecessary but expensive to do object_ref/unref. Add back an owner field to MemoryRegion, so that these memory regions can skip the reference counting. Signed-off-by: Paolo Bonzini --- include/exec/memory.h | 1 + memory.c | 28 ++++++++++++---------------- 2 files changed, 13 insertions(+), 16 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory.h b/include/exec/memory.h index 5b1fd123cd..24b7cba737 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -172,6 +172,7 @@ struct MemoryRegion { bool global_locking; uint8_t dirty_log_mask; ram_addr_t ram_addr; + Object *owner; const MemoryRegionIOMMUOps *iommu_ops; const MemoryRegionOps *ops; diff --git a/memory.c b/memory.c index f666c77823..b4d2b52a77 100644 --- a/memory.c +++ b/memory.c @@ -905,20 +905,22 @@ void memory_region_init(MemoryRegion *mr, const char *name, uint64_t size) { - if (!owner) { - owner = container_get(qdev_get_machine(), "/unattached"); - } - object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION); mr->size = int128_make64(size); if (size == UINT64_MAX) { mr->size = int128_2_64(); } mr->name = g_strdup(name); + mr->owner = owner; if (name) { char *escaped_name = memory_region_escape_name(name); char *name_array = g_strdup_printf("%s[*]", escaped_name); + + if (!owner) { + owner = container_get(qdev_get_machine(), "/unattached"); + } + object_property_add_child(owner, name_array, OBJECT(mr), &error_abort); object_unref(OBJECT(mr)); g_free(name_array); @@ -1369,24 +1371,18 @@ void memory_region_ref(MemoryRegion *mr) * The memory region is a child of its owner. As long as the * owner doesn't call unparent itself on the memory region, * ref-ing the owner will also keep the memory region alive. - * Memory regions without an owner are supposed to never go away, - * but we still ref/unref them for debugging purposes. + * Memory regions without an owner are supposed to never go away; + * we do not ref/unref them because it slows down DMA sensibly. */ - Object *obj = OBJECT(mr); - if (obj && obj->parent) { - object_ref(obj->parent); - } else { - object_ref(obj); + if (mr && mr->owner) { + object_ref(mr->owner); } } void memory_region_unref(MemoryRegion *mr) { - Object *obj = OBJECT(mr); - if (obj && obj->parent) { - object_unref(obj->parent); - } else { - object_unref(obj); + if (mr && mr->owner) { + object_unref(mr->owner); } } -- cgit v1.2.3-55-g7522 From a203ac702e0720135fac8b1f2061d119814c1798 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 9 Dec 2015 10:18:57 +0100 Subject: memory: extract first iteration of address_space_read and address_space_write We want to inline the case where there is only one iteration, because then the compiler can also inline the memcpy. As a start, extract everything after the first address_space_translate call. Signed-off-by: Paolo Bonzini --- exec.c | 85 +++++++++++++++++++++++++++++++++++++++------------ include/exec/memory.h | 6 ++++ 2 files changed, 71 insertions(+), 20 deletions(-) (limited to 'include/exec') diff --git a/exec.c b/exec.c index 44e6e38f9f..1597e8ab48 100644 --- a/exec.c +++ b/exec.c @@ -2468,22 +2468,19 @@ static bool prepare_mmio_access(MemoryRegion *mr) return release_lock; } -MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, - const uint8_t *buf, int len) +/* Called within RCU critical section. */ +static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr, + MemTxAttrs attrs, + const uint8_t *buf, + int len, hwaddr addr1, + hwaddr l, MemoryRegion *mr) { - hwaddr l; uint8_t *ptr; uint64_t val; - hwaddr addr1; - MemoryRegion *mr; MemTxResult result = MEMTX_OK; bool release_lock = false; - rcu_read_lock(); - while (len > 0) { - l = len; - mr = address_space_translate(as, addr, &addr1, &l, true); - + for (;;) { if (!memory_access_is_direct(mr, true)) { release_lock |= prepare_mmio_access(mr); l = memory_access_size(mr, l, addr1); @@ -2533,28 +2530,50 @@ MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, len -= l; buf += l; addr += l; + + if (!len) { + break; + } + + l = len; + mr = address_space_translate(as, addr, &addr1, &l, true); } - rcu_read_unlock(); return result; } -MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, - uint8_t *buf, int len) +MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, + const uint8_t *buf, int len) { hwaddr l; - uint8_t *ptr; - uint64_t val; hwaddr addr1; MemoryRegion *mr; MemTxResult result = MEMTX_OK; - bool release_lock = false; - rcu_read_lock(); - while (len > 0) { + if (len > 0) { + rcu_read_lock(); l = len; - mr = address_space_translate(as, addr, &addr1, &l, false); + mr = address_space_translate(as, addr, &addr1, &l, true); + result = address_space_write_continue(as, addr, attrs, buf, len, + addr1, l, mr); + rcu_read_unlock(); + } + + return result; +} + +/* Called within RCU critical section. */ +MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr, + MemTxAttrs attrs, uint8_t *buf, + int len, hwaddr addr1, hwaddr l, + MemoryRegion *mr) +{ + uint8_t *ptr; + uint64_t val; + MemTxResult result = MEMTX_OK; + bool release_lock = false; + for (;;) { if (!memory_access_is_direct(mr, false)) { /* I/O case */ release_lock |= prepare_mmio_access(mr); @@ -2601,8 +2620,34 @@ MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, len -= l; buf += l; addr += l; + + if (!len) { + break; + } + + l = len; + mr = address_space_translate(as, addr, &addr1, &l, false); + } + + return result; +} + +MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, + uint8_t *buf, int len) +{ + hwaddr l; + hwaddr addr1; + MemoryRegion *mr; + MemTxResult result = MEMTX_OK; + + if (len > 0) { + rcu_read_lock(); + l = len; + mr = address_space_translate(as, addr, &addr1, &l, false); + result = address_space_read_continue(as, addr, attrs, buf, len, + addr1, l, mr); + rcu_read_unlock(); } - rcu_read_unlock(); return result; } diff --git a/include/exec/memory.h b/include/exec/memory.h index 24b7cba737..3680d6a135 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -1366,6 +1366,12 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, int is_write, hwaddr access_len); +/* Internal functions, part of the implementation of address_space_read. */ +MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr, + MemTxAttrs attrs, uint8_t *buf, + int len, hwaddr addr1, hwaddr l, + MemoryRegion *mr); + #endif #endif -- cgit v1.2.3-55-g7522 From 1619d1fe737d2af068aefe134386a69b76164794 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 9 Dec 2015 17:47:39 +0100 Subject: memory: inline a few small accessors These are used in the address_space_* fast paths. Signed-off-by: Paolo Bonzini --- include/exec/memory.h | 22 ++++++++++++++++++---- memory.c | 20 -------------------- 2 files changed, 18 insertions(+), 24 deletions(-) (limited to 'include/exec') diff --git a/include/exec/memory.h b/include/exec/memory.h index 3680d6a135..a0993e50ab 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -523,7 +523,10 @@ uint64_t memory_region_size(MemoryRegion *mr); * * @mr: the memory region being queried */ -bool memory_region_is_ram(MemoryRegion *mr); +static inline bool memory_region_is_ram(MemoryRegion *mr) +{ + return mr->ram; +} /** * memory_region_is_skip_dump: check whether a memory region should not be @@ -563,7 +566,11 @@ static inline bool memory_region_is_romd(MemoryRegion *mr) * * @mr: the memory region being queried */ -bool memory_region_is_iommu(MemoryRegion *mr); +static inline bool memory_region_is_iommu(MemoryRegion *mr) +{ + return mr->iommu_ops; +} + /** * memory_region_notify_iommu: notify a change in an IOMMU translation entry. @@ -645,7 +652,11 @@ uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr); * * @mr: the memory region being queried */ -bool memory_region_is_rom(MemoryRegion *mr); +static inline bool memory_region_is_rom(MemoryRegion *mr) +{ + return mr->ram && mr->readonly; +} + /** * memory_region_get_fd: Get a file descriptor backing a RAM memory region. @@ -970,7 +981,10 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr, * DO NOT USE THIS FUNCTION. This is a temporary workaround while the Xen * code is being reworked. */ -ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr); +static inline ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr) +{ + return mr->ram_addr; +} uint64_t memory_region_get_alignment(const MemoryRegion *mr); /** diff --git a/memory.c b/memory.c index b4d2b52a77..93bd8ed7bc 100644 --- a/memory.c +++ b/memory.c @@ -1403,11 +1403,6 @@ const char *memory_region_name(const MemoryRegion *mr) return mr->name; } -bool memory_region_is_ram(MemoryRegion *mr) -{ - return mr->ram; -} - bool memory_region_is_skip_dump(MemoryRegion *mr) { return mr->skip_dump; @@ -1427,16 +1422,6 @@ bool memory_region_is_logging(MemoryRegion *mr, uint8_t client) return memory_region_get_dirty_log_mask(mr) & (1 << client); } -bool memory_region_is_rom(MemoryRegion *mr) -{ - return mr->ram && mr->readonly; -} - -bool memory_region_is_iommu(MemoryRegion *mr) -{ - return mr->iommu_ops; -} - void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n) { notifier_list_add(&mr->iommu_notify, n); @@ -1928,11 +1913,6 @@ void memory_region_set_alias_offset(MemoryRegion *mr, hwaddr offset) memory_region_transaction_commit(); } -ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr) -{ - return mr->ram_addr; -} - uint64_t memory_region_get_alignment(const MemoryRegion *mr) { return mr->align; -- cgit v1.2.3-55-g7522 From 3cc8f884996584630734a90c9b3c535af81e3c92 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 9 Dec 2015 10:34:13 +0100 Subject: memory: try to inline constant-length reads memcpy can take a large amount of time for small reads and writes. Handle the common case of reading s/g descriptors from memory (there is no corresponding "write" case that is as common, because writes often use address_space_st* functions) by inlining the relevant parts of address_space_read into the caller. Signed-off-by: Paolo Bonzini --- exec.c | 15 ++-------- include/exec/memory.h | 74 +++++++++++++++++++++++++++++++++++++------------ include/exec/ram_addr.h | 1 - 3 files changed, 59 insertions(+), 31 deletions(-) (limited to 'include/exec') diff --git a/exec.c b/exec.c index 1597e8ab48..8718a75b64 100644 --- a/exec.c +++ b/exec.c @@ -390,17 +390,6 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x return section; } -static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write) -{ - if (is_write) { - return memory_region_is_ram(mr) && !mr->readonly; - } else { - return memory_region_is_ram(mr) || memory_region_is_romd(mr); - } - - return false; -} - /* Called from RCU critical section */ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, hwaddr *xlat, hwaddr *plen, @@ -2632,8 +2621,8 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr, return result; } -MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, - uint8_t *buf, int len) +MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr, + MemTxAttrs attrs, uint8_t *buf, int len) { hwaddr l; hwaddr addr1; diff --git a/include/exec/memory.h b/include/exec/memory.h index a0993e50ab..01f10049c1 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -1234,23 +1234,7 @@ MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, const uint8_t *buf, int len); -/** - * address_space_read: read from an address space. - * - * Return a MemTxResult indicating whether the operation succeeded - * or failed (eg unassigned memory, device rejected the transaction, - * IOMMU fault). - * - * @as: #AddressSpace to be accessed - * @addr: address within that address space - * @attrs: memory transaction attributes - * @buf: buffer with the data transferred - */ -MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, - uint8_t *buf, int len); - -/** - * address_space_ld*: load from an address space +/* address_space_ld*: load from an address space * address_space_st*: store to an address space * * These functions perform a load or store of the byte, word, @@ -1385,6 +1369,62 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, uint8_t *buf, int len, hwaddr addr1, hwaddr l, MemoryRegion *mr); +MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr, + MemTxAttrs attrs, uint8_t *buf, int len); +void *qemu_get_ram_ptr(ram_addr_t addr); + +static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write) +{ + if (is_write) { + return memory_region_is_ram(mr) && !mr->readonly; + } else { + return memory_region_is_ram(mr) || memory_region_is_romd(mr); + } + + return false; +} + +/** + * address_space_read: read from an address space. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @attrs: memory transaction attributes + * @buf: buffer with the data transferred + */ +static inline __attribute__((__always_inline__)) +MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, + uint8_t *buf, int len) +{ + MemTxResult result = MEMTX_OK; + hwaddr l, addr1; + void *ptr; + MemoryRegion *mr; + + if (__builtin_constant_p(len)) { + if (len) { + rcu_read_lock(); + l = len; + mr = address_space_translate(as, addr, &addr1, &l, false); + if (len == l && memory_access_is_direct(mr, false)) { + addr1 += memory_region_get_ram_addr(mr); + ptr = qemu_get_ram_ptr(addr1); + memcpy(buf, ptr, len); + } else { + result = address_space_read_continue(as, addr, attrs, buf, len, + addr1, l, mr); + } + rcu_read_unlock(); + } + } else { + result = address_space_read_full(as, addr, attrs, buf, len); + } + return result; +} #endif diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index d1d9963680..ba4c04d202 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -73,7 +73,6 @@ ram_addr_t qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t max_size, MemoryRegion *mr, Error **errp); int qemu_get_ram_fd(ram_addr_t addr); void *qemu_get_ram_block_host_ptr(ram_addr_t addr); -void *qemu_get_ram_ptr(ram_addr_t addr); void qemu_ram_free(ram_addr_t addr); int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp); -- cgit v1.2.3-55-g7522