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:
parent
37939f24c2
commit
ae15515d80
|
@ -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
14
lapic.c
|
@ -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
6
main.c
|
@ -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
10
mp.c
|
@ -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
2
proc.h
|
@ -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
8
trap.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue