From ac6c5dce818cbd7ad4574fc511b0401a0afde729 Mon Sep 17 00:00:00 2001 From: Conghui Chen Date: Wed, 22 May 2019 03:01:23 +0800 Subject: [PATCH] HV: Clean vpic and vioapic logic when lapic is pt When the lapic is passthru, vpic and vioapic cannot be used anymore. In current code, user can still inject vpic interrupt to Guest OS, this is not allowed. This patch remove the vpic and vioapic initiate functions during creating VM with lapic passthru. But the APIs in vpic and vioapic are called in many places, for these APIs, follow the below principles: 1. For the APIs which will access uninitiated variables, and may case hypervisor hang, add @pre to make sure user should call them after vpic or vioapic is initiated. 2. For the APIs which only return some static value, do noting with them. 3. For the APIs which user will called to inject interrupt, such as vioapic_set_irqline_lock or vpic_set_irqline, add condition in these APIs to make sure it only inject interrupt when vpic or vioapic is initiated. This change is to make sure the vuart or hypercall need not to care whether lapic is passthru or the vpic and vioapic is initiated or not. Tracked-On: #3227 Signed-off-by: Conghui Chen --- hypervisor/arch/x86/guest/vm.c | 8 ++++++-- hypervisor/dm/vioapic.c | 21 +++++++++++++++++---- hypervisor/dm/vpic.c | 3 +++ hypervisor/include/dm/vioapic.h | 1 + 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 0604f2da7..06d426b42 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -477,7 +477,9 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_ register_pm1ab_handler(vm); } } - vpic_init(vm); + if (!is_lapic_pt_configured(vm)) { + vpic_init(vm); + } /* Create virtual uart;*/ vuart_init(vm, vm_config->vuart); @@ -495,7 +497,9 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_ vm->wire_mode = VPIC_WIRE_INTR; /* Init full emulated vIOAPIC instance */ - vioapic_init(vm); + if (!is_lapic_pt_configured(vm)) { + vioapic_init(vm); + } /* Intercept the virtual pm port for RTVM */ if (is_rt_vm(vm)) { diff --git a/hypervisor/dm/vioapic.c b/hypervisor/dm/vioapic.c index b8893f566..2ddf34e09 100644 --- a/hypervisor/dm/vioapic.c +++ b/hypervisor/dm/vioapic.c @@ -124,6 +124,8 @@ vioapic_set_pinstate(struct acrn_vioapic *vioapic, uint32_t pin, uint32_t level) * GSI_RAISING_PULSE/GSI_FALLING_PULSE * * @pre irqline < vioapic_pincount(vm) + * @pre vm != NULL + * @pre vioapic->ready == true * @return None */ void @@ -166,6 +168,7 @@ vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t irqline, uint32_t * GSI_RAISING_PULSE/GSI_FALLING_PULSE * * @pre irqline < vioapic_pincount(vm) + * @pre vm != NULL * * @return None */ @@ -173,10 +176,11 @@ void vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t irqline, uint32_t operation) { struct acrn_vioapic *vioapic = vm_ioapic(vm); - - spinlock_obtain(&(vioapic->mtx)); - vioapic_set_irqline_nolock(vm, irqline, operation); - spinlock_release(&(vioapic->mtx)); + if (vioapic->ready) { + spinlock_obtain(&(vioapic->mtx)); + vioapic_set_irqline_nolock(vm, irqline, operation); + spinlock_release(&(vioapic->mtx)); + } } static uint32_t @@ -385,6 +389,10 @@ vioapic_mmio_rw(struct acrn_vioapic *vioapic, uint64_t gpa, spinlock_release(&(vioapic->mtx)); } +/* + * @pre vm != NULL + * @pre vioapic->ready == true + */ void vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector) { @@ -460,6 +468,7 @@ vioapic_init(struct acrn_vm *vm) (uint64_t)VIOAPIC_BASE, (uint64_t)VIOAPIC_BASE + VIOAPIC_SIZE, vm); + vm->arch_vm.vioapic.ready = true; } uint32_t @@ -476,6 +485,10 @@ vioapic_pincount(const struct acrn_vm *vm) return ret; } +/* + * @pre handler_private_data != NULL + * @pre vioapic->ready == true + */ int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_private_data) { struct acrn_vm *vm = (struct acrn_vm *)handler_private_data; diff --git a/hypervisor/dm/vpic.c b/hypervisor/dm/vpic.c index f06cccffc..8dacb45ff 100644 --- a/hypervisor/dm/vpic.c +++ b/hypervisor/dm/vpic.c @@ -509,6 +509,7 @@ vpic_pincount(void) /** * @pre vm->vpic != NULL * @pre irqline < NR_VPIC_PINS_TOTAL + * @pre this function should be called after vpic_init() */ void vpic_get_irqline_trigger_mode(const struct acrn_vm *vm, uint32_t irqline, enum vpic_trigger *trigger) @@ -531,6 +532,7 @@ void vpic_get_irqline_trigger_mode(const struct acrn_vm *vm, uint32_t irqline, * @param[inout] vecptr Pointer to vector buffer and will be filled * with eligible vector if any. * + * @pre this function should be called after vpic_init() * @return None */ void vpic_pending_intr(struct acrn_vm *vm, uint32_t *vecptr) @@ -593,6 +595,7 @@ static void vpic_pin_accepted(struct i8259_reg_state *i8259, uint32_t pin) * @return None * * @pre vm != NULL + * @pre this function should be called after vpic_init() */ void vpic_intr_accepted(struct acrn_vm *vm, uint32_t vector) { diff --git a/hypervisor/include/dm/vioapic.h b/hypervisor/include/dm/vioapic.h index 22633a16c..45bfea5d4 100644 --- a/hypervisor/include/dm/vioapic.h +++ b/hypervisor/include/dm/vioapic.h @@ -53,6 +53,7 @@ struct acrn_vioapic { struct acrn_vm *vm; spinlock_t mtx; uint32_t id; + bool ready; uint32_t ioregsel; union ioapic_rte rtbl[REDIR_ENTRIES_HW]; /* pin_state status bitmap: 1 - high, 0 - low */