changelog shortlog tags branches changeset files file revisions raw help

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

changeset 7235: b1dc95374307
parent: 19de954d8073
child: 889b634159e5
author: cinap_lenrek@felloff.net
date: Mon, 13 May 2019 19:20:21 +0200
permissions: -rw-r--r--
description: bcm64: implement reboot support
cinap_lenrek@7199 1
 #include "u.h"
cinap_lenrek@7199 2
 #include "tos.h"
cinap_lenrek@7199 3
 #include "../port/lib.h"
cinap_lenrek@7199 4
 #include "mem.h"
cinap_lenrek@7199 5
 #include "dat.h"
cinap_lenrek@7199 6
 #include "fns.h"
cinap_lenrek@7199 7
 #include "../port/error.h"
cinap_lenrek@7199 8
 #include "io.h"
cinap_lenrek@7199 9
 #include "init.h"
cinap_lenrek@7199 10
 #include "sysreg.h"
cinap_lenrek@7235 11
 #include "reboot.h"
cinap_lenrek@7199 12
 
cinap_lenrek@7199 13
 #include <pool.h>
cinap_lenrek@7199 14
 #include <libsec.h>
cinap_lenrek@7199 15
 
cinap_lenrek@7199 16
 Conf conf;
cinap_lenrek@7199 17
 
cinap_lenrek@7199 18
 /*
cinap_lenrek@7199 19
  *  starting place for first process
cinap_lenrek@7199 20
  */
cinap_lenrek@7199 21
 void
cinap_lenrek@7199 22
 init0(void)
cinap_lenrek@7199 23
 {
cinap_lenrek@7199 24
 	char buf[2*KNAMELEN], **sp;
cinap_lenrek@7199 25
 
cinap_lenrek@7199 26
 	up->nerrlab = 0;
cinap_lenrek@7199 27
 	spllo();
cinap_lenrek@7199 28
 
cinap_lenrek@7199 29
 	/*
cinap_lenrek@7199 30
 	 * These are o.k. because rootinit is null.
cinap_lenrek@7199 31
 	 * Then early kproc's will have a root and dot.
cinap_lenrek@7199 32
 	 */
cinap_lenrek@7199 33
 	up->slash = namec("#/", Atodir, 0, 0);
cinap_lenrek@7199 34
 	pathclose(up->slash->path);
cinap_lenrek@7199 35
 	up->slash->path = newpath("/");
cinap_lenrek@7199 36
 	up->dot = cclone(up->slash);
cinap_lenrek@7199 37
 	chandevinit();
cinap_lenrek@7199 38
 
cinap_lenrek@7199 39
 	if(!waserror()){
cinap_lenrek@7199 40
 		snprint(buf, sizeof(buf), "%s %s", "ARM64", conffile);
cinap_lenrek@7199 41
 		ksetenv("terminal", buf, 0);
cinap_lenrek@7199 42
 		ksetenv("cputype", "arm64", 0);
cinap_lenrek@7199 43
 		if(cpuserver)
cinap_lenrek@7199 44
 			ksetenv("service", "cpu", 0);
cinap_lenrek@7199 45
 		else
cinap_lenrek@7199 46
 			ksetenv("service", "terminal", 0);
cinap_lenrek@7199 47
 		snprint(buf, sizeof(buf), "-a %s", getethermac());
cinap_lenrek@7199 48
 		ksetenv("etherargs", buf, 0);
cinap_lenrek@7199 49
 
cinap_lenrek@7199 50
 		/* convert plan9.ini variables to #e and #ec */
cinap_lenrek@7199 51
 		setconfenv();
cinap_lenrek@7199 52
 		poperror();
cinap_lenrek@7199 53
 	}
cinap_lenrek@7199 54
 	kproc("alarm", alarmkproc, 0);
cinap_lenrek@7199 55
 
cinap_lenrek@7199 56
 	sp = (char**)(USTKTOP-sizeof(Tos) - 8 - sizeof(sp[0])*4);
cinap_lenrek@7199 57
 	sp[3] = sp[2] = sp[1] = nil;
cinap_lenrek@7199 58
 	strcpy(sp[1] = (char*)&sp[4], "boot");
cinap_lenrek@7199 59
 	sp[0] = (void*)&sp[1];
cinap_lenrek@7199 60
 
cinap_lenrek@7199 61
 	touser((uintptr)sp);
cinap_lenrek@7199 62
 
cinap_lenrek@7199 63
 	assert(0);			/* shouldn't have returned */
cinap_lenrek@7199 64
 }
