changelog shortlog tags branches changeset files file revisions raw help

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

changeset 7234: fc141b91ed8a
parent: 66132ebbe687
child: 889b634159e5
author: cinap_lenrek@felloff.net
date: Mon, 13 May 2019 19:12:41 +0200
permissions: -rw-r--r--
description: bcm, bcm64: preserve memsize across reboots, avoid trashing atags while parsing cmdline

we override atag memory on reboot, so preserve
the memsize learned from atag as *maxmem plan9
variable. the global memsize variable is not
needed anymore.

avoid trashing the following atag when zero
terminating the cmdline string.

zero memory after plan9.ini variables.
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@6832 7
 #include "io.h"
cinap_lenrek@2323 8
 
cinap_lenrek@2323 9
 #include "init.h"
cinap_lenrek@2323 10
 #include <pool.h>
cinap_lenrek@2323 11
 
cinap_lenrek@2323 12
 #include "reboot.h"
cinap_lenrek@2323 13
 
cinap_lenrek@2323 14
 /* Firmware compatibility */
cinap_lenrek@2323 15
 #define	Minfirmrev	326770
cinap_lenrek@2323 16
 #define	Minfirmdate	"22 Jul 2012"
cinap_lenrek@2323 17
 
cinap_lenrek@2323 18
 uintptr kseg0 = KZERO;
cinap_lenrek@2323 19
 Mach*	machaddr[MAXMACH];
cinap_lenrek@2323 20
 Conf	conf;
cinap_lenrek@2323 21
 
cinap_lenrek@2323 22
 void
cinap_lenrek@2323 23
 machinit(void)
cinap_lenrek@2323 24
 {
cinap_lenrek@6832 25
 	Mach *m0;
cinap_lenrek@6832 26
 
cinap_lenrek@6832 27
 	m->ticks = 1;
cinap_lenrek@6832 28
 	m->perf.period = 1;
cinap_lenrek@6832 29
 	m0 = MACHP(0);
cinap_lenrek@6832 30
 	if (m->machno != 0) {
cinap_lenrek@6832 31
 		/* synchronise with cpu 0 */
cinap_lenrek@6832 32
 		m->ticks = m0->ticks;
cinap_lenrek@6832 33
 	}
cinap_lenrek@6832 34
 }
cinap_lenrek@6832 35
 
cinap_lenrek@6832 36
 void
cinap_lenrek@6832 37
 mach0init(void)
cinap_lenrek@6832 38
 {
cinap_lenrek@6832 39
 	m->mmul1 = (PTE*)L1;
cinap_lenrek@2323 40
 	m->machno = 0;
cinap_lenrek@2323 41
 	machaddr[m->machno] = m;
cinap_lenrek@2323 42
 
cinap_lenrek@2323 43
 	m->ticks = 1;
cinap_lenrek@2323 44
 	m->perf.period = 1;
cinap_lenrek@2323 45
 
cinap_lenrek@5034 46
 	active.machs[0] = 1;
cinap_lenrek@2323 47
 	active.exiting = 0;
cinap_lenrek@2323 48
 
cinap_lenrek@2323 49
 	up = nil;
cinap_lenrek@2323 50
 }
cinap_lenrek@2323 51
 
cinap_lenrek@2323 52
 static void
cinap_lenrek@6832 53
 launchinit(void)
cinap_lenrek@6832 54
 {
cinap_lenrek@6832 55
 	int mach;
cinap_lenrek@6832 56
 	Mach *mm;
cinap_lenrek@6832 57
 	PTE *l1;
cinap_lenrek@6832 58
 
cinap_lenrek@6832 59
 	for(mach = 1; mach < conf.nmach; mach++){
cinap_lenrek@6832 60
 		machaddr[mach] = mm = mallocalign(MACHSIZE, MACHSIZE, 0, 0);
cinap_lenrek@6832 61
 		l1 = mallocalign(L1SIZE, L1SIZE, 0, 0);
cinap_lenrek@6832 62
 		if(mm == nil || l1 == nil)
cinap_lenrek@6832 63
 			panic("launchinit");
cinap_lenrek@6832 64
 		memset(mm, 0, MACHSIZE);
cinap_lenrek@6832 65
 		mm->machno = mach;
cinap_lenrek@6832 66
 
cinap_lenrek@6832 67
 		memmove(l1, m->mmul1, L1SIZE);  /* clone cpu0's l1 table */
cinap_lenrek@6832 68
 		cachedwbse(l1, L1SIZE);
cinap_lenrek@6832 69
 		mm->mmul1 = l1;
cinap_lenrek@6832 70
 		cachedwbse(mm, MACHSIZE);
cinap_lenrek@6832 71
 
cinap_lenrek@6832 72
 	}
cinap_lenrek@6832 73
 	cachedwbse(machaddr, sizeof machaddr);
cinap_lenrek@6832 74
 	if((mach = startcpus(conf.nmach)) < conf.nmach)
cinap_lenrek@6855 75
 		print("only %d cpu%s started\n", mach, mach == 1? "" : "s");
cinap_lenrek@6832 76
 }
cinap_lenrek@6832 77
 
cinap_lenrek@2323 78
 void
cinap_lenrek@2323 79
 main(void)
cinap_lenrek@2323 80
 {
cinap_lenrek@2323 81
 	extern char edata[], end[];
cinap_lenrek@6832 82
 	uint fw, board;
cinap_lenrek@2323 83
 
cinap_lenrek@2323 84
 	m = (Mach*)MACHADDR;
cinap_lenrek@2323 85
 	memset(edata, 0, end - edata);	/* clear bss */
cinap_lenrek@6832 86
 	mach0init();
cinap_lenrek@2323 87
 	quotefmtinstall();
cinap_lenrek@7159 88
 	bootargsinit();
cinap_lenrek@2323 89
 	confinit();		/* figures out amount of memory */
cinap_lenrek@2323 90
 	xinit();
cinap_lenrek@2323 91
 	uartconsinit();
cinap_lenrek@2323 92
 	screeninit();
cinap_lenrek@2323 93
 
cinap_lenrek@2323 94
 	print("\nPlan 9 from Bell Labs\n");
cinap_lenrek@6832 95
 	board = getboardrev();
cinap_lenrek@6832 96
 	fw = getfirmware();
cinap_lenrek@6832 97
 	print("board rev: %#ux firmware rev: %d\n", board, fw);
cinap_lenrek@6832 98
 	if(fw < Minfirmrev){
cinap_lenrek@6832 99
 		print("Sorry, firmware (start*.elf) must be at least rev %d"
cinap_lenrek@6832 100
 		      " or newer than %s\n", Minfirmrev, Minfirmdate);
cinap_lenrek@2323 101
 		for(;;)
cinap_lenrek@2323 102
 			;
cinap_lenrek@2323 103
 	}
cinap_lenrek@6832 104
 	/* set clock rate to arm_freq from config.txt (default pi1:700Mhz pi2:900MHz) */
cinap_lenrek@6832 105
 	setclkrate(ClkArm, 0);
cinap_lenrek@2323 106
 	trapinit();
cinap_lenrek@2323 107
 	clockinit();
cinap_lenrek@2323 108
 	printinit();
cinap_lenrek@2323 109
 	timersinit();
cinap_lenrek@2323 110
 	cpuidprint();
cinap_lenrek@2323 111
 	archreset();
cinap_lenrek@6832 112
 	vgpinit();
cinap_lenrek@2323 113
 
cinap_lenrek@2323 114
 	procinit0();
cinap_lenrek@2323 115
 	initseg();
cinap_lenrek@2323 116
 	links();
cinap_lenrek@2323 117
 	chandevreset();			/* most devices are discovered here */
cinap_lenrek@2323 118
 	pageinit();
cinap_lenrek@2323 119
 	userinit();
cinap_lenrek@6832 120
 	launchinit();
cinap_lenrek@6851 121
 	mmuinit1(0);
cinap_lenrek@2323 122
 	schedinit();
cinap_lenrek@2323 123
 	assert(0);			/* shouldn't have returned */
cinap_lenrek@2323 124
 }
cinap_lenrek@2323 125
 
cinap_lenrek@2323 126
 /*
cinap_lenrek@2323 127
  *  starting place for first process
cinap_lenrek@2323 128
  */
cinap_lenrek@2323 129
 void
cinap_lenrek@2323 130
 init0(void)
