hv: mmio: add a lock to protect mmio_node access

After adding PCI BAR remap support, mmio_node may unregister when there's others
access it. This patch add a lock to protect mmio_node access.

Tracked-On: #3475
Signed-off-by: Li, Fei1 <fei1.li@intel.com>
This commit is contained in:
Li, Fei1 2019-10-31 08:11:25 +08:00 committed by wenlingz
parent 21cb120bcc
commit 9d26dab6d6
3 changed files with 11 additions and 2 deletions

View File

@ -484,6 +484,7 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
prepare_epc_vm_memmap(vm);
spinlock_init(&vm->vm_lock);
spinlock_init(&vm->emul_mmio_lock);
vm->arch_vm.vlapic_state = VM_VLAPIC_XAPIC;
vm->intr_inject_delay_delta = 0UL;

View File

@ -486,6 +486,7 @@ hv_emulate_mmio(struct acrn_vcpu *vcpu, struct io_request *io_req)
address = mmio_req->address;
size = mmio_req->size;
spinlock_obtain(&vcpu->vm->emul_mmio_lock);
for (idx = 0U; idx <= vcpu->vm->max_emul_mmio_regions; idx++) {
mmio_handler = &(vcpu->vm->emul_mmio[idx]);
if (mmio_handler->read_write != NULL) {
@ -510,6 +511,7 @@ hv_emulate_mmio(struct acrn_vcpu *vcpu, struct io_request *io_req)
if ((status == -ENODEV) && (read_write != NULL)) {
status = read_write(io_req, handler_private_data);
}
spinlock_release(&vcpu->vm->emul_mmio_lock);
return status;
}
@ -687,6 +689,7 @@ void register_mmio_emulation_handler(struct acrn_vm *vm,
/* Ensure both a read/write handler and range check function exist */
if ((read_write != NULL) && (end > start)) {
spinlock_obtain(&vm->emul_mmio_lock);
mmio_node = find_free_mmio_node(vm);
if (mmio_node != NULL) {
/* Fill in information for this node */
@ -695,6 +698,7 @@ void register_mmio_emulation_handler(struct acrn_vm *vm,
mmio_node->range_start = start;
mmio_node->range_end = end;
}
spinlock_release(&vm->emul_mmio_lock);
}
}
@ -713,9 +717,12 @@ void register_mmio_emulation_handler(struct acrn_vm *vm,
void unregister_mmio_emulation_handler(struct acrn_vm *vm,
uint64_t start, uint64_t end)
{
struct mem_io_node *mmio_node = find_match_mmio_node(vm, start, end);
struct mem_io_node *mmio_node;
spinlock_obtain(&vm->emul_mmio_lock);
mmio_node = find_match_mmio_node(vm, start, end);
if (mmio_node != NULL) {
(void)memset(mmio_node, 0U, sizeof(struct mem_io_node));
}
spinlock_release(&vm->emul_mmio_lock);
}

View File

@ -123,8 +123,9 @@ struct acrn_vm {
struct acrn_vuart vuart[MAX_VUART_NUM_PER_VM]; /* Virtual UART */
enum vpic_wire_mode wire_mode;
struct iommu_domain *iommu; /* iommu domain of this VM */
spinlock_t vm_lock; /* Spin-lock used to protect VM modifications */
spinlock_t vm_lock; /* Spin-lock used to protect vlapic_state modifications for a VM */
spinlock_t emul_mmio_lock; /* Used to protect emulation mmio_node concurrent access for a VM */
uint16_t max_emul_mmio_regions; /* max index of the emulated mmio_region */
struct mem_io_node emul_mmio[CONFIG_MAX_EMULATED_MMIO_REGIONS];