15d9de2d3SDavid du Colombier #include "u.h"
25d9de2d3SDavid du Colombier #include "tos.h"
35d9de2d3SDavid du Colombier #include "../port/lib.h"
45d9de2d3SDavid du Colombier #include "mem.h"
55d9de2d3SDavid du Colombier #include "dat.h"
65d9de2d3SDavid du Colombier #include "fns.h"
75d9de2d3SDavid du Colombier
85d9de2d3SDavid du Colombier #include "init.h"
95d9de2d3SDavid du Colombier #include <pool.h>
105d9de2d3SDavid du Colombier
115d9de2d3SDavid du Colombier #include "reboot.h"
125d9de2d3SDavid du Colombier
1323a96966SDavid du Colombier enum {
1423a96966SDavid du Colombier /* space for syscall args, return PC, top-of-stack struct */
1523a96966SDavid du Colombier Ustkheadroom = sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),
1623a96966SDavid du Colombier };
1723a96966SDavid du Colombier
185d9de2d3SDavid du Colombier /* Firmware compatibility */
195d9de2d3SDavid du Colombier #define Minfirmrev 326770
20*3ec63e64SDavid du Colombier #define Minfirmdate "19 Aug 2013"
215d9de2d3SDavid du Colombier
225d9de2d3SDavid du Colombier /*
235d9de2d3SDavid du Colombier * Where configuration info is left for the loaded programme.
245d9de2d3SDavid du Colombier */
255d9de2d3SDavid du Colombier #define BOOTARGS ((char*)CONFADDR)
265d9de2d3SDavid du Colombier #define BOOTARGSLEN (MACHADDR-CONFADDR)
275d9de2d3SDavid du Colombier #define MAXCONF 64
285d9de2d3SDavid du Colombier #define MAXCONFLINE 160
295d9de2d3SDavid du Colombier
305d9de2d3SDavid du Colombier uintptr kseg0 = KZERO;
315d9de2d3SDavid du Colombier Mach* machaddr[MAXMACH];
325d9de2d3SDavid du Colombier Conf conf;
335d9de2d3SDavid du Colombier ulong memsize = 128*1024*1024;
345d9de2d3SDavid du Colombier
355d9de2d3SDavid du Colombier /*
365d9de2d3SDavid du Colombier * Option arguments from the command line.
375d9de2d3SDavid du Colombier * oargv[0] is the boot file.
385d9de2d3SDavid du Colombier */
395d9de2d3SDavid du Colombier static int oargc;
405d9de2d3SDavid du Colombier static char* oargv[20];
415d9de2d3SDavid du Colombier static char oargb[128];
425d9de2d3SDavid du Colombier static int oargblen;
435d9de2d3SDavid du Colombier
445d9de2d3SDavid du Colombier static uintptr sp; /* XXX - must go - user stack of init proc */
455d9de2d3SDavid du Colombier
465d9de2d3SDavid du Colombier /* store plan9.ini contents here at least until we stash them in #ec */
475d9de2d3SDavid du Colombier static char confname[MAXCONF][KNAMELEN];
485d9de2d3SDavid du Colombier static char confval[MAXCONF][MAXCONFLINE];
495d9de2d3SDavid du Colombier static int nconf;
505d9de2d3SDavid du Colombier
515d9de2d3SDavid du Colombier typedef struct Atag Atag;
525d9de2d3SDavid du Colombier struct Atag {
535d9de2d3SDavid du Colombier u32int size; /* size of atag in words, including this header */
545d9de2d3SDavid du Colombier u32int tag; /* atag type */
555d9de2d3SDavid du Colombier union {
565d9de2d3SDavid du Colombier u32int data[1]; /* actually [size-2] */
575d9de2d3SDavid du Colombier /* AtagMem */
585d9de2d3SDavid du Colombier struct {
595d9de2d3SDavid du Colombier u32int size;
605d9de2d3SDavid du Colombier u32int base;
615d9de2d3SDavid du Colombier } mem;
625d9de2d3SDavid du Colombier /* AtagCmdLine */
635d9de2d3SDavid du Colombier char cmdline[1]; /* actually [4*(size-2)] */
645d9de2d3SDavid du Colombier };
655d9de2d3SDavid du Colombier };
665d9de2d3SDavid du Colombier
675d9de2d3SDavid du Colombier enum {
685d9de2d3SDavid du Colombier AtagNone = 0x00000000,
695d9de2d3SDavid du Colombier AtagCore = 0x54410001,
705d9de2d3SDavid du Colombier AtagMem = 0x54410002,
715d9de2d3SDavid du Colombier AtagCmdline = 0x54410009,
725d9de2d3SDavid du Colombier };
735d9de2d3SDavid du Colombier
745d9de2d3SDavid du Colombier static int
findconf(char * name)755d9de2d3SDavid du Colombier findconf(char *name)
765d9de2d3SDavid du Colombier {
775d9de2d3SDavid du Colombier int i;
785d9de2d3SDavid du Colombier
795d9de2d3SDavid du Colombier for(i = 0; i < nconf; i++)
805d9de2d3SDavid du Colombier if(cistrcmp(confname[i], name) == 0)
815d9de2d3SDavid du Colombier return i;
825d9de2d3SDavid du Colombier return -1;
835d9de2d3SDavid du Colombier }
845d9de2d3SDavid du Colombier
855d9de2d3SDavid du Colombier char*
getconf(char * name)865d9de2d3SDavid du Colombier getconf(char *name)
875d9de2d3SDavid du Colombier {
885d9de2d3SDavid du Colombier int i;
895d9de2d3SDavid du Colombier
905d9de2d3SDavid du Colombier i = findconf(name);
915d9de2d3SDavid du Colombier if(i >= 0)
925d9de2d3SDavid du Colombier return confval[i];
935d9de2d3SDavid du Colombier return nil;
945d9de2d3SDavid du Colombier }
955d9de2d3SDavid du Colombier
965d9de2d3SDavid du Colombier void
addconf(char * name,char * val)975d9de2d3SDavid du Colombier addconf(char *name, char *val)
985d9de2d3SDavid du Colombier {
995d9de2d3SDavid du Colombier int i;
1005d9de2d3SDavid du Colombier
1015d9de2d3SDavid du Colombier i = findconf(name);
1025d9de2d3SDavid du Colombier if(i < 0){
1035d9de2d3SDavid du Colombier if(val == nil || nconf >= MAXCONF)
1045d9de2d3SDavid du Colombier return;
1055d9de2d3SDavid du Colombier i = nconf++;
1065d9de2d3SDavid du Colombier strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
1075d9de2d3SDavid du Colombier }
1085d9de2d3SDavid du Colombier strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
1095d9de2d3SDavid du Colombier }
1105d9de2d3SDavid du Colombier
1115d9de2d3SDavid du Colombier static void
writeconf(void)1125d9de2d3SDavid du Colombier writeconf(void)
1135d9de2d3SDavid du Colombier {
1145d9de2d3SDavid du Colombier char *p, *q;
1155d9de2d3SDavid du Colombier int n;
1165d9de2d3SDavid du Colombier
1175d9de2d3SDavid du Colombier p = getconfenv();
1185d9de2d3SDavid du Colombier
1195d9de2d3SDavid du Colombier if(waserror()) {
1205d9de2d3SDavid du Colombier free(p);
1215d9de2d3SDavid du Colombier nexterror();
1225d9de2d3SDavid du Colombier }
1235d9de2d3SDavid du Colombier
1245d9de2d3SDavid du Colombier /* convert to name=value\n format */
1255d9de2d3SDavid du Colombier for(q=p; *q; q++) {
1265d9de2d3SDavid du Colombier q += strlen(q);
1275d9de2d3SDavid du Colombier *q = '=';
1285d9de2d3SDavid du Colombier q += strlen(q);
1295d9de2d3SDavid du Colombier *q = '\n';
1305d9de2d3SDavid du Colombier }
1315d9de2d3SDavid du Colombier n = q - p + 1;
1325d9de2d3SDavid du Colombier if(n >= BOOTARGSLEN)
1335d9de2d3SDavid du Colombier error("kernel configuration too large");
1345d9de2d3SDavid du Colombier memmove(BOOTARGS, p, n);
1355d9de2d3SDavid du Colombier memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
1365d9de2d3SDavid du Colombier poperror();
1375d9de2d3SDavid du Colombier free(p);
1385d9de2d3SDavid du Colombier }
1395d9de2d3SDavid du Colombier
1405d9de2d3SDavid du Colombier static void
plan9iniinit(char * s,int cmdline)1415d9de2d3SDavid du Colombier plan9iniinit(char *s, int cmdline)
1425d9de2d3SDavid du Colombier {
1435d9de2d3SDavid du Colombier char *toks[MAXCONF];
1445d9de2d3SDavid du Colombier int i, c, n;
1455d9de2d3SDavid du Colombier char *v;
1465d9de2d3SDavid du Colombier
1475d9de2d3SDavid du Colombier if((c = *s) < ' ' || c >= 0x80)
1485d9de2d3SDavid du Colombier return;
1495d9de2d3SDavid du Colombier if(cmdline)
1505d9de2d3SDavid du Colombier n = tokenize(s, toks, MAXCONF);
1515d9de2d3SDavid du Colombier else
1525d9de2d3SDavid du Colombier n = getfields(s, toks, MAXCONF, 1, "\n");
1535d9de2d3SDavid du Colombier for(i = 0; i < n; i++){
1545d9de2d3SDavid du Colombier if(toks[i][0] == '#')
1555d9de2d3SDavid du Colombier continue;
1565d9de2d3SDavid du Colombier v = strchr(toks[i], '=');
1575d9de2d3SDavid du Colombier if(v == nil)
1585d9de2d3SDavid du Colombier continue;
1595d9de2d3SDavid du Colombier *v++ = '\0';
1605d9de2d3SDavid du Colombier addconf(toks[i], v);
1615d9de2d3SDavid du Colombier }
1625d9de2d3SDavid du Colombier }
1635d9de2d3SDavid du Colombier
1645d9de2d3SDavid du Colombier static void
ataginit(Atag * a)1655d9de2d3SDavid du Colombier ataginit(Atag *a)
1665d9de2d3SDavid du Colombier {
1675d9de2d3SDavid du Colombier int n;
1685d9de2d3SDavid du Colombier
1695d9de2d3SDavid du Colombier if(a->tag != AtagCore){
1705d9de2d3SDavid du Colombier plan9iniinit((char*)a, 0);
1715d9de2d3SDavid du Colombier return;
1725d9de2d3SDavid du Colombier }
1735d9de2d3SDavid du Colombier while(a->tag != AtagNone){
1745d9de2d3SDavid du Colombier switch(a->tag){
1755d9de2d3SDavid du Colombier case AtagMem:
1765d9de2d3SDavid du Colombier /* use only first bank */
1775d9de2d3SDavid du Colombier if(conf.mem[0].limit == 0 && a->mem.size != 0){
1785d9de2d3SDavid du Colombier memsize = a->mem.size;
1795d9de2d3SDavid du Colombier conf.mem[0].base = a->mem.base;
1805d9de2d3SDavid du Colombier conf.mem[0].limit = a->mem.base + memsize;
1815d9de2d3SDavid du Colombier }
1825d9de2d3SDavid du Colombier break;
1835d9de2d3SDavid du Colombier case AtagCmdline:
1845d9de2d3SDavid du Colombier n = (a->size * sizeof(u32int)) - offsetof(Atag, cmdline[0]);
1855d9de2d3SDavid du Colombier if(a->cmdline + n < BOOTARGS + BOOTARGSLEN)
1865d9de2d3SDavid du Colombier a->cmdline[n] = 0;
1875d9de2d3SDavid du Colombier else
1885d9de2d3SDavid du Colombier BOOTARGS[BOOTARGSLEN-1] = 0;
1895d9de2d3SDavid du Colombier plan9iniinit(a->cmdline, 1);
1905d9de2d3SDavid du Colombier break;
1915d9de2d3SDavid du Colombier }
1925d9de2d3SDavid du Colombier a = (Atag*)((u32int*)a + a->size);
1935d9de2d3SDavid du Colombier }
1945d9de2d3SDavid du Colombier }
1955d9de2d3SDavid du Colombier
1965d9de2d3SDavid du Colombier void
machinit(void)1975d9de2d3SDavid du Colombier machinit(void)
1985d9de2d3SDavid du Colombier {
1995d9de2d3SDavid du Colombier m->machno = 0;
2005d9de2d3SDavid du Colombier machaddr[m->machno] = m;
2015d9de2d3SDavid du Colombier
2025d9de2d3SDavid du Colombier m->ticks = 1;
2035d9de2d3SDavid du Colombier m->perf.period = 1;
2045d9de2d3SDavid du Colombier
2055d9de2d3SDavid du Colombier conf.nmach = 1;
2065d9de2d3SDavid du Colombier
2075d9de2d3SDavid du Colombier active.machs = 1;
2085d9de2d3SDavid du Colombier active.exiting = 0;
2095d9de2d3SDavid du Colombier
2105d9de2d3SDavid du Colombier up = nil;
2115d9de2d3SDavid du Colombier }
2125d9de2d3SDavid du Colombier
2135d9de2d3SDavid du Colombier static void
optionsinit(char * s)2145d9de2d3SDavid du Colombier optionsinit(char* s)
2155d9de2d3SDavid du Colombier {
2165d9de2d3SDavid du Colombier strecpy(oargb, oargb+sizeof(oargb), s);
2175d9de2d3SDavid du Colombier
2185d9de2d3SDavid du Colombier oargblen = strlen(oargb);
2195d9de2d3SDavid du Colombier oargc = tokenize(oargb, oargv, nelem(oargv)-1);
2205d9de2d3SDavid du Colombier oargv[oargc] = nil;
2215d9de2d3SDavid du Colombier }
2225d9de2d3SDavid du Colombier
2235d9de2d3SDavid du Colombier void
main(void)2245d9de2d3SDavid du Colombier main(void)
2255d9de2d3SDavid du Colombier {
2265d9de2d3SDavid du Colombier extern char edata[], end[];
2275d9de2d3SDavid du Colombier uint rev;
2285d9de2d3SDavid du Colombier
2295d9de2d3SDavid du Colombier okay(1);
2305d9de2d3SDavid du Colombier m = (Mach*)MACHADDR;
2315d9de2d3SDavid du Colombier memset(edata, 0, end - edata); /* clear bss */
2325d9de2d3SDavid du Colombier machinit();
2335d9de2d3SDavid du Colombier mmuinit1();
2345d9de2d3SDavid du Colombier
2355d9de2d3SDavid du Colombier optionsinit("/boot/boot boot");
2365d9de2d3SDavid du Colombier quotefmtinstall();
2375d9de2d3SDavid du Colombier
2385d9de2d3SDavid du Colombier ataginit((Atag*)BOOTARGS);
2395d9de2d3SDavid du Colombier confinit(); /* figures out amount of memory */
2405d9de2d3SDavid du Colombier xinit();
2415d9de2d3SDavid du Colombier uartconsinit();
2425d9de2d3SDavid du Colombier screeninit();
2435d9de2d3SDavid du Colombier
2445d9de2d3SDavid du Colombier print("\nPlan 9 from Bell Labs\n");
2455d9de2d3SDavid du Colombier rev = getfirmware();
2465d9de2d3SDavid du Colombier print("firmware: rev %d\n", rev);
2475d9de2d3SDavid du Colombier if(rev < Minfirmrev){
248*3ec63e64SDavid du Colombier print("Sorry, firmware (start*.elf) must be at least rev %d"
249*3ec63e64SDavid du Colombier " or newer than %s\n", Minfirmrev, Minfirmdate);
2505d9de2d3SDavid du Colombier for(;;)
2515d9de2d3SDavid du Colombier ;
2525d9de2d3SDavid du Colombier }
2535d9de2d3SDavid du Colombier trapinit();
2545d9de2d3SDavid du Colombier clockinit();
2555d9de2d3SDavid du Colombier printinit();
2565d9de2d3SDavid du Colombier timersinit();
2575d9de2d3SDavid du Colombier if(conf.monitor)
2585d9de2d3SDavid du Colombier swcursorinit();
2595d9de2d3SDavid du Colombier cpuidprint();
2605d9de2d3SDavid du Colombier archreset();
2615d9de2d3SDavid du Colombier
2625d9de2d3SDavid du Colombier procinit0();
2635d9de2d3SDavid du Colombier initseg();
2645d9de2d3SDavid du Colombier links();
2655d9de2d3SDavid du Colombier chandevreset(); /* most devices are discovered here */
2665d9de2d3SDavid du Colombier pageinit();
2675d9de2d3SDavid du Colombier swapinit();
2685d9de2d3SDavid du Colombier userinit();
2695d9de2d3SDavid du Colombier schedinit();
2705d9de2d3SDavid du Colombier assert(0); /* shouldn't have returned */
2715d9de2d3SDavid du Colombier }
2725d9de2d3SDavid du Colombier
2735d9de2d3SDavid du Colombier /*
2745d9de2d3SDavid du Colombier * starting place for first process
2755d9de2d3SDavid du Colombier */
2765d9de2d3SDavid du Colombier void
init0(void)2775d9de2d3SDavid du Colombier init0(void)
2785d9de2d3SDavid du Colombier {
2795d9de2d3SDavid du Colombier int i;
2805d9de2d3SDavid du Colombier char buf[2*KNAMELEN];
2815d9de2d3SDavid du Colombier
2825d9de2d3SDavid du Colombier up->nerrlab = 0;
2835d9de2d3SDavid du Colombier coherence();
2845d9de2d3SDavid du Colombier spllo();
2855d9de2d3SDavid du Colombier
2865d9de2d3SDavid du Colombier /*
2875d9de2d3SDavid du Colombier * These are o.k. because rootinit is null.
2885d9de2d3SDavid du Colombier * Then early kproc's will have a root and dot.
2895d9de2d3SDavid du Colombier */
2905d9de2d3SDavid du Colombier up->slash = namec("#/", Atodir, 0, 0);
2915d9de2d3SDavid du Colombier pathclose(up->slash->path);
2925d9de2d3SDavid du Colombier up->slash->path = newpath("/");
2935d9de2d3SDavid du Colombier up->dot = cclone(up->slash);
2945d9de2d3SDavid du Colombier
2955d9de2d3SDavid du Colombier chandevinit();
2965d9de2d3SDavid du Colombier
2975d9de2d3SDavid du Colombier if(!waserror()){
2985d9de2d3SDavid du Colombier snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
2995d9de2d3SDavid du Colombier ksetenv("terminal", buf, 0);
3005d9de2d3SDavid du Colombier ksetenv("cputype", "arm", 0);
3015d9de2d3SDavid du Colombier if(cpuserver)
3025d9de2d3SDavid du Colombier ksetenv("service", "cpu", 0);
3035d9de2d3SDavid du Colombier else
3045d9de2d3SDavid du Colombier ksetenv("service", "terminal", 0);
3055d9de2d3SDavid du Colombier snprint(buf, sizeof(buf), "-a %s", getethermac());
3065d9de2d3SDavid du Colombier ksetenv("etherargs", buf, 0);
3075d9de2d3SDavid du Colombier
3085d9de2d3SDavid du Colombier /* convert plan9.ini variables to #e and #ec */
3095d9de2d3SDavid du Colombier for(i = 0; i < nconf; i++) {
3105d9de2d3SDavid du Colombier ksetenv(confname[i], confval[i], 0);
3115d9de2d3SDavid du Colombier ksetenv(confname[i], confval[i], 1);
3125d9de2d3SDavid du Colombier }
3135d9de2d3SDavid du Colombier poperror();
3145d9de2d3SDavid du Colombier }
3155d9de2d3SDavid du Colombier kproc("alarm", alarmkproc, 0);
3165d9de2d3SDavid du Colombier touser(sp);
3175d9de2d3SDavid du Colombier assert(0); /* shouldn't have returned */
3185d9de2d3SDavid du Colombier }
3195d9de2d3SDavid du Colombier
3205d9de2d3SDavid du Colombier static void
bootargs(uintptr base)3215d9de2d3SDavid du Colombier bootargs(uintptr base)
3225d9de2d3SDavid du Colombier {
3235d9de2d3SDavid du Colombier int i;
3245d9de2d3SDavid du Colombier ulong ssize;
3255d9de2d3SDavid du Colombier char **av, *p;
3265d9de2d3SDavid du Colombier
3275d9de2d3SDavid du Colombier /*
3285d9de2d3SDavid du Colombier * Push the boot args onto the stack.
3295d9de2d3SDavid du Colombier * The initial value of the user stack must be such
3305d9de2d3SDavid du Colombier * that the total used is larger than the maximum size
3315d9de2d3SDavid du Colombier * of the argument list checked in syscall.
3325d9de2d3SDavid du Colombier */
3335d9de2d3SDavid du Colombier i = oargblen+1;
33423a96966SDavid du Colombier p = UINT2PTR(STACKALIGN(base + BY2PG - Ustkheadroom - i));
3355d9de2d3SDavid du Colombier memmove(p, oargb, i);
3365d9de2d3SDavid du Colombier
3375d9de2d3SDavid du Colombier /*
3385d9de2d3SDavid du Colombier * Now push the argv pointers.
3395d9de2d3SDavid du Colombier * The code jumped to by touser in lproc.s expects arguments
3405d9de2d3SDavid du Colombier * main(char* argv0, ...)
3415d9de2d3SDavid du Colombier * and calls
3425d9de2d3SDavid du Colombier * startboot("/boot/boot", &argv0)
3435d9de2d3SDavid du Colombier * not the usual (int argc, char* argv[])
3445d9de2d3SDavid du Colombier */
3455d9de2d3SDavid du Colombier av = (char**)(p - (oargc+1)*sizeof(char*));
3465d9de2d3SDavid du Colombier ssize = base + BY2PG - PTR2UINT(av);
3475d9de2d3SDavid du Colombier for(i = 0; i < oargc; i++)
3485d9de2d3SDavid du Colombier *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
3495d9de2d3SDavid du Colombier *av = nil;
3505d9de2d3SDavid du Colombier sp = USTKTOP - ssize;
3515d9de2d3SDavid du Colombier }
3525d9de2d3SDavid du Colombier
3535d9de2d3SDavid du Colombier /*
3545d9de2d3SDavid du Colombier * create the first process
3555d9de2d3SDavid du Colombier */
3565d9de2d3SDavid du Colombier void
userinit(void)3575d9de2d3SDavid du Colombier userinit(void)
3585d9de2d3SDavid du Colombier {
3595d9de2d3SDavid du Colombier Proc *p;
3605d9de2d3SDavid du Colombier Segment *s;
3615d9de2d3SDavid du Colombier KMap *k;
3625d9de2d3SDavid du Colombier Page *pg;
3635d9de2d3SDavid du Colombier
3645d9de2d3SDavid du Colombier /* no processes yet */
3655d9de2d3SDavid du Colombier up = nil;
3665d9de2d3SDavid du Colombier
3675d9de2d3SDavid du Colombier p = newproc();
3685d9de2d3SDavid du Colombier p->pgrp = newpgrp();
3695d9de2d3SDavid du Colombier p->egrp = smalloc(sizeof(Egrp));
3705d9de2d3SDavid du Colombier p->egrp->ref = 1;
3715d9de2d3SDavid du Colombier p->fgrp = dupfgrp(nil);
3725d9de2d3SDavid du Colombier p->rgrp = newrgrp();
3735d9de2d3SDavid du Colombier p->procmode = 0640;
3745d9de2d3SDavid du Colombier
3755d9de2d3SDavid du Colombier kstrdup(&eve, "");
3765d9de2d3SDavid du Colombier kstrdup(&p->text, "*init*");
3775d9de2d3SDavid du Colombier kstrdup(&p->user, eve);
3785d9de2d3SDavid du Colombier
3795d9de2d3SDavid du Colombier /*
3805d9de2d3SDavid du Colombier * Kernel Stack
3815d9de2d3SDavid du Colombier */
3825d9de2d3SDavid du Colombier p->sched.pc = PTR2UINT(init0);
3835d9de2d3SDavid du Colombier p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
3845d9de2d3SDavid du Colombier p->sched.sp = STACKALIGN(p->sched.sp);
3855d9de2d3SDavid du Colombier
3865d9de2d3SDavid du Colombier /*
3875d9de2d3SDavid du Colombier * User Stack
3885d9de2d3SDavid du Colombier *
3895d9de2d3SDavid du Colombier * Technically, newpage can't be called here because it
3905d9de2d3SDavid du Colombier * should only be called when in a user context as it may
3915d9de2d3SDavid du Colombier * try to sleep if there are no pages available, but that
3925d9de2d3SDavid du Colombier * shouldn't be the case here.
3935d9de2d3SDavid du Colombier */
3945d9de2d3SDavid du Colombier s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
3955d9de2d3SDavid du Colombier s->flushme++;
3965d9de2d3SDavid du Colombier p->seg[SSEG] = s;
3975d9de2d3SDavid du Colombier pg = newpage(1, 0, USTKTOP-BY2PG);
3985d9de2d3SDavid du Colombier segpage(s, pg);
3995d9de2d3SDavid du Colombier k = kmap(pg);
4005d9de2d3SDavid du Colombier bootargs(VA(k));
4015d9de2d3SDavid du Colombier kunmap(k);
4025d9de2d3SDavid du Colombier
4035d9de2d3SDavid du Colombier /*
4045d9de2d3SDavid du Colombier * Text
4055d9de2d3SDavid du Colombier */
4065d9de2d3SDavid du Colombier s = newseg(SG_TEXT, UTZERO, 1);
4075d9de2d3SDavid du Colombier p->seg[TSEG] = s;
4085d9de2d3SDavid du Colombier pg = newpage(1, 0, UTZERO);
4095d9de2d3SDavid du Colombier memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
4105d9de2d3SDavid du Colombier segpage(s, pg);
4115d9de2d3SDavid du Colombier k = kmap(s->map[0]->pages[0]);
4125d9de2d3SDavid du Colombier memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
4135d9de2d3SDavid du Colombier kunmap(k);
4145d9de2d3SDavid du Colombier
4155d9de2d3SDavid du Colombier ready(p);
4165d9de2d3SDavid du Colombier }
4175d9de2d3SDavid du Colombier
4185d9de2d3SDavid du Colombier void
confinit(void)4195d9de2d3SDavid du Colombier confinit(void)
4205d9de2d3SDavid du Colombier {
4215d9de2d3SDavid du Colombier int i;
4225d9de2d3SDavid du Colombier ulong kpages;
4235d9de2d3SDavid du Colombier uintptr pa;
4245d9de2d3SDavid du Colombier char *p;
4255d9de2d3SDavid du Colombier
4265d9de2d3SDavid du Colombier if(0 && (p = getconf("service")) != nil){
4275d9de2d3SDavid du Colombier if(strcmp(p, "cpu") == 0)
4285d9de2d3SDavid du Colombier cpuserver = 1;
4295d9de2d3SDavid du Colombier else if(strcmp(p,"terminal") == 0)
4305d9de2d3SDavid du Colombier cpuserver = 0;
4315d9de2d3SDavid du Colombier }
4325d9de2d3SDavid du Colombier if((p = getconf("*maxmem")) != nil){
4335d9de2d3SDavid du Colombier memsize = strtoul(p, 0, 0) - PHYSDRAM;
4345d9de2d3SDavid du Colombier if (memsize < 16*MB) /* sanity */
4355d9de2d3SDavid du Colombier memsize = 16*MB;
4365d9de2d3SDavid du Colombier }
4375d9de2d3SDavid du Colombier
4385d9de2d3SDavid du Colombier getramsize(&conf.mem[0]);
4395d9de2d3SDavid du Colombier if(conf.mem[0].limit == 0){
4405d9de2d3SDavid du Colombier conf.mem[0].base = PHYSDRAM;
4415d9de2d3SDavid du Colombier conf.mem[0].limit = PHYSDRAM + memsize;
4425d9de2d3SDavid du Colombier }else if(p != nil)
4435d9de2d3SDavid du Colombier conf.mem[0].limit = conf.mem[0].base + memsize;
4445d9de2d3SDavid du Colombier
4455d9de2d3SDavid du Colombier conf.npage = 0;
4465d9de2d3SDavid du Colombier pa = PADDR(PGROUND(PTR2UINT(end)));
4475d9de2d3SDavid du Colombier
4485d9de2d3SDavid du Colombier /*
4495d9de2d3SDavid du Colombier * we assume that the kernel is at the beginning of one of the
4505d9de2d3SDavid du Colombier * contiguous chunks of memory and fits therein.
4515d9de2d3SDavid du Colombier */
4525d9de2d3SDavid du Colombier for(i=0; i<nelem(conf.mem); i++){
4535d9de2d3SDavid du Colombier /* take kernel out of allocatable space */
4545d9de2d3SDavid du Colombier if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
4555d9de2d3SDavid du Colombier conf.mem[i].base = pa;
4565d9de2d3SDavid du Colombier
4575d9de2d3SDavid du Colombier conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
4585d9de2d3SDavid du Colombier conf.npage += conf.mem[i].npage;
4595d9de2d3SDavid du Colombier }
4605d9de2d3SDavid du Colombier
4615d9de2d3SDavid du Colombier conf.upages = (conf.npage*80)/100;
4625d9de2d3SDavid du Colombier conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
4635d9de2d3SDavid du Colombier
4645d9de2d3SDavid du Colombier /* only one processor */
4655d9de2d3SDavid du Colombier conf.nmach = 1;
4665d9de2d3SDavid du Colombier
4675d9de2d3SDavid du Colombier /* set up other configuration parameters */
4685d9de2d3SDavid du Colombier conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
4695d9de2d3SDavid du Colombier if(cpuserver)
4705d9de2d3SDavid du Colombier conf.nproc *= 3;
4715d9de2d3SDavid du Colombier if(conf.nproc > 2000)
4725d9de2d3SDavid du Colombier conf.nproc = 2000;
4735d9de2d3SDavid du Colombier conf.nswap = conf.npage*3;
4745d9de2d3SDavid du Colombier conf.nswppo = 4096;
4755d9de2d3SDavid du Colombier conf.nimage = 200;
4765d9de2d3SDavid du Colombier
4775d9de2d3SDavid du Colombier conf.copymode = 0; /* copy on write */
4785d9de2d3SDavid du Colombier
4795d9de2d3SDavid du Colombier /*
4805d9de2d3SDavid du Colombier * Guess how much is taken by the large permanent
4815d9de2d3SDavid du Colombier * datastructures. Mntcache and Mntrpc are not accounted for
4825d9de2d3SDavid du Colombier * (probably ~300KB).
4835d9de2d3SDavid du Colombier */
4845d9de2d3SDavid du Colombier kpages = conf.npage - conf.upages;
4855d9de2d3SDavid du Colombier kpages *= BY2PG;
4865d9de2d3SDavid du Colombier kpages -= conf.upages*sizeof(Page)
4875d9de2d3SDavid du Colombier + conf.nproc*sizeof(Proc)
4885d9de2d3SDavid du Colombier + conf.nimage*sizeof(Image)
4895d9de2d3SDavid du Colombier + conf.nswap
4905d9de2d3SDavid du Colombier + conf.nswppo*sizeof(Page);
4915d9de2d3SDavid du Colombier mainmem->maxsize = kpages;
4925d9de2d3SDavid du Colombier if(!cpuserver)
4935d9de2d3SDavid du Colombier /*
4945d9de2d3SDavid du Colombier * give terminals lots of image memory, too; the dynamic
4955d9de2d3SDavid du Colombier * allocation will balance the load properly, hopefully.
4965d9de2d3SDavid du Colombier * be careful with 32-bit overflow.
4975d9de2d3SDavid du Colombier */
4985d9de2d3SDavid du Colombier imagmem->maxsize = kpages;
4995d9de2d3SDavid du Colombier
5005d9de2d3SDavid du Colombier }
5015d9de2d3SDavid du Colombier
5025d9de2d3SDavid du Colombier static void
shutdown(int ispanic)5035d9de2d3SDavid du Colombier shutdown(int ispanic)
5045d9de2d3SDavid du Colombier {
5055d9de2d3SDavid du Colombier int ms, once;
5065d9de2d3SDavid du Colombier
5075d9de2d3SDavid du Colombier lock(&active);
5085d9de2d3SDavid du Colombier if(ispanic)
5095d9de2d3SDavid du Colombier active.ispanic = ispanic;
5105d9de2d3SDavid du Colombier else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
5115d9de2d3SDavid du Colombier active.ispanic = 0;
5125d9de2d3SDavid du Colombier once = active.machs & (1<<m->machno);
5135d9de2d3SDavid du Colombier active.machs &= ~(1<<m->machno);
5145d9de2d3SDavid du Colombier active.exiting = 1;
5155d9de2d3SDavid du Colombier unlock(&active);
5165d9de2d3SDavid du Colombier
5175d9de2d3SDavid du Colombier if(once)
5185d9de2d3SDavid du Colombier iprint("cpu%d: exiting\n", m->machno);
5195d9de2d3SDavid du Colombier spllo();
5205d9de2d3SDavid du Colombier for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
5215d9de2d3SDavid du Colombier delay(TK2MS(2));
5225d9de2d3SDavid du Colombier if(active.machs == 0 && consactive() == 0)
5235d9de2d3SDavid du Colombier break;
5245d9de2d3SDavid du Colombier }
5255d9de2d3SDavid du Colombier delay(1000);
5265d9de2d3SDavid du Colombier }
5275d9de2d3SDavid du Colombier
5285d9de2d3SDavid du Colombier /*
5295d9de2d3SDavid du Colombier * exit kernel either on a panic or user request
5305d9de2d3SDavid du Colombier */
5315d9de2d3SDavid du Colombier void
exit(int code)5325d9de2d3SDavid du Colombier exit(int code)
5335d9de2d3SDavid du Colombier {
5345d9de2d3SDavid du Colombier shutdown(code);
5355d9de2d3SDavid du Colombier splfhi();
5365d9de2d3SDavid du Colombier archreboot();
5375d9de2d3SDavid du Colombier }
5385d9de2d3SDavid du Colombier
5395d9de2d3SDavid du Colombier /*
5405d9de2d3SDavid du Colombier * stub for ../omap/devether.c
5415d9de2d3SDavid du Colombier */
5425d9de2d3SDavid du Colombier int
isaconfig(char * class,int ctlrno,ISAConf * isa)5435d9de2d3SDavid du Colombier isaconfig(char *class, int ctlrno, ISAConf *isa)
5445d9de2d3SDavid du Colombier {
5455d9de2d3SDavid du Colombier USED(ctlrno);
5465d9de2d3SDavid du Colombier USED(isa);
5475d9de2d3SDavid du Colombier return strcmp(class, "ether") == 0;
5485d9de2d3SDavid du Colombier }
5495d9de2d3SDavid du Colombier
5505d9de2d3SDavid du Colombier /*
5515d9de2d3SDavid du Colombier * the new kernel is already loaded at address `code'
5525d9de2d3SDavid du Colombier * of size `size' and entry point `entry'.
5535d9de2d3SDavid du Colombier */
5545d9de2d3SDavid du Colombier void
reboot(void * entry,void * code,ulong size)5555d9de2d3SDavid du Colombier reboot(void *entry, void *code, ulong size)
5565d9de2d3SDavid du Colombier {
5575d9de2d3SDavid du Colombier void (*f)(ulong, ulong, ulong);
5585d9de2d3SDavid du Colombier
5595d9de2d3SDavid du Colombier print("starting reboot...");
5605d9de2d3SDavid du Colombier writeconf();
5615d9de2d3SDavid du Colombier shutdown(0);
5625d9de2d3SDavid du Colombier
5635d9de2d3SDavid du Colombier /*
5645d9de2d3SDavid du Colombier * should be the only processor running now
5655d9de2d3SDavid du Colombier */
5665d9de2d3SDavid du Colombier
5675d9de2d3SDavid du Colombier print("reboot entry %#lux code %#lux size %ld\n",
5685d9de2d3SDavid du Colombier PADDR(entry), PADDR(code), size);
5695d9de2d3SDavid du Colombier delay(100);
5705d9de2d3SDavid du Colombier
5715d9de2d3SDavid du Colombier /* turn off buffered serial console */
5725d9de2d3SDavid du Colombier serialoq = nil;
5735d9de2d3SDavid du Colombier kprintoq = nil;
5745d9de2d3SDavid du Colombier screenputs = nil;
5755d9de2d3SDavid du Colombier
5765d9de2d3SDavid du Colombier /* shutdown devices */
5775d9de2d3SDavid du Colombier chandevshutdown();
5785d9de2d3SDavid du Colombier
5795d9de2d3SDavid du Colombier /* stop the clock (and watchdog if any) */
5805d9de2d3SDavid du Colombier clockshutdown();
5815d9de2d3SDavid du Colombier
5825d9de2d3SDavid du Colombier splfhi();
5835d9de2d3SDavid du Colombier intrsoff();
5845d9de2d3SDavid du Colombier
5855d9de2d3SDavid du Colombier /* setup reboot trampoline function */
5865d9de2d3SDavid du Colombier f = (void*)REBOOTADDR;
5875d9de2d3SDavid du Colombier memmove(f, rebootcode, sizeof(rebootcode));
5885d9de2d3SDavid du Colombier cacheuwbinv();
5895d9de2d3SDavid du Colombier
5905d9de2d3SDavid du Colombier /* off we go - never to return */
5915d9de2d3SDavid du Colombier (*f)(PADDR(entry), PADDR(code), size);
5925d9de2d3SDavid du Colombier
5935d9de2d3SDavid du Colombier iprint("loaded kernel returned!\n");
5945d9de2d3SDavid du Colombier delay(1000);
5955d9de2d3SDavid du Colombier archreboot();
5965d9de2d3SDavid du Colombier }
5975d9de2d3SDavid du Colombier
5985d9de2d3SDavid du Colombier int
cmpswap(long * addr,long old,long new)5995d9de2d3SDavid du Colombier cmpswap(long *addr, long old, long new)
6005d9de2d3SDavid du Colombier {
6015d9de2d3SDavid du Colombier return cas32(addr, old, new);
6025d9de2d3SDavid du Colombier }
603