plan9fox/sys/src/9/ppc/main.c
cinap_lenrek e4ce6aadac kernel: handle tos and per process pcycle counters in port/
we might as well handle the per process cycle
counter in the portable part instead of duplicating the code
in every arch and have inconsistent implementations.

we now have a portable kenter() and kexit() function,
that is ment to be used in trap/syscall from user,
which updates the counters.

some kernels missed initializing Mach.cyclefreq.
2020-12-20 22:34:41 +01:00

373 lines
6.6 KiB
C

#include "u.h"
#include "tos.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "pool.h"
#define MAXCONF 64
typedef struct Plan9ini Plan9ini;
struct Plan9ini
{
char *name;
char *val;
};
char *plan9inistr;
Plan9ini plan9ini[MAXCONF];
int nconf;
Conf conf;
FPsave initfp;
Lock testlock;
static void plan9iniinit(void);
char *
cpuid(void)
{
char *id;
id = "unknown PowerPC";
switch(m->cputype) {
case 8:
id = "PowerPC 750";
break;
case 9:
id = "PowerPC 604e";
break;
case 0x81:
id = "PowerPC 8260";
break;
case 0x8081:
id = "PowerPC 826xA";
break;
default:
break;
}
return id;
}
void
cpuidprint(void)
{
print("cpu0: %s, rev 0x%lux, cpu hz %lld, bus hz %ld\n",
cpuid(), getpvr()&0xffff, m->cpuhz, m->bushz);
}
void
main(void)
{
memset(edata, 0, (ulong)end-(ulong)edata);
conf.nmach = 1;
machinit();
confinit();
xinit();
trapinit();
mmuinit();
plan9iniinit();
hwintrinit();
clockinit();
timerinit();
console();
quotefmtinstall();
printinit();
cpuidprint();
print("\nPlan 9 from Bell Labs\n");
procinit0();
initseg();
timersinit();
links();
chandevreset();
pageinit();
sharedseginit();
fpsave(&initfp);
initfp.fpscr = 0;
userinit();
schedinit();
}
char*
getconf(char *name)
{
int i;
for(i = 0; i < nconf; i++)
if(cistrcmp(name, plan9ini[i].name) == 0)
return plan9ini[i].val;
return nil;
}
static void
plan9iniinit(void)
{
long i;
int c;
char *cp, line[MAXCONF], *p, *q;
/*
* parse configuration args from dos file plan9.ini
*/
cp = plan9inistr;
for(i = 0; i < MAXCONF; i++){
/*
* Strip out '\r', change '\t' -> ' ', test for 0xff which is end of file
*/
p = line;
for(q = cp; c = (uchar)*q; q++){
if(c == '\r')
continue;
if(c == '\t')
c = ' ';
if(c == 0xff || c == '\n')
break;
*p++ = c;
}
*p = 0;
if (*line == 0)
break;
if(*line != '#' && (cp = strchr(line, '='))){
*cp++ = '\0';
kstrdup(&plan9ini[nconf].name, line);
kstrdup(&plan9ini[nconf].val, cp);
nconf++;
}
if (c == 0xff)
break;
cp = q + 1;
}
}
void
init0(void)
{
char buf[2*KNAMELEN];
int i;
chandevinit();
if(!waserror()){
snprint(buf, sizeof(buf), "power %s mtx", conffile);
ksetenv("terminal", buf, 0);
ksetenv("cputype", "power", 0);
if(cpuserver)
ksetenv("service", "cpu", 0);
else
ksetenv("service", "terminal", 0);
for(i = 0; i < nconf; i++){
if(plan9ini[i].name[0] != '*')
ksetenv(plan9ini[i].name, plan9ini[i].val, 0);
ksetenv(plan9ini[i].name, plan9ini[i].val, 1);
}
poperror();
}
kproc("alarm", alarmkproc, 0);
kproc("mmusweep", mmusweep, 0);
touser((void*)(USTKTOP - sizeof(Tos)));
}
void
exit(int)
{
cpushutdown();
for(;;) idlehands();
}
/*
* set up floating point for a new process
*/
void
procsetup(Proc *p)
{
p->fpstate = FPinit;
}
void
procfork(Proc *p)
{
}
void
procrestore(Proc *p)
{
}
/*
* Save the mach dependent part of the process state.
*/
void
procsave(Proc *p)
{
if(p->fpstate == FPactive){
if(p->state != Moribund)
fpsave(up->fpsave);
p->fpstate = FPinactive;
}
}
void
confinit(void)
{
char *p;
int userpcnt;
ulong pa, kpages;
/* passed in from ROM monitor: */
if(p = getconf("service")){
if(strcmp(p, "cpu") == 0)
cpuserver = 1;
else if(strcmp(p,"terminal") == 0)
cpuserver = 0;
}
if(p = getconf("*kernelpercent"))
userpcnt = 100 - strtol(p, 0, 0);
else
userpcnt = 0;
pa = PGROUND(PADDR(end));
/* Blast Board specific */
conf.mem[0].npage = (MEM1SIZE - pa)/BY2PG;
conf.mem[0].base = pa;
conf.mem[1].npage = MEM2SIZE/BY2PG;
conf.mem[1].base = MEM2BASE;
conf.npage = conf.mem[0].npage + conf.mem[1].npage;
conf.nmach = 1;
conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
if(cpuserver)
conf.nproc *= 3;
if(conf.nproc > 2000)
conf.nproc = 2000;
conf.nimage = 200;
conf.nswap = conf.nproc*80;
conf.nswppo = 4096;
conf.copymode = 0; /* copy on write */
if(cpuserver) {
if(userpcnt < 10)
userpcnt = 70;
kpages = conf.npage - (conf.npage*userpcnt)/100;
/*
* Hack for the big boys. Only good while physmem < 4GB.
* Give the kernel a max. of 16MB + enough to allocate the
* page pool.
* This is an overestimate as conf.upages < conf.npages.
* The patch of nimage is a band-aid, scanning the whole
* page list in imagereclaim just takes too long.
*/
if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
conf.nimage = 2000;
kpages += (conf.nproc*KSTACK)/BY2PG;
}
} else {
if(userpcnt < 10) {
if(conf.npage*BY2PG < 16*MB)
userpcnt = 40;
else
userpcnt = 60;
}
kpages = conf.npage - (conf.npage*userpcnt)/100;
/*
* Make sure terminals with low memory get at least
* 4MB on the first Image chunk allocation.
*/
if(conf.npage*BY2PG < 16*MB)
imagmem->minarena = 4*1024*1024;
}
conf.upages = conf.npage - kpages;
conf.ialloc = (kpages/2)*BY2PG;
/*
* Guess how much is taken by the large permanent
* datastructures. Mntcache and Mntrpc are not accounted for.
*/
kpages *= BY2PG;
kpages -= conf.upages*sizeof(Page)
+ conf.nproc*sizeof(Proc)
+ conf.nimage*sizeof(Image)
+ conf.nswap
+ conf.nswppo*sizeof(Page*);
mainmem->maxsize = kpages;
if(!cpuserver){
/*
* give terminals lots of image memory, too; the dynamic
* allocation will balance the load properly, hopefully.
* be careful with 32-bit overflow.
*/
imagmem->maxsize = kpages;
}
}
static int
getcfields(char* lp, char** fields, int n, char* sep)
{
int i;
for(i = 0; lp && *lp && i < n; i++){
while(*lp && strchr(sep, *lp) != 0)
*lp++ = 0;
if(*lp == 0)
break;
fields[i] = lp;
while(*lp && strchr(sep, *lp) == 0){
if(*lp == '\\' && *(lp+1) == '\n')
*lp++ = ' ';
lp++;
}
}
return i;
}
int
isaconfig(char *class, int ctlrno, ISAConf *isa)
{
int i;
char cc[KNAMELEN], *p;
sprint(cc, "%s%d", class, ctlrno);
p = getconf(cc);
if(p == 0)
return 0;
isa->nopt = tokenize(p, isa->opt, NISAOPT);
for(i = 0; i < isa->nopt; i++){
p = isa->opt[i];
if(cistrncmp(p, "type=", 5) == 0)
isa->type = p + 5;
else if(cistrncmp(p, "port=", 5) == 0)
isa->port = strtoul(p+5, &p, 0);
else if(cistrncmp(p, "irq=", 4) == 0)
isa->irq = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "dma=", 4) == 0)
isa->dma = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "mem=", 4) == 0)
isa->mem = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "size=", 5) == 0)
isa->size = strtoul(p+5, &p, 0);
else if(cistrncmp(p, "freq=", 5) == 0)
isa->freq = strtoul(p+5, &p, 0);
}
return 1;
}
void
setupwatchpts(Proc *, Watchpt *, int n)
{
if(n > 0)
error("no watchpoints");
}