~kris/9p

9hist

b1ec3ceb0d8ef6460723416c08f4eba8ecd0704f — David du Colombier 31 years ago c1738b3
Plan 9 from Bell Labs 1994-10-31
4 files changed, 115 insertions(+), 66 deletions(-)

M pc/clock.c
M pc/fns.h
M pc/l.s
M pc/main.c
M pc/clock.c => pc/clock.c +106 -52
@@ 29,9 29,8 @@ enum

static int cpufreq = 66000000;
static int cpumhz = 66;
static int cputype = 486;
static int loopconst = 100;
ulong cpuidax, cpuiddx;
static int cpuidax, cpuiddx;

static void
clock(Ureg *ur, void *arg)


@@ 72,6 71,49 @@ clock(Ureg *ur, void *arg)
	mouseclock();
}

#define STEPPING(x)	((x)&0xf)
#define MODEL(x)	(((x)>>4)&0xf)
#define FAMILY(x)	(((x)>>8)&0xf)

enum
{
	/* flags */
	CpuidFPU	= 0x001,	/* on-chip floating point unit */
	CpuidMCE	= 0x080,	/* machine check exception */
	CpuidCX8	= 0x100,	/* CMPXCHG8B instruction */
};

typedef struct
{
	int family;
	int model;
	int aalcycles;
	char *name;
} X86type;

X86type x86type[] =
{
	/* from the cpuid instruction */
	{ 4,	0,	22,	"Intel486DX", },
	{ 4,	1,	22,	"Intel486DX", },
	{ 4,	2,	22,	"Intel486SX", },
	{ 4,	4,	22,	"Intel486DX2", },
	{ 4,	5,	22,	"Intel486SL", },
	{ 4,	8,	22,	"IntelDX4", },
	{ 5,	1,	23,	"Pentium510", },
	{ 5,	2,	23,	"Pentium735", },

	/* family defaults */
	{ 3,	-1,	32,	"Intel386", },
	{ 4,	-1,	22,	"Intel486", },
	{ 5,	-1,	23,	"Pentium", },

	/* total default */
	{ -1,	-1,	23,	"unknown", },
};

static X86type	*cputype;

