Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "u.h"
2
#include "../port/lib.h"
3
#include "mem.h"
4
#include "dat.h"
5
#include "fns.h"
6
#include "io.h"
7
 
8
#include "init.h"
9
#include <pool.h>
10
#include <tos.h>
11
 
12
#include "arm.h"
13
#include "reboot.h"
14
 
15
/*
16
 * Where configuration info is left for the loaded programme.
17
 * This will turn into a structure as more is done by the boot loader
18
 * (e.g. why parse the .ini file twice?).
19
 * There are 3584 bytes available at CONFADDR.
20
 */
21
#define BOOTARGS	((char*)CONFADDR)
22
#define	BOOTARGSLEN	(16*KiB)		/* limit in devenv.c */
23
#define	MAXCONF		64
24
#define MAXCONFLINE	160
25
 
26
enum {
27
	Minmem	= 256*MB,			/* conservative default */
28
 
29
	/* space for syscall args, return PC, top-of-stack struct */
30
	Ustkheadroom	= sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),
31
};
32
 
33
#define isascii(c) ((uchar)(c) > 0 && (uchar)(c) < 0177)
34
 
35
extern char bdata[], edata[], end[], etext[];
36
 
37
uintptr kseg0 = KZERO;
38
Mach* machaddr[MAXMACH];
39
uchar *l2pages;
40
 
41
Memcache cachel[8];		/* arm arch v7 supports 1-7 */
42
/*
43
 * these are used by the cache.v7.s routines.
44
 */
45
Lowmemcache *cacheconf;
46
 
47
/*
48
 * Option arguments from the command line.
49
 * oargv[0] is the boot file.
50
 * Optionsinit() is called from multiboot()
51
 * or some other machine-dependent place
52
 * to set it all up.
53
 */
54
static int oargc;
55
static char* oargv[20];
56
static char oargb[128];
57
static int oargblen;
58
static char oenv[4096];
59
 
60
static uintptr sp;		/* XXX - must go - user stack of init proc */
61
 
62
int vflag;
63
int normalprint;
64
char debug[256];
65
 
66
static Lock testlock;
67
 
68
/* store plan9.ini contents here at least until we stash them in #ec */
69
static char confname[MAXCONF][KNAMELEN];
70
static char confval[MAXCONF][MAXCONFLINE];
71
static int nconf;
72
 
73
static int
74
findconf(char *name)
75
{
76
	int i;
77
 
78
	for(i = 0; i < nconf; i++)
79
		if(cistrcmp(confname[i], name) == 0)
80
			return i;
81
	return -1;
82
}
83
 
84
char*
85
getconf(char *name)
86
{
87
	int i;
88
 
89
	i = findconf(name);
90
	if(i >= 0)
91
		return confval[i];
92
	return nil;
93
}
94
 
95
void
96
addconf(char *name, char *val)
97
{
98
	int i;
99
 
100
	i = findconf(name);
101
	if(i < 0){
102
		if(val == nil || nconf >= MAXCONF)
103
			return;
104
		i = nconf++;
105
		strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
106
	}
107
//	confval[i] = val;
108
	strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
109
}
110
 
111
static void
112
writeconf(void)
113
{
114
	char *p, *q;
115
	int n;
116
 
117
	p = getconfenv();
118
 
119
	if(waserror()) {
120
		free(p);
121
		nexterror();
122
	}
123
 
124
	/* convert to name=value\n format */
125
	for(q=p; *q; q++) {
126
		q += strlen(q);
127
		*q = '=';
128
		q += strlen(q);
129
		*q = '\n';
130
	}
131
	n = q - p + 1;
132
	if(n >= BOOTARGSLEN)
133
		error("kernel configuration too large");
134
	memmove(BOOTARGS, p, n);
135
	memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
136
	poperror();
137
	free(p);
138
}
139
 
