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
> [email protected]
> 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
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev