ref: c26d56edea946bf2206bc894fe1c944c37d96ce7
parent: bfc9136801651ac4921c78e5b9b3a71cf382f26d
author: glenda <glenda@cirno>
date: Sun May 5 21:55:14 EDT 2024
moving to having NIX work as a device.
--- a/sys/src/nix/pc64/dat.h
+++ b/sys/src/nix/pc64/dat.h
@@ -241,6 +241,13 @@
{
char machs[MAXMACH]; /* bitmap of active CPUs */
int exiting; /* shutdown */
+
+ // NIX
+ Lock;
+ int nonline; /* # of active CPUs */
+ int nbooting; /* # of CPUs waiting for the bTC to go */
+ int ispanic; /* shutdown in response to a panic */
+ int thunderbirdsarego; /* lets the added processors continue */
}active;
/*
--- a/sys/src/nix/pc64/devnix.c
+++ b/sys/src/nix/pc64/devnix.c
@@ -1,5 +1,9 @@
/*
- * Lml 22 driver
+ * NIX driver
+ * Cores are placed into NIX mode by
+ * wiring a proc to a core
+ * opening a file by core number
+ * The file has the 'one opener' attribute
*/
#include "u.h"
#include "../port/lib.h"
@@ -8,10 +12,7 @@
#include "fns.h"
#include "../port/error.h"
#include "io.h"
-#include "../port/pci.h"
-#include "devlml.h"
-
#define DBGREAD 0x01
#define DBGWRIT 0x02
#define DBGINTR 0x04
@@ -22,383 +23,169 @@
enum{
Qdir,
- Qctl0,
- Qjpg0,
- Qraw0,
- Qctl1,
- Qjpg1,
- Qraw1,
+ Qctl,
+ Qstat,
+ Q1,
};
-static Dirtab lmldir[] = {
+static Dirtab nixdir[] = {
".", {Qdir, 0, QTDIR}, 0, 0555,
- "lml0ctl", {Qctl0}, 0, 0666,
- "lml0jpg", {Qjpg0}, 0, 0444,
- "lml0raw", {Qraw0}, 0, 0444,
- "lml1ctl", {Qctl1}, 0, 0666,
- "lml1jpg", {Qjpg1}, 0, 0444,
- "lml1raw", {Qraw1}, 0, 0444,
+ "nixctl", {Qctl}, 0, 0666,
+ "nixstat", {Qstat}, 0, 0444,
+ "nix1", {Q1}, 0, 0444,
};
-typedef struct LML LML;
+typedef struct DEVNIX DEVNIX;
-struct LML {
- /* Hardware */
- Pcidev *pcidev;
- uintptr pciBaseAddr;
+struct DEVNIX {
+ int online;
+ int nixed;
+} DEVNIX[MAXMACH];
- /* Allocated memory */
- CodeData *codedata;
+int nnix;
- /* Software state */
- ulong jpgframeno;
- int frameNo;
- Rendez sleepjpg;
- int jpgopens;
-} lmls[NLML];
-int nlml;
-
-static FrameHeader jpgheader = {
- MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8,
- { 'L', 'M', 'L', '\0'},
- -1, 0, 0, 0
-};
-
-#define writel(v, a) *(ulong *)(a) = (v)
-#define readl(a) *(ulong*)(a)
-
-static int
-getbuffer(void *x)
-{
- static last = NBUF-1;
- int l = last;
- LML *lml;
-
- lml = x;
- for(;;){
- last = (last+1) % NBUF;
- if(lml->codedata->statCom[last] & STAT_BIT)
- return last + 1;
- if(last == l)
- return 0;
- }
-}
-
-static long
-jpgread(LML *lml, void *va, long nbytes, vlong, int dosleep)
-{
- int bufno;
- FrameHeader *jpgheader;
-
- /*
- * reads should be of size 1 or sizeof(FrameHeader).
- * Frameno is the number of the buffer containing the data.
- */
- while((bufno = getbuffer(lml)) == 0 && dosleep)
- sleep(&lml->sleepjpg, getbuffer, lml);
- if(--bufno < 0)
- return 0;
-
- jpgheader = (FrameHeader*)(lml->codedata->frag[bufno].hdr+2);
- if(nbytes == sizeof(FrameHeader)){
- memmove(va, jpgheader, sizeof(FrameHeader));
- return sizeof(FrameHeader);
- }
- if(nbytes == 1){
- *(char *)va = bufno;
- return 1;
- }
- return 0;
-}
-
-static void lmlintr(Ureg *, void *);
-
static void
-prepbuf(LML *lml)
+nixreset(void)
{
- int i;
- CodeData *cd;
+ DEVNIX *nix;
- cd = lml->codedata;
- for(i = 0; i < NBUF; i++){
- cd->statCom[i] = PADDR(&(cd->fragdesc[i]));
- cd->fragdesc[i].addr = PADDR(cd->frag[i].fb);
- /* Length is in double words, in position 1..20 */
- cd->fragdesc[i].leng = FRAGSIZE >> 1 | FRAGM_FINAL_B;
- memmove(cd->frag[i].hdr+2, &jpgheader, sizeof(FrameHeader)-2);
- }
-}
-
-static void
-lmlreset(void)
-{
- uvlong regpa;
- char name[32];
- void *regva;
- LML *lml;
- Pcidev *pcidev;
- Physseg segbuf;
-
pcidev = nil;
- for(nlml = 0; nlml < NLML && (pcidev = pcimatch(pcidev, VENDOR_ZORAN,
- ZORAN_36067)); nlml++){
- lml = &lmls[nlml];
- lml->pcidev = pcidev;
- lml->codedata = (CodeData*)(((ulong)xalloc(Codedatasize+ BY2PG)
- + BY2PG-1) & ~(BY2PG-1));
- if(lml->codedata == nil){
- print("devlml: xalloc(%ux, %ux, 0)\n", Codedatasize, BY2PG);
- return;
+ for(nnix = 0; nnix < MAXMACH; nnix++){
+ nix = &nixs[nnix];
}
- print("Installing Motion JPEG driver %s, irq %d\n",
- MJPG_VERSION, pcidev->intl);
- print("MJPG buffer at 0x%.8p, size 0x%.8ux\n", lml->codedata,
- Codedatasize);
- /* Get access to DMA memory buffer */
- lml->codedata->pamjpg = PADDR(lml->codedata->statCom);
- prepbuf(lml);
-
- print("zr36067 found at 0x%.8lux", pcidev->mem[0].bar & ~0x0F);
-
- regpa = pcidev->mem[0].bar & ~0x0F;
- regva = vmap(regpa, pcidev->mem[0].size);
- if(regva == 0){
- print("lml: failed to map registers\n");
- return;
- }
- lml->pciBaseAddr = (uintptr)regva;
- print(", mapped at %#p\n", lml->pciBaseAddr);
-
- memset(&segbuf, 0, sizeof(segbuf));
- segbuf.attr = SG_PHYSICAL;
- sprint(name, "lml%d.mjpg", nlml);
- kstrdup(&segbuf.name, name);
- segbuf.pa = PADDR(lml->codedata);
- segbuf.size = Codedatasize;
- if(addphysseg(&segbuf) == nil){
- print("lml: physsegment: %s\n", name);
- return;
- }
-
- memset(&segbuf, 0, sizeof(segbuf));
- segbuf.attr = SG_PHYSICAL | SG_DEVICE | SG_NOEXEC;
- sprint(name, "lml%d.regs", nlml);
- kstrdup(&segbuf.name, name);
- segbuf.pa = (uintptr)regpa;
- segbuf.size = pcidev->mem[0].size;
- if(addphysseg(&segbuf) == nil){
- print("lml: physsegment: %s\n", name);
- return;
- }
-
- /* set up interrupt handler */
- intrenable(pcidev->intl, lmlintr, lml, pcidev->tbdf, "lml");
- }
}
static Chan*
-lmlattach(char *spec)
+nixattach(char *spec)
{
if(debug&DBGFS)
- print("lmlattach\n");
+ print("nixattach\n");
return devattach(L'Λ', spec);
}
static Walkqid*
-lmlwalk(Chan *c, Chan *nc, char **name, int nname)
+nixwalk(Chan *c, Chan *nc, char **name, int nname)
{
if(debug&DBGFS)
- print("lmlwalk\n");
- return devwalk(c, nc, name, nname, lmldir, 3*nlml+1, devgen);
+ print("nixwalk\n");
+ return devwalk(c, nc, name, nname, nixdir, 3*nnix+1, devgen);
}
static int
-lmlstat(Chan *c, uchar *db, int n)
+nixstat(Chan *c, uchar *db, int n)
{
if(debug&DBGFS)
- print("lmlstat\n");
- return devstat(c, db, n, lmldir, 3*nlml+1, devgen);
+ print("nixstat\n");
+ return devstat(c, db, n, nixdir, 3*nnix+1, devgen);
}
static Chan*
-lmlopen(Chan *c, int omode)
+nixopen(Chan *c, int omode)
{
int i;
- LML *lml;
+ DEVNIX *nix;
if(debug&DBGFS)
- print("lmlopen\n");
+ print("nixopen\n");
if(omode != OREAD)
error(Eperm);
c->aux = 0;
i = 0;
switch((ulong)c->qid.path){
- case Qctl1:
- i++;
- /* fall through */
- case Qctl0:
- if(i >= nlml)
- error(Eio);
+ case Qctl:
+ error(Eperm);
break;
- case Qjpg1:
- case Qraw1:
- i++;
- /* fall through */
- case Qjpg0:
- case Qraw0:
- /* allow one open */
- if(i >= nlml)
- error(Eio);
- lml = lmls+i;
- if(lml->jpgopens)
- error(Einuse);
- lml->jpgopens = 1;
- lml->jpgframeno = 0;
- prepbuf(lml);
+ case Qstat:
+ error(Eperm);
break;
+ case Q1:
+ error("Eperm")
+ break;
}
- return devopen(c, omode, lmldir, 3*nlml+1, devgen);
+ return devopen(c, omode, nixdir, 3*nnix+1, devgen);
}
static void
-lmlclose(Chan *c)
+nixclose(Chan *c)
{
int i;
if(debug&DBGFS)
- print("lmlclose\n");
+ print("nixclose\n");
i = 0;
switch((ulong)c->qid.path){
- case Qjpg1:
- case Qraw1:
- i++;
- /* fall through */
- case Qjpg0:
- case Qraw0:
- lmls[i].jpgopens = 0;
- break;
+ case Q1:
+ default:
}
}
static long
-lmlread(Chan *c, void *va, long n, vlong voff)
+nixread(Chan *c, void *va, long n, vlong voff)
{
int i, len;
long off = voff;
uchar *buf = va;
- LML *lml;
- static char lmlinfo[1024];
+ DEVNIX *nix;
+ static char nixinfo[1024];
i = 0;
switch((ulong)c->qid.path){
case Qdir:
- n = devdirread(c, (char *)buf, n, lmldir, 3*nlml+1, devgen);
+ n = devdirread(c, (char *)buf, n, nixdir, 3*nnix+1, devgen);
if(debug&(DBGFS|DBGREAD))
- print("lmlread %ld\n", n);
+ print("nixread %ld\n", n);
return n;
- case Qctl1:
- i++;
- /* fall through */
- case Qctl0:
- if(i >= nlml)
+ case Qctl:
+ error(Eperm);
+ break;
+ case Qstat:
+ if(i >= nnix)
error(Eio);
- lml = lmls+i;
- len = snprint(lmlinfo, sizeof lmlinfo, "lml%djpg lml%draw\nlml%d.regs 0x%lux 0x%ux\nlml%d.mjpg 0x%lux 0x%ux\n",
- i, i,
- i, lml->pcidev->mem[0].bar & ~0x0F, lml->pcidev->mem[0].size,
- i, PADDR(lml->codedata), Codedatasize);
+ nix = nixs+i;
+ len = snprint(nixinfo, sizeof nixinfo, "sizzle me a sizzler");
if(voff > len)
return 0;
if(n > len - voff)
n = len - voff;
- memmove(va, lmlinfo+voff, n);
+ memmove(va, nixinfo+voff, n);
return n;
- case Qjpg1:
- i++;
- /* fall through */
- case Qjpg0:
- if(i >= nlml)
- error(Eio);
- return jpgread(lmls+i, buf, n, off, 1);
- case Qraw1:
- i++;
- /* fall through */
- case Qraw0:
- if(i >= nlml)
- error(Eio);
- return jpgread(lmls+i, buf, n, off, 0);
+ case Q1:
+ error(Eperm);
+ break;
}
return -1;
}
static long
-lmlwrite(Chan *, void *, long, vlong)
+nixwrite(Chan *, void *, long, vlong)
{
error(Eperm);
return 0;
}
-Dev lmldevtab = {
+Dev nixdevtab = {
L'Λ',
- "video",
+ "nix",
- lmlreset,
+ nixreset,
devinit,
devshutdown,
- lmlattach,
- lmlwalk,
- lmlstat,
- lmlopen,
+ nixattach,
+ nixwalk,
+ nixstat,
+ nixopen,
devcreate,
- lmlclose,
- lmlread,
+ nixclose,
+ nixread,
devbread,
- lmlwrite,
+ nixwrite,
devbwrite,
devremove,
devwstat,
};
-static void
-lmlintr(Ureg *, void *x)
-{
- ulong fstart, fno, flags, statcom;
- FrameHeader *jpgheader;
- LML *lml;
-
- lml = x;
- flags = readl(lml->pciBaseAddr+INTR_STAT);
- /* Reset all interrupts from 067 */
- writel(0xff000000, lml->pciBaseAddr + INTR_STAT);
-
- if(flags & INTR_JPEGREP){
-
- if(debug&DBGINTR)
- print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags);
-
- fstart = lml->jpgframeno & 3;
- for(;;){
- lml->jpgframeno++;
- fno = lml->jpgframeno & 3;
- if(lml->codedata->statCom[fno] & STAT_BIT)
- break;
- if(fno == fstart){
- if(debug & DBGINTR)
- print("Spurious lml jpg intr?\n");
- return;
- }
- }
- statcom = lml->codedata->statCom[fno];
- jpgheader = (FrameHeader *)(lml->codedata->frag[fno].hdr + 2);
- jpgheader->frameNo = lml->jpgframeno;
- jpgheader->ftime = todget(nil);
- jpgheader->frameSize = (statcom & 0x00ffffff) >> 1;
- jpgheader->frameSeqNo = statcom >> 24;
- wakeup(&lml->sleepjpg);
- }
-}
--- a/sys/src/nix/pc64/nix.h
+++ b/sys/src/nix/pc64/nix.h
@@ -43,3 +43,4 @@
char* note; /* to be posted in the TC after returning */
uchar data[ICCLNSZ]; /* sent to the AC */
};
+
--- a/sys/src/nix/pc64/nixmkfile
+++ b/sys/src/nix/pc64/nixmkfile
@@ -60,6 +60,7 @@
$CONF.rootc.$O\
$DEVS\
$PORT\
+ devnix.$O\
acore.$O\
tcore.$O\
l64acidt.$O\
--- /dev/null
+++ b/sys/src/nix/pc64/nixquidsC
@@ -1,0 +1,204 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+#include "mp.h"
+
+#define DBG print
+
+static void
+squidboy(Apic* apic)
+{
+ void acmmuswitch(void);
+ void acinit(void);
+ void acsched(void);
+
+ machinit();
+ mmuinit();
+ cpuidentify();
+ if(arch->clockinit)
+ arch->clockinit();
+ cpuidprint();
+ syncclock();
+ active.machs[m->machno] = 1;
+ apic->online = 1;
+ lapicinit(apic);
+ lapiconline();
+ timersinit();
+ m->nixtype = NIXAC;
+
+ /*
+ * CAUTION: no time sync done, etc.
+ */
+ DBG("Wait for the thunderbirds!\n");
+ if (0)
+ while(!active.thunderbirdsarego)
+ ;
+
+
+ DBG("Hello Squidboy %d %d\n", m->apicno, m->machno);
+
+ switch(m->nixtype){
+ case NIXAC:
+ acmmuswitch();
+ acinit();
+ // consider ilock/iunlock here, but .. why no ainc?
+ active.nbooting--;
+ active.nonline++;
+ //adec(&active.nbooting);
+ //ainc(&active.nonline); /* this was commented out */
+ acsched();
+ panic("squidboy");
+ break;
+ case NIXTC:
+ schedinit();
+ break;
+ }
+ panic("squidboy returns (type %d)", m->nixtype);
+}
+
+void
+mpstartap(Apic* apic)
+{
+ uintptr *apbootp, *pml4, *pdp0, v;
+ Segdesc *gdt;
+ Mach *mach;
+ uchar *p;
+ int i;
+
+ /*
+ * Initialise the AP page-tables and Mach structure.
+ * Xspanalloc will panic if an allocation can't be made.
+ */
+ p = xspanalloc(2*PTSZ + BY2PG + MACHSIZE, BY2PG, 0);
+ pml4 = (uintptr*)p;
+ p += PTSZ;
+ pdp0 = (uintptr*)p;
+ p += PTSZ;
+ gdt = (Segdesc*)p;
+ p += BY2PG;
+ mach = (Mach*)p;
+
+ memset(pml4, 0, PTSZ);
+ memset(pdp0, 0, PTSZ);
+ memset(gdt, 0, BY2PG);
+ memset(mach, 0, MACHSIZE);
+
+ mach->machno = apic->machno;
+ mach->pml4 = pml4;
+ mach->gdt = gdt; /* filled by mmuinit */
+ MACHP(mach->machno) = mach;
+
+ /*
+ * map KZERO (note that we share the KZERO (and VMAP)
+ * PDP between processors.
+ */
+ *mmuwalk(pml4, KZERO, 3, 0) = *mmuwalk(m->pml4, KZERO, 3, 0);
+ for(v = VMAP; v < VMAP+VMAPSIZE; v += PGLSZ(3)){
+ mmuwalk(m->pml4, v, 2, 1); /* force create */
+ *mmuwalk(pml4, v, 3, 0) = *mmuwalk(m->pml4, v, 3, 0);
+ }
+
+ /* double map */
+ pml4[0] = PADDR(pdp0) | PTEWRITE|PTEVALID;
+ pdp0[0] = *mmuwalk(pml4, KZERO, 2, 0);
+
+ /*
+ * Tell the AP where its kernel vector and pdb are.
+ * The offsets are known in the AP bootstrap code.
+ */
+ apbootp = (uintptr*)(APBOOTSTRAP+0x08);
+ apbootp[0] = (uintptr)squidboy; /* assembler jumps here eventually */
+ apbootp[1] = (uintptr)PADDR(pml4);
+ apbootp[2] = (uintptr)apic;
+ apbootp[3] = (uintptr)mach;
+ apbootp[4] |= (uintptr)m->havenx<<11; /* EFER */
+
+ /*
+ * Universal Startup Algorithm.
+ */
+ p = KADDR(0x467); /* warm-reset vector */
+ *p++ = PADDR(APBOOTSTRAP);
+ *p++ = PADDR(APBOOTSTRAP)>>8;
+ i = (PADDR(APBOOTSTRAP) & ~0xFFFF)/16;
+ /* code assumes i==0 */
+ if(i != 0)
+ print("mp: bad APBOOTSTRAP\n");
+ *p++ = i;
+ *p = i>>8;
+ coherence();
+
+ nvramwrite(0x0F, 0x0A); /* shutdown code: warm reset upon init ipi */
+ lapicstartap(apic, PADDR(APBOOTSTRAP));
+ for(i = 0; i < 100000; i++){
+ if(arch->fastclock == tscticks)
+ cycles(&m->tscticks); /* for ap's syncclock(); */
+ if(apic->online)
+ break;
+ delay(1);
+ }
+ nvramwrite(0x0F, 0x00);
+}
+
+static void
+testiccs(void)
+{
+ int i;
+ Mach *mp;
+ extern void testicc(int);
+
+ /* setup arguments for all */
+ for(i = 0; i < MACHMAX; i++)
+ if((mp = sys->machptr[i]) != nil && mp->online && mp->nixtype == NIXAC)
+ testicc(i);
+ print("bootcore: all cores done\n");
+}
+
+/*
+ * Rendezvous with other cores. Set roles for those that came
+ * up online, and wait until they are initialized.
+ * Sync TSC with them.
+ * We assume other processors that could boot had time to
+ * set online to 1 by now.
+ */
+static void
+nixsquids(void)
+{
+ Mach *mp;
+ int i;
+ uvlong now, start;
+
+ for(i = 1; i < MACHMAX; i++)
+ if((mp = sys->machptr[i]) != nil && mp->online){
+ /*
+ * Inter-core calls. A ensure *mp->iccall and mp->icargs
+ * go into different cache lines.
+ */
+ mp->icc = mallocalign(sizeof *m->icc, ICCLNSZ, 0, 0);
+ mp->icc->fn = nil;
+ if(i < numtcs){
+ sys->nmach++;
+ mp->nixtype = NIXTC;
+ sys->nc[NIXTC]++;
+ }else
+ sys->nc[NIXAC]++;
+ ainc(&active.nbooting);
+ }
+ sys->epoch = rdtsc();
+ mfence();
+ wrmsr(0x10, sys->epoch);
+ m->rdtsc = rdtsc();
+ active.thunderbirdsarego = 1;
+ start = fastticks2us(fastticks(nil));
+ do{
+ now = fastticks2us(fastticks(nil));
+ }while(active.nbooting > 0 && now - start < 1000000)
+ ;
+ if(active.nbooting > 0)
+ print("cpu0: %d cores couldn't start\n", active.nbooting);
+ active.nbooting = 0;
+}
--- a/sys/src/nix/pc64/squidboy.c
+++ /dev/null
@@ -1,133 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-
-#include "mp.h"
-
-#define DBG print
-
-static void
-squidboy(Apic* apic)
-{
- void acmmuswitch(void);
- void acinit(void);
- void acsched(void);
-
- machinit();
- mmuinit();
- cpuidentify();
- if(arch->clockinit)
- arch->clockinit();
- cpuidprint();
- syncclock();
- active.machs[m->machno] = 1;
- apic->online = 1;
- lapicinit(apic);
- lapiconline();
- timersinit();
- m->nixtype = NIXAC;
-
- DBG("Hello Squidboy %d %d\n", m->apicno, m->machno);
-
- switch(m->nixtype){
- case NIXAC:
- acmmuswitch();
- acinit();
- //adec(&active.nbooting);
- //ainc(&active.nonline); /* this was commented out */
- acsched();
- panic("squidboy");
- break;
- case NIXTC:
- schedinit();
- break;
- }
- panic("squidboy returns (type %d)", m->nixtype);
-}
-
-void
-mpstartap(Apic* apic)
-{
- uintptr *apbootp, *pml4, *pdp0, v;
- Segdesc *gdt;
- Mach *mach;
- uchar *p;
- int i;
-
- /*
- * Initialise the AP page-tables and Mach structure.
- * Xspanalloc will panic if an allocation can't be made.
- */
- p = xspanalloc(2*PTSZ + BY2PG + MACHSIZE, BY2PG, 0);
- pml4 = (uintptr*)p;
- p += PTSZ;
- pdp0 = (uintptr*)p;
- p += PTSZ;
- gdt = (Segdesc*)p;
- p += BY2PG;
- mach = (Mach*)p;
-
- memset(pml4, 0, PTSZ);
- memset(pdp0, 0, PTSZ);
- memset(gdt, 0, BY2PG);
- memset(mach, 0, MACHSIZE);
-
- mach->machno = apic->machno;
- mach->pml4 = pml4;
- mach->gdt = gdt; /* filled by mmuinit */
- MACHP(mach->machno) = mach;
-
- /*
- * map KZERO (note that we share the KZERO (and VMAP)
- * PDP between processors.
- */
- *mmuwalk(pml4, KZERO, 3, 0) = *mmuwalk(m->pml4, KZERO, 3, 0);
- for(v = VMAP; v < VMAP+VMAPSIZE; v += PGLSZ(3)){
- mmuwalk(m->pml4, v, 2, 1); /* force create */
- *mmuwalk(pml4, v, 3, 0) = *mmuwalk(m->pml4, v, 3, 0);
- }
-
- /* double map */
- pml4[0] = PADDR(pdp0) | PTEWRITE|PTEVALID;
- pdp0[0] = *mmuwalk(pml4, KZERO, 2, 0);
-
- /*
- * Tell the AP where its kernel vector and pdb are.
- * The offsets are known in the AP bootstrap code.
- */
- apbootp = (uintptr*)(APBOOTSTRAP+0x08);
- apbootp[0] = (uintptr)squidboy; /* assembler jumps here eventually */
- apbootp[1] = (uintptr)PADDR(pml4);
- apbootp[2] = (uintptr)apic;
- apbootp[3] = (uintptr)mach;
- apbootp[4] |= (uintptr)m->havenx<<11; /* EFER */
-
- /*
- * Universal Startup Algorithm.
- */
- p = KADDR(0x467); /* warm-reset vector */
- *p++ = PADDR(APBOOTSTRAP);
- *p++ = PADDR(APBOOTSTRAP)>>8;
- i = (PADDR(APBOOTSTRAP) & ~0xFFFF)/16;
- /* code assumes i==0 */
- if(i != 0)
- print("mp: bad APBOOTSTRAP\n");
- *p++ = i;
- *p = i>>8;
- coherence();
-
- nvramwrite(0x0F, 0x0A); /* shutdown code: warm reset upon init ipi */
- lapicstartap(apic, PADDR(APBOOTSTRAP));
- for(i = 0; i < 100000; i++){
- if(arch->fastclock == tscticks)
- cycles(&m->tscticks); /* for ap's syncclock(); */
- if(apic->online)
- break;
- delay(1);
- }
- nvramwrite(0x0F, 0x00);
-}