cinap_lenrek@2323 131
 {
cinap_lenrek@7159 132
 	char buf[2*KNAMELEN], **sp;
cinap_lenrek@2323 133
 
cinap_lenrek@2323 134
 	up->nerrlab = 0;
cinap_lenrek@2323 135
 	coherence();
cinap_lenrek@2323 136
 	spllo();
cinap_lenrek@2323 137
 
cinap_lenrek@2323 138
 	/*
cinap_lenrek@2323 139
 	 * These are o.k. because rootinit is null.
cinap_lenrek@2323 140
 	 * Then early kproc's will have a root and dot.
cinap_lenrek@2323 141
 	 */
cinap_lenrek@2323 142
 	up->slash = namec("#/", Atodir, 0, 0);
cinap_lenrek@2323 143
 	pathclose(up->slash->path);
cinap_lenrek@2323 144
 	up->slash->path = newpath("/");
cinap_lenrek@2323 145
 	up->dot = cclone(up->slash);
cinap_lenrek@2323 146
 
cinap_lenrek@2323 147
 	chandevinit();
cinap_lenrek@2323 148
 
cinap_lenrek@2323 149
 	if(!waserror()){
cinap_lenrek@2323 150
 		snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
cinap_lenrek@2323 151
 		ksetenv("terminal", buf, 0);
cinap_lenrek@2323 152
 		ksetenv("cputype", "arm", 0);
cinap_lenrek@2323 153
 		if(cpuserver)
cinap_lenrek@2323 154
 			ksetenv("service", "cpu", 0);
cinap_lenrek@2323 155
 		else
cinap_lenrek@2323 156
 			ksetenv("service", "terminal", 0);
cinap_lenrek@2323 157
 		snprint(buf, sizeof(buf), "-a %s", getethermac());
cinap_lenrek@2323 158
 		ksetenv("etherargs", buf, 0);
cinap_lenrek@2323 159
 
cinap_lenrek@2323 160
 		/* convert plan9.ini variables to #e and #ec */
cinap_lenrek@7159 161
 		setconfenv();
cinap_lenrek@2323 162
 		poperror();
cinap_lenrek@2323 163
 	}
cinap_lenrek@2323 164
 	kproc("alarm", alarmkproc, 0);
cinap_lenrek@2323 165
 
cinap_lenrek@7159 166
 	sp = (char**)(USTKTOP - sizeof(Tos) - 8 - sizeof(sp[0])*4);
cinap_lenrek@7159 167
 	sp[3] = sp[2] = sp[1] = nil;
cinap_lenrek@7159 168
 	strcpy(sp[0] = (char*)&sp[4], "boot");
cinap_lenrek@2323 169
 
cinap_lenrek@7159 170
 	touser((uintptr)sp);
cinap_lenrek@7159 171
 	assert(0);			/* shouldn't have returned */
cinap_lenrek@2323 172
 }
cinap_lenrek@2323 173
 
cinap_lenrek@2323 174
 /*
cinap_lenrek@2323 175
  *  create the first process
cinap_lenrek@2323 176
  */
cinap_lenrek@2323 177
 void
cinap_lenrek@2323 178
 userinit(void)
cinap_lenrek@2323 179
 {
cinap_lenrek@2323 180
 	Proc *p;
cinap_lenrek@2323 181
 	Segment *s;
cinap_lenrek@2323 182
 	KMap *k;
cinap_lenrek@2323 183
 	Page *pg;
cinap_lenrek@2323 184
 
cinap_lenrek@2323 185
 	/* no processes yet */
cinap_lenrek@2323 186
 	up = nil;
cinap_lenrek@2323 187
 
cinap_lenrek@2323 188
 	p = newproc();
cinap_lenrek@2323 189
 	p->pgrp = newpgrp();
cinap_lenrek@2323 190
 	p->egrp = smalloc(sizeof(Egrp));
cinap_lenrek@2323 191
 	p->egrp->ref = 1;
cinap_lenrek@2323 192
 	p->fgrp = dupfgrp(nil);
cinap_lenrek@2323 193
 	p->rgrp = newrgrp();
cinap_lenrek@2323 194
 	p->procmode = 0640;
cinap_lenrek@2323 195
 
cinap_lenrek@2323 196
 	kstrdup(&eve, "");
cinap_lenrek@2323 197
 	kstrdup(&p->text, "*init*");
cinap_lenrek@2323 198
 	kstrdup(&p->user, eve);
cinap_lenrek@2323 199
 
cinap_lenrek@2323 200
 	/*
cinap_lenrek@2323 201
 	 * Kernel Stack
cinap_lenrek@2323 202
 	 */
cinap_lenrek@7155 203
 	p->sched.pc = (uintptr)init0;
cinap_lenrek@7155 204
 	p->sched.sp = (uintptr)p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr);
