Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


reworked the interrupt handling to streamline things, also added initial support...
Jack Lange [Tue, 11 Aug 2009 21:49:07 +0000 (16:49 -0500)]
palacios/include/palacios/vmcb.h
palacios/include/palacios/vmm_intr.h
palacios/src/palacios/svm_handler.c
palacios/src/palacios/vmm_intr.c

index 04dec0a..94e8d88 100644 (file)
@@ -179,8 +179,7 @@ struct Guest_Control {
     uint_t rsvd4      : 24;  // Should be 0
 } __attribute__((packed));
 
-#define SVM_INJECTION_EXTERNAL_INTR 0
-#define SVM_INJECTION_VIRTUAL_INTR  0
+#define SVM_INJECTION_IRQ  0
 #define SVM_INJECTION_NMI           2
 #define SVM_INJECTION_EXCEPTION     3
 #define SVM_INJECTION_SOFT_INTR     4
index 8dc5fd8..5f44b9e 100644 (file)
@@ -28,7 +28,7 @@
 #include <palacios/vmm_lock.h>
 
 
-typedef enum {INVALID_INTR, EXTERNAL_IRQ, NMI, SOFTWARE_INTR, VIRTUAL_INTR} intr_type_t;
+typedef enum {V3_INVALID_INTR, V3_EXTERNAL_IRQ, V3_VIRTUAL_IRQ, V3_NMI, V3_SOFTWARE_INTR} v3_intr_type_t;
 
 struct guest_info;
 struct v3_interrupt;
@@ -40,6 +40,7 @@ struct v3_irq_hook {
     void * priv_data;
 };
 
+#define MAX_IRQ 256
 
 
 
