changelog shortlog tags branches changeset files file revisions raw help

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

changeset 2503: e48d4208f76f
parent: f7c2fc5e9dd8
child: 4b8b4a29def2
author: cinap_lenrek@gmx.de
date: Sun, 14 Apr 2013 16:28:54 +0200
permissions: -rw-r--r--
description: reduce software cursor flickering

the software cursor starts flickering and reacts bumby if a process
spends most of its time with drawlock acquired because the timer interrupt
thats supposed to redraw the cursor fails to acquire the lock at the time
the timer fires.

instead of trying to draw the cursor on the screen from a timer interrupt
30 times per second, devmouse now creates a process calling cursoron() and
cursoroff() when the cursor needs to be redrawn. this allows the swcursor
to schedule a redraw while holding the drawlock in swcursoravoid() and
cursoron()/cursoroff() are now able to wait for a qlock (drawlock) because
they get called from process context.

the overall responsiveness is also improved with this change as the cursor
redraw rate isnt limited to 30 times a second anymore.
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
cinap_lenrek@2323 219
 main(void)
cinap_lenrek@2323 220
 {
cinap_lenrek@2323 221
 	extern char edata[], end[];
cinap_lenrek@2323 222
 	uint rev;
cinap_lenrek@2323 223
 
cinap_lenrek@2323 224
 	okay(1);
cinap_lenrek@2323 225
 	m = (Mach*)MACHADDR;
cinap_lenrek@2323 226
 	memset(edata, 0, end - edata);	/* clear bss */
cinap_lenrek@2323 227
 	machinit();
cinap_lenrek@2323 228
 	mmuinit1();
cinap_lenrek@2323 229
 
cinap_lenrek@2323 230
 	optionsinit("/boot/boot boot");
cinap_lenrek@2323 231
 	quotefmtinstall();
cinap_lenrek@2323 232
 	
cinap_lenrek@2323 233
 	ataginit((Atag*)BOOTARGS);
cinap_lenrek@2323 234
 	confinit();		/* figures out amount of memory */
cinap_lenrek@2323 235
 	xinit();
cinap_lenrek@2323 236
 	uartconsinit();
cinap_lenrek@2323 237
 	screeninit();
cinap_lenrek@2323 238
 
cinap_lenrek@2323 239
 	print("\nPlan 9 from Bell Labs\n");
cinap_lenrek@2323 240
 	rev = getfirmware();
cinap_lenrek@2323 241
 	print("firmware: rev %d\n", rev);
cinap_lenrek@2323 242
 	if(rev < Minfirmrev){
cinap_lenrek@2323 243
 		print("Sorry, firmware (start.elf) must be at least rev %d (%s)\n",
cinap_lenrek@2323 244
 			Minfirmrev, Minfirmdate);
cinap_lenrek@2323 245
 		for(;;)
cinap_lenrek@2323 246
 			;
cinap_lenrek@2323 247
 	}
cinap_lenrek@2323 248
 	trapinit();
cinap_lenrek@2323 249
 	clockinit();
cinap_lenrek@2323 250
 	printinit();
cinap_lenrek@2323 251
 	timersinit();
cinap_lenrek@2323 252
 	cpuidprint();
cinap_lenrek@2323 253
 	archreset();
cinap_lenrek@2323 254
 
cinap_lenrek@2323 255
 	procinit0();
cinap_lenrek@2323 256
 	initseg();
cinap_lenrek@2323 257
 	links();
cinap_lenrek@2323 258
 	chandevreset();			/* most devices are discovered here */
cinap_lenrek@2323 259
 	pageinit();
cinap_lenrek@2323 260
 	swapinit();
cinap_lenrek@2323 261
 	userinit();
cinap_lenrek@2323 262
 	schedinit();
cinap_lenrek@2323 263
 	assert(0);			/* shouldn't have returned */
cinap_lenrek@2323 264
 }
cinap_lenrek@2323 265
 
cinap_lenrek@2323 266
 /*
cinap_lenrek@2323 267
  *  starting place for first process
cinap_lenrek@2323 268
  */
cinap_lenrek@2323 269
 void
