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.


Partially functional icc_bus (works for UP)
Peter Dinda [Thu, 8 Jul 2010 23:11:53 +0000 (18:11 -0500)]
Works up to init for SMP

palacios/include/devices/apic_regs.h
palacios/include/devices/icc_bus.h
palacios/src/devices/Kconfig
palacios/src/devices/apic.c
palacios/src/devices/icc_bus.c
palacios/src/devices/io_apic.c
palacios/src/palacios/vmm_telemetry.c

index 4d4f540..67f5b24 100644 (file)
@@ -220,7 +220,7 @@ struct int_cmd_reg {
 
        struct {
            uint_t vec           : 8;
-           uint_t msg_type      : 3;
+           uint_t del_mode      : 3; 
            uint_t dst_mode      : 1;
            uint_t del_status    : 1;
            uint_t rsvd1         : 1;
index c51f6f8..6b1fabb 100644 (file)
@@ -29,19 +29,32 @@ struct v3_icc_ops {
 /**
  *
  */
-int v3_icc_register_apic(struct guest_info * vm, struct vm_device * icc_bus, uint8_t apic_phys_id, struct v3_icc_ops * ops, void * priv_data);
-
+int v3_icc_register_apic(struct guest_info *core, struct vm_device * icc_bus, uint8_t apic_phys_id, struct v3_icc_ops * ops, void * priv_data);
+int v3_icc_register_ioapic(struct v3_vm_info *vm, struct vm_device * icc_bus, uint8_t apic_phys_id);
 
 /**
- * Send an inter-processor interrupt (IPI) from this local APIC to another local APIC.
+ * Send an inter-processor interrupt (IPI) from one local APIC to another local APIC.
  *
- * @param icc_bus - The ICC bus that routes IPIs.
+ * @param icc_bus  - The ICC bus that routes IPIs.
+ * @param apic_src - The source APIC id.
  * @param apic_num - The remote APIC number.
- * @param intr_num - The interrupt number.
+ * @param icr      - A copy of the APIC's ICR.  (LAPIC-style ICR, clone from redir table for ioapics)
  */
-int v3_icc_send_irq(struct vm_device * icc_bus, uint8_t apic_num, uint32_t irq_num);
+int v3_icc_send_ipi(struct vm_device * icc_bus, uint32_t apic_src, uint64_t icr);
+
 
+#if 0
+/**
+ * Send an IRQinter-processor interrupt (IPI) from one local APIC to another local APIC.
+ *
+ * @param icc_bus  - The ICC bus that routes IPIs.
+ * @param apic_src - The source APIC id.
+ * @param apic_num - The remote APIC number.
+ * @param icrlo    - The low 32 bites of the APIC's ICR.
+ */
+int v3_icc_send_irq(struct vm_device * icc_bus, uint32_t ioapic_src, uint8_t apic_num, uint8_t irq);
 
+#endif
 
 
 #endif /* ICC_BUS_H_ */
index b04376f..9a07e71 100644 (file)
@@ -38,6 +38,13 @@ config ICC_BUS
        help 
          The ICC Bus for APIC/IOAPIC communication
 
+config DEBUG_ICC_BUS
+       bool "ICC BUS Debugging"
+       default n
+       depends on ICC_BUS && DEBUG_ON
+       help
+         Enable debugging for the ICC BUS
+
 
 config BOCHS_DEBUG
        bool "Bochs Debug Console Device"
index 7289717..b35258d 100644 (file)
@@ -191,12 +191,12 @@ struct apic_state {
 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data);
 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data);
 
-static void init_apic_state(struct apic_state * apic, uint32_t id) {
+static void init_apic_state(struct apic_state * apic, uint32_t id, struct vm_device * icc) {
     apic->base_addr = DEFAULT_BASE_ADDR;
     apic->base_addr_msr.value = 0x0000000000000900LL;
     apic->base_addr_msr.value |= ((uint64_t)DEFAULT_BASE_ADDR); 
 
-    PrintDebug("Sizeof Interrupt Request Register %d, should be 32\n", 
+    PrintDebug("apic %u: Sizeof Interrupt Request Register %d, should be 32\n", apic->lapic_id.val,
               (uint_t)sizeof(apic->int_req_reg));
 
     memset(apic->int_req_reg, 0, sizeof(apic->int_req_reg));
@@ -210,6 +210,8 @@ static void init_apic_state(struct apic_state * apic, uint32_t id) {
     apic->tmr_cur_cnt = 0x00000000;
 
     apic->lapic_id.val = id;
+    
+    apic->icc_bus = icc;
 
     // The P6 has 6 LVT entries, so we set the value to (6-1)...
     apic->apic_ver.val = 0x80050010;
@@ -261,7 +263,7 @@ static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, vo
 
     if (old_reg == NULL) {
        // uh oh...
-       PrintError("APIC Base address region does not exit...\n");
+       PrintError("apic %u: APIC Base address region does not exit...\n",apic->lapic_id.val);
        return -1;
     }
     
@@ -272,7 +274,7 @@ static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, vo
     apic->base_addr = src.value;
 
     if (v3_hook_full_mem(dev->vm, core->cpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, dev) == -1) {
-       PrintError("Could not hook new APIC Base address\n");
+       PrintError("apic %u: Could not hook new APIC Base address\n",apic->lapic_id.val);
        v3_unlock(apic->lock);
        return -1;
     }
@@ -290,12 +292,18 @@ static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
     uchar_t * en_location = apic->int_en_reg + major_offset;
     uchar_t flag = 0x1 << minor_offset;
 
+
+#if 1
+
     if (irq_num <= 15) {
-       PrintError("Attempting to raise an invalid interrupt: %d\n", irq_num);
+       PrintError("apic %u: Attempting to raise an invalid interrupt: %d\n", apic->lapic_id.val,irq_num);
        return -1;
     }
 
-    PrintDebug("Raising APIC IRQ %d\n", irq_num);
+#endif
+
+
+    PrintDebug("apic %u: Raising APIC IRQ %d\n", apic->lapic_id.val,irq_num);
 
     if (*req_location & flag) {
        //V3_Print("Interrupts coallescing\n");
@@ -304,7 +312,7 @@ static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
     if (*en_location & flag) {
        *req_location |= flag;
     } else {
-       PrintDebug("Interrupt  not enabled... %.2x\n", *en_location);
+       PrintDebug("apic %u: Interrupt  not enabled... %.2x\n", apic->lapic_id.val, *en_location);
        return 0;
     }
 
@@ -428,13 +436,13 @@ static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_t
            masked = apic->err_vec_tbl.mask;
            break;
        default:
-           PrintError("Invalid APIC interrupt type\n");
+           PrintError("apic %u: Invalid APIC interrupt type\n",apic->lapic_id.val);
            return -1;
     }
 
     // interrupt is masked, don't send
     if (masked == 1) {
-       PrintDebug("Inerrupt is masked\n");
+       PrintDebug("apic %u: Inerrupt is masked\n",apic->lapic_id.val);
        return 0;
     }
 
@@ -442,24 +450,25 @@ static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_t
        //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
        return activate_apic_irq(apic, vec_num);
     } else {
-       PrintError("Unhandled Delivery Mode\n");
+       PrintError("apic %u: Unhandled Delivery Mode\n",apic->lapic_id.val);
        return -1;
     }
 }
 
 
 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
-    struct apic_state * apic = (struct apic_state *)priv_data;
+    struct apic_state * apics = (struct apic_state *)(priv_data);
+    struct apic_state * apic = &(apics[core->cpu_id]);
     addr_t reg_addr  = guest_addr - apic->base_addr;
     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
     uint32_t val = 0;
 
 
-    PrintDebug("Read apic address space (%p)\n", 
+    PrintDebug("apic %u: Read apic address space (%p)\n",apic->lapic_id.val, 
               (void *)guest_addr);
 
     if (msr->apic_enable == 0) {
-       PrintError("Write to APIC address space with disabled APIC\n");
+       PrintError("apic %u: Write to APIC address space with disabled APIC\n",apic->lapic_id.val);
        return -1;
     }
 
@@ -671,8 +680,9 @@ static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, ui
        case SEOI_OFFSET:
 
        default:
-           PrintError("Read from Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
-           return -1;
+           PrintError("apic %u: Read from Unhandled APIC Register: %x (getting zero)\n", apic->lapic_id.val, (uint32_t)reg_addr);
+           //      return -1;
+           val=0;
     }
 
 
@@ -693,11 +703,11 @@ static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, ui
        *val_ptr = val;
 
     } else {
-       PrintError("Invalid apic read length (%d)\n", length);
+       PrintError("apic %u: Invalid apic read length (%d)\n", apic->lapic_id.val, length);
        return -1;
     }
 
-    PrintDebug("Read finished (val=%x)\n", *(uint32_t *)dst);
+    PrintDebug("apic %u: Read finished (val=%x)\n", apic->lapic_id.val, *(uint32_t *)dst);
 
     return length;
 }
@@ -707,22 +717,24 @@ static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, ui
  *
  */
 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data) {
-    struct apic_state * apic = (struct apic_state *)priv_data;
+    struct apic_state * apics = (struct apic_state *)(priv_data);
+    struct apic_state * apic = &(apics[core->cpu_id]);
     addr_t reg_addr  = guest_addr - apic->base_addr;
     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
     uint32_t op_val = *(uint32_t *)src;
 
-    PrintDebug("Write to apic address space (%p) (val=%x)\n", 
+    PrintDebug("apic %u: Write to address space (%p) (val=%x)\n", 
+              apic->lapic_id.val,
               (void *)guest_addr, *(uint32_t *)src);
 
     if (msr->apic_enable == 0) {
-       PrintError("Write to APIC address space with disabled APIC\n");
+       PrintError("apic %u: Write to APIC address space with disabled APIC\n",apic->lapic_id.val);
        return -1;
     }
 
 
     if (length != 4) {
-       PrintError("Invalid apic write length (%d)\n", length);
+       PrintError("apic %u: Invalid apic write length (%d)\n", apic->lapic_id.val, length);
        return -1;
     }
 
@@ -757,9 +769,9 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
        case PPR_OFFSET:
        case EXT_APIC_FEATURE_OFFSET:
 #if 1
-           PrintError("Attempting to write to read only register %p (ignored)\n", (void *)reg_addr);
+           PrintError("apic %u: Attempting to write to read only register %p (ignored)\n", apic->lapic_id.val, (void *)reg_addr);
 #else   
-           PrintError("Attempting to write to read only register %p (error)\n", (void *)reg_addr);
+           PrintError("apic %u: Attempting to write to read only register %p (error)\n", apic->lapic_id.val, (void *)reg_addr);
            return -1;
 #endif
            break;
@@ -862,7 +874,9 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
        case INT_CMD_LO_OFFSET:
            apic->int_cmd.lo = op_val;
            // ICC???
-           v3_icc_send_irq(apic->icc_bus, apic->int_cmd.dst, apic->int_cmd.val);
+           PrintDebug("apic %u: sending cmd 0x%llx to apic %u\n",apic->lapic_id.val,
+                      apic->int_cmd.val, apic->int_cmd.dst);
+           v3_icc_send_ipi(apic->icc_bus, apic->lapic_id.val, apic->int_cmd.val);
            break;
        case INT_CMD_HI_OFFSET:
            apic->int_cmd.hi = op_val;
@@ -872,11 +886,11 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
        case EXT_APIC_CMD_OFFSET:
        case SEOI_OFFSET:
        default:
-           PrintError("Write to Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
-           return -1;
+           PrintError("apic %u: Write to Unhandled APIC Register: %x (ignored)\n", apic->lapic_id.val, (uint32_t)reg_addr);
+           //      return -1;
     }
 
-    PrintDebug("Write finished\n");
+    PrintDebug("apic %u: Write finished\n",apic->lapic_id.val);
 
     return length;
 }
@@ -943,7 +957,8 @@ static int apic_begin_irq(struct guest_info * info, void * private_data, int irq
 
 /* Timer Functions */
 static void apic_update_time(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data) {
-    struct apic_state * apic = (struct apic_state *)priv_data;
+    struct apic_state * apics = (struct apic_state *)(priv_data);
+    struct apic_state * apic = &(apics[info->cpu_id]);
     // The 32 bit GCC runtime is a pile of shit
 #ifdef __V3_64BIT__
     uint64_t tmr_ticks = 0;
@@ -961,7 +976,7 @@ static void apic_update_time(struct guest_info * info, ullong_t cpu_cycles, ullo
     if ((apic->tmr_init_cnt == 0) || 
        ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
          (apic->tmr_cur_cnt == 0))) {
-       //PrintDebug("APIC timer not yet initialized\n");
+       //PrintDebug("apic %u: APIC timer not yet initialized\n",apic->lapic_id.val);
        return;
     }
 
@@ -992,7 +1007,7 @@ static void apic_update_time(struct guest_info * info, ullong_t cpu_cycles, ullo
            shift_num = 7;
            break;
        default:
-           PrintError("Invalid Timer Divider configuration\n");
+           PrintError("apic %u: Invalid Timer Divider configuration\n",apic->lapic_id.val);
            return;
     }
 
@@ -1006,15 +1021,15 @@ static void apic_update_time(struct guest_info * info, ullong_t cpu_cycles, ullo
        apic->tmr_cur_cnt = 0;
 
        // raise irq
-       PrintDebug("Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n", 
+       PrintDebug("apic %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n", apic->lapic_id.val,
                   apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
 
        if (apic_intr_pending(info, priv_data)) {
-           PrintDebug("Overriding pending IRQ %d\n", apic_get_intr_number(info, priv_data));
+           PrintDebug("apic %u: Overriding pending IRQ %d\n", apic->lapic_id.val, apic_get_intr_number(info, priv_data));
        }
 
        if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
-           PrintError("Could not raise Timer interrupt\n");
+           PrintError("apic %u: Could not raise Timer interrupt\n",apic->lapic_id.val);
        }
     
        if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
@@ -1042,6 +1057,9 @@ static struct vm_timer_ops timer_ops = {
 
 
 static int apic_free(struct vm_device * dev) {
+
+    /* TODO: This should crosscall to force an unhook on each CPU */
+
     //   struct apic_state * apic = (struct apic_state *)dev->private_data;
 
     v3_unhook_msr(dev->vm, BASE_ADDR_MSR);
@@ -1066,14 +1084,14 @@ static struct v3_icc_ops icc_ops = {
 
 
 static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
-    PrintDebug("Creating an APIC for each core\n");
+    PrintDebug("apic: creating an APIC for each core\n");
     char * name = v3_cfg_val(cfg, "name");
     char * icc_name = v3_cfg_val(cfg,"bus");
     struct vm_device * icc = v3_find_dev(vm, icc_name);
     int i;
 
     if (!icc) {
-        PrintError("Cannot find ICC Bus (%s)\n", icc_name);
+        PrintError("apic: Cannot find ICC Bus (%s)\n", icc_name);
         return -1;
     }
 
@@ -1085,7 +1103,7 @@ static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct vm_device * dev = v3_allocate_device(name, &dev_ops, apic);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", name);
+       PrintError("apic: Could not attach device %s\n", name);
        return -1;
     }
 
@@ -1093,7 +1111,7 @@ static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     for (i = 0; i < vm->num_cores; i++) {
        struct guest_info * core = &(vm->cores[i]);
 
-       init_apic_state(&(apic[i]),i);
+       init_apic_state(&(apic[i]),i,icc);
 
        v3_register_intr_controller(core, &intr_ops, &(apic[i]));
 
index f5de549..e75734d 100644 (file)
 #include <palacios/vmm_sprintf.h>
 #include <palacios/vm_guest.h>
 #include <devices/icc_bus.h>
+#include <devices/apic_regs.h>
+
 
 #define MAX_APICS 256
 
+#ifndef CONFIG_DEBUG_ICC_BUS
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
+
+void v3_force_exit() {
+}
 
 struct ipi_thunk_data {
     struct vm_device * target;
     uint64_t val;
 };
 
-struct int_cmd_reg {
-    union {
-        uint64_t val;
-
-        struct {
-            uint32_t lo;
-            uint32_t hi;
-        } __attribute__((packed));
-
-        struct {
-            uint_t vec           : 8;
-            uint_t msg_type      : 3;
-            uint_t dst_mode      : 1;
-            uint_t del_status    : 1;
-            uint_t rsvd1         : 1;
-            uint_t lvl           : 1;
-            uint_t trig_mode     : 1;
-            uint_t rem_rd_status : 2;
-            uint_t dst_shorthand : 2;
-            uint64_t rsvd2       : 36;
-            uint32_t dst         : 8;
-        } __attribute__((packed));
-    } __attribute__((packed));
-} __attribute__((packed));
-
-
 
 
 struct apic_data {
@@ -69,6 +53,8 @@ struct apic_data {
 
 struct icc_bus_state {
     struct apic_data apics[MAX_APICS];
+    
+    uint32_t         ioapic_id;
 };
 
 static struct v3_device_ops dev_ops = {
@@ -79,59 +65,131 @@ static struct v3_device_ops dev_ops = {
 };
 
 
+static char *shorthand_str[] = { 
+    "(no shorthand)",
+    "(self)",
+    "(all)",
+    "(all-but-me)",
+ };
+
+static char *deliverymode_str[] = { 
+    "(fixed)",
+    "(lowest priority)",
+    "(SMI)",
+    "(reserved)",
+    "(NMI)",
+    "(INIT)",
+    "(Start Up)",
+    "(reserved)",
+};
 
 
-int v3_icc_send_irq(struct vm_device * icc_bus, uint8_t apic_num, uint32_t irq_num) {
-    struct icc_bus_state * state = (struct icc_bus_state *)icc_bus->private_data;
-    struct apic_data * apic = &(state->apics[apic_num]);    
 
+static int deliver(uint32_t src_apic, struct apic_data *dest_apic, struct int_cmd_reg *icr, struct icc_bus_state * state) {
+
+    switch (icr->del_mode) {                                           
+
+       case 0:  //fixed
+       case 1: // lowest priority
+           PrintDebug("icc_bus: delivering to core %u\n",dest_apic->core->cpu_id); 
+           dest_apic->ops->raise_intr(dest_apic->core, icr->vec, dest_apic->priv_data); 
+           if (src_apic!=state->ioapic_id && dest_apic->core->cpu_id != src_apic) { 
+               PrintDebug("icc_bus: non-local core, forcing it to exit\n"); 
+               // TODO: do what the print says
+           }                                                   
+           break;                                                      
+           
+       case 2:   //SMI                 
+           PrintError("icc_bus: SMI delivery is unsupported\n");       
+           return -1;                                          
+           break;                                                      
+           
+       case 3:  //reserved                                             
+       case 7:
+           PrintError("icc_bus: Reserved delivery mode 3 is unsupported\n"); 
+           return -1;                                          
+           break;                                                      
+
+       case 4:  //NMI                                  
+           PrintError("icc_bus: NMI delivery is unsupported\n"); 
+           return -1;                                          
+           break;                                                      
+
+       case 5: //INIT
+           PrintError("icc_bus: INIT delivery is unsupported\n"); 
+           return -1;                                          
+           break;                                                      
+
+       case 6: //Start Up
+           PrintError("icc_bus: Startup Delivery is unsupported\n"); 
+           return -1;                                          
+           break;                                                      
+    }
 
-    struct int_cmd_reg icr;
-    icr.lo = irq_num;
+    return 0;
+} 
 
 
-    char * type = NULL;
-    char * dest = NULL;
-    char foo[8];
 
-    switch (icr.dst_shorthand) {
-       case 0x0:
-           sprintf(foo, "%d", icr.dst);
-           dest = foo;
-           break;
-       case 0x1:
-           dest = "(self)";
-           break;
-       case 0x2:
-           dest = "(broadcast inclusive)";
-           break;
-       case 0x3:
-           dest = "(broadcast)";
-           break;
-    }
+int v3_icc_send_ipi(struct vm_device * icc_bus, uint32_t src_apic, uint64_t icr_data) {
 
-    switch (icr.msg_type) {
-       case 0x0:
-           type = "";
-           break;
-       case 0x4:
-           type = "(NMI)";
-           break;
-       case 0x5:
-           type = "(INIT)";
-           break;
-       case 0x6:
-           type = "(Startup)";
-           break;
+    PrintDebug("icc_bus: icc_bus=%p, src_apic=%u, icr_data=%llx\n",icc_bus,src_apic,icr_data);
+
+    struct int_cmd_reg *icr = (struct int_cmd_reg *)&icr_data;
+    struct icc_bus_state * state = (struct icc_bus_state *)icc_bus->private_data;
+
+    // initial sanity checks
+    if (src_apic>=MAX_APICS || (!state->apics[src_apic].present && src_apic!=state->ioapic_id)) { 
+       PrintError("icc_bus: Apparently sending from unregistered apic id=%u\n",src_apic);
+       return -1;
+    }
+    if (icr->dst_mode==0  && !state->apics[icr->dst].present) { 
+       PrintError("icc_bus: Attempted send to unregistered apic id=%u\n",icr->dst);
+       return -1;
     }
+    
+    struct apic_data * dest_apic =  &(state->apics[icr->dst]);
+
+
+    PrintDebug("icc_bus: IPI %s %u from %s %u to %s %u (icr=0x%llx)\n",
+              deliverymode_str[icr->del_mode], icr->vec, src_apic==state->ioapic_id ? "ioapic" : "apic",
+              src_apic, shorthand_str[icr->dst_shorthand], icr->dst,icr->val);
 
 
-    PrintDebug("Sending IPI of type %s and destination type %s from LAPIC %u to LAPIC %u.\n", 
-              type, dest, V3_Get_CPU(), apic_num);
 
-    apic->ops->raise_intr(apic->core, irq_num & 0xff, apic->priv_data);
 
-    //V3_Call_On_CPU(apic_num,  icc_force_exit, (void *)(uint64_t)(val & 0xff));
+    switch (icr->dst_shorthand) {
+
+       case 0:  // no shorthand
+           if (deliver(src_apic,dest_apic,icr,state)) { 
+               return -1;
+           }
+           break;
+
+       case 1:  // self
+           if (icr->dst==state->ioapic_id) { 
+               PrintError("icc_bus: ioapic attempting to send to itself\n");
+               return -1;
+           }
+           if (deliver(src_apic,dest_apic,icr,state)) { 
+               return -1;
+           }
+           break;
+
+       case 2: 
+       case 3: { // all and all-but-me
+           int i;
+           for (i=0;i<MAX_APICS;i++) { 
+               dest_apic=&(state->apics[i]);
+               if (dest_apic->present && (i!=src_apic || icr->dst_shorthand==2)) { 
+                   if (deliver(src_apic,dest_apic,icr,state)) { 
+                       return -1;
+                   }
+               }
+           }
+       }
+           break;
+    }
 
     return 0;
 }
@@ -146,7 +204,7 @@ int v3_icc_register_apic(struct guest_info  * core, struct vm_device * icc_bus,
     struct apic_data * apic = &(icc->apics[apic_num]);
 
     if (apic->present == 1) {
-       PrintError("Attempt to re-register apic %u\n", apic_num);
+       PrintError("icc_bus: Attempt to re-register apic %u\n", apic_num);
        return -1;
     }
     
@@ -155,16 +213,33 @@ int v3_icc_register_apic(struct guest_info  * core, struct vm_device * icc_bus,
     apic->core = core;
     apic->ops = ops;
    
-    PrintDebug("Registered apic%u\n", apic_num);
+    PrintDebug("icc_bus: Registered apic %u\n", apic_num);
 
     return 0;
 }
 
 
+int v3_icc_register_ioapic(struct v3_vm_info *vm, struct vm_device * icc_bus, uint8_t apic_num)
+{
+    struct icc_bus_state * icc = (struct icc_bus_state *)icc_bus->private_data;
+
+    if (icc->ioapic_id) { 
+       PrintError("icc_bus: Attempt to register a second ioapic!\n");
+       return -1;
+    }
+
+    icc->ioapic_id=apic_num;
+
+    PrintDebug("icc_bus: Registered ioapic %u\n", apic_num);
+    
+
+    return 0;
+}
+
 
 
 static int icc_bus_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
-    PrintDebug("Creating ICC_BUS\n");
+    PrintDebug("icc_bus: Creating ICC_BUS\n");
 
     char * name = v3_cfg_val(cfg, "name");
 
@@ -174,7 +249,7 @@ static int icc_bus_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct vm_device * dev = v3_allocate_device(name, &dev_ops, icc_bus);
 
     if (v3_attach_device(vm, dev) == -1) {
-        PrintError("Could not attach device %s\n", name);
+        PrintError("icc_bus: Could not attach device %s\n", name);
         return -1;
     }
 
index 9a0db56..263f940 100644 (file)
@@ -21,6 +21,7 @@
 #include <palacios/vmm.h>
 #include <palacios/vmm_dev_mgr.h>
 #include <devices/icc_bus.h>
+#include <devices/apic_regs.h>
 #include <palacios/vm_guest.h>
 
 #ifndef CONFIG_DEBUG_IO_APIC
@@ -140,12 +141,12 @@ struct io_apic_state {
 };
 
 
-static void init_ioapic_state(struct io_apic_state * ioapic) {
+static void init_ioapic_state(struct io_apic_state * ioapic, uint32_t id) {
     int i = 0;
     ioapic->base_addr = IO_APIC_BASE_ADDR;
     ioapic->index_reg = 0;
 
-    ioapic->ioapic_id.val = 0x00000000;
+    ioapic->ioapic_id.val = id;
     ioapic->ioapic_ver.val = 0x00170011;
     ioapic->ioapic_arb_id.val = 0x00000000;
 
@@ -163,7 +164,7 @@ static int ioapic_read(struct guest_info * core, addr_t guest_addr, void * dst,
     uint32_t reg_tgt = guest_addr - ioapic->base_addr;
     uint32_t * op_val = (uint32_t *)dst;
 
-    PrintDebug("IOAPIC Read at %p\n", (void *)guest_addr);
+    PrintDebug("ioapic %u: IOAPIC Read at %p\n", ioapic->ioapic_id.val, (void *)guest_addr);
 
     if (reg_tgt == 0x00) {
        *op_val = ioapic->index_reg;
@@ -185,7 +186,7 @@ static int ioapic_read(struct guest_info * core, addr_t guest_addr, void * dst,
                    uint_t hi_val = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) % 1;
 
                    if (redir_index > 0x3f) {
-                       PrintError("Invalid redirection table entry %x\n", (uint32_t)redir_index);
+                       PrintError("ioapic %u: Invalid redirection table entry %x\n", ioapic->ioapic_id.val, (uint32_t)redir_index);
                        return -1;
                    }
                    if (hi_val) {
@@ -207,7 +208,7 @@ static int ioapic_write(struct guest_info * core, addr_t guest_addr, void * src,
     uint32_t reg_tgt = guest_addr - ioapic->base_addr;
     uint32_t op_val = *(uint32_t *)src;
 
-    PrintDebug("IOAPIC Write at %p (val = %d)\n", (void *)guest_addr, *(uint32_t *)src);
+    PrintDebug("ioapic %u: IOAPIC Write at %p (val = %d)\n",  ioapic->ioapic_id.val, (void *)guest_addr, *(uint32_t *)src);
 
     if (reg_tgt == 0x00) {
        ioapic->index_reg = op_val;
@@ -219,7 +220,7 @@ static int ioapic_write(struct guest_info * core, addr_t guest_addr, void * src,
                break;
            case IOAPIC_VER_REG:
                // GPF/PageFault/Ignore?
-               PrintError("Writing to read only IOAPIC register\n");
+               PrintError("ioapic %u: Writing to read only IOAPIC register\n", ioapic->ioapic_id.val);
                return -1;
            case IOAPIC_ARB_REG:
                ioapic->ioapic_arb_id.val = op_val;
@@ -233,14 +234,14 @@ static int ioapic_write(struct guest_info * core, addr_t guest_addr, void * src,
 
 
                    if (redir_index > 0x3f) {
-                       PrintError("Invalid redirection table entry %x\n", (uint32_t)redir_index);
+                       PrintError("ioapic %u: Invalid redirection table entry %x\n", ioapic->ioapic_id.val, (uint32_t)redir_index);
                        return -1;
                    }
                    if (hi_val) {
-                       PrintDebug("Writing to hi of pin %d\n", redir_index);
+                       PrintDebug("ioapic %u: Writing to hi of pin %d\n", ioapic->ioapic_id.val, redir_index);
                        ioapic->redir_tbl[redir_index].hi = op_val;
                    } else {
-                       PrintDebug("Writing to lo of pin %d\n", redir_index);
+                       PrintDebug("ioapic %u: Writing to lo of pin %d\n", ioapic->ioapic_id.val, redir_index);
                        op_val &= REDIR_LO_MASK;
                        ioapic->redir_tbl[redir_index].lo &= ~REDIR_LO_MASK;
                        ioapic->redir_tbl[redir_index].lo |= op_val;
@@ -259,15 +260,30 @@ static int ioapic_raise_irq(struct v3_vm_info * vm, void * private_data, int irq
     struct redir_tbl_entry * irq_entry = NULL;
 
     if (irq > 24) {
-       PrintDebug("IRQ out of range of IO APIC\n");
+       PrintDebug("ioapic %u: IRQ out of range of IO APIC\n", ioapic->ioapic_id.val);
        return -1;
     }
 
     irq_entry = &(ioapic->redir_tbl[irq]);
 
     if (irq_entry->mask == 0) {
-       PrintDebug("IOAPIC Signalling APIC to raise INTR %d\n", irq_entry->vec);
-       v3_icc_send_irq(ioapic->icc_bus, irq_entry->dst_field, irq_entry->vec);
+       PrintDebug("ioapic %u: IOAPIC Signalling APIC to raise INTR %d\n", ioapic->ioapic_id.val, irq_entry->vec);
+
+       // the format of the redirection table entry is just slightly 
+       // different than that of the lapic's cmd register, which is the other
+       // way an IPI is initiated.   So we will translate
+       //
+       struct int_cmd_reg icr;
+       
+       icr.val = irq_entry->val;
+       icr.rsvd1=0;
+       icr.lvl=1;
+       icr.trig_mode=irq_entry->trig_mode;
+       icr.rem_rd_status=0;
+       icr.dst_shorthand=0; // no shorthand
+       icr.rsvd2=0;
+
+       v3_icc_send_ipi(ioapic->icc_bus, ioapic->ioapic_id.val,icr.val);
     }
 
     return 0;
@@ -307,11 +323,11 @@ static int ioapic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     char * name = v3_cfg_val(cfg, "name");
 
     if (!icc_bus) {
-       PrintError("Could not locate ICC BUS device (%s)\n", v3_cfg_val(cfg, "bus"));
+       PrintError("ioapic: Could not locate ICC BUS device (%s)\n", v3_cfg_val(cfg, "bus"));
        return -1;
     }
 
-    PrintDebug("Creating IO APIC\n");
+    PrintDebug("ioapic: Creating IO APIC\n");
 
     struct io_apic_state * ioapic = (struct io_apic_state *)V3_Malloc(sizeof(struct io_apic_state));
 
@@ -321,13 +337,16 @@ static int ioapic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
 
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", name);
+       PrintError("ioapic: Could not attach device %s\n", name);
        return -1;
     }
 
 
     v3_register_intr_router(vm, &router_ops, dev);
-    init_ioapic_state(ioapic);
+
+    init_ioapic_state(ioapic,vm->num_cores);
+
+    v3_icc_register_ioapic(vm,icc_bus,ioapic->ioapic_id.val);
 
     v3_hook_full_mem(vm, V3_MEM_CORE_ANY, ioapic->base_addr, ioapic->base_addr + PAGE_SIZE_4KB, 
                     ioapic_read, ioapic_write, dev);
index 16088a2..fae3c76 100644 (file)
@@ -211,6 +211,11 @@ void v3_print_telemetry(struct v3_vm_info * vm) {
        
        V3_Print("Exit information for Core %d\n", core->cpu_id);
 
+       if (!node) { 
+           V3_Print("No information yet for this core\n");
+           continue;
+       }
+
        do {
            evt = rb_entry(node, struct exit_event, tree_node);
            const char * code_str = vmexit_code_to_str(evt->exit_code);