1*a81c3ea0SDavid du Colombier #include "u.h"
2*a81c3ea0SDavid du Colombier #include "../port/lib.h"
3*a81c3ea0SDavid du Colombier #include "mem.h"
4*a81c3ea0SDavid du Colombier #include "dat.h"
5*a81c3ea0SDavid du Colombier #include "fns.h"
6*a81c3ea0SDavid du Colombier #include "io.h"
7*a81c3ea0SDavid du Colombier #include "../ip/ip.h"
8*a81c3ea0SDavid du Colombier #include <pool.h>
9*a81c3ea0SDavid du Colombier #include <tos.h>
10*a81c3ea0SDavid du Colombier #include <bootexec.h>
11*a81c3ea0SDavid du Colombier #include "init.h"
12*a81c3ea0SDavid du Colombier #include "reboot.h"
13*a81c3ea0SDavid du Colombier
14*a81c3ea0SDavid du Colombier enum {
15*a81c3ea0SDavid du Colombier /* space for syscall args, return PC, top-of-stack struct */
16*a81c3ea0SDavid du Colombier Stkheadroom = sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),
17*a81c3ea0SDavid du Colombier };
18*a81c3ea0SDavid du Colombier
19*a81c3ea0SDavid du Colombier typedef struct mipsexec Mipsexec;
20*a81c3ea0SDavid du Colombier
21*a81c3ea0SDavid du Colombier #define MAXCONF 64
22*a81c3ea0SDavid du Colombier #define CONFBUFLEN 4096
23*a81c3ea0SDavid du Colombier #define MAXBOOTENV 256
24*a81c3ea0SDavid du Colombier
25*a81c3ea0SDavid du Colombier /* only for reboot */
26*a81c3ea0SDavid du Colombier #define BOOTARGS ((char*)(CONFADDR))
27*a81c3ea0SDavid du Colombier #define BOOTARGSLEN CONFBUFLEN
28*a81c3ea0SDavid du Colombier #define CONFARGVLEN (MAXCONF*BY2WD)
29*a81c3ea0SDavid du Colombier
30*a81c3ea0SDavid du Colombier /* args passed by boot loader for main() */
31*a81c3ea0SDavid du Colombier int _argc;
32*a81c3ea0SDavid du Colombier char **_argv;
33*a81c3ea0SDavid du Colombier char **_env;
34*a81c3ea0SDavid du Colombier static char *bootenvname[MAXBOOTENV];
35*a81c3ea0SDavid du Colombier static char *bootenvval[MAXBOOTENV];
36*a81c3ea0SDavid du Colombier static int nenv;
37*a81c3ea0SDavid du Colombier
38*a81c3ea0SDavid du Colombier /* plan9.ini */
39*a81c3ea0SDavid du Colombier static char confbuf[CONFBUFLEN];
40*a81c3ea0SDavid du Colombier static char *confname[MAXCONF];
41*a81c3ea0SDavid du Colombier static char *confval[MAXCONF];
42*a81c3ea0SDavid du Colombier static int nconf;
43*a81c3ea0SDavid du Colombier
44*a81c3ea0SDavid du Colombier /*
45*a81c3ea0SDavid du Colombier * Option arguments from the command line.
46*a81c3ea0SDavid du Colombier * oargv[0] is the boot file.
47*a81c3ea0SDavid du Colombier */
48*a81c3ea0SDavid du Colombier static int oargc;
49*a81c3ea0SDavid du Colombier static char* oargv[20];
50*a81c3ea0SDavid du Colombier static char oargb[128];
51*a81c3ea0SDavid du Colombier static int oargblen;
52*a81c3ea0SDavid du Colombier
53*a81c3ea0SDavid du Colombier static uintptr sp; /* XXX - must go - user stack of init proc */
54*a81c3ea0SDavid du Colombier
55*a81c3ea0SDavid du Colombier /*
56*a81c3ea0SDavid du Colombier * software tlb simulation
57*a81c3ea0SDavid du Colombier */
58*a81c3ea0SDavid du Colombier static Softtlb stlb[MAXMACH][STLBSIZE];
59*a81c3ea0SDavid du Colombier
60*a81c3ea0SDavid du Colombier Mach *machaddr[MAXMACH];
61*a81c3ea0SDavid du Colombier Conf conf;
62*a81c3ea0SDavid du Colombier ulong memsize;
63*a81c3ea0SDavid du Colombier FPsave initfp;
64*a81c3ea0SDavid du Colombier
65*a81c3ea0SDavid du Colombier int normalprint;
66*a81c3ea0SDavid du Colombier ulong cpufreq;
67*a81c3ea0SDavid du Colombier
68*a81c3ea0SDavid du Colombier /*
69*a81c3ea0SDavid du Colombier * initialize a processor's mach structure. each processor does this
70*a81c3ea0SDavid du Colombier * for itself.
71*a81c3ea0SDavid du Colombier */
72*a81c3ea0SDavid du Colombier void
machinit(void)73*a81c3ea0SDavid du Colombier machinit(void)
74*a81c3ea0SDavid du Colombier {
75*a81c3ea0SDavid du Colombier /* Ensure CU1 is off */
76*a81c3ea0SDavid du Colombier clrfpintr();
77*a81c3ea0SDavid du Colombier
78*a81c3ea0SDavid du Colombier m->stb = &stlb[m->machno][0];
79*a81c3ea0SDavid du Colombier
80*a81c3ea0SDavid du Colombier clockinit();
81*a81c3ea0SDavid du Colombier }
82*a81c3ea0SDavid du Colombier
83*a81c3ea0SDavid du Colombier static void
optionsinit(char * s)84*a81c3ea0SDavid du Colombier optionsinit(char* s)
85*a81c3ea0SDavid du Colombier {
86*a81c3ea0SDavid du Colombier strecpy(oargb, oargb+sizeof(oargb), s);
87*a81c3ea0SDavid du Colombier
88*a81c3ea0SDavid du Colombier oargblen = strlen(oargb);
89*a81c3ea0SDavid du Colombier oargc = tokenize(oargb, oargv, nelem(oargv)-1);
90*a81c3ea0SDavid du Colombier oargv[oargc] = nil;
91*a81c3ea0SDavid du Colombier }
92*a81c3ea0SDavid du Colombier
93*a81c3ea0SDavid du Colombier void
plan9iniinit(void)94*a81c3ea0SDavid du Colombier plan9iniinit(void)
95*a81c3ea0SDavid du Colombier {
96*a81c3ea0SDavid du Colombier char *cp;
97*a81c3ea0SDavid du Colombier int i;
98*a81c3ea0SDavid du Colombier
99*a81c3ea0SDavid du Colombier nconf = 0;
100*a81c3ea0SDavid du Colombier if(_argv != nil){
101*a81c3ea0SDavid du Colombier memmove(confbuf, _argv[0], sizeof(confbuf));
102*a81c3ea0SDavid du Colombier for(i=1; i<_argc && nconf<MAXCONF; i++){
103*a81c3ea0SDavid du Colombier _argv[i] += confbuf - _argv[0];
104*a81c3ea0SDavid du Colombier if(*_argv[i] == '#')
105*a81c3ea0SDavid du Colombier continue;
106*a81c3ea0SDavid du Colombier cp = strchr(_argv[i], '=');
107*a81c3ea0SDavid du Colombier if(cp == nil)
108*a81c3ea0SDavid du Colombier continue;
109*a81c3ea0SDavid du Colombier *cp++ = '\0';
110*a81c3ea0SDavid du Colombier confname[nconf] = _argv[i];
111*a81c3ea0SDavid du Colombier confval[nconf] = cp;
112*a81c3ea0SDavid du Colombier nconf++;
113*a81c3ea0SDavid du Colombier }
114*a81c3ea0SDavid du Colombier }
115*a81c3ea0SDavid du Colombier
116*a81c3ea0SDavid du Colombier nenv = 0;
117*a81c3ea0SDavid du Colombier if(_env != nil)
118*a81c3ea0SDavid du Colombier for(i=0; _env[i] != nil && nenv<MAXBOOTENV; i++){
119*a81c3ea0SDavid du Colombier if(*_env[i] == '#')
120*a81c3ea0SDavid du Colombier continue;
121*a81c3ea0SDavid du Colombier cp = strchr(_env[i], '=');
122*a81c3ea0SDavid du Colombier if(cp == nil)
123*a81c3ea0SDavid du Colombier continue;
124*a81c3ea0SDavid du Colombier *cp++ = '\0';
125*a81c3ea0SDavid du Colombier bootenvname[nenv] = _env[i];
126*a81c3ea0SDavid du Colombier bootenvval[nenv] = cp;
127*a81c3ea0SDavid du Colombier nenv++;
128*a81c3ea0SDavid du Colombier }
129*a81c3ea0SDavid du Colombier }
130*a81c3ea0SDavid du Colombier
131*a81c3ea0SDavid du Colombier static int
findconf(char * name)132*a81c3ea0SDavid du Colombier findconf(char *name)
133*a81c3ea0SDavid du Colombier {
134*a81c3ea0SDavid du Colombier int i;
135*a81c3ea0SDavid du Colombier
136*a81c3ea0SDavid du Colombier for(i = 0; i < nconf; i++)
137*a81c3ea0SDavid du Colombier if(cistrcmp(confname[i], name) == 0)
138*a81c3ea0SDavid du Colombier return i;
139*a81c3ea0SDavid du Colombier return -1;
140*a81c3ea0SDavid du Colombier }
141*a81c3ea0SDavid du Colombier
142*a81c3ea0SDavid du Colombier char*
getconf(char * name)143*a81c3ea0SDavid du Colombier getconf(char *name)
144*a81c3ea0SDavid du Colombier {
145*a81c3ea0SDavid du Colombier int i;
146*a81c3ea0SDavid du Colombier
147*a81c3ea0SDavid du Colombier i = findconf(name);
148*a81c3ea0SDavid du Colombier if(i >= 0)
149*a81c3ea0SDavid du Colombier return confval[i];
150*a81c3ea0SDavid du Colombier return nil;
151*a81c3ea0SDavid du Colombier }
152*a81c3ea0SDavid du Colombier
153*a81c3ea0SDavid du Colombier static int
findbootenv(char * name)154*a81c3ea0SDavid du Colombier findbootenv(char *name)
155*a81c3ea0SDavid du Colombier {
156*a81c3ea0SDavid du Colombier int i;
157*a81c3ea0SDavid du Colombier
158*a81c3ea0SDavid du Colombier for(i = 0; i < nenv; i++)
159*a81c3ea0SDavid du Colombier if(cistrcmp(bootenvname[i], name) == 0)
160*a81c3ea0SDavid du Colombier return i;
161*a81c3ea0SDavid du Colombier return -1;
162*a81c3ea0SDavid du Colombier }
163*a81c3ea0SDavid du Colombier
164*a81c3ea0SDavid du Colombier static char*
getbootenv(char * name)165*a81c3ea0SDavid du Colombier getbootenv(char *name)
166*a81c3ea0SDavid du Colombier {
167*a81c3ea0SDavid du Colombier int i;
168*a81c3ea0SDavid du Colombier
169*a81c3ea0SDavid du Colombier i = findbootenv(name);
170*a81c3ea0SDavid du Colombier if(i >= 0)
171*a81c3ea0SDavid du Colombier return bootenvval[i];
172*a81c3ea0SDavid du Colombier return nil;
173*a81c3ea0SDavid du Colombier }
174*a81c3ea0SDavid du Colombier
175*a81c3ea0SDavid du Colombier void
confinit(void)176*a81c3ea0SDavid du Colombier confinit(void)
177*a81c3ea0SDavid du Colombier {
178*a81c3ea0SDavid du Colombier char *p;
179*a81c3ea0SDavid du Colombier int i;
180*a81c3ea0SDavid du Colombier ulong kpages, ktop;
181*a81c3ea0SDavid du Colombier ulong maxmem, highmemsize;
182*a81c3ea0SDavid du Colombier
183*a81c3ea0SDavid du Colombier /* memory size */
184*a81c3ea0SDavid du Colombier memsize = MEMSIZE;
185*a81c3ea0SDavid du Colombier if((p = getbootenv("memsize")) != nil)
186*a81c3ea0SDavid du Colombier memsize = strtoul(p, 0, 0) * MB;
187*a81c3ea0SDavid du Colombier highmemsize = 0;
188*a81c3ea0SDavid du Colombier if((p = getbootenv("highmemsize")) != nil)
189*a81c3ea0SDavid du Colombier highmemsize = strtoul(p, 0, 0) * MB;
190*a81c3ea0SDavid du Colombier if((p = getconf("*maxmem")) != nil){
191*a81c3ea0SDavid du Colombier maxmem = strtoul(p, 0, 0);
192*a81c3ea0SDavid du Colombier memsize = MIN(memsize, maxmem);
193*a81c3ea0SDavid du Colombier maxmem -= memsize;
194*a81c3ea0SDavid du Colombier highmemsize = MIN(highmemsize, maxmem);
195*a81c3ea0SDavid du Colombier if(memsize < 16*MB) /* sanity */
196*a81c3ea0SDavid du Colombier memsize = 16*MB;
197*a81c3ea0SDavid du Colombier }
198*a81c3ea0SDavid du Colombier
199*a81c3ea0SDavid du Colombier /* set up other configuration parameters */
200*a81c3ea0SDavid du Colombier conf.nproc = 2000;
201*a81c3ea0SDavid du Colombier conf.nswap = 262144;
202*a81c3ea0SDavid du Colombier conf.nswppo = 4096;
203*a81c3ea0SDavid du Colombier conf.nimage = 200;
204*a81c3ea0SDavid du Colombier
205*a81c3ea0SDavid du Colombier /*
206*a81c3ea0SDavid du Colombier * divide memory to user pages and kernel.
207*a81c3ea0SDavid du Colombier */
208*a81c3ea0SDavid du Colombier conf.mem[0].base = ktop = PADDR(PGROUND((ulong)end));
209*a81c3ea0SDavid du Colombier conf.mem[0].npage = memsize/BY2PG - ktop/BY2PG;
210*a81c3ea0SDavid du Colombier
211*a81c3ea0SDavid du Colombier conf.mem[1].base = HIGHMEM;
212*a81c3ea0SDavid du Colombier conf.mem[1].npage = highmemsize/BY2PG;
213*a81c3ea0SDavid du Colombier
214*a81c3ea0SDavid du Colombier conf.npage = 0;
215*a81c3ea0SDavid du Colombier for(i=0; i<nelem(conf.mem); i++)
216*a81c3ea0SDavid du Colombier conf.npage += conf.mem[i].npage;
217*a81c3ea0SDavid du Colombier
218*a81c3ea0SDavid du Colombier kpages = conf.npage - (conf.npage*80)/100;
219*a81c3ea0SDavid du Colombier if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
220*a81c3ea0SDavid du Colombier kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
221*a81c3ea0SDavid du Colombier kpages += (conf.nproc*KSTACK)/BY2PG;
222*a81c3ea0SDavid du Colombier }
223*a81c3ea0SDavid du Colombier conf.upages = conf.npage - kpages;
224*a81c3ea0SDavid du Colombier conf.ialloc = (kpages/2)*BY2PG;
225*a81c3ea0SDavid du Colombier
226*a81c3ea0SDavid du Colombier kpages *= BY2PG;
227*a81c3ea0SDavid du Colombier kpages -= conf.upages*sizeof(Page)
228*a81c3ea0SDavid du Colombier + conf.nproc*sizeof(Proc)
229*a81c3ea0SDavid du Colombier + conf.nimage*sizeof(Image)
230*a81c3ea0SDavid du Colombier + conf.nswap
231*a81c3ea0SDavid du Colombier + conf.nswppo*sizeof(Page);
232*a81c3ea0SDavid du Colombier mainmem->maxsize = kpages;
233*a81c3ea0SDavid du Colombier
234*a81c3ea0SDavid du Colombier /*
235*a81c3ea0SDavid du Colombier * set up CPU's mach structure
236*a81c3ea0SDavid du Colombier * cpu0's was zeroed in main() and our stack is in Mach, so don't zero it.
237*a81c3ea0SDavid du Colombier */
238*a81c3ea0SDavid du Colombier m->machno = 0;
239*a81c3ea0SDavid du Colombier m->hz = cpufreq; /* initial guess at MHz */
240*a81c3ea0SDavid du Colombier m->speed = m->hz / Mhz;
241*a81c3ea0SDavid du Colombier conf.nmach = 1;
242*a81c3ea0SDavid du Colombier
243*a81c3ea0SDavid du Colombier conf.nuart = 1;
244*a81c3ea0SDavid du Colombier conf.copymode = 0; /* copy on write */
245*a81c3ea0SDavid du Colombier }
246*a81c3ea0SDavid du Colombier
247*a81c3ea0SDavid du Colombier void
procrestore(Proc * p)248*a81c3ea0SDavid du Colombier procrestore(Proc *p)
249*a81c3ea0SDavid du Colombier {
250*a81c3ea0SDavid du Colombier uvlong t;
251*a81c3ea0SDavid du Colombier
252*a81c3ea0SDavid du Colombier if(p->kp)
253*a81c3ea0SDavid du Colombier return;
254*a81c3ea0SDavid du Colombier cycles(&t);
255*a81c3ea0SDavid du Colombier p->pcycles -= t;
256*a81c3ea0SDavid du Colombier }
257*a81c3ea0SDavid du Colombier
258*a81c3ea0SDavid du Colombier /*
259*a81c3ea0SDavid du Colombier * Save the mach dependent part of the process state.
260*a81c3ea0SDavid du Colombier */
261*a81c3ea0SDavid du Colombier void
procsave(Proc * p)262*a81c3ea0SDavid du Colombier procsave(Proc *p)
263*a81c3ea0SDavid du Colombier {
264*a81c3ea0SDavid du Colombier uvlong t;
265*a81c3ea0SDavid du Colombier
266*a81c3ea0SDavid du Colombier cycles(&t);
267*a81c3ea0SDavid du Colombier p->pcycles += t;
268*a81c3ea0SDavid du Colombier //fpuprocsave(); // XXX
269*a81c3ea0SDavid du Colombier }
270*a81c3ea0SDavid du Colombier
271*a81c3ea0SDavid du Colombier static void
fmtinit(void)272*a81c3ea0SDavid du Colombier fmtinit(void)
273*a81c3ea0SDavid du Colombier {
274*a81c3ea0SDavid du Colombier printinit();
275*a81c3ea0SDavid du Colombier quotefmtinstall();
276*a81c3ea0SDavid du Colombier /* ipreset installs these when chandevreset runs */
277*a81c3ea0SDavid du Colombier fmtinstall('i', eipfmt);
278*a81c3ea0SDavid du Colombier fmtinstall('I', eipfmt);
279*a81c3ea0SDavid du Colombier fmtinstall('E', eipfmt);
280*a81c3ea0SDavid du Colombier fmtinstall('V', eipfmt);
281*a81c3ea0SDavid du Colombier fmtinstall('M', eipfmt);
282*a81c3ea0SDavid du Colombier }
283*a81c3ea0SDavid du Colombier
284*a81c3ea0SDavid du Colombier /*
285*a81c3ea0SDavid du Colombier * setup MIPS trap vectors
286*a81c3ea0SDavid du Colombier */
287*a81c3ea0SDavid du Colombier void
vecinit(void)288*a81c3ea0SDavid du Colombier vecinit(void)
289*a81c3ea0SDavid du Colombier {
290*a81c3ea0SDavid du Colombier memmove((ulong*)UTLBMISS, (ulong*)vector0, 0x80);
291*a81c3ea0SDavid du Colombier memmove((ulong*)XEXCEPTION, (ulong*)vector0, 0x80);
292*a81c3ea0SDavid du Colombier memmove((ulong*)CACHETRAP, (ulong*)vector100, 0x80);
293*a81c3ea0SDavid du Colombier memmove((ulong*)EXCEPTION, (ulong*)vector180, 0x80);
294*a81c3ea0SDavid du Colombier /* 0x200 not used in looongson 2e */
295*a81c3ea0SDavid du Colombier icflush((ulong*)UTLBMISS, 4*1024);
296*a81c3ea0SDavid du Colombier
297*a81c3ea0SDavid du Colombier setstatus(getstatus() & ~BEV);
298*a81c3ea0SDavid du Colombier }
299*a81c3ea0SDavid du Colombier
300*a81c3ea0SDavid du Colombier static void
prcpuid(void)301*a81c3ea0SDavid du Colombier prcpuid(void)
302*a81c3ea0SDavid du Colombier {
303*a81c3ea0SDavid du Colombier ulong cpuid, cfg;
304*a81c3ea0SDavid du Colombier char *cpu;
305*a81c3ea0SDavid du Colombier
306*a81c3ea0SDavid du Colombier cpuid = prid();
307*a81c3ea0SDavid du Colombier cfg = getconfig();
308*a81c3ea0SDavid du Colombier if (((cpuid>>16) & MASK(8)) == 0) /* vendor */
309*a81c3ea0SDavid du Colombier cpu = "old mips";
310*a81c3ea0SDavid du Colombier else if (((cpuid>>16) & MASK(8)) == 1)
311*a81c3ea0SDavid du Colombier switch ((cpuid>>8) & MASK(8)) { /* processor */
312*a81c3ea0SDavid du Colombier case 0x93:
313*a81c3ea0SDavid du Colombier cpu = "mips 24k";
314*a81c3ea0SDavid du Colombier break;
315*a81c3ea0SDavid du Colombier case 0x96:
316*a81c3ea0SDavid du Colombier cpu = "mips 24ke";
317*a81c3ea0SDavid du Colombier break;
318*a81c3ea0SDavid du Colombier default:
319*a81c3ea0SDavid du Colombier cpu = "mips";
320*a81c3ea0SDavid du Colombier break;
321*a81c3ea0SDavid du Colombier }
322*a81c3ea0SDavid du Colombier else
323*a81c3ea0SDavid du Colombier cpu = "other mips";
324*a81c3ea0SDavid du Colombier delay(200);
325*a81c3ea0SDavid du Colombier print("cpu%d: %ldMHz %s %se 0x%ulx v%ld.%ld rev %ld has fpu\n",
326*a81c3ea0SDavid du Colombier m->machno, m->hz / Mhz, cpu, cfg & (1<<15)? "b": "l",
327*a81c3ea0SDavid du Colombier (cpuid>>8) & MASK(8), (cpuid>>5) & MASK(3), (cpuid>>2) & MASK(3),
328*a81c3ea0SDavid du Colombier cpuid & MASK(2));
329*a81c3ea0SDavid du Colombier delay(200);
330*a81c3ea0SDavid du Colombier
331*a81c3ea0SDavid du Colombier print("cpu%d: %d tlb entries, using %dK pages\n", m->machno,
332*a81c3ea0SDavid du Colombier 64, BY2PG/1024);
333*a81c3ea0SDavid du Colombier delay(50);
334*a81c3ea0SDavid du Colombier print("cpu%d: l1 i cache: %d sets 4 ways 32 bytes/line\n", m->machno,
335*a81c3ea0SDavid du Colombier 32 << ((cfg>>9) & MASK(3)));
336*a81c3ea0SDavid du Colombier delay(50);
337*a81c3ea0SDavid du Colombier print("cpu%d: l1 d cache: %d sets 4 ways 32 bytes/line\n", m->machno,
338*a81c3ea0SDavid du Colombier 32 << ((cfg>>6) & MASK(3)));
339*a81c3ea0SDavid du Colombier delay(500);
340*a81c3ea0SDavid du Colombier }
341*a81c3ea0SDavid du Colombier
342*a81c3ea0SDavid du Colombier static int
ckpagemask(ulong mask,ulong size)343*a81c3ea0SDavid du Colombier ckpagemask(ulong mask, ulong size)
344*a81c3ea0SDavid du Colombier {
345*a81c3ea0SDavid du Colombier int s;
346*a81c3ea0SDavid du Colombier ulong pm;
347*a81c3ea0SDavid du Colombier
348*a81c3ea0SDavid du Colombier s = splhi();
349*a81c3ea0SDavid du Colombier setpagemask(mask);
350*a81c3ea0SDavid du Colombier pm = getpagemask();
351*a81c3ea0SDavid du Colombier splx(s);
352*a81c3ea0SDavid du Colombier if(pm != mask){
353*a81c3ea0SDavid du Colombier iprint("page size %ldK not supported on this cpu; "
354*a81c3ea0SDavid du Colombier "mask %#lux read back as %#lux\n", size/1024, mask, pm);
355*a81c3ea0SDavid du Colombier return -1;
356*a81c3ea0SDavid du Colombier }
357*a81c3ea0SDavid du Colombier return 0;
358*a81c3ea0SDavid du Colombier }
359*a81c3ea0SDavid du Colombier
360*a81c3ea0SDavid du Colombier void
init0(void)361*a81c3ea0SDavid du Colombier init0(void)
362*a81c3ea0SDavid du Colombier {
363*a81c3ea0SDavid du Colombier char buf[128];
364*a81c3ea0SDavid du Colombier int i;
365*a81c3ea0SDavid du Colombier
366*a81c3ea0SDavid du Colombier up->nerrlab = 0;
367*a81c3ea0SDavid du Colombier
368*a81c3ea0SDavid du Colombier spllo();
369*a81c3ea0SDavid du Colombier
370*a81c3ea0SDavid du Colombier /*
371*a81c3ea0SDavid du Colombier * These are o.k. because rootinit is null.
372*a81c3ea0SDavid du Colombier * Then early kproc's will have a root and dot.
373*a81c3ea0SDavid du Colombier */
374*a81c3ea0SDavid du Colombier up->slash = namec("#/", Atodir, 0, 0);
375*a81c3ea0SDavid du Colombier pathclose(up->slash->path);
376*a81c3ea0SDavid du Colombier up->slash->path = newpath("/");
377*a81c3ea0SDavid du Colombier up->dot = cclone(up->slash);
378*a81c3ea0SDavid du Colombier
379*a81c3ea0SDavid du Colombier chandevinit();
380*a81c3ea0SDavid du Colombier
381*a81c3ea0SDavid du Colombier if(!waserror()){
382*a81c3ea0SDavid du Colombier ksetenv("cputype", "spim", 0);
383*a81c3ea0SDavid du Colombier snprint(buf, sizeof buf, "spim %s loongson 2f", conffile);
384*a81c3ea0SDavid du Colombier ksetenv("terminal", buf, 0);
385*a81c3ea0SDavid du Colombier if(cpuserver)
386*a81c3ea0SDavid du Colombier ksetenv("service", "cpu", 0);
387*a81c3ea0SDavid du Colombier else
388*a81c3ea0SDavid du Colombier ksetenv("service", "terminal", 0);
389*a81c3ea0SDavid du Colombier // ksetenv("nobootprompt", "local!/boot/bzroot", 0); // for bzroot
390*a81c3ea0SDavid du Colombier ksetenv("nvram", "/boot/nvram", 0);
391*a81c3ea0SDavid du Colombier /* convert plan9.ini variables to #e and #ec */
392*a81c3ea0SDavid du Colombier for(i = 0; i < nconf; i++) {
393*a81c3ea0SDavid du Colombier if(*confname[i] == '*')
394*a81c3ea0SDavid du Colombier continue;
395*a81c3ea0SDavid du Colombier ksetenv(confname[i], confval[i], 0);
396*a81c3ea0SDavid du Colombier ksetenv(confname[i], confval[i], 1);
397*a81c3ea0SDavid du Colombier }
398*a81c3ea0SDavid du Colombier poperror();
399*a81c3ea0SDavid du Colombier }
400*a81c3ea0SDavid du Colombier kproc("alarm", alarmkproc, 0);
401*a81c3ea0SDavid du Colombier // i8250console();
402*a81c3ea0SDavid du Colombier touser(sp);
403*a81c3ea0SDavid du Colombier }
404*a81c3ea0SDavid du Colombier
405*a81c3ea0SDavid du Colombier static void
bootargs(uintptr base)406*a81c3ea0SDavid du Colombier bootargs(uintptr base)
407*a81c3ea0SDavid du Colombier {
408*a81c3ea0SDavid du Colombier int i;
409*a81c3ea0SDavid du Colombier ulong ssize;
410*a81c3ea0SDavid du Colombier char **av, *p;
411*a81c3ea0SDavid du Colombier
412*a81c3ea0SDavid du Colombier /*
413*a81c3ea0SDavid du Colombier * Push the boot args onto the stack.
414*a81c3ea0SDavid du Colombier * The initial value of the user stack must be such
415*a81c3ea0SDavid du Colombier * that the total used is larger than the maximum size
416*a81c3ea0SDavid du Colombier * of the argument list checked in syscall.
417*a81c3ea0SDavid du Colombier */
418*a81c3ea0SDavid du Colombier i = oargblen+1;
419*a81c3ea0SDavid du Colombier p = UINT2PTR(STACKALIGN(base + BY2PG - Stkheadroom - i));
420*a81c3ea0SDavid du Colombier memmove(p, oargb, i);
421*a81c3ea0SDavid du Colombier
422*a81c3ea0SDavid du Colombier /*
423*a81c3ea0SDavid du Colombier * Now push the argv pointers.
424*a81c3ea0SDavid du Colombier * The code jumped to by touser in l.s expects arguments
425*a81c3ea0SDavid du Colombier * main(char* argv0, ...)
426*a81c3ea0SDavid du Colombier * and calls
427*a81c3ea0SDavid du Colombier * startboot("/boot/boot", &argv0)
428*a81c3ea0SDavid du Colombier * not the usual (int argc, char* argv[])
429*a81c3ea0SDavid du Colombier */
430*a81c3ea0SDavid du Colombier av = (char**)(p - (oargc+1)*sizeof(char*));
431*a81c3ea0SDavid du Colombier ssize = base + BY2PG - PTR2UINT(av);
432*a81c3ea0SDavid du Colombier for(i = 0; i < oargc; i++)
433*a81c3ea0SDavid du Colombier *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
434*a81c3ea0SDavid du Colombier *av = nil;
435*a81c3ea0SDavid du Colombier sp = USTKTOP - ssize;
436*a81c3ea0SDavid du Colombier }
437*a81c3ea0SDavid du Colombier
438*a81c3ea0SDavid du Colombier void
userinit(void)439*a81c3ea0SDavid du Colombier userinit(void)
440*a81c3ea0SDavid du Colombier {
441*a81c3ea0SDavid du Colombier Proc *p;
442*a81c3ea0SDavid du Colombier KMap *k;
443*a81c3ea0SDavid du Colombier Page *pg;
444*a81c3ea0SDavid du Colombier Segment *s;
445*a81c3ea0SDavid du Colombier
446*a81c3ea0SDavid du Colombier p = newproc();
447*a81c3ea0SDavid du Colombier p->pgrp = newpgrp();
448*a81c3ea0SDavid du Colombier p->egrp = smalloc(sizeof(Egrp));
449*a81c3ea0SDavid du Colombier p->egrp->ref = 1;
450*a81c3ea0SDavid du Colombier p->fgrp = dupfgrp(nil);
451*a81c3ea0SDavid du Colombier p->rgrp = newrgrp();
452*a81c3ea0SDavid du Colombier p->procmode = 0640;
453*a81c3ea0SDavid du Colombier
454*a81c3ea0SDavid du Colombier kstrdup(&eve, "");
455*a81c3ea0SDavid du Colombier kstrdup(&p->text, "*init*");
456*a81c3ea0SDavid du Colombier kstrdup(&p->user, eve);
457*a81c3ea0SDavid du Colombier
458*a81c3ea0SDavid du Colombier p->fpstate = FPinit;
459*a81c3ea0SDavid du Colombier p->fpsave.fpstatus = initfp.fpstatus;
460*a81c3ea0SDavid du Colombier
461*a81c3ea0SDavid du Colombier /*
462*a81c3ea0SDavid du Colombier * Kernel Stack
463*a81c3ea0SDavid du Colombier */
464*a81c3ea0SDavid du Colombier p->sched.pc = (ulong)init0;
465*a81c3ea0SDavid du Colombier p->sched.sp = (ulong)p->kstack+KSTACK-Stkheadroom;
466*a81c3ea0SDavid du Colombier p->sched.sp = STACKALIGN(p->sched.sp);
467*a81c3ea0SDavid du Colombier
468*a81c3ea0SDavid du Colombier /*
469*a81c3ea0SDavid du Colombier * User Stack
470*a81c3ea0SDavid du Colombier *
471*a81c3ea0SDavid du Colombier * Technically, newpage can't be called here because it
472*a81c3ea0SDavid du Colombier * should only be called when in a user context as it may
473*a81c3ea0SDavid du Colombier * try to sleep if there are no pages available, but that
474*a81c3ea0SDavid du Colombier * shouldn't be the case here.
475*a81c3ea0SDavid du Colombier */
476*a81c3ea0SDavid du Colombier s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
477*a81c3ea0SDavid du Colombier p->seg[SSEG] = s;
478*a81c3ea0SDavid du Colombier pg = newpage(1, 0, USTKTOP-BY2PG);
479*a81c3ea0SDavid du Colombier memset(pg->cachectl, PG_DATFLUSH, sizeof(pg->cachectl));
480*a81c3ea0SDavid du Colombier segpage(s, pg);
481*a81c3ea0SDavid du Colombier k = kmap(pg);
482*a81c3ea0SDavid du Colombier bootargs(VA(k));
483*a81c3ea0SDavid du Colombier kunmap(k);
484*a81c3ea0SDavid du Colombier
485*a81c3ea0SDavid du Colombier /*
486*a81c3ea0SDavid du Colombier * Text
487*a81c3ea0SDavid du Colombier */
488*a81c3ea0SDavid du Colombier s = newseg(SG_TEXT, UTZERO, 1);
489*a81c3ea0SDavid du Colombier s->flushme++;
490*a81c3ea0SDavid du Colombier p->seg[TSEG] = s;
491*a81c3ea0SDavid du Colombier pg = newpage(1, 0, UTZERO);
492*a81c3ea0SDavid du Colombier memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
493*a81c3ea0SDavid du Colombier segpage(s, pg);
494*a81c3ea0SDavid du Colombier k = kmap(s->map[0]->pages[0]);
495*a81c3ea0SDavid du Colombier memset((void*)VA(k), 0, BY2PG);
496*a81c3ea0SDavid du Colombier memmove((ulong*)VA(k), initcode, sizeof initcode);
497*a81c3ea0SDavid du Colombier kunmap(k);
498*a81c3ea0SDavid du Colombier
499*a81c3ea0SDavid du Colombier ready(p);
500*a81c3ea0SDavid du Colombier }
501*a81c3ea0SDavid du Colombier
502*a81c3ea0SDavid du Colombier /* called from rebootcmd() */
503*a81c3ea0SDavid du Colombier int
parsemipsboothdr(Chan * c,ulong magic,Execvals * evp)504*a81c3ea0SDavid du Colombier parsemipsboothdr(Chan *c, ulong magic, Execvals *evp)
505*a81c3ea0SDavid du Colombier {
506*a81c3ea0SDavid du Colombier long extra;
507*a81c3ea0SDavid du Colombier Mipsexec me;
508*a81c3ea0SDavid du Colombier
509*a81c3ea0SDavid du Colombier /*
510*a81c3ea0SDavid du Colombier * BOOT_MAGIC is sometimes defined like this:
511*a81c3ea0SDavid du Colombier * #define BOOT_MAGIC (0x160<<16) || magic == ((0x160<<16)|3)
512*a81c3ea0SDavid du Colombier * so we can only use it in a fairly stylized manner.
513*a81c3ea0SDavid du Colombier */
514*a81c3ea0SDavid du Colombier if(magic == BOOT_MAGIC) {
515*a81c3ea0SDavid du Colombier c->offset = 0; /* back up */
516*a81c3ea0SDavid du Colombier readn(c, &me, sizeof me);
517*a81c3ea0SDavid du Colombier /* if binary is -H1, read an extra long */
518*a81c3ea0SDavid du Colombier if (l2be(me.amagic) == 0407 && me.nscns == 0)
519*a81c3ea0SDavid du Colombier readn(c, &extra, sizeof extra);
520*a81c3ea0SDavid du Colombier evp->entry = l2be(me.mentry);
521*a81c3ea0SDavid du Colombier evp->textsize = l2be(me.tsize);
522*a81c3ea0SDavid du Colombier evp->datasize = l2be(me.dsize);
523*a81c3ea0SDavid du Colombier return 0;
524*a81c3ea0SDavid du Colombier } else
525*a81c3ea0SDavid du Colombier return -1;
526*a81c3ea0SDavid du Colombier }
527*a81c3ea0SDavid du Colombier
528*a81c3ea0SDavid du Colombier void
main(void)529*a81c3ea0SDavid du Colombier main(void)
530*a81c3ea0SDavid du Colombier {
531*a81c3ea0SDavid du Colombier extern char edata[], end[];
532*a81c3ea0SDavid du Colombier
533*a81c3ea0SDavid du Colombier m = (Mach*)MACHADDR;
534*a81c3ea0SDavid du Colombier memset(m, 0, sizeof(Mach)); /* clear Mach */
535*a81c3ea0SDavid du Colombier m->machno = 0;
536*a81c3ea0SDavid du Colombier machaddr[m->machno] = m;
537*a81c3ea0SDavid du Colombier up = nil;
538*a81c3ea0SDavid du Colombier memset(edata, 0, end-edata); /* clear bss */
539*a81c3ea0SDavid du Colombier
540*a81c3ea0SDavid du Colombier optionsinit("/boot/boot boot");
541*a81c3ea0SDavid du Colombier plan9iniinit();
542*a81c3ea0SDavid du Colombier confinit();
543*a81c3ea0SDavid du Colombier savefpregs(&initfp);
544*a81c3ea0SDavid du Colombier
545*a81c3ea0SDavid du Colombier machinit();
546*a81c3ea0SDavid du Colombier active.exiting = 0;
547*a81c3ea0SDavid du Colombier active.machs = 1;
548*a81c3ea0SDavid du Colombier
549*a81c3ea0SDavid du Colombier kmapinit();
550*a81c3ea0SDavid du Colombier xinit();
551*a81c3ea0SDavid du Colombier screeninit();
552*a81c3ea0SDavid du Colombier
553*a81c3ea0SDavid du Colombier ckpagemask(PGSZ, BY2PG);
554*a81c3ea0SDavid du Colombier tlbinit();
555*a81c3ea0SDavid du Colombier machwire();
556*a81c3ea0SDavid du Colombier
557*a81c3ea0SDavid du Colombier timersinit();
558*a81c3ea0SDavid du Colombier fmtinit();
559*a81c3ea0SDavid du Colombier vecinit();
560*a81c3ea0SDavid du Colombier
561*a81c3ea0SDavid du Colombier normalprint = 1;
562*a81c3ea0SDavid du Colombier print("\nPlan 9\n");
563*a81c3ea0SDavid du Colombier print("\0\0\0\0\0\0\0"); // XXX 0c bug fixed -- leave this for sanity
564*a81c3ea0SDavid du Colombier prcpuid();
565*a81c3ea0SDavid du Colombier if(PTECACHABILITY == PTENONCOHERWT)
566*a81c3ea0SDavid du Colombier print("caches configured as write-through\n");
567*a81c3ea0SDavid du Colombier // xsummary();
568*a81c3ea0SDavid du Colombier
569*a81c3ea0SDavid du Colombier i8259init();
570*a81c3ea0SDavid du Colombier kbdinit();
571*a81c3ea0SDavid du Colombier if(conf.monitor)
572*a81c3ea0SDavid du Colombier swcursorinit();
573*a81c3ea0SDavid du Colombier
574*a81c3ea0SDavid du Colombier pageinit();
575*a81c3ea0SDavid du Colombier procinit0();
576*a81c3ea0SDavid du Colombier initseg();
577*a81c3ea0SDavid du Colombier links();
578*a81c3ea0SDavid du Colombier chandevreset();
579*a81c3ea0SDavid du Colombier
580*a81c3ea0SDavid du Colombier swapinit();
581*a81c3ea0SDavid du Colombier userinit();
582*a81c3ea0SDavid du Colombier parseboothdr = parsemipsboothdr;
583*a81c3ea0SDavid du Colombier schedinit();
584*a81c3ea0SDavid du Colombier panic("schedinit returned");
585*a81c3ea0SDavid du Colombier }
586*a81c3ea0SDavid du Colombier
587*a81c3ea0SDavid du Colombier static void
writeconf(void)588*a81c3ea0SDavid du Colombier writeconf(void)
589*a81c3ea0SDavid du Colombier {
590*a81c3ea0SDavid du Colombier char *p, *q;
591*a81c3ea0SDavid du Colombier int n;
592*a81c3ea0SDavid du Colombier
593*a81c3ea0SDavid du Colombier p = getconfenv();
594*a81c3ea0SDavid du Colombier
595*a81c3ea0SDavid du Colombier if(waserror()) {
596*a81c3ea0SDavid du Colombier free(p);
597*a81c3ea0SDavid du Colombier nexterror();
598*a81c3ea0SDavid du Colombier }
599*a81c3ea0SDavid du Colombier
600*a81c3ea0SDavid du Colombier /* convert to name=value\0 format */
601*a81c3ea0SDavid du Colombier _argc = 1; /* skip _argv[0] */
602*a81c3ea0SDavid du Colombier _argv = (void*)CONFARGV;
603*a81c3ea0SDavid du Colombier _argv[0] = BOOTARGS;
604*a81c3ea0SDavid du Colombier for(q=p; *q; q++) {
605*a81c3ea0SDavid du Colombier _argv[_argc] = (char*)((ulong)BOOTARGS + (q - p));
606*a81c3ea0SDavid du Colombier _argc++;
607*a81c3ea0SDavid du Colombier q += strlen(q);
608*a81c3ea0SDavid du Colombier *q = '=';
609*a81c3ea0SDavid du Colombier q += strlen(q);
610*a81c3ea0SDavid du Colombier }
611*a81c3ea0SDavid du Colombier n = q - p + 1;
612*a81c3ea0SDavid du Colombier _env = &_argv[_argc];
613*a81c3ea0SDavid du Colombier
614*a81c3ea0SDavid du Colombier if(n >= BOOTARGSLEN || (ulong)_env >= CONFARGV + CONFARGVLEN)
615*a81c3ea0SDavid du Colombier error("kernel configuration too large");
616*a81c3ea0SDavid du Colombier memmove(BOOTARGS, p, n);
617*a81c3ea0SDavid du Colombier memset(BOOTARGS + n, '\0', BOOTARGSLEN - n);
618*a81c3ea0SDavid du Colombier memset(_env, 0, CONFARGV + CONFARGVLEN - (ulong)_env);
619*a81c3ea0SDavid du Colombier
620*a81c3ea0SDavid du Colombier poperror();
621*a81c3ea0SDavid du Colombier free(p);
622*a81c3ea0SDavid du Colombier }
623*a81c3ea0SDavid du Colombier
624*a81c3ea0SDavid du Colombier static void
shutdown(int ispanic)625*a81c3ea0SDavid du Colombier shutdown(int ispanic)
626*a81c3ea0SDavid du Colombier {
627*a81c3ea0SDavid du Colombier int ms, once;
628*a81c3ea0SDavid du Colombier
629*a81c3ea0SDavid du Colombier ilock(&active);
630*a81c3ea0SDavid du Colombier if(ispanic)
631*a81c3ea0SDavid du Colombier active.ispanic = ispanic;
632*a81c3ea0SDavid du Colombier else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
633*a81c3ea0SDavid du Colombier active.ispanic = 0;
634*a81c3ea0SDavid du Colombier once = active.machs & (1<<m->machno);
635*a81c3ea0SDavid du Colombier /*
636*a81c3ea0SDavid du Colombier * setting exiting will make hzclock() on each processor call exit(0),
637*a81c3ea0SDavid du Colombier * which calls shutdown(0) and idles non-bootstrap cpus and returns
638*a81c3ea0SDavid du Colombier * on bootstrap processors (to permit a reboot). clearing our bit
639*a81c3ea0SDavid du Colombier * in machs avoids calling exit(0) from hzclock() on this processor.
640*a81c3ea0SDavid du Colombier */
641*a81c3ea0SDavid du Colombier active.machs &= ~(1<<m->machno);
642*a81c3ea0SDavid du Colombier active.exiting = 1;
643*a81c3ea0SDavid du Colombier iunlock(&active);
644*a81c3ea0SDavid du Colombier
645*a81c3ea0SDavid du Colombier if(once) {
646*a81c3ea0SDavid du Colombier delay(m->machno*1000); /* stagger them */
647*a81c3ea0SDavid du Colombier iprint("cpu%d: exiting\n", m->machno);
648*a81c3ea0SDavid du Colombier }
649*a81c3ea0SDavid du Colombier spllo();
650*a81c3ea0SDavid du Colombier for(ms = MAXMACH * 1000; ms > 0; ms -= TK2MS(2)){
651*a81c3ea0SDavid du Colombier delay(TK2MS(2));
652*a81c3ea0SDavid du Colombier if(active.machs == 0 && consactive() == 0)
653*a81c3ea0SDavid du Colombier break;
654*a81c3ea0SDavid du Colombier }
655*a81c3ea0SDavid du Colombier delay(100);
656*a81c3ea0SDavid du Colombier }
657*a81c3ea0SDavid du Colombier
658*a81c3ea0SDavid du Colombier void
exit(int ispanic)659*a81c3ea0SDavid du Colombier exit(int ispanic)
660*a81c3ea0SDavid du Colombier {
661*a81c3ea0SDavid du Colombier int timer;
662*a81c3ea0SDavid du Colombier
663*a81c3ea0SDavid du Colombier delay(1000);
664*a81c3ea0SDavid du Colombier shutdown(ispanic);
665*a81c3ea0SDavid du Colombier timer = 0;
666*a81c3ea0SDavid du Colombier while(active.machs || consactive()) {
667*a81c3ea0SDavid du Colombier if(timer++ > 400)
668*a81c3ea0SDavid du Colombier break;
669*a81c3ea0SDavid du Colombier delay(10);
670*a81c3ea0SDavid du Colombier }
671*a81c3ea0SDavid du Colombier delay(1000);
672*a81c3ea0SDavid du Colombier splhi();
673*a81c3ea0SDavid du Colombier
674*a81c3ea0SDavid du Colombier setstatus(BEV);
675*a81c3ea0SDavid du Colombier coherence();
676*a81c3ea0SDavid du Colombier
677*a81c3ea0SDavid du Colombier iprint("exit: awaiting reset\n");
678*a81c3ea0SDavid du Colombier delay(1000); /* await a reset */
679*a81c3ea0SDavid du Colombier
680*a81c3ea0SDavid du Colombier if(!active.ispanic) {
681*a81c3ea0SDavid du Colombier iprint("exit: jumping to rom\n");
682*a81c3ea0SDavid du Colombier // *Reset |= Rstcpucold; /* cpu cold reset */
683*a81c3ea0SDavid du Colombier outb(0x381, 0xf4);
684*a81c3ea0SDavid du Colombier outb(0x382, 0xec);
685*a81c3ea0SDavid du Colombier outb(0x383, 1);
686*a81c3ea0SDavid du Colombier }
687*a81c3ea0SDavid du Colombier
688*a81c3ea0SDavid du Colombier iprint("exit: looping\n");
689*a81c3ea0SDavid du Colombier for(;;);
690*a81c3ea0SDavid du Colombier }
691*a81c3ea0SDavid du Colombier
692*a81c3ea0SDavid du Colombier /*
693*a81c3ea0SDavid du Colombier * the new kernel is already loaded at address `code'
694*a81c3ea0SDavid du Colombier * of size `size' and entry point `entry'.
695*a81c3ea0SDavid du Colombier */
696*a81c3ea0SDavid du Colombier void
reboot(void * entry,void * code,ulong size)697*a81c3ea0SDavid du Colombier reboot(void *entry, void *code, ulong size)
698*a81c3ea0SDavid du Colombier {
699*a81c3ea0SDavid du Colombier void (*f)(ulong, ulong, ulong, ulong);
700*a81c3ea0SDavid du Colombier
701*a81c3ea0SDavid du Colombier writeconf();
702*a81c3ea0SDavid du Colombier
703*a81c3ea0SDavid du Colombier /*
704*a81c3ea0SDavid du Colombier * the boot processor is cpu0. execute this function on it
705*a81c3ea0SDavid du Colombier * so that the new kernel has the same cpu0.
706*a81c3ea0SDavid du Colombier */
707*a81c3ea0SDavid du Colombier if(m->machno != 0) {
708*a81c3ea0SDavid du Colombier procwired(up, 0);
709*a81c3ea0SDavid du Colombier sched();
710*a81c3ea0SDavid du Colombier }
711*a81c3ea0SDavid du Colombier if(m->machno != 0)
712*a81c3ea0SDavid du Colombier print("on cpu%d (not 0)!\n", m->machno);
713*a81c3ea0SDavid du Colombier
714*a81c3ea0SDavid du Colombier if(code == nil || entry == nil)
715*a81c3ea0SDavid du Colombier exit(1);
716*a81c3ea0SDavid du Colombier
717*a81c3ea0SDavid du Colombier shutdown(0);
718*a81c3ea0SDavid du Colombier
719*a81c3ea0SDavid du Colombier /*
720*a81c3ea0SDavid du Colombier * should be the only processor running now
721*a81c3ea0SDavid du Colombier */
722*a81c3ea0SDavid du Colombier iprint("reboot: entry %#p code %#p size %ld\n", entry, code, size);
723*a81c3ea0SDavid du Colombier iprint("code[0] = %#lux\n", *(ulong *)code);
724*a81c3ea0SDavid du Colombier
725*a81c3ea0SDavid du Colombier /* turn off buffered serial console */
726*a81c3ea0SDavid du Colombier serialoq = nil;
727*a81c3ea0SDavid du Colombier kprintoq = nil;
728*a81c3ea0SDavid du Colombier screenputs = nil;
729*a81c3ea0SDavid du Colombier
730*a81c3ea0SDavid du Colombier /* shutdown devices */
731*a81c3ea0SDavid du Colombier chandevshutdown();
732*a81c3ea0SDavid du Colombier
733*a81c3ea0SDavid du Colombier splhi();
734*a81c3ea0SDavid du Colombier intrshutdown();
735*a81c3ea0SDavid du Colombier
736*a81c3ea0SDavid du Colombier /* setup reboot trampoline function */
737*a81c3ea0SDavid du Colombier f = (void*)REBOOTADDR;
738*a81c3ea0SDavid du Colombier memmove(f, rebootcode, sizeof(rebootcode));
739*a81c3ea0SDavid du Colombier icflush(f, sizeof(rebootcode));
740*a81c3ea0SDavid du Colombier
741*a81c3ea0SDavid du Colombier setstatus(BEV); /* also, kernel mode, no interrupts */
742*a81c3ea0SDavid du Colombier coherence();
743*a81c3ea0SDavid du Colombier
744*a81c3ea0SDavid du Colombier /* off we go - never to return */
745*a81c3ea0SDavid du Colombier (*f)((ulong)entry, (ulong)code, size, _argc);
746*a81c3ea0SDavid du Colombier
747*a81c3ea0SDavid du Colombier panic("loaded kernel returned!");
748*a81c3ea0SDavid du Colombier }
749*a81c3ea0SDavid du Colombier
750*a81c3ea0SDavid du Colombier /*
751*a81c3ea0SDavid du Colombier * stub for ../port/devpnp.c
752*a81c3ea0SDavid du Colombier */
753*a81c3ea0SDavid du Colombier int
isaconfig(char * class,int ctlrno,ISAConf * isa)754*a81c3ea0SDavid du Colombier isaconfig(char *class, int ctlrno, ISAConf *isa)
755*a81c3ea0SDavid du Colombier {
756*a81c3ea0SDavid du Colombier USED(class, ctlrno, isa);
757*a81c3ea0SDavid du Colombier return 0;
758*a81c3ea0SDavid du Colombier }
759