[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] memory: try to inline constant-length reads
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH] memory: try to inline constant-length reads |
Date: |
Wed, 16 Dec 2015 12:00:01 +0100 |
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 <address@hidden>
---
exec.c | 15 ++--------
include/exec/memory.h | 74 +++++++++++++++++++++++++++++++++++++------------
include/exec/ram_addr.h | 1 -
3 files changed, 59 insertions(+), 31 deletions(-)
diff --git a/exec.c b/exec.c
index 7783012..744e4c7 100644
--- a/exec.c
+++ b/exec.c
@@ -393,17 +393,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,
@@ -2659,8 +2648,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 a0993e5..01f1004 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 7115154..7f88eaa 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);
void qemu_ram_free_from_ptr(ram_addr_t addr);
--
2.5.0
- [Qemu-devel] [PATCH 0/8] Optimize address_space_read/write/map, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 3/8] memory: reorder MemoryRegion fields, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 5/8] memory: split address_space_read and address_space_write, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 1/8] exec: always call qemu_get_ram_ptr within rcu_read_lock, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 4/8] memory: avoid unnecessary object_ref/unref, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 2/8] exec: make qemu_ram_ptr_length more similar to qemu_get_ram_ptr, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 8/8] memory: try to inline constant-length reads, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH 6/8] memory: extract first iteration of address_space_read and address_space_write, Paolo Bonzini, 2015/12/16
- [Qemu-devel] [PATCH] memory: try to inline constant-length reads,
Paolo Bonzini <=
- [Qemu-devel] [PATCH 7/8] memory: inline a few small accessors, Paolo Bonzini, 2015/12/16