irq.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 544 行 · 第 1/2 页
C
544 行
{ case HVMIRQ_callback_gsi: gsi = hvm_irq->callback_via.gsi = (uint8_t)via; if ( (gsi == 0) || (gsi >= ARRAY_SIZE(hvm_irq->gsi_assert_count)) ) hvm_irq->callback_via_type = HVMIRQ_callback_none; else if ( hvm_irq->callback_via_asserted && (hvm_irq->gsi_assert_count[gsi]++ == 0) ) { vioapic_irq_positive_edge(d, gsi); if ( gsi <= 15 ) vpic_irq_positive_edge(d, gsi); } break; case HVMIRQ_callback_pci_intx: pdev = hvm_irq->callback_via.pci.dev = (uint8_t)(via >> 11) & 31; pintx = hvm_irq->callback_via.pci.intx = (uint8_t)via & 3; if ( hvm_irq->callback_via_asserted ) __hvm_pci_intx_assert(d, pdev, pintx); break; default: break; } spin_unlock(&d->arch.hvm_domain.irq_lock); dprintk(XENLOG_G_INFO, "Dom%u callback via changed to ", d->domain_id); switch ( via_type ) { case HVMIRQ_callback_gsi: printk("GSI %u\n", gsi); break; case HVMIRQ_callback_pci_intx: printk("PCI INTx Dev 0x%02x Int%c\n", pdev, 'A' + pintx); break; default: printk("None\n"); break; }}struct hvm_intack hvm_vcpu_has_pending_irq(struct vcpu *v){ struct hvm_domain *plat = &v->domain->arch.hvm_domain; int vector; if ( unlikely(v->nmi_pending) ) return hvm_intack_nmi; if ( vlapic_accept_pic_intr(v) && plat->vpic[0].int_output ) return hvm_intack_pic(0); vector = vlapic_has_pending_irq(v); if ( vector != -1 ) return hvm_intack_lapic(vector); return hvm_intack_none;}struct hvm_intack hvm_vcpu_ack_pending_irq( struct vcpu *v, struct hvm_intack intack){ int vector; switch ( intack.source ) { case hvm_intsrc_nmi: if ( !test_and_clear_bool(v->nmi_pending) ) intack = hvm_intack_none; break; case hvm_intsrc_pic: ASSERT(v->vcpu_id == 0); if ( (vector = vpic_ack_pending_irq(v)) == -1 ) intack = hvm_intack_none; else intack.vector = (uint8_t)vector; break; case hvm_intsrc_lapic: if ( !vlapic_ack_pending_irq(v, intack.vector) ) intack = hvm_intack_none; break; default: intack = hvm_intack_none; break; } return intack;}int hvm_local_events_need_delivery(struct vcpu *v){ struct hvm_intack intack = hvm_vcpu_has_pending_irq(v); if ( likely(intack.source == hvm_intsrc_none) ) return 0; return !hvm_interrupt_blocked(v, intack);}#if 0 /* Keep for debugging */static void irq_dump(struct domain *d){ struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; int i; printk("PCI 0x%16.16"PRIx64"%16.16"PRIx64 " ISA 0x%8.8"PRIx32" ROUTE %u %u %u %u\n", hvm_irq->pci_intx.pad[0], hvm_irq->pci_intx.pad[1], (uint32_t) hvm_irq->isa_irq.pad[0], hvm_irq->pci_link.route[0], hvm_irq->pci_link.route[1], hvm_irq->pci_link.route[2], hvm_irq->pci_link.route[3]); for ( i = 0 ; i < VIOAPIC_NUM_PINS; i += 8 ) printk("GSI %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8 " %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8"\n", hvm_irq->gsi_assert_count[i+0], hvm_irq->gsi_assert_count[i+1], hvm_irq->gsi_assert_count[i+2], hvm_irq->gsi_assert_count[i+3], hvm_irq->gsi_assert_count[i+4], hvm_irq->gsi_assert_count[i+5], hvm_irq->gsi_assert_count[i+6], hvm_irq->gsi_assert_count[i+7]); printk("Link %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8" %2.2"PRIu8"\n", hvm_irq->pci_link_assert_count[0], hvm_irq->pci_link_assert_count[1], hvm_irq->pci_link_assert_count[2], hvm_irq->pci_link_assert_count[3]); printk("Callback via %i:0x%"PRIx32",%s asserted\n", hvm_irq->callback_via_type, hvm_irq->callback_via.gsi, hvm_irq->callback_via_asserted ? "" : " not");}#endifstatic int irq_save_pci(struct domain *d, hvm_domain_context_t *h){ struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; unsigned int asserted, pdev, pintx; int rc; spin_lock(&d->arch.hvm_domain.irq_lock); pdev = hvm_irq->callback_via.pci.dev; pintx = hvm_irq->callback_via.pci.intx; asserted = (hvm_irq->callback_via_asserted && (hvm_irq->callback_via_type == HVMIRQ_callback_pci_intx)); /* * Deassert virtual interrupt via PCI INTx line. The virtual interrupt * status is not save/restored, so the INTx line must be deasserted in * the restore context. */ if ( asserted ) __hvm_pci_intx_deassert(d, pdev, pintx); /* Save PCI IRQ lines */ rc = hvm_save_entry(PCI_IRQ, 0, h, &hvm_irq->pci_intx); if ( asserted ) __hvm_pci_intx_assert(d, pdev, pintx); spin_unlock(&d->arch.hvm_domain.irq_lock); return rc;}static int irq_save_isa(struct domain *d, hvm_domain_context_t *h){ struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; /* Save ISA IRQ lines */ return ( hvm_save_entry(ISA_IRQ, 0, h, &hvm_irq->isa_irq) );}static int irq_save_link(struct domain *d, hvm_domain_context_t *h){ struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; /* Save PCI-ISA link state */ return ( hvm_save_entry(PCI_LINK, 0, h, &hvm_irq->pci_link) );}static int irq_load_pci(struct domain *d, hvm_domain_context_t *h){ struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; int link, dev, intx, gsi; /* Load the PCI IRQ lines */ if ( hvm_load_entry(PCI_IRQ, h, &hvm_irq->pci_intx) != 0 ) return -EINVAL; /* Clear the PCI link assert counts */ for ( link = 0; link < 4; link++ ) hvm_irq->pci_link_assert_count[link] = 0; /* Clear the GSI link assert counts */ for ( gsi = 0; gsi < VIOAPIC_NUM_PINS; gsi++ ) hvm_irq->gsi_assert_count[gsi] = 0; /* Recalculate the counts from the IRQ line state */ for ( dev = 0; dev < 32; dev++ ) for ( intx = 0; intx < 4; intx++ ) if ( test_bit(dev*4 + intx, &hvm_irq->pci_intx.i) ) { /* Direct GSI assert */ gsi = hvm_pci_intx_gsi(dev, intx); hvm_irq->gsi_assert_count[gsi]++; /* PCI-ISA bridge assert */ link = hvm_pci_intx_link(dev, intx); hvm_irq->pci_link_assert_count[link]++; } return 0;}static int irq_load_isa(struct domain *d, hvm_domain_context_t *h){ struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; int irq; /* Load the ISA IRQ lines */ if ( hvm_load_entry(ISA_IRQ, h, &hvm_irq->isa_irq) != 0 ) return -EINVAL; /* Adjust the GSI assert counts for the ISA IRQ line state. * This relies on the PCI IRQ state being loaded first. */ for ( irq = 0; irq < 16; irq++ ) if ( test_bit(irq, &hvm_irq->isa_irq.i) ) hvm_irq->gsi_assert_count[hvm_isa_irq_to_gsi(irq)]++; return 0;}static int irq_load_link(struct domain *d, hvm_domain_context_t *h){ struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; int link, gsi; /* Load the PCI-ISA IRQ link routing table */ if ( hvm_load_entry(PCI_LINK, h, &hvm_irq->pci_link) != 0 ) return -EINVAL; /* Sanity check */ for ( link = 0; link < 4; link++ ) if ( hvm_irq->pci_link.route[link] > 15 ) { gdprintk(XENLOG_ERR, "HVM restore: PCI-ISA link %u out of range (%u)\n", link, hvm_irq->pci_link.route[link]); return -EINVAL; } /* Adjust the GSI assert counts for the link outputs. * This relies on the PCI and ISA IRQ state being loaded first */ for ( link = 0; link < 4; link++ ) { if ( hvm_irq->pci_link_assert_count[link] != 0 ) { gsi = hvm_irq->pci_link.route[link]; if ( gsi != 0 ) hvm_irq->gsi_assert_count[gsi]++; } } return 0;}HVM_REGISTER_SAVE_RESTORE(PCI_IRQ, irq_save_pci, irq_load_pci, 1, HVMSR_PER_DOM);HVM_REGISTER_SAVE_RESTORE(ISA_IRQ, irq_save_isa, irq_load_isa, 1, HVMSR_PER_DOM);HVM_REGISTER_SAVE_RESTORE(PCI_LINK, irq_save_link, irq_load_link, 1, HVMSR_PER_DOM);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?