cinap_lenrek@2323 205
 	p->sched.sp = STACKALIGN(p->sched.sp);
cinap_lenrek@2323 206
 
cinap_lenrek@2323 207
 	/*
cinap_lenrek@2323 208
 	 * User Stack
cinap_lenrek@2323 209
 	 *
cinap_lenrek@2323 210
 	 * Technically, newpage can't be called here because it
cinap_lenrek@2323 211
 	 * should only be called when in a user context as it may
cinap_lenrek@2323 212
 	 * try to sleep if there are no pages available, but that
cinap_lenrek@2323 213
 	 * shouldn't be the case here.
cinap_lenrek@2323 214
 	 */
cinap_lenrek@2323 215
 	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
cinap_lenrek@2323 216
 	s->flushme++;
cinap_lenrek@2323 217
 	p->seg[SSEG] = s;
cinap_lenrek@2323 218
 	pg = newpage(1, 0, USTKTOP-BY2PG);
cinap_lenrek@2323 219
 	segpage(s, pg);
cinap_lenrek@2323 220
 	k = kmap(pg);
cinap_lenrek@7159 221
 	memset((void*)VA(k), 0, BY2PG);
cinap_lenrek@2323 222
 	kunmap(k);
cinap_lenrek@2323 223
 
cinap_lenrek@2323 224
 	/*
cinap_lenrek@2323 225
 	 * Text
cinap_lenrek@2323 226
 	 */
cinap_lenrek@2323 227
 	s = newseg(SG_TEXT, UTZERO, 1);
cinap_lenrek@2323 228
 	p->seg[TSEG] = s;
cinap_lenrek@2323 229
 	pg = newpage(1, 0, UTZERO);
cinap_lenrek@4250 230
 	pg->txtflush = ~0;
cinap_lenrek@2323 231
 	segpage(s, pg);
cinap_lenrek@2323 232
 	k = kmap(s->map[0]->pages[0]);
cinap_lenrek@7155 233
 	memmove((void*)VA(k), initcode, sizeof initcode);
cinap_lenrek@2323 234
 	kunmap(k);
cinap_lenrek@2323 235
 
cinap_lenrek@2323 236
 	ready(p);
cinap_lenrek@2323 237
 }
cinap_lenrek@2323 238
 
cinap_lenrek@2323 239
 void
cinap_lenrek@2323 240
 confinit(void)
cinap_lenrek@2323 241
 {
stanley@3401 242
 	int i, userpcnt;
cinap_lenrek@7234 243
 	ulong kpages, memsize = 0;
cinap_lenrek@2323 244
 	uintptr pa;
cinap_lenrek@2323 245
 	char *p;
cinap_lenrek@2323 246
 
cinap_lenrek@3448 247
 	if(p = getconf("service")){
cinap_lenrek@3448 248
 		if(strcmp(p, "cpu") == 0)
cinap_lenrek@3448 249
 			cpuserver = 1;
cinap_lenrek@3448 250
 		else if(strcmp(p,"terminal") == 0)
cinap_lenrek@3448 251
 			cpuserver = 0;
cinap_lenrek@3448 252
 	}
cinap_lenrek@3448 253
 
stanley@3401 254
 	if(p = getconf("*kernelpercent"))
stanley@3401 255
 		userpcnt = 100 - strtol(p, 0, 0);
stanley@3401 256
 	else
stanley@3401 257
 		userpcnt = 0;
stanley@3401 258
 
cinap_lenrek@7234 259
 	if(p = getconf("*maxmem"))
cinap_lenrek@2323 260
 		memsize = strtoul(p, 0, 0) - PHYSDRAM;
cinap_lenrek@7234 261
 	if (memsize < 16*MB)		/* sanity */
cinap_lenrek@7234 262
 		memsize = 16*MB;
cinap_lenrek@2323 263
 	getramsize(&conf.mem[0]);
cinap_lenrek@2323 264
 	if(conf.mem[0].limit == 0){
cinap_lenrek@2323 265
 		conf.mem[0].base = PHYSDRAM;
cinap_lenrek@2323 266
 		conf.mem[0].limit = PHYSDRAM + memsize;
cinap_lenrek@2323 267
 	}else if(p != nil)
cinap_lenrek@2323 268
 		conf.mem[0].limit = conf.mem[0].base + memsize;
cinap_lenrek@2323 269
 
cinap_lenrek@2323 270
 	conf.npage = 0;
cinap_lenrek@7155 271
 	pa = PADDR(PGROUND((uintptr)end));
cinap_lenrek@2323 272
 
cinap_lenrek@2323 273
 	/*
cinap_lenrek@2323 274
 	 *  we assume that the kernel is at the beginning of one of the
cinap_lenrek@2323 275
 	 *  contiguous chunks of memory and fits therein.
cinap_lenrek@2323 276
 	 */
cinap_lenrek@2323 277
 	for(i=0; i<nelem(conf.mem); i++){
cinap_lenrek@2323 278
 		/* take kernel out of allocatable space */
cinap_lenrek@2323 279
 		if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
cinap_lenrek@2323 280
 			conf.mem[i].base = pa;
cinap_lenrek@2323 281
 
cinap_lenrek@2323 282
 		conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
cinap_lenrek@2323 283
 		conf.npage += conf.mem[i].npage;
cinap_lenrek@2323 284
 	}
cinap_lenrek@2323 285
 
stanley@3401 286
 	if(userpcnt < 10)
stanley@3401 287
 		userpcnt = 60 + cpuserver*10;
stanley@3401 288
 	kpages = conf.npage - (conf.npage*userpcnt)/100;
stanley@3401 289
 
stanley@3401 290
 	/*
stanley@3401 291
 	 * can't go past the end of virtual memory
stanley@3401 292
 	 * (ulong)-KZERO is 2^32 - KZERO
stanley@3401 293
 	 */
stanley@3401 294
 	if(kpages > ((ulong)-KZERO)/BY2PG)
stanley@3401 295
 		kpages = ((ulong)-KZERO)/BY2PG;
stanley@3401 296
 
stanley@3401 297
 	conf.upages = conf.npage - kpages;
stanley@3401 298
 	conf.ialloc = (kpages/2)*BY2PG;
cinap_lenrek@2323 299
 
cinap_lenrek@6832 300
 	conf.nmach = getncpus();
cinap_lenrek@2323 301
 
cinap_lenrek@2323 302
 	/* set up other configuration parameters */
cinap_lenrek@2323 303
 	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
cinap_lenrek@2323 304
 	if(cpuserver)
cinap_lenrek@2323 305
 		conf.nproc *= 3;
cinap_lenrek@2323 306
 	if(conf.nproc > 2000)
cinap_lenrek@2323 307
 		conf.nproc = 2000;
cinap_lenrek@2323 308
 	conf.nswap = conf.npage*3;
cinap_lenrek@2323 309
 	conf.nswppo = 4096;
cinap_lenrek@2323 310
 	conf.nimage = 200;
cinap_lenrek@2323 311
 
cinap_lenrek@6832 312
 	conf.copymode = conf.nmach > 1;
cinap_lenrek@2323 313
 
cinap_lenrek@2323 314
 	/*
cinap_lenrek@2323 315
 	 * Guess how much is taken by the large permanent
cinap_lenrek@4074 316
 	 * datastructures. Mntcache and Mntrpc are not accounted for.
cinap_lenrek@2323 317
 	 */
cinap_lenrek@2323 318
 	kpages = conf.npage - conf.upages;
cinap_lenrek@2323 319
 	kpages *= BY2PG;
cinap_lenrek@2323 320
 	kpages -= conf.upages*sizeof(Page)
cinap_lenrek@2323 321
 		+ conf.nproc*sizeof(Proc)
cinap_lenrek@2323 322
 		+ conf.nimage*sizeof(Image)
cinap_lenrek@2323 323
 		+ conf.nswap
stanley@3401 324
 		+ conf.nswppo*sizeof(Page*);
cinap_lenrek@2323 325
 	mainmem->maxsize = kpages;
cinap_lenrek@2323 326
 	if(!cpuserver)
cinap_lenrek@2323 327
 		/*
cinap_lenrek@2323 328
 		 * give terminals lots of image memory, too; the dynamic
cinap_lenrek@2323 329
 		 * allocation will balance the load properly, hopefully.
cinap_lenrek@2323 330
 		 * be careful with 32-bit overflow.
cinap_lenrek@2323 331
 		 */
cinap_lenrek@2323 332
 		imagmem->maxsize = kpages;
cinap_lenrek@2323 333
 
cinap_lenrek@2323 334
 }
cinap_lenrek@2323 335
 
cinap_lenrek@6851 336
 static void
cinap_lenrek@6855 337
 rebootjump(void *entry, void *code, ulong size)
