dm: fix deadlock between emulate_mem and un/register_mem

There is a deadlock when emulate_mem is called on the memory region
of PCI extended configuration space. The call trace is something like:
    emulate_mem
 -> pci_emul_ecfg_handler
 -> pci_cfgrw
 -> pci_emul_cmdsts_write
 -> unregister_bar/register_bar
 -> modify_bar_registration
 -> unregister_mem/register_mem

mmio_rwlock is hold in emulate_mem when calling unregister_mem/
register_mem which is trying to acquire mmio_rwlock again, and deadlock
happened.

It is possible that bar address is changed just between a on-going
MMIO access which can bring a race condition in theroy. Guest needs to
take care of the serial operation between bar addess update and MMIO
access of that bar.

Tracked-On: #2962
Signed-off-by: Yu Wang <yu1.wang@intel.com>
Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com>
Signed-off-by: Liu Shuo A <shuo.a.liu@intel.com>
Acked-by: Yin Fengwei <fengwei.yin@intel.com>
This commit is contained in:
Liu Shuo A 2018-12-17 15:05:05 +08:00 committed by wenlingz
parent d648df766c
commit fa7f6c2c83
1 changed files with 2 additions and 2 deletions

View File

@ -182,8 +182,10 @@ emulate_mem(struct vmctx *ctx, struct mmio_request *mmio_req)
assert(entry != NULL);
if (entry->enabled == false) {
pthread_rwlock_unlock(&mmio_rwlock);
return -1;
}
pthread_rwlock_unlock(&mmio_rwlock);
if (mmio_req->direction == REQUEST_READ)
err = mem_read(ctx, 0, paddr, (uint64_t *)&mmio_req->value,
@ -192,8 +194,6 @@ emulate_mem(struct vmctx *ctx, struct mmio_request *mmio_req)
err = mem_write(ctx, 0, paddr, mmio_req->value,
size, &entry->mr_param);
pthread_rwlock_unlock(&mmio_rwlock);
return err;
}