changelog shortlog tags branches changeset files file revisions raw help

Mercurial > hg > plan9front / annotate sys/src/9/bcm/main.c

changeset 3401: 69064e032a3e
parent: 4b8b4a29def2
child: 4477c30eec57
author: stanley.lieber@gmail.com
date: Fri, 28 Feb 2014 00:27:32 -0500
permissions: -rw-r--r--
description: bcm kernel: add *kernelpercent option for cmdline.txt
cinap_lenrek@2323 1
 #include "u.h"
cinap_lenrek@2323 2
 #include "tos.h"
cinap_lenrek@2323 3
 #include "../port/lib.h"
cinap_lenrek@2323 4
 #include "mem.h"
cinap_lenrek@2323 5
 #include "dat.h"
cinap_lenrek@2323 6
 #include "fns.h"
cinap_lenrek@2323 7
 
cinap_lenrek@2323 8
 #include "init.h"
cinap_lenrek@2323 9
 #include <pool.h>
cinap_lenrek@2323 10
 
cinap_lenrek@2323 11
 #include "reboot.h"
cinap_lenrek@2323 12
 
cinap_lenrek@2323 13
 /* Firmware compatibility */
cinap_lenrek@2323 14
 #define	Minfirmrev	326770
cinap_lenrek@2323 15
 #define	Minfirmdate	"22 Jul 2012"
cinap_lenrek@2323 16
 
cinap_lenrek@2323 17
 /*
cinap_lenrek@2323 18
  * Where configuration info is left for the loaded programme.
cinap_lenrek@2323 19
  */
cinap_lenrek@2323 20
 #define BOOTARGS	((char*)CONFADDR)
cinap_lenrek@2323 21
 #define	BOOTARGSLEN	(MACHADDR-CONFADDR)
cinap_lenrek@2323 22
 #define	MAXCONF		64
cinap_lenrek@2323 23
 #define MAXCONFLINE	160
cinap_lenrek@2323 24
 
cinap_lenrek@2323 25
 uintptr kseg0 = KZERO;
cinap_lenrek@2323 26
 Mach*	machaddr[MAXMACH];
cinap_lenrek@2323 27
 Conf	conf;
cinap_lenrek@2323 28
 ulong	memsize = 128*1024*1024;
cinap_lenrek@2323 29
 
cinap_lenrek@2323 30
 /*
cinap_lenrek@2323 31
  * Option arguments from the command line.
cinap_lenrek@2323 32
  * oargv[0] is the boot file.
cinap_lenrek@2323 33
  */
cinap_lenrek@2323 34
 static int oargc;
cinap_lenrek@2323 35
 static char* oargv[20];
cinap_lenrek@2323 36
 static char oargb[128];
cinap_lenrek@2323 37
 static int oargblen;
cinap_lenrek@2323 38
 
cinap_lenrek@2323 39
 static uintptr sp;		/* XXX - must go - user stack of init proc */
cinap_lenrek@2323 40
 
cinap_lenrek@2323 41
 /* store plan9.ini contents here at least until we stash them in #ec */
cinap_lenrek@2323 42
 static char confname[MAXCONF][KNAMELEN];
cinap_lenrek@2323 43
 static char confval[MAXCONF][MAXCONFLINE];
cinap_lenrek@2323 44
 static int nconf;
cinap_lenrek@2323 45
 
cinap_lenrek@2323 46
 typedef struct Atag Atag;
cinap_lenrek@2323 47
 struct Atag {
cinap_lenrek@2323 48
 	u32int	size;	/* size of atag in words, including this header */
cinap_lenrek@2323 49
 	u32int	tag;	/* atag type */
cinap_lenrek@2323 50
 	union {
cinap_lenrek@2323 51
 		u32int	data[1];	/* actually [size-2] */
cinap_lenrek@2323 52
 		/* AtagMem */
cinap_lenrek@2323 53
 		struct {
cinap_lenrek@2323 54
 			u32int	size;
cinap_lenrek@2323 55
 			u32int	base;
cinap_lenrek@2323 56
 		} mem;
cinap_lenrek@2323 57
 		/* AtagCmdLine */
cinap_lenrek@2323 58
 		char	cmdline[1];	/* actually [4*(size-2)] */
cinap_lenrek@2323 59
 	};
cinap_lenrek@2323 60
 };
cinap_lenrek@2323 61
 
cinap_lenrek@2323 62
 enum {
cinap_lenrek@2323 63
 	AtagNone	= 0x00000000,
cinap_lenrek@2323 64
 	AtagCore	= 0x54410001,
cinap_lenrek@2323 65
 	AtagMem		= 0x54410002,
cinap_lenrek@2323 66
 	AtagCmdline	= 0x54410009,
cinap_lenrek@2323 67
 };
cinap_lenrek@2323 68
 
cinap_lenrek@2323 69
 static int
cinap_lenrek@2323 70
 findconf(char *name)
