~kris/9p

9hist

2ba50734e9d1b0f44c13acefccd6edab287f15f4 — David du Colombier 27 years ago e34105f
Plan 9 from Bell Labs 1999-04-02
7 files changed, 78 insertions(+), 119 deletions(-)

M carrera/clock.c
M carrera/fns.h
M carrera/mem.h
M pc/devether.c
M pc/ether2114x.c
M pc/mp.c
M port/taslock.c
M carrera/clock.c => carrera/clock.c +10 -60
@@ 18,7 18,8 @@ typedef struct Clock0link {
static Clock0link *clock0link;
static Lock clock0lock;
static ulong		incr;		/* compare register increment */
static uvlong		fasthz;		/* ticks/sec of fast clock */
static ulong		lastcmp;


void
addclock0link(void (*clock)(void))


@@ 51,8 52,6 @@ delay(int l)
			;
}

ulong lastcmp;

void
clockinit(void)
{


@@ 73,23 72,9 @@ clockinit(void)
		m->delayloop = 1;

	incr = (m->speed*1000000)/HZ;
	fasthz = m->speed*1000000;
	wrcompare(lastcmp = rdcount()+incr);
}

uvlong
updatefastclock(ulong count)
{
	ulong delta;

	/* keep track of higher precision time */
	delta = count - m->lastcyclecount;
	m->lastcyclecount = count;
	m->fastclock += delta;

	return m->fastclock;
}

void
clock(Ureg *ur)
{


@@ 97,8 82,11 @@ clock(Ureg *ur)
	ulong count;

	count = rdcount();
	wrcompare(lastcmp = count+incr);
	updatefastclock(count);
	if(lastcmp+incr < count+100)
		lastcmp = count+incr;
	else
		lastcmp += incr;
	wrcompare(lastcmp);

	m->ticks++;
	if(m->proc)


@@ 146,48 134,10 @@ clock(Ureg *ur)
		sched();
}

ulong timewarp;

vlong
fastticks(uvlong *hz)
{
	uvlong cyclecount;
	ulong cnt, d;
	int x;

	x = splhi();
	cnt = rdcount();
	cyclecount = updatefastclock(cnt);
	d = lastcmp - cnt + 100;
	if(d > incr+100){
		wrcompare(lastcmp = cnt+incr);
		timewarp++;
	}
	splx(x);

	if(hz)
		*hz = fasthz;

	return (vlong)cyclecount;
}

void
idlehands(void)
{
#ifdef adsfasdf
	ulong cnt, cmp, d;
	int x;

	x = splhi();
	cnt = rdcount();
	cmp = rdcompare();
	cnt -= 100;		/* to cover for time from splhi to rdcount */
	d = cmp - cnt;
	if(d > incr+100){
		wrcompare(lastcmp = cnt+incr);
		timewarp++;
//		print("%lud %lud %d %lux\n", cnt, cmp, cnt-cmp, d);
	}
	splx(x);
#endif
	if(hz != nil)
		*hz = HZ*100;
	return m->ticks*100;
}

M carrera/fns.h => carrera/fns.h +1 -1
@@ 25,7 25,7 @@ void		gettlb(int, ulong*);
int		gettlbp(ulong, ulong*);
ulong		gettlbvirt(int);
void		icflush(void *, ulong);
void		idlehands(void);
#define		idlehands()
void		intr(Ureg*);
void		ioinit(int);
int		iprint(char*, ...);

M carrera/mem.h => carrera/mem.h +1 -1
@@ 22,7 22,7 @@
/*
 * Time
 */
#define	HZ		500			/* clock frequency */
#define	HZ		1000			/* clock frequency */
#define	MS2HZ		(1000/HZ)		/* millisec per clock tick */
#define	TK2SEC(t)	((t)/HZ)		/* ticks to seconds */
#define	TK2MS(t)	((t)*MS2HZ)		/* ticks to milliseconds */

M pc/devether.c => pc/devether.c +1 -1
@@ 213,7 213,7 @@ etheroq(Ether* ether, Block* bp)
	 * If it's a loopback packet indicate to etheriq that the data isn't
	 * needed and return, etheriq will pass-on or free the block.
	 * To enable bridging to work, only packets that were originated
	 * by this interface are feedback
	 * by this interface are fed back.
	 */
	pkt = (Etherpkt*)bp->rp;
	len = BLEN(bp);

