/* raise irq to CPU if necessary. must be called every time the active irq may change */ static int pic_update_irq(PDEVPIC pThis) { PicState *pics = &pThis->aPics[0]; int irq2, irq; /* first look at slave pic */ irq2 = pic_get_irq(&pics[1]); Log(("pic_update_irq irq2=%d\n", irq2)); if (irq2 >= 0) { /* if irq request by slave pic, signal master PIC */ pic_set_irq1(&pics[0], 2, 1); } else { /* If not, clear the IR on the master PIC. */ pic_set_irq1(&pics[0], 2, 0); } /* look at requested irq */ irq = pic_get_irq(&pics[0]); if (irq >= 0) { /* If irq 2 is pending on the master pic, then there must be one pending on the slave pic too! Otherwise we'll get * spurious slave interrupts in picGetInterrupt. */ if (irq != 2 || irq2 != -1) { #if defined(DEBUG_PIC) int i; for(i = 0; i < 2; i++) { Log(("pic%d: imr=%x irr=%x padd=%d\n", i, pics[i].imr, pics[i].irr, pics[i].priority_add)); } Log(("pic: cpu_interrupt\n")); #endif pThis->CTX_SUFF(pPicHlp)->pfnSetInterruptFF(pThis->CTX_SUFF(pDevIns)); } else { STAM_COUNTER_INC(&pThis->StatClearedActiveIRQ2); Log(("pic_update_irq: irq 2 is active, but no interrupt is pending on the slave pic!!\n")); /* Clear it here, so lower priority interrupts can still be dispatched. */ /* if this was the only pending irq, then we must clear the interrupt ff flag */ pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns)); /** @note Is this correct? */ pics[0].irr &= ~(1 << 2); /* Call ourselves again just in case other interrupts are pending */ return pic_update_irq(pThis); } } else { Log(("pic_update_irq: no interrupt is pending!!\n")); /* we must clear the interrupt ff flag */ pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns)); } return VINF_SUCCESS; }
int pic_read_irq(PicState2 *s) { int irq, irq2, intno; irq = pic_get_irq(&s->pics[0]); if (irq >= 0) { pic_intack(&s->pics[0], irq); #ifndef TARGET_IA64 if (time_drift_fix && irq == 0) { extern int64_t timer_acks, timer_ints_to_push; timer_acks++; if (timer_ints_to_push > 0) { timer_ints_to_push--; /* simulate an edge irq0, like the one generated by i8254 */ pic_set_irq1(&s->pics[0], 0, 0); pic_set_irq1(&s->pics[0], 0, 1); } } #endif if (irq == 2) { irq2 = pic_get_irq(&s->pics[1]); if (irq2 >= 0) { pic_intack(&s->pics[1], irq2); } else { /* spurious IRQ on slave controller */ irq2 = 7; } intno = s->pics[1].irq_base + irq2; #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY) irq = irq2 + 8; #endif } else { intno = s->pics[0].irq_base + irq; } } else { /* spurious IRQ on host controller */ irq = 7; intno = s->pics[0].irq_base + irq; } pic_update_irq(s); #ifdef DEBUG_IRQ_LATENCY printf("IRQ%d latency=%0.3fus\n", irq, (double)(qemu_get_clock(vm_clock) - irq_time[irq]) * 1000000.0 / get_ticks_per_sec()); #endif #if defined(DEBUG_PIC) printf("pic_interrupt: irq=%d\n", irq); #endif return intno; }
/* * raise irq to CPU if necessary. must be called every time the active * irq may change */ static void pic_update_irq(struct kvm_pic *s) { int irq2, irq; irq2 = pic_get_irq(&s->pics[1]); if (irq2 >= 0) { /* * if irq request by slave pic, signal master PIC */ pic_set_irq1(&s->pics[0], 2, 1); pic_set_irq1(&s->pics[0], 2, 0); } irq = pic_get_irq(&s->pics[0]); if (irq >= 0) s->irq_request(s->irq_request_opaque, 1); else s->irq_request(s->irq_request_opaque, 0); }
/* XXX: should not export it, but it is needed for an APIC kludge */ void pic_update_irq(PicState2 *s) { int irq2, irq; /* first look at slave pic */ irq2 = pic_get_irq(&s->pics[1]); if (irq2 >= 0) { /* if irq request by slave pic, signal master PIC */ pic_set_irq1(&s->pics[0], 2, 1); pic_set_irq1(&s->pics[0], 2, 0); } /* look at requested irq */ irq = pic_get_irq(&s->pics[0]); if (irq >= 0) { #if defined(DEBUG_PIC) { int i; for(i = 0; i < 2; i++) { printf("pic%d: imr=%x irr=%x padd=%d\n", i, s->pics[i].imr, s->pics[i].irr, s->pics[i].priority_add); } } printf("pic: cpu_interrupt\n"); #endif qemu_irq_raise(s->parent_irq); } /* all targets should do this rather than acking the IRQ in the cpu */ /* vova: at least on x86 targets this is required to avoid crashed when simulation speed is low (for example due to logging enabled */ //#if defined(TARGET_MIPS) || defined(TARGET_PPC) || defined(TARGET_ALPHA) else { qemu_irq_lower(s->parent_irq); } //#endif }
/* XXX: should not export it, but it is needed for an APIC kludge */ void pic_update_irq(PicState2 *s) { int irq2, irq; /* first look at slave pic */ irq2 = pic_get_irq(&s->pics[1]); if (irq2 >= 0) { /* if irq request by slave pic, signal master PIC */ pic_set_irq1(&s->pics[0], 2, 1); pic_set_irq1(&s->pics[0], 2, 0); } /* look at requested irq */ irq = pic_get_irq(&s->pics[0]); if (irq >= 0) { #if defined(DEBUG_PIC) { int i; for(i = 0; i < 2; i++) { printf("pic%d: imr=%x irr=%x padd=%d\n", i, s->pics[i].imr, s->pics[i].irr, s->pics[i].priority_add); } } printf("pic: cpu_interrupt\n"); #endif qemu_irq_raise(s->parent_irq); } /* all targets should do this rather than acking the IRQ in the cpu */ #if defined(TARGET_MIPS) || defined(TARGET_PPC) else { qemu_irq_lower(s->parent_irq); } #endif }