summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/bhyve/mem.c')
-rw-r--r--usr.sbin/bhyve/mem.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/usr.sbin/bhyve/mem.c b/usr.sbin/bhyve/mem.c
index 7ea630f..2a9f430 100644
--- a/usr.sbin/bhyve/mem.c
+++ b/usr.sbin/bhyve/mem.c
@@ -157,10 +157,12 @@ mem_write(void *ctx, int vcpu, uint64_t gpa, uint64_t wval, int size, void *arg)
}
int
-emulate_mem(struct vmctx *ctx, int vcpu, uint64_t paddr, struct vie *vie)
+emulate_mem(struct vmctx *ctx, int vcpu, uint64_t paddr, struct vie *vie,
+ struct vm_guest_paging *paging)
+
{
struct mmio_rb_range *entry;
- int err;
+ int err, immutable;
pthread_rwlock_rdlock(&mmio_rwlock);
/*
@@ -184,10 +186,28 @@ emulate_mem(struct vmctx *ctx, int vcpu, uint64_t paddr, struct vie *vie)
}
assert(entry != NULL);
- err = vmm_emulate_instruction(ctx, vcpu, paddr, vie,
+
+ /*
+ * An 'immutable' memory range is guaranteed to be never removed
+ * so there is no need to hold 'mmio_rwlock' while calling the
+ * handler.
+ *
+ * XXX writes to the PCIR_COMMAND register can cause register_mem()
+ * to be called. If the guest is using PCI extended config space
+ * to modify the PCIR_COMMAND register then register_mem() can
+ * deadlock on 'mmio_rwlock'. However by registering the extended
+ * config space window as 'immutable' the deadlock can be avoided.
+ */
+ immutable = (entry->mr_param.flags & MEM_F_IMMUTABLE);
+ if (immutable)
+ pthread_rwlock_unlock(&mmio_rwlock);
+
+ err = vmm_emulate_instruction(ctx, vcpu, paddr, vie, paging,
mem_read, mem_write, &entry->mr_param);
- pthread_rwlock_unlock(&mmio_rwlock);
-
+
+ if (!immutable)
+ pthread_rwlock_unlock(&mmio_rwlock);
+
return (err);
}
@@ -244,6 +264,7 @@ unregister_mem(struct mem_range *memp)
mr = &entry->mr_param;
assert(mr->name == memp->name);
assert(mr->base == memp->base && mr->size == memp->size);
+ assert((mr->flags & MEM_F_IMMUTABLE) == 0);
RB_REMOVE(mmio_rb_tree, &mmio_rb_root, entry);
/* flush Per-vCPU cache */
OpenPOWER on IntegriCloud