cinap_lenrek@7199 65
 
cinap_lenrek@7199 66
 /*
cinap_lenrek@7199 67
  *  create the first process
cinap_lenrek@7199 68
  */
cinap_lenrek@7199 69
 void
cinap_lenrek@7199 70
 userinit(void)
cinap_lenrek@7199 71
 {
cinap_lenrek@7199 72
 	Proc *p;
cinap_lenrek@7199 73
 	Segment *s;
cinap_lenrek@7199 74
 	KMap *k;
cinap_lenrek@7199 75
 	Page *pg;
cinap_lenrek@7199 76
 
cinap_lenrek@7199 77
 	/* no processes yet */
cinap_lenrek@7199 78
 	up = nil;
cinap_lenrek@7199 79
 
cinap_lenrek@7199 80
 	p = newproc();
cinap_lenrek@7199 81
 	p->pgrp = newpgrp();
cinap_lenrek@7199 82
 	p->egrp = smalloc(sizeof(Egrp));
cinap_lenrek@7199 83
 	p->egrp->ref = 1;
cinap_lenrek@7199 84
 	p->fgrp = dupfgrp(nil);
cinap_lenrek@7199 85
 	p->rgrp = newrgrp();
cinap_lenrek@7199 86
 	p->procmode = 0640;
cinap_lenrek@7199 87
 
cinap_lenrek@7199 88
 	kstrdup(&eve, "");
cinap_lenrek@7199 89
 	kstrdup(&p->text, "*init*");
cinap_lenrek@7199 90
 	kstrdup(&p->user, eve);
cinap_lenrek@7199 91
 
cinap_lenrek@7199 92
 	/*
cinap_lenrek@7199 93
 	 * Kernel Stack
cinap_lenrek@7199 94
 	 */
cinap_lenrek@7199 95
 	p->sched.pc = (uintptr)init0;
cinap_lenrek@7199 96
 	p->sched.sp = (uintptr)p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr);
cinap_lenrek@7199 97
 	p->sched.sp = STACKALIGN(p->sched.sp);
cinap_lenrek@7199 98
 	*(void**)p->sched.sp = kproc; // fake
cinap_lenrek@7199 99
 
cinap_lenrek@7199 100
 	/*
cinap_lenrek@7199 101
 	 * User Stack
cinap_lenrek@7199 102
 	 *
cinap_lenrek@7199 103
 	 * Technically, newpage can't be called here because it
cinap_lenrek@7199 104
 	 * should only be called when in a user context as it may
cinap_lenrek@7199 105
 	 * try to sleep if there are no pages available, but that
cinap_lenrek@7199 106
 	 * shouldn't be the case here.
cinap_lenrek@7199 107
 	 */
cinap_lenrek@7199 108
 	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
cinap_lenrek@7199 109
 	s->flushme++;
cinap_lenrek@7199 110
 	p->seg[SSEG] = s;
cinap_lenrek@7199 111
 	pg = newpage(1, 0, USTKTOP-BY2PG);
cinap_lenrek@7199 112
 	segpage(s, pg);
cinap_lenrek@7199 113
 	k = kmap(pg);
cinap_lenrek@7199 114
 	memset((void*)VA(k), 0, BY2PG);
cinap_lenrek@7199 115
 	kunmap(k);
cinap_lenrek@7199 116
 
cinap_lenrek@7199 117
 	/*
cinap_lenrek@7199 118
 	 * Text
cinap_lenrek@7199 119
 	 */
cinap_lenrek@7199 120
 	s = newseg(SG_TEXT, UTZERO, 1);
