Skip to content

Commit 82fa994

Browse files
peterfangacrnsi
authored andcommitted
dm: safely access MMIO hint in MMIO emulation
mmio_hint in mem.c can potentially be accessed concurrently in emulate_mem() because it only holds a read lock. Use a local variable to make sure the same entry address is used throughout the function. Since it only serves as a hint, it's okay if the function does not use the most up-to-date version of mmio_hint, as long as mmio_hint is accessed atomically. Explicitly enforce natural alignment on mmio_hint to guarantee atomic accesses on x86 and increase code portability, even though compilers most likely always do it. Entries in the RB tree are only removed in unregister_mem_int() while holding a write lock, so accessing mmio_hint while holding a read lock is safe. Tracked-On: #2902 Signed-off-by: Peter Fang <peter.fang@intel.com> Reviewed-by: Shuo A Liu <shuo.a.liu@intel.com>
1 parent 4c38ff0 commit 82fa994

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

devicemodel/core/mem.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ RB_PROTOTYPE_STATIC(mmio_rb_tree, mmio_rb_range, mr_link, mmio_rb_range_compare)
6060
* consecutive addresses in a range, it makes sense to cache the
6161
* result of a lookup.
6262
*/
63-
static struct mmio_rb_range *mmio_hint;
63+
static struct mmio_rb_range *mmio_hint __aligned(sizeof(struct mmio_rb_range *));
6464

6565
static pthread_rwlock_t mmio_rwlock;
6666

@@ -156,16 +156,18 @@ emulate_mem(struct vmctx *ctx, struct mmio_request *mmio_req)
156156
{
157157
uint64_t paddr = mmio_req->address;
158158
int size = mmio_req->size;
159-
struct mmio_rb_range *entry = NULL;
159+
struct mmio_rb_range *hint, *entry = NULL;
160160
int err;
161161

162162
pthread_rwlock_rdlock(&mmio_rwlock);
163+
163164
/*
164165
* First check the per-VM cache
165166
*/
166-
if (mmio_hint && paddr >= mmio_hint->mr_base &&
167-
paddr <= mmio_hint->mr_end)
168-
entry = mmio_hint;
167+
hint = mmio_hint;
168+
169+
if (hint && paddr >= hint->mr_base && paddr <= hint->mr_end)
170+
entry = hint;
169171
else if (mmio_rb_lookup(&mmio_rb_root, paddr, &entry) == 0)
170172
/* Update the per-VM cache */
171173
mmio_hint = entry;

0 commit comments

Comments
 (0)