1*d6dfd9efSDavid du Colombier #include "u.h"
2*d6dfd9efSDavid du Colombier #include "../port/lib.h"
3*d6dfd9efSDavid du Colombier #include "mem.h"
4*d6dfd9efSDavid du Colombier #include "dat.h"
5*d6dfd9efSDavid du Colombier #include "fns.h"
6*d6dfd9efSDavid du Colombier #include "../ip/ip.h"
7*d6dfd9efSDavid du Colombier
8*d6dfd9efSDavid du Colombier #include <pool.h>
9*d6dfd9efSDavid du Colombier #include <tos.h>
10*d6dfd9efSDavid du Colombier
11*d6dfd9efSDavid du Colombier #include "qtm.h"
12*d6dfd9efSDavid du Colombier
13*d6dfd9efSDavid du Colombier #include "init.h"
14*d6dfd9efSDavid du Colombier
15*d6dfd9efSDavid du Colombier #define MAXCONF 32
16*d6dfd9efSDavid du Colombier
17*d6dfd9efSDavid du Colombier ulong dverify = 0x01020304;
18*d6dfd9efSDavid du Colombier ulong bverify;
19*d6dfd9efSDavid du Colombier int securemem;
20*d6dfd9efSDavid du Colombier Conf conf;
21*d6dfd9efSDavid du Colombier
22*d6dfd9efSDavid du Colombier /*
23*d6dfd9efSDavid du Colombier * Option arguments from the command line.
24*d6dfd9efSDavid du Colombier * oargv[0] is the boot file.
25*d6dfd9efSDavid du Colombier * Optionsinit() is called from multiboot()
26*d6dfd9efSDavid du Colombier * or some other machine-dependent place
27*d6dfd9efSDavid du Colombier * to set it all up.
28*d6dfd9efSDavid du Colombier */
29*d6dfd9efSDavid du Colombier static int oargc;
30*d6dfd9efSDavid du Colombier static char* oargv[20];
31*d6dfd9efSDavid du Colombier static char oargb[128];
32*d6dfd9efSDavid du Colombier static int oargblen;
33*d6dfd9efSDavid du Colombier static char oenv[4096];
34*d6dfd9efSDavid du Colombier
35*d6dfd9efSDavid du Colombier static uintptr sp; /* XXX - must go - user stack of init proc */
36*d6dfd9efSDavid du Colombier
37*d6dfd9efSDavid du Colombier static char confname[MAXCONF][KNAMELEN];
38*d6dfd9efSDavid du Colombier static char *confval[MAXCONF];
39*d6dfd9efSDavid du Colombier static int nconf;
40*d6dfd9efSDavid du Colombier
41*d6dfd9efSDavid du Colombier static void
mypanic(Pool * p,char * fmt,...)42*d6dfd9efSDavid du Colombier mypanic(Pool *p, char *fmt, ...)
43*d6dfd9efSDavid du Colombier {
44*d6dfd9efSDavid du Colombier USED(p, fmt);
45*d6dfd9efSDavid du Colombier print("malloc panic\n");
46*d6dfd9efSDavid du Colombier delay(1000);
47*d6dfd9efSDavid du Colombier splhi();
48*d6dfd9efSDavid du Colombier for (;;)
49*d6dfd9efSDavid du Colombier ;
50*d6dfd9efSDavid du Colombier }
51*d6dfd9efSDavid du Colombier
52*d6dfd9efSDavid du Colombier void
machninit(int machno)53*d6dfd9efSDavid du Colombier machninit(int machno)
54*d6dfd9efSDavid du Colombier {
55*d6dfd9efSDavid du Colombier if (machno >= MAXMACH)
56*d6dfd9efSDavid du Colombier panic("machno %d >= MAXMACH %d", machno, MAXMACH);
57*d6dfd9efSDavid du Colombier conf.nmach++;
58*d6dfd9efSDavid du Colombier m = MACHP(machno);
59*d6dfd9efSDavid du Colombier memset(m, 0, sizeof(Mach));
60*d6dfd9efSDavid du Colombier m->machno = machno;
61*d6dfd9efSDavid du Colombier m->cputype = getpvr()>>16; /* OWN[0:11] and PCF[12:15] fields */
62*d6dfd9efSDavid du Colombier m->delayloop = 20000; /* initial estimate only; set by clockinit */
63*d6dfd9efSDavid du Colombier m->perf.period = 1;
64*d6dfd9efSDavid du Colombier /* other values set by archreset */
65*d6dfd9efSDavid du Colombier }
66*d6dfd9efSDavid du Colombier
67*d6dfd9efSDavid du Colombier void
cpuidprint(void)68*d6dfd9efSDavid du Colombier cpuidprint(void)
69*d6dfd9efSDavid du Colombier {
70*d6dfd9efSDavid du Colombier char name[64];
71*d6dfd9efSDavid du Colombier
72*d6dfd9efSDavid du Colombier cputype2name(name, sizeof name);
73*d6dfd9efSDavid du Colombier print("cpu%d: %ldMHz PowerPC %s\n", m->machno, m->cpuhz/1000000, name);
74*d6dfd9efSDavid du Colombier }
75*d6dfd9efSDavid du Colombier
76*d6dfd9efSDavid du Colombier void
mach0init(void)77*d6dfd9efSDavid du Colombier mach0init(void)
78*d6dfd9efSDavid du Colombier {
79*d6dfd9efSDavid du Colombier conf.nmach = 0;
80*d6dfd9efSDavid du Colombier
81*d6dfd9efSDavid du Colombier machninit(0);
82*d6dfd9efSDavid du Colombier
83*d6dfd9efSDavid du Colombier active.machs = 1;
84*d6dfd9efSDavid du Colombier active.exiting = 0;
85*d6dfd9efSDavid du Colombier }
86*d6dfd9efSDavid du Colombier
87*d6dfd9efSDavid du Colombier static void
setconf(char * name,char * val)88*d6dfd9efSDavid du Colombier setconf(char *name, char *val)
89*d6dfd9efSDavid du Colombier {
90*d6dfd9efSDavid du Colombier strncpy(confname[nconf], name, KNAMELEN);
91*d6dfd9efSDavid du Colombier kstrdup(&confval[nconf], val);
92*d6dfd9efSDavid du Colombier nconf++;
93*d6dfd9efSDavid du Colombier }
94*d6dfd9efSDavid du Colombier
95*d6dfd9efSDavid du Colombier static void
plan9iniinit(void)96*d6dfd9efSDavid du Colombier plan9iniinit(void)
97*d6dfd9efSDavid du Colombier {
98*d6dfd9efSDavid du Colombier /* virtex configuration */
99*d6dfd9efSDavid du Colombier setconf("nvram", "/boot/nvram");
100*d6dfd9efSDavid du Colombier setconf("nvroff", "0");
101*d6dfd9efSDavid du Colombier setconf("nvrlen", "512");
102*d6dfd9efSDavid du Colombier
103*d6dfd9efSDavid du Colombier setconf("aoeif", "ether0");
104*d6dfd9efSDavid du Colombier setconf("aoedev", "e!#æ/aoe/1.0");
105*d6dfd9efSDavid du Colombier }
106*d6dfd9efSDavid du Colombier
107*d6dfd9efSDavid du Colombier char*
getenv(char * name,char * buf,int n)108*d6dfd9efSDavid du Colombier getenv(char* name, char* buf, int n)
109*d6dfd9efSDavid du Colombier {
110*d6dfd9efSDavid du Colombier char *e, *p, *q;
111*d6dfd9efSDavid du Colombier
112*d6dfd9efSDavid du Colombier p = oenv;
113*d6dfd9efSDavid du Colombier while(*p != 0){
114*d6dfd9efSDavid du Colombier if((e = strchr(p, '=')) == nil)
115*d6dfd9efSDavid du Colombier break;
116*d6dfd9efSDavid du Colombier for(q = name; p < e; p++){
117*d6dfd9efSDavid du Colombier if(*p != *q)
118*d6dfd9efSDavid du Colombier break;
119*d6dfd9efSDavid du Colombier q++;
120*d6dfd9efSDavid du Colombier }
121*d6dfd9efSDavid du Colombier if(p == e && *q == 0){
122*d6dfd9efSDavid du Colombier strecpy(buf, buf+n, e+1);
123*d6dfd9efSDavid du Colombier return buf;
124*d6dfd9efSDavid du Colombier }
125*d6dfd9efSDavid du Colombier p += strlen(p)+1;
126*d6dfd9efSDavid du Colombier }
127*d6dfd9efSDavid du Colombier
128*d6dfd9efSDavid du Colombier return nil;
129*d6dfd9efSDavid du Colombier }
130*d6dfd9efSDavid du Colombier
131*d6dfd9efSDavid du Colombier static void
optionsinit(char * s)132*d6dfd9efSDavid du Colombier optionsinit(char* s)
133*d6dfd9efSDavid du Colombier {
134*d6dfd9efSDavid du Colombier char *o;
135*d6dfd9efSDavid du Colombier
136*d6dfd9efSDavid du Colombier o = strecpy(oargb, oargb+sizeof(oargb), s)+1;
137*d6dfd9efSDavid du Colombier if(getenv("bootargs", o, o - oargb) != nil)
138*d6dfd9efSDavid du Colombier *(o-1) = ' ';
139*d6dfd9efSDavid du Colombier
140*d6dfd9efSDavid du Colombier oargblen = strlen(oargb);
141*d6dfd9efSDavid du Colombier oargc = tokenize(oargb, oargv, nelem(oargv)-1);
142*d6dfd9efSDavid du Colombier oargv[oargc] = nil;
143*d6dfd9efSDavid du Colombier }
144*d6dfd9efSDavid du Colombier
145*d6dfd9efSDavid du Colombier void
main(void)146*d6dfd9efSDavid du Colombier main(void)
147*d6dfd9efSDavid du Colombier {
148*d6dfd9efSDavid du Colombier int machno;
149*d6dfd9efSDavid du Colombier
150*d6dfd9efSDavid du Colombier /* entry to main pushed stuff onto the stack. */
151*d6dfd9efSDavid du Colombier
152*d6dfd9efSDavid du Colombier // memset(edata, 0, (ulong)end-(ulong)edata);
153*d6dfd9efSDavid du Colombier
154*d6dfd9efSDavid du Colombier machno = getpir();
155*d6dfd9efSDavid du Colombier if (machno > 0)
156*d6dfd9efSDavid du Colombier startcpu(machno);
157*d6dfd9efSDavid du Colombier
158*d6dfd9efSDavid du Colombier // dcrcompile();
159*d6dfd9efSDavid du Colombier if (dverify != 0x01020304) {
160*d6dfd9efSDavid du Colombier uartlputs("data segment not initialised\n");
161*d6dfd9efSDavid du Colombier panic("data segment not initialised");
162*d6dfd9efSDavid du Colombier }
163*d6dfd9efSDavid du Colombier if (bverify != 0) {
164*d6dfd9efSDavid du Colombier uartlputs("bss segment not zeroed\n");
165*d6dfd9efSDavid du Colombier panic("bss segment not zeroed");
166*d6dfd9efSDavid du Colombier }
167*d6dfd9efSDavid du Colombier mach0init();
168*d6dfd9efSDavid du Colombier archreset();
169*d6dfd9efSDavid du Colombier quotefmtinstall();
170*d6dfd9efSDavid du Colombier optionsinit("/boot/boot boot");
171*d6dfd9efSDavid du Colombier // archconsole();
172*d6dfd9efSDavid du Colombier
173*d6dfd9efSDavid du Colombier meminit();
174*d6dfd9efSDavid du Colombier confinit();
175*d6dfd9efSDavid du Colombier mmuinit();
176*d6dfd9efSDavid du Colombier xinit(); /* xinit would print if it could */
177*d6dfd9efSDavid du Colombier trapinit();
178*d6dfd9efSDavid du Colombier qtminit();
179*d6dfd9efSDavid du Colombier ioinit();
180*d6dfd9efSDavid du Colombier uncinit();
181*d6dfd9efSDavid du Colombier printinit();
182*d6dfd9efSDavid du Colombier uartliteconsole();
183*d6dfd9efSDavid du Colombier
184*d6dfd9efSDavid du Colombier mainmem->flags |= POOL_ANTAGONISM;
185*d6dfd9efSDavid du Colombier mainmem->panic = mypanic;
186*d6dfd9efSDavid du Colombier ethermedium.maxtu = 1512; /* must be multiple of 4 for temac's dma */
187*d6dfd9efSDavid du Colombier
188*d6dfd9efSDavid du Colombier // print("\n\nPlan 9k H\n"); /* already printed by l.s */
189*d6dfd9efSDavid du Colombier plan9iniinit();
190*d6dfd9efSDavid du Colombier timersinit();
191*d6dfd9efSDavid du Colombier clockinit();
192*d6dfd9efSDavid du Colombier
193*d6dfd9efSDavid du Colombier dma0init(); /* does not start kprocs; see init0 */
194*d6dfd9efSDavid du Colombier fpuinit();
195*d6dfd9efSDavid du Colombier procinit0();
196*d6dfd9efSDavid du Colombier initseg();
197*d6dfd9efSDavid du Colombier links();
198*d6dfd9efSDavid du Colombier
199*d6dfd9efSDavid du Colombier chandevreset();
200*d6dfd9efSDavid du Colombier okprint = 1; /* only now can we print */
201*d6dfd9efSDavid du Colombier barriers();
202*d6dfd9efSDavid du Colombier dcflush((uintptr)&okprint, sizeof okprint);
203*d6dfd9efSDavid du Colombier
204*d6dfd9efSDavid du Colombier cpuidprint();
205*d6dfd9efSDavid du Colombier
206*d6dfd9efSDavid du Colombier print("%d Hz clock", HZ);
207*d6dfd9efSDavid du Colombier print("; memory size %,ud (%#ux)\n", (uint)memsz, (uint)memsz);
208*d6dfd9efSDavid du Colombier
209*d6dfd9efSDavid du Colombier pageinit();
210*d6dfd9efSDavid du Colombier swapinit();
211*d6dfd9efSDavid du Colombier userinit();
212*d6dfd9efSDavid du Colombier active.thunderbirdsarego = 1;
213*d6dfd9efSDavid du Colombier dcflush((uintptr)&active.thunderbirdsarego,
214*d6dfd9efSDavid du Colombier sizeof active.thunderbirdsarego);
215*d6dfd9efSDavid du Colombier schedinit();
216*d6dfd9efSDavid du Colombier /* no return */
217*d6dfd9efSDavid du Colombier panic("schedinit returned");
218*d6dfd9efSDavid du Colombier }
219*d6dfd9efSDavid du Colombier
220*d6dfd9efSDavid du Colombier void
confinit(void)221*d6dfd9efSDavid du Colombier confinit(void)
222*d6dfd9efSDavid du Colombier {
223*d6dfd9efSDavid du Colombier char *p;
224*d6dfd9efSDavid du Colombier int i, userpcnt;
225*d6dfd9efSDavid du Colombier ulong kpages;
226*d6dfd9efSDavid du Colombier
227*d6dfd9efSDavid du Colombier if(p = getconf("*kernelpercent"))
228*d6dfd9efSDavid du Colombier userpcnt = 100 - strtol(p, 0, 0);
229*d6dfd9efSDavid du Colombier else
230*d6dfd9efSDavid du Colombier userpcnt = 85;
231*d6dfd9efSDavid du Colombier
232*d6dfd9efSDavid du Colombier conf.npage = 0;
233*d6dfd9efSDavid du Colombier for(i=0; i<nelem(conf.mem); i++)
234*d6dfd9efSDavid du Colombier conf.npage += conf.mem[i].npage;
235*d6dfd9efSDavid du Colombier
236*d6dfd9efSDavid du Colombier /* see machninit for nmach setting */
237*d6dfd9efSDavid du Colombier conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
238*d6dfd9efSDavid du Colombier if(conf.nproc > 2000)
239*d6dfd9efSDavid du Colombier conf.nproc = 2000;
240*d6dfd9efSDavid du Colombier conf.nimage = 200;
241*d6dfd9efSDavid du Colombier conf.nswap = conf.nproc*80;
242*d6dfd9efSDavid du Colombier conf.nswppo = 4096;
243*d6dfd9efSDavid du Colombier conf.copymode = 0; /* copy on write */
244*d6dfd9efSDavid du Colombier
245*d6dfd9efSDavid du Colombier if(userpcnt < 10)
246*d6dfd9efSDavid du Colombier userpcnt = 60;
247*d6dfd9efSDavid du Colombier kpages = conf.npage - (conf.npage*userpcnt)/100;
248*d6dfd9efSDavid du Colombier
249*d6dfd9efSDavid du Colombier conf.upages = conf.npage - kpages;
250*d6dfd9efSDavid du Colombier conf.ialloc = (kpages/2)*BY2PG;
251*d6dfd9efSDavid du Colombier
252*d6dfd9efSDavid du Colombier kpages *= BY2PG;
253*d6dfd9efSDavid du Colombier kpages -= conf.upages*sizeof(Page)
254*d6dfd9efSDavid du Colombier + conf.nproc*sizeof(Proc)
255*d6dfd9efSDavid du Colombier + conf.nimage*sizeof(Image)
256*d6dfd9efSDavid du Colombier + conf.nswap
257*d6dfd9efSDavid du Colombier + conf.nswppo*sizeof(Page);
258*d6dfd9efSDavid du Colombier mainmem->maxsize = kpages;
259*d6dfd9efSDavid du Colombier }
260*d6dfd9efSDavid du Colombier
261*d6dfd9efSDavid du Colombier void
init0(void)262*d6dfd9efSDavid du Colombier init0(void)
263*d6dfd9efSDavid du Colombier {
264*d6dfd9efSDavid du Colombier int i;
265*d6dfd9efSDavid du Colombier char buf[2*KNAMELEN];
266*d6dfd9efSDavid du Colombier
267*d6dfd9efSDavid du Colombier assert(up != nil);
268*d6dfd9efSDavid du Colombier up->nerrlab = 0;
269*d6dfd9efSDavid du Colombier barriers();
270*d6dfd9efSDavid du Colombier intrack(~0);
271*d6dfd9efSDavid du Colombier clrmchk();
272*d6dfd9efSDavid du Colombier barriers();
273*d6dfd9efSDavid du Colombier spllo();
274*d6dfd9efSDavid du Colombier
275*d6dfd9efSDavid du Colombier /*
276*d6dfd9efSDavid du Colombier * These are o.k. because rootinit is null.
277*d6dfd9efSDavid du Colombier * Then early kproc's will have a root and dot.
278*d6dfd9efSDavid du Colombier */
279*d6dfd9efSDavid du Colombier up->slash = namec("#/", Atodir, 0, 0);
280*d6dfd9efSDavid du Colombier pathclose(up->slash->path);
281*d6dfd9efSDavid du Colombier up->slash->path = newpath("/");
282*d6dfd9efSDavid du Colombier up->dot = cclone(up->slash);
283*d6dfd9efSDavid du Colombier
284*d6dfd9efSDavid du Colombier dmainit(); /* starts dma kprocs */
285*d6dfd9efSDavid du Colombier devtabinit();
286*d6dfd9efSDavid du Colombier
287*d6dfd9efSDavid du Colombier if(!waserror()){
288*d6dfd9efSDavid du Colombier snprint(buf, sizeof(buf), "power %s", conffile);
289*d6dfd9efSDavid du Colombier ksetenv("terminal", buf, 0);
290*d6dfd9efSDavid du Colombier ksetenv("cputype", "power", 0);
291*d6dfd9efSDavid du Colombier if(cpuserver)
292*d6dfd9efSDavid du Colombier ksetenv("service", "cpu", 0);
293*d6dfd9efSDavid du Colombier else
294*d6dfd9efSDavid du Colombier ksetenv("service", "terminal", 0);
295*d6dfd9efSDavid du Colombier
296*d6dfd9efSDavid du Colombier /* virtex configuration */
297*d6dfd9efSDavid du Colombier ksetenv("nvram", "/boot/nvram", 0);
298*d6dfd9efSDavid du Colombier ksetenv("nvroff", "0", 0);
299*d6dfd9efSDavid du Colombier ksetenv("nvrlen", "512", 0);
300*d6dfd9efSDavid du Colombier
301*d6dfd9efSDavid du Colombier ksetenv("nobootprompt", "tcp", 0);
302*d6dfd9efSDavid du Colombier
303*d6dfd9efSDavid du Colombier poperror();
304*d6dfd9efSDavid du Colombier }
305*d6dfd9efSDavid du Colombier for(i = 0; i < nconf; i++){
306*d6dfd9efSDavid du Colombier if(confval[i] == nil)
307*d6dfd9efSDavid du Colombier continue;
308*d6dfd9efSDavid du Colombier if(confname[i][0] != '*'){
309*d6dfd9efSDavid du Colombier if(!waserror()){
310*d6dfd9efSDavid du Colombier ksetenv(confname[i], confval[i], 0);
311*d6dfd9efSDavid du Colombier poperror();
312*d6dfd9efSDavid du Colombier }
313*d6dfd9efSDavid du Colombier }
314*d6dfd9efSDavid du Colombier if(!waserror()){
315*d6dfd9efSDavid du Colombier ksetenv(confname[i], confval[i], 1);
316*d6dfd9efSDavid du Colombier poperror();
317*d6dfd9efSDavid du Colombier }
318*d6dfd9efSDavid du Colombier }
319*d6dfd9efSDavid du Colombier
320*d6dfd9efSDavid du Colombier kproc("alarm", alarmkproc, 0);
321*d6dfd9efSDavid du Colombier if (securemem)
322*d6dfd9efSDavid du Colombier kproc("mutate", mutateproc, 0);
323*d6dfd9efSDavid du Colombier else
324*d6dfd9efSDavid du Colombier print("no secure memory found\n");
325*d6dfd9efSDavid du Colombier
326*d6dfd9efSDavid du Colombier /*
327*d6dfd9efSDavid du Colombier * The initial value of the user stack must be such
328*d6dfd9efSDavid du Colombier * that the total used is larger than the maximum size
329*d6dfd9efSDavid du Colombier * of the argument list checked in syscall.
330*d6dfd9efSDavid du Colombier */
331*d6dfd9efSDavid du Colombier sync();
332*d6dfd9efSDavid du Colombier isync();
333*d6dfd9efSDavid du Colombier touser(sp);
334*d6dfd9efSDavid du Colombier }
335*d6dfd9efSDavid du Colombier
336*d6dfd9efSDavid du Colombier static void
bootargs(uintptr base)337*d6dfd9efSDavid du Colombier bootargs(uintptr base)
338*d6dfd9efSDavid du Colombier {
339*d6dfd9efSDavid du Colombier int i;
340*d6dfd9efSDavid du Colombier ulong ssize;
341*d6dfd9efSDavid du Colombier char **av, *p;
342*d6dfd9efSDavid du Colombier
343*d6dfd9efSDavid du Colombier /*
344*d6dfd9efSDavid du Colombier * Push the boot args onto the stack.
345*d6dfd9efSDavid du Colombier * The initial value of the user stack must be such
346*d6dfd9efSDavid du Colombier * that the total used is larger than the maximum size
347*d6dfd9efSDavid du Colombier * of the argument list checked in syscall.
348*d6dfd9efSDavid du Colombier */
349*d6dfd9efSDavid du Colombier i = oargblen+1;
350*d6dfd9efSDavid du Colombier p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(up->s.args) - i));
351*d6dfd9efSDavid du Colombier memmove(p, oargb, i);
352*d6dfd9efSDavid du Colombier
353*d6dfd9efSDavid du Colombier /*
354*d6dfd9efSDavid du Colombier * Now push argc and the argv pointers.
355*d6dfd9efSDavid du Colombier * This isn't strictly correct as the code jumped to by
356*d6dfd9efSDavid du Colombier * touser in init9.s calls startboot (port/initcode.c) which
357*d6dfd9efSDavid du Colombier * expects arguments
358*d6dfd9efSDavid du Colombier * startboot(char *argv0, char **argv)
359*d6dfd9efSDavid du Colombier * not the usual (int argc, char* argv[]), but argv0 is
360*d6dfd9efSDavid du Colombier * unused so it doesn't matter (at the moment...).
361*d6dfd9efSDavid du Colombier */
362*d6dfd9efSDavid du Colombier av = (char**)(p - (oargc+2)*sizeof(char*));
363*d6dfd9efSDavid du Colombier ssize = base + BY2PG - PTR2UINT(av);
364*d6dfd9efSDavid du Colombier *av++ = (char*)oargc;
365*d6dfd9efSDavid du Colombier for(i = 0; i < oargc; i++)
366*d6dfd9efSDavid du Colombier *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
367*d6dfd9efSDavid du Colombier *av = nil;
368*d6dfd9efSDavid du Colombier
369*d6dfd9efSDavid du Colombier /*
370*d6dfd9efSDavid du Colombier * Leave space for the return PC of the
371*d6dfd9efSDavid du Colombier * caller of initcode.
372*d6dfd9efSDavid du Colombier */
373*d6dfd9efSDavid du Colombier sp = USTKTOP - ssize - sizeof(void*);
374*d6dfd9efSDavid du Colombier }
375*d6dfd9efSDavid du Colombier
376*d6dfd9efSDavid du Colombier void
userinit(void)377*d6dfd9efSDavid du Colombier userinit(void)
378*d6dfd9efSDavid du Colombier {
379*d6dfd9efSDavid du Colombier Proc *p;
380*d6dfd9efSDavid du Colombier Segment *s;
381*d6dfd9efSDavid du Colombier KMap *k;
382*d6dfd9efSDavid du Colombier Page *pg;
383*d6dfd9efSDavid du Colombier
384*d6dfd9efSDavid du Colombier /* no processes yet */
385*d6dfd9efSDavid du Colombier up = nil;
386*d6dfd9efSDavid du Colombier
387*d6dfd9efSDavid du Colombier p = newproc();
388*d6dfd9efSDavid du Colombier p->pgrp = newpgrp();
389*d6dfd9efSDavid du Colombier p->egrp = smalloc(sizeof(Egrp));
390*d6dfd9efSDavid du Colombier p->egrp->ref = 1;
391*d6dfd9efSDavid du Colombier p->fgrp = dupfgrp(nil);
392*d6dfd9efSDavid du Colombier p->rgrp = newrgrp();
393*d6dfd9efSDavid du Colombier p->procmode = 0640;
394*d6dfd9efSDavid du Colombier
395*d6dfd9efSDavid du Colombier kstrdup(&eve, "");
396*d6dfd9efSDavid du Colombier kstrdup(&p->text, "*init*");
397*d6dfd9efSDavid du Colombier kstrdup(&p->user, eve);
398*d6dfd9efSDavid du Colombier
399*d6dfd9efSDavid du Colombier /*
400*d6dfd9efSDavid du Colombier * Kernel Stack
401*d6dfd9efSDavid du Colombier */
402*d6dfd9efSDavid du Colombier p->sched.pc = PTR2UINT(init0);
403*d6dfd9efSDavid du Colombier p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
404*d6dfd9efSDavid du Colombier p->sched.sp = STACKALIGN(p->sched.sp);
405*d6dfd9efSDavid du Colombier
406*d6dfd9efSDavid du Colombier /*
407*d6dfd9efSDavid du Colombier * User Stack
408*d6dfd9efSDavid du Colombier *
409*d6dfd9efSDavid du Colombier * Technically, newpage can't be called here because it
410*d6dfd9efSDavid du Colombier * should only be called when in a user context as it may
411*d6dfd9efSDavid du Colombier * try to sleep if there are no pages available, but that
412*d6dfd9efSDavid du Colombier * shouldn't be the case here.
413*d6dfd9efSDavid du Colombier */
414*d6dfd9efSDavid du Colombier s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
415*d6dfd9efSDavid du Colombier p->seg[SSEG] = s;
416*d6dfd9efSDavid du Colombier pg = newpage(1, 0, USTKTOP-BY2PG);
417*d6dfd9efSDavid du Colombier segpage(s, pg);
418*d6dfd9efSDavid du Colombier k = kmap(pg);
419*d6dfd9efSDavid du Colombier bootargs(VA(k));
420*d6dfd9efSDavid du Colombier kunmap(k);
421*d6dfd9efSDavid du Colombier
422*d6dfd9efSDavid du Colombier /*
423*d6dfd9efSDavid du Colombier * Text
424*d6dfd9efSDavid du Colombier */
425*d6dfd9efSDavid du Colombier s = newseg(SG_TEXT, UTZERO, 1);
426*d6dfd9efSDavid du Colombier s->flushme++;
427*d6dfd9efSDavid du Colombier p->seg[TSEG] = s;
428*d6dfd9efSDavid du Colombier pg = newpage(1, 0, UTZERO);
429*d6dfd9efSDavid du Colombier memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
430*d6dfd9efSDavid du Colombier segpage(s, pg);
431*d6dfd9efSDavid du Colombier k = kmap(s->map[0]->pages[0]);
432*d6dfd9efSDavid du Colombier memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
433*d6dfd9efSDavid du Colombier sync();
434*d6dfd9efSDavid du Colombier kunmap(k);
435*d6dfd9efSDavid du Colombier
436*d6dfd9efSDavid du Colombier ready(p);
437*d6dfd9efSDavid du Colombier }
438*d6dfd9efSDavid du Colombier
439*d6dfd9efSDavid du Colombier /*
440*d6dfd9efSDavid du Colombier * power-saving wait for interrupt when nothing ready.
441*d6dfd9efSDavid du Colombier * ../port/proc.c should really call this splhi itself
442*d6dfd9efSDavid du Colombier * to avoid the race avoided here by the call to anyready
443*d6dfd9efSDavid du Colombier */
444*d6dfd9efSDavid du Colombier void
idlehands(void)445*d6dfd9efSDavid du Colombier idlehands(void)
446*d6dfd9efSDavid du Colombier {
447*d6dfd9efSDavid du Colombier int s, oldbits;
448*d6dfd9efSDavid du Colombier
449*d6dfd9efSDavid du Colombier /* we only use one processor, no matter what */
450*d6dfd9efSDavid du Colombier // if (conf.nmach > 1)
451*d6dfd9efSDavid du Colombier // return;
452*d6dfd9efSDavid du Colombier s = splhi();
453*d6dfd9efSDavid du Colombier if(!anyready()) {
454*d6dfd9efSDavid du Colombier oldbits = lightstate(Ledidle);
455*d6dfd9efSDavid du Colombier putmsr(getmsr() | MSR_WE | MSR_EE | MSR_CE); /* MSR_DE too? */
456*d6dfd9efSDavid du Colombier lightstate(oldbits);
457*d6dfd9efSDavid du Colombier }
458*d6dfd9efSDavid du Colombier splx(s);
459*d6dfd9efSDavid du Colombier }
460*d6dfd9efSDavid du Colombier
461*d6dfd9efSDavid du Colombier /*
462*d6dfd9efSDavid du Colombier * set mach dependent process state for a new process
463*d6dfd9efSDavid du Colombier */
464*d6dfd9efSDavid du Colombier void
procsetup(Proc * p)465*d6dfd9efSDavid du Colombier procsetup(Proc* p)
466*d6dfd9efSDavid du Colombier {
467*d6dfd9efSDavid du Colombier fpusysprocsetup(p);
468*d6dfd9efSDavid du Colombier }
469*d6dfd9efSDavid du Colombier
470*d6dfd9efSDavid du Colombier /*
471*d6dfd9efSDavid du Colombier * Save the mach dependent part of the process state.
472*d6dfd9efSDavid du Colombier */
473*d6dfd9efSDavid du Colombier void
procsave(Proc * p)474*d6dfd9efSDavid du Colombier procsave(Proc *p)
475*d6dfd9efSDavid du Colombier {
476*d6dfd9efSDavid du Colombier fpuprocsave(p);
477*d6dfd9efSDavid du Colombier }
478*d6dfd9efSDavid du Colombier
479*d6dfd9efSDavid du Colombier void
shutdown(int ispanic)480*d6dfd9efSDavid du Colombier shutdown(int ispanic)
481*d6dfd9efSDavid du Colombier {
482*d6dfd9efSDavid du Colombier int ms, once;
483*d6dfd9efSDavid du Colombier
484*d6dfd9efSDavid du Colombier lock(&active);
485*d6dfd9efSDavid du Colombier if(ispanic)
486*d6dfd9efSDavid du Colombier active.ispanic = ispanic;
487*d6dfd9efSDavid du Colombier else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
488*d6dfd9efSDavid du Colombier active.ispanic = 0;
489*d6dfd9efSDavid du Colombier once = active.machs & (1<<m->machno);
490*d6dfd9efSDavid du Colombier active.machs &= ~(1<<m->machno);
491*d6dfd9efSDavid du Colombier active.exiting = 1;
492*d6dfd9efSDavid du Colombier unlock(&active);
493*d6dfd9efSDavid du Colombier
494*d6dfd9efSDavid du Colombier if(once)
495*d6dfd9efSDavid du Colombier print("cpu%d: exiting\n", m->machno);
496*d6dfd9efSDavid du Colombier spllo();
497*d6dfd9efSDavid du Colombier for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
498*d6dfd9efSDavid du Colombier delay(TK2MS(2));
499*d6dfd9efSDavid du Colombier if(active.machs == 0 && consactive() == 0)
500*d6dfd9efSDavid du Colombier break;
501*d6dfd9efSDavid du Colombier }
502*d6dfd9efSDavid du Colombier
503*d6dfd9efSDavid du Colombier #ifdef notdef
504*d6dfd9efSDavid du Colombier if(active.ispanic && m->machno == 0){
505*d6dfd9efSDavid du Colombier if(cpuserver)
506*d6dfd9efSDavid du Colombier delay(30000);
507*d6dfd9efSDavid du Colombier else
508*d6dfd9efSDavid du Colombier for(;;)
509*d6dfd9efSDavid du Colombier halt();
510*d6dfd9efSDavid du Colombier }
511*d6dfd9efSDavid du Colombier else
512*d6dfd9efSDavid du Colombier #endif /* notdef */
513*d6dfd9efSDavid du Colombier delay(1000);
514*d6dfd9efSDavid du Colombier }
515*d6dfd9efSDavid du Colombier
516*d6dfd9efSDavid du Colombier void
writeconf(void)517*d6dfd9efSDavid du Colombier writeconf(void)
518*d6dfd9efSDavid du Colombier {
519*d6dfd9efSDavid du Colombier char *p, *q;
520*d6dfd9efSDavid du Colombier int n;
521*d6dfd9efSDavid du Colombier
522*d6dfd9efSDavid du Colombier p = getconfenv();
523*d6dfd9efSDavid du Colombier
524*d6dfd9efSDavid du Colombier if(waserror()) {
525*d6dfd9efSDavid du Colombier free(p);
526*d6dfd9efSDavid du Colombier nexterror();
527*d6dfd9efSDavid du Colombier }
528*d6dfd9efSDavid du Colombier
529*d6dfd9efSDavid du Colombier /* convert to name=value\n format */
530*d6dfd9efSDavid du Colombier for(q=p; *q; q++) {
531*d6dfd9efSDavid du Colombier q += strlen(q);
532*d6dfd9efSDavid du Colombier *q = '=';
533*d6dfd9efSDavid du Colombier q += strlen(q);
534*d6dfd9efSDavid du Colombier *q = '\n';
535*d6dfd9efSDavid du Colombier }
536*d6dfd9efSDavid du Colombier n = q - p + 1;
537*d6dfd9efSDavid du Colombier if(n >= BOOTARGSLEN)
538*d6dfd9efSDavid du Colombier error("kernel configuration too large");
539*d6dfd9efSDavid du Colombier memset(BOOTLINE, 0, BOOTLINELEN); /* zero 9load boot line */
540*d6dfd9efSDavid du Colombier memmove(BOOTARGS, p, n);
541*d6dfd9efSDavid du Colombier poperror();
542*d6dfd9efSDavid du Colombier free(p);
543*d6dfd9efSDavid du Colombier }
544*d6dfd9efSDavid du Colombier
545*d6dfd9efSDavid du Colombier void
archreboot(void)546*d6dfd9efSDavid du Colombier archreboot(void)
547*d6dfd9efSDavid du Colombier {
548*d6dfd9efSDavid du Colombier splhi();
549*d6dfd9efSDavid du Colombier iprint("reboot requested; going into wait state\n");
550*d6dfd9efSDavid du Colombier for(;;)
551*d6dfd9efSDavid du Colombier putmsr(getmsr() | MSR_WE);
552*d6dfd9efSDavid du Colombier }
553*d6dfd9efSDavid du Colombier
554*d6dfd9efSDavid du Colombier void
exit(int ispanic)555*d6dfd9efSDavid du Colombier exit(int ispanic)
556*d6dfd9efSDavid du Colombier {
557*d6dfd9efSDavid du Colombier shutdown(ispanic);
558*d6dfd9efSDavid du Colombier archreboot();
559*d6dfd9efSDavid du Colombier }
560*d6dfd9efSDavid du Colombier
561*d6dfd9efSDavid du Colombier static int
findconf(char * name)562*d6dfd9efSDavid du Colombier findconf(char *name)
563*d6dfd9efSDavid du Colombier {
564*d6dfd9efSDavid du Colombier int i;
565*d6dfd9efSDavid du Colombier
566*d6dfd9efSDavid du Colombier for(i = 0; i < nconf; i++)
567*d6dfd9efSDavid du Colombier if(cistrcmp(confname[i], name) == 0)
568*d6dfd9efSDavid du Colombier return i;
569*d6dfd9efSDavid du Colombier return -1;
570*d6dfd9efSDavid du Colombier }
571*d6dfd9efSDavid du Colombier
572*d6dfd9efSDavid du Colombier void
addconf(char * name,char * val)573*d6dfd9efSDavid du Colombier addconf(char *name, char *val)
574*d6dfd9efSDavid du Colombier {
575*d6dfd9efSDavid du Colombier int i;
576*d6dfd9efSDavid du Colombier
577*d6dfd9efSDavid du Colombier i = findconf(name);
578*d6dfd9efSDavid du Colombier if(i < 0){
579*d6dfd9efSDavid du Colombier if(val == nil || nconf >= MAXCONF)
580*d6dfd9efSDavid du Colombier return;
581*d6dfd9efSDavid du Colombier i = nconf++;
582*d6dfd9efSDavid du Colombier strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
583*d6dfd9efSDavid du Colombier }
584*d6dfd9efSDavid du Colombier confval[i] = val;
585*d6dfd9efSDavid du Colombier }
586*d6dfd9efSDavid du Colombier
587*d6dfd9efSDavid du Colombier char*
getconf(char * name)588*d6dfd9efSDavid du Colombier getconf(char *name)
589*d6dfd9efSDavid du Colombier {
590*d6dfd9efSDavid du Colombier int i;
591*d6dfd9efSDavid du Colombier
592*d6dfd9efSDavid du Colombier i = findconf(name);
593*d6dfd9efSDavid du Colombier if(i >= 0)
594*d6dfd9efSDavid du Colombier return confval[i];
595*d6dfd9efSDavid du Colombier return nil;
596*d6dfd9efSDavid du Colombier }
597*d6dfd9efSDavid du Colombier
598*d6dfd9efSDavid du Colombier void
dump(void * vaddr,int words)599*d6dfd9efSDavid du Colombier dump(void *vaddr, int words)
600*d6dfd9efSDavid du Colombier {
601*d6dfd9efSDavid du Colombier ulong *addr;
602*d6dfd9efSDavid du Colombier
603*d6dfd9efSDavid du Colombier addr = vaddr;
604*d6dfd9efSDavid du Colombier while (words-- > 0)
605*d6dfd9efSDavid du Colombier print("%.8lux%c", *addr++, words % 8 == 0? '\n': ' ');
606*d6dfd9efSDavid du Colombier }
607