From ae15515d80559ff95b315e3342c3baa00b87be1c Mon Sep 17 00:00:00 2001 From: Frans Kaashoek Date: Fri, 2 Sep 2016 08:31:13 -0400 Subject: [PATCH] APIC IDs may not be consecutive and start from zero, so we cannot really use it as a direct index into cpus. Record apicid in struct cpu and have cpunum() look for it. Replace cpu->id with cpunum() everywhere, and replace cpu->id with cpu->apicid. Thanks to Xi Wang. --- console.c | 2 +- lapic.c | 16 +++++++++++++--- main.c | 6 +++--- mp.c | 10 ++++------ proc.h | 2 +- trap.c | 8 ++++---- 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/console.c b/console.c index 298a6e7..d84c7ff 100644 --- a/console.c +++ b/console.c @@ -110,7 +110,7 @@ panic(char *s) cli(); cons.locking = 0; - cprintf("cpu%d: panic: ", cpu->id); + cprintf("cpu with apicid %d: panic: ", cpu->apicid); cprintf(s); cprintf("\n"); getcallerpcs(&s, pcs); diff --git a/lapic.c b/lapic.c index 4bf2618..7507f97 100644 --- a/lapic.c +++ b/lapic.c @@ -1,6 +1,7 @@ // The local APIC manages internal (non-I/O) interrupts. // See Chapter 8 & Appendix C of Intel processor manual volume 3. +#include "param.h" #include "types.h" #include "defs.h" #include "date.h" @@ -8,6 +9,7 @@ #include "traps.h" #include "mmu.h" #include "x86.h" +#include "proc.h" // ncpu // Local APIC registers, divided by 4 for use as uint[] indices. #define ID (0x0020/4) // ID @@ -99,6 +101,8 @@ lapicinit(void) int cpunum(void) { + int apicid, i; + // Cannot call cpu when interrupts are enabled: // result not guaranteed to last long enough to be used! // Would prefer to panic but even printing is chancy here: @@ -111,9 +115,15 @@ cpunum(void) __builtin_return_address(0)); } - if(lapic) - return lapic[ID]>>24; - return 0; + if (!lapic) + return 0; + + apicid = lapic[ID] >> 24; + for (i = 0; i < ncpu; ++i) { + if (cpus[i].apicid == apicid) + return i; + } + panic("unknown apicid\n"); } // Acknowledge interrupt. diff --git a/main.c b/main.c index 2972b21..47c36cc 100644 --- a/main.c +++ b/main.c @@ -22,7 +22,7 @@ main(void) mpinit(); // detect other processors lapicinit(); // interrupt controller seginit(); // segment descriptors - cprintf("\ncpu%d: starting xv6\n\n", cpu->id); + cprintf("\ncpu%d: starting xv6\n\n", cpunum()); picinit(); // another interrupt controller ioapicinit(); // another interrupt controller consoleinit(); // console hardware @@ -54,7 +54,7 @@ mpenter(void) static void mpmain(void) { - cprintf("cpu%d: starting\n", cpu->id); + cprintf("cpu%d: starting\n", cpunum()); idtinit(); // load idt register xchg(&cpu->started, 1); // tell startothers() we're up scheduler(); // start running processes @@ -89,7 +89,7 @@ startothers(void) *(void**)(code-8) = mpenter; *(int**)(code-12) = (void *) V2P(entrypgdir); - lapicstartap(c->id, V2P(code)); + lapicstartap(c->apicid, V2P(code)); // wait for cpu to finish mpmain() while(c->started == 0) diff --git a/mp.c b/mp.c index 977a823..ade8930 100644 --- a/mp.c +++ b/mp.c @@ -106,12 +106,10 @@ mpinit(void) switch(*p){ case MPPROC: proc = (struct mpproc*)p; - if(ncpu != proc->apicid){ - cprintf("mpinit: ncpu=%d apicid=%d\n", ncpu, proc->apicid); - ismp = 0; + if(ncpu < NCPU) { + cpus[ncpu].apicid = proc->apicid; // apicid may differ from ncpu + ncpu++; } - cpus[ncpu].id = ncpu; - ncpu++; p += sizeof(struct mpproc); continue; case MPIOAPIC: @@ -125,8 +123,8 @@ mpinit(void) p += 8; continue; default: - cprintf("mpinit: unknown config type %x\n", *p); ismp = 0; + break; } } if(!ismp){ diff --git a/proc.h b/proc.h index d1597cf..7352805 100644 --- a/proc.h +++ b/proc.h @@ -1,6 +1,6 @@ // Per-CPU state struct cpu { - uchar id; // Local APIC ID; index into cpus[] below + uchar apicid; // Local APIC ID struct context *scheduler; // swtch() here to enter scheduler struct taskstate ts; // Used by x86 to find stack for interrupt struct segdesc gdt[NSEGS]; // x86 global descriptor table diff --git a/trap.c b/trap.c index 20ae62d..e6b3784 100644 --- a/trap.c +++ b/trap.c @@ -48,7 +48,7 @@ trap(struct trapframe *tf) switch(tf->trapno){ case T_IRQ0 + IRQ_TIMER: - if(cpu->id == 0){ + if(cpunum() == 0){ acquire(&tickslock); ticks++; wakeup(&ticks); @@ -74,7 +74,7 @@ trap(struct trapframe *tf) case T_IRQ0 + 7: case T_IRQ0 + IRQ_SPURIOUS: cprintf("cpu%d: spurious interrupt at %x:%x\n", - cpu->id, tf->cs, tf->eip); + cpunum(), tf->cs, tf->eip); lapiceoi(); break; @@ -83,13 +83,13 @@ trap(struct trapframe *tf) if(proc == 0 || (tf->cs&3) == 0){ // In kernel, it must be our mistake. cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n", - tf->trapno, cpu->id, tf->eip, rcr2()); + tf->trapno, cpunum(), tf->eip, rcr2()); panic("trap"); } // In user space, assume process misbehaved. cprintf("pid %d %s: trap %d err %d on cpu %d " "eip 0x%x addr 0x%x--kill proc\n", - proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip, + proc->pid, proc->name, tf->trapno, tf->err, cpunum(), tf->eip, rcr2()); proc->killed = 1; }