vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

sysproc.ed (10059B)


      1 1i
      2 #define	WANT_M
      3 .
      4 g/"edf.h"/d
      5 ,s/->ref =/->ref.ref =/g
      6 ,s/ref(p->dot)/ref(\&p->dot->ref)/g
      7 ,s/ref(p->fgrp)/ref(\&p->fgrp->ref)/g
      8 ,s/ref(p->pgrp)/ref(\&p->pgrp->ref)/g
      9 ,s/ref(p->egrp)/ref(\&p->egrp->ref)/g
     10 ,s/lock(img)/lock(\&img->ref.lk)/g
     11 ,s/ref(img)/ref(\&img->ref)/g
     12 ,s/return0(void\*)/return0(void *v)/g
     13 ,s/(s = up->seg\[i\])/(&)/g
     14 ,s;MACHP(0)->ticks;msec();g
     15 /ESEG.*= newseg/a
     16 	flushmmu();	// Needed for Plan 9 VX
     17 .
     18 ,s;sleep(\&phore;sleep(\&phore.rendez;g
     19 ,s;lock(\&s->sema);lock(\&s->sema.rendez.lk);g
     20 ,s;wakeup(p);wakeup(\&p->rendez);g
     21 ,s;lock(up->rgrp);lock(\&up->rgrp->ref.lk);g
     22 ,s;ref(up->rgrp);ref(\&up->rgrp->ref);g
     23 /sysr1/ s/(ulong\*)/(uint32 *x)/
     24 /Admitted/,/	yield/c
     25 		yield();
     26 .
     27 /^	checkpagerefs/ c
     28 	vx32sysr1();
     29 .
     30 /^sysrfork/ s/ulong/uint32/
     31 /^l2be/ s/long/uint32/
     32 -1 s/ulong/uint32/
     33 /^sysexec/ s/ulong/uint32/
     34 -1i
     35 static char Echanged[] = "exec arguments changed underfoot";
     36 
     37 .
     38 /^{/+1;/^}/-1 c
     39 	char *volatile elem, *volatile file, *ufile;
     40 	Chan *volatile tc;
     41 
     42 	/*
     43 	 * Open the file, remembering the final element and the full name.
     44 	 */
     45 	file = nil;
     46 	elem = nil;
     47 	tc = nil;
     48 	if(waserror()){
     49 		if(file)
     50 			free(file);
     51 		if(elem)
     52 			free(elem);
     53 		if(tc)
     54 			cclose(tc);
     55 		nexterror();
     56 	}
     57 
     58 	ufile = uvalidaddr(arg[0], 1, 0);
     59 	file = validnamedup(ufile, 1);
     60 	tc = namec(file, Aopen, OEXEC, 0);
     61 	kstrdup((char**)&elem, up->genbuf);
     62 
     63 	/*
     64 	 * Read the header.  If it's a #!, fill in progarg[] with info and repeat.
     65 	 */
     66 	int i, n, nprogarg;
     67 	char *progarg[sizeof(Exec)/2+1];
     68 	char *prog, *p;
     69 	char line[sizeof(Exec)+1];
     70 	Exec exec;
     71 
     72 	nprogarg = 0;
     73 	n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
     74 	if(n < 2)
     75 		error(Ebadexec);
     76 	p = (char*)&exec;
     77 	if(p[0] == '#' && p[1] == '!'){
     78 		memmove(line, p, n);
     79 		nprogarg = shargs(line, n, progarg);
     80 		if(nprogarg == 0)
     81 			error(Ebadexec);
     82 		
     83 		/* The original file becomes an extra arg after #! line */
     84 		progarg[nprogarg++] = file;
     85 		
     86 		/*
     87 		 * Take the #! $0 as a file to open, and replace
     88 		 * $0 with the original path's name.
     89 		 */
     90 		prog = progarg[0];
     91 		progarg[0] = elem;
     92 		cclose(tc);
     93 		tc = nil;	/* in case namec errors out */
     94 		tc = namec(prog, Aopen, OEXEC, 0);
     95 		n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
     96 		if(n < 2)
     97 			error(Ebadexec);
     98 	}
     99 
    100 	/* 
    101 	 * #! has had its chance, now we need a real binary
    102 	 */
    103 	uint32 magic, entry, text, etext, data, edata, bss, ebss;
    104 
    105 	magic = l2be(exec.magic);
    106 	if(n != sizeof(Exec) || l2be(exec.magic) != AOUT_MAGIC)
    107 		error(Ebadexec);
    108 
    109 	entry = l2be(exec.entry);
    110 	text = l2be(exec.text);
    111 	data = l2be(exec.data);
    112 	bss = l2be(exec.bss);
    113 	etext = ROUND(UTZERO+sizeof(Exec)+text, BY2PG);
    114 	edata = ROUND(etext + data, BY2PG);
    115 	ebss = ROUND(etext + data + bss, BY2PG);
    116 	
    117 //iprint("entry %#lux text %#lux data %#lux bss %#lux\n", entry, text, data, bss);
    118 //iprint("etext %#lux edata %#lux ebss %#lux\n", etext, edata, ebss);
    119 
    120 	if(entry < UTZERO+sizeof(Exec) || entry >= UTZERO+sizeof(Exec)+text)
    121 		error(Ebadexec);
    122 	
    123 	/* many overflow possibilities */
    124 	if(text >= USTKTOP || data >= USTKTOP || bss >= USTKTOP
    125 	|| etext >= USTKTOP || edata >= USTKTOP || ebss >= USTKTOP
    126 	|| etext >= USTKTOP || edata < etext || ebss < edata)
    127 		error(Ebadexec);
    128 
    129 	/*
    130 	 * Copy argv into new stack segment temporarily mapped elsewhere.
    131 	 * Be careful: multithreaded program could be changing argv during this.
    132 	 * Pass 1: count number of arguments, string bytes.
    133 	 */
    134 	int nargv, strbytes;
    135 	uint32 argp, ssize, spage;
    136 
    137 	strbytes = 0;
    138 	for(i=0; i<nprogarg; i++)
    139 		strbytes += strlen(progarg[i]) + 1;
    140 
    141 	argp = arg[1];
    142 	for(nargv=0;; nargv++, argp += BY2WD){
    143 		uint32 a;
    144 		char *str;
    145 
    146 		a = *(uint32*)uvalidaddr(argp, BY2WD, 0);
    147 		if(a == 0)
    148 			break;
    149 		str = uvalidaddr(a, 1, 0);
    150 		n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;
    151 		if(nprogarg > 0 && nargv == 0)
    152 			continue;	/* going to skip argv[0] on #! */
    153 		strbytes += n;
    154 	}
    155 	if(nargv == 0)
    156 		error("exec missing argv");
    157 
    158 	/* 
    159 	 * Skip over argv[0] if using #!.  Waited until now so that
    160 	 * string would still be checked for validity during loop.
    161 	 */
    162 	if(nprogarg > 0){
    163 		nargv--;
    164 		arg[1] += BY2WD;
    165 	}
    166 
    167 	ssize = BY2WD*((nprogarg+nargv)+1) + ROUND(strbytes, BY2WD) + sizeof(Tos);
    168 
    169 	/*
    170 	 * 8-byte align SP for those (e.g. sparc) that need it.
    171 	 * execregs() will subtract another 4 bytes for argc.
    172 	 */
    173 	if((ssize+4) & 7)
    174 		ssize += 4;
    175 	spage = (ssize+(BY2PG-1)) >> PGSHIFT;
    176 
    177 	/*
    178 	 * Pass 2: build the stack segment, being careful not to assume
    179 	 * that the counts from pass 1 are still valid.
    180 	 */
    181 	if(spage > TSTKSIZ)
    182 		error(Enovmem);
    183 
    184 	qlock(&up->seglock);
    185 	if(waserror()){
    186 		if(up->seg[ESEG]){
    187 			putseg(up->seg[ESEG]);
    188 			up->seg[ESEG] = nil;
    189 		}
    190 		qunlock(&up->seglock);
    191 		nexterror();
    192 	}
    193 	up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);
    194 	flushmmu();	// Needed for Plan 9 VX  XXX really?
    195 
    196 	/*
    197 	 * Top-of-stack structure.
    198 	 */
    199 	uchar *uzero;
    200 	uzero = up->pmmu.uzero;
    201 	Tos *tos;
    202 	uint32 utos;
    203 	utos = USTKTOP - sizeof(Tos);
    204 	tos = (Tos*)(uzero + utos + TSTKTOP - USTKTOP);
    205 	tos->cyclefreq = m->cyclefreq;
    206 	cycles((uvlong*)&tos->pcycles);
    207 	tos->pcycles = -tos->pcycles;
    208 	tos->kcycles = tos->pcycles;
    209 	tos->clock = 0;
    210 
    211 	/*
    212 	 * Argument pointers and strings, together.
    213 	 */
    214 	char *bp, *ep;
    215 	uint32 *targp;
    216 	uint32 ustrp, uargp;
    217 
    218 	ustrp = utos - ROUND(strbytes, BY2WD);
    219 	uargp = ustrp - BY2WD*((nprogarg+nargv)+1);
    220 	bp = (char*)(uzero + ustrp + TSTKTOP - USTKTOP);
    221 	ep = bp + strbytes;
    222 	p = bp;
    223 	targp = (uint32*)(uzero + uargp + TSTKTOP - USTKTOP);
    224 	
    225 	/* #! args are trusted */
    226 	for(i=0; i<nprogarg; i++){
    227 		n = strlen(progarg[i]) + 1;
    228 		if(n  > ep - p)
    229 			error(Echanged);
    230 		memmove(p, progarg[i], n);
    231 		p += n;
    232 		*targp++ = ustrp;
    233 		ustrp += n;
    234 	}
    235 	
    236 	/* the rest are not */
    237 	argp = arg[1];
    238 	for(i=0; i<nargv; i++){
    239 		uint32 a;
    240 		char *str;
    241 		
    242 		a = *(uint32*)uvalidaddr(argp, BY2WD, 0);
    243 		argp += BY2WD;
    244 		
    245 		str = uvalidaddr(a, 1, 0);
    246 		n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;
    247 		if(n  > ep - p)
    248 			error(Echanged);
    249 		memmove(p, str, n);
    250 		p += n;
    251 		*targp++ = ustrp;
    252 		ustrp += n;
    253 	}
    254 
    255 	if(*(uint32*)uvalidaddr(argp, BY2WD, 0) != 0)
    256 		error(Echanged);	
    257 	*targp = 0;
    258 
    259 	/*
    260 	 * But wait, there's more: prepare an arg copy for up->args
    261 	 * using the copy we just made in the temporary segment.
    262 	 */
    263 	char *args;
    264 	int nargs;
    265 
    266 	n = p - bp;	/* includes NUL on last arg, so must be > 0 */
    267 	if(n <= 0)	/* nprogarg+nargv > 0; checked above */
    268 		error(Egreg);
    269 	if(n > 128)
    270 		n = 128;
    271 	args = smalloc(n);
    272 	if(waserror()){
    273 		free(args);
    274 		nexterror();
    275 	}
    276 	memmove(args, bp, n);
    277 	/* find beginning of UTF character boundary to place final NUL */
    278 	while(n > 0 && (args[n-1]&0xC0) == 0x80)
    279 		n--;
    280 	args[n-1] = '\0';
    281 	nargs = n;
    282 
    283 	/*
    284 	 * Now we're ready to commit.
    285 	 */
    286 	free(up->text);
    287 	up->text = elem;
    288 	free(up->args);
    289 	up->args = args;
    290 	up->nargs = n;
    291 	elem = nil;
    292 	poperror();	/* args */
    293 
    294 	/*
    295 	 * Free old memory.  Special segments maintained across exec.
    296 	 */
    297 	Segment *s;
    298 	for(i = SSEG; i <= BSEG; i++) {
    299 		putseg(up->seg[i]);
    300 		up->seg[i] = nil;	/* in case of error */
    301 	}
    302 	for(i = BSEG+1; i< NSEG; i++) {
    303 		s = up->seg[i];
    304 		if(s && (s->type&SG_CEXEC)) {
    305 			putseg(s);
    306 			up->seg[i] = nil;
    307 		}
    308 	}
    309 	
    310 	/*
    311 	 * Close on exec
    312 	 */
    313 	Fgrp *f;
    314 	f = up->fgrp;
    315 	for(i=0; i<=f->maxfd; i++)
    316 		fdclose(i, CCEXEC);
    317 
    318 	/* Text.  Shared. Attaches to cache image if possible */
    319 	/* attachimage returns a locked cache image */
    320 	Image *img;
    321 	Segment *ts;
    322 	img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (etext-UTZERO)>>PGSHIFT);
    323 	ts = img->s;
    324 	up->seg[TSEG] = ts;
    325 	ts->flushme = 1;
    326 	ts->fstart = 0;
    327 	ts->flen = sizeof(Exec)+text;
    328 	unlock(&img->ref.lk);
    329 
    330 	/* Data. Shared. */
    331 	s = newseg(SG_DATA, etext, (edata-etext)>>PGSHIFT);
    332 	up->seg[DSEG] = s;
    333 
    334 	/* Attached by hand */
    335 	incref(&img->ref);
    336 	s->image = img;
    337 	s->fstart = ts->fstart+ts->flen;
    338 	s->flen = data;
    339 
    340 	/* BSS. Zero fill on demand */
    341 	up->seg[BSEG] = newseg(SG_BSS, edata, (ebss-edata)>>PGSHIFT);
    342 
    343 	/*
    344 	 * Move the stack
    345 	 */
    346 	s = up->seg[ESEG];
    347 	up->seg[ESEG] = 0;
    348 	up->seg[SSEG] = s;
    349 	qunlock(&up->seglock);
    350 	poperror();	/* seglock */
    351 
    352 	s->base = USTKTOP-USTKSIZE;
    353 	s->top = USTKTOP;
    354 	relocateseg(s, USTKTOP-TSTKTOP);
    355 
    356 	/*
    357 	 *  '/' processes are higher priority (hack to make /ip more responsive).
    358 	 */
    359 	if(devtab[tc->type]->dc == L'/')
    360 		up->basepri = PriRoot;
    361 	up->priority = up->basepri;
    362 	poperror();	/* tc, elem, file */
    363 	cclose(tc);
    364 	free(file);
    365 	// elem is now up->text
    366 
    367 	/*
    368 	 *  At this point, the mmu contains info about the old address
    369 	 *  space and needs to be flushed
    370 	 */
    371 	flushmmu();
    372 	qlock(&up->debug);
    373 	up->nnote = 0;
    374 	up->notify = 0;
    375 	up->notified = 0;
    376 	up->privatemem = 0;
    377 	procsetup(up);
    378 	qunlock(&up->debug);
    379 	if(up->hang)
    380 		up->procctl = Proc_stopme;
    381 
    382 	return execregs(entry, USTKTOP - uargp, nprogarg+nargv);
    383 .
    384 /^syssleep/s/ulong/uint32/
    385 /^sysalarm/s/ulong/uint32/
    386 /^sysexits/s/ulong/uint32/
    387 /status/;/if(status)/ c
    388 	char *status;
    389 	char *inval = "invalid exit string";
    390 	char buf[ERRMAX];
    391 
    392 	if(arg[0]){
    393 .
    394 /validaddr/c
    395 			status = uvalidaddr(arg[0], 1, 0);
    396 .
    397 /^	}/ c
    398 	}else
    399 		status = nil;
    400 .
    401 /^sys_wait/s/ulong/uint32/
    402 /validaddr(arg\[0\], sizeof(OWaitmsg), 1)/ c
    403 	ow = uvalidaddr(arg[0], sizeof(OWaitmsg), 1);
    404 .
    405 /ow =/d
    406 /^sysawait/s/ulong/uint32/
    407 /ulong n/ s/ulong/uint32/
    408 a
    409 	char *buf;
    410 .
    411 /validaddr/ s/v/buf = uv/
    412 /i = / s/(char\*)arg\[0\]/buf/
    413 /^generrstr/ s/char \*buf/uint32 addr/
    414 /^$/i
    415 	char *buf;
    416 .
    417 /validaddr/ s/v/buf = uv/
    418 s/(ulong)buf/addr/
    419 /^syserrstr/s/ulong/uint32/
    420 /return/s/(char\*)//
    421 /^sys_errstr/s/ulong/uint32/
    422 /return/s/(char\*)//
    423 /^sysnotify/s/ulong/uint32/
    424 /validaddr/;/up->notify/c
    425 		uvalidaddr(arg[0], 1, 0);
    426 	up->notify = arg[0];	/* checked again when used */
    427 .
    428 /^sysnoted/s/ulong/uint32/
    429 /^syssegbrk/s/ulong/uint32/
    430 /addr/s/ulong/uint32/
    431 /^syssegattach/s/ulong/uint32/
    432 /return/s/(char\*)arg\[1\]/uvalidaddr(arg[1], 1, 0)/
    433 /^syssegdetach/s/ulong/uint32/
    434 /addr/s/ulong/uint32/
    435 /^syssegfree/s/ulong/uint32/
    436 /from/s/ulong/uint32/
    437 /^sysbrk_/s/ulong/uint32/
    438 /^sysrendezvous/s/ulong/uint32/
    439 /^syssemacquire/s/ulong/uint32/
    440 /validaddr/ s/v/addr = uv/
    441 /addr =/d
    442 /(ulong)addr/s/(ulong)addr/arg[0]/
    443 /^syssemrelease/s/ulong/uint32/
    444 /validaddr/ s/v/addr = uv/
    445 /addr =/d
    446 /(ulong)addr/s/(ulong)addr/arg[0]/