#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"
#include "../ip/ip.h"
#include <../port/error.h>
static FPsave initfp;
/*
* software tlb simulation
*/
static Softtlb stlb[MAXMACH][STLBSIZE];
Conf conf;
char*
getconf(char *name)
{
return (char*)arcs(0x78, name);
}
static void
fmtinit(void)
{
printinit();
quotefmtinstall();
/* ipreset installs these when chandevreset runs */
fmtinstall('i', eipfmt);
fmtinstall('I', eipfmt);
fmtinstall('E', eipfmt);
fmtinstall('V', eipfmt);
fmtinstall('M', eipfmt);
}
static int
ckpagemask(ulong mask, ulong size)
{
int s;
ulong pm;
s = splhi();
setpagemask(mask);
pm = getpagemask();
splx(s);
if(pm != mask){
iprint("page size %ldK not supported on this cpu; "
"mask %#lux read back as %#lux\n", size/1024, mask, pm);
return -1;
}
return 0;
}
void
addmem(uintptr base, uintptr top)
{
uintptr s, e;
ulong *m;
int i;
if(base >= top)
return;
/* exclude kernel */
s = 0;
e = PADDR(PGROUND((uintptr)end));
if(s < top && e > base){
if(s > base)
addmem(base, s);
if(e < top)
addmem(e, top);
return;
}
/* exclude reserved firmware memory regions */
m = nil;
while((m = (ulong*)arcs(0x48, m)) != nil){
s = m[1]<<12;
e = s + (m[2]<<12);
switch(m[0]){
case 2: /* FreeMemory */
case 3: /* BadMemory */
continue;
}
if(s < top && e > base){
if(s > base)
addmem(base, s);
if(e < top)
addmem(e, top);
return;
}
}
for(i=0; i<nelem(conf.mem); i++){
if(conf.mem[i].npage == 0){
conf.mem[i].base = base;
conf.mem[i].npage = (top - base)/BY2PG;
conf.npage += conf.mem[i].npage;
return;
}
}
print("conf.mem[] too small\n");
}
/*
* get memory configuration word for a bank
*/
ulong
bank_conf(int bank)
{
switch(bank){
case 0:
return *(ulong *)(KSEG1|MEMCFG0) >> 16;
case 1:
return *(ulong *)(KSEG1|MEMCFG0) & 0xffff;
case 2:
return *(ulong *)(KSEG1|MEMCFG1) >> 16;
case 3:
return *(ulong *)(KSEG1|MEMCFG1) & 0xffff;
}
return 0;
}
void
meminit(void)
{
uintptr base, size, top;
ulong mconf;
int i;
/*
* divide memory twixt user pages and kernel.
*/
conf.npage = 0;
for(i=0; i<4; i++){
mconf = bank_conf(i);
if(!(mconf & 0x2000))
continue;
base = (mconf & 0xff) << 22;
size = ((mconf & 0x1f00) + 0x0100) << 14;
top = base + size;
addmem(base, top);
}
}
static int
havegfx(void)
{
char *s = getconf("ConsoleOut");
return s != nil && strstr(s, "video()") != nil;
}
void
main(void)
{
savefpregs(&initfp);
arcsconsinit();
meminit();
confinit();
machinit(); /* calls clockinit */
active.exiting = 0;
active.machs[0] = 1;
print("\nPlan 9\n");
kmapinit();
xinit();
timersinit();
fmtinit();
if(havegfx()){
conf.monitor = 1;
screeninit();
}
ckpagemask(PGSZ, BY2PG);
tlbinit();
pageinit();
procinit0();
initseg();
links();
chandevreset();
userinit();
schedinit();
panic("schedinit returned");
}
/*
* initialize a processor's mach structure. each processor does this
* for itself.
*/
void
machinit(void)
{
extern void gevector(void); /* l.s */
extern void utlbmiss(void);
extern void vector0(void);
extern void vector180(void);
void **sbp = (void*)SPBADDR;
m->stb = stlb[m->machno];
/* install exception handlers */
sbp[0x18/4] = utlbmiss;
sbp[0x14/4] = gevector;
/* we could install our own vectors directly, but we'll try to play nice */
if(0){
memmove((void*)(KSEG0+0x0), (void*)vector0, 0x80);
memmove((void*)(KSEG0+0x180), (void*)vector180, 0x80);
icflush((void*)(KSEG0+0x0), 0x80);
icflush((void*)(KSEG0+0x180), 0x80);
}
/* Ensure CU1 is off */
clrfpintr();
clockinit();
}
void
init0(void)
{
char buf[128], **sp;
chandevinit();
if(!waserror()){
ksetenv("cputype", "mips", 0);
snprint(buf, sizeof buf, "mips %s", conffile);
ksetenv("terminal", buf, 0);
if(cpuserver)
ksetenv("service", "cpu", 0);
else
ksetenv("service", "terminal", 0);
ksetenv("bootargs", "tcp", 0);
ksetenv("console", "0", 0);
/* no usb */
ksetenv("usbwait", "0", 0);
ksetenv("nousbrc", "1", 0);
poperror();
}
/* process input for arcs console */
if(!conf.keyboard)
kproc("arcs", arcsproc, 0);
kproc("alarm", alarmkproc, 0);
sp = (char**)(USTKTOP-sizeof(Tos) - 8 - sizeof(sp[0])*4);
sp[3] = sp[2] = sp[1] = nil;
strcpy(sp[0] = (char*)&sp[4], "boot");
touser(sp);
}
void
exit(int)
{
cpushutdown();
splhi();
arcs(0x18); /* reboot */
}
void
reboot(void *, void *, ulong)
{
}
void
evenaddr(uintptr va)
{
if((va & 3) != 0){
dumpstack();
postnote(up, 1, "sys: odd address", NDebug);
error(Ebadarg);
}
}
void
procsetup(Proc *p)
{
p->fpstate = FPinit;
memmove(p->fpsave, &initfp, sizeof(FPsave));
cycles(&p->kentry);
p->pcycles = -p->kentry;
}
void
procfork(Proc *p)
{
int s;
p->kentry = up->kentry;
p->pcycles = -p->kentry;
s = splhi();
switch(up->fpstate & ~FPillegal){
case FPactive:
savefpregs(up->fpsave);
up->fpstate = FPinactive;
/* wet floor */
case FPinactive:
memmove(p->fpsave, up->fpsave, sizeof(FPsave));
p->fpstate = FPinactive;
}
splx(s);
}
void
procsave(Proc *p)
{
uvlong t;
if(p->fpstate == FPactive){
if(p->state != Moribund) {
savefpregs(p->fpsave);
p->fpstate = FPinactive;
}
}
cycles(&t);
p->pcycles += t;
}
void
procrestore(Proc *p)
{
uvlong t;
if(p->kp)
return;
cycles(&t);
p->pcycles -= t;
}
void
idlehands(void)
{
}
void
confinit(void)
{
ulong kpages;
/*
* set up CPU's mach structure
* cpu0's was zeroed in l.s and our stack is in Mach, so don't zero it.
*/
m->machno = 0;
m->speed = 150; /* initial guess at MHz */
m->hz = m->speed * Mhz;
conf.nmach = 1;
/* set up other configuration parameters */
conf.nproc = 2000;
conf.nswap = 262144;
conf.nswppo = 4096;
conf.nimage = 200;
conf.copymode = 0; /* copy on write */
kpages = conf.npage - (conf.npage*80)/100;
if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
kpages += (conf.nproc*KSTACK)/BY2PG;
}
conf.upages = conf.npage - kpages;
conf.ialloc = (kpages/2)*BY2PG;
kpages *= BY2PG;
kpages -= conf.upages*sizeof(Page)
+ conf.nproc*sizeof(Proc)
+ conf.nimage*sizeof(Image)
+ conf.nswap
+ conf.nswppo*sizeof(Page*);
mainmem->maxsize = kpages;
imagmem->maxsize = kpages;
// mainmem->flags |= POOL_PARANOIA;
}
void
setupwatchpts(Proc *, Watchpt *, int n)
{
if(n > 0)
error("no watchpoints");
}
int
isaconfig(char *, int, ISAConf*)
{
return 0;
}