140
/*
141
 * assumes that we have loaded our /cfg/pxe/mac file at CONFADDR
142
 * (usually 0x1000) with tftp in u-boot.  no longer uses malloc, so
143
 * can be called early.
144
 */
145
static void
146
plan9iniinit(void)
147
{
148
	char *k, *v, *next;
149
 
150
	k = (char *)CONFADDR;
151
	if(!isascii(*k))
152
		return;
153
 
154
	for(; k && *k != '\0'; k = next) {
155
		if (!isascii(*k))		/* sanity check */
156
			break;
157
		next = strchr(k, '\n');
158
		if (next)
159
			*next++ = '\0';
160
 
161
		if (*k == '\0' || *k == '\n' || *k == '#')
162
			continue;
163
		v = strchr(k, '=');
164
		if(v == nil)
165
			continue;		/* mal-formed line */
166
		*v++ = '\0';
167
 
168
		addconf(k, v);
169
	}
170
}
171
 
172
static void
173
optionsinit(char* s)
174
{
175
	char *o;
176
 
177
	strcpy(oenv, "");
178
	o = strecpy(oargb, oargb+sizeof(oargb), s)+1;
179
	if(getenv("bootargs", o, o - oargb) != nil)
180
		*(o-1) = ' ';
181
 
182
	oargblen = strlen(oargb);
183
	oargc = tokenize(oargb, oargv, nelem(oargv)-1);
184
	oargv[oargc] = nil;
185
}
186
 
187
char*
188
getenv(char* name, char* buf, int n)
189
{
190
	char *e, *p, *q;
191
 
192
	p = oenv;
193
	while(*p != 0){
194
		if((e = strchr(p, '=')) == nil)
195
			break;
196
		for(q = name; p < e; p++){
197
			if(*p != *q)
198
				break;
199
			q++;
200
		}
201
		if(p == e && *q == 0){
202
			strecpy(buf, buf+n, e+1);
203
			return buf;
204
		}
205
		p += strlen(p)+1;
206
	}
207
 
208
	return nil;
209
}
210
 
211
/* enable scheduling of this cpu */
212
void
213
machon(uint cpu)
214
{
215
	ulong cpubit;
216
 
217
	cpubit = 1 << cpu;
218
	lock(&active);
219
	if ((active.machs & cpubit) == 0) {	/* currently off? */
220
		conf.nmach++;
221
		active.machs |= cpubit;
222
	}
223
	unlock(&active);
224
}
225
 
226
/* disable scheduling of this cpu */
227
void
228
machoff(uint cpu)
229
{
230
	ulong cpubit;
231
 
232
	cpubit = 1 << cpu;
233
	lock(&active);
234
	if (active.machs & cpubit) {		/* currently on? */
235
		conf.nmach--;
236
		active.machs &= ~cpubit;
237
	}
238
	unlock(&active);
239
}
240
 
241
void
242
machinit(void)
243
{
244
	Mach *m0;
245
 
246
	if (m == 0) {
247
		serialputc('?');
248
		serialputc('m');
249
		serialputc('0');
250
	}
251
	if(machaddr[m->machno] != m) {
252
		serialputc('?');
253
		serialputc('m');
254
		serialputc('m');
255
	}
256
 
257
	if (canlock(&testlock)) {
258
		serialputc('?');
259
		serialputc('l');
260
		panic("cpu%d: locks don't work", m->machno);
261
	}
262
 
263
	m->ticks = 1;
264
	m->perf.period = 1;
265
	m0 = MACHP(0);
266
	if (m->machno != 0) {
267
		/* synchronise with cpu 0 */
268
		m->ticks = m0->ticks;
269
		m->fastclock = m0->fastclock;
270
		m->cpuhz = m0->cpuhz;
271
		m->delayloop = m0->delayloop;
272
	}
273
	if (m->machno != 0 &&
274
	    (m->fastclock == 0 || m->cpuhz == 0 || m->delayloop == 0))
275
		panic("buggered cpu 0 Mach");
276
 
277
	machon(m->machno);
278
	fpoff();
279
}
280
 
281
/* l.s has already zeroed Mach, which now contains our stack. */
282
void
283
mach0init(void)
284
{
285
	if (m == 0) {
286
		serialputc('?');
287
		serialputc('m');
288
	}
289
	conf.nmach = 0;
290
 
291
	m->machno = 0;
292
	machaddr[0] = m;
293
 
294
	lock(&testlock);		/* hold this forever */
295
	machinit();
296
 
297
	active.exiting = 0;
298
	l1cache->wbse(&active, sizeof active);
299
	up = nil;
300
}
301
 
302
/*
303
 *  count CPU's, set up their mach structures and l1 ptes.
304
 *  we're running on cpu 0 and our data structures were
305
 *  statically allocated.
306
 */
307
void
308
launchinit(void)
309
{
310
	int mach;
311
	Mach *mm;
312
	PTE *l1;
313
 
314
	for(mach = 1; mach < MAXMACH; mach++){
315
		machaddr[mach] = mm = mallocalign(MACHSIZE, MACHSIZE, 0, 0);
316
		l1 = mallocalign(L1SIZE, L1SIZE, 0, 0);
317
		if(mm == nil || l1 == nil)
318
			panic("launchinit");
319
		memset(mm, 0, MACHSIZE);
320
		mm->machno = mach;
321
 
322
		memmove(l1, (void *)L1, L1SIZE);  /* clone cpu0's l1 table */
323
		l1cache->wbse(l1, L1SIZE);
324
 
325
		mm->mmul1 = l1;
326
		l1cache->wbse(mm, MACHSIZE);
327
	}
328
	l1cache->wbse(machaddr, sizeof machaddr);
329
	conf.nmach = 1;
330
}
331
 
332
void
333
dump(void *vaddr, int words)
334
{
335
	ulong *addr;
336
 
337
	addr = vaddr;
338
	while (words-- > 0)
339
		iprint("%.8lux%c", *addr++, words % 8 == 0? '\n': ' ');
340
}
341
 
342
static void
343
cacheinit(void)
344
{
345
	allcacheinfo(cachel);
346
	cacheconf = (Lowmemcache *)CACHECONF;
347
	cacheconf->l1waysh = cachel[1].waysh;
348
	cacheconf->l1setsh = cachel[1].setsh;
349
	/* on the tegra 2, l2 is unarchitected */
350
	cacheconf->l2waysh = cachel[2].waysh;
351
	cacheconf->l2setsh = cachel[2].setsh;
352
 
353
	l2pl310init();
354
	allcacheson();
355
	allcache->wb();
356
}
357
 
358
void
359
l2pageinit(void)
360
{
361
	l2pages = KADDR(PHYSDRAM + DRAMSIZE - RESRVDHIMEM);
362
}
363
 
364
/*
365
 * at entry, l.s has set m for cpu0 and printed "Plan 9 from Be"
366
 * but has not zeroed bss.
367
 */
