📄 io_apic_64.c
字号:
break; } case 3: /* low active */ { polarity = 1; break; } default: /* invalid */ { printk(KERN_WARNING "broken BIOS!!\n"); polarity = 1; break; } } return polarity;}static int MPBIOS_trigger(int idx){ int bus = mp_irqs[idx].mpc_srcbus; int trigger; /* * Determine IRQ trigger mode (edge or level sensitive): */ switch ((mp_irqs[idx].mpc_irqflag>>2) & 3) { case 0: /* conforms, ie. bus-type dependent */ if (test_bit(bus, mp_bus_not_pci)) trigger = default_ISA_trigger(idx); else trigger = default_PCI_trigger(idx); break; case 1: /* edge */ { trigger = 0; break; } case 2: /* reserved */ { printk(KERN_WARNING "broken BIOS!!\n"); trigger = 1; break; } case 3: /* level */ { trigger = 1; break; } default: /* invalid */ { printk(KERN_WARNING "broken BIOS!!\n"); trigger = 0; break; } } return trigger;}static inline int irq_polarity(int idx){ return MPBIOS_polarity(idx);}static inline int irq_trigger(int idx){ return MPBIOS_trigger(idx);}static int pin_2_irq(int idx, int apic, int pin){ int irq, i; int bus = mp_irqs[idx].mpc_srcbus; /* * Debugging check, we are in big trouble if this message pops up! */ if (mp_irqs[idx].mpc_dstirq != pin) printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n"); if (test_bit(bus, mp_bus_not_pci)) { irq = mp_irqs[idx].mpc_srcbusirq; } else { /* * PCI IRQs are mapped in order */ i = irq = 0; while (i < apic) irq += nr_ioapic_registers[i++]; irq += pin; } BUG_ON(irq >= NR_IRQS); return irq;}static int __assign_irq_vector(int irq, cpumask_t mask){ /* * NOTE! The local APIC isn't very good at handling * multiple interrupts at the same interrupt level. * As the interrupt level is determined by taking the * vector number and shifting that right by 4, we * want to spread these out a bit so that they don't * all fall in the same interrupt level. * * Also, we've got to be careful not to trash gate * 0x80, because int 0x80 is hm, kind of importantish. ;) */ static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0; unsigned int old_vector; int cpu; struct irq_cfg *cfg; BUG_ON((unsigned)irq >= NR_IRQS); cfg = &irq_cfg[irq]; /* Only try and allocate irqs on cpus that are present */ cpus_and(mask, mask, cpu_online_map); if ((cfg->move_in_progress) || cfg->move_cleanup_count) return -EBUSY; old_vector = cfg->vector; if (old_vector) { cpumask_t tmp; cpus_and(tmp, cfg->domain, mask); if (!cpus_empty(tmp)) return 0; } for_each_cpu_mask(cpu, mask) { cpumask_t domain, new_mask; int new_cpu; int vector, offset; domain = vector_allocation_domain(cpu); cpus_and(new_mask, domain, cpu_online_map); vector = current_vector; offset = current_offset;next: vector += 8; if (vector >= FIRST_SYSTEM_VECTOR) { /* If we run out of vectors on large boxen, must share them. */ offset = (offset + 1) % 8; vector = FIRST_DEVICE_VECTOR + offset; } if (unlikely(current_vector == vector)) continue; if (vector == IA32_SYSCALL_VECTOR) goto next; for_each_cpu_mask(new_cpu, new_mask) if (per_cpu(vector_irq, new_cpu)[vector] != -1) goto next; /* Found one! */ current_vector = vector; current_offset = offset; if (old_vector) { cfg->move_in_progress = 1; cfg->old_domain = cfg->domain; } for_each_cpu_mask(new_cpu, new_mask) per_cpu(vector_irq, new_cpu)[vector] = irq; cfg->vector = vector; cfg->domain = domain; return 0; } return -ENOSPC;}static int assign_irq_vector(int irq, cpumask_t mask){ int err; unsigned long flags; spin_lock_irqsave(&vector_lock, flags); err = __assign_irq_vector(irq, mask); spin_unlock_irqrestore(&vector_lock, flags); return err;}static void __clear_irq_vector(int irq){ struct irq_cfg *cfg; cpumask_t mask; int cpu, vector; BUG_ON((unsigned)irq >= NR_IRQS); cfg = &irq_cfg[irq]; BUG_ON(!cfg->vector); vector = cfg->vector; cpus_and(mask, cfg->domain, cpu_online_map); for_each_cpu_mask(cpu, mask) per_cpu(vector_irq, cpu)[vector] = -1; cfg->vector = 0; cfg->domain = CPU_MASK_NONE;}void __setup_vector_irq(int cpu){ /* Initialize vector_irq on a new cpu */ /* This function must be called with vector_lock held */ int irq, vector; /* Mark the inuse vectors */ for (irq = 0; irq < NR_IRQS; ++irq) { if (!cpu_isset(cpu, irq_cfg[irq].domain)) continue; vector = irq_cfg[irq].vector; per_cpu(vector_irq, cpu)[vector] = irq; } /* Mark the free vectors */ for (vector = 0; vector < NR_VECTORS; ++vector) { irq = per_cpu(vector_irq, cpu)[vector]; if (irq < 0) continue; if (!cpu_isset(cpu, irq_cfg[irq].domain)) per_cpu(vector_irq, cpu)[vector] = -1; }}static struct irq_chip ioapic_chip;static void ioapic_register_intr(int irq, unsigned long trigger){ if (trigger) { irq_desc[irq].status |= IRQ_LEVEL; set_irq_chip_and_handler_name(irq, &ioapic_chip, handle_fasteoi_irq, "fasteoi"); } else { irq_desc[irq].status &= ~IRQ_LEVEL; set_irq_chip_and_handler_name(irq, &ioapic_chip, handle_edge_irq, "edge"); }}static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, int trigger, int polarity){ struct irq_cfg *cfg = irq_cfg + irq; struct IO_APIC_route_entry entry; cpumask_t mask; if (!IO_APIC_IRQ(irq)) return; mask = TARGET_CPUS; if (assign_irq_vector(irq, mask)) return; cpus_and(mask, cfg->domain, mask); apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " "IRQ %d Mode:%i Active:%i)\n", apic, mp_ioapics[apic].mpc_apicid, pin, cfg->vector, irq, trigger, polarity); /* * add it to the IO-APIC irq-routing table: */ memset(&entry,0,sizeof(entry)); entry.delivery_mode = INT_DELIVERY_MODE; entry.dest_mode = INT_DEST_MODE; entry.dest = cpu_mask_to_apicid(mask); entry.mask = 0; /* enable IRQ */ entry.trigger = trigger; entry.polarity = polarity; entry.vector = cfg->vector; /* Mask level triggered irqs. * Use IRQ_DELAYED_DISABLE for edge triggered irqs. */ if (trigger) entry.mask = 1; ioapic_register_intr(irq, trigger); if (irq < 16) disable_8259A_irq(irq); ioapic_write_entry(apic, pin, entry);}static void __init setup_IO_APIC_irqs(void){ int apic, pin, idx, irq, first_notcon = 1; apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); for (apic = 0; apic < nr_ioapics; apic++) { for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { idx = find_irq_entry(apic,pin,mp_INT); if (idx == -1) { if (first_notcon) { apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin); first_notcon = 0; } else apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin); continue; } if (!first_notcon) { apic_printk(APIC_VERBOSE, " not connected.\n"); first_notcon = 1; } irq = pin_2_irq(idx, apic, pin); add_pin_to_irq(irq, apic, pin); setup_IO_APIC_irq(apic, pin, irq, irq_trigger(idx), irq_polarity(idx)); } } if (!first_notcon) apic_printk(APIC_VERBOSE, " not connected.\n");}/* * Set up the 8259A-master output pin as broadcast to all * CPUs. */static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector){ struct IO_APIC_route_entry entry; unsigned long flags; memset(&entry,0,sizeof(entry)); disable_8259A_irq(0); /* mask LVT0 */ apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); /* * We use logical delivery to get the timer IRQ * to the first CPU. */ entry.dest_mode = INT_DEST_MODE; entry.mask = 0; /* unmask IRQ now */ entry.dest = cpu_mask_to_apicid(TARGET_CPUS); entry.delivery_mode = INT_DELIVERY_MODE; entry.polarity = 0; entry.trigger = 0; entry.vector = vector; /* * The timer IRQ doesn't have to know that behind the * scene we have a 8259A-master in AEOI mode ... */ set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge"); /* * Add it to the IO-APIC irq-routing table: */ spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1)); io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0)); spin_unlock_irqrestore(&ioapic_lock, flags); enable_8259A_irq(0);}void __apicdebuginit print_IO_APIC(void){ int apic, i; union IO_APIC_reg_00 reg_00; union IO_APIC_reg_01 reg_01; union IO_APIC_reg_02 reg_02; unsigned long flags; if (apic_verbosity == APIC_QUIET) return; printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); for (i = 0; i < nr_ioapics; i++) printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]); /* * We are a bit conservative about what we expect. We have to * know about every hardware change ASAP. */ printk(KERN_INFO "testing the IO APIC.......................\n"); for (apic = 0; apic < nr_ioapics; apic++) { spin_lock_irqsave(&ioapic_lock, flags); reg_00.raw = io_apic_read(apic, 0); reg_01.raw = io_apic_read(apic, 1); if (reg_01.bits.version >= 0x10) reg_02.raw = io_apic_read(apic, 2); spin_unlock_irqrestore(&ioapic_lock, flags); printk("\n"); printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid); printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)®_01); printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.bits.entries); printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.bits.PRQ); printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.bits.version); if (reg_01.bits.version >= 0x10) { printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw); printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.bits.arbitration); } printk(KERN_DEBUG ".... IRQ redirection table:\n"); printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol" " Stat Dmod Deli Vect: \n"); for (i = 0; i <= reg_01.bits.entries; i++) { struct IO_APIC_route_entry entry; entry = ioapic_read_entry(apic, i); printk(KERN_DEBUG " %02x %03X ", i, entry.dest ); printk("%1d %1d %1d %1d %1d %1d %1d %02X\n", entry.mask, entry.trigger, entry.irr, entry.polarity, entry.delivery_status, entry.dest_mode, entry.delivery_mode, entry.vector ); } } printk(KERN_DEBUG "IRQ to pin mappings:\n"); for (i = 0; i < NR_IRQS; i++) { struct irq_pin_list *entry = irq_2_pin + i; if (entry->pin < 0) continue; printk(KERN_DEBUG "IRQ%d ", i); for (;;) { printk("-> %d:%d", entry->apic, entry->pin); if (!entry->next) break; entry = irq_2_pin + entry->next; } printk("\n"); } printk(KERN_INFO ".................................... done.\n"); return;}#if 0static __apicdebuginit void print_APIC_bitfield (int base){ unsigned int v; int i, j; if (apic_verbosity == APIC_QUIET) return; printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG); for (i = 0; i < 8; i++) { v = apic_read(base + i*0x10); for (j = 0; j < 32; j++) { if (v & (1<<j)) printk("1"); else printk("0"); } printk("\n"); }}void __apicdebuginit print_local_APIC(void * dummy){ unsigned int v, ver, maxlvt; if (apic_verbosity == APIC_QUIET) return; printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", smp_processor_id(), hard_smp_processor_id()); v = apic_read(APIC_ID); printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(v)); v = apic_read(APIC_LVR); printk(KERN_INFO "... APIC VERSION: %08x\n", v); ver = GET_APIC_VERSION(v); maxlvt = get_maxlvt(); v = apic_read(APIC_TASKPRI); printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK); v = apic_read(APIC_ARBPRI); printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v, v & APIC_ARBPRI_MASK); v = apic_read(APIC_PROCPRI); printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v); v = apic_read(APIC_EOI); printk(KERN_DEBUG "... APIC EOI: %08x\n", v); v = apic_read(APIC_RRR); printk(KERN_DEBUG "... APIC RRR: %08x\n", v); v = apic_read(APIC_LDR); printk(KERN_DEBUG "... APIC LDR: %08x\n", v); v = apic_read(APIC_DFR); printk(KERN_DEBUG "... APIC DFR: %08x\n", v); v = apic_read(APIC_SPIV); printk(KERN_DEBUG "... APIC SPIV: %08x\n", v); printk(KERN_DEBUG "... APIC ISR field:\n"); print_APIC_bitfield(APIC_ISR); printk(KERN_DEBUG "... APIC TMR field:\n"); print_APIC_bitfield(APIC_TMR); printk(KERN_DEBUG "... APIC IRR field:\n"); print_APIC_bitfield(APIC_IRR); v = apic_read(APIC_ESR); printk(KERN_DEBUG "... APIC ESR: %08x\n", v); v = apic_read(APIC_ICR); printk(KERN_DEBUG "... APIC ICR: %08x\n", v); v = apic_read(APIC_ICR2); printk(KERN_DEBUG "... APIC ICR2: %08x\n", v); v = apic_read(APIC_LVTT); printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); if (maxlvt > 3) { /* PC is LVT#4. */ v = apic_read(APIC_LVTPC); printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v); } v = apic_read(APIC_LVT0); printk(KERN_DEBUG "... APIC LVT0: %08x\n", v); v = apic_read(APIC_LVT1); printk(KERN_DEBUG "... APIC LVT1: %08x\n", v); if (maxlvt > 2) { /* ERR is LVT#3. */ v = apic_read(APIC_LVTERR); printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v); } v = apic_read(APIC_TMICT); printk(KERN_DEBUG "... APIC TMICT: %08x\n", v); v = apic_read(APIC_TMCCT); printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v); v = apic_read(APIC_TDCR); printk(KERN_DEBUG "... APIC TDCR: %08x\n", v); printk("\n");}void print_all_local_APICs (void){ on_each_cpu(print_local_APIC, NULL, 1, 1);}void __apicdebuginit print_PIC(void){ unsigned int v; unsigned long flags; if (apic_verbosity == APIC_QUIET) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -