
replace machine specific userinit() by a portable implemntation that uses kproc() to create the first process. the initcode text is mapped using kmap(), so there is no need for machine specific tmpmap() functions. initcode stack preparation should be done in init0() where the stack is mapped and can be accessed directly. replacing the machine specific userinit() allows some big simplifications as sysrfork() and kproc() are now the only callers of newproc() and we can avoid initializing fields that we know are being initialized by these callers. rename autogenerated init.h and reboot.h headers. the initcode[] and rebootcode[] blobs are now in *.i files and hex generation was moved to portmkfile. the machine specific mkfile only needs to specify how to build rebootcode.out and initcode.out.
88 lines
1.8 KiB
C
88 lines
1.8 KiB
C
#include "u.h"
|
|
#include "../port/lib.h"
|
|
#include "mem.h"
|
|
#include "dat.h"
|
|
#include "fns.h"
|
|
#include "../port/error.h"
|
|
|
|
/*
|
|
* The initcode array contains the binary text of the first
|
|
* user process. Its job is to invoke the exec system call
|
|
* for /boot/boot.
|
|
* Initcode does not link with standard plan9 libc _main()
|
|
* trampoline due to size constrains. Instead it is linked
|
|
* with a small machine specific trampoline init9.s that
|
|
* only sets the base address register and passes arguments
|
|
* to startboot() (see port/initcode.c).
|
|
*/
|
|
#include "initcode.i"
|
|
|
|
/*
|
|
* The first process kernel process starts here.
|
|
*/
|
|
static void
|
|
proc0(void*)
|
|
{
|
|
KMap *k;
|
|
Page *p;
|
|
|
|
spllo();
|
|
|
|
up->pgrp = newpgrp();
|
|
up->egrp = smalloc(sizeof(Egrp));
|
|
up->egrp->ref = 1;
|
|
up->fgrp = dupfgrp(nil);
|
|
up->rgrp = newrgrp();
|
|
|
|
/*
|
|
* These are o.k. because rootinit is null.
|
|
* Then early kproc's will have a root and dot.
|
|
*/
|
|
up->slash = namec("#/", Atodir, 0, 0);
|
|
pathclose(up->slash->path);
|
|
up->slash->path = newpath("/");
|
|
up->dot = cclone(up->slash);
|
|
|
|
/*
|
|
* Setup Text and Stack segments for initcode.
|
|
*/
|
|
up->seg[SSEG] = newseg(SG_STACK | SG_NOEXEC, USTKTOP-USTKSIZE, USTKSIZE / BY2PG);
|
|
up->seg[TSEG] = newseg(SG_TEXT | SG_RONLY, UTZERO, 1);
|
|
p = newpage(1, 0, UTZERO);
|
|
k = kmap(p);
|
|
memmove((void*)VA(k), initcode, sizeof(initcode));
|
|
kunmap(k);
|
|
p->txtflush = ~0;
|
|
segpage(up->seg[TSEG], p);
|
|
up->seg[TSEG]->flushme++;
|
|
|
|
/*
|
|
* Become a user process.
|
|
*/
|
|
up->kp = 0;
|
|
up->noswap = 0;
|
|
procpriority(up, PriNormal, 0);
|
|
procsetup(up);
|
|
|
|
flushmmu();
|
|
|
|
/*
|
|
* init0():
|
|
* call chandevinit()
|
|
* setup environment variables
|
|
* prepare the stack for initcode
|
|
* switch to usermode to run initcode
|
|
*/
|
|
init0();
|
|
|
|
/* init0 will never return */
|
|
panic("init0");
|
|
}
|
|
|
|
void
|
|
userinit(void)
|
|
{
|
|
up = nil;
|
|
kstrdup(&eve, "");
|
|
kproc("*init*", proc0, nil);
|
|
}
|