368
void
369
main(void)
370
{
371
	int cpu;
372
	static ulong vfy = 0xcafebabe;
373
 
374
	up = nil;
375
	if (vfy != 0xcafebabe) {
376
		serialputc('?');
377
		serialputc('d');
378
		panic("data segment misaligned");
379
	}
380
 
381
	memset(edata, 0, end - edata);
382
 
383
	/*
384
	 * we can't lock until smpon has run, but we're supposed to wait
385
	 * until l1 & l2 are on.  too bad.  l1 is on, l2 will soon be.
386
	 */
387
	smpon();
388
	iprint("ll Labs ");
389
	cacheinit();
390
 
391
	/*
392
	 * data segment is aligned, bss is zeroed, caches' characteristics
393
	 * are known.  begin initialisation.
394
	 */
395
	mach0init();
396
	l2pageinit();
397
	mmuinit();
398
 
399
	optionsinit("/boot/boot boot");
400
	quotefmtinstall();
401
 
402
	/* want plan9.ini to be able to affect memory sizing in confinit */
403
	plan9iniinit();		/* before we step on plan9.ini in low memory */
404
 
405
	/* l2 looks for *l2off= in plan9.ini */
406
	l2cache->on();		/* l2->on requires locks to work, thus smpon */
407
	l2cache->info(&cachel[2]);
408
	allcache->on();
409
 
410
	cortexa9cachecfg();
411
 
412
	trapinit();		/* so confinit can probe memory to size it */
413
	confinit();		/* figures out amount of memory */
414
	/* xinit prints (if it can), so finish up the banner here. */
415
	delay(100);
416
	navailcpus = getncpus();
417
	iprint("(mp arm; %d cpus)\n\n", navailcpus);
418
	delay(100);
419
 
420
	for (cpu = 1; cpu < navailcpus; cpu++)
421
		stopcpu(cpu);
422
 
423
	xinit();
424
	irqtooearly = 0;	/* now that xinit and trapinit have run */
425
 
426
	mainmem->flags |= POOL_ANTAGONISM /* | POOL_PARANOIA */ ;
427
 
428
	/*
429
	 * Printinit will cause the first malloc call.
430
	 * (printinit->qopen->malloc) unless any of the
431
	 * above (like clockinit) do an irqenable, which
432
	 * will call malloc.
433
	 * If the system dies here it's probably due
434
	 * to malloc(->xalloc) not being initialised
435
	 * correctly, or the data segment is misaligned
436
	 * (it's amazing how far you can get with
437
	 * things like that completely broken).
438
	 *
439
	 * (Should be) boilerplate from here on.
440
	 */
441
 
442
	archreset();			/* cfg clock signals, print cache cfg */
443
	clockinit();			/* start clocks */
444
	timersinit();
445
 
446
	delay(50);			/* let uart catch up */
447
	printinit();
448
	kbdenable();
449
 
450
	cpuidprint();
451
	chkmissing();
452
 
453
	procinit0();
454
	initseg();
455
 
456
//	dmainit();
457
	links();
458
	conf.monitor = 1;
459
//	screeninit();
460
 
461
	iprint("pcireset...");
462
	pcireset();			/* this tends to hang after a reboot */
463
	iprint("ok\n");
464
 
465
	chandevreset();			/* most devices are discovered here */
466
//	i8250console();			/* too early; see init0 */
467
 
468
	pageinit();			/* prints "1020M memory: ⋯ */
469
	swapinit();
470
	userinit();
471
 
472
	/*
473
	 * starting a cpu will eventually result in it calling schedinit,
474
	 * so everything necessary to run user processes should be set up
475
	 * before starting secondary cpus.
476
	 */
477
	launchinit();
478
	/* SMP & FW are already on when we get here; u-boot set them? */
479
	for (cpu = 1; cpu < navailcpus; cpu++)
480
		if (startcpu(cpu) < 0)
481
			panic("cpu%d didn't start", cpu);
482
	l1diag();
483
 
484
	schedinit();
485
	panic("cpu%d: schedinit returned", m->machno);
486
}
487
 
488
static void
489
shutdown(int ispanic)
490
{
491
	int ms, once;
492
 
493
	lock(&active);
494
	if(ispanic)
495
		active.ispanic = ispanic;
496
	else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
497
		active.ispanic = 0;
498
	once = active.machs & (1<<m->machno);
499
	/*
500
	 * setting exiting will make hzclock() on each processor call exit(0),
501
	 * which calls shutdown(0) and idles non-bootstrap cpus and returns
502
	 * on bootstrap processors (to permit a reboot).  clearing our bit
503
	 * in machs avoids calling exit(0) from hzclock() on this processor.
504
	 */
505
	active.machs &= ~(1<<m->machno);
506
	active.exiting = 1;
507
	unlock(&active);
508
 
509
	if(once) {
510
		delay(m->machno*1000);		/* stagger them */
511
		iprint("cpu%d: exiting\n", m->machno);
512
	}
513
	spllo();
514
	if (m->machno == 0)
515
		ms = 5*1000;
516
	else
517
		ms = 2*1000;
518
	for(; ms > 0; ms -= TK2MS(2)){
519
		delay(TK2MS(2));
520
		if(active.machs == 0 && consactive() == 0)
521
			break;
522
	}
523
	delay(500);
524
}
525
 
526
/*
527
 *  exit kernel either on a panic or user request
528
 */
529
void
530
exit(int code)
531
{
532
	shutdown(code);
533
	splhi();
534
	if (m->machno == 0)
535
		archreboot();
536
	else {
537
		intrcpushutdown();
538
		stopcpu(m->machno);
539
		for (;;)
540
			idlehands();
541
	}
542
}
543
 
544
int
545
isaconfig(char *class, int ctlrno, ISAConf *isa)
546
{
547
	char cc[32], *p;
548
	int i;
549
 
550
	snprint(cc, sizeof cc, "%s%d", class, ctlrno);
551
	p = getconf(cc);
552
	if(p == nil)
553
		return 0;
554
 
555
	isa->type = "";
556
	isa->nopt = tokenize(p, isa->opt, NISAOPT);
557
	for(i = 0; i < isa->nopt; i++){
558
		p = isa->opt[i];
559
		if(cistrncmp(p, "type=", 5) == 0)
560
			isa->type = p + 5;
561
		else if(cistrncmp(p, "port=", 5) == 0)
562
			isa->port = strtoul(p+5, &p, 0);
563
		else if(cistrncmp(p, "irq=", 4) == 0)
564
			isa->irq = strtoul(p+4, &p, 0);
565
		else if(cistrncmp(p, "dma=", 4) == 0)
566
			isa->dma = strtoul(p+4, &p, 0);
567
		else if(cistrncmp(p, "mem=", 4) == 0)
568
			isa->mem = strtoul(p+4, &p, 0);
569
		else if(cistrncmp(p, "size=", 5) == 0)
570
			isa->size = strtoul(p+5, &p, 0);
571
		else if(cistrncmp(p, "freq=", 5) == 0)
572
			isa->freq = strtoul(p+5, &p, 0);
573
	}
574
	return 1;
575
}
576
 
577
/*
578
 * the new kernel is already loaded at address `code'
579
 * of size `size' and entry point `entry'.
580
 */
581
void
582
reboot(void *entry, void *code, ulong size)
583
{
584
	int cpu, nmach, want, ms;
585
	void (*f)(ulong, ulong, ulong);
586
 
587
	nmach = conf.nmach;
588
	writeconf();
589
 
590
	/*
591
	 * the boot processor is cpu0.  execute this function on it
592
	 * so that the new kernel has the same cpu0.
593
	 */
594
	if (m->machno != 0) {
595
		procwired(up, 0);
596
		sched();
597
	}
598
	if (m->machno != 0)
599
		print("on cpu%d (not 0)!\n", m->machno);
600
 
601
	/*
602
	 * the other cpus could be holding locks that will never get
603
	 * released (e.g., in the print path) if we put them into
604
	 * reset now, so force them to shutdown gracefully first.
605
	 */
606
	for (want = 0, cpu = 1; cpu < navailcpus; cpu++)
607
		want |= 1 << cpu;
608
	active.stopped = 0;
609
	shutdown(0);
610
	for (ms = 15*1000; ms > 0 && active.stopped != want; ms -= 10)
611
		delay(10);
612
	delay(20);
613
	if (active.stopped != want) {
614
		for (cpu = 1; cpu < nmach; cpu++)
615
			stopcpu(cpu);		/* make really sure */
616
		delay(20);
617
	}
618
 
619
	/*
620
	 * should be the only processor running now
621
	 */
622
	pcireset();
623
//	print("reboot entry %#lux code %#lux size %ld\n",
624
//		PADDR(entry), PADDR(code), size);
625
 
626
	/* turn off buffered serial console */
627
	serialoq = nil;
628
	kprintoq = nil;
629
	screenputs = nil;
630
 
631
	/* shutdown devices */
632
	chandevshutdown();
633
 
634
	/* call off the dog */
635
	clockshutdown();
636
 
637
	splhi();
638
	intrshutdown();
639
 
640
	/* setup reboot trampoline function */
641
	f = (void*)REBOOTADDR;
642
	memmove(f, rebootcode, sizeof(rebootcode));
643
	cachedwb();
644
	l2cache->wbinv();
645
	l2cache->off();
646
	cacheuwbinv();
647
 
648
	/* off we go - never to return */
649
	(*f)(PADDR(entry), PADDR(code), size);
650
 
651
	iprint("loaded kernel returned!\n");
652
	archreboot();
653
}
654
 