cinap_lenrek@2323 270
 init0(void)
cinap_lenrek@2323 271
 {
cinap_lenrek@2323 272
 	int i;
cinap_lenrek@2323 273
 	char buf[2*KNAMELEN];
cinap_lenrek@2323 274
 
cinap_lenrek@2323 275
 	up->nerrlab = 0;
cinap_lenrek@2323 276
 	coherence();
cinap_lenrek@2323 277
 	spllo();
cinap_lenrek@2323 278
 
cinap_lenrek@2323 279
 	/*
cinap_lenrek@2323 280
 	 * These are o.k. because rootinit is null.
cinap_lenrek@2323 281
 	 * Then early kproc's will have a root and dot.
cinap_lenrek@2323 282
 	 */
cinap_lenrek@2323 283
 	up->slash = namec("#/", Atodir, 0, 0);
cinap_lenrek@2323 284
 	pathclose(up->slash->path);
cinap_lenrek@2323 285
 	up->slash->path = newpath("/");
cinap_lenrek@2323 286
 	up->dot = cclone(up->slash);
cinap_lenrek@2323 287
 
cinap_lenrek@2323 288
 	chandevinit();
cinap_lenrek@2323 289
 
cinap_lenrek@2323 290
 	if(!waserror()){
cinap_lenrek@2323 291
 		snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
cinap_lenrek@2323 292
 		ksetenv("terminal", buf, 0);
cinap_lenrek@2323 293
 		ksetenv("cputype", "arm", 0);
cinap_lenrek@2323 294
 		if(cpuserver)
cinap_lenrek@2323 295
 			ksetenv("service", "cpu", 0);
cinap_lenrek@2323 296
 		else
cinap_lenrek@2323 297
 			ksetenv("service", "terminal", 0);
cinap_lenrek@2323 298
 		snprint(buf, sizeof(buf), "-a %s", getethermac());
cinap_lenrek@2323 299
 		ksetenv("etherargs", buf, 0);
cinap_lenrek@2323 300
 
cinap_lenrek@2323 301
 		/* convert plan9.ini variables to #e and #ec */
cinap_lenrek@2323 302
 		for(i = 0; i < nconf; i++) {
cinap_lenrek@2323 303
 			ksetenv(confname[i], confval[i], 0);
cinap_lenrek@2323 304
 			ksetenv(confname[i], confval[i], 1);
cinap_lenrek@2323 305
 		}
cinap_lenrek@2323 306
 		poperror();
cinap_lenrek@2323 307
 	}
cinap_lenrek@2323 308
 	kproc("alarm", alarmkproc, 0);
cinap_lenrek@2323 309
 	touser(sp);
cinap_lenrek@2323 310
 	assert(0);			/* shouldn't have returned */
cinap_lenrek@2323 311
 }
cinap_lenrek@2323 312
 
cinap_lenrek@2323 313
 static void
cinap_lenrek@2323 314
 bootargs(uintptr base)
cinap_lenrek@2323 315
 {
cinap_lenrek@2323 316
 	int i;
cinap_lenrek@2323 317
 	ulong ssize;
cinap_lenrek@2323 318
 	char **av, *p;
cinap_lenrek@2323 319
 
cinap_lenrek@2323 320
 	/*
cinap_lenrek@2323 321
 	 * Push the boot args onto the stack.
cinap_lenrek@2323 322
 	 * The initial value of the user stack must be such
cinap_lenrek@2323 323
 	 * that the total used is larger than the maximum size
cinap_lenrek@2323 324
 	 * of the argument list checked in syscall.
cinap_lenrek@2323 325
 	 */
cinap_lenrek@2323 326
 	i = oargblen+1;
cinap_lenrek@2323 327
 	p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(Tos) - i));
cinap_lenrek@2323 328
 	memmove(p, oargb, i);
cinap_lenrek@2323 329
 
cinap_lenrek@2323 330
 	/*
cinap_lenrek@2323 331
 	 * Now push the argv pointers.
cinap_lenrek@2323 332
 	 * The code jumped to by touser in lproc.s expects arguments
cinap_lenrek@2323 333
 	 *	main(char* argv0, ...)
cinap_lenrek@2323 334
 	 * and calls
cinap_lenrek@2323 335
 	 * 	startboot("/boot/boot", &argv0)
cinap_lenrek@2323 336
 	 * not the usual (int argc, char* argv[])
cinap_lenrek@2323 337
 	 */