@@ -52,6 +53,8 @@ struct v3_intr_state {
     uint_t irq_started;
     uint_t irq_vector;
 
+    uint8_t virq_map[MAX_IRQ / 8];
+
     v3_lock_t irq_lock;
 
     /* some way to get the [A]PIC intr */
@@ -64,6 +67,9 @@ struct v3_intr_state {
 void v3_init_interrupt_state(struct guest_info * info);
 
 
+int v3_raise_virq(struct guest_info * info, int irq);
+int v3_lower_virq(struct guest_info * info, int irq);
+
 int v3_raise_irq(struct guest_info * info, int irq);
 int v3_lower_irq(struct guest_info * info, int irq);
 
@@ -81,11 +87,12 @@ struct intr_ctrl_ops {
 
 void v3_register_intr_controller(struct guest_info * info, struct intr_ctrl_ops * ops, void * state);
 
-int v3_intr_pending(struct guest_info * info);
-uint_t v3_get_intr_number(struct guest_info * info);
-intr_type_t v3_get_intr_type(struct guest_info * info);
+v3_intr_type_t v3_intr_pending(struct guest_info * info);
+uint32_t v3_get_intr(struct guest_info * info);
+
+//intr_type_t v3_get_intr_type(struct guest_info * info);
 
-int v3_injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type);
+int v3_injecting_intr(struct guest_info * info, uint_t intr_num, v3_intr_type_t type);
 
 /*
   int start_irq(struct vm_intr * intr);
index a981c96..f7fd96e 100644 (file)
@@ -79,7 +79,7 @@ int v3_handle_svm_exit(struct guest_info * info) {
        info->intr_state.irq_started = 1;
        info->intr_state.irq_pending = 0;
 
-       v3_injecting_intr(info, info->intr_state.irq_vector, EXTERNAL_IRQ);
+       v3_injecting_intr(info, info->intr_state.irq_vector, V3_EXTERNAL_IRQ);
     }
 
     if ((info->intr_state.irq_started == 1) && (guest_ctrl->exit_int_info.valid == 0)) {
@@ -97,42 +97,6 @@ int v3_handle_svm_exit(struct guest_info * info) {
     }
 
 
-    // Disable printing io exits due to bochs debug messages
-    //if (!((exit_code == VMEXIT_IOIO) && ((ushort_t)(guest_ctrl->exit_info1 >> 16) == 0x402))) {
-
-    if ((0) && (exit_code <= VMEXIT_EXCP14)) {
-       uchar_t instr[32];
-       int ret;
-       // Dump out the instr stream
-
-       //PrintDebug("RIP: %x\n", guest_state->rip);
-       PrintDebug("\n\n\nRIP Linear: %p\n", (void *)get_addr_linear(info, info->rip, &(info->segments.cs)));
-
-       v3_print_GPRs(info);
-       v3_print_ctrl_regs(info);
-
-
-       // OK, now we will read the instruction
-       // The only difference between PROTECTED and PROTECTED_PG is whether we read
-       // from guest_pa or guest_va
-       if (info->mem_mode == PHYSICAL_MEM) { 
-           // The real rip address is actually a combination of the rip + CS base 
-           ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 32, instr);
-       } else { 
-           ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 32, instr);
-       }
-
-
-       if (ret != 32) {
-           // I think we should inject a GPF into the guest
-           PrintDebug("Could not read instruction (ret=%d)\n", ret);
-       } else {
-           PrintDebug("Instr Stream:\n");
-           PrintTraceMemDump(instr, 32);
-       }
-    }
-
-
 
     if (info->enable_profiler) {
        rdtscll(info->profiler.start_time);
@@ -362,7 +326,6 @@ int v3_handle_svm_exit(struct guest_info * info) {
     }
 
 
-
     if (v3_excp_pending(info)) {
        uint_t excp = v3_get_excp_number(info);
        
@@ -394,15 +357,11 @@ int v3_handle_svm_exit(struct guest_info * info) {
        guest_ctrl->guest_ctrl.V_IGN_TPR = 1;
        guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf;
 
-    } else if (v3_intr_pending(info)) {
+    } else {
+       switch (v3_intr_pending(info)) {
+           case V3_EXTERNAL_IRQ: {
+               uint32_t irq = v3_get_intr(info);
 
-       switch (v3_get_intr_type(info)) {
-           case EXTERNAL_IRQ: {
-               uint_t irq = v3_get_intr_number(info);
-                   
-               // check to see if ==-1 (non exists)
-                   
-                   
                guest_ctrl->guest_ctrl.V_IRQ = 1;
                guest_ctrl->guest_ctrl.V_INTR_VECTOR = irq;
                guest_ctrl->guest_ctrl.V_IGN_TPR = 1;
@@ -416,27 +375,24 @@ int v3_handle_svm_exit(struct guest_info * info) {
 
                info->intr_state.irq_pending = 1;
                info->intr_state.irq_vector = irq;
-                   
+               
                break;
            }
-           case NMI:
+           case V3_NMI:
                guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI;
                break;
-           case SOFTWARE_INTR:
+           case V3_SOFTWARE_INTR:
                guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
                break;
-           case VIRTUAL_INTR:
-               guest_ctrl->EVENTINJ.type = SVM_INJECTION_VIRTUAL_INTR;
+           case V3_VIRTUAL_IRQ:
+               guest_ctrl->EVENTINJ.type = SVM_INJECTION_IRQ;
                break;
-               
-           case INVALID_INTR: 
+
+           case V3_INVALID_INTR:
            default:
-               PrintError("Attempted to issue an invalid interrupt\n");
-               return -1;
+               break;
        }
        
-    } else {
-       //PrintDebug("Not interrupts or exceptions pending\n");
     }
 
 
index b65dfef..358b307 100644 (file)
@@ -146,8 +146,25 @@ int v3_deliver_irq(struct guest_info * info, struct v3_interrupt * intr) {
 
 
 
+int v3_raise_virq(struct guest_info * info, int irq) {
+    struct v3_intr_state * intr_state = &(info->intr_state);
+    int major = irq / 8;
+    int minor = irq % 8;
+
+    intr_state->virq_map[major] |= (1 << minor);
+   
+    return 0;
+}
+
+int v3_lower_virq(struct guest_info * info, int irq) {
+    struct v3_intr_state * intr_state = &(info->intr_state);
+    int major = irq / 8;
+    int minor = irq % 8;
 
+    intr_state->virq_map[major] &= ~(1 << minor);
 
+    return 0;
+}
 
 
 int v3_lower_irq(struct guest_info * info, int irq) {
@@ -184,68 +201,95 @@ int v3_raise_irq(struct guest_info * info, int irq) {
 
 
 
-int v3_intr_pending(struct guest_info * info) {
+v3_intr_type_t v3_intr_pending(struct guest_info * info) {
     struct v3_intr_state * intr_state = &(info->intr_state);
     struct intr_controller * ctrl = NULL;
-    int ret = 0;
+    int ret = V3_INVALID_INTR;
+    int i = 0;
 
     //  PrintDebug("[intr_pending]\n");
-    addr_t irq_state = v3_lock_irqsave(intr_state->irq_lock);    
+    addr_t irq_state = v3_lock_irqsave(intr_state->irq_lock);
 
-    list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) {
-       if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data) == 1) {
-           ret = 1;
+    // VIRQs have priority
+    for (i = 0; i < MAX_IRQ / 8; i++) {
+       if (intr_state->virq_map[i] != 0) {   
+           ret = V3_VIRTUAL_IRQ;
            break;
        }
     }
 
+    if (ret == V3_INVALID_INTR) {
+       list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) {
+           if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data) == 1) {
+               ret = V3_EXTERNAL_IRQ;
+               break;
+           }
+       }
+    }
+
     v3_unlock_irqrestore(intr_state->irq_lock, irq_state);
 
     return ret;
 }
 
 
-uint_t v3_get_intr_number(struct guest_info * info) {
+uint32_t v3_get_intr(struct guest_info * info) {
     struct v3_intr_state * intr_state = &(info->intr_state);
     struct intr_controller * ctrl = NULL;
     uint_t ret = 0;
+    int i = 0;
+    int j = 0;
 
     addr_t irq_state = v3_lock_irqsave(intr_state->irq_lock);    
 
-    list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) {
-       if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data)) {
-           uint_t intr_num = ctrl->ctrl_ops->get_intr_number(ctrl->priv_data);
-           
-           //  PrintDebug("[get_intr_number] intr_number = %d\n", intr_num);
-           ret = intr_num;
+    // virqs have priority
+    for (i = 0; i < MAX_IRQ / 8; i++) {
+       if (intr_state->virq_map[i] != 0) {
+           for (j = 0; j < 8; j++) {
+               if (intr_state->virq_map[i] & (1 << j)) {
+                   ret = (i * 8) + j;
+                   break;
+               }
+           }
            break;
        }
     }
 
-    v3_unlock_irqrestore(intr_state->irq_lock, irq_state);
+    if (!ret) {
+       list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) {
+           if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data)) {
+               uint_t intr_num = ctrl->ctrl_ops->get_intr_number(ctrl->priv_data);
+               
+               //      PrintDebug("[get_intr_number] intr_number = %d\n", intr_num);
+               ret = intr_num;
+               break;
+           }
+       }
+    }
 
+    v3_unlock_irqrestore(intr_state->irq_lock, irq_state);
 
     return ret;
 }
 
-
+/*
 intr_type_t v3_get_intr_type(struct guest_info * info) {
     struct v3_intr_state * intr_state = &(info->intr_state);
     struct intr_controller * ctrl = NULL;
-    intr_type_t type = INVALID_INTR;
+    intr_type_t type = V3_INVALID_INTR;
 
     addr_t irq_state = v3_lock_irqsave(intr_state->irq_lock);  
 
     list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) {
        if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data) == 1) {
            //PrintDebug("[get_intr_type] External_irq\n");
-           type = EXTERNAL_IRQ;
+           type = V3_EXTERNAL_IRQ;         
            break;
        }
     }
 
 #ifdef DEBUG_INTERRUPTS
-    if (type == INVALID_INTR) {
+    if (type == V3_INVALID_INTR) {
        PrintError("[get_intr_type] Invalid_Intr\n");
     }
 #endif
@@ -254,16 +298,16 @@ intr_type_t v3_get_intr_type(struct guest_info * info) {
 
     return type;
 }
+*/
 
 
 
 
 
-
-int v3_injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type) {
+int v3_injecting_intr(struct guest_info * info, uint_t intr_num, v3_intr_type_t type) {
     struct v3_intr_state * intr_state = &(info->intr_state);
 
-    if (type == EXTERNAL_IRQ) {
+    if (type == V3_EXTERNAL_IRQ) {
        struct intr_controller * ctrl = NULL;
 
        addr_t irq_state = v3_lock_irqsave(intr_state->irq_lock);