M pc/ether2114x.c => pc/ether2114x.c +6 -5
@@ 827,7 827,8 @@ typephylink(Ctlr* ctlr, uchar*)
		csr6 |= Fd;
	if(ctlr->ttm & x)
		csr6 |= Ttm;
	debug("csr6 0x%2.2uX 0x%2.2uX\n", csr6, ctlr->csr6);
	debug("csr6 0x%8.8uX 0x%8.8uX 0x%8.8luX\n",
		csr6, ctlr->csr6, csr32r(ctlr, 6));
	if(csr6 != ctlr->csr6){
		ctlr->csr6 = csr6;
		csr32w(ctlr, 6, csr6);


@@ 1226,16 1227,16 @@ srom(Ctlr* ctlr)
			p += (*p & ~0x80)+1;
		}
		else{
debug("type0: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
    p[0], p[1], p[2], p[3]); 
			debug("type0: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
				p[0], p[1], p[2], p[3]); 
			if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
				ctlr->sctk = k;
			p += 4;
		}
	}
	ctlr->curk = ctlr->sctk;
debug("sct 0x%uX medium 0x%uX k %d curk %d phy %d\n",
    ctlr->sct, ctlr->medium, ctlr->k, ctlr->curk, phy);
	debug("sct 0x%uX medium 0x%uX k %d curk %d phy %d\n",
		ctlr->sct, ctlr->medium, ctlr->k, ctlr->curk, phy);

	if(phy){
		x = 0;

M pc/mp.c => pc/mp.c +58 -50
@@ 19,6 19,7 @@ static int machno2apicno[MaxAPICNO+1];	/* inverse map: machno -> APIC ID */
static Lock mprdthilock;
static int mprdthi;
static Ref mpvnoref;			/* unique vector assignment */
static Lock mpclocksynclock;

static char* buses[] = {
	"CBUSI ",


@@ 214,13 215,14 @@ mpintrinit(Bus* bus, PCMPintr* intr, int vno, int /*irq*/)
	case PcmpExtINT:
		v |= ApicExtINT;
		/*
		 * The AMI Goliath doesn't boot successfully with it's LINTR0 entry
		 * which decodes to low+level. The PPro manual says ExtINT should be
		 * level, whereas the Pentium is edge. Setting the Goliath to edge+high
		 * seems to cure the problem. Other PPro MP tables (e.g. ASUS P/I-P65UP5
		 * have a entry which decodes to edge+high, so who knows.
		 * Perhaps it would be best just to not set an ExtINT entry at all,
		 * it shouldn't be needed for SMP mode.
		 * The AMI Goliath doesn't boot successfully with it's LINTR0
		 * entry which decodes to low+level. The PPro manual says ExtINT
		 * should be level, whereas the Pentium is edge. Setting the
		 * Goliath to edge+high seems to cure the problem. Other PPro
		 * MP tables (e.g. ASUS P/I-P65UP5 have a entry which decodes
		 * to edge+high, so who knows.
		 * Perhaps it would be best just to not set an ExtINT entry at
		 * all, it shouldn't be needed for SMP mode.
		 */
		po = PcmpHIGH;
		el = PcmpEDGE;


@@ 229,7 231,7 @@ mpintrinit(Bus* bus, PCMPintr* intr, int vno, int /*irq*/)

	/*
	 */
	if(bus->type == BusEISA && !po && !el /*&& !(elcr & (1<<irq))*/){
	if(bus->type == BusEISA && !po && !el /*&& !(i8259elcr & (1<<irq))*/){
		po = PcmpHIGH;
		el = PcmpEDGE;
	}


@@ 280,7 282,8 @@ mklintr(PCMPintr* p)

	if(p->apicno == 0xFF){
		for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){
			if((apic->flags & PcmpEN) && apic->type == PcmpPROCESSOR)
			if((apic->flags & PcmpEN)
			&& apic->type == PcmpPROCESSOR)
				apic->lintr[intin] = v;
		}
	}


@@ 348,8 351,6 @@ checkmtrr(void)
#define PDX(va)		((((ulong)(va))>>22) & 0x03FF)
#define PTX(va)		((((ulong)(va))>>12) & 0x03FF)

Lock clocksynclock;

static void
squidboy(Apic* apic)
{


@@ 371,12 372,12 @@ squidboy(Apic* apic)
	/*
	 * Restrain your octopus! Don't let it go out on the sea!
	 */
	ilock(&clocksynclock);
	ilock(&mpclocksynclock);
	x = MACHP(0)->ticks;
	while(MACHP(0)->ticks == x)
		;
	wrmsr(0x10, MACHP(0)->fastclock); /* synchronize fast counters */
	iunlock(&clocksynclock);
	iunlock(&mpclocksynclock);

	lapicinit(apic);
	lapiconline();


@@ 480,16 481,17 @@ mpinit(void)
	bpapic = 0;

	/*
	 * 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.
	 * 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.
	 */
	p = ((uchar*)pcmp)+sizeof(PCMP);
	e = ((uchar*)pcmp)+pcmp->length;
	while(p < e) switch(*p){

	default:
		print("mpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n", *p, e-p);
		print("mpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n",
			*p, e-p);
		while(p < e){
			print("%uX ", *p);
			p++;


@@ 562,7 564,8 @@ mpinit(void)
	 */
	memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap));
	for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){
		if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN && apic->type == PcmpPROCESSOR)
		if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN
		&& apic->type == PcmpPROCESSOR)
			mpstartap(apic);
	}



