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

📄 io_apic.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
{    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");            spin_unlock_irqrestore(&ioapic_lock, flags);            return 0;        }                /* Set the correct irq-handling type. */        irq_desc[IO_APIC_VECTOR(new_irq)].handler = new_rte.trigger ?             &ioapic_level_type: &ioapic_edge_type;                if ( old_irq != new_irq )            add_pin_to_irq(new_irq, apic, pin);        /* Mask iff level triggered. */        new_rte.mask = new_rte.trigger;    }    else if ( !new_rte.mask )    {        /* This pin leads nowhere but the guest has not masked it. */        WARN_BOGUS_WRITE("Installing bogus unmasked IO-APIC entry!\n");        new_rte.mask = 1;    }    io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&new_rte) + 0));    io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&new_rte) + 1));    spin_unlock_irqrestore(&ioapic_lock, flags);    return 0;}void dump_ioapic_irq_info(void){    struct irq_pin_list *entry;    struct IO_APIC_route_entry rte;    unsigned int irq, pin, printed = 0;    unsigned long flags;    for ( irq = 0; irq < NR_IRQS; irq++ )    {        entry = &irq_2_pin[irq];        if ( entry->pin == -1 )            continue;        if ( !printed++ )            printk("IO-APIC interrupt information:\n");        printk("    IRQ%3d Vec%3d:\n", irq, irq_to_vector(irq));        for ( ; ; )        {            pin = entry->pin;            printk("      Apic 0x%02x, Pin %2d: ", entry->apic, pin);            spin_lock_irqsave(&ioapic_lock, flags);            *(((int *)&rte) + 0) = io_apic_read(entry->apic, 0x10 + 2 * pin);            *(((int *)&rte) + 1) = io_apic_read(entry->apic, 0x11 + 2 * pin);            spin_unlock_irqrestore(&ioapic_lock, flags);            printk("vector=%u, delivery_mode=%u, dest_mode=%s, "                   "delivery_status=%d

⌨️ 快捷键说明

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