#include <palacios/vmm_types.h>
#include <palacios/vmm.h>
#include <palacios/vmm_dev_mgr.h>
+#include <palacios/vm_guest.h>
-#ifndef CONFIG_DEBUG_PIC
+#ifndef V3_CONFIG_DEBUG_PIC
#undef PrintDebug
#define PrintDebug(fmt, args...)
#endif
struct pic_internal {
- uchar_t master_irr;
- uchar_t slave_irr;
+ uint8_t master_irr;
+ uint8_t slave_irr;
- uchar_t master_isr;
- uchar_t slave_isr;
+ uint8_t master_isr;
+ uint8_t slave_isr;
- uchar_t master_elcr;
- uchar_t slave_elcr;
- uchar_t master_elcr_mask;
- uchar_t slave_elcr_mask;
+ uint8_t master_elcr;
+ uint8_t slave_elcr;
+ uint8_t master_elcr_mask;
+ uint8_t slave_elcr_mask;
- uchar_t master_icw1;
- uchar_t master_icw2;
- uchar_t master_icw3;
- uchar_t master_icw4;
+ uint8_t master_icw1;
+ uint8_t master_icw2;
+ uint8_t master_icw3;
+ uint8_t master_icw4;
- uchar_t slave_icw1;
- uchar_t slave_icw2;
- uchar_t slave_icw3;
- uchar_t slave_icw4;
+ uint8_t slave_icw1;
+ uint8_t slave_icw2;
+ uint8_t slave_icw3;
+ uint8_t slave_icw4;
- uchar_t master_imr;
- uchar_t slave_imr;
- uchar_t master_ocw2;
- uchar_t master_ocw3;
- uchar_t slave_ocw2;
- uchar_t slave_ocw3;
+ uint8_t master_imr;
+ uint8_t slave_imr;
+ uint8_t master_ocw2;
+ uint8_t master_ocw3;
+ uint8_t slave_ocw2;
+ uint8_t slave_ocw3;
pic_state_t master_state;
pic_state_t slave_state;
+
+ struct guest_info * core;
+
+ struct {
+ int (*ack)(struct guest_info * core, uint32_t irq, void * private_data);
+ void * private_data;
+ } irq_ack_cbs[15];
+
+
+ void * router_handle;
+ void * controller_handle;
};
}
-static int pic_raise_intr(struct v3_vm_info * vm, void * private_data, int irq) {
+static int pic_raise_intr(struct v3_vm_info * vm, void * private_data, struct v3_irq * irq) {
struct pic_internal * state = (struct pic_internal*)private_data;
+ uint8_t irq_num = irq->irq;
- if (irq == 2) {
- irq = 9;
- state->master_irr |= 0x04; // PAD
+ if (irq_num == 2) {
+ irq_num = 9;
+ state->master_irr |= 0x04;
}
- PrintDebug("8259 PIC: Raising irq %d in the PIC\n", irq);
+ PrintDebug("8259 PIC: Raising irq %d in the PIC\n", irq_num);
- if (irq <= 7) {
- state->master_irr |= 0x01 << irq;
- } else if ((irq > 7) && (irq < 16)) {
- state->slave_irr |= 0x01 << (irq - 8); // PAD if -7 then irq 15=no irq
+ if (irq_num <= 7) {
+ state->master_irr |= 0x01 << irq_num;
+ } else if ((irq_num > 7) && (irq_num < 16)) {
+ state->slave_irr |= 0x01 << (irq_num - 8);
} else {
- PrintDebug("8259 PIC: Invalid IRQ raised (%d)\n", irq);
+ PrintDebug("8259 PIC: Invalid IRQ raised (%d)\n", irq_num);
return -1;
}
- v3_interrupt_cpu(vm, 0, 0);
+ state->irq_ack_cbs[irq_num].ack = irq->ack;
+ state->irq_ack_cbs[irq_num].private_data = irq->private_data;
+
+ if (V3_Get_CPU() != vm->cores[0].pcpu_id) {
+ // guest is running on another core, interrupt it to deliver irq
+ v3_interrupt_cpu(vm, 0, 0);
+ }
return 0;
}
-static int pic_lower_intr(struct v3_vm_info * vm, void * private_data, int irq) {
+static int pic_lower_intr(struct v3_vm_info * vm, void * private_data, struct v3_irq * irq) {
struct pic_internal * state = (struct pic_internal*)private_data;
+ uint8_t irq_num = irq->irq;
- PrintDebug("[pic_lower_intr] IRQ line %d now low\n", irq);
- if (irq <= 7) {
- state->master_irr &= ~(1 << irq);
+ PrintDebug("[pic_lower_intr] IRQ line %d now low\n", irq_num);
+ if (irq_num <= 7) {
+
+ state->master_irr &= ~(1 << irq_num);
if ((state->master_irr & ~(state->master_imr)) == 0) {
PrintDebug("\t\tFIXME: Master maybe should do sth\n");
}
- } else if ((irq > 7) && (irq < 16)) {
+ } else if ((irq_num > 7) && (irq_num < 16)) {
- state->slave_irr &= ~(1 << (irq - 8));
+ state->slave_irr &= ~(1 << (irq_num - 8));
if ((state->slave_irr & (~(state->slave_imr))) == 0) {
PrintDebug("\t\tFIXME: Slave maybe should do sth\n");
}
state->master_irr &= ~(0x1 << irq);
}
} else {
- PrintDebug("8259 PIC: (master) Ignoring begin_irq for %d since I don't own it\n",irq);
+ PrintDebug("8259 PIC: (master) Ignoring begin_irq for %d since I don't own it\n", irq);
}
} else {
state->slave_irr &= ~(0x1 << (irq - 8));
}
} else {
- PrintDebug("8259 PIC: (slave) Ignoring begin_irq for %d since I don't own it\n",irq);
+ PrintDebug("8259 PIC: (slave) Ignoring begin_irq for %d since I don't own it\n", irq);
}
-
}
+
+
return 0;
}
}
if ((state->master_ocw3 & 0x03) == 0x02) {
- *(uchar_t *)dst = state->master_irr;
+ *(uint8_t *)dst = state->master_irr;
} else if ((state->master_ocw3 & 0x03) == 0x03) {
- *(uchar_t *)dst = state->master_isr;
+ *(uint8_t *)dst = state->master_isr;
} else {
- *(uchar_t *)dst = 0;
+ *(uint8_t *)dst = 0;
}
return 1;
return -1;
}
- *(uchar_t *)dst = state->master_imr;
+ *(uint8_t *)dst = state->master_imr;
return 1;
}
if ((state->slave_ocw3 & 0x03) == 0x02) {
- *(uchar_t*)dst = state->slave_irr;
+ *(uint8_t*)dst = state->slave_irr;
} else if ((state->slave_ocw3 & 0x03) == 0x03) {
- *(uchar_t *)dst = state->slave_isr;
+ *(uint8_t *)dst = state->slave_isr;
} else {
- *(uchar_t *)dst = 0;
+ *(uint8_t *)dst = 0;
}
return 1;
return -1;
}
- *(uchar_t *)dst = state->slave_imr;
+ *(uint8_t *)dst = state->slave_imr;
return 1;
}
static int write_master_port1(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
struct pic_internal * state = (struct pic_internal *)priv_data;
- uchar_t cw = *(uchar_t *)src;
+ uint8_t cw = *(uint8_t *)src;
PrintDebug("8259 PIC: Write master port 1 with 0x%x\n",cw);
if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
// specific EOI;
state->master_isr &= ~(0x01 << cw2->level);
+
+
+ /*
+ // ack the irq if requested
+ if (state->irq_ack_cbs[irq].ack) {
+ state->irq_ack_cbs[irq].ack(info, irq, state->irq_ack_cbs[irq].private_data);
+ }
+ */
+
} else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
int i;
// Non-specific EOI
static int write_master_port2(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
struct pic_internal * state = (struct pic_internal *)priv_data;
- uchar_t cw = *(uchar_t *)src;
+ uint8_t cw = *(uint8_t *)src;
PrintDebug("8259 PIC: Write master port 2 with 0x%x\n",cw);
static int write_slave_port1(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
struct pic_internal * state = (struct pic_internal *)priv_data;
- uchar_t cw = *(uchar_t *)src;
+ uint8_t cw = *(uint8_t *)src;
PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
static int write_slave_port2(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
struct pic_internal * state = (struct pic_internal *)priv_data;
- uchar_t cw = *(uchar_t *)src;
+ uint8_t cw = *(uint8_t *)src;
PrintDebug("8259 PIC: Write slave port 2 with 0x%x\n",cw);
+static int pic_free(struct pic_internal * state) {
+ struct guest_info * core = state->core;
+ v3_remove_intr_controller(core, state->controller_handle);
+ v3_remove_intr_router(core->vm_info, state->router_handle);
+ V3_Free(state);
+ return 0;
+}
-static int pic_free(struct pic_internal * state) {
+#ifdef V3_CONFIG_CHECKPOINT
+static int pic_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct pic_internal * pic = (struct pic_internal *)private_data;
+
+ v3_chkpt_save_8(ctx, "MASTER_IRR", &(pic->master_irr));
+ v3_chkpt_save_8(ctx, "SLAVE_IRR", &(pic->slave_irr));
+
+ v3_chkpt_save_8(ctx, "MASTER_ISR", &(pic->master_isr));
+ v3_chkpt_save_8(ctx, "SLAVE_ISR", &(pic->slave_isr));
+ v3_chkpt_save_8(ctx, "MASTER_ELCR", &(pic->master_elcr));
+ v3_chkpt_save_8(ctx, "SLAVE_ELCR", &(pic->slave_elcr));
+ v3_chkpt_save_8(ctx, "MASTER_ELCR_MASK", &(pic->master_elcr_mask));
+ v3_chkpt_save_8(ctx, "SLAVE_ELCR_MASK", &(pic->slave_elcr_mask));
- // unregister intr_controller
- // unregister intr router
+ v3_chkpt_save_8(ctx, "MASTER_ICW1", &(pic->master_icw1));
+ v3_chkpt_save_8(ctx, "MASTER_ICW2", &(pic->master_icw2));
+ v3_chkpt_save_8(ctx, "MASTER_ICW3", &(pic->master_icw3));
+ v3_chkpt_save_8(ctx, "MASTER_ICW4", &(pic->master_icw4));
- V3_Free(state);
+
+ v3_chkpt_save_8(ctx, "SLAVE_ICW1", &(pic->slave_icw1));
+ v3_chkpt_save_8(ctx, "SLAVE_ICW2", &(pic->slave_icw2));
+ v3_chkpt_save_8(ctx, "SLAVE_ICW3", &(pic->slave_icw3));
+ v3_chkpt_save_8(ctx, "SLAVE_ICW4", &(pic->slave_icw4));
+
+
+ v3_chkpt_save_8(ctx, "MASTER_IMR", &(pic->master_imr));
+ v3_chkpt_save_8(ctx, "SLAVE_IMR", &(pic->slave_imr));
+ v3_chkpt_save_8(ctx, "MASTER_OCW2", &(pic->master_ocw2));
+ v3_chkpt_save_8(ctx, "MASTER_OCW3", &(pic->master_ocw3));
+ v3_chkpt_save_8(ctx, "SLAVE_OCW2", &(pic->slave_ocw2));
+ v3_chkpt_save_8(ctx, "SLAVE_OCW3", &(pic->slave_ocw3));
+
+ v3_chkpt_save_8(ctx, "MASTER_STATE", &(pic->master_state));
+ v3_chkpt_save_8(ctx, "SLAVE_STATE", &(pic->slave_state));
+
+
return 0;
+
}
+static int pic_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct pic_internal * pic = (struct pic_internal *)private_data;
+
+
+ v3_chkpt_load_8(ctx, "MASTER_IRR", &(pic->master_irr));
+ v3_chkpt_load_8(ctx, "SLAVE_IRR", &(pic->slave_irr));
+
+ v3_chkpt_load_8(ctx, "MASTER_ISR", &(pic->master_isr));
+ v3_chkpt_load_8(ctx, "SLAVE_ISR", &(pic->slave_isr));
+
+ v3_chkpt_load_8(ctx, "MASTER_ELCR", &(pic->master_elcr));
+ v3_chkpt_load_8(ctx, "SLAVE_ELCR", &(pic->slave_elcr));
+ v3_chkpt_load_8(ctx, "MASTER_ELCR_MASK", &(pic->master_elcr_mask));
+ v3_chkpt_load_8(ctx, "SLAVE_ELCR_MASK", &(pic->slave_elcr_mask));
+ v3_chkpt_load_8(ctx, "MASTER_ICW1", &(pic->master_icw1));
+ v3_chkpt_load_8(ctx, "MASTER_ICW2", &(pic->master_icw2));
+ v3_chkpt_load_8(ctx, "MASTER_ICW3", &(pic->master_icw3));
+ v3_chkpt_load_8(ctx, "MASTER_ICW4", &(pic->master_icw4));
+ v3_chkpt_load_8(ctx, "SLAVE_ICW1", &(pic->slave_icw1));
+ v3_chkpt_load_8(ctx, "SLAVE_ICW2", &(pic->slave_icw2));
+ v3_chkpt_load_8(ctx, "SLAVE_ICW3", &(pic->slave_icw3));
+ v3_chkpt_load_8(ctx, "SLAVE_ICW4", &(pic->slave_icw4));
+ v3_chkpt_load_8(ctx, "MASTER_IMR", &(pic->master_imr));
+ v3_chkpt_load_8(ctx, "SLAVE_IMR", &(pic->slave_imr));
+ v3_chkpt_load_8(ctx, "MASTER_OCW2", &(pic->master_ocw2));
+ v3_chkpt_load_8(ctx, "MASTER_OCW3", &(pic->master_ocw3));
+ v3_chkpt_load_8(ctx, "SLAVE_OCW2", &(pic->slave_ocw2));
+ v3_chkpt_load_8(ctx, "SLAVE_OCW3", &(pic->slave_ocw3));
+
+ v3_chkpt_load_8(ctx, "MASTER_STATE", &(pic->master_state));
+ v3_chkpt_load_8(ctx, "SLAVE_STATE", &(pic->slave_state));
+
+ return 0;
+}
+
+#endif
+
static struct v3_device_ops dev_ops = {
.free = (int (*)(void *))pic_free,
-
+#ifdef V3_CONFIG_CHECKPOINT
+ .save = pic_save,
+ .load = pic_load
+#endif
};
-#include <palacios/vm_guest.h>
+
static int pic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct pic_internal * state = NULL;
return -1;
}
+ state->core = core;
- v3_register_intr_controller(core, &intr_ops, state);
- v3_register_intr_router(vm, &router_ops, state);
+ state->controller_handle = v3_register_intr_controller(core, &intr_ops, state);
+ state->router_handle = v3_register_intr_router(vm, &router_ops, state);
state->master_irr = 0;
state->master_isr = 0;