cinap_lenrek@2323 71
 {
cinap_lenrek@2323 72
 	int i;
cinap_lenrek@2323 73
 
cinap_lenrek@2323 74
 	for(i = 0; i < nconf; i++)
cinap_lenrek@2323 75
 		if(cistrcmp(confname[i], name) == 0)
cinap_lenrek@2323 76
 			return i;
cinap_lenrek@2323 77
 	return -1;
cinap_lenrek@2323 78
 }
cinap_lenrek@2323 79
 
cinap_lenrek@2323 80
 char*
cinap_lenrek@2323 81
 getconf(char *name)
cinap_lenrek@2323 82
 {
cinap_lenrek@2323 83
 	int i;
cinap_lenrek@2323 84
 
cinap_lenrek@2323 85
 	i = findconf(name);
cinap_lenrek@2323 86
 	if(i >= 0)
cinap_lenrek@2323 87
 		return confval[i];
cinap_lenrek@2323 88
 	return nil;
cinap_lenrek@2323 89
 }
cinap_lenrek@2323 90
 
cinap_lenrek@2323 91
 void
cinap_lenrek@2323 92
 addconf(char *name, char *val)
cinap_lenrek@2323 93
 {
cinap_lenrek@2323 94
 	int i;
cinap_lenrek@2323 95
 
cinap_lenrek@2323 96
 	i = findconf(name);
cinap_lenrek@2323 97
 	if(i < 0){
cinap_lenrek@2323 98
 		if(val == nil || nconf >= MAXCONF)
cinap_lenrek@2323 99
 			return;
cinap_lenrek@2323 100
 		i = nconf++;
cinap_lenrek@2323 101
 		strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
cinap_lenrek@2323 102
 	}
cinap_lenrek@2323 103
 	strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
cinap_lenrek@2323 104
 }
cinap_lenrek@2323 105
 
cinap_lenrek@2323 106
 static void
cinap_lenrek@2323 107
 writeconf(void)
cinap_lenrek@2323 108
 {
cinap_lenrek@2323 109
 	char *p, *q;
cinap_lenrek@2323 110
 	int n;
cinap_lenrek@2323 111
 
cinap_lenrek@2323 112
 	p = getconfenv();
cinap_lenrek@2323 113
 
cinap_lenrek@2323 114
 	if(waserror()) {
cinap_lenrek@2323 115
 		free(p);
cinap_lenrek@2323 116
 		nexterror();
cinap_lenrek@2323 117
 	}
cinap_lenrek@2323 118
 
cinap_lenrek@2323 119
 	/* convert to name=value\n format */
cinap_lenrek@2323 120
 	for(q=p; *q; q++) {
cinap_lenrek@2323 121
 		q += strlen(q);
cinap_lenrek@2323 122
 		*q = '=';
cinap_lenrek@2323 123
 		q += strlen(q);
cinap_lenrek@2323 124
 		*q = '\n';
cinap_lenrek@2323 125
 	}
cinap_lenrek@2323 126
 	n = q - p + 1;
cinap_lenrek@2323 127
 	if(n >= BOOTARGSLEN)
cinap_lenrek@2323 128
 		error("kernel configuration too large");
cinap_lenrek@2323 129
 	memmove(BOOTARGS, p, n);
cinap_lenrek@2323 130
 	memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
cinap_lenrek@2323 131
 	poperror();
cinap_lenrek@2323 132
 	free(p);
cinap_lenrek@2323 133
 }
cinap_lenrek@2323 134
 
cinap_lenrek@2323 135
 static void
cinap_lenrek@2323 136
 plan9iniinit(char *s, int cmdline)
cinap_lenrek@2323 137
 {
cinap_lenrek@2323 138
 	char *toks[MAXCONF];
cinap_lenrek@2323 139
 	int i, c, n;
cinap_lenrek@2323 140
 	char *v;
cinap_lenrek@2323 141
 
cinap_lenrek@2323 142
 	if((c = *s) < ' ' || c >= 0x80)
cinap_lenrek@2323 143
 		return;
cinap_lenrek@2323 144
 	if(cmdline)
cinap_lenrek@2323 145
 		n = tokenize(s, toks, MAXCONF);
cinap_lenrek@2323 146
 	else
cinap_lenrek@2323 147
 		n = getfields(s, toks, MAXCONF, 1, "\n");
cinap_lenrek@2323 148
 	for(i = 0; i < n; i++){
cinap_lenrek@2323 149
 		if(toks[i][0] == '#')
cinap_lenrek@2323 150
 			continue;
cinap_lenrek@2323 151
 		v = strchr(toks[i], '=');
cinap_lenrek@2323 152
 		if(v == nil)
cinap_lenrek@2323 153
 			continue;
cinap_lenrek@2323 154
 		*v++ = '\0';
cinap_lenrek@2323 155
 		addconf(toks[i], v);
cinap_lenrek@2323 156
 	}
cinap_lenrek@2323 157
 }