cinap_lenrek@7199 121
 	p->seg[TSEG] = s;
cinap_lenrek@7199 122
 	pg = newpage(1, 0, UTZERO);
cinap_lenrek@7199 123
 	pg->txtflush = ~0;
cinap_lenrek@7199 124
 	segpage(s, pg);
cinap_lenrek@7235 125
 	k = kmap(pg);
cinap_lenrek@7199 126
 	memmove((void*)VA(k), initcode, sizeof initcode);
cinap_lenrek@7199 127
 	kunmap(k);
cinap_lenrek@7199 128
 
cinap_lenrek@7199 129
 	ready(p);
cinap_lenrek@7199 130
 }
cinap_lenrek@7199 131
 
cinap_lenrek@7199 132
 void
cinap_lenrek@7199 133
 confinit(void)
cinap_lenrek@7199 134
 {
cinap_lenrek@7199 135
 	int i, userpcnt;
cinap_lenrek@7235 136
 	ulong kpages, memsize = 0;
cinap_lenrek@7199 137
 	uintptr pa;
cinap_lenrek@7199 138
 	char *p;
cinap_lenrek@7199 139
 
cinap_lenrek@7199 140
 	if(p = getconf("service")){
cinap_lenrek@7199 141
 		if(strcmp(p, "cpu") == 0)
cinap_lenrek@7199 142
 			cpuserver = 1;
cinap_lenrek@7199 143
 		else if(strcmp(p,"terminal") == 0)
cinap_lenrek@7199 144
 			cpuserver = 0;
cinap_lenrek@7199 145
 	}
cinap_lenrek@7199 146
 
cinap_lenrek@7199 147
 	if(p = getconf("*kernelpercent"))
cinap_lenrek@7199 148
 		userpcnt = 100 - strtol(p, 0, 0);
cinap_lenrek@7199 149
 	else
cinap_lenrek@7199 150
 		userpcnt = 0;
cinap_lenrek@7199 151
 
cinap_lenrek@7235 152
 	if(p = getconf("*maxmem"))
cinap_lenrek@7199 153
 		memsize = strtoul(p, 0, 0) - PHYSDRAM;
cinap_lenrek@7235 154
 	if (memsize < 16*MB)		/* sanity */
cinap_lenrek@7235 155
 		memsize = 16*MB;
cinap_lenrek@7199 156
 	getramsize(&conf.mem[0]);
cinap_lenrek@7199 157
 	if(conf.mem[0].limit == 0){
cinap_lenrek@7199 158
 		conf.mem[0].base = PHYSDRAM;
cinap_lenrek@7199 159
 		conf.mem[0].limit = PHYSDRAM + memsize;
cinap_lenrek@7199 160
 	}else if(p != nil)
cinap_lenrek@7199 161
 		conf.mem[0].limit = conf.mem[0].base + memsize;
cinap_lenrek@7199 162
 
cinap_lenrek@7199 163
 	conf.npage = 0;
cinap_lenrek@7199 164
 	pa = PADDR(PGROUND((uintptr)end));
cinap_lenrek@7199 165
 
cinap_lenrek@7199 166
 	/*
cinap_lenrek@7199 167
 	 *  we assume that the kernel is at the beginning of one of the
cinap_lenrek@7199 168
 	 *  contiguous chunks of memory and fits therein.
cinap_lenrek@7199 169
 	 */
cinap_lenrek@7199 170
 	for(i=0; i<nelem(conf.mem); i++){
cinap_lenrek@7199 171
 		/* take kernel out of allocatable space */
cinap_lenrek@7199 172
 		if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
cinap_lenrek@7199 173
 			conf.mem[i].base = pa;
cinap_lenrek@7199 174
 
cinap_lenrek@7199 175
 		conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
cinap_lenrek@7199 176
 		conf.npage += conf.mem[i].npage;
cinap_lenrek@7199 177
 	}
cinap_lenrek@7199 178
 
cinap_lenrek@7199 179
 	if(userpcnt < 10)
cinap_lenrek@7199 180
 		userpcnt = 60 + cpuserver*10;
cinap_lenrek@7199 181
 	kpages = conf.npage - (conf.npage*userpcnt)/100;
cinap_lenrek@7199 182
 
cinap_lenrek@7199 183
 	/*
cinap_lenrek@7199 184
 	 * can't go past the end of virtual memory
cinap_lenrek@7199 185
 	 * (uintptr)-KZERO is 2^32 - KZERO
cinap_lenrek@7199 186
 	 */
cinap_lenrek@7199 187
 	if(kpages > ((uintptr)-KZERO)/BY2PG)
cinap_lenrek@7199 188
 		kpages = ((uintptr)-KZERO)/BY2PG;
cinap_lenrek@7199 189
 
cinap_lenrek@7199 190
 	conf.upages = conf.npage - kpages;
cinap_lenrek@7199 191
 	conf.ialloc = (kpages/2)*BY2PG;
cinap_lenrek@7199 192
 
cinap_lenrek@7199 193
 	conf.nmach = getncpus();
cinap_lenrek@7199 194
 
cinap_lenrek@7199 195
 	/* set up other configuration parameters */
cinap_lenrek@7199 196
 	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
cinap_lenrek@7199 197
 	if(cpuserver)
cinap_lenrek@7199 198
 		conf.nproc *= 3;
cinap_lenrek@7199 199
 	if(conf.nproc > 2000)
cinap_lenrek@7199 200
 		conf.nproc = 2000;
cinap_lenrek@7199 201
 	conf.nswap = conf.npage*3;
cinap_lenrek@7199 202
 	conf.nswppo = 4096;
cinap_lenrek@7199 203
 	conf.nimage = 200;
cinap_lenrek@7199 204
 
cinap_lenrek@7199 205
 	conf.copymode = conf.nmach > 1;
cinap_lenrek@7199 206
 
cinap_lenrek@7199 207
 	/*
cinap_lenrek@7199 208
 	 * Guess how much is taken by the large permanent
cinap_lenrek@7199 209
 	 * datastructures. Mntcache and Mntrpc are not accounted for.
cinap_lenrek@7199 210
 	 */
cinap_lenrek@7199 211
 	kpages = conf.npage - conf.upages;
cinap_lenrek@7199 212
 	kpages *= BY2PG;
cinap_lenrek@7199 213
 	kpages -= conf.upages*sizeof(Page)
cinap_lenrek@7199 214
 		+ conf.nproc*sizeof(Proc)
cinap_lenrek@7199 215
 		+ conf.nimage*sizeof(Image)
cinap_lenrek@7199 216
 		+ conf.nswap
cinap_lenrek@7199 217
 		+ conf.nswppo*sizeof(Page*);
cinap_lenrek@7199 218
 	mainmem->maxsize = kpages;
cinap_lenrek@7199 219
 	if(!cpuserver)
cinap_lenrek@7199 220
 		/*
cinap_lenrek@7199 221
 		 * give terminals lots of image memory, too; the dynamic
cinap_lenrek@7199 222
 		 * allocation will balance the load properly, hopefully.
cinap_lenrek@7199 223
 		 * be careful with 32-bit overflow.
cinap_lenrek@7199 224
 		 */
cinap_lenrek@7199 225
 		imagmem->maxsize = kpages;
cinap_lenrek@7199 226
 }
