+
+
struct apic_msr {
union {
uint64_t value;
+typedef enum {INIT, SIPI, STARTED} ipi_state_t;
struct apic_state {
addr_t base_addr;
uint32_t rem_rd_data;
+ ipi_state_t ipi_state;
+
uint8_t int_req_reg[32];
uint8_t int_svc_reg[32];
uint8_t int_en_reg[32];
v3_lock_t lock;
};
+
+
+
+
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);
apic->icc_bus = icc;
+ apic->ipi_state = INIT;
+
// The P6 has 6 LVT entries, so we set the value to (6-1)...
apic->apic_ver.val = 0x80050010;
PrintError("apic %u: core %u: Attempting to write to read only register %p (error)\n",
apic->lapic_id.val, core->cpu_id, (void *)reg_addr);
- return -1;
+ // return -1;
break;
apic->task_prio.val = op_val;
break;
case LDR_OFFSET:
+ PrintDebug("apic %u: core %u: setting log_dst.val to 0x%x\n",
+ apic->lapic_id.val, core->cpu_id, op_val);
apic->log_dst.val = op_val;
break;
case DFR_OFFSET:
// ICC???
PrintDebug("apic %u: core %u: sending cmd 0x%llx to apic %u\n",
- apic->clapic_id.val, core->cpu_id,
+ apic->lapic_id.val, core->cpu_id,
apic->int_cmd.val, apic->int_cmd.dst);
-
- v3_icc_send_ipi(apic->icc_bus, apic->lapic_id.val, apic->int_cmd.val, 0);
+ if (v3_icc_send_ipi(apic->icc_bus, apic->lapic_id.val, apic->int_cmd.val, 0)==-1) {
+ return -1;
+ }
break;
case INT_CMD_HI_OFFSET:
static struct vm_timer_ops timer_ops = {
- .update_time = apic_update_time,
+ .update_timer = apic_update_time,
};
.stop = NULL,
};
+static int apic_should_deliver_flat(struct guest_info * core, uint8_t mda, void * private_data)
+{
+ struct apic_state * apic = (struct apic_state *)private_data;
+
+ if (mda==0xff || // broadcast or
+ (apic->log_dst.dst_log_id & mda)) { // I am in the set
+ PrintDebug("apic %u core %u: accepting flat IRQ (mda 0x%x == log_dst 0x%x)\n",
+ apic->lapic_id.val, core->cpu_id, mda, apic->log_dst.dst_log_id);
+ return 1;
+ } else {
+ PrintDebug("apic %u core %u: rejecting flat IRQ (mda 0x%x != log_dst 0x%x)\n",
+ apic->lapic_id.val, core->cpu_id, mda, apic->log_dst.dst_log_id);
+ return 0;
+ }
+}
+static int apic_should_deliver_cluster(struct guest_info * core, uint8_t mda, void * private_data)
+{
+ struct apic_state * apic = (struct apic_state *)private_data;
+
+ if (mda==0xff || // broadcast or
+ ( ((mda & 0xf0) == (apic->log_dst.dst_log_id & 0xf0)) && // (I am in the cluster and
+ ((mda & 0x0f) & (apic->log_dst.dst_log_id & 0x0f)) ) ) { // I am in the set)
+ PrintDebug("apic %u core %u: accepting clustered IRQ (mda 0x%x == log_dst 0x%x)\n",
+ apic->lapic_id.val, core->cpu_id, mda, apic->log_dst.dst_log_id);
+
+ return 1;
+ } else {
+ PrintDebug("apic %u core %u: rejecting clustered IRQ (mda 0x%x != log_dst 0x%x)\n",
+ apic->lapic_id.val, core->cpu_id, mda, apic->log_dst.dst_log_id);
+ return 0;
+ }
+}
+
+static int apic_should_deliver(struct guest_info * core, uint8_t mda, void *private_data)
+{
+ struct apic_state * apic = (struct apic_state *)private_data;
+ if (apic->dst_fmt.model == 0xf) {
+ return apic_should_deliver_cluster(core, mda, private_data);
+ } else if (apic->dst_fmt.model == 0x0) {
+ return apic_should_deliver_flat(core, mda, private_data);
+ } else {
+ PrintError("apic %u core %u: invalid destination format register value 0x%x for logical mode delivery.\n", apic->lapic_id.val, core->cpu_id, apic->dst_fmt.model);
+ return 0;
+ }
+}
static struct v3_icc_ops icc_ops = {
.raise_intr = apic_raise_intr,
+ .should_deliver = apic_should_deliver,
};
-
-
static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
PrintDebug("apic: creating an APIC for each core\n");
char * dev_id = v3_cfg_val(cfg, "ID");