code: 9ferno

Download patch

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;
 	}