⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io_apic.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
        /*         * legacy devices should be connected to IO APIC #0         */        setup_ExtINT_IRQ0_pin(apic2, pin2, vector);        if (timer_irq_works()) {            printk("works.\n");            if (pin1 != -1)                replace_pin_at_irq(0, apic1, pin1, apic2, pin2);            else                add_pin_to_irq(0, apic2, pin2);            return;        }        /*         * Cleanup, just in case ...         */        clear_IO_APIC_pin(apic2, pin2);    }    printk(" failed.\n");    if (nmi_watchdog == NMI_IO_APIC) {        printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");        nmi_watchdog = 0;    }    printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");    disable_8259A_irq(0);    irq_desc[vector].handler = &lapic_irq_type;    apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */    enable_8259A_irq(0);    if (timer_irq_works()) {        printk(" works.\n");        return;    }    apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);    printk(" failed.\n");    printk(KERN_INFO "...trying to set up timer as ExtINT IRQ...");    /*timer_ack = 0;*/    init_8259A(0);    make_8259A_irq(0);    apic_write_around(APIC_LVT0, APIC_DM_EXTINT);    unlock_ExtINT_logic();    if (timer_irq_works()) {        printk(" works.\n");        return;    }    printk(" failed :(.\n");    panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "          "report.  Then try booting with the 'noapic' option");}/* * * IRQ's that are handled by the PIC in the MPS IOAPIC case. * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ. *   Linux doesn't really care, as it's not actually used *   for any interrupt handling anyway. */#define PIC_IRQS	(1 << PIC_CASCADE_IR)void __init setup_IO_APIC(void){    enable_IO_APIC();    if (acpi_ioapic)        io_apic_irqs = ~0;	/* all IRQs go through IOAPIC */    else        io_apic_irqs = ~PIC_IRQS;    printk("ENABLING IO-APIC IRQs\n");    printk(" -> Using %s ACK method\n", ioapic_ack_new ? "new" : "old");    /*     * Set up IO-APIC IRQ routing.     */    if (!acpi_ioapic)        setup_ioapic_ids_from_mpc();    sync_Arb_IDs();    setup_IO_APIC_irqs();    init_IO_APIC_traps();    check_timer();    print_IO_APIC();    register_keyhandler('z', print_IO_APIC_keyhandler, "print ioapic info");}struct IO_APIC_route_entry *ioapic_pm_state=NULL;void ioapic_pm_state_alloc(void){    int i, nr_entry = 0;    if (ioapic_pm_state != NULL)        return;    for (i = 0; i < nr_ioapics; i++)        nr_entry += nr_ioapic_registers[i];    ioapic_pm_state = _xmalloc(sizeof(struct IO_APIC_route_entry)*nr_entry,                               sizeof(struct IO_APIC_route_entry));}int ioapic_suspend(void){    struct IO_APIC_route_entry *entry;    unsigned long flags;    int apic,i;    ioapic_pm_state_alloc();    if (ioapic_pm_state == NULL) {        printk("Cannot suspend ioapic due to lack of memory\n");        return 1;    }    entry = ioapic_pm_state;    spin_lock_irqsave(&ioapic_lock, flags);    for (apic = 0; apic < nr_ioapics; apic++) {        for (i = 0; i < nr_ioapic_registers[apic]; i ++, entry ++ ) {            *(((int *)entry) + 1) = io_apic_read(apic, 0x11 + 2 * i);            *(((int *)entry) + 0) = io_apic_read(apic, 0x10 + 2 * i);        }    }    spin_unlock_irqrestore(&ioapic_lock, flags);    return 0;}int ioapic_resume(void){    struct IO_APIC_route_entry *entry;    unsigned long flags;    union IO_APIC_reg_00 reg_00;    int i,apic;        if (ioapic_pm_state == NULL){        printk("Cannot resume ioapic due to lack of memory\n");        return 1;    }        entry = ioapic_pm_state;    spin_lock_irqsave(&ioapic_lock, flags);    for (apic = 0; apic < nr_ioapics; apic++){        reg_00.raw = io_apic_read(apic, 0);        if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid) {            reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;            io_apic_write(apic, 0, reg_00.raw);        }        for (i = 0; i < nr_ioapic_registers[apic]; i++, entry++) {            io_apic_write(apic, 0x11+2*i, *(((int *)entry)+1));            io_apic_write(apic, 0x10+2*i, *(((int *)entry)+0));        }    }    spin_unlock_irqrestore(&ioapic_lock, flags);    return 0;}/* --------------------------------------------------------------------------                          ACPI-based IOAPIC Configuration   -------------------------------------------------------------------------- */#ifdef CONFIG_ACPI_BOOTint __init io_apic_get_unique_id (int ioapic, int apic_id){    union IO_APIC_reg_00 reg_00;    static physid_mask_t apic_id_map = PHYSID_MASK_NONE;    physid_mask_t tmp;    unsigned long flags;    int i = 0;    /*     * The P4 platform supports up to 256 APIC IDs on two separate APIC      * buses (one for LAPICs, one for IOAPICs), where predecessors only      * supports up to 16 on one shared APIC bus.     *      * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full     *      advantage of new APIC bus architecture.     */    if (physids_empty(apic_id_map))        apic_id_map = ioapic_phys_id_map(phys_cpu_present_map);    spin_lock_irqsave(&ioapic_lock, flags);    reg_00.raw = io_apic_read(ioapic, 0);    spin_unlock_irqrestore(&ioapic_lock, flags);    if (apic_id >= get_physical_broadcast()) {        printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "               "%d\n", ioapic, apic_id, reg_00.bits.ID);        apic_id = reg_00.bits.ID;    }    /*     * Every APIC in a system must have a unique ID or we get lots of nice      * 'stuck on smp_invalidate_needed IPI wait' messages.     */    if (check_apicid_used(apic_id_map, apic_id)) {        for (i = 0; i < get_physical_broadcast(); i++) {            if (!check_apicid_used(apic_id_map, i))                break;        }        if (i == get_physical_broadcast())            panic("Max apic_id exceeded!\n");        printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "               "trying %d\n", ioapic, apic_id, i);        apic_id = i;    }     tmp = apicid_to_cpu_present(apic_id);    physids_or(apic_id_map, apic_id_map, tmp);    if (reg_00.bits.ID != apic_id) {        reg_00.bits.ID = apic_id;        spin_lock_irqsave(&ioapic_lock, flags);        io_apic_write(ioapic, 0, reg_00.raw);        reg_00.raw = io_apic_read(ioapic, 0);        spin_unlock_irqrestore(&ioapic_lock, flags);        /* Sanity check */        if (reg_00.bits.ID != apic_id) {            printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);            return -1;        }    }    apic_printk(APIC_VERBOSE, KERN_INFO                "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);    return apic_id;}int __init io_apic_get_version (int ioapic){    union IO_APIC_reg_01	reg_01;    unsigned long flags;    spin_lock_irqsave(&ioapic_lock, flags);    reg_01.raw = io_apic_read(ioapic, 1);    spin_unlock_irqrestore(&ioapic_lock, flags);    return reg_01.bits.version;}int __init io_apic_get_redir_entries (int ioapic){    union IO_APIC_reg_01	reg_01;    unsigned long flags;    spin_lock_irqsave(&ioapic_lock, flags);    reg_01.raw = io_apic_read(ioapic, 1);    spin_unlock_irqrestore(&ioapic_lock, flags);    return reg_01.bits.entries;}int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low){    struct IO_APIC_route_entry entry;    unsigned long flags;    if (!IO_APIC_IRQ(irq)) {        printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",               ioapic);        return -EINVAL;    }    /*     * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.     * Note that we mask (disable) IRQs now -- these get enabled when the     * corresponding device driver registers for this IRQ.     */    memset(&entry,0,sizeof(entry));    entry.delivery_mode = INT_DELIVERY_MODE;    entry.dest_mode = INT_DEST_MODE;    entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);    entry.trigger = edge_level;    entry.polarity = active_high_low;    entry.mask  = 1;    /*     * IRQs < 16 are already in the irq_2_pin[] map     */    if (irq >= 16)        add_pin_to_irq(irq, ioapic, pin);    entry.vector = assign_irq_vector(irq);    apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry "		"(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic,		mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,		edge_level, active_high_low);    ioapic_register_intr(irq, entry.vector, edge_level);    if (!ioapic && (irq < 16))        disable_8259A_irq(irq);    spin_lock_irqsave(&ioapic_lock, flags);    io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));    io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));    set_native_irq_info(entry.vector, TARGET_CPUS);    spin_unlock_irqrestore(&ioapic_lock, flags);    return 0;}#endif /*CONFIG_ACPI_BOOT*/static int ioapic_physbase_to_id(unsigned long physbase){    int apic;    for ( apic = 0; apic < nr_ioapics; apic++ )        if ( mp_ioapics[apic].mpc_apicaddr == physbase )            return apic;    return -EINVAL;}int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval){    int apic;    unsigned long flags;    if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )        return apic;    spin_lock_irqsave(&ioapic_lock, flags);    *pval = io_apic_read(apic, reg);    spin_unlock_irqrestore(&ioapic_lock, flags);    return 0;}#define WARN_BOGUS_WRITE(f, a...)                                       \    dprintk(XENLOG_INFO, "\n%s: "                                        \            "apic=%d, pin=%d, old_irq=%d, new_irq=%d\n"                 \            "%s: old_entry=%08x, new_entry=%08x\n"                      \            "%s: " f, __FUNCTION__, apic, pin, old_irq, new_irq,        \            __FUNCTION__, *(u32 *)&old_rte, *(u32 *)&new_rte,           \            __FUNCTION__ , ##a )int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val){    int apic, pin, old_irq = -1, new_irq = -1;    struct IO_APIC_route_entry old_rte = { 0 }, new_rte = { 0 };    unsigned long flags;    if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )        return apic;    /* Only write to the first half of a route entry. */    if ( (reg < 0x10) || (reg & 1) )        return 0;        pin = (reg - 0x10) >> 1;    /* Write first half from guest; second half is target info. */    *(u32 *)&new_rte = val;    new_rte.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);    /*     * What about weird destination types?     *  SMI:    Ignore? Ought to be set up by the BIOS.     *  NMI:    Ignore? Watchdog functionality is Xen's concern.     *  INIT:   Definitely ignore: probably a guest OS bug.     *  ExtINT: Ignore? Linux only asserts this at start of day.     * For now, print a message and return an error. We can fix up on demand.     */    if ( new_rte.delivery_mode > dest_LowestPrio )    {        printk("ERROR: Attempt to write weird IOAPIC destination mode!\n");        printk("       APIC=%d/%d, lo-reg=%x\n", apic, pin, val);        return -EINVAL;    }    /*     * The guest does not know physical APIC arrangement (flat vs. cluster).     * Apply genapic conventions for this platform.     */    new_rte.delivery_mode = INT_DELIVERY_MODE;    new_rte.dest_mode     = INT_DEST_MODE;    spin_lock_irqsave(&ioapic_lock, flags);    /* Read first (interesting) half of current routing entry. */    *(u32 *)&old_rte = io_apic_read(apic, 0x10 + 2 * pin);    /* No change to the first half of the routing entry? Bail quietly. */    if ( *(u32 *)&old_rte == *(u32 *)&new_rte )    {        spin_unlock_irqrestore(&ioapic_lock, flags);        return 0;    }    /* Special delivery modes (SMI,NMI,INIT,ExtInt) should have no vector.  */    if ( (old_rte.delivery_mode > dest_LowestPrio) && (old_rte.vector != 0) )    {        WARN_BOGUS_WRITE("Special delivery mode %d with non-zero vector "                         "%02x\n", old_rte.delivery_mode, old_rte.vector);        /* Nobble the vector here as it does not relate to a valid irq. */        old_rte.vector = 0;    }    if ( old_rte.vector >= FIRST_DYNAMIC_VECTOR )        old_irq = vector_irq[old_rte.vector];    if ( new_rte.vector >= FIRST_DYNAMIC_VECTOR )        new_irq = vector_irq[new_rte.vector];    if ( (old_irq != new_irq) && (old_irq != -1) && IO_APIC_IRQ(old_irq) )    {        if ( irq_desc[IO_APIC_VECTOR(old_irq)].action )        {            WARN_BOGUS_WRITE("Attempt to remove IO-APIC pin of in-use IRQ!\n");            spin_unlock_irqrestore(&ioapic_lock, flags);            return 0;        }        remove_pin_at_irq(old_irq, apic, pin);    }    if ( (new_irq != -1) && IO_APIC_IRQ(new_irq) )    {        if ( irq_desc[IO_APIC_VECTOR(new_irq)].action )        {            WARN_BOGUS_WRITE("Attempt to %s IO-APIC pin for in-use IRQ!\n",                             (old_irq != new_irq) ? "add" : "modify");    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -