[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH v3 1/9] memory: Add function for finding flat memory ranges
From: |
i . kotrasinsk |
Subject: |
[RFC PATCH v3 1/9] memory: Add function for finding flat memory ranges |
Date: |
Wed, 5 Feb 2020 14:28:29 +0100 |
From: Igor Kotrasinski <address@hidden>
Given an address this lets us find the largest contiguous memory range
at that address.
Signed-off-by: Igor Kotrasinski <address@hidden>
---
include/exec/memory.h | 19 +++++++++++++
memory.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/include/exec/memory.h b/include/exec/memory.h
index e85b7de..ac09221 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1915,6 +1915,25 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr,
hwaddr addr, uint64_t size);
/**
+ * memory_region_find_flat_range: translate an address/size relative to
+ * a MemoryRegion into a FlatRange containing it.
+ *
+ * Returns a #MemoryRegionSection that describes this FlatRange.
+ * It will have the following characteristics:
+ * - @size = 0 iff no containing FlatRange was found
+ * - @mr is non-%NULL iff a containing FlatRange was found
+ *
+ * Remember that in the return value the @offset_within_region is
+ * relative to the returned region (in the .@mr field), not to the
+ * @mr argument.
+ *
+ * @mr: a MemoryRegion within which @addr is a relative address
+ * @addr: start of the area within @as to be searched
+ * @size: size of the area to be searched
+ */
+MemoryRegionSection memory_region_find_flat_range(MemoryRegion *mr,
+ hwaddr addr, uint64_t size);
+/**
* memory_global_dirty_log_sync: synchronize the dirty log for all memory
*
* Synchronizes the dirty page log for all address spaces.
diff --git a/memory.c b/memory.c
index aeaa8dc..0973c44 100644
--- a/memory.c
+++ b/memory.c
@@ -2523,6 +2523,25 @@ static FlatRange *flatview_lookup(FlatView *view,
AddrRange addr)
sizeof(FlatRange), cmp_flatrange_addr);
}
+static int cmp_flatrange_addr_containing(const void *addr_, const void *fr_)
+{
+ const AddrRange *addr = addr_;
+ const FlatRange *fr = fr_;
+
+ if (int128_le(addr->start, fr->addr.start)) {
+ return -1;
+ } else if (int128_ge(addrrange_end(*addr), addrrange_end(fr->addr))) {
+ return 1;
+ }
+ return 0;
+}
+
+static FlatRange *flatview_lookup_containing(FlatView *view, AddrRange addr)
+{
+ return bsearch(&addr, view->ranges, view->nr,
+ sizeof(FlatRange), cmp_flatrange_addr_containing);
+}
+
bool memory_region_is_mapped(MemoryRegion *mr)
{
return mr->container ? true : false;
@@ -2532,7 +2551,8 @@ bool memory_region_is_mapped(MemoryRegion *mr)
* returned region. It must be called from an RCU critical section.
*/
static MemoryRegionSection memory_region_find_rcu(MemoryRegion *mr,
- hwaddr addr, uint64_t size)
+ hwaddr addr,
+ uint64_t size)
{
MemoryRegionSection ret = { .mr = NULL };
MemoryRegion *root;
@@ -2576,6 +2596,50 @@ static MemoryRegionSection
memory_region_find_rcu(MemoryRegion *mr,
return ret;
}
+/*
+ * Same as memory_region_find_flat_range, but it does not add a reference to
+ * the returned region. It must be called from an RCU critical section.
+ */
+static MemoryRegionSection memory_region_find_flat_range_rcu(MemoryRegion *mr,
+ hwaddr addr,
+ uint64_t size)
+{
+ MemoryRegionSection ret = { .size = int128_zero(), .mr = NULL };
+ MemoryRegion *root;
+ AddressSpace *as;
+ AddrRange range;
+ FlatView *view;
+ FlatRange *fr;
+
+ addr += mr->addr;
+ for (root = mr; root->container; ) {
+ root = root->container;
+ addr += root->addr;
+ }
+
+ as = memory_region_to_address_space(root);
+ if (!as) {
+ return ret;
+ }
+ range = addrrange_make(int128_make64(addr), int128_make64(size));
+
+ view = address_space_to_flatview(as);
+ fr = flatview_lookup_containing(view, range);
+ if (!fr) {
+ return ret;
+ }
+
+ ret.mr = fr->mr;
+ ret.fv = view;
+ range = fr->addr;
+ ret.offset_within_region = fr->offset_in_region;
+ ret.size = range.size;
+ ret.offset_within_address_space = int128_get64(range.start);
+ ret.readonly = fr->readonly;
+ ret.nonvolatile = fr->nonvolatile;
+ return ret;
+}
+
MemoryRegionSection memory_region_find(MemoryRegion *mr,
hwaddr addr, uint64_t size)
{
@@ -2588,6 +2652,19 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr,
return ret;
}
+MemoryRegionSection memory_region_find_flat_range(MemoryRegion *mr,
+ hwaddr addr, uint64_t size)
+{
+ MemoryRegionSection ret;
+ rcu_read_lock();
+ ret = memory_region_find_flat_range_rcu(mr, addr, size);
+ if (ret.mr) {
+ memory_region_ref(ret.mr);
+ }
+ rcu_read_unlock();
+ return ret;
+}
+
bool memory_region_present(MemoryRegion *container, hwaddr addr)
{
MemoryRegion *mr;
--
2.7.4
- [RFC PATCH v3 0/9] Add an interVM memory sharing device, i . kotrasinsk, 2020/02/05
- Message not available
- Message not available
- Message not available
- [RFC PATCH v3 1/9] memory: Add function for finding flat memory ranges,
i . kotrasinsk <=
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available