commit 3121e29fbb5db64ed76b5682d9f99633776de500
parent 8bb7079c6bce55bab6c85408b33c56644e6930b0
Author: Brian Swetland <swetland@frotz.net>
Date: Sat, 4 Jan 2014 18:35:00 -0800
support systems where cpu# != apicid
- add an apicid field to struct cpu, don't assume id == apicid
- startothers() uses cpu->apicid when calling lapicstartap()
- cpunum() now walks the cpu table to back-map apicid to id
this isn't too bad because cpunum() is only called from
seginit() to initialize the cpu-local pointer to its struct cpu.
Everywhere else uses cpu->id.
Now booting with two cores on an i3-4010u.
Diffstat:
4 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/include/proc.h b/include/proc.h
@@ -3,7 +3,8 @@
// Per-CPU state
struct cpu {
- uchar id; // Local APIC ID; index into cpus[] below
+ uchar 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/kernel/lapic.c b/kernel/lapic.c
@@ -7,6 +7,8 @@
#include "traps.h"
#include "mmu.h"
#include "x86.h"
+#include "param.h"
+#include "proc.h"
// Local APIC registers, divided by 4 for use as uint[] indices.
#define ID (0x0020/4) // ID
@@ -95,9 +97,13 @@ lapicinit(void)
lapicw(TPR, 0);
}
+// This is only used during secondary processor startup.
+// cpu->id is the fast way to get the cpu number, once the
+// processor is fully started.
int
cpunum(void)
{
+ int n, id;
// 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:
@@ -110,8 +116,14 @@ cpunum(void)
__builtin_return_address(0));
}
- if(lapic)
- return lapic[ID]>>24;
+ if(!lapic)
+ return 0;
+
+ id = lapic[ID]>>24;
+ for (n = 0; n < ncpu; n++)
+ if (id == cpus[n].apicid)
+ return n;
+
return 0;
}
diff --git a/kernel/main.c b/kernel/main.c
@@ -99,7 +99,7 @@ startothers(void)
*(int**)(code-12) = (void *) v2p(entrypgdir);
#endif
- lapicstartap(c->id, v2p(code));
+ lapicstartap(c->apicid, v2p(code));
// wait for cpu to finish mpmain()
while(c->started == 0)
diff --git a/kernel/mp.c b/kernel/mp.c
@@ -114,13 +114,11 @@ 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;
- }
+ cprintf("mpinit ncpu=%d apicid=%d\n", ncpu, proc->apicid);
if(proc->flags & MPBOOT)
bcpu = &cpus[ncpu];
cpus[ncpu].id = ncpu;
+ cpus[ncpu].apicid = proc->apicid;
ncpu++;
p += sizeof(struct mpproc);
continue;