655
/*
656
 *  starting place for first process
657
 */
658
void
659
init0(void)
660
{
661
	int i;
662
	char buf[2*KNAMELEN];
663
 
664
	up->nerrlab = 0;
665
	coherence();
666
	spllo();
667
 
668
	/*
669
	 * These are o.k. because rootinit is null.
670
	 * Then early kproc's will have a root and dot.
671
	 */
672
	up->slash = namec("#/", Atodir, 0, 0);
673
	pathclose(up->slash->path);
674
	up->slash->path = newpath("/");
675
	up->dot = cclone(up->slash);
676
 
677
	chandevinit();
678
	i8250console();		/* might be redundant, but harmless */
679
	if(kbdq == nil)
680
		panic("init0: nil kbdq");
681
	if(serialoq == nil)
682
		panic("init0: nil serialoq");
683
	normalprint = 1;
684
 
685
	if(!waserror()){
686
		snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
687
		ksetenv("terminal", buf, 0);
688
		ksetenv("cputype", "arm", 0);
689
		if(cpuserver)
690
			ksetenv("service", "cpu", 0);
691
		else
692
			ksetenv("service", "terminal", 0);
693
 
694
		/* convert plan9.ini variables to #e and #ec */
695
		for(i = 0; i < nconf; i++) {
696
			ksetenv(confname[i], confval[i], 0);
697
			ksetenv(confname[i], confval[i], 1);
698
		}
699
		poperror();
700
	}
701
	kproc("alarm", alarmkproc, 0);
702
//	kproc("startcpusproc", startcpusproc, nil);
703
 
704
	touser(sp);
705
}
706
 
707
static void
708
bootargs(uintptr base)
709
{
710
	int i;
711
	ulong ssize;
712
	char **av, *p;
713
 
714
	/*
715
	 * Push the boot args onto the stack.
716
	 * The initial value of the user stack must be such
717
	 * that the total used is larger than the maximum size
718
	 * of the argument list checked in syscall.
719
	 */
720
	i = oargblen+1;
721
	p = UINT2PTR(STACKALIGN(base + BY2PG - Ustkheadroom - i));
722
	memmove(p, oargb, i);
723
 
724
	/*
725
	 * Now push argc and the argv pointers.
726
	 * This isn't strictly correct as the code jumped to by
727
	 * touser in init9.s calls startboot (port/initcode.c) which
728
	 * expects arguments
729
	 * 	startboot(char *argv0, char **argv)
730
	 * not the usual (int argc, char* argv[]), but argv0 is
731
	 * unused so it doesn't matter (at the moment...).
732
	 */
733
	av = (char**)(p - (oargc+2)*sizeof(char*));
734
	ssize = base + BY2PG - PTR2UINT(av);
735
	*av++ = (char*)oargc;
736
	for(i = 0; i < oargc; i++)
737
		*av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
738
	*av = nil;
739
 
740
	/*
741
	 * Leave space for the return PC of the
742
	 * caller of initcode.
743
	 */
744
	sp = USTKTOP - ssize - sizeof(void*);
745
}
746
 
