changelog shortlog tags branches changeset files file revisions raw help

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

changeset 3415: 4477c30eec57
parent: 69064e032a3e
child: 9ebd6b091242
author: cinap_lenrek@felloff.net
date: Tue, 04 Mar 2014 22:37:15 +0100
permissions: -rw-r--r--
description: pc64: fix segattach

the comment about Physseg.size being in pages is wrong,
change type to uintptr and correct the comment.

change the length parameter of segattach() and isoverlap()
to uintptr as well. segments can grow over 4GB in pc64 now
and globalsegattach() in devsegment calculates len argument
of isoverlap() by s->top - s->bot. note that the syscall
still takes 32bit ulong argument for the length!

check for integer overflow in segattach(), make sure segment
goes not beyond USTKTOP.

change PTEMAPMEM constant to uvlong as it is used to calculate
SEGMAXSIZE.
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);
cinap_lenrek@3415 226
 	seg.size = BY2PG;
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
 }