Gabe Black wrote: > I'm trying to figure out why the kernel isn't unmasking an IRQ it's > trying to wait for, and it would really help if I could get a source and > disassembly listing from objdump. I've tried it with the kernel I've > been running, but for some reason it doesn't include any source lines. > If somebody knows how to get this to work please let me know. > > Gabe > _______________________________________________ > m5-dev mailing list > m5-dev@m5sim.org > http://m5sim.org/mailman/listinfo/m5-dev > Ok, I figured out what line the problem is on. It's line 675 of arch/x86_64/kernel/io_apic.c in function __assign_irq_vector. It looks like it's comparing the mask of processors that could accept the interrupt (I think) with the "domain" member of the irq configuration. I don't know what that "domain" is or why it's set. It also only seems to need to check the domain if old_vector is set to something, so I think what it's doing is checking if the irq already has a vector assigned to it, and if so then bailing out. Unfortunately, that means that it never unmasks the redirection table entry in the I/O APIC that would let the timer interrupt through, and then it waits for it until it dies. The interrupt wouldn't get through anyway because I haven't built that yet, but the interrupt never tries to get through because the APIC is set to mask it. Does anybody know what it's trying to do in that function and what that domain member is/is for? The function is below.
Once I get that figured out, I'll immediately be blocked by needing to figure out how the various APICs will communicate over the memory system, namely how the local APIC in the CPU will be exposed to the outside world. I'll also eventually need a better way of assigning APIC ids and figuring out what the system configuration looks like to install in the MP configuration table. Gabe 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; } _______________________________________________ m5-dev mailing list m5-dev@m5sim.org http://m5sim.org/mailman/listinfo/m5-dev