cinap_lenrek@2323 158
 
cinap_lenrek@2323 159
 static void
cinap_lenrek@2323 160
 ataginit(Atag *a)
cinap_lenrek@2323 161
 {
cinap_lenrek@2323 162
 	int n;
cinap_lenrek@2323 163
 
cinap_lenrek@2323 164
 	if(a->tag != AtagCore){
cinap_lenrek@2323 165
 		plan9iniinit((char*)a, 0);
cinap_lenrek@2323 166
 		return;
cinap_lenrek@2323 167
 	}
cinap_lenrek@2323 168
 	while(a->tag != AtagNone){
cinap_lenrek@2323 169
 		switch(a->tag){
cinap_lenrek@2323 170
 		case AtagMem:
cinap_lenrek@2323 171
 			/* use only first bank */
cinap_lenrek@2323 172
 			if(conf.mem[0].limit == 0 && a->mem.size != 0){
cinap_lenrek@2323 173
 				memsize = a->mem.size;
cinap_lenrek@2323 174
 				conf.mem[0].base = a->mem.base;
cinap_lenrek@2323 175
 				conf.mem[0].limit = a->mem.base + memsize;
cinap_lenrek@2323 176
 			}
cinap_lenrek@2323 177
 			break;
cinap_lenrek@2323 178
 		case AtagCmdline:
cinap_lenrek@2323 179
 			n = (a->size * sizeof(u32int)) - offsetof(Atag, cmdline[0]);
cinap_lenrek@2323 180
 			if(a->cmdline + n < BOOTARGS + BOOTARGSLEN)
cinap_lenrek@2323 181
 				a->cmdline[n] = 0;
cinap_lenrek@2323 182
 			else
cinap_lenrek@2323 183
 				BOOTARGS[BOOTARGSLEN-1] = 0;
cinap_lenrek@2323 184
 			plan9iniinit(a->cmdline, 1);
cinap_lenrek@2323 185
 			break;
cinap_lenrek@2323 186
 		}
cinap_lenrek@2323 187
 		a = (Atag*)((u32int*)a + a->size);
cinap_lenrek@2323 188
 	}
cinap_lenrek@2323 189
 }
cinap_lenrek@2323 190
 
cinap_lenrek@2323 191
 void
cinap_lenrek@2323 192
 machinit(void)
cinap_lenrek@2323 193
 {
cinap_lenrek@2323 194
 	m->machno = 0;
cinap_lenrek@2323 195
 	machaddr[m->machno] = m;
cinap_lenrek@2323 196
 
cinap_lenrek@2323 197
 	m->ticks = 1;
cinap_lenrek@2323 198
 	m->perf.period = 1;
cinap_lenrek@2323 199
 
cinap_lenrek@2323 200
 	conf.nmach = 1;
cinap_lenrek@2323 201
 
cinap_lenrek@2323 202
 	active.machs = 1;
cinap_lenrek@2323 203
 	active.exiting = 0;
cinap_lenrek@2323 204
 
cinap_lenrek@2323 205
 	up = nil;
cinap_lenrek@2323 206
 }
cinap_lenrek@2323 207
 
cinap_lenrek@2323 208
 static void
cinap_lenrek@2323 209
 optionsinit(char* s)
cinap_lenrek@2323 210
 {
cinap_lenrek@2323 211
 	strecpy(oargb, oargb+sizeof(oargb), s);
cinap_lenrek@2323 212
 
cinap_lenrek@2323 213
 	oargblen = strlen(oargb);
cinap_lenrek@2323 214
 	oargc = tokenize(oargb, oargv, nelem(oargv)-1);
cinap_lenrek@2323 215
 	oargv[oargc] = nil;
cinap_lenrek@2323 216
 }
cinap_lenrek@2323 217
 
cinap_lenrek@2323 218
 void
mveety@3216 219
 gpiomeminit(void)
mveety@3216 220
 {
mveety@3216 221
 	Physseg seg;
mveety@3216 222
 	memset(&seg, 0, sizeof seg);
mveety@3216 223
 	seg.attr = SG_PHYSICAL;
mveety@3216 224
 	seg.name = "gpio";
mveety@3216 225
 	seg.pa = (VIRTIO+0x200000);
mveety@3216 226
 	seg.size = 1;
mveety@3216 227
 	addphysseg(&seg);
mveety@3216 228
 }
mveety@3216 229
 
mveety@3216 230
 
mveety@3216 231
 void
cinap_lenrek@2323 232
 main(void)
