ref: 6bb619c8db2867ddd9cd19c0aec05065f5ee0cae
parent: c88203b29aa39982ea701c083bb0d6bb2ea0483b
author: 9ferno <gophone2015@gmail.com>
date: Wed Oct 13 14:26:45 EDT 2021
working multiple processor configuration
--- a/mkfile
+++ b/mkfile
@@ -251,11 +251,14 @@
@{rfork n
mk binds
{ echo 'console=0 b115200'
- #echo '*dumpmp=1'
- echo '*nomp=1'
+ echo '*dumpmp=1'
+ echo '*apicdebug=1'
+ #echo '*nomp=1'
grep -v '^bootfile=' /n/src9/os/pc/plan9.ini
#echo 'bootfile='^`{echo $kernel | sed 's!^/n/src9!!'}
+ #echo 'bootfile=9pc64'
echo 'bootfile=ipc64'
+ echo wait
} > /env/plan9.ini
bind /env/plan9.ini /n/src9/plan9.ini
cat /n/src9/plan9.ini
--- a/os/pc/apic.c
+++ b/os/pc/apic.c
@@ -115,7 +115,71 @@
USED(data);
}
+static void
+showglobalconfig(void)
+{
+ u64 flags;
+ u32 iopl;
+ uintptr apic_base;
+
+ print("APIC global configuration\n");
+ flags = rflags();
+ print(" RFLAGS: 0x%zux, ", flags);
+ if(flags & 0x200)
+ print("maskable interrupts enabled, ");
+ else
+ print("maskable interrupts disabled, ");
+ iopl = flags & (0x11 << 12);
+ print("iopl 0x%x", iopl);
+ print("\n");
+
+ rdmsr(0x1B, (s64*)&apic_base);
+ print(" APIC_BASE: 0x%zux, ", apic_base);
+ if(apic_base & 0x100)
+ print("BSP, ");
+ else
+ print("not BSP, ");
+ if(apic_base & 0x400)
+ print("enable x2APIC mode, ");
+ else
+ print("disable x2APIC mode, ");
+ if(apic_base & 0x800)
+ print("APIC global enable");
+ else
+ print("APIC global disable");
+ print("\n");
+}
+
void
+showlapicregisters(void)
+{
+ showglobalconfig();
+ print(" LapicID %lux\n", lapicr(LapicID));
+ print(" LapicVER %lux\n", lapicr(LapicVER));
+ print(" LapicTPR %lux\n", lapicr(LapicTPR));
+ print(" LapicAPR %lux\n", lapicr(LapicAPR));
+ print(" LapicPPR %lux\n", lapicr(LapicPPR));
+ print(" LapicEOI %lux\n", lapicr(LapicEOI));
+ print(" LapicLDR %lux\n", lapicr(LapicLDR));
+ print(" LapicDFR %lux\n", lapicr(LapicDFR));
+ print(" LapicSVR %lux\n", lapicr(LapicSVR));
+ print(" LapicISR %lux\n", lapicr(LapicISR));
+ print(" LapicTMR %lux\n", lapicr(LapicTMR));
+ print(" LapicIRR %lux\n", lapicr(LapicIRR));
+ print(" LapicESR %lux\n", lapicr(LapicESR));
+ print(" LapicICRLO %lux\n", lapicr(LapicICRLO));
+ print(" LapicICRHI %lux\n", lapicr(LapicICRHI));
+ print(" LapicTIMER %lux\n", lapicr(LapicTIMER));
+ print(" LapicPCINT %lux\n", lapicr(LapicPCINT));
+ print(" LapicLINT0 %lux\n", lapicr(LapicLINT0));
+ print(" LapicLINT1 %lux\n", lapicr(LapicLINT1));
+ print(" LapicERROR %lux\n", lapicr(LapicERROR));
+ print(" LapicTICR %lux\n", lapicr(LapicTICR));
+ print(" LapicTCCR %lux\n", lapicr(LapicTCCR));
+ print(" LapicTDCR %lux\n", lapicr(LapicTDCR));
+}
+
+void
lapiconline(void)
{
Apictimer *a;
@@ -138,6 +202,7 @@
lapicw(LapicTDCR, lapictdxtab[a->tdx]);
lapicw(LapicTPR, 0);
+ showlapicregisters();
}
/*
@@ -209,6 +274,7 @@
dfr = 0xffffffff;
ldr = 0x00000000;
+print("lapicinit LapicID ID 0x%lux apic->machno 0x%d\n", lapicr(LapicID), apic->machno);
lapicw(LapicDFR, dfr);
lapicw(LapicLDR, ldr);
lapicw(LapicTPR, 0xff);
@@ -239,6 +305,7 @@
lapiceoi(0);
lvt = (lapicr(LapicVER)>>16) & 0xFF;
+print("lapicinit LapicVER Version 0x%lux\n", lvt);
if(lvt >= 4)
lapicw(LapicPCINT, ApicIMASK);
lapicw(LapicERROR, VectorPIC+IrqERROR);
@@ -269,21 +336,28 @@
int i;
ulong crhi;
+ showlapicregisters();
+print("lapicstartap v 0x%x\n", v);
/* make apic's processor do a warm reset */
crhi = apic->apicno<<24;
lapicw(LapicICRHI, crhi);
lapicw(LapicICRLO, LapicFIELD|ApicLEVEL|LapicASSERT|ApicINIT);
+print("lapicstartap LapicFIELD|ApicLEVEL|LapicASSERT|ApicINIT 0x%ux\n", LapicFIELD|ApicLEVEL|LapicASSERT|ApicINIT);
microdelay(200);
lapicw(LapicICRLO, LapicFIELD|ApicLEVEL|LapicDEASSERT|ApicINIT);
delay(10);
+print("lapicstartap LapicID ID 0x%lux apic->machno 0x%d\n", lapicr(LapicID), apic->machno);
/* assumes apic is not an 82489dx */
for(i = 0; i < 2; i++){
lapicw(LapicICRHI, crhi);
/* make apic's processor start at v in real mode */
lapicw(LapicICRLO, LapicFIELD|ApicEDGE|ApicSTARTUP|(v/BY2PG));
+print("lapicstartap LapicFIELD|ApicEDGE|ApicSTARTUP|(v/BY2PG) 0x%zux\n", LapicFIELD|ApicEDGE|ApicSTARTUP|(v/BY2PG));
microdelay(200);
}
+print("lapicstartap apic->machno %d after the for loop\n", apic->machno);
+ showlapicregisters();
}
void
@@ -380,6 +454,7 @@
* Make sure interrupts are all masked off for now.
*/
iowin = apic->addr+(0x10/sizeof(ulong));
+print("ioapicinit apic->addr 0x%p iowin 0x%p\n", apic->addr, iowin);
lock(apic);
*apic->addr = IoapicVER;
apic->mre = (*iowin>>16) & 0xFF;
@@ -388,6 +463,7 @@
*iowin = apicno<<24;
unlock(apic);
+print("ioapicinit *iowin 0x%ux\n", *iowin);
hi = 0;
lo = ApicIMASK;
for(v = 0; v <= apic->mre; v++)
@@ -421,16 +497,18 @@
timerintr(u, 0);
}
-void
-lapicintron(void)
+int
+lapicintron(Vctl*)
{
lapicw(LapicTPR, 0);
+ return 0;
}
-void
-lapicintroff(void)
+int
+lapicintroff(int)
{
lapicw(LapicTPR, 0xFF);
+ return 0;
}
void
--- a/os/pc/archacpi.c
+++ b/os/pc/archacpi.c
@@ -112,6 +112,7 @@
Tbl *t;
int i;
+print("maptable pa 0x%p\n", pa);
if(-pa < 8)
return;
@@ -131,9 +132,11 @@
if(l < Tblsz
|| l >= 0x10000000
|| -pa < l){
+print("mptable vunmap t 0x%p\n", t);
vunmap(t, 8);
return;
}
+print("mptable memreserve pa 0x%p l 0x%d\n", pa, l);
memreserve(pa, l);
vunmap(t, 8);
if((t = vmap(pa, l)) == nil)
@@ -144,19 +147,25 @@
}
tblmap[ntblmap++] = t;
+print("mptable ntblmap 0x%d\n", ntblmap);
p = (uchar*)t;
e = p + l;
if(memcmp("RSDT", t->sig, 4) == 0){
+print("mptable RSDT\n");
for(p = t->data; p+3 < e; p += 4)
maptable(get32(p));
+print("mptable exiting RSDT\n");
return;
}
if(memcmp("XSDT", t->sig, 4) == 0){
+print("mptable XSDT\n");
for(p = t->data; p+7 < e; p += 8)
maptable(get64(p));
+print("mptable exiting XSDT\n");
return;
}
if(memcmp("FACP", t->sig, 4) == 0){
+print("mptable FACP\n");
if(l < 44)
return;
maptable(get32(p + 40));
@@ -574,15 +583,17 @@
acpiinit(void)
{
Tbl *t;
- Apic *a;
+ Apic *a, *apic;
void *va;
uchar *s, *p, *e;
ulong lapicbase;
int machno, i, c;
+print("acpiinit: before amlinit\n");
amlinit();
/* load DSDT */
+print("acpiinit: load DSDT\n");
if((t = findtable("DSDT")) != nil){
amlintmask = (~0ULL) >> (t->rev <= 1)*32;
amlload(t->data, tbldlen(t));
@@ -589,6 +600,7 @@
}
/* load SSDT, there can be multiple tables */
+print("acpiinit: load SSDT\n");
for(i=0; i<ntblmap; i++){
t = tblmap[i];
if(memcmp(t->sig, "SSDT", 4) == 0)
@@ -596,20 +608,28 @@
}
/* set APIC mode */
+print("acpiinit: set APIC mode\n");
amleval(amlwalk(amlroot, "_PIC"), "i", 1, nil);
t = findtable("APIC");
if(t == nil)
panic("acpiinit: no MADT (APIC) table");
+print("acpiinit: found APIC\n");
s = t->data;
e = s + tbldlen(t);
lapicbase = get32(s); s += 8;
+print("acpiinit: lapicbase 0x%lux\n", lapicbase);
va = vmap(lapicbase, 1024);
print("LAPIC: %.8lux %#p\n", lapicbase, va);
if(va == nil)
panic("acpiinit: cannot map lapic %.8lux", lapicbase);
+ print("t->data:");
+ for(p = s; p < e; p ++){
+ print(" %x", *p);
+ }
+ print("\n");
machno = 0;
for(p = s; p < e; p += c){
c = p[1];
@@ -617,6 +637,7 @@
break;
switch(*p){
case 0x00: /* Processor Local APIC */
+print("acpiinit Processor Local APIC p[3] %d MaxAPICNO %d\n", p[3], MaxAPICNO);
if(p[3] > MaxAPICNO)
break;
if((a = xalloc(sizeof(Apic))) == nil)
@@ -631,6 +652,7 @@
/* skip disabled processors */
if((a->flags & PcmpEN) == 0 || mpapic[a->apicno] != nil){
+print("acpiinit disabled processor a->flags & PcmpEN 0x%x mpapic[a->apicno] 0x%p\n", a->flags & PcmpEN, mpapic[a->apicno]);
xfree(a);
break;
}
@@ -644,8 +666,11 @@
a->flags |= PcmpBP;
mpapic[a->apicno] = a;
+ print("acpinit LAPIC%d: pa=%lux va=%#p flags=%x\n",
+ a->apicno, a->paddr, a->addr, a->flags);
break;
case 0x01: /* I/O APIC */
+print("acpiinit Processor I/O APIC p[2] %d MaxAPICNO %d\n", p[2], MaxAPICNO);
if(p[2] > MaxAPICNO)
break;
if((a = xalloc(sizeof(Apic))) == nil)
@@ -658,11 +683,21 @@
a->gsibase = get32(p+8);
a->flags = PcmpEN;
mpioapic[a->apicno] = a;
+print("acpiinit ioapicinit\n");
ioapicinit(a, a->apicno);
break;
}
}
+print("after initialization\n");
+ for(i=0; i<=MaxAPICNO; i++){
+ if(apic = mpapic[i])
+ print("LAPIC%d: pa=%lux va=%#p flags=%x\n",
+ i, apic->paddr, apic->addr, apic->flags);
+ if(apic = mpioapic[i])
+ print("IOAPIC%d: pa=%lux va=%#p flags=%x gsibase=%d mre=%d\n",
+ i, apic->paddr, apic->addr, apic->flags, apic->gsibase, apic->mre);
+ }
/*
* need 2nd pass as vbox puts interrupt overrides
* *before* the ioapic entries (!)
@@ -689,16 +724,20 @@
}
}
+print("acpiinit: embedded controller\n");
/* find embedded controller */
amlenum(amlroot, "_HID", enumec, nil);
/* look for PCI interrupt mappings */
+print("acpiinit: interrupt mappings\n");
amlenum(amlroot, "_PRT", enumprt, nil);
/* add identity mapped legacy isa interrupts */
+print("acpiinit: legacy isa interrupts\n");
for(i=0; i<16; i++)
addirq(i, BusISA, 0, i, 0);
+print("acpiinit: free aml\n");
/* free the AML interpreter */
amlexit();
@@ -705,6 +744,7 @@
/*
* Ininitalize local APIC and start application processors.
*/
+print("acpiinit: calling mpinit\n");
mpinit();
}
@@ -802,15 +842,24 @@
}
if(rsd == nil)
return 1;
- if(checksum(rsd, 20) && checksum(rsd, 36))
+ if(checksum(rsd, 20) && checksum(rsd, 36)){
+print("checksum(rsd, 20) && checksum(rsd, 36) unmatched\n");
return 1;
+ }
+print("archacpi identify: maptables()\n");
maptables();
+print("archacpi identify: after maptables()\n");
addarchfile("acpitbls", 0444, readtbls, nil);
addarchfile("acpimem", 0600, readmem, writemem);
- if(v == 0 || findtable("APIC") == nil)
+print("archacpi identify: findtable APIC()\n");
+ if(v == 0 || findtable("APIC") == nil){
+print("v == 0 || findtable(APIC) == nil\n");
return 1;
- if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
+ }
+ if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0){
+print("(cp = getconf(*nomp)) != nil && strcmp(cp, 0) != 0\n");
return 1;
+ }
if(getconf("*nohpet") == nil
&& (t = findtable("HPET")) != nil
&& ((uchar*)t)[40] == 0
@@ -818,8 +867,10 @@
archacpi.clockinit = hpetinit;
archacpi.fastclock = hpetread;
}
+print("archacpi identify: after hpet\n");
if(m->havetsc && getconf("*notsc") == nil)
archacpi.fastclock = tscticks;
+print("archacpi identify: after notsc\n");
return 0;
}
--- a/os/pc/archmp.c
+++ b/os/pc/archmp.c
@@ -4,66 +4,380 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
+#include "../port/pci.h"
#include "mp.h"
-#define cpuserver 1
+static PCMP *pcmp;
-_MP_ *_mp_;
+static char* buses[] = {
+ "CBUSI ",
+ "CBUSII",
+ "EISA ",
+ "FUTURE",
+ "INTERN",
+ "ISA ",
+ "MBI ",
+ "MBII ",
+ "MCA ",
+ "MPI ",
+ "MPSA ",
+ "NUBUS ",
+ "PCI ",
+ "PCMCIA",
+ "TC ",
+ "VL ",
+ "VME ",
+ "XPRESS",
+ 0,
+};
-static _MP_*
-mpscan(uchar *addr, int len)
+static Bus*
+mpgetbus(int busno)
{
- uchar *e, *p, sum;
+ Bus *bus;
+
+ for(bus = mpbus; bus; bus = bus->next)
+ if(bus->busno == busno)
+ return bus;
+
+ print("mpgetbus: can't find bus %d\n", busno);
+ return 0;
+}
+
+static Apic*
+mkprocessor(PCMPprocessor* p)
+{
+ static int machno = 1;
+ int apicno;
+ Apic *apic;
+
+ apicno = p->apicno;
+ if(!(p->flags & PcmpEN) || apicno > MaxAPICNO || mpapic[apicno] != nil)
+ return 0;
+
+ if((apic = xalloc(sizeof(Apic))) == nil)
+ panic("mkprocessor: no memory for Apic");
+ apic->type = PcmpPROCESSOR;
+ apic->apicno = apicno;
+ apic->flags = p->flags;
+ apic->lintr[0] = ApicIMASK;
+ apic->lintr[1] = ApicIMASK;
+ if(p->flags & PcmpBP)
+ apic->machno = 0;
+ else
+ apic->machno = machno++;
+ mpapic[apicno] = apic;
+
+ return apic;
+}
+
+static Bus*
+mkbus(PCMPbus* p)
+{
+ Bus *bus;
int i;
- e = addr+len;
- for(p = addr; p < e; p += sizeof(_MP_)){
- if(memcmp(p, "_MP_", 4))
- continue;
- sum = 0;
- for(i = 0; i < sizeof(_MP_); i++)
- sum += p[i];
- if(sum == 0)
- return (_MP_*)p;
+ for(i = 0; buses[i]; i++)
+ if(strncmp(buses[i], p->string, sizeof(p->string)) == 0)
+ break;
+ if(buses[i] == 0)
+ return 0;
+
+ if((bus = xalloc(sizeof(Bus))) == nil)
+ panic("mkbus: no memory for Bus");
+ if(mpbus)
+ mpbuslast->next = bus;
+ else
+ mpbus = bus;
+ mpbuslast = bus;
+
+ bus->type = i;
+ bus->busno = p->busno;
+ if(bus->type == BusEISA){
+ bus->po = PcmpLOW;
+ bus->el = PcmpLEVEL;
+ if(mpeisabus != -1)
+ print("mkbus: more than one EISA bus\n");
+ mpeisabus = bus->busno;
}
- return 0;
+ else if(bus->type == BusPCI){
+ bus->po = PcmpLOW;
+ bus->el = PcmpLEVEL;
+ }
+ else if(bus->type == BusISA){
+ bus->po = PcmpHIGH;
+ bus->el = PcmpEDGE;
+ if(mpisabus != -1)
+ print("mkbus: more than one ISA bus\n");
+ mpisabus = bus->busno;
+ }
+ else{
+ bus->po = PcmpHIGH;
+ bus->el = PcmpEDGE;
+ }
+
+ return bus;
}
-static _MP_*
-mpsearch(void)
+static Apic*
+mkioapic(PCMPioapic* p)
{
- uchar *bda;
- ulong p;
- _MP_ *mp;
+ void *va;
+ int apicno;
+ Apic *apic;
+ apicno = p->apicno;
+ if(!(p->flags & PcmpEN) || apicno > MaxAPICNO || mpioapic[apicno] != nil)
+ return 0;
/*
- * Search for the MP Floating Pointer Structure:
- * 1) in the first KB of the EBDA;
- * 2) in the last KB of system base memory;
- * 3) in the BIOS ROM between 0xE0000 and 0xFFFFF.
+ * Map the I/O APIC.
*/
- bda = KADDR(0x400);
- if((p = (bda[0x0F]<<8)|bda[0x0E])){
- if(mp = mpscan(KADDR(p), 1024))
- return mp;
+ if((va = vmap(p->addr, 1024)) == nil)
+ return 0;
+ if((apic = xalloc(sizeof(Apic))) == nil)
+ panic("mkioapic: no memory for Apic");
+ apic->type = PcmpIOAPIC;
+ apic->apicno = apicno;
+ apic->addr = va;
+ apic->paddr = p->addr;
+ apic->flags = p->flags;
+ mpioapic[apicno] = apic;
+
+ return apic;
+}
+
+static Aintr*
+mkiointr(PCMPintr* p)
+{
+ Bus *bus;
+ Aintr *aintr;
+ PCMPintr* pcmpintr;
+
+ /*
+ * According to the MultiProcessor Specification, a destination
+ * I/O APIC of 0xFF means the signal is routed to all I/O APICs.
+ * It's unclear how that can possibly be correct so treat it as
+ * an error for now.
+ */
+ if(p->apicno > MaxAPICNO || mpioapic[p->apicno] == nil)
+ return 0;
+
+ if((bus = mpgetbus(p->busno)) == 0)
+ return 0;
+
+ if((aintr = xalloc(sizeof(Aintr))) == nil)
+ panic("mkiointr: no memory for Aintr");
+ aintr->intr = p;
+
+ if(0)
+ print("mkiointr: type %d intr type %d flags %#o "
+ "bus %d irq %d apicno %d intin %d\n",
+ p->type, p->intr, p->flags,
+ p->busno, p->irq, p->apicno, p->intin);
+ /*
+ * Hack for Intel SR1520ML motherboard, which BIOS describes
+ * the i82575 dual ethernet controllers incorrectly.
+ */
+ if(memcmp(pcmp->product, "INTEL X38MLST ", 20) == 0){
+ if(p->busno == 1 && p->intin == 16 && p->irq == 1){
+ if((pcmpintr = xalloc(sizeof(PCMPintr))) == nil)
+ panic("iointr: no memory for PCMPintr");
+ memmove(pcmpintr, p, sizeof(PCMPintr));
+ print("mkiointr: %20.20s bus %d intin %d irq %d\n",
+ (char*)pcmp->product,
+ pcmpintr->busno, pcmpintr->intin,
+ pcmpintr->irq);
+ pcmpintr->intin = 17;
+ aintr->intr = pcmpintr;
+ }
}
+ aintr->apic = mpioapic[p->apicno];
+ aintr->next = bus->aintr;
+ aintr->bus = bus;
+ bus->aintr = aintr;
+
+ return aintr;
+}
+
+static int
+mklintr(PCMPintr* p)
+{
+ Apic *apic;
+ Bus *bus;
+ int i, intin, v;
+
+ /*
+ * The offsets of vectors for LINT[01] are known to be
+ * 0 and 1 from the local APIC vector space at VectorLAPIC.
+ */
+ if((bus = mpgetbus(p->busno)) == 0)
+ return 0;
+ intin = p->intin;
+
+ /*
+ * Pentium Pros have problems if LINT[01] are set to ExtINT
+ * so just bag it, SMP mode shouldn't need ExtINT anyway.
+ */
+ if(p->intr == PcmpExtINT || p->intr == PcmpNMI)
+ v = ApicIMASK;
+ else
+ v = mpintrinit(bus, p, VectorLAPIC+intin, p->irq);
+
+ if(p->apicno == 0xFF){
+ for(i=0; i<=MaxAPICNO; i++){
+ if((apic = mpapic[i]) == nil)
+ continue;
+ if(apic->flags & PcmpEN)
+ apic->lintr[intin] = v;
+ }
+ }
else{
- p = ((bda[0x14]<<8)|bda[0x13])*1024;
- if(mp = mpscan(KADDR(p-1024), 1024))
- return mp;
+ if(apic = mpapic[p->apicno])
+ if(apic->flags & PcmpEN)
+ apic->lintr[intin] = v;
}
- return mpscan(KADDR(0xF0000), 0x10000);
+
+ return v;
}
+static void
+dumpmp(uchar *p, uchar *e)
+{
+ int i;
+
+ for(i = 0; p < e; p++) {
+ if((i % 16) == 0) print("*mp%d=", i/16);
+ print("%.2x ", *p);
+ if((++i % 16) == 0) print("\n");
+ }
+ if((i % 16) != 0) print("\n");
+}
+
+
+static void
+mpoverride(uchar** newp, uchar** e)
+{
+ int size, i, j;
+ char buf[20];
+ uchar* p;
+ char* s;
+
+ size = strtol(getconf("*mp"), 0, 0);
+ if(size <= 0) panic("mpoverride: invalid size in *mp");
+ *newp = p = xalloc(size);
+ if(p == nil) panic("mpoverride: can't allocate memory");
+ *e = p + size;
+ for(i = 0; ; i++){
+ snprint(buf, sizeof buf, "*mp%d", i);
+ s = getconf(buf);
+ if(s == nil) break;
+ while(*s){
+ j = strtol(s, &s, 16);
+ if(*s && *s != ' ' || j < 0 || j > 0xff) panic("mpoverride: invalid entry in %s", buf);
+ if(p >= *e) panic("mpoverride: overflow in %s", buf);
+ *p++ = j;
+ }
+ }
+ if(p != *e) panic("mpoverride: size doesn't match");
+}
+
+static void
+pcmpinit(void)
+{
+ uchar *p, *e;
+ Apic *apic;
+ void *va;
+
+ /*
+ * Map the local APIC.
+ */
+ va = vmap(pcmp->lapicbase, 1024);
+
+ print("LAPIC: %.8lux %#p\n", pcmp->lapicbase, va);
+ if(va == nil)
+ panic("pcmpinit: cannot map lapic %.8lux", pcmp->lapicbase);
+
+ p = ((uchar*)pcmp)+PCMPsz;
+ e = ((uchar*)pcmp)+pcmp->length;
+ if(getconf("*dumpmp") != nil)
+ dumpmp(p, e);
+ if(getconf("*mp") != nil)
+ mpoverride(&p, &e);
+
+ /*
+ * Run through the table saving information needed for starting
+ * application processors and initialising any I/O APICs. The table
+ * is guaranteed to be in order such that only one pass is necessary.
+ */
+ while(p < e) switch(*p){
+ default:
+ print("pcmpinit: unknown PCMP type 0x%uX (e-p 0x%zuX)\n",
+ *p, e-p);
+ while(p < e){
+ print("%uX ", *p);
+ p++;
+ }
+ break;
+
+ case PcmpPROCESSOR:
+ if(apic = mkprocessor((PCMPprocessor*)p)){
+ apic->addr = va;
+ apic->paddr = pcmp->lapicbase;
+ }
+ p += PCMPprocessorsz;
+ continue;
+
+ case PcmpBUS:
+ mkbus((PCMPbus*)p);
+ p += PCMPbussz;
+ continue;
+
+ case PcmpIOAPIC:
+ if(apic = mkioapic((PCMPioapic*)p))
+ ioapicinit(apic, apic->apicno);
+ p += PCMPioapicsz;
+ continue;
+
+ case PcmpIOINTR:
+ mkiointr((PCMPintr*)p);
+ p += PCMPintrsz;
+ continue;
+
+ case PcmpLINTR:
+ mklintr((PCMPintr*)p);
+ p += PCMPintrsz;
+ continue;
+ }
+
+ /*
+ * Ininitalize local APIC and start application processors.
+ */
+ mpinit();
+}
+
+static void
+mpreset(void)
+{
+ /* stop application processors */
+ mpshutdown();
+
+ /* do generic reset */
+ archreset();
+}
+
static int identify(void);
+extern int i8259irqno(int, int);
PCArch archmp = {
.id= "_MP_",
.ident= identify,
-.reset= mpshutdown,
-.intrinit= mpinit,
-.intrenable= mpintrenable,
+.reset= mpreset,
+.intrinit= pcmpinit,
+.intrassign= mpintrassign,
+.intrirqno= i8259irqno,
+.intrenable= lapicintron,
+.intrdisable= lapicintroff,
.fastclock= i8253read,
.timerset= lapictimerset,
};
@@ -71,12 +385,15 @@
static int
identify(void)
{
- PCMP *pcmp;
- uchar *p, sum;
- ulong length;
+ char *cp;
+ _MP_ *_mp_;
+ ulong pa, len;
- if(getconf("*nomp"))
+print("archmp.c: identify\n");
+ if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0){
+print("archmp.c: identify *nomp != nil\n");
return 1;
+ }
/*
* Search for an MP configuration table. For now,
@@ -85,54 +402,41 @@
* if correct, check the version.
* To do: check extended table checksum.
*/
- if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0)
+ if((_mp_ = sigsearch("_MP_", _MP_sz)) == nil || _mp_->physaddr == 0){
+print("archmp.c: identify sigsearch _MP_ not found\n");
return 1;
+ }
- pcmp = KADDR(_mp_->physaddr);
- if(memcmp(pcmp, "PCMP", 4))
+print("archmp sigsearch found _mp_ 0x%p\n", _mp_);
+ len = PCMPsz;
+ pa = _mp_->physaddr;
+ if(pa + len-1 < pa)
return 1;
- length = pcmp->length;
- sum = 0;
- for(p = (uchar*)pcmp; length; length--)
- sum += *p++;
-
- if(sum || (pcmp->version != 1 && pcmp->version != 4))
+ memreserve(pa, len);
+ if((pcmp = vmap(pa, len)) == nil)
return 1;
-
- if(cpuserver && m->havetsc)
- archmp.fastclock = tscticks;
- return 0;
-}
-
-Lock mpsynclock;
-
-void
-syncclock(void)
-{
- uvlong x;
-
- if(arch->fastclock != tscticks)
- return;
-
- if(m->machno == 0){
- wrmsr(0x10, 0);
- m->tscticks = 0;
- } else {
- x = MACHP(0)->tscticks;
- while(x == MACHP(0)->tscticks)
- ;
- wrmsr(0x10, MACHP(0)->tscticks);
- cycles(&m->tscticks);
+ if(pcmp->length < PCMPsz
+ || pa + pcmp->length-1 < pa
+ || memcmp(pcmp, "PCMP", 4) != 0
+ || (pcmp->version != 1 && pcmp->version != 4)){
+Bad:
+ vunmap(pcmp, len);
+ pcmp = nil;
+ return 1;
}
-}
+ len = pcmp->length;
+ memreserve(pa, len);
+ vunmap(pcmp, PCMPsz);
+ if((pcmp = vmap(pa, len)) == nil)
+ return 1;
-uvlong
-tscticks(uvlong *hz)
-{
- if(hz != nil)
- *hz = m->cpuhz;
+ if(checksum(pcmp, len) != 0)
+ goto Bad;
- cycles(&m->tscticks); /* Uses the rdtsc instruction */
- return m->tscticks;
+print("archmp identify after checksum\n");
+ if(m->havetsc && getconf("*notsc") == nil)
+ archmp.fastclock = tscticks;
+
+ return 0;
}
--- a/os/pc/devarch.c
+++ b/os/pc/devarch.c
@@ -856,10 +856,13 @@
arch = knownarch[0];
for(p = knownarch; *p != nil; p++){
+print("archinit checking %s .. ", (*p)->id);
if((*p)->ident != nil && (*p)->ident() == 0){
+print(" identified\n");
arch = *p;
break;
}
+print(" not identified\n");
}
if(arch != knownarch[0]){
if(arch->id == nil)
@@ -873,7 +876,7 @@
if(arch->clockinit == nil)
arch->clockinit = knownarch[0]->clockinit;
}
-
+print("archinit id %s\n", arch->id);
/*
* Decide whether to use copy-on-reference (386 and mp).
* We get another chance to set it in mpinit() for a
--- a/os/pc/i8259.c
+++ b/os/pc/i8259.c
@@ -29,6 +29,9 @@
static int i8259mask = 0xFFFF; /* disabled interrupts */
int i8259elcr; /* mask of level-triggered interrupts */
+void i8259on(void);
+void i8259off(void);
+
void
i8259init(void)
{
@@ -128,41 +131,10 @@
}
int
-i8259enable(Vctl* v)
+i8259enable(Vctl*)
{
- int irq, irqbit;
-
- /*
- * Given an IRQ, enable the corresponding interrupt in the i8259
- * and return the vector to be used. The i8259 is set to use a fixed
- * range of vectors starting at VectorPIC.
- */
- irq = v->irq;
- if(irq < 0 || irq > MaxIrqPIC){
- print("i8259enable: irq %d out of range\n", irq);
- return -1;
- }
- irqbit = 1<<irq;
-
- ilock(&i8259lock);
- if(!(i8259mask & irqbit) && !(i8259elcr & irqbit)){
- print("i8259enable: irq %d shared but not level\n", irq);
- iunlock(&i8259lock);
- return -1;
- }
- i8259mask &= ~irqbit;
- if(irq < 8)
- outb(Int0aux, i8259mask & 0xFF);
- else
- outb(Int1aux, (i8259mask>>8) & 0xFF);
-
- if(i8259elcr & irqbit)
- v->eoi = i8259isr;
- else
- v->isr = i8259isr;
- iunlock(&i8259lock);
-
- return VectorPIC+irq;
+ i8259on();
+ return 1; /* TODO fix this */
}
int
@@ -172,29 +144,9 @@
}
int
-i8259disable(int irq)
+i8259disable(int)
{
- int irqbit;
-
- /*
- * Given an IRQ, disable the corresponding interrupt
- * in the 8259.
- */
- if(irq < 0 || irq > MaxIrqPIC){
- print("i8259disable: irq %d out of range\n", irq);
- return -1;
- }
- irqbit = 1<<irq;
-
- ilock(&i8259lock);
- if(!(i8259mask & irqbit)){
- i8259mask |= irqbit;
- if(irq < 8)
- outb(Int0aux, i8259mask & 0xFF);
- else
- outb(Int1aux, (i8259mask>>8) & 0xFF);
- }
- iunlock(&i8259lock);
+ i8259off();
return 0;
}
--- a/os/pc/mp.c
+++ b/os/pc/mp.c
@@ -123,6 +123,41 @@
}
}
+static void
+showglobalconfig(void)
+{
+ u64 flags;
+ u32 iopl;
+ uintptr apic_base;
+
+ print("APIC global configuration\n");
+ flags = rflags();
+ print(" RFLAGS: 0x%zux, ", flags);
+ if(flags & 0x200)
+ print("maskable interrupts enabled, ");
+ else
+ print("maskable interrupts disabled, ");
+ iopl = flags & (0x11 << 12);
+ print("iopl 0x%x", iopl);
+ print("\n");
+
+ rdmsr(0x1B, (s64*)&apic_base);
+ print(" APIC_BASE: 0x%zux, ", apic_base);
+ if(apic_base & 0x100)
+ print("BSP, ");
+ else
+ print("not BSP, ");
+ if(apic_base & 0x400)
+ print("enable x2APIC mode, ");
+ else
+ print("disable x2APIC mode, ");
+ if(apic_base & 0x800)
+ print("APIC global enable");
+ else
+ print("APIC global disable");
+ print("\n");
+}
+
void
mpinit(void)
{
@@ -130,10 +165,16 @@
Apic *apic;
char *cp;
+print("mpinit\n");
+ showglobalconfig();
i8259init();
+print("mpinit i8259init\n");
syncclock();
+print("mpinit after syncclock getconf(*apicdebug) %s\n", getconf("*apicdebug"));
- if(getconf("*apicdebug")){
+/* system trap handlers work here, interrupt vectors are working? */
+
+ if(getconf("*apicdebug") || 1){
Bus *b;
Aintr *ai;
PCMPintr *pi;
@@ -156,6 +197,7 @@
}
}
}
+print("mpinit after apicdebug\n");
apic = nil;
for(i=0; i<=MaxAPICNO; i++){
@@ -174,6 +216,8 @@
apic->online = 1;
lapicinit(apic);
+print("mpinit after lapicinit\n");
+lapicerror(nil,nil);
/*
* These interrupts are local to the processor
@@ -184,6 +228,8 @@
intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror");
intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious");
lapiconline();
+print("mpinit after lapiconline\n");
+lapicerror(nil,nil);
/*
* Initialise the application processors.
@@ -200,6 +246,10 @@
if(sizeof(apbootstrap) > 4*KiB)
print("mpinit: sizeof(apbootstrap) 0x%x > 4*KiB -- fix it\n", sizeof(apbootstrap));
memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap));
+for(i=0;i<sizeof(apbootstrap);i++){
+ print(" %x", *((uchar*)APBOOTSTRAP+i));
+}
+print("\n");
for(i=0; i<nelem(mpapic); i++){
if((apic = mpapic[i]) == nil)
continue;
@@ -213,6 +263,7 @@
ncpu--;
}
}
+print("mpinit after mpstartap\n");
/*
* we don't really know the number of processors till
--- a/os/pc/mp.h
+++ b/os/pc/mp.h
@@ -12,6 +12,8 @@
uchar reserved[3];
} _MP_;
+#define _MP_sz (4+4+1+1+1+1+1+3)
+
typedef struct { /* configuration table header */
uchar signature[4]; /* "PCMP" */
ushort length; /* total table length */
@@ -27,6 +29,8 @@
uchar reserved;
} PCMP;
+#define PCMPsz (4+2+1+1+20+4+2+2+4+2+1+1)
+
typedef struct { /* processor table entry */
uchar type; /* entry type (0) */
uchar apicno; /* local APIC id */
@@ -37,6 +41,8 @@
uchar reserved[8];
} PCMPprocessor;
+#define PCMPprocessorsz (1+1+1+1+4+4+8)
+
typedef struct { /* bus table entry */
uchar type; /* entry type (1) */
uchar busno; /* bus id */
@@ -43,6 +49,8 @@
char string[6]; /* bus type string */
} PCMPbus;
+#define PCMPbussz (1+1+6)
+
typedef struct { /* I/O APIC table entry */
uchar type; /* entry type (2) */
uchar apicno; /* I/O APIC id */
@@ -51,6 +59,8 @@
ulong addr; /* I/O APIC address */
} PCMPioapic;
+#define PCMPioapicsz (1+1+1+1+4)
+
typedef struct { /* interrupt table entry */
uchar type; /* entry type ([34]) */
uchar intr; /* interrupt type */
@@ -61,6 +71,8 @@
uchar intin; /* destination APIC [L]INTIN# */
} PCMPintr;
+#define PCMPintrsz (1+1+2+1+1+1+1)
+
typedef struct { /* system address space mapping entry */
uchar type; /* entry type (128) */
uchar length; /* of this entry (20) */
@@ -70,6 +82,8 @@
ulong addrlength[2];
} PCMPsasm;
+#define PCMPsasmsz (1+1+1+1+8+8)
+
typedef struct { /* bus hierarchy descriptor entry */
uchar type; /* entry type (129) */
uchar length; /* of this entry (8) */
@@ -79,6 +93,8 @@
uchar reserved[3];
} PCMPhierarchy;
+#define PCMPhirarchysz (1+1+1+1+1+3)
+
typedef struct { /* compatibility bus address space modifier entry */
uchar type; /* entry type (130) */
uchar length; /* of this entry (8) */
@@ -87,6 +103,8 @@
ulong range; /* predefined range list */
} PCMPcbasm;
+#define PCMPcbasmsz (1+1+1+1+4)
+
enum { /* table entry types */
PcmpPROCESSOR = 0x00, /* one entry per processor */
PcmpBUS = 0x01, /* one entry per bus */
@@ -150,6 +168,7 @@
typedef struct Aintr {
PCMPintr* intr;
Apic* apic;
+ Bus* bus;
Aintr* next;
};
@@ -157,17 +176,21 @@
int type;
int apicno;
ulong* addr; /* register base address */
+ ulong paddr;
int flags; /* PcmpBP|PcmpEN */
Lock; /* I/O APIC: register access */
int mre; /* I/O APIC: maximum redirection entry */
+ int gsibase; /* I/O APIC: global system interrupt base (acpi) */
int lintr[2]; /* Local APIC */
int machno;
+
+ int online;
} Apic;
enum {
- MaxAPICNO = 31,
+ MaxAPICNO = 254, /* 255 is physical broadcast */
};
enum { /* I/O APIC registers */
@@ -206,20 +229,34 @@
ApicIMASK = 0x00010000, /* [16] Interrupt Mask */
};
+extern void ioapicinit(Apic*, int);
extern void ioapicrdtr(Apic*, int, int*, int*);
extern void ioapicrdtw(Apic*, int, int, int);
-extern void ioapicinit(Apic*, int);
-extern void lapiconline(void);
-extern void lapicinit(Apic*);
-extern void lapicstartap(Apic*, int);
+
+extern void lapicclock(Ureg*, void*);
+extern int lapiceoi(int);
extern void lapicerror(Ureg*, void*);
-extern void lapicspurious(Ureg*, void*);
+extern void lapicicrw(ulong, ulong);
+extern void lapicinit(Apic*);
+extern int lapicintroff(int);
+extern int lapicintron(Vctl*);
extern int lapicisr(int);
-extern int lapiceoi(int);
-extern void lapicicrw(int, int);
+extern void lapicnmidisable(void);
+extern void lapicnmienable(void);
+extern void lapiconline(void);
+extern void lapicspurious(Ureg*, void*);
+extern void lapicstartap(Apic*, int);
+extern void lapictimerset(uvlong);
+extern int mpintrinit(Bus*, PCMPintr*, int, int);
extern void mpinit(void);
+extern int mpintrassign(Vctl*);
extern void mpshutdown(void);
-extern int mpintrenable(Vctl*);
+extern void mpstartap(Apic*);
-extern _MP_ *_mp_;
+extern Bus* mpbus;
+extern Bus* mpbuslast;
+extern int mpisabus;
+extern int mpeisabus;
+extern Apic *mpioapic[];
+extern Apic *mpapic[];
--- a/os/pc64/apbootstrap.s
+++ b/os/pc64/apbootstrap.s
@@ -130,6 +130,27 @@
PUSHQ AX /* clear flags */
POPFQ
+/*_idle1:
+MOVL $0xB8000, AX
+MOVB $0x41, BX
+MOVB BX, (AX)
+MOVL $0xB8001, AX
+MOVB $15, BX
+MOVB BX, (AX)
+MOVL $0xB8002, AX
+MOVB $0x41, BX
+MOVB BX, (AX)
+MOVL $0xB8003, AX
+MOVB $15, BX
+MOVB BX, (AX)
+MOVL $0xB8004, AX
+MOVB $0x41, BX
+MOVB BX, (AX)
+MOVL $0xB8005, AX
+MOVB $15, BX
+MOVB BX, (AX)
+ JMP _idle1*/
+
MOVQ _apvector(SB), AX
MOVQ _apapic(SB), RARG
PUSHQ RARG
--- a/os/pc64/apic.c
+++ /dev/null
@@ -1,448 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "mp.h"
-
-enum { /* Local APIC registers */
- LapicID = 0x0020, /* ID */
- LapicVER = 0x0030, /* Version */
- LapicTPR = 0x0080, /* Task Priority */
- LapicAPR = 0x0090, /* Arbitration Priority */
- LapicPPR = 0x00A0, /* Processor Priority */
- LapicEOI = 0x00B0, /* EOI */
- LapicLDR = 0x00D0, /* Logical Destination */
- LapicDFR = 0x00E0, /* Destination Format */
- LapicSVR = 0x00F0, /* Spurious Interrupt Vector */
- LapicISR = 0x0100, /* Interrupt Status (8 registers) */
- LapicTMR = 0x0180, /* Trigger Mode (8 registers) */
- LapicIRR = 0x0200, /* Interrupt Request (8 registers) */
- LapicESR = 0x0280, /* Error Status */
- LapicICRLO = 0x0300, /* Interrupt Command */
- LapicICRHI = 0x0310, /* Interrupt Command [63:32] */
- LapicTIMER = 0x0320, /* Local Vector Table 0 (TIMER) */
- LapicPCINT = 0x0340, /* Performance Counter LVT */
- LapicLINT0 = 0x0350, /* Local Vector Table 1 (LINT0) */
- LapicLINT1 = 0x0360, /* Local Vector Table 2 (LINT1) */
- LapicERROR = 0x0370, /* Local Vector Table 3 (ERROR) */
- LapicTICR = 0x0380, /* Timer Initial Count */
- LapicTCCR = 0x0390, /* Timer Current Count */
- LapicTDCR = 0x03E0, /* Timer Divide Configuration */
-};
-
-enum { /* LapicSVR */
- LapicENABLE = 0x00000100, /* Unit Enable */
- LapicFOCUS = 0x00000200, /* Focus Processor Checking Disable */
-};
-
-enum { /* LapicICRLO */
- /* [14] IPI Trigger Mode Level (RW) */
- LapicDEASSERT = 0x00000000, /* Deassert level-sensitive interrupt */
- LapicASSERT = 0x00004000, /* Assert level-sensitive interrupt */
-
- /* [17:16] Remote Read Status */
- LapicINVALID = 0x00000000, /* Invalid */
- LapicWAIT = 0x00010000, /* In-Progress */
- LapicVALID = 0x00020000, /* Valid */
-
- /* [19:18] Destination Shorthand */
- LapicFIELD = 0x00000000, /* No shorthand */
- LapicSELF = 0x00040000, /* Self is single destination */
- LapicALLINC = 0x00080000, /* All including self */
- LapicALLEXC = 0x000C0000, /* All Excluding self */
-};
-
-enum { /* LapicESR */
- LapicSENDCS = 0x00000001, /* Send CS Error */
- LapicRCVCS = 0x00000002, /* Receive CS Error */
- LapicSENDACCEPT = 0x00000004, /* Send Accept Error */
- LapicRCVACCEPT = 0x00000008, /* Receive Accept Error */
- LapicSENDVECTOR = 0x00000020, /* Send Illegal Vector */
- LapicRCVVECTOR = 0x00000040, /* Receive Illegal Vector */
- LapicREGISTER = 0x00000080, /* Illegal Register Address */
-};
-
-enum { /* LapicTIMER */
- /* [17] Timer Mode (RW) */
- LapicONESHOT = 0x00000000, /* One-shot */
- LapicPERIODIC = 0x00020000, /* Periodic */
-
- /* [19:18] Timer Base (RW) */
- LapicCLKIN = 0x00000000, /* use CLKIN as input */
- LapicTMBASE = 0x00040000, /* use TMBASE */
- LapicDIVIDER = 0x00080000, /* use output of the divider */
-};
-
-static uchar lapictdxtab[] = { /* LapicTDCR */
- 0x0B, /* divide by 1 */
- 0x00, /* divide by 2 */
- 0x01, /* divide by 4 */
- 0x02, /* divide by 8 */
- 0x03, /* divide by 16 */
- 0x08, /* divide by 32 */
- 0x09, /* divide by 64 */
- 0x0A, /* divide by 128 */
-};
-
-static ulong* lapicbase;
-
-typedef struct Apictimer Apictimer;
-struct Apictimer
-{
- uvlong hz;
- ulong max;
- ulong min;
- ulong div;
- int tdx;
-};
-
-static Apictimer lapictimer[MAXMACH];
-
-static ulong
-lapicr(int r)
-{
- return *(lapicbase+(r/sizeof(*lapicbase)));
-}
-
-static void
-lapicw(int r, ulong data)
-{
- *(lapicbase+(r/sizeof(*lapicbase))) = data;
- data = *(lapicbase+(LapicID/sizeof(*lapicbase)));
- USED(data);
-}
-
-void
-lapiconline(void)
-{
- Apictimer *a;
-
- a = &lapictimer[m->machno];
-
- /*
- * Reload the timer to de-synchronise the processors,
- * then lower the task priority to allow interrupts to be
- * accepted by the APIC.
- */
- microdelay((TK2MS(1)*1000/conf.nmach) * m->machno);
- lapicw(LapicTICR, a->max);
- lapicw(LapicTIMER, LapicCLKIN|LapicPERIODIC|(VectorPIC+IrqTIMER));
-
- /*
- * not strickly neccesary, but reported (osdev.org) to be
- * required for some machines.
- */
- lapicw(LapicTDCR, lapictdxtab[a->tdx]);
-
- lapicw(LapicTPR, 0);
-}
-
-/*
- * use the i8253/tsc clock to figure out our lapic timer rate.
- */
-static void
-lapictimerinit(void)
-{
- uvlong x, v, hz;
- Apictimer *a;
- int s;
-
- if(m->machno != 0){
- lapictimer[m->machno] = lapictimer[0];
- return;
- }
-
- s = splhi();
- a = &lapictimer[m->machno];
- a->tdx = 0;
-Retry:
- lapicw(LapicTIMER, ApicIMASK|LapicCLKIN|LapicONESHOT|(VectorPIC+IrqTIMER));
- lapicw(LapicTDCR, lapictdxtab[a->tdx]);
-
- x = fastticks(&hz);
- x += hz/10;
- lapicw(LapicTICR, 0xffffffff);
- do{
- v = fastticks(nil);
- }while(v < x);
-
- v = (0xffffffffUL-lapicr(LapicTCCR))*10;
- if(v > hz-(hz/10)){
- if(v > hz+(hz/10) && a->tdx < nelem(lapictdxtab)-1){
- a->tdx++;
- goto Retry;
- }
- v = hz;
- }
-
- assert(v >= (100*HZ));
-
- a->hz = v;
- a->div = hz/a->hz;
- a->max = a->hz/HZ;
- a->min = a->hz/(100*HZ);
-
- splx(s);
-
- v = (v+500000LL)/1000000LL;
- print("cpu%d: lapic clock at %lludMHz\n", m->machno, v);
-}
-
-void
-lapicinit(Apic* apic)
-{
- ulong dfr, ldr, lvt;
-
- if(lapicbase == 0)
- lapicbase = apic->addr;
-
- /*
- * These don't really matter in Physical mode;
- * set the defaults anyway.
- */
- if(strncmp(m->cpuidid, "AuthenticAMD", 12) == 0)
- dfr = 0xf0000000;
- else
- dfr = 0xffffffff;
- ldr = 0x00000000;
-
- lapicw(LapicDFR, dfr);
- lapicw(LapicLDR, ldr);
- lapicw(LapicTPR, 0xff);
- lapicw(LapicSVR, LapicENABLE|(VectorPIC+IrqSPURIOUS));
-
- lapictimerinit();
-
- /*
- * Some Pentium revisions have a bug whereby spurious
- * interrupts are generated in the through-local mode.
- */
- switch(m->cpuidax & 0xFFF){
- case 0x526: /* stepping cB1 */
- case 0x52B: /* stepping E0 */
- case 0x52C: /* stepping cC0 */
- wrmsr(0x0E, 1<<14); /* TR12 */
- break;
- }
-
- /*
- * Set the local interrupts. It's likely these should just be
- * masked off for SMP mode as some Pentium Pros have problems if
- * LINT[01] are set to ExtINT.
- * Acknowledge any outstanding interrupts.
- lapicw(LapicLINT0, apic->lintr[0]);
- lapicw(LapicLINT1, apic->lintr[1]);
- */
- lapiceoi(0);
-
- lvt = (lapicr(LapicVER)>>16) & 0xFF;
- if(lvt >= 4)
- lapicw(LapicPCINT, ApicIMASK);
- lapicw(LapicERROR, VectorPIC+IrqERROR);
- lapicw(LapicESR, 0);
- lapicr(LapicESR);
-
- /*
- * Issue an INIT Level De-Assert to synchronise arbitration ID's.
- */
- lapicw(LapicICRHI, 0);
- lapicw(LapicICRLO, LapicALLINC|ApicLEVEL|LapicDEASSERT|ApicINIT);
- while(lapicr(LapicICRLO) & ApicDELIVS)
- ;
-
- /*
- * Do not allow acceptance of interrupts until all initialisation
- * for this processor is done. For the bootstrap processor this can be
- * early duing initialisation. For the application processors this should
- * be after the bootstrap processor has lowered priority and is accepting
- * interrupts.
- lapicw(LapicTPR, 0);
- */
-}
-
-void
-lapicstartap(Apic* apic, int v)
-{
- int i;
- ulong crhi;
-
- /* make apic's processor do a warm reset */
- crhi = apic->apicno<<24;
- lapicw(LapicICRHI, crhi);
- lapicw(LapicICRLO, LapicFIELD|ApicLEVEL|LapicASSERT|ApicINIT);
- microdelay(200);
- lapicw(LapicICRLO, LapicFIELD|ApicLEVEL|LapicDEASSERT|ApicINIT);
- delay(10);
-
- /* assumes apic is not an 82489dx */
- for(i = 0; i < 2; i++){
- lapicw(LapicICRHI, crhi);
- /* make apic's processor start at v in real mode */
- lapicw(LapicICRLO, LapicFIELD|ApicEDGE|ApicSTARTUP|(v/BY2PG));
- microdelay(200);
- }
-}
-
-void
-lapicerror(Ureg*, void*)
-{
- ulong esr;
-
- lapicw(LapicESR, 0);
- esr = lapicr(LapicESR);
- switch(m->cpuidax & 0xFFF){
- case 0x526: /* stepping cB1 */
- case 0x52B: /* stepping E0 */
- case 0x52C: /* stepping cC0 */
- return;
- }
- print("cpu%d: lapicerror: 0x%8.8luX\n", m->machno, esr);
-}
-
-void
-lapicspurious(Ureg*, void*)
-{
- print("cpu%d: lapicspurious\n", m->machno);
-}
-
-int
-lapicisr(int v)
-{
- ulong isr;
-
- isr = lapicr(LapicISR + (v/32));
-
- return isr & (1<<(v%32));
-}
-
-int
-lapiceoi(int v)
-{
- lapicw(LapicEOI, 0);
-
- return v;
-}
-
-void
-lapicicrw(ulong hi, ulong lo)
-{
- lapicw(LapicICRHI, hi);
- lapicw(LapicICRLO, lo);
-}
-
-void
-ioapicrdtr(Apic* apic, int sel, int* hi, int* lo)
-{
- ulong *iowin;
-
- iowin = apic->addr+(0x10/sizeof(ulong));
- sel = IoapicRDT + 2*sel;
-
- lock(apic);
- *apic->addr = sel+1;
- if(hi)
- *hi = *iowin;
- *apic->addr = sel;
- if(lo)
- *lo = *iowin;
- unlock(apic);
-}
-
-void
-ioapicrdtw(Apic* apic, int sel, int hi, int lo)
-{
- ulong *iowin;
-
- iowin = apic->addr+(0x10/sizeof(ulong));
- sel = IoapicRDT + 2*sel;
-
- lock(apic);
- *apic->addr = sel+1;
- *iowin = hi;
- *apic->addr = sel;
- *iowin = lo;
- unlock(apic);
-}
-
-void
-ioapicinit(Apic* apic, int apicno)
-{
- int hi, lo, v;
- ulong *iowin;
-
- /*
- * Initialise the I/O APIC.
- * The MultiProcessor Specification says it is the responsibility
- * of the O/S to set the APIC id.
- * Make sure interrupts are all masked off for now.
- */
- iowin = apic->addr+(0x10/sizeof(ulong));
- lock(apic);
- *apic->addr = IoapicVER;
- apic->mre = (*iowin>>16) & 0xFF;
-
- *apic->addr = IoapicID;
- *iowin = apicno<<24;
- unlock(apic);
-
- hi = 0;
- lo = ApicIMASK;
- for(v = 0; v <= apic->mre; v++)
- ioapicrdtw(apic, v, hi, lo);
-}
-
-void
-lapictimerset(uvlong next)
-{
- vlong period;
- Apictimer *a;
-
- a = &lapictimer[m->machno];
- period = next - fastticks(nil);
- period /= a->div;
- if(period < a->min)
- period = a->min;
- else if(period > a->max - a->min)
- period = a->max;
- lapicw(LapicTICR, period);
-}
-
-void
-lapicclock(Ureg *u, void*)
-{
- /*
- * since the MTRR updates need to be synchronized across processors,
- * we want to do this within the clock tick.
- */
- mtrrclock();
- timerintr(u, 0);
-}
-
-int
-lapicintron(Vctl*)
-{
- lapicw(LapicTPR, 0);
- return 0;
-}
-
-int
-lapicintroff(int)
-{
- lapicw(LapicTPR, 0xFF);
- return 0;
-}
-
-void
-lapicnmienable(void)
-{
- lapicw(LapicPCINT, ApicNMI);
-}
-
-void
-lapicnmidisable(void)
-{
- lapicw(LapicPCINT, ApicIMASK);
-}
--- a/os/pc64/archmp.c
+++ /dev/null
@@ -1,435 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/pci.h"
-
-#include "mp.h"
-
-static PCMP *pcmp;
-
-static char* buses[] = {
- "CBUSI ",
- "CBUSII",
- "EISA ",
- "FUTURE",
- "INTERN",
- "ISA ",
- "MBI ",
- "MBII ",
- "MCA ",
- "MPI ",
- "MPSA ",
- "NUBUS ",
- "PCI ",
- "PCMCIA",
- "TC ",
- "VL ",
- "VME ",
- "XPRESS",
- 0,
-};
-
-static Bus*
-mpgetbus(int busno)
-{
- Bus *bus;
-
- for(bus = mpbus; bus; bus = bus->next)
- if(bus->busno == busno)
- return bus;
-
- print("mpgetbus: can't find bus %d\n", busno);
- return 0;
-}
-
-static Apic*
-mkprocessor(PCMPprocessor* p)
-{
- static int machno = 1;
- int apicno;
- Apic *apic;
-
- apicno = p->apicno;
- if(!(p->flags & PcmpEN) || apicno > MaxAPICNO || mpapic[apicno] != nil)
- return 0;
-
- if((apic = xalloc(sizeof(Apic))) == nil)
- panic("mkprocessor: no memory for Apic");
- apic->type = PcmpPROCESSOR;
- apic->apicno = apicno;
- apic->flags = p->flags;
- apic->lintr[0] = ApicIMASK;
- apic->lintr[1] = ApicIMASK;
- if(p->flags & PcmpBP)
- apic->machno = 0;
- else
- apic->machno = machno++;
- mpapic[apicno] = apic;
-
- return apic;
-}
-
-static Bus*
-mkbus(PCMPbus* p)
-{
- Bus *bus;
- int i;
-
- for(i = 0; buses[i]; i++)
- if(strncmp(buses[i], p->string, sizeof(p->string)) == 0)
- break;
- if(buses[i] == 0)
- return 0;
-
- if((bus = xalloc(sizeof(Bus))) == nil)
- panic("mkbus: no memory for Bus");
- if(mpbus)
- mpbuslast->next = bus;
- else
- mpbus = bus;
- mpbuslast = bus;
-
- bus->type = i;
- bus->busno = p->busno;
- if(bus->type == BusEISA){
- bus->po = PcmpLOW;
- bus->el = PcmpLEVEL;
- if(mpeisabus != -1)
- print("mkbus: more than one EISA bus\n");
- mpeisabus = bus->busno;
- }
- else if(bus->type == BusPCI){
- bus->po = PcmpLOW;
- bus->el = PcmpLEVEL;
- }
- else if(bus->type == BusISA){
- bus->po = PcmpHIGH;
- bus->el = PcmpEDGE;
- if(mpisabus != -1)
- print("mkbus: more than one ISA bus\n");
- mpisabus = bus->busno;
- }
- else{
- bus->po = PcmpHIGH;
- bus->el = PcmpEDGE;
- }
-
- return bus;
-}
-
-static Apic*
-mkioapic(PCMPioapic* p)
-{
- void *va;
- int apicno;
- Apic *apic;
-
- apicno = p->apicno;
- if(!(p->flags & PcmpEN) || apicno > MaxAPICNO || mpioapic[apicno] != nil)
- return 0;
- /*
- * Map the I/O APIC.
- */
- if((va = vmap(p->addr, 1024)) == nil)
- return 0;
- if((apic = xalloc(sizeof(Apic))) == nil)
- panic("mkioapic: no memory for Apic");
- apic->type = PcmpIOAPIC;
- apic->apicno = apicno;
- apic->addr = va;
- apic->paddr = p->addr;
- apic->flags = p->flags;
- mpioapic[apicno] = apic;
-
- return apic;
-}
-
-static Aintr*
-mkiointr(PCMPintr* p)
-{
- Bus *bus;
- Aintr *aintr;
- PCMPintr* pcmpintr;
-
- /*
- * According to the MultiProcessor Specification, a destination
- * I/O APIC of 0xFF means the signal is routed to all I/O APICs.
- * It's unclear how that can possibly be correct so treat it as
- * an error for now.
- */
- if(p->apicno > MaxAPICNO || mpioapic[p->apicno] == nil)
- return 0;
-
- if((bus = mpgetbus(p->busno)) == 0)
- return 0;
-
- if((aintr = xalloc(sizeof(Aintr))) == nil)
- panic("mkiointr: no memory for Aintr");
- aintr->intr = p;
-
- if(0)
- print("mkiointr: type %d intr type %d flags %#o "
- "bus %d irq %d apicno %d intin %d\n",
- p->type, p->intr, p->flags,
- p->busno, p->irq, p->apicno, p->intin);
- /*
- * Hack for Intel SR1520ML motherboard, which BIOS describes
- * the i82575 dual ethernet controllers incorrectly.
- */
- if(memcmp(pcmp->product, "INTEL X38MLST ", 20) == 0){
- if(p->busno == 1 && p->intin == 16 && p->irq == 1){
- if((pcmpintr = xalloc(sizeof(PCMPintr))) == nil)
- panic("iointr: no memory for PCMPintr");
- memmove(pcmpintr, p, sizeof(PCMPintr));
- print("mkiointr: %20.20s bus %d intin %d irq %d\n",
- (char*)pcmp->product,
- pcmpintr->busno, pcmpintr->intin,
- pcmpintr->irq);
- pcmpintr->intin = 17;
- aintr->intr = pcmpintr;
- }
- }
- aintr->apic = mpioapic[p->apicno];
- aintr->next = bus->aintr;
- aintr->bus = bus;
- bus->aintr = aintr;
-
- return aintr;
-}
-
-static int
-mklintr(PCMPintr* p)
-{
- Apic *apic;
- Bus *bus;
- int i, intin, v;
-
- /*
- * The offsets of vectors for LINT[01] are known to be
- * 0 and 1 from the local APIC vector space at VectorLAPIC.
- */
- if((bus = mpgetbus(p->busno)) == 0)
- return 0;
- intin = p->intin;
-
- /*
- * Pentium Pros have problems if LINT[01] are set to ExtINT
- * so just bag it, SMP mode shouldn't need ExtINT anyway.
- */
- if(p->intr == PcmpExtINT || p->intr == PcmpNMI)
- v = ApicIMASK;
- else
- v = mpintrinit(bus, p, VectorLAPIC+intin, p->irq);
-
- if(p->apicno == 0xFF){
- for(i=0; i<=MaxAPICNO; i++){
- if((apic = mpapic[i]) == nil)
- continue;
- if(apic->flags & PcmpEN)
- apic->lintr[intin] = v;
- }
- }
- else{
- if(apic = mpapic[p->apicno])
- if(apic->flags & PcmpEN)
- apic->lintr[intin] = v;
- }
-
- return v;
-}
-
-static void
-dumpmp(uchar *p, uchar *e)
-{
- int i;
-
- for(i = 0; p < e; p++) {
- if((i % 16) == 0) print("*mp%d=", i/16);
- print("%.2x ", *p);
- if((++i % 16) == 0) print("\n");
- }
- if((i % 16) != 0) print("\n");
-}
-
-
-static void
-mpoverride(uchar** newp, uchar** e)
-{
- int size, i, j;
- char buf[20];
- uchar* p;
- char* s;
-
- size = strtol(getconf("*mp"), 0, 0);
- if(size <= 0) panic("mpoverride: invalid size in *mp");
- *newp = p = xalloc(size);
- if(p == nil) panic("mpoverride: can't allocate memory");
- *e = p + size;
- for(i = 0; ; i++){
- snprint(buf, sizeof buf, "*mp%d", i);
- s = getconf(buf);
- if(s == nil) break;
- while(*s){
- j = strtol(s, &s, 16);
- if(*s && *s != ' ' || j < 0 || j > 0xff) panic("mpoverride: invalid entry in %s", buf);
- if(p >= *e) panic("mpoverride: overflow in %s", buf);
- *p++ = j;
- }
- }
- if(p != *e) panic("mpoverride: size doesn't match");
-}
-
-static void
-pcmpinit(void)
-{
- uchar *p, *e;
- Apic *apic;
- void *va;
-
- /*
- * Map the local APIC.
- */
- va = vmap(pcmp->lapicbase, 1024);
-
- print("LAPIC: %.8lux %#p\n", pcmp->lapicbase, va);
- if(va == nil)
- panic("pcmpinit: cannot map lapic %.8lux", pcmp->lapicbase);
-
- p = ((uchar*)pcmp)+PCMPsz;
- e = ((uchar*)pcmp)+pcmp->length;
- if(getconf("*dumpmp") != nil)
- dumpmp(p, e);
- if(getconf("*mp") != nil)
- mpoverride(&p, &e);
-
- /*
- * Run through the table saving information needed for starting
- * application processors and initialising any I/O APICs. The table
- * is guaranteed to be in order such that only one pass is necessary.
- */
- while(p < e) switch(*p){
- default:
- print("pcmpinit: unknown PCMP type 0x%uX (e-p 0x%zuX)\n",
- *p, e-p);
- while(p < e){
- print("%uX ", *p);
- p++;
- }
- break;
-
- case PcmpPROCESSOR:
- if(apic = mkprocessor((PCMPprocessor*)p)){
- apic->addr = va;
- apic->paddr = pcmp->lapicbase;
- }
- p += PCMPprocessorsz;
- continue;
-
- case PcmpBUS:
- mkbus((PCMPbus*)p);
- p += PCMPbussz;
- continue;
-
- case PcmpIOAPIC:
- if(apic = mkioapic((PCMPioapic*)p))
- ioapicinit(apic, apic->apicno);
- p += PCMPioapicsz;
- continue;
-
- case PcmpIOINTR:
- mkiointr((PCMPintr*)p);
- p += PCMPintrsz;
- continue;
-
- case PcmpLINTR:
- mklintr((PCMPintr*)p);
- p += PCMPintrsz;
- continue;
- }
-
- /*
- * Ininitalize local APIC and start application processors.
- */
- mpinit();
-}
-
-static void
-mpreset(void)
-{
- /* stop application processors */
- mpshutdown();
-
- /* do generic reset */
- archreset();
-}
-
-static int identify(void);
-extern int i8259irqno(int, int);
-
-PCArch archmp = {
-.id= "_MP_",
-.ident= identify,
-.reset= mpreset,
-.intrinit= pcmpinit,
-.intrassign= mpintrassign,
-.intrirqno= i8259irqno,
-.intrenable= lapicintron,
-.intrdisable= lapicintroff,
-.fastclock= i8253read,
-.timerset= lapictimerset,
-};
-
-static int
-identify(void)
-{
- char *cp;
- _MP_ *_mp_;
- ulong pa, len;
-
- if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
- return 1;
-
- /*
- * Search for an MP configuration table. For now,
- * don't accept the default configurations (physaddr == 0).
- * Check for correct signature, calculate the checksum and,
- * if correct, check the version.
- * To do: check extended table checksum.
- */
- if((_mp_ = sigsearch("_MP_", _MP_sz)) == nil || _mp_->physaddr == 0)
- return 1;
-
- len = PCMPsz;
- pa = _mp_->physaddr;
- if(pa + len-1 < pa)
- return 1;
-
- memreserve(pa, len);
- if((pcmp = vmap(pa, len)) == nil)
- return 1;
- if(pcmp->length < PCMPsz
- || pa + pcmp->length-1 < pa
- || memcmp(pcmp, "PCMP", 4) != 0
- || (pcmp->version != 1 && pcmp->version != 4)){
-Bad:
- vunmap(pcmp, len);
- pcmp = nil;
- return 1;
- }
- len = pcmp->length;
- memreserve(pa, len);
- vunmap(pcmp, PCMPsz);
- if((pcmp = vmap(pa, len)) == nil)
- return 1;
-
- if(checksum(pcmp, len) != 0)
- goto Bad;
-
- if(m->havetsc && getconf("*notsc") == nil)
- archmp.fastclock = tscticks;
-
- return 0;
-}
--- a/os/pc64/dat.h
+++ b/os/pc64/dat.h
@@ -110,7 +110,7 @@
struct Confmem
{
uintptr base;
- u32 npage;
+ uintptr npage;
};
struct Conf
@@ -119,11 +119,11 @@
u32 nproc; /* processes */
u32 monitor; /* has monitor? */
Confmem mem[16]; /* physical memory */
- u32 npage; /* total physical pages of memory */
- u32 nswap; /* number of swap pages */
+ uintptr npage; /* total physical pages of memory */
+ uintptr nswap; /* number of swap pages */
u32 copymode; /* 0 is copy on write, 1 is copy on reference */
- u32 ialloc; /* max interrupt time allocation in bytes */
- u32 pipeqsize; /* size in bytes of pipe queues */
+ uintptr ialloc; /* max interrupt time allocation in bytes */
+ uintptr pipeqsize; /* size in bytes of pipe queues */
u32 nuart; /* number of uart devices */
};
--- a/os/pc64/fns.h
+++ b/os/pc64/fns.h
@@ -175,6 +175,7 @@
s32 rdmsr(s32, s64*);
ulong rdtsc32(void);
void rdrandbuf(void*, u32);
+u64 rflags(void);
void* rsdsearch(void);
void screeninit(void);
int screenprint(char*, ...); /* debugging */
--- a/os/pc64/l.s
+++ b/os/pc64/l.s
@@ -115,6 +115,17 @@
#define PDO(v) ((PTLX((v), 1))<<3)
#define PTO(v) ((PTLX((v), 0))<<3)
+/* code for debugging
+ writes a single A at the left top of the screen
+_idle1:
+MOVL $0xB8000, AX
+MOVB $0x41, BX
+MOVB BX, (AX)
+MOVL $0xB8001, AX
+MOVB $15, BX
+MOVB BX, (AX)
+ JMP _idle1
+*/
TEXT _warp64<>(SB), 1, $-4
/* clear global data tables - IDT, GDT, Page tables, Mach */
@@ -549,6 +560,11 @@
PUSHFQ
POPQ AX
ANDQ $0x200, AX /* 0x200 - Interrupt Flag */
+ RET
+
+TEXT rflags(SB), 1, $-4
+ PUSHFQ
+ POPQ AX
RET
/*
--- a/os/pc64/main.c
+++ b/os/pc64/main.c
@@ -25,6 +25,9 @@
char bootdisk[KNAMELEN];
+/* until I sort out the mp initialization issue */
+extern void startaps(void);
+
static void
doc(char *m)
{
@@ -147,6 +150,7 @@
meminit(); /* builds the conf.mem entries */
doc("confinit");
confinit();
+ doc("xinit");
xinit();
/* TODO 9front does this for dma
if(i8237alloc != nil)
@@ -160,10 +164,13 @@
cpuidprint();
doc("mmuinit");
mmuinit(); /* builds the page tables, lgdt, lidt */
- print("poolsizeinit\n");
+ memmapdump();
+ doc("poolsizeinit");
poolsizeinit();
memmapdump();
+ doc("eve inferno");
eve = strdup("inferno");
+ doc("arch->intrinit");
if(arch->intrinit){ /* launches other processors on an mp */
doc("intrinit");
arch->intrinit();
@@ -320,20 +327,20 @@
pcnt = 70;
conf.ialloc = (((conf.npage*(100-pcnt))/100)/2)*BY2PG;
conf.nproc = 100 + ((conf.npage*BY2PG)/MiB)*5;
- print("conf.npage %d conf.ialloc %ud conf.nproc %d\n",
+ print("conf.npage %zd conf.ialloc %zud conf.nproc %d\n",
conf.npage, conf.ialloc, conf.nproc);
+ USED(maxmem);
}
void
poolsizeinit(void)
{
- u64 nb;
-
- nb = conf.npage*BY2PG;
- print("poolsizeinit nb 0x%zx conf.npage %d\n", nb, conf.npage);
- poolsize(mainmem, (nb*main_pool_pcnt)/100, 0);
- poolsize(heapmem, (nb*heap_pool_pcnt)/100, 0);
- poolsize(imagmem, (nb*image_pool_pcnt)/100, 1);
+ print("poolsizeinit conf.npage %zd\n", conf.npage);
+ poolsize(mainmem, ((conf.npage*main_pool_pcnt)/100)*BY2PG, 0);
+ poolsize(heapmem, ((conf.npage*heap_pool_pcnt)/100)*BY2PG, 0);
+ /* TODO causes a double fault now. needs to be fixed
+ poolsize(imagmem, ((conf.npage*image_pool_pcnt)/100)*BY2PG, 1); */
+ print("after poolsizeinit\n");
}
/*
--- a/os/pc64/memory.c
+++ b/os/pc64/memory.c
@@ -37,6 +37,7 @@
/* no need to add page tables with pmap() here as
* mmuinit() has done it for us
+ * use xspanalloc() if xlists are built
*/
if(conf.mem[0].npage != 0)
return xspanalloc(BY2PG, BY2PG, 0);
@@ -728,6 +729,7 @@
{
uintptr base, size;
Confmem *cm;
+ int i;
umbexclude();
for(base = memmapnext(-1, MemUMB); base != -1; base = memmapnext(base, MemUMB)){
@@ -736,26 +738,38 @@
mapkzero(PGROUND(base), size, MemUMB);
}
+ memmapdump();
cm = &conf.mem[0];
for(base = memmapnext(-1, MemRAM); base != -1; base = memmapnext(base, MemRAM)){
size = memmapsize(base, BY2PG) & ~(BY2PG-1);
+ print("memmapnext() base 0x%zx size 0x%zux %zud\n", base, size, size);
if(size == 0)
continue;
if(cm >= &conf.mem[nelem(conf.mem)]){
- print("meminit: out of entries, loosing: %#p (%llud)\n", base, (uvlong)size);
+ print("meminit: out of entries, loosing: 0x%#p (%zud)\n", (void *)base, size);
continue;
}
if(base < MemMin){
- print("meminit: ignoring RAM below MemMin base 0x%p size 0x%zd\n", base, size);
+ print("meminit: ignoring RAM below MemMin 0x%p base 0x%p size 0x%zd\n",
+ MemMin, (void *)base, size);
continue;
}
- cm->base = memmapalloc(base, size, BY2PG, MemRAM);
- if(cm->base == -1)
+ base = memmapalloc(base, size, BY2PG, MemRAM);
+ print("memmapalloc() base 0x%zx\n", base);
+ if(base == -1){
+ print("base == -1\n");
continue;
- base = cm->base;
+ }
+ cm->base = base;
cm->npage = size/BY2PG;
+ print(" cm->base 0x%zx cm->npage 0x%zux %zud\n", cm->base, cm->npage, cm->npage);
cm++;
}
+ print("meminit: conf.mem entries\n");
+ for(i = 0; i < nelem(conf.mem); i++)
+ print("%d base 0x%zx 0x%zp npage 0x%zx %zd\n",
+ i, conf.mem[i].base, conf.mem[i].base,
+ conf.mem[i].npage, conf.mem[i].npage);
memmapdump();
// showpagetables((uintptr*)PML4ADDR);
--- a/os/pc64/mkfile
+++ b/os/pc64/mkfile
@@ -69,7 +69,7 @@
cp i$CONF $INSTALLDIR/i$CONF
# copies generated by the rule below
-PCHEADERS=usbehci.h ahci.h yukdump.h vga.h audio.h
+PCHEADERS=usbehci.h mp.h ahci.h yukdump.h vga.h audio.h
REPCH=`{echo $PCHEADERS | sed 's/\.h//g; s/ /|/g'}
^($REPCH)\.h:R: ../pc/\1.h
--- a/os/pc64/mmu.c
+++ b/os/pc64/mmu.c
@@ -141,7 +141,7 @@
cm = &conf.mem[i];
if(cm->npage == 0)
continue;
- DP("i %d base 0x%p npage 0x%d\n", i, cm->base, cm->npage);
+ DP("i %d base 0x%zx npage 0x%zx %zd\n", i, cm->base, cm->npage, cm->npage);
pmap(cm->base, PTEGLOBAL|PTEWRITE|PTENOEXEC|PTEVALID, cm->npage*BY2PG);
}
}
@@ -280,11 +280,11 @@
s32 z, l;
if(size <= 0)
- panic("pmap: pa=%#p size=%lld", pa, size);
- DP("pmap pa 0x%p-0x%zux flags 0x%llux size %llud 0x%llux\n",
+ panic("pmap: pa=%#zux size=%lld", pa, size);
+ print("pmap pa 0x%zux-0x%zux flags 0x%llux size %llud 0x%llux\n",
pa, (uintptr)pa+size, flags, size, size);
pa = PPN(pa);
- DP("\tpa 0x%p\n", pa);
+ DP("\tpa 0x%zux\n", pa);
while(size > 0){
/* reducing complexity, use 4096 byte pages all through */
l = 0;
--- a/os/pc64/pc64
+++ b/os/pc64/pc64
@@ -126,10 +126,9 @@
#wminit
code
- int kernel_pool_pcnt = 10;
- int main_pool_pcnt = 40;
+ int main_pool_pcnt = 50;
int heap_pool_pcnt = 20;
- int image_pool_pcnt = 40;
+ int image_pool_pcnt = 20;
int cflag=0;
int swcursor=0;
int consoleprint=1;
--- a/os/pc64/squidboy.c
+++ b/os/pc64/squidboy.c
@@ -13,6 +13,7 @@
static void
squidboy(Apic* apic)
{
+print("starting squidboy\n");
machinit();
mmuinit();
cpuidentify();
@@ -20,7 +21,7 @@
arch->clockinit();
cpuidprint();
syncclock();
- /* active.machs[m->machno] = 1; */
+ active.machs[m->machno] = 1;
apic->online = 1;
lapicinit(apic);
lapiconline();
@@ -32,27 +33,28 @@
void
mpstartap(Apic* apic)
{
- uintptr *apbootp, *pml4, *pdp0;
+ uintptr *apbootp, *pml4/*, *pdp0*/;
Segdesc *gdt;
Mach *mach;
uchar *p, *q;
int i;
+print("mpstartap apic->machno %d: \n", apic->machno);
/*
* 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);
+ p = xspanalloc(1*PTSZ + BY2PG + MACHSIZE, BY2PG, 0);
pml4 = (uintptr*)p;
p += PTSZ;
- pdp0 = (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(pdp0, 0, PTSZ);*/
memset(gdt, 0, BY2PG);
memset(mach, 0, MACHSIZE);
@@ -62,15 +64,15 @@
MACHP(mach->machno) = mach;
/*
- * map KZERO (note that we share the KZERO
- * PDP between processors.
+ * share the page tables across all processors except for pml4
+ * they should be static at this point
*/
- pml4[PTLX(KZERO, 3)] = MACHP(0)->pml4[PTLX(KZERO, 3)];
+ for(i=0; i<BY2PG/8; i+=8){
+ pml4[i] = MACHP(0)->pml4[i];
+if(pml4[i] != 0)
+print("mpstartap i %d pml4[i] 0x%p MACHP(0)->pml4[i] 0x%p\n", i, pml4[i], MACHP(0)->pml4[i]);
+ }
- /* 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.
@@ -81,6 +83,10 @@
apbootp[2] = (uintptr)apic;
apbootp[3] = (uintptr)mach;
apbootp[4] |= (uintptr)m->havenx<<11; /* EFER */
+for(i=0;i<80;i++){
+ print(" %x", *((uchar*)APBOOTSTRAP+i));
+}
+print("\n");
/*
* Universal Startup Algorithm.
@@ -91,19 +97,28 @@
i = (PADDR(APBOOTSTRAP) & ~0xFFFF)/16;
/* code assumes i==0 */
if(i != 0)
- print("mp: bad APBOOTSTRAP\n");
+ print("mp: bad APBOOTSTRAP i 0x%ux\n", i);
*p++ = i;
*p = i>>8;
+ print("p 0x%p PADDR(APBOOTSTRAP) 0x%p (PADDR(APBOOTSTRAP) & ~0xFFFF)/16 0x%p\n",
+ p, PADDR(APBOOTSTRAP), (PADDR(APBOOTSTRAP) & ~0xFFFF)/16);
+ for(q = (uchar*)KADDR(0x467); q<=p; q++){
+ print(" q 0x%p *q 0x%x",q, *q);
+ }
+ print("\n");
coherence();
- nvramwrite(0x0F, 0x0A); /* shutdown code: warm reset upon init ipi */
+ 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)
+ if(apic->online){
+print("online\n");
break;
+ }
delay(1);
}
+print("nvramwrite(0x0F, 000)\n");
nvramwrite(0x0F, 0x00);
}
--- a/os/pc64/trap.c
+++ b/os/pc64/trap.c
@@ -365,9 +365,9 @@
/* clear the interrupt */
i8259isr(vno);
- if(0)print("cpu%d: spurious interrupt %d, last %d",
+ if(1)print("cpu%d: spurious interrupt %d, last %d",
m->machno, vno, m->lastintr);
- if(0)if(conf.nmach > 1){
+ if(1)if(conf.nmach > 1){
for(i = 0; i < MAXMACH; i++){
if(active.machs[i] == 0)
continue;
--- a/os/port/alloc.c
+++ b/os/port/alloc.c
@@ -444,7 +444,7 @@
void *nv;
intptr osize;
- //if(size >= 1024*1024*1024) /* for sanity and to avoid overflow */
+ // if(size >= 1024*1024*1024) /* for sanity and to avoid overflow */
// return nil;
if(size == 0){
poolfree(p, v);
@@ -907,10 +907,13 @@
p->ressize = max-RESERVED;
if (contig && max > 0) {
p->chunk = max-1024;
+ print("poolsize: poolalloc() contig chunk 0x%zx %zd\n", p->chunk, p->chunk);
x = poolalloc(p, p->chunk);
if(x == nil)
panic("poolsize: don't have %d bytes\n", p->chunk);
+ print("poolsize: before poolfree()\n");
poolfree(p, x);
+ print("poolsize: after poolfree()\n");
p->hw = 0;
}
}
--- a/os/port/memmap.c
+++ b/os/port/memmap.c
@@ -181,7 +181,7 @@
print("----------------------\n");
}
-uvlong
+uintptr
memmapnext(uintptr addr, u32 type)
{
Mapent *i, *e;
@@ -200,7 +200,7 @@
return -1;
}
-uvlong
+uintptr
memmapsize(uintptr addr, uintptr align)
{
Mapent *i;
--- a/os/port/xalloc.c
+++ b/os/port/xalloc.c
@@ -36,7 +36,7 @@
{
Lock;
Hole hole[Nhole];
- Hole* flist;
+ Hole* flist; /* front of list */
Hole* table;
};
@@ -237,7 +237,7 @@
print("%lld holes free\n", i);
i = 0;
- for(h = xlists.table; h; h = h->link) {
+ for(h = xlists.table; h; h = h->link){
print("%.8zux %.8zux %zud\n", h->addr, h->top, h->size);
i += h->size;
}