cinap_lenrek@2323 338
 	av = (char**)(p - (oargc+1)*sizeof(char*));
cinap_lenrek@2323 339
 	ssize = base + BY2PG - PTR2UINT(av);
cinap_lenrek@2323 340
 	for(i = 0; i < oargc; i++)
cinap_lenrek@2323 341
 		*av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
cinap_lenrek@2323 342
 	*av = nil;
cinap_lenrek@2323 343
 	sp = USTKTOP - ssize;
cinap_lenrek@2323 344
 }
cinap_lenrek@2323 345
 
cinap_lenrek@2323 346
 /*
cinap_lenrek@2323 347
  *  create the first process
cinap_lenrek@2323 348
  */
cinap_lenrek@2323 349
 void
cinap_lenrek@2323 350
 userinit(void)
cinap_lenrek@2323 351
 {
cinap_lenrek@2323 352
 	Proc *p;
cinap_lenrek@2323 353
 	Segment *s;
cinap_lenrek@2323 354
 	KMap *k;
cinap_lenrek@2323 355
 	Page *pg;
cinap_lenrek@2323 356
 
cinap_lenrek@2323 357
 	/* no processes yet */
cinap_lenrek@2323 358
 	up = nil;
cinap_lenrek@2323 359
 
cinap_lenrek@2323 360
 	p = newproc();
cinap_lenrek@2323 361
 	p->pgrp = newpgrp();
cinap_lenrek@2323 362
 	p->egrp = smalloc(sizeof(Egrp));
cinap_lenrek@2323 363
 	p->egrp->ref = 1;
cinap_lenrek@2323 364
 	p->fgrp = dupfgrp(nil);
cinap_lenrek@2323 365
 	p->rgrp = newrgrp();
cinap_lenrek@2323 366
 	p->procmode = 0640;
cinap_lenrek@2323 367
 
cinap_lenrek@2323 368
 	kstrdup(&eve, "");
cinap_lenrek@2323 369
 	kstrdup(&p->text, "*init*");
cinap_lenrek@2323 370
 	kstrdup(&p->user, eve);
cinap_lenrek@2323 371
 
cinap_lenrek@2323 372
 	/*
cinap_lenrek@2323 373
 	 * Kernel Stack
cinap_lenrek@2323 374
 	 */
cinap_lenrek@2323 375
 	p->sched.pc = PTR2UINT(init0);
cinap_lenrek@2323 376
 	p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
cinap_lenrek@2323 377
 	p->sched.sp = STACKALIGN(p->sched.sp);
cinap_lenrek@2323 378
 
cinap_lenrek@2323 379
 	/*
cinap_lenrek@2323 380
 	 * User Stack
cinap_lenrek@2323 381
 	 *
cinap_lenrek@2323 382
 	 * Technically, newpage can't be called here because it
cinap_lenrek@2323 383
 	 * should only be called when in a user context as it may
cinap_lenrek@2323 384
 	 * try to sleep if there are no pages available, but that
cinap_lenrek@2323 385
 	 * shouldn't be the case here.
cinap_lenrek@2323 386
 	 */
cinap_lenrek@2323 387
 	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
cinap_lenrek@2323 388
 	s->flushme++;
cinap_lenrek@2323 389
 	p->seg[SSEG] = s;
cinap_lenrek@2323 390
 	pg = newpage(1, 0, USTKTOP-BY2PG);
cinap_lenrek@2323 391
 	segpage(s, pg);
cinap_lenrek@2323 392
 	k = kmap(pg);
cinap_lenrek@2323 393
 	bootargs(VA(k));
cinap_lenrek@2323 394
 	kunmap(k);
cinap_lenrek@2323 395
 
cinap_lenrek@2323 396
 	/*
cinap_lenrek@2323 397
 	 * Text
cinap_lenrek@2323 398
 	 */
cinap_lenrek@2323 399
 	s = newseg(SG_TEXT, UTZERO, 1);
cinap_lenrek@2323 400
 	p->seg[TSEG] = s;
cinap_lenrek@2323 401
 	pg = newpage(1, 0, UTZERO);
cinap_lenrek@2323 402
 	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
cinap_lenrek@2323 403
 	segpage(s, pg);
cinap_lenrek@2323 404
 	k = kmap(s->map[0]->pages[0]);
cinap_lenrek@2323 405
 	memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
cinap_lenrek@2323 406
 	kunmap(k);
cinap_lenrek@2323 407
 
cinap_lenrek@2323 408
 	ready(p);
cinap_lenrek@2323 409
 }