cinap_lenrek@2323 233
 {
cinap_lenrek@2323 234
 	extern char edata[], end[];
cinap_lenrek@2323 235
 	uint rev;
cinap_lenrek@2323 236
 
cinap_lenrek@2323 237
 	okay(1);
cinap_lenrek@2323 238
 	m = (Mach*)MACHADDR;
cinap_lenrek@2323 239
 	memset(edata, 0, end - edata);	/* clear bss */
cinap_lenrek@2323 240
 	machinit();
cinap_lenrek@2323 241
 	mmuinit1();
cinap_lenrek@2323 242
 
cinap_lenrek@2323 243
 	optionsinit("/boot/boot boot");
cinap_lenrek@2323 244
 	quotefmtinstall();
cinap_lenrek@2323 245
 	
cinap_lenrek@2323 246
 	ataginit((Atag*)BOOTARGS);
cinap_lenrek@2323 247
 	confinit();		/* figures out amount of memory */
cinap_lenrek@2323 248
 	xinit();
cinap_lenrek@2323 249
 	uartconsinit();
cinap_lenrek@2323 250
 	screeninit();
cinap_lenrek@2323 251
 
cinap_lenrek@2323 252
 	print("\nPlan 9 from Bell Labs\n");
cinap_lenrek@2323 253
 	rev = getfirmware();
cinap_lenrek@2323 254
 	print("firmware: rev %d\n", rev);
cinap_lenrek@2323 255
 	if(rev < Minfirmrev){
cinap_lenrek@2323 256
 		print("Sorry, firmware (start.elf) must be at least rev %d (%s)\n",
cinap_lenrek@2323 257
 			Minfirmrev, Minfirmdate);
cinap_lenrek@2323 258
 		for(;;)
cinap_lenrek@2323 259
 			;
cinap_lenrek@2323 260
 	}
cinap_lenrek@2323 261
 	trapinit();
cinap_lenrek@2323 262
 	clockinit();
cinap_lenrek@2323 263
 	printinit();
cinap_lenrek@2323 264
 	timersinit();
cinap_lenrek@2323 265
 	cpuidprint();
cinap_lenrek@2323 266
 	archreset();
cinap_lenrek@2323 267
 
cinap_lenrek@2323 268
 	procinit0();
cinap_lenrek@2323 269
 	initseg();
cinap_lenrek@2323 270
 	links();
cinap_lenrek@2323 271
 	chandevreset();			/* most devices are discovered here */
cinap_lenrek@2323 272
 	pageinit();
cinap_lenrek@2323 273
 	swapinit();
cinap_lenrek@2323 274
 	userinit();
mveety@3216 275
 	gpiomeminit();
cinap_lenrek@2323 276
 	schedinit();
cinap_lenrek@2323 277
 	assert(0);			/* shouldn't have returned */
cinap_lenrek@2323 278
 }
cinap_lenrek@2323 279
 
cinap_lenrek@2323 280
 /*
cinap_lenrek@2323 281
  *  starting place for first process
cinap_lenrek@2323 282
  */
cinap_lenrek@2323 283
 void
cinap_lenrek@2323 284
 init0(void)
cinap_lenrek@2323 285
 {
cinap_lenrek@2323 286
 	int i;
cinap_lenrek@2323 287
 	char buf[2*KNAMELEN];
cinap_lenrek@2323 288
 
cinap_lenrek@2323 289
 	up->nerrlab = 0;
cinap_lenrek@2323 290
 	coherence();
cinap_lenrek@2323 291
 	spllo();
cinap_lenrek@2323 292
 
cinap_lenrek@2323 293
 	/*
cinap_lenrek@2323 294
 	 * These are o.k. because rootinit is null.
cinap_lenrek@2323 295
 	 * Then early kproc's will have a root and dot.
cinap_lenrek@2323 296
 	 */
cinap_lenrek@2323 297
 	up->slash = namec("#/", Atodir, 0, 0);
cinap_lenrek@2323 298
 	pathclose(up->slash->path);
cinap_lenrek@2323 299
 	up->slash->path = newpath("/");
cinap_lenrek@2323 300
 	up->dot = cclone(up->slash);
cinap_lenrek@2323 301
 
cinap_lenrek@2323 302
 	chandevinit();
cinap_lenrek@2323 303
 
cinap_lenrek@2323 304
 	if(!waserror()){
cinap_lenrek@2323 305
 		snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
cinap_lenrek@2323 306
 		ksetenv("terminal", buf, 0);
cinap_lenrek@2323 307
 		ksetenv("cputype", "arm", 0);
cinap_lenrek@2323 308
 		if(cpuserver)
cinap_lenrek@2323 309
 			ksetenv("service", "cpu", 0);
cinap_lenrek@2323 310
 		else
cinap_lenrek@2323 311
 			ksetenv("service", "terminal", 0);
cinap_lenrek@2323 312
 		snprint(buf, sizeof(buf), "-a %s", getethermac());
cinap_lenrek@2323 313
 		ksetenv("etherargs", buf, 0);
cinap_lenrek@2323 314
 
cinap_lenrek@2323 315
 		/* convert plan9.ini variables to #e and #ec */
cinap_lenrek@2323 316
 		for(i = 0; i < nconf; i++) {
cinap_lenrek@2323 317
 			ksetenv(confname[i], confval[i], 0);
cinap_lenrek@2323 318
 			ksetenv(confname[i], confval[i], 1);
cinap_lenrek@2323 319
 		}
cinap_lenrek@2323 320
 		poperror();
cinap_lenrek@2323 321
 	}
cinap_lenrek@2323 322
 	kproc("alarm", alarmkproc, 0);
cinap_lenrek@2323 323
 	touser(sp);
cinap_lenrek@2323 324
 	assert(0);			/* shouldn't have returned */
cinap_lenrek@2323 325
 }