747
/*
748
 *  create the first process
749
 */
750
void
751
userinit(void)
752
{
753
	Proc *p;
754
	Segment *s;
755
	KMap *k;
756
	Page *pg;
757
 
758
	/* no processes yet */
759
	up = nil;
760
 
761
	p = newproc();
762
	p->pgrp = newpgrp();
763
	p->egrp = smalloc(sizeof(Egrp));
764
	p->egrp->ref = 1;
765
	p->fgrp = dupfgrp(nil);
766
	p->rgrp = newrgrp();
767
	p->procmode = 0640;
768
 
769
	kstrdup(&eve, "");
770
	kstrdup(&p->text, "*init*");
771
	kstrdup(&p->user, eve);
772
 
773
	/*
774
	 * Kernel Stack
775
	 */
776
	p->sched.pc = PTR2UINT(init0);
777
	p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
778
	p->sched.sp = STACKALIGN(p->sched.sp);
779
 
780
	/*
781
	 * User Stack
782
	 *
783
	 * Technically, newpage can't be called here because it
784
	 * should only be called when in a user context as it may
785
	 * try to sleep if there are no pages available, but that
786
	 * shouldn't be the case here.
787
	 */
788
	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
789
	s->flushme++;
790
	p->seg[SSEG] = s;
791
	pg = newpage(1, 0, USTKTOP-BY2PG);
792
	segpage(s, pg);
793
	k = kmap(pg);
794
	bootargs(VA(k));
795
	kunmap(k);
796
 
797
	/*
798
	 * Text
799
	 */
800
	s = newseg(SG_TEXT, UTZERO, 1);
801
	p->seg[TSEG] = s;
802
	pg = newpage(1, 0, UTZERO);
803
	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
804
	segpage(s, pg);
805
	k = kmap(s->map[0]->pages[0]);
806
	memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
807
	kunmap(k);
808
 
809
	ready(p);
810
}
811
 
812
Conf conf;			/* XXX - must go - gag */
813
 
814
Confmem tsmem[nelem(conf.mem)] = {
815
	/*
816
	 * Memory available to Plan 9:
817
	 */
818
	{ .base = PHYSDRAM, .limit = PHYSDRAM + Minmem, },
819
};
820
ulong memsize = DRAMSIZE;
821
 
822
static int
823
gotmem(uintptr sz)
824
{
825
	uintptr addr;
826
 
827
	/* back off a little from the end */
828
	addr = (uintptr)KADDR(PHYSDRAM + sz - BY2WD);
829
	if (probeaddr(addr) >= 0) {	/* didn't trap? memory present */
830
		memsize = sz;
831
		return 0;
832
	}
833
	return -1;
834
}
835
 
