plan9fox/sys/src/9/zynq/main.c
2018-06-14 21:54:42 +02:00

411 lines
6.5 KiB
C

#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "init.h"
#include "pool.h"
#include "io.h"
#include "../port/error.h"
#include "tos.h"
Conf conf;
int normalprint, delaylink;
enum { MAXCONF = 64 };
char *confname[MAXCONF], *confval[MAXCONF];
int nconf;
void
exit(int)
{
cpushutdown();
for(;;) idlehands();
}
void
reboot(void *, void *, ulong)
{
}
void
evenaddr(uintptr va)
{
if((va & 3) != 0){
dumpstack();
postnote(up, 1, "sys: odd address", NDebug);
error(Ebadarg);
}
}
void
procfork(Proc *p)
{
ulong s;
p->kentry = up->kentry;
p->pcycles = -p->kentry;
s = splhi();
switch(up->fpstate & ~FPillegal){
case FPactive:
fpsave(up->fpsave);
up->fpstate = FPinactive;
case FPinactive:
memmove(p->fpsave, up->fpsave, sizeof(FPsave));
p->fpstate = FPinactive;
}
splx(s);
}
void
procsetup(Proc *p)
{
p->fpstate = FPinit;
fpoff();
cycles(&p->kentry);
p->pcycles = -p->kentry;
}
void
kexit(Ureg *)
{
Tos *tos;
uvlong t;
tos = (Tos*)(USTKTOP-sizeof(Tos));
cycles(&t);
tos->kcycles += t - up->kentry;
tos->pcycles = t + up->pcycles;
tos->pid = up->pid;
}
ulong *l2;
void
l2init(void)
{
enum {
CTRL = 0x100/4,
AUX,
TAGRAM,
DATARAM,
INVPA = 0x770/4,
INVWAY = 0x77C/4,
PREFETCH = 0xF60/4,
};
mpcore[0] |= 1;
slcr[0xa1c/4] = 0x020202;
l2 = vmap(L2_BASE, BY2PG);
l2[CTRL] &= ~1;
l2[TAGRAM] = l2[TAGRAM] & ~0x777 | 0x111;
l2[DATARAM] = l2[DATARAM] & ~0x777 | 0x121;
l2[PREFETCH] |= 3<<28 | 1<<24;
l2[AUX] |= 3<<28 | 1<<20;
l2[INVWAY] = 0xff;
while((l2[INVPA] & 1) != 0)
;
l2[CTRL] = 1;
}
void
clean2pa(uintptr start, uintptr end)
{
uintptr pa;
start &= ~31;
end = (end + 31) & ~31;
for(pa = start; pa < end; pa += 32)
l2[0x7b0/4] = pa;
}
void
inval2pa(uintptr start, uintptr end)
{
uintptr pa;
start &= ~31;
end = (end + 31) & ~31;
for(pa = start; pa < end; pa += 32)
l2[0x770/4] = pa;
}
static void
options(void)
{
long i, n;
char *cp, *line[MAXCONF], *p, *q;
cp = (char *) CONFADDR;
p = cp;
for(q = cp; *q; q++){
if(*q == '\r')
continue;
if(*q == '\t')
*q = ' ';
*p++ = *q;
}
*p = 0;
n = getfields(cp, line, MAXCONF, 1, "\n");
for(i = 0; i < n; i++){
if(*line[i] == '#')
continue;
cp = strchr(line[i], '=');
if(cp == nil)
continue;
*cp++ = '\0';
confname[nconf] = line[i];
confval[nconf] = cp;
nconf++;
}
}
void
confinit(void)
{
ulong kmem;
int i;
conf.nmach = 1;
conf.nproc = 2000;
conf.ialloc = 16*1024*1024;
conf.nimage = 200;
conf.mem[0].base = PGROUND((ulong)end - KZERO);
conf.mem[0].npage = (1024*1024*1024 - conf.mem[0].base) >> PGSHIFT;
ramdiskinit();
conf.npage = 0;
for(i = 0; i < nelem(conf.mem); i++)
conf.npage += conf.mem[i].npage;
kmem = 200*1024*1024;
conf.upages = conf.npage - kmem/BY2PG;
kmem -= conf.upages*sizeof(Page)
+ conf.nproc*sizeof(Proc)
+ conf.nimage*sizeof(Image);
mainmem->maxsize = kmem;
imagmem->maxsize = kmem - (kmem/10);
}
static void
init0(void)
{
char buf[ERRMAX], **sp;
int i;
up->nerrlab = 0;
spllo();
up->slash = namec("#/", Atodir, 0, 0);
pathclose(up->slash->path);
up->slash->path = newpath("/");
up->dot = cclone(up->slash);
chandevinit();
uartconsole();
if(!waserror()){
ksetenv("cputype", "arm", 0);
if(cpuserver)
ksetenv("service", "cpu", 0);
else
ksetenv("service", "terminal", 0);
ksetenv("console", "0", 0);
snprint(buf, sizeof(buf), "zynq %s", conffile);
ksetenv("terminal", buf, 0);
for(i = 0; i < nconf; i++){
if(*confname[i] != '*')
ksetenv(confname[i], confval[i], 0);
ksetenv(confname[i], confval[i], 1);
}
poperror();
}
kproc("alarm", alarmkproc, 0);
sp = (char**)(USTKTOP - sizeof(Tos) - 8 - sizeof(sp[0])*4);
sp[3] = sp[2] = nil;
strcpy(sp[1] = (char*)&sp[4], "boot");
sp[0] = nil;
touser(sp);
}
void
userinit(void)
{
Proc *p;
Segment *s;
void *v;
Page *pg;
p = newproc();
p->pgrp = newpgrp();
p->egrp = smalloc(sizeof(Egrp));
p->egrp->ref = 1;
p->fgrp = dupfgrp(nil);
p->rgrp = newrgrp();
p->procmode = 0640;
kstrdup(&eve, "");
kstrdup(&p->text, "*init*");
kstrdup(&p->user, eve);
procsetup(p);
p->sched.pc = (ulong)init0;
p->sched.sp = (ulong)p->kstack + KSTACK - (sizeof(Sargs) + BY2WD);
s = newseg(SG_STACK, USTKTOP - USTKSIZE, USTKSIZE / BY2PG);
p->seg[SSEG] = s;
pg = newpage(0, 0, USTKTOP - BY2PG);
segpage(s, pg);
v = tmpmap(pg->pa);
memset(v, 0, BY2PG);
tmpunmap(v);
s = newseg(SG_TEXT, UTZERO, 1);
s->flushme++;
p->seg[TSEG] = s;
pg = newpage(0, 0, UTZERO);
pg->txtflush = ~0;
segpage(s, pg);
v = tmpmap(pg->pa);
memset(v, 0, BY2PG);
memmove(v, initcode, sizeof(initcode));
tmpunmap(v);
ready(p);
}
void
sanity(void)
{
static int dat = 0xdeadbeef;
extern ulong vectors[];
assert(dat == 0xdeadbeef);
assert(((uintptr)vectors & 31) == 0);
assert(sizeof(Mach) + KSTACK <= MACHSIZE);
assert((KZERO & SECSZ - 1) == 0);
}
char *
getconf(char *n)
{
int i;
for(i = 0; i < nconf; i++)
if(cistrcmp(confname[i], n) == 0)
return confval[i];
return nil;
}
int
isaconfig(char *, int, ISAConf*)
{
return 0;
}
void
cpuidprint(void)
{
print("cpu%d: %dMHz ARM Cortex-A9\n", m->machno, m->cpumhz);
}
void
mpinit(void)
{
extern void mpbootstrap(void); /* l.s */
Mach *m1;
ulong *v;
int i;
if(getconf("*nomp"))
return;
conf.nmach = 2;
conf.copymode = 1;
m1 = MACHP(1);
memset(m1, 0, MACHSIZE);
m1->machno = 1;
m1->l1.pa = MACHL1(m1->machno)-KZERO;
m1->l1.va = KADDR(m1->l1.pa);
memset(m1->l1.va, 0, L1SZ);
for(i=0; i<L1X(VMAPSZ); i++)
m1->l1.va[L1X(VMAP)+i] = m->l1.va[L1X(VMAP)+i];
for(i=0; i<L1X(-KZERO); i++)
m1->l1.va[L1X(KZERO)+i] = m->l1.va[L1X(KZERO)+i];
coherence();
cleandse((uchar*)KZERO, (uchar*)0xFFFFFFFF);
invaldse((uchar*)KZERO, (uchar*)0xFFFFFFFF);
/* ocm is uncached */
v = KADDR(0xFFFFF000);
v[0xFF0/4] = PADDR(mpbootstrap);
coherence();
sendevent();
synccycles();
}
void
main(void)
{
active.machs[m->machno] = 1;
if(m->machno != 0){
uartputs("\n", 1);
mmuinit();
intrinit();
timerinit();
cpuidprint();
synccycles();
timersinit();
schedinit();
return;
}
uartinit();
mmuinit();
l2init();
intrinit();
options();
confinit();
timerinit();
uartputs(" from Bell Labs\n", 16);
xinit();
printinit();
quotefmtinstall();
cpuidprint();
sanity();
mpinit();
todinit();
timersinit();
procinit0();
initseg();
if(delaylink)
bootlinks();
else
links();
archinit();
chandevreset();
pageinit();
screeninit();
userinit();
schedinit();
}
void
setupwatchpts(Proc *, Watchpt *, int n)
{
if(n > 0)
error("no watchpoints");
}