cinap_lenrek@2323 326
 
cinap_lenrek@2323 327
 static void
cinap_lenrek@2323 328
 bootargs(uintptr base)
cinap_lenrek@2323 329
 {
cinap_lenrek@2323 330
 	int i;
cinap_lenrek@2323 331
 	ulong ssize;
cinap_lenrek@2323 332
 	char **av, *p;
cinap_lenrek@2323 333
 
cinap_lenrek@2323 334
 	/*
cinap_lenrek@2323 335
 	 * Push the boot args onto the stack.
cinap_lenrek@2323 336
 	 * The initial value of the user stack must be such
cinap_lenrek@2323 337
 	 * that the total used is larger than the maximum size
cinap_lenrek@2323 338
 	 * of the argument list checked in syscall.
cinap_lenrek@2323 339
 	 */
cinap_lenrek@2323 340
 	i = oargblen+1;
cinap_lenrek@2323 341
 	p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(Tos) - i));
cinap_lenrek@2323 342
 	memmove(p, oargb, i);
cinap_lenrek@2323 343
 
cinap_lenrek@2323 344
 	/*
cinap_lenrek@2323 345
 	 * Now push the argv pointers.
cinap_lenrek@2323 346
 	 * The code jumped to by touser in lproc.s expects arguments
cinap_lenrek@2323 347
 	 *	main(char* argv0, ...)
cinap_lenrek@2323 348
 	 * and calls
cinap_lenrek@2323 349
 	 * 	startboot("/boot/boot", &argv0)
cinap_lenrek@2323 350
 	 * not the usual (int argc, char* argv[])
cinap_lenrek@2323 351
 	 */
cinap_lenrek@2323 352
 	av = (char**)(p - (oargc+1)*sizeof(char*));
cinap_lenrek@2323 353
 	ssize = base + BY2PG - PTR2UINT(av);
cinap_lenrek@2323 354
 	for(i = 0; i < oargc; i++)
cinap_lenrek@2323 355
 		*av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
cinap_lenrek@2323 356
 	*av = nil;
cinap_lenrek@2323 357
 	sp = USTKTOP - ssize;
cinap_lenrek@2323 358
 }
cinap_lenrek@2323 359
 
cinap_lenrek@2323 360
 /*
cinap_lenrek@2323 361
  *  create the first process
cinap_lenrek@2323 362
  */
cinap_lenrek@2323 363
 void
cinap_lenrek@2323 364
 userinit(void)
