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.
This commit is contained in:
Frans Kaashoek 2016-09-02 08:31:13 -04:00
parent 37939f24c2
commit ae15515d80
6 changed files with 26 additions and 18 deletions

View file

@ -110,7 +110,7 @@ panic(char *s)
cli(); cli();
cons.locking = 0; cons.locking = 0;
cprintf("cpu%d: panic: ", cpu->id); cprintf("cpu with apicid %d: panic: ", cpu->apicid);
cprintf(s); cprintf(s);
cprintf("\n"); cprintf("\n");
getcallerpcs(&s, pcs); getcallerpcs(&s, pcs);

14
lapic.c
View file

@ -1,6 +1,7 @@
// The local APIC manages internal (non-I/O) interrupts. // The local APIC manages internal (non-I/O) interrupts.
// See Chapter 8 & Appendix C of Intel processor manual volume 3. // See Chapter 8 & Appendix C of Intel processor manual volume 3.
#include "param.h"
#include "types.h" #include "types.h"
#include "defs.h" #include "defs.h"
#include "date.h" #include "date.h"
@ -8,6 +9,7 @@
#include "traps.h" #include "traps.h"
#include "mmu.h" #include "mmu.h"
#include "x86.h" #include "x86.h"
#include "proc.h" // ncpu
// Local APIC registers, divided by 4 for use as uint[] indices. // Local APIC registers, divided by 4 for use as uint[] indices.
#define ID (0x0020/4) // ID #define ID (0x0020/4) // ID
@ -99,6 +101,8 @@ lapicinit(void)
int int
cpunum(void) cpunum(void)
{ {
int apicid, i;
// Cannot call cpu when interrupts are enabled: // Cannot call cpu when interrupts are enabled:
// result not guaranteed to last long enough to be used! // result not guaranteed to last long enough to be used!
// Would prefer to panic but even printing is chancy here: // Would prefer to panic but even printing is chancy here:
@ -111,9 +115,15 @@ cpunum(void)
__builtin_return_address(0)); __builtin_return_address(0));
} }
if(lapic) if (!lapic)
return lapic[ID]>>24;
return 0; 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. // Acknowledge interrupt.

6
main.c
View file

@ -22,7 +22,7 @@ main(void)
mpinit(); // detect other processors mpinit(); // detect other processors
lapicinit(); // interrupt controller lapicinit(); // interrupt controller
seginit(); // segment descriptors seginit(); // segment descriptors
cprintf("\ncpu%d: starting xv6\n\n", cpu->id); cprintf("\ncpu%d: starting xv6\n\n", cpunum());
picinit(); // another interrupt controller picinit(); // another interrupt controller
ioapicinit(); // another interrupt controller ioapicinit(); // another interrupt controller
consoleinit(); // console hardware consoleinit(); // console hardware
@ -54,7 +54,7 @@ mpenter(void)
static void static void
mpmain(void) mpmain(void)
{ {
cprintf("cpu%d: starting\n", cpu->id); cprintf("cpu%d: starting\n", cpunum());
idtinit(); // load idt register idtinit(); // load idt register
xchg(&cpu->started, 1); // tell startothers() we're up xchg(&cpu->started, 1); // tell startothers() we're up
scheduler(); // start running processes scheduler(); // start running processes
@ -89,7 +89,7 @@ startothers(void)
*(void**)(code-8) = mpenter; *(void**)(code-8) = mpenter;
*(int**)(code-12) = (void *) V2P(entrypgdir); *(int**)(code-12) = (void *) V2P(entrypgdir);
lapicstartap(c->id, V2P(code)); lapicstartap(c->apicid, V2P(code));
// wait for cpu to finish mpmain() // wait for cpu to finish mpmain()
while(c->started == 0) while(c->started == 0)

10
mp.c
View file

@ -106,12 +106,10 @@ mpinit(void)
switch(*p){ switch(*p){
case MPPROC: case MPPROC:
proc = (struct mpproc*)p; proc = (struct mpproc*)p;
if(ncpu != proc->apicid){ if(ncpu < NCPU) {
cprintf("mpinit: ncpu=%d apicid=%d\n", ncpu, proc->apicid); cpus[ncpu].apicid = proc->apicid; // apicid may differ from ncpu
ismp = 0;
}
cpus[ncpu].id = ncpu;
ncpu++; ncpu++;
}
p += sizeof(struct mpproc); p += sizeof(struct mpproc);
continue; continue;
case MPIOAPIC: case MPIOAPIC:
@ -125,8 +123,8 @@ mpinit(void)
p += 8; p += 8;
continue; continue;
default: default:
cprintf("mpinit: unknown config type %x\n", *p);
ismp = 0; ismp = 0;
break;
} }
} }
if(!ismp){ if(!ismp){

2
proc.h
View file

@ -1,6 +1,6 @@
// Per-CPU state // Per-CPU state
struct cpu { 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 context *scheduler; // swtch() here to enter scheduler
struct taskstate ts; // Used by x86 to find stack for interrupt struct taskstate ts; // Used by x86 to find stack for interrupt
struct segdesc gdt[NSEGS]; // x86 global descriptor table struct segdesc gdt[NSEGS]; // x86 global descriptor table

8
trap.c
View file

@ -48,7 +48,7 @@ trap(struct trapframe *tf)
switch(tf->trapno){ switch(tf->trapno){
case T_IRQ0 + IRQ_TIMER: case T_IRQ0 + IRQ_TIMER:
if(cpu->id == 0){ if(cpunum() == 0){
acquire(&tickslock); acquire(&tickslock);
ticks++; ticks++;
wakeup(&ticks); wakeup(&ticks);
@ -74,7 +74,7 @@ trap(struct trapframe *tf)
case T_IRQ0 + 7: case T_IRQ0 + 7:
case T_IRQ0 + IRQ_SPURIOUS: case T_IRQ0 + IRQ_SPURIOUS:
cprintf("cpu%d: spurious interrupt at %x:%x\n", cprintf("cpu%d: spurious interrupt at %x:%x\n",
cpu->id, tf->cs, tf->eip); cpunum(), tf->cs, tf->eip);
lapiceoi(); lapiceoi();
break; break;
@ -83,13 +83,13 @@ trap(struct trapframe *tf)
if(proc == 0 || (tf->cs&3) == 0){ if(proc == 0 || (tf->cs&3) == 0){
// In kernel, it must be our mistake. // In kernel, it must be our mistake.
cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n", 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"); panic("trap");
} }
// In user space, assume process misbehaved. // In user space, assume process misbehaved.
cprintf("pid %d %s: trap %d err %d on cpu %d " cprintf("pid %d %s: trap %d err %d on cpu %d "
"eip 0x%x addr 0x%x--kill proc\n", "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()); rcr2());
proc->killed = 1; proc->killed = 1;
} }