/*
 *  delay for l milliseconds more or less.  delayloop is set by
 *  clockinit() to match the actual CPU speed.


@@ 89,26 131,18 @@ printcpufreq(void)
		cpufreq, cputype, cpuidax, cpuiddx);
}

int
x86(void)
{
	return cputype->family;
}

void
clockinit(void)
{
	ulong x, y;	/* change in counter */
	ulong cycles, loops;

	switch(cputype = x86()){
	case 386:
		loops = 10000;
		cycles = 32;
		break;
	case 486:
		loops = 10000;
		cycles = 22;
		break;
	default:
		loops = 30000;
		cycles = 23;
		break;
	}
	int x, y;	/* change in counter */
	int family, model, loops;
	X86type *t;

	/*
	 *  set vector for clock interrupts


@@ 116,45 150,65 @@ clockinit(void)
	setvec(Clockvec, clock, 0);

	/*
	 *  figure out what we are
	 */
	x86cpuid(&cpuidax, &cpuiddx);
	family = FAMILY(cpuidax);
	model = MODEL(cpuidax);
	for(t = x86type; t->name; t++)
		if((t->family == family && t->model == model)
		|| (t->family == family && t->model == -1)
		|| (t->family == -1))
			break;
	cputype = t;

	/*
	 *  set clock for 1/HZ seconds
	 */
	outb(Tmode, Load0|Square);
	outb(T0cntr, (Freq/HZ));	/* low byte */
	outb(T0cntr, (Freq/HZ)>>8);	/* high byte */


	/*
	 *  measure time for the loop
	 *
	 *			MOVL	loops,CX
	 *	aaml1:	 	AAM
	 *			LOOP	aaml1
	 *
	 *  the time for the loop should be independent from external
	 *  cache's and memory system since it fits in the execution
	 *  prefetch buffer.
	 *
	 */
	outb(Tmode, Latch0);
	x = inb(T0cntr);
	x |= inb(T0cntr)<<8;
	aamloop(loops);
	outb(Tmode, Latch0);
	y = inb(T0cntr);
	y |= inb(T0cntr)<<8;
	x -= y;

	/*
	 *  counter  goes at twice the frequency, once per transition,
	 *  i.e., twice per square wave
	 */
	x >>= 1;

	/*
 	 *  figure out clock frequency and a loop multiplier for delay().
	 */
	cpufreq = loops*((cycles*Freq)/x);
	loopconst = (cpufreq/1000)/cycles;	/* AAM+LOOP's for 1 ms */
	/* use biggest loop that works */
	for(loops = 10000; ; loops += 5000) {
		/*
		 *  measure time for the loop
		 *
		 *			MOVL	loops,CX
		 *	aaml1:	 	AAM
		 *			LOOP	aaml1
		 *
		 *  the time for the loop should be independent of external
		 *  cache and memory system since it fits in the execution
		 *  prefetch buffer.
		 *
		 */
		outb(Tmode, Latch0);
		x = inb(T0cntr);
		x |= inb(T0cntr)<<8;
		aamloop(loops);
		outb(Tmode, Latch0);
		y = inb(T0cntr);
		y |= inb(T0cntr)<<8;
		x -= y;

		if(x < 0)
			x += 2^16;
		if(x > (2^15))
			break;
	
		/*
		 *  counter  goes at twice the frequency, once per transition,
		 *  i.e., twice per square wave
		 */
		x >>= 1;

		/*
	 	 *  figure out clock frequency and a loop multiplier for delay().
		 */
		cpufreq = loops*((t->aalcycles*Freq)/x);
		loopconst = (cpufreq/1000)/t->aalcycles;	/* AAM+LOOP's for 1 ms */
	} while(x > 0);

	/*
	 *  add in possible .1% error and convert to MHz

M pc/fns.h => pc/fns.h +1 -0
@@ 91,6 91,7 @@ void	vgainit(void);
void	vgasavecrash(uchar*, int);
void	vgarestorecrash(uchar*, int);
int	x86(void);
int	x86cpuid(int*, int*);

#define	waserror()	(up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
#define	kmapperm(x)	kmap(x)

M pc/l.s => pc/l.s +7 -12
@@ 572,7 572,7 @@ TEXT	getstatus(SB),$0
/*
 *  return cpu type (586 == pentium or better)
 */
TEXT	x86(SB),$0
TEXT	x86cpuid(SB),$0

	PUSHFL
	MOVL	0(SP),AX


@@ 591,22 591,17 @@ TEXT	x86(SB),$0
	/* CPUID */
	 BYTE $0x0F
	 BYTE $0xA2

	MOVL	AX, cpuidax(SB)
	MOVL	DX, cpuiddx(SB)

	SHLL	$20,AX
	SHRL	$28,AX
	CMPL	AX, $4
	JEQ	is486
	MOVL	$586,AX
	JMP	done
is486:
	MOVL	$486,AX
	MOVL	$(4<<8),AX
	MOVL	$0,DX
	JMP	done
is386:
	MOVL	$386,AX
	MOVL	$(3<<8),AX
	MOVL	$0,DX
done:
	MOVL	AX, a+0(FP)
	MOVL	DX, d+4(FP)
	POPL	BX
	POPFL
	RET

M pc/main.c => pc/main.c +1 -2
@@ 448,11 448,10 @@ confinit(void)
	conf.nswap = conf.nproc*80;
	conf.nimage = 50;
	switch(x86()){
	case 386:
	case 3:
		conf.copymode = 1;	/* copy on reference */
		break;
	default:
	case 486:
		conf.copymode = 0;	/* copy on write */
		break;
	}