cinap_lenrek@2323 365
 {
cinap_lenrek@2323 366
 	Proc *p;
cinap_lenrek@2323 367
 	Segment *s;
cinap_lenrek@2323 368
 	KMap *k;
cinap_lenrek@2323 369
 	Page *pg;
cinap_lenrek@2323 370
 
cinap_lenrek@2323 371
 	/* no processes yet */
cinap_lenrek@2323 372
 	up = nil;
cinap_lenrek@2323 373
 
cinap_lenrek@2323 374
 	p = newproc();
cinap_lenrek@2323 375
 	p->pgrp = newpgrp();
cinap_lenrek@2323 376
 	p->egrp = smalloc(sizeof(Egrp));
cinap_lenrek@2323 377
 	p->egrp->ref = 1;
cinap_lenrek@2323 378
 	p->fgrp = dupfgrp(nil);
cinap_lenrek@2323 379
 	p->rgrp = newrgrp();
cinap_lenrek@2323 380
 	p->procmode = 0640;
cinap_lenrek@2323 381
 
cinap_lenrek@2323 382
 	kstrdup(&eve, "");
cinap_lenrek@2323 383
 	kstrdup(&p->text, "*init*");
cinap_lenrek@2323 384
 	kstrdup(&p->user, eve);
cinap_lenrek@2323 385
 
cinap_lenrek@2323 386
 	/*
cinap_lenrek@2323 387
 	 * Kernel Stack
cinap_lenrek@2323 388
 	 */
cinap_lenrek@2323 389
 	p->sched.pc = PTR2UINT(init0);
cinap_lenrek@2323 390
 	p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
cinap_lenrek@2323 391
 	p->sched.sp = STACKALIGN(p->sched.sp);
cinap_lenrek@2323 392
 
cinap_lenrek@2323 393
 	/*
cinap_lenrek@2323 394
 	 * User Stack
cinap_lenrek@2323 395
 	 *
cinap_lenrek@2323 396
 	 * Technically, newpage can't be called here because it
cinap_lenrek@2323 397
 	 * should only be called when in a user context as it may
cinap_lenrek@2323 398
 	 * try to sleep if there are no pages available, but that
cinap_lenrek@2323 399
 	 * shouldn't be the case here.
cinap_lenrek@2323 400
 	 */
cinap_lenrek@2323 401
 	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
cinap_lenrek@2323 402
 	s->flushme++;
cinap_lenrek@2323 403
 	p->seg[SSEG] = s;
cinap_lenrek@2323 404
 	pg = newpage(1, 0, USTKTOP-BY2PG);
cinap_lenrek@2323 405
 	segpage(s, pg);
cinap_lenrek@2323 406
 	k = kmap(pg);
cinap_lenrek@2323 407
 	bootargs(VA(k));
cinap_lenrek@2323 408
 	kunmap(k);
cinap_lenrek@2323 409
 
cinap_lenrek@2323 410
 	/*
cinap_lenrek@2323 411
 	 * Text
cinap_lenrek@2323 412
 	 */
cinap_lenrek@2323 413
 	s = newseg(SG_TEXT, UTZERO, 1);
cinap_lenrek@2323 414
 	p->seg[TSEG] = s;
cinap_lenrek@2323 415
 	pg = newpage(1, 0, UTZERO);
cinap_lenrek@2323 416
 	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
cinap_lenrek@2323 417
 	segpage(s, pg);
cinap_lenrek@2323 418
 	k = kmap(s->map[0]->pages[0]);
cinap_lenrek@2323 419
 	memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
cinap_lenrek@2323 420
 	kunmap(k);
cinap_lenrek@2323 421
 
cinap_lenrek@2323 422
 	ready(p);
cinap_lenrek@2323 423
 }
cinap_lenrek@2323 424
 
cinap_lenrek@2323 425
 void
cinap_lenrek@2323 426
 confinit(void)
