From aef5a4fd29e2840ee99961a22349301a48c10f1a Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Wed, 17 Apr 2019 16:30:28 -0700 Subject: [PATCH] hv: free ptdev device IRQs when shutting down VM Currently ptdev_release_all_entries() calls ptirq_release_entry() to release ptdev IRQs, which is not sufficient because free_irq() is not included in ptirq_release_entry(). Furthermore, function ptirq_deactivate_entry() and ptirq_release_entry() have lots of overlaps which make the differences between them are not clear. This patch does: - Adds ptirq_deactivate_entry() call in ptdev_release_all_entries() if the irq has not already freed. - Remove unnecessary code from ptirq_deactivate_entry() to make it do the exact opposite to function ptirq_activate_entry(), except that entry->allocated_pirq is not reset, which is not necessary. - Added the missing del_timer() to ptirq_release_entry() to make it almost opposite to ptirq_alloc_entry(); Added memset() to clear the whole entry, which doesn't have impacts to the functionalities but keep the data structure clean. Tracked-On: #2700 Signed-off-by: Sainath Grandhi Signed-off-by: Zide Chen Acked-by: Eddie Dong --- hypervisor/common/ptdev.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/hypervisor/common/ptdev.c b/hypervisor/common/ptdev.c index e67d57b19..6f5418b25 100644 --- a/hypervisor/common/ptdev.c +++ b/hypervisor/common/ptdev.c @@ -112,16 +112,15 @@ void ptirq_release_entry(struct ptirq_remapping_info *entry) { uint64_t rflags; - /* - * remove entry from softirq list - * is required before calling ptirq_release_entry. - */ spinlock_irqsave_obtain(&entry->vm->softirq_dev_lock, &rflags); list_del_init(&entry->softirq_node); + del_timer(&entry->intr_delay_timer); spinlock_irqrestore_release(&entry->vm->softirq_dev_lock, rflags); - atomic_clear32(&entry->active, ACTIVE_FLAG); + bitmap_clear_nolock((entry->ptdev_entry_id) & 0x3FU, &ptirq_entry_bitmaps[((entry->ptdev_entry_id) & 0x3FU) >> 6U]); + + (void)memset((void *)entry, 0U, sizeof(struct ptirq_remapping_info)); } /* interrupt context */ @@ -176,18 +175,8 @@ int32_t ptirq_activate_entry(struct ptirq_remapping_info *entry, uint32_t phys_i void ptirq_deactivate_entry(struct ptirq_remapping_info *entry) { - uint64_t rflags; - atomic_clear32(&entry->active, ACTIVE_FLAG); - free_irq(entry->allocated_pirq); - entry->allocated_pirq = IRQ_INVALID; - - /* remove from softirq list if added */ - spinlock_irqsave_obtain(&entry->vm->softirq_dev_lock, &rflags); - list_del_init(&entry->softirq_node); - del_timer(&entry->intr_delay_timer); - spinlock_irqrestore_release(&entry->vm->softirq_dev_lock, rflags); } void ptdev_init(void) @@ -207,8 +196,9 @@ void ptdev_release_all_entries(const struct acrn_vm *vm) /* VM already down */ for (idx = 0U; idx < CONFIG_MAX_PT_IRQ_ENTRIES; idx++) { entry = &ptirq_entries[idx]; - if (entry->vm == vm) { + if ((entry->vm == vm) && is_entry_active(entry)) { spinlock_obtain(&ptdev_lock); + ptirq_deactivate_entry(entry); ptirq_release_entry(entry); spinlock_release(&ptdev_lock); }