cinap_lenrek@7199 227
 
cinap_lenrek@7199 228
 void
cinap_lenrek@7199 229
 machinit(void)
cinap_lenrek@7199 230
 {
cinap_lenrek@7199 231
 	m->ticks = 1;
cinap_lenrek@7199 232
 	m->perf.period = 1;
cinap_lenrek@7199 233
 	active.machs[m->machno] = 1;
cinap_lenrek@7199 234
 }
cinap_lenrek@7199 235
 
cinap_lenrek@7199 236
 void
cinap_lenrek@7199 237
 mpinit(void)
cinap_lenrek@7199 238
 {
cinap_lenrek@7199 239
 	extern void _start(void);
cinap_lenrek@7199 240
 	int i;
cinap_lenrek@7199 241
 
cinap_lenrek@7199 242
 	for(i = 0; i < MAXMACH; i++)
cinap_lenrek@7199 243
 		((uintptr*)SPINTABLE)[i] = 0;
cinap_lenrek@7199 244
 
cinap_lenrek@7199 245
 	for(i = 1; i < conf.nmach; i++)
cinap_lenrek@7199 246
 		MACHP(i)->machno = i;
cinap_lenrek@7199 247
 
cinap_lenrek@7235 248
 	coherence();
cinap_lenrek@7199 249
 
cinap_lenrek@7199 250
 	for(i = 1; i < conf.nmach; i++)
cinap_lenrek@7199 251
 		((uintptr*)SPINTABLE)[i] = PADDR(_start);
cinap_lenrek@7199 252
 
cinap_lenrek@7199 253
 	cachedwbinvse((void*)SPINTABLE, MAXMACH*8);
cinap_lenrek@7199 254
 	sev();
cinap_lenrek@7199 255
 	delay(100);
cinap_lenrek@7199 256
 	sev();
cinap_lenrek@7199 257
 	synccycles();
cinap_lenrek@7235 258
 
cinap_lenrek@7235 259
 	for(i = 0; i < MAXMACH; i++)
cinap_lenrek@7235 260
 		((uintptr*)SPINTABLE)[i] = 0;
cinap_lenrek@7199 261
 }