cinap_lenrek@2323 410
 
cinap_lenrek@2323 411
 void
cinap_lenrek@2323 412
 confinit(void)
cinap_lenrek@2323 413
 {
cinap_lenrek@2323 414
 	int i;
cinap_lenrek@2323 415
 	ulong kpages;
cinap_lenrek@2323 416
 	uintptr pa;
cinap_lenrek@2323 417
 	char *p;
cinap_lenrek@2323 418
 
cinap_lenrek@2323 419
 	if(0 && (p = getconf("service")) != nil){
cinap_lenrek@2323 420
 		if(strcmp(p, "cpu") == 0)
cinap_lenrek@2323 421
 			cpuserver = 1;
cinap_lenrek@2323 422
 		else if(strcmp(p,"terminal") == 0)
cinap_lenrek@2323 423
 			cpuserver = 0;
cinap_lenrek@2323 424
 	}
cinap_lenrek@2323 425
 	if((p = getconf("*maxmem")) != nil){
cinap_lenrek@2323 426
 		memsize = strtoul(p, 0, 0) - PHYSDRAM;
cinap_lenrek@2323 427
 		if (memsize < 16*MB)		/* sanity */
cinap_lenrek@2323 428
 			memsize = 16*MB;
cinap_lenrek@2323 429
 	}
cinap_lenrek@2323 430
 
cinap_lenrek@2323 431
 	getramsize(&conf.mem[0]);
cinap_lenrek@2323 432
 	if(conf.mem[0].limit == 0){
cinap_lenrek@2323 433
 		conf.mem[0].base = PHYSDRAM;
cinap_lenrek@2323 434
 		conf.mem[0].limit = PHYSDRAM + memsize;
cinap_lenrek@2323 435
 	}else if(p != nil)
cinap_lenrek@2323 436
 		conf.mem[0].limit = conf.mem[0].base + memsize;
cinap_lenrek@2323 437
 
cinap_lenrek@2323 438
 	conf.npage = 0;
cinap_lenrek@2323 439
 	pa = PADDR(PGROUND(PTR2UINT(end)));
cinap_lenrek@2323 440
 
cinap_lenrek@2323 441
 	/*
cinap_lenrek@2323 442
 	 *  we assume that the kernel is at the beginning of one of the
cinap_lenrek@2323 443
 	 *  contiguous chunks of memory and fits therein.
cinap_lenrek@2323 444
 	 */
cinap_lenrek@2323 445
 	for(i=0; i<nelem(conf.mem); i++){
cinap_lenrek@2323 446
 		/* take kernel out of allocatable space */
cinap_lenrek@2323 447
 		if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
cinap_lenrek@2323 448
 			conf.mem[i].base = pa;
cinap_lenrek@2323 449
 
cinap_lenrek@2323 450
 		conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
cinap_lenrek@2323 451
 		conf.npage += conf.mem[i].npage;
cinap_lenrek@2323 452
 	}
cinap_lenrek@2323 453
 
cinap_lenrek@2323 454
 	conf.upages = (conf.npage*80)/100;
cinap_lenrek@2323 455
 	conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
cinap_lenrek@2323 456
 
cinap_lenrek@2323 457
 	/* only one processor */
cinap_lenrek@2323 458
 	conf.nmach = 1;
cinap_lenrek@2323 459
 
cinap_lenrek@2323 460
 	/* set up other configuration parameters */
cinap_lenrek@2323 461
 	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
cinap_lenrek@2323 462
 	if(cpuserver)
cinap_lenrek@2323 463
 		conf.nproc *= 3;
cinap_lenrek@2323 464
 	if(conf.nproc > 2000)
cinap_lenrek@2323 465
 		conf.nproc = 2000;
cinap_lenrek@2323 466
 	conf.nswap = conf.npage*3;
cinap_lenrek@2323 467
 	conf.nswppo = 4096;
cinap_lenrek@2323 468
 	conf.nimage = 200;
cinap_lenrek@2323 469
 
cinap_lenrek@2323 470
 	conf.copymode = 0;		/* copy on write */
cinap_lenrek@2323 471
 
cinap_lenrek@2323 472
 	/*
cinap_lenrek@2323 473
 	 * Guess how much is taken by the large permanent
cinap_lenrek@2323 474
 	 * datastructures. Mntcache and Mntrpc are not accounted for
cinap_lenrek@2323 475
 	 * (probably ~300KB).
cinap_lenrek@2323 476
 	 */
cinap_lenrek@2323 477
 	kpages = conf.npage - conf.upages;
cinap_lenrek@2323 478
 	kpages *= BY2PG;
cinap_lenrek@2323 479
 	kpages -= conf.upages*sizeof(Page)
cinap_lenrek@2323 480
 		+ conf.nproc*sizeof(Proc)
cinap_lenrek@2323 481
 		+ conf.nimage*sizeof(Image)
cinap_lenrek@2323 482
 		+ conf.nswap
cinap_lenrek@2323 483
 		+ conf.nswppo*sizeof(Page);
cinap_lenrek@2323 484
 	mainmem->maxsize = kpages;
cinap_lenrek@2323 485
 	if(!cpuserver)
cinap_lenrek@2323 486
 		/*
cinap_lenrek@2323 487
 		 * give terminals lots of image memory, too; the dynamic
cinap_lenrek@2323 488
 		 * allocation will balance the load properly, hopefully.
cinap_lenrek@2323 489
 		 * be careful with 32-bit overflow.
cinap_lenrek@2323 490
 		 */
cinap_lenrek@2323 491
 		imagmem->maxsize = kpages;
cinap_lenrek@2323 492
 
cinap_lenrek@2323 493
 }
