From fa7f6c2c8360be93f862e7647da18329d75a7962 Mon Sep 17 00:00:00 2001 From: Liu Shuo A Date: Mon, 17 Dec 2018 15:05:05 +0800 Subject: [PATCH] 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 Signed-off-by: Jian Jun Chen Signed-off-by: Liu Shuo A Acked-by: Yin Fengwei --- devicemodel/core/mem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/devicemodel/core/mem.c b/devicemodel/core/mem.c index a5c673d63..4994eb221 100644 --- a/devicemodel/core/mem.c +++ b/devicemodel/core/mem.c @@ -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; }