cinap_lenrek@2323 427
 {
stanley@3401 428
 	int i, userpcnt;
cinap_lenrek@2323 429
 	ulong kpages;
cinap_lenrek@2323 430
 	uintptr pa;
cinap_lenrek@2323 431
 	char *p;
cinap_lenrek@2323 432
 
stanley@3401 433
 	if(p = getconf("*kernelpercent"))
stanley@3401 434
 		userpcnt = 100 - strtol(p, 0, 0);
stanley@3401 435
 	else
stanley@3401 436
 		userpcnt = 0;
stanley@3401 437
 
cinap_lenrek@2323 438
 	if(0 && (p = getconf("service")) != nil){
cinap_lenrek@2323 439
 		if(strcmp(p, "cpu") == 0)
cinap_lenrek@2323 440
 			cpuserver = 1;
cinap_lenrek@2323 441
 		else if(strcmp(p,"terminal") == 0)
cinap_lenrek@2323 442
 			cpuserver = 0;
cinap_lenrek@2323 443
 	}
cinap_lenrek@2323 444
 	if((p = getconf("*maxmem")) != nil){
cinap_lenrek@2323 445
 		memsize = strtoul(p, 0, 0) - PHYSDRAM;
cinap_lenrek@2323 446
 		if (memsize < 16*MB)		/* sanity */
cinap_lenrek@2323 447
 			memsize = 16*MB;
cinap_lenrek@2323 448
 	}
cinap_lenrek@2323 449
 
cinap_lenrek@2323 450
 	getramsize(&conf.mem[0]);
cinap_lenrek@2323 451
 	if(conf.mem[0].limit == 0){
cinap_lenrek@2323 452
 		conf.mem[0].base = PHYSDRAM;
cinap_lenrek@2323 453
 		conf.mem[0].limit = PHYSDRAM + memsize;
cinap_lenrek@2323 454
 	}else if(p != nil)
cinap_lenrek@2323 455
 		conf.mem[0].limit = conf.mem[0].base + memsize;
cinap_lenrek@2323 456
 
cinap_lenrek@2323 457
 	conf.npage = 0;
cinap_lenrek@2323 458
 	pa = PADDR(PGROUND(PTR2UINT(end)));
cinap_lenrek@2323 459
 
cinap_lenrek@2323 460
 	/*
cinap_lenrek@2323 461
 	 *  we assume that the kernel is at the beginning of one of the
cinap_lenrek@2323 462
 	 *  contiguous chunks of memory and fits therein.
cinap_lenrek@2323 463
 	 */
cinap_lenrek@2323 464
 	for(i=0; i<nelem(conf.mem); i++){
cinap_lenrek@2323 465
 		/* take kernel out of allocatable space */
cinap_lenrek@2323 466
 		if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
cinap_lenrek@2323 467
 			conf.mem[i].base = pa;
cinap_lenrek@2323 468
 
cinap_lenrek@2323 469
 		conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
cinap_lenrek@2323 470
 		conf.npage += conf.mem[i].npage;
cinap_lenrek@2323 471
 	}
cinap_lenrek@2323 472
 
stanley@3401 473
 	if(userpcnt < 10)
stanley@3401 474
 		userpcnt = 60 + cpuserver*10;
stanley@3401 475
 	kpages = conf.npage - (conf.npage*userpcnt)/100;
stanley@3401 476
 
stanley@3401 477
 	/*
stanley@3401 478
 	 * can't go past the end of virtual memory
stanley@3401 479
 	 * (ulong)-KZERO is 2^32 - KZERO
stanley@3401 480
 	 */
stanley@3401 481
 	if(kpages > ((ulong)-KZERO)/BY2PG)
stanley@3401 482
 		kpages = ((ulong)-KZERO)/BY2PG;
stanley@3401 483
 
stanley@3401 484
 	conf.upages = conf.npage - kpages;
stanley@3401 485
 	conf.ialloc = (kpages/2)*BY2PG;
cinap_lenrek@2323 486
 
cinap_lenrek@2323 487
 	/* only one processor */
cinap_lenrek@2323 488
 	conf.nmach = 1;
cinap_lenrek@2323 489
 
cinap_lenrek@2323 490
 	/* set up other configuration parameters */
cinap_lenrek@2323 491
 	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
cinap_lenrek@2323 492
 	if(cpuserver)
cinap_lenrek@2323 493
 		conf.nproc *= 3;
cinap_lenrek@2323 494
 	if(conf.nproc > 2000)
cinap_lenrek@2323 495
 		conf.nproc = 2000;
cinap_lenrek@2323 496
 	conf.nswap = conf.npage*3;
cinap_lenrek@2323 497
 	conf.nswppo = 4096;
cinap_lenrek@2323 498
 	conf.nimage = 200;
cinap_lenrek@2323 499
 
cinap_lenrek@2323 500
 	conf.copymode = 0;		/* copy on write */
cinap_lenrek@2323 501
 
cinap_lenrek@2323 502
 	/*
cinap_lenrek@2323 503
 	 * Guess how much is taken by the large permanent
cinap_lenrek@2323 504
 	 * datastructures. Mntcache and Mntrpc are not accounted for
cinap_lenrek@2323 505
 	 * (probably ~300KB).
cinap_lenrek@2323 506
 	 */
cinap_lenrek@2323 507
 	kpages = conf.npage - conf.upages;
cinap_lenrek@2323 508
 	kpages *= BY2PG;
cinap_lenrek@2323 509
 	kpages -= conf.upages*sizeof(Page)
cinap_lenrek@2323 510
 		+ conf.nproc*sizeof(Proc)
cinap_lenrek@2323 511
 		+ conf.nimage*sizeof(Image)
cinap_lenrek@2323 512
 		+ conf.nswap
stanley@3401 513
 		+ conf.nswppo*sizeof(Page*);
cinap_lenrek@2323 514
 	mainmem->maxsize = kpages;
cinap_lenrek@2323 515
 	if(!cpuserver)
cinap_lenrek@2323 516
 		/*
cinap_lenrek@2323 517
 		 * give terminals lots of image memory, too; the dynamic
cinap_lenrek@2323 518
 		 * allocation will balance the load properly, hopefully.
cinap_lenrek@2323 519
 		 * be careful with 32-bit overflow.
cinap_lenrek@2323 520
 		 */
cinap_lenrek@2323 521
 		imagmem->maxsize = kpages;
cinap_lenrek@2323 522
 
cinap_lenrek@2323 523
 }
cinap_lenrek@2323 524
 
cinap_lenrek@2323 525
 static void
cinap_lenrek@2323 526
 shutdown(int ispanic)
cinap_lenrek@2323 527
 {
cinap_lenrek@2323 528
 	int ms, once;
cinap_lenrek@2323 529
 
cinap_lenrek@2323 530
 	lock(&active);
cinap_lenrek@2323 531
 	if(ispanic)
cinap_lenrek@2323 532
 		active.ispanic = ispanic;
cinap_lenrek@2323 533
 	else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
cinap_lenrek@2323 534
 		active.ispanic = 0;
cinap_lenrek@2323 535
 	once = active.machs & (1<<m->machno);
cinap_lenrek@2323 536
 	active.machs &= ~(1<<m->machno);
cinap_lenrek@2323 537
 	active.exiting = 1;
cinap_lenrek@2323 538
 	unlock(&active);
cinap_lenrek@2323 539
 
cinap_lenrek@2323 540
 	if(once)
cinap_lenrek@2323 541
 		iprint("cpu%d: exiting\n", m->machno);
cinap_lenrek@2323 542
 	spllo();
cinap_lenrek@2323 543
 	for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
cinap_lenrek@2323 544
 		delay(TK2MS(2));
cinap_lenrek@2323 545
 		if(active.machs == 0 && consactive() == 0)
cinap_lenrek@2323 546
 			break;
cinap_lenrek@2323 547
 	}
