From: Jack Lange Date: Sun, 18 Mar 2012 21:43:59 +0000 (-0400) Subject: added ackable interrupts X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=7e2270f01390b44dc99e28d56abb30bee18d1907;hp=68a5f03fab0737ce304261028a4517c49ea954c6;p=palacios.git added ackable interrupts --- diff --git a/palacios/include/palacios/vmm_intr.h b/palacios/include/palacios/vmm_intr.h index adf2aa4..de98185 100644 --- a/palacios/include/palacios/vmm_intr.h +++ b/palacios/include/palacios/vmm_intr.h @@ -35,6 +35,14 @@ struct v3_vm_info; struct v3_interrupt; +struct v3_irq { + uint32_t irq; + + int (*ack)(struct guest_info * core, uint32_t irq, void * private_data); + void * private_data; +}; + + struct v3_irq_hook { int (*handler)(struct v3_vm_info * vm, struct v3_interrupt * intr, void * priv_data); @@ -82,6 +90,12 @@ int v3_lower_virq(struct guest_info * info, int irq); int v3_raise_irq(struct v3_vm_info * vm, int irq); int v3_lower_irq(struct v3_vm_info * vm, int irq); +/* The irq structure is passed by value to avoid confusion and + * the possibility that people will dynamically allocate memory for it + */ +int v3_raise_acked_irq(struct v3_vm_info * vm, struct v3_irq irq); +int v3_lower_acked_irq(struct v3_vm_info * vm, struct v3_irq irq); + int v3_raise_swintr(struct guest_info * core, uint8_t vector); @@ -93,8 +107,8 @@ struct intr_ctrl_ops { }; struct intr_router_ops { - int (*raise_intr)(struct v3_vm_info * vm, void * private_data, int irq); - int (*lower_intr)(struct v3_vm_info * vm, void * private_data, int irq); + int (*raise_intr)(struct v3_vm_info * vm, void * private_data, struct v3_irq * irq); + int (*lower_intr)(struct v3_vm_info * vm, void * private_data, struct v3_irq * irq); }; void v3_clear_pending_intr(struct guest_info * core); diff --git a/palacios/src/devices/8259a.c b/palacios/src/devices/8259a.c index b383151..0d55349 100644 --- a/palacios/src/devices/8259a.c +++ b/palacios/src/devices/8259a.c @@ -197,46 +197,50 @@ static void DumpPICState(struct pic_internal *p) } -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; } -#ifdef V3_CONFIG_MULTITHREAD_OS - v3_interrupt_cpu(vm, 0, 0); -#endif + 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"); } diff --git a/palacios/src/devices/io_apic.c b/palacios/src/devices/io_apic.c index 0a6c04a..9d477de 100644 --- a/palacios/src/devices/io_apic.c +++ b/palacios/src/devices/io_apic.c @@ -263,11 +263,12 @@ static int ioapic_write(struct guest_info * core, addr_t guest_addr, void * src, } -static int ioapic_raise_irq(struct v3_vm_info * vm, void * private_data, int irq) { +static int ioapic_raise_irq(struct v3_vm_info * vm, void * private_data, struct v3_irq * irq) { struct io_apic_state * ioapic = (struct io_apic_state *)(private_data); struct redir_tbl_entry * irq_entry = NULL; + uint8_t irq_num = irq->irq; - if (irq == 0) { + if (irq_num == 0) { // IRQ 0 being raised, in the Palacios context, means the PIT // However, the convention is that it is the PIC that is connected // to PIN 0 of the IOAPIC and the PIT is connected to pin 2 @@ -275,15 +276,15 @@ static int ioapic_raise_irq(struct v3_vm_info * vm, void * private_data, int irq // the PIC may signal to the IOAPIC in a different path. // Yes, this is kind of hideous, but it is needed to have the // PIT correctly show up via the IOAPIC - irq = 2; + irq_num = 2; } - if (irq > 24) { + if (irq_num > 24) { PrintDebug("ioapic %u: IRQ out of range of IO APIC\n", ioapic->ioapic_id.id); return -1; } - irq_entry = &(ioapic->redir_tbl[irq]); + irq_entry = &(ioapic->redir_tbl[irq_num]); if (irq_entry->mask == 0) { struct v3_gen_ipi ipi; @@ -299,8 +300,8 @@ static int ioapic_raise_irq(struct v3_vm_info * vm, void * private_data, int irq ipi.dst = irq_entry->dst_field; ipi.dst_shorthand = 0; - ipi.ack = NULL; - ipi.private_data = NULL; + ipi.ack = irq->ack; + ipi.private_data = irq->private_data; PrintDebug("ioapic %u: IPI: vector 0x%x, mode 0x%x, logical 0x%x, trigger 0x%x, dst 0x%x, shorthand 0x%x\n", ioapic->ioapic_id.id, ipi.vector, ipi.mode, ipi.logical, ipi.trigger_mode, ipi.dst, ipi.dst_shorthand); @@ -315,7 +316,7 @@ static int ioapic_raise_irq(struct v3_vm_info * vm, void * private_data, int irq } /* I don't know if we can do anything here.... */ -static int ioapic_lower_irq(struct v3_vm_info * vm, void * private_data, int irq) { +static int ioapic_lower_irq(struct v3_vm_info * vm, void * private_data, struct v3_irq * irq) { return 0; } diff --git a/palacios/src/palacios/vmm_intr.c b/palacios/src/palacios/vmm_intr.c index 9010a4c..48e46ea 100644 --- a/palacios/src/palacios/vmm_intr.c +++ b/palacios/src/palacios/vmm_intr.c @@ -274,37 +274,59 @@ int v3_lower_virq(struct guest_info * info, int irq) { int v3_lower_irq(struct v3_vm_info * vm, int irq) { + struct v3_irq irq_state; + + irq_state.irq = irq; + irq_state.ack = NULL; + irq_state.private_data = NULL; + + return v3_lower_acked_irq(vm, irq_state); +} + +int v3_raise_irq(struct v3_vm_info * vm, int irq) { + struct v3_irq irq_state; + + irq_state.irq = irq; + irq_state.ack = NULL; + irq_state.private_data = NULL; + + return v3_raise_acked_irq(vm, irq_state); +} + + +int v3_raise_acked_irq(struct v3_vm_info * vm, struct v3_irq irq) { struct intr_router * router = NULL; struct v3_intr_routers * routers = &(vm->intr_routers); - // PrintDebug("[v3_lower_irq]\n"); + // PrintDebug("[v3_raise_irq (%d)]\n", irq); addr_t irq_state = v3_lock_irqsave(routers->irq_lock); list_for_each_entry(router, &(routers->router_list), router_node) { - router->router_ops->lower_intr(vm, router->priv_data, irq); + router->router_ops->raise_intr(vm, router->priv_data, &irq); } - + v3_unlock_irqrestore(routers->irq_lock, irq_state); return 0; } -int v3_raise_irq(struct v3_vm_info * vm, int irq) { + +int v3_lower_acked_irq(struct v3_vm_info * vm, struct v3_irq irq) { struct intr_router * router = NULL; struct v3_intr_routers * routers = &(vm->intr_routers); - // PrintDebug("[v3_raise_irq (%d)]\n", irq); + // PrintDebug("[v3_lower_irq]\n"); addr_t irq_state = v3_lock_irqsave(routers->irq_lock); list_for_each_entry(router, &(routers->router_list), router_node) { - router->router_ops->raise_intr(vm, router->priv_data, irq); + router->router_ops->lower_intr(vm, router->priv_data, &irq); } - + v3_unlock_irqrestore(routers->irq_lock, irq_state); return 0; -} +}