@@ 575,7 578,7 @@ mpinit(void)
}

static int
mpintrenablex(Vctl* v)
mpintrenablex(Vctl* v, int tbdf)
{
	Bus *bus;
	Aintr *aintr;


@@ 584,12 587,11 @@ mpintrenablex(Vctl* v)
	int bno, dno, irq, lo, n, type, vno;

	/*
	 * Find the bus, default is ISA.
	 * There cannot be multiple ISA or EISA buses.
	 * Find the bus.
	 */
	type = BUSTYPE(v->tbdf);
	bno = BUSBNO(v->tbdf);
	dno = BUSDNO(v->tbdf);
	type = BUSTYPE(tbdf);
	bno = BUSBNO(tbdf);
	dno = BUSDNO(tbdf);
	n = 0;
	for(bus = mpbus; bus != nil; bus = bus->next){
		if(bus->type != type)


@@ 610,12 612,12 @@ mpintrenablex(Vctl* v)
	 * obtained from the PCI config space.
	 */
	if(bus->type == BusPCI){
		pcidev = pcimatchtbdf(v->tbdf);
		pcidev = pcimatchtbdf(tbdf);
		if(pcidev != nil && (n = pcicfgr8(pcidev, PciINTP)) != 0)
			irq = (dno<<2)|(n-1);
		else
			irq = -1;
		//print("pcidev %uX: irq %uX v->irq %uX\n", v->tbdf, irq, v->irq);
		//print("pcidev %uX: irq %uX v->irq %uX\n", tbdf, irq, v->irq);
	}
	else
		irq = v->irq;


@@ 629,37 631,42 @@ mpintrenablex(Vctl* v)
			continue;

		/*
		 * Check not already enabled. This is a bad thing as it implies the
		 * same device is requesting the same interrupt to be enabled multiple
		 * times. The RDT read here is safe for now as currently interrupts
		 * are never disabled once enabled.
		 * Check not already enabled. This is a bad thing as it implies
		 * the same device is requesting the same interrupt to be
		 * enabled multiple times. The RDT read here is safe for now
		 * as currently interrupts are never disabled once enabled.
		 */
		apic = aintr->apic;
		ioapicrdtr(apic, aintr->intr->intin, 0, &lo);
		if(!(lo & ApicIMASK)){
			print("mpintrenable: multiple enable of irq %d, tbdf %uX\n",
				v->irq, v->tbdf);
			print("mpintrenable: multiple enable irq%d, tbdf %uX\n",
				v->irq, tbdf);
			return -1;
		}

		/*
		 * With the APIC a unique vector can be assigned to each request
		 * to enable an interrupt. There are two reasons this is a good idea:
		 * 1) to prevent lost interrupts, no more than 2 interrupts should
		 *    be assigned per block of 16 vectors (there is an in-service
		 *    entry and a holding entry for each priority level and there is
		 *    a priority level per block of 16 interrupts).
		 * 2) each input pin on the IOAPIC will receive a different vector
		 *    regardless of whether the devices on that pin use the same IRQ
		 *    as devices on another pin.
		 * With the APIC a unique vector can be assigned to each
		 * request to enable an interrupt. There are two reasons this
		 * is a good idea:
		 * 1) to prevent lost interrupts, no more than 2 interrupts
		 *    should be assigned per block of 16 vectors (there is an
		 *    in-service entry and a holding entry for each priority
		 *    level and there is one priority level per block of 16
		 *    interrupts).
		 * 2) each input pin on the IOAPIC will receive a different
		 *    vector regardless of whether the devices on that pin use
		 *    the same IRQ as devices on another pin.
		 */
		vno = VectorAPIC + (incref(&mpvnoref)-1)*8;
		if(vno > MaxVectorAPIC){
			print("mpintrenable: vno %d, irq %d, tbdf %uX\n",
				vno, v->irq, v->tbdf);
				vno, v->irq, tbdf);
			return -1;
		}
		lo = mpintrinit(bus, aintr->intr, vno, v->irq);
		//print("lo 0x%uX: busno %d intr %d vno %d irq %d elcr 0x%uX\n",
		//	lo, bus->busno, aintr->intr->irq, vno,
		//	v->irq, i8259elcr);
		if(lo & ApicIMASK)
			return -1;
		lo |= ApicLOGICAL;


@@ 669,6 676,9 @@ mpintrenablex(Vctl* v)
 			ioapicrdtw(apic, aintr->intr->intin, mprdthi, lo);
			unlock(&mprdthilock);
		}
		//else
		//	print("lo not enabled 0x%uX %d\n",
		//		apic->flags, apic->type);

		v->isr = lapicisr;
		v->eoi = lapiceoi;