cinap_lenrek@2323 548
 	delay(1000);
cinap_lenrek@2323 549
 }
cinap_lenrek@2323 550
 
cinap_lenrek@2323 551
 /*
cinap_lenrek@2323 552
  *  exit kernel either on a panic or user request
cinap_lenrek@2323 553
  */
cinap_lenrek@2323 554
 void
cinap_lenrek@2323 555
 exit(int code)
cinap_lenrek@2323 556
 {
cinap_lenrek@2323 557
 	shutdown(code);
cinap_lenrek@2323 558
 	splfhi();
cinap_lenrek@2323 559
 	archreboot();
cinap_lenrek@2323 560
 }
cinap_lenrek@2323 561
 
cinap_lenrek@2323 562
 /*
cinap_lenrek@2323 563
  * stub for ../omap/devether.c
cinap_lenrek@2323 564
  */
cinap_lenrek@2323 565
 int
cinap_lenrek@2323 566
 isaconfig(char *class, int ctlrno, ISAConf *isa)
cinap_lenrek@2323 567
 {
cinap_lenrek@2323 568
 	USED(ctlrno);
cinap_lenrek@2323 569
 	USED(isa);
cinap_lenrek@2323 570
 	return strcmp(class, "ether") == 0;
cinap_lenrek@2323 571
 }
cinap_lenrek@2323 572
 
cinap_lenrek@2323 573
 /*
cinap_lenrek@2323 574
  * the new kernel is already loaded at address `code'
cinap_lenrek@2323 575
  * of size `size' and entry point `entry'.
cinap_lenrek@2323 576
  */
cinap_lenrek@2323 577
 void
cinap_lenrek@2323 578
 reboot(void *entry, void *code, ulong size)
cinap_lenrek@2323 579
 {
cinap_lenrek@2323 580
 	void (*f)(ulong, ulong, ulong);
cinap_lenrek@2323 581
 
cinap_lenrek@2323 582
 	print("starting reboot...");
cinap_lenrek@2323 583
 	writeconf();
cinap_lenrek@2323 584
 	shutdown(0);
cinap_lenrek@2323 585
 
cinap_lenrek@2323 586
 	/*
cinap_lenrek@2323 587
 	 * should be the only processor running now
cinap_lenrek@2323 588
 	 */
cinap_lenrek@2323 589
 
cinap_lenrek@2323 590
 	print("reboot entry %#lux code %#lux size %ld\n",
cinap_lenrek@2323 591
 		PADDR(entry), PADDR(code), size);
cinap_lenrek@2323 592
 	delay(100);
cinap_lenrek@2323 593
 
cinap_lenrek@2323 594
 	/* turn off buffered serial console */
cinap_lenrek@2323 595
 	serialoq = nil;
cinap_lenrek@2323 596
 	kprintoq = nil;
cinap_lenrek@2323 597
 	screenputs = nil;
cinap_lenrek@2323 598
 
cinap_lenrek@2323 599
 	/* shutdown devices */
cinap_lenrek@2323 600
 	chandevshutdown();
cinap_lenrek@2323 601
 
cinap_lenrek@2323 602
 	/* stop the clock (and watchdog if any) */
cinap_lenrek@2323 603
 	clockshutdown();
cinap_lenrek@2323 604
 
cinap_lenrek@2323 605
 	splfhi();
cinap_lenrek@2323 606
 	intrsoff();
cinap_lenrek@2323 607
 
cinap_lenrek@2323 608
 	/* setup reboot trampoline function */
cinap_lenrek@2323 609
 	f = (void*)REBOOTADDR;
cinap_lenrek@2323 610
 	memmove(f, rebootcode, sizeof(rebootcode));
cinap_lenrek@2323 611
 	cacheuwbinv();
cinap_lenrek@2323 612
 
cinap_lenrek@2323 613
 	/* off we go - never to return */
cinap_lenrek@2323 614
 	(*f)(PADDR(entry), PADDR(code), size);
cinap_lenrek@2323 615
 
cinap_lenrek@2323 616
 	iprint("loaded kernel returned!\n");
cinap_lenrek@2323 617
 	delay(1000);
cinap_lenrek@2323 618
 	archreboot();
cinap_lenrek@2323 619
 }
cinap_lenrek@2323 620
 
cinap_lenrek@2323 621
 int
cinap_lenrek@2323 622
 cmpswap(long *addr, long old, long new)
cinap_lenrek@2323 623
 {
cinap_lenrek@2323 624
 	return cas32(addr, old, new);
cinap_lenrek@2323 625
 }