From: Peter Dinda Date: Fri, 2 Aug 2013 20:41:13 +0000 (-0500) Subject: Fixes to interrupt (IRQ and VIRQ) injection logic: X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=e0711262cc7bef8962813f713d36cc8cabf80cb4;hp=cbe14745457d9a646157633e1fa8eccffe035953;p=palacios.git Fixes to interrupt (IRQ and VIRQ) injection logic: - eliminates potential race condition between intr being pending when intially checked, and no vector available before injection begins - differentiates "do no have a vector" from "vector 0" - detects VIRQ 0 correctly if it is raised --- diff --git a/palacios/include/palacios/vmm_intr.h b/palacios/include/palacios/vmm_intr.h index de98185..df1750b 100644 --- a/palacios/include/palacios/vmm_intr.h +++ b/palacios/include/palacios/vmm_intr.h @@ -28,7 +28,7 @@ #include -typedef enum {V3_INVALID_INTR, V3_EXTERNAL_IRQ, V3_VIRTUAL_IRQ, V3_NMI, V3_SOFTWARE_INTR} v3_intr_type_t; +typedef enum {V3_INVALID_INTR=0, V3_EXTERNAL_IRQ, V3_VIRTUAL_IRQ, V3_NMI, V3_SOFTWARE_INTR} v3_intr_type_t; struct guest_info; struct v3_vm_info; @@ -121,7 +121,7 @@ void v3_remove_intr_controller(struct guest_info * core, void * handle); void v3_remove_intr_router(struct v3_vm_info * vm, void * handle); v3_intr_type_t v3_intr_pending(struct guest_info * info); -uint32_t v3_get_intr(struct guest_info * info); +int v3_get_intr(struct guest_info * info); int v3_injecting_intr(struct guest_info * info, uint_t intr_num, v3_intr_type_t type); diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 847bb1e..c226e68 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -527,7 +527,11 @@ static int update_irq_entry_state(struct guest_info * info) { } else { switch (v3_intr_pending(info)) { case V3_EXTERNAL_IRQ: { - uint32_t irq = v3_get_intr(info); + int irq = v3_get_intr(info); + + if (irq<0) { + break; + } guest_ctrl->guest_ctrl.V_IRQ = 1; guest_ctrl->guest_ctrl.V_INTR_VECTOR = irq; diff --git a/palacios/src/palacios/vmm_intr.c b/palacios/src/palacios/vmm_intr.c index 2e78872..ee54bef 100644 --- a/palacios/src/palacios/vmm_intr.c +++ b/palacios/src/palacios/vmm_intr.c @@ -369,7 +369,7 @@ v3_intr_type_t v3_intr_pending(struct guest_info * info) { // External IRQs have lowest priority list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) { - if (ctrl->ctrl_ops->intr_pending(info, ctrl->priv_data) == 1) { + if (ctrl->ctrl_ops->intr_pending(info, ctrl->priv_data)) { ret = V3_EXTERNAL_IRQ; break; } @@ -394,12 +394,14 @@ v3_intr_type_t v3_intr_pending(struct guest_info * info) { } -uint32_t v3_get_intr(struct guest_info * info) { +int v3_get_intr(struct guest_info * info) { struct v3_intr_core_state * intr_state = &(info->intr_core_state); struct intr_controller * ctrl = NULL; - uint_t ret = 0; + int ret = -1; int i = 0; int j = 0; + int found_virq=0; + int found_irq=0; addr_t irq_state = v3_lock_irqsave(intr_state->irq_lock); @@ -409,6 +411,8 @@ uint32_t v3_get_intr(struct guest_info * info) { for (j = 0; j < 8; j++) { if (intr_state->virq_map[i] & (1 << j)) { ret = (i * 8) + j; + // need to be able to find virq 0 + found_virq=1; break; } } @@ -416,20 +420,28 @@ uint32_t v3_get_intr(struct guest_info * info) { } } - if (!ret) { + if (!found_virq) { list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) { if (ctrl->ctrl_ops->intr_pending(info, ctrl->priv_data)) { - uint_t intr_num = ctrl->ctrl_ops->get_intr_number(info, ctrl->priv_data); + int intr_num = ctrl->ctrl_ops->get_intr_number(info, ctrl->priv_data); - // PrintDebug(info->vm_info, info, "[get_intr_number] intr_number = %d\n", intr_num); - ret = intr_num; - break; + if (intr_num >= 0) { + // PrintDebug(info->vm_info, info, "[get_intr_number] intr_number = %d\n", intr_num); + ret = intr_num; + found_irq=1; + break; + } + } } } v3_unlock_irqrestore(intr_state->irq_lock, irq_state); + if (!found_virq && !found_irq) { + PrintError(info->vm_info,info,"Strange... neither a VIRQ nor an IRQ was found...\n"); + } + return ret; } diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index 2741051..2653af0 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -820,7 +820,14 @@ static int update_irq_entry_state(struct guest_info * info) { switch (v3_intr_pending(info)) { case V3_EXTERNAL_IRQ: { - info->intr_core_state.irq_vector = v3_get_intr(info); + + int irq = v3_get_intr(info); + + if (irq<0) { + break; + } + + info->intr_core_state.irq_vector = irq; ent_int.vector = info->intr_core_state.irq_vector; ent_int.type = 0; ent_int.error_code = 0;