@@ 691,7 701,7 @@ mpintrenable(Vctl* v)
	 * breakpoint and page-fault).
	 */
	tbdf = v->tbdf;
	if(tbdf != BUSUNKNOWN && (vno = mpintrenablex(v)) != -1)
	if(tbdf != BUSUNKNOWN && (vno = mpintrenablex(v, tbdf)) != -1)
		return vno;

	irq = v->irq;


@@ 716,15 726,13 @@ mpintrenable(Vctl* v)
	 * polarity set to 'default for this bus' which wouldn't
	 * be compatible with ISA.
	 */
	if(mpisabus != -1){
		v->tbdf = MKBUS(BusISA, 0, 0, 0);
		vno = mpintrenablex(v);
	if(mpeisabus != -1){
		vno = mpintrenablex(v, MKBUS(BusEISA, 0, 0, 0));
		if(vno != -1)
			return vno;
	}
	if(mpeisabus != -1){
		v->tbdf = MKBUS(BusEISA, 0, 0, 0);
		vno = mpintrenablex(v);
	if(mpisabus != -1){
		vno = mpintrenablex(v, MKBUS(BusISA, 0, 0, 0));
		if(vno != -1)
			return vno;
	}


@@ 767,7 775,7 @@ mpshutdown(void)
	 * warm-boot sequence is tried. The following is Intel specific and
	 * seems to perform a cold-boot, but at least it comes back.
	 */
	*(ushort*)KADDR(0x472) = 0x1234;		/* BIOS warm-boot flag */
	*(ushort*)KADDR(0x472) = 0x1234;	/* BIOS warm-boot flag */
	outb(0xCF9, 0x02);
	outb(0xCF9, 0x06);
#else

M port/taslock.c => port/taslock.c +1 -1
@@ 110,7 110,7 @@ lockstats.glare++;
	} else
		oldpri = 0;
	if(conf.nmach < 2)
		panic("ilock: no way out: pc %uX held by %uX\n", pc, l->pc);
		panic("ilock: no way out: pc %uX\n", pc);

	for(;;){
lockstats.inglare++;