cinap_lenrek@7199 262
 
cinap_lenrek@7199 263
 void
cinap_lenrek@7199 264
 main(void)
cinap_lenrek@7199 265
 {
cinap_lenrek@7199 266
 	machinit();
cinap_lenrek@7199 267
 	if(m->machno){
cinap_lenrek@7199 268
 		trapinit();
cinap_lenrek@7199 269
 		fpuinit();
cinap_lenrek@7199 270
 		clockinit();
cinap_lenrek@7199 271
 		cpuidprint();
cinap_lenrek@7199 272
 		synccycles();
cinap_lenrek@7199 273
 		timersinit();
cinap_lenrek@7199 274
 		flushtlb();
cinap_lenrek@7199 275
 		mmu1init();
cinap_lenrek@7199 276
 		m->ticks = MACHP(0)->ticks;
cinap_lenrek@7199 277
 		schedinit();
cinap_lenrek@7199 278
 		return;
cinap_lenrek@7199 279
 	}
cinap_lenrek@7235 280
 	quotefmtinstall();
cinap_lenrek@7199 281
 	bootargsinit();
cinap_lenrek@7199 282
 	confinit();
cinap_lenrek@7199 283
 	xinit();
cinap_lenrek@7199 284
 	printinit();
cinap_lenrek@7199 285
 	uartconsinit();
cinap_lenrek@7199 286
 	screeninit();
cinap_lenrek@7199 287
 	print("\nPlan 9\n");
cinap_lenrek@7199 288
 	xsummary();
cinap_lenrek@7199 289
 
cinap_lenrek@7199 290
 	/* set clock rate to arm_freq from config.txt */
cinap_lenrek@7199 291
 	setclkrate(ClkArm, 0);
cinap_lenrek@7199 292
 
cinap_lenrek@7199 293
 	trapinit();
cinap_lenrek@7199 294
 	fpuinit();
cinap_lenrek@7199 295
 	clockinit();
cinap_lenrek@7199 296
 	cpuidprint();
cinap_lenrek@7199 297
 	timersinit();
cinap_lenrek@7199 298
 	pageinit();
cinap_lenrek@7199 299
 	procinit0();
cinap_lenrek@7199 300
 	initseg();
cinap_lenrek@7199 301
 	links();
cinap_lenrek@7199 302
 	chandevreset();
cinap_lenrek@7199 303
 	userinit();
cinap_lenrek@7199 304
 	mpinit();
cinap_lenrek@7199 305
 	mmu0clear((uintptr*)L1);
cinap_lenrek@7199 306
 	flushtlb();
cinap_lenrek@7199 307
 	mmu1init();
cinap_lenrek@7199 308
 	schedinit();
cinap_lenrek@7199 309
 }