cinap_lenrek@2323 494
 
cinap_lenrek@2323 495
 static void
cinap_lenrek@2323 496
 shutdown(int ispanic)
cinap_lenrek@2323 497
 {
cinap_lenrek@2323 498
 	int ms, once;
cinap_lenrek@2323 499
 
cinap_lenrek@2323 500
 	lock(&active);
cinap_lenrek@2323 501
 	if(ispanic)
cinap_lenrek@2323 502
 		active.ispanic = ispanic;
cinap_lenrek@2323 503
 	else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
cinap_lenrek@2323 504
 		active.ispanic = 0;
cinap_lenrek@2323 505
 	once = active.machs & (1<<m->machno);
cinap_lenrek@2323 506
 	active.machs &= ~(1<<m->machno);
cinap_lenrek@2323 507
 	active.exiting = 1;
cinap_lenrek@2323 508
 	unlock(&active);
cinap_lenrek@2323 509
 
cinap_lenrek@2323 510
 	if(once)
cinap_lenrek@2323 511
 		iprint("cpu%d: exiting\n", m->machno);
cinap_lenrek@2323 512
 	spllo();
cinap_lenrek@2323 513
 	for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
cinap_lenrek@2323 514
 		delay(TK2MS(2));
cinap_lenrek@2323 515
 		if(active.machs == 0 && consactive() == 0)
cinap_lenrek@2323 516
 			break;
cinap_lenrek@2323 517
 	}
cinap_lenrek@2323 518
 	delay(1000);
cinap_lenrek@2323 519
 }
cinap_lenrek@2323 520
 
cinap_lenrek@2323 521
 /*
cinap_lenrek@2323 522
  *  exit kernel either on a panic or user request
cinap_lenrek@2323 523
  */
cinap_lenrek@2323 524
 void
cinap_lenrek@2323 525
 exit(int code)
