|
|
|
1999/0218/sys/src/9/pc/archgeneric.c:1,236 –
1999/0820/sys/src/9/pc/archgeneric.c:0
(short | long | prev)
|
Deleted.
rsc Mon Mar 7 10:28:56 2005
|
|
1992/0923
| |
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
|
|
1997/0327
| |
static int
unimplemented(int)
{
return 0;
}
|
|
1992/0923
| |
static void
|
|
1997/0327
| |
nop(void)
|
|
1992/0923
| |
{
}
|
|
1997/0327
| |
void (*coherence)(void) = nop;
|
|
1998/0710
| |
void cycletimerinit(void);
uvlong cycletimer(uvlong*);
|
|
1997/0327
| |
PCArch* arch;
extern PCArch* knownarch[];
PCArch archgeneric = {
"generic", /* id */
0, /* ident */
i8042reset, /* reset */
unimplemented, /* serialpower */
unimplemented, /* modempower */
i8259init, /* intrinit */
i8259enable, /* intrenable */
i8253enable, /* clockenable */
|
|
1998/0710
| |
i8253read, /* read the standard timer */
|
|
1997/0327
| |
};
typedef struct {
int family;
int model;
int aalcycles;
char* name;
} X86type;
|
|
1998/0522
| |
static X86type x86intel[] =
|
|
1992/0923
| |
{
|
|
1997/0327
| |
{ 4, 0, 22, "486DX", }, /* known chips */
{ 4, 1, 22, "486DX50", },
{ 4, 2, 22, "486SX", },
{ 4, 3, 22, "486DX2", },
{ 4, 4, 22, "486SL", },
{ 4, 5, 22, "486SX2", },
{ 4, 7, 22, "DX2WB", }, /* P24D */
|
|
1997/0407
| |
{ 4, 8, 22, "DX4", }, /* P24C */
{ 4, 9, 22, "DX4WB", }, /* P24CT */
|
|
1997/0327
| |
{ 5, 0, 23, "P5", },
{ 5, 1, 23, "P5", },
{ 5, 2, 23, "P54C", },
|
|
1997/0407
| |
{ 5, 3, 23, "P24T", },
{ 5, 4, 23, "P55C MMX", },
|
|
1997/0404
| |
{ 5, 7, 23, "P54C VRT", },
|
|
1997/0327
| |
{ 6, 1, 16, "PentiumPro", },/* determined by trial and error */
|
|
1998/0906
| |
{ 6, 3, 16, "PentiumII", },
{ 6, 5, 16, "PentiumII/Xeon", },
|
|
1997/0327
| |
{ 3, -1, 32, "386", }, /* family defaults */
{ 4, -1, 22, "486", },
|
|
1998/0906
| |
{ 5, -1, 23, "P5", },
{ 6, -1, 16, "P6", },
|
|
1997/0327
| |
{ -1, -1, 23, "unknown", }, /* total default */
|
|
1992/0923
| |
};
|
|
1997/0327
| |
|
|
1998/0522
| |
/*
* The AMD processors all implement the CPUID instruction.
* The later ones also return the processor name via functions
* 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX
* and DX:
* K5 "AMD-K5(tm) Processor"
* K6 "AMD-K6tm w/ multimedia extensions"
* K6 3D "AMD-K6(tm) 3D processor"
* K6 3D+ ?
*/
static X86type x86amd[] =
{
{ 5, 0, 23, "AMD-K5", }, /* guesswork */
{ 5, 1, 23, "AMD-K5", }, /* guesswork */
{ 5, 2, 23, "AMD-K5", }, /* guesswork */
{ 5, 3, 23, "AMD-K5", }, /* guesswork */
|
|
1998/0702
| |
{ 5, 6, 11, "AMD-K6", }, /* determined by trial and error */
{ 5, 7, 11, "AMD-K6", }, /* determined by trial and error */
|
|
1998/1222
| |
{ 5, 8, 11, "AMD-K6 3D", }, /* guesswork */
{ 5, 9, 11, "AMD-K6 3D+", },/* guesswork */
|
|
1998/0522
| |
{ 4, -1, 22, "Am486", }, /* guesswork */
{ 5, -1, 23, "AMD-K5/K6", }, /* guesswork */
{ -1, -1, 23, "unknown", }, /* total default */
};
|
|
1997/0327
| |
void
cpuidprint(void)
{
int i;
char buf[128];
i = sprint(buf, "cpu%d: %dMHz ", m->machno, m->cpumhz);
if(m->cpuidid[0])
i += sprint(buf+i, "%s ", m->cpuidid);
|
|
1998/0825
| |
sprint(buf+i, "%s (cpuid: AX 0x%4.4uX DX 0x%4.4uX)\n",
|
|
1997/0327
| |
m->cpuidtype, m->cpuidax, m->cpuiddx);
print(buf);
}
int
cpuidentify(void)
{
int family, model;
X86type *t;
|
|
1998/0401
| |
ulong cr4;
vlong mct;
|
|
1997/0327
| |
cpuid(m->cpuidid, &m->cpuidax, &m->cpuiddx);
|
|
1998/0522
| |
if(strncmp(m->cpuidid, "AuthenticAMD", 12) == 0)
t = x86amd;
else
t = x86intel;
|
|
1997/0327
| |
family = X86FAMILY(m->cpuidax);
model = X86MODEL(m->cpuidax);
|
|
1998/0522
| |
while(t->name){
|
|
1997/0327
| |
if((t->family == family && t->model == model)
|| (t->family == family && t->model == -1)
|| (t->family == -1))
break;
|
|
1998/0522
| |
t++;
|
|
1997/0327
| |
}
m->cpuidtype = t->name;
|
|
1999/0131
| |
i8253init(t->aalcycles, t->family >= 5);
|
|
1997/0327
| |
/*
* If machine check exception or page size extensions are supported
* enable them in CR4 and clear any other set extensions.
* If machine check was enabled clear out any lingering status.
*/
if(m->cpuiddx & 0x88){
cr4 = 0;
if(m->cpuiddx & 0x08)
cr4 |= 0x10; /* page size extensions */
if(m->cpuiddx & 0x80)
cr4 |= 0x40; /* machine check enable */
putcr4(cr4);
if(m->cpuiddx & 0x80)
|
|
1998/0401
| |
rdmsr(0x01, &mct);
|
|
1997/0327
| |
}
return t->family;
}
void
archinit(void)
{
PCArch **p;
arch = 0;
for(p = knownarch; *p; p++){
if((*p)->ident && (*p)->ident() == 0){
arch = *p;
break;
}
}
if(arch == 0)
arch = &archgeneric;
else{
if(arch->id == 0)
arch->id = archgeneric.id;
if(arch->reset == 0)
arch->reset = archgeneric.reset;
if(arch->serialpower == 0)
arch->serialpower = archgeneric.serialpower;
if(arch->modempower == 0)
arch->modempower = archgeneric.modempower;
if(arch->intrinit == 0)
arch->intrinit = archgeneric.intrinit;
if(arch->intrenable == 0)
arch->intrenable = archgeneric.intrenable;
}
|
|
1998/0710
| |
/* pick the better timer */
if(X86FAMILY(m->cpuidax) >= 5){
cycletimerinit();
arch->fastclock = cycletimer;
}
|
|
1997/0327
| |
/*
* Decide whether to use copy-on-reference (386 and mp).
*/
if(X86FAMILY(m->cpuidax) == 3 || conf.nmach > 1)
conf.copymode = 1;
|
|
1999/0112
| |
if(X86FAMILY(m->cpuidax) >= 5)
|
|
1997/0327
| |
coherence = wbflush;
|
|
1998/0710
| |
}
|
|
1999/0130
| |
static uvlong fasthz;
|
|
1998/0710
| |
void
cycletimerinit(void)
{
|
|
1998/0716
| |
wrmsr(0x10, 0);
|
|
1999/0218
| |
fasthz = m->cpuhz;
|
|
1998/0710
| |
}
/*
|
|
1998/1106
| |
* return the most precise clock we have
|
|
1998/0710
| |
*/
uvlong
cycletimer(uvlong *hz)
{
uvlong tsc;
rdmsr(0x10, (vlong*)&tsc);
|
|
1998/0717
| |
m->fastclock = tsc;
|
|
1998/0710
| |
if(hz != nil)
*hz = fasthz;
return tsc;
|
|
1999/0130
| |
}
vlong
fastticks(uvlong *hz)
{
return (*arch->fastclock)(hz);
|
|
1997/0327
| |
}
|