cinap_lenrek@7199 310
 
cinap_lenrek@7235 311
 static void
cinap_lenrek@7235 312
 rebootjump(void *entry, void *code, ulong size)
cinap_lenrek@7235 313
 {
cinap_lenrek@7235 314
 	void (*f)(void*, void*, ulong);
cinap_lenrek@7235 315
 
cinap_lenrek@7235 316
 	intrsoff();
cinap_lenrek@7235 317
 	intrcpushutdown();
cinap_lenrek@7235 318
 
cinap_lenrek@7235 319
 	/* redo identity map */
cinap_lenrek@7235 320
 	mmuidmap((uintptr*)L1);
cinap_lenrek@7235 321
 
cinap_lenrek@7235 322
 	/* setup reboot trampoline function */
cinap_lenrek@7235 323
 	f = (void*)REBOOTADDR;
cinap_lenrek@7235 324
 	memmove(f, rebootcode, sizeof(rebootcode));
cinap_lenrek@7235 325
 	cachedwbinvse(f, sizeof(rebootcode));
cinap_lenrek@7235 326
 	cacheiinvse(f, sizeof(rebootcode));
cinap_lenrek@7235 327
 
cinap_lenrek@7235 328
 	(*f)(entry, code, size);
cinap_lenrek@7235 329
 
cinap_lenrek@7235 330
 	for(;;);
cinap_lenrek@7235 331
 }
cinap_lenrek@7235 332
 
cinap_lenrek@7199 333
 void
cinap_lenrek@7199 334
 exit(int)
cinap_lenrek@7199 335
 {
cinap_lenrek@7199 336
 	cpushutdown();
cinap_lenrek@7235 337
 	splfhi();
cinap_lenrek@7235 338
 	if(m->machno == 0)
cinap_lenrek@7235 339
 		archreboot();
cinap_lenrek@7235 340
 	rebootjump(0, 0, 0);
cinap_lenrek@7199 341
 }
cinap_lenrek@7199 342
 
cinap_lenrek@7199 343
 void
cinap_lenrek@7235 344
 reboot(void *entry, void *code, ulong size)
cinap_lenrek@7199 345
 {
cinap_lenrek@7235 346
 	writeconf();
cinap_lenrek@7235 347
 	while(m->machno != 0){
cinap_lenrek@7235 348
 		procwired(up, 0);
cinap_lenrek@7235 349
 		sched();
cinap_lenrek@7235 350
 	}
cinap_lenrek@7235 351
 
cinap_lenrek@7235 352
 	cpushutdown();
cinap_lenrek@7235 353
 	delay(2000);
cinap_lenrek@7235 354
 
cinap_lenrek@7235 355
 	splfhi();
cinap_lenrek@7235 356
 
cinap_lenrek@7235 357
 	/* turn off buffered serial console */
cinap_lenrek@7235 358
 	serialoq = nil;
cinap_lenrek@7235 359
 
cinap_lenrek@7235 360
 	/* shutdown devices */
cinap_lenrek@7235 361
 	chandevshutdown();
cinap_lenrek@7235 362
 
cinap_lenrek@7235 363
 	/* stop the clock (and watchdog if any) */
cinap_lenrek@7235 364
 	clockshutdown();
cinap_lenrek@7235 365
 	wdogoff();
cinap_lenrek@7235 366
 
cinap_lenrek@7235 367
 	/* off we go - never to return */
cinap_lenrek@7235 368
 	rebootjump(entry, code, size);
cinap_lenrek@7199 369
 }
cinap_lenrek@7199 370
 
cinap_lenrek@7199 371
 /*
cinap_lenrek@7199 372
  * stub for ../omap/devether.c
cinap_lenrek@7199 373
  */
cinap_lenrek@7199 374
 int
cinap_lenrek@7199 375
 isaconfig(char *, int, ISAConf *)
cinap_lenrek@7199 376
 {
cinap_lenrek@7199 377
 	return 0;
cinap_lenrek@7199 378
 }