cinap_lenrek@2323 526
 {
cinap_lenrek@2323 527
 	shutdown(code);
cinap_lenrek@2323 528
 	splfhi();
cinap_lenrek@2323 529
 	archreboot();
cinap_lenrek@2323 530
 }
cinap_lenrek@2323 531
 
cinap_lenrek@2323 532
 /*
cinap_lenrek@2323 533
  * stub for ../omap/devether.c
cinap_lenrek@2323 534
  */
cinap_lenrek@2323 535
 int
cinap_lenrek@2323 536
 isaconfig(char *class, int ctlrno, ISAConf *isa)
cinap_lenrek@2323 537
 {
cinap_lenrek@2323 538
 	USED(ctlrno);
cinap_lenrek@2323 539
 	USED(isa);
cinap_lenrek@2323 540
 	return strcmp(class, "ether") == 0;
cinap_lenrek@2323 541
 }
cinap_lenrek@2323 542
 
cinap_lenrek@2323 543
 /*
cinap_lenrek@2323 544
  * the new kernel is already loaded at address `code'
cinap_lenrek@2323 545
  * of size `size' and entry point `entry'.
cinap_lenrek@2323 546
  */
cinap_lenrek@2323 547
 void
cinap_lenrek@2323 548
 reboot(void *entry, void *code, ulong size)
cinap_lenrek@2323 549
 {
cinap_lenrek@2323 550
 	void (*f)(ulong, ulong, ulong);
cinap_lenrek@2323 551
 
cinap_lenrek@2323 552
 	print("starting reboot...");
cinap_lenrek@2323 553
 	writeconf();
cinap_lenrek@2323 554
 	shutdown(0);
cinap_lenrek@2323 555
 
cinap_lenrek@2323 556
 	/*
cinap_lenrek@2323 557
 	 * should be the only processor running now
cinap_lenrek@2323 558
 	 */
cinap_lenrek@2323 559
 
cinap_lenrek@2323 560
 	print("reboot entry %#lux code %#lux size %ld\n",
cinap_lenrek@2323 561
 		PADDR(entry), PADDR(code), size);
cinap_lenrek@2323 562
 	delay(100);
cinap_lenrek@2323 563
 
cinap_lenrek@2323 564
 	/* turn off buffered serial console */
cinap_lenrek@2323 565
 	serialoq = nil;
cinap_lenrek@2323 566
 	kprintoq = nil;
cinap_lenrek@2323 567
 	screenputs = nil;
cinap_lenrek@2323 568
 
cinap_lenrek@2323 569
 	/* shutdown devices */
cinap_lenrek@2323 570
 	chandevshutdown();
cinap_lenrek@2323 571
 
cinap_lenrek@2323 572
 	/* stop the clock (and watchdog if any) */
cinap_lenrek@2323 573
 	clockshutdown();
cinap_lenrek@2323 574
 
cinap_lenrek@2323 575
 	splfhi();
cinap_lenrek@2323 576
 	intrsoff();
cinap_lenrek@2323 577
 
cinap_lenrek@2323 578
 	/* setup reboot trampoline function */
cinap_lenrek@2323 579
 	f = (void*)REBOOTADDR;
cinap_lenrek@2323 580
 	memmove(f, rebootcode, sizeof(rebootcode));
cinap_lenrek@2323 581
 	cacheuwbinv();
cinap_lenrek@2323 582
 
cinap_lenrek@2323 583
 	/* off we go - never to return */
cinap_lenrek@2323 584
 	(*f)(PADDR(entry), PADDR(code), size);
cinap_lenrek@2323 585
 
cinap_lenrek@2323 586
 	iprint("loaded kernel returned!\n");
cinap_lenrek@2323 587
 	delay(1000);
cinap_lenrek@2323 588
 	archreboot();
cinap_lenrek@2323 589
 }
cinap_lenrek@2323 590
 
cinap_lenrek@2323 591
 int
cinap_lenrek@2323 592
 cmpswap(long *addr, long old, long new)
cinap_lenrek@2323 593
 {
cinap_lenrek@2323 594
 	return cas32(addr, old, new);
cinap_lenrek@2323 595
 }