836
void
837
confinit(void)
838
{
839
	int i;
840
	ulong kpages;
841
	uintptr pa;
842
	char *p;
843
 
844
	/*
845
	 * Copy the physical memory configuration to Conf.mem.
846
	 */
847
	if(nelem(tsmem) > nelem(conf.mem)){
848
		iprint("memory configuration botch\n");
849
		exit(1);
850
	}
851
	if(0 && (p = getconf("*maxmem")) != nil) {
852
		memsize = strtoul(p, 0, 0) - PHYSDRAM;
853
		if (memsize < 16*MB)		/* sanity */
854
			memsize = 16*MB;
855
	}
856
 
857
	/*
858
	 * see if all that memory exists; if not, find out how much does.
859
	 * trapinit must have been called first.
860
	 */
861
	if (gotmem(memsize - RESRVDHIMEM) < 0)
862
		panic("can't find 1GB of memory");
863
 
864
	tsmem[0].limit = PHYSDRAM + memsize;
865
	memmove(conf.mem, tsmem, sizeof(tsmem));
866
 
867
	conf.npage = 0;
868
	pa = PADDR(PGROUND(PTR2UINT(end)));
869
 
870
	/*
871
	 *  we assume that the kernel is at the beginning of one of the
872
	 *  contiguous chunks of memory and fits therein.
873
	 */
874
	for(i=0; i<nelem(conf.mem); i++){
875
		/* take kernel out of allocatable space */
876
		if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
877
			conf.mem[i].base = pa;
878
 
879
		conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
880
		conf.npage += conf.mem[i].npage;
881
	}
882
 
883
	conf.upages = (conf.npage*80)/100;
884
	conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
885
 
886
	/* set up other configuration parameters */
887
	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
888
	if(cpuserver)
889
		conf.nproc *= 3;
890
	if(conf.nproc > 2000)
891
		conf.nproc = 2000;
892
	conf.nswap = conf.npage*3;
893
	conf.nswppo = 4096;
894
	conf.nimage = 200;
895
 
896
	/*
897
	 * it's simpler on mp systems to take page-faults early,
898
	 * on reference, rather than later, on write, which might
899
	 * require tlb shootdowns.
900
	 */
901
	conf.copymode = 1;		/* copy on reference */
902
 
903
	/*
904
	 * Guess how much is taken by the large permanent
905
	 * datastructures. Mntcache and Mntrpc are not accounted for
906
	 * (probably ~300KB).
907
	 */
908
	kpages = conf.npage - conf.upages;
909
	kpages *= BY2PG;
910
	kpages -= conf.upages*sizeof(Page)
911
		+ conf.nproc*sizeof(Proc)
912
		+ conf.nimage*sizeof(Image)
913
		+ conf.nswap
914
		+ conf.nswppo*sizeof(Page);
915
	mainmem->maxsize = kpages;
916
	if(!cpuserver)
917
		/*
918
		 * give terminals lots of image memory, too; the dynamic
919
		 * allocation will balance the load properly, hopefully.
920
		 * be careful with 32-bit overflow.
921
		 */
922
		imagmem->maxsize = kpages;
923
 
924
//	archconfinit();
925
}
926
 
927
int
928
cmpswap(long *addr, long old, long new)
929
{
930
	return cas((int *)addr, old, new);
931
}
932
 
933
void
934
advertwfi(void)			/* advertise my wfi status */
935
{
936
	ilock(&active);
937
	active.wfi |= 1 << m->machno;
938
	iunlock(&active);
939
}
940
 
941
void
942
unadvertwfi(void)		/* do not advertise my wfi status */
943
{
944
	ilock(&active);
945
	active.wfi &= ~(1 << m->machno);
946
	iunlock(&active);
947
}
948
 
949
void
950
idlehands(void)
951
{
952
#ifdef use_ipi
953
	int advertised;
954
 
955
	/* don't go into wfi until my local timer is ticking */
956
	if (m->ticks <= 1)
957
		return;
958
 
959
	advertised = 0;
960
	m->inidlehands++;
961
	/* avoid recursion via ilock, advertise iff this cpu is initialised */
962
	if (m->inidlehands == 1 && m->syscall > 0) {
963
		advertwfi();
964
		advertised = 1;
965
	}
966
 
967
	wfi();
968
 
969
	if (advertised)
970
		unadvertwfi();
971
	m->inidlehands--;
972
#endif
973
}
974
 
975
void
976
wakewfi(void)
977
{
978
#ifdef use_ipi
979
	uint cpu;
980
 
981
	/*
982
	 * find any cpu other than me currently in wfi.
983
	 * need not be exact.
984
	 */
985
	cpu = BI2BY*BY2WD - 1 - clz(active.wfi & ~(1 << m->machno));
986
	if (cpu < MAXMACH)
987
		intrcpu(cpu);
988
#endif
989
}