cinap_lenrek@6851 338
 {
cinap_lenrek@6855 339
 	void (*f)(void*, void*, ulong);
cinap_lenrek@6851 340
 
cinap_lenrek@6851 341
 	intrsoff();
cinap_lenrek@6851 342
 	intrcpushutdown();
cinap_lenrek@6851 343
 
cinap_lenrek@6851 344
 	/* redo identity map */
cinap_lenrek@6851 345
 	mmuinit1(1);
cinap_lenrek@6851 346
 
cinap_lenrek@6855 347
 	/* setup reboot trampoline function */
cinap_lenrek@6855 348
 	f = (void*)REBOOTADDR;
cinap_lenrek@6855 349
 	memmove(f, rebootcode, sizeof(rebootcode));
cinap_lenrek@6851 350
 	cacheuwbinv();
cinap_lenrek@6851 351
 
cinap_lenrek@6851 352
 	(*f)(entry, code, size);
cinap_lenrek@6851 353
 
cinap_lenrek@6851 354
 	for(;;);
cinap_lenrek@6851 355
 }
cinap_lenrek@6851 356
 
cinap_lenrek@2323 357
 /*
cinap_lenrek@2323 358
  *  exit kernel either on a panic or user request
cinap_lenrek@2323 359
  */
cinap_lenrek@2323 360
 void
cinap_lenrek@4993 361
 exit(int)
cinap_lenrek@2323 362
 {
cinap_lenrek@4993 363
 	cpushutdown();
cinap_lenrek@2323 364
 	splfhi();
cinap_lenrek@6855 365
 	if(m->machno == 0)
cinap_lenrek@6855 366
 		archreboot();
cinap_lenrek@6855 367
 	rebootjump(0, 0, 0);
cinap_lenrek@2323 368
 }
cinap_lenrek@2323 369
 
cinap_lenrek@2323 370
 /*
cinap_lenrek@2323 371
  * stub for ../omap/devether.c
cinap_lenrek@2323 372
  */
cinap_lenrek@2323 373
 int
cinap_lenrek@6832 374
 isaconfig(char *, int, ISAConf *)
cinap_lenrek@2323 375
 {
cinap_lenrek@6832 376
 	return 0;
cinap_lenrek@2323 377
 }
cinap_lenrek@2323 378
 
cinap_lenrek@2323 379
 /*
cinap_lenrek@2323 380
  * the new kernel is already loaded at address `code'
cinap_lenrek@2323 381
  * of size `size' and entry point `entry'.
cinap_lenrek@2323 382
  */
cinap_lenrek@2323 383
 void
cinap_lenrek@2323 384
 reboot(void *entry, void *code, ulong size)
cinap_lenrek@2323 385
 {
cinap_lenrek@2323 386
 	writeconf();
cinap_lenrek@6855 387
 	while(m->machno != 0){
cinap_lenrek@6832 388
 		procwired(up, 0);
cinap_lenrek@6832 389
 		sched();
cinap_lenrek@6832 390
 	}
cinap_lenrek@6832 391
 
cinap_lenrek@4993 392
 	cpushutdown();
cinap_lenrek@6855 393
 	delay(2000);
cinap_lenrek@6832 394
 
cinap_lenrek@6832 395
 	splfhi();
cinap_lenrek@2323 396
 
cinap_lenrek@2323 397
 	/* turn off buffered serial console */
cinap_lenrek@2323 398
 	serialoq = nil;
cinap_lenrek@2323 399
 
cinap_lenrek@2323 400
 	/* shutdown devices */
cinap_lenrek@2323 401
 	chandevshutdown();
cinap_lenrek@2323 402
 
cinap_lenrek@2323 403
 	/* stop the clock (and watchdog if any) */
cinap_lenrek@2323 404
 	clockshutdown();
cinap_lenrek@6851 405
 	wdogoff();
cinap_lenrek@2323 406
 
cinap_lenrek@2323 407
 	/* off we go - never to return */
cinap_lenrek@6855 408
 	rebootjump(entry, code, size);
cinap_lenrek@2323 409
 }
cinap_lenrek@2323 410
 
aiju@6012 411
 void
aiju@6012 412
 setupwatchpts(Proc *, Watchpt *, int n)
aiju@6012 413
 {
aiju@6012 414
 	if(n > 0)
aiju@6012 415
 		error("no watchpoints");
aiju@6012 416
 }