-/* init_main.c 3.4 %H% */
-
-#include "../h/param.h"
-#include "../h/systm.h"
-#include "../h/dir.h"
-#include "../h/user.h"
-#include "../h/filsys.h"
-#include "../h/mount.h"
-#include "../h/map.h"
-#include "../h/proc.h"
-#include "../h/inode.h"
-#include "../h/seg.h"
-#include "../h/conf.h"
-#include "../h/buf.h"
-#include "../h/mtpr.h"
-#include "../h/pte.h"
-#include "../h/clock.h"
-#include "../h/vm.h"
-#include "../h/cmap.h"
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ * @(#)init_main.c 7.7 (Berkeley) %G%
+ */
+#include "../machine/pte.h"
+
+#include "param.h"
+#include "systm.h"
+#include "dir.h"
+#include "user.h"
+#include "kernel.h"
+#include "fs.h"
+#include "mount.h"
+#include "map.h"
+#include "proc.h"
+#include "inode.h"
+#include "seg.h"
+#include "conf.h"
+#include "buf.h"
+#include "vm.h"
+#include "cmap.h"
+#include "text.h"
+#include "clist.h"
+#include "malloc.h"
+#include "protosw.h"
+#include "quota.h"
+#include "reboot.h"
+#include "../machine/reg.h"
+#include "../machine/cpu.h"
+
+int cmask = CMASK;
/*
* Initialization code.
* Called from cold start routine as
* hand craft 0th process
* call all initialization routines
* fork - process 0 to schedule
- * - process 2 to page out
* - process 1 execute bootstrap
- *
- * loop at loc 13 (0xd) in user mode -- /etc/init
- * cannot be executed.
+ * - process 2 to page out
*/
main(firstaddr)
+ int firstaddr;
{
+ register int i;
+ register struct proc *p;
+ register struct pgrp *pg;
+ struct fs *fs;
+ int s;
- cpusid = mfpr(SID); /* get system identification */
-#ifdef FASTVAX
rqinit();
-#endif
+#include "loop.h"
startup(firstaddr);
- if (lotsfree == 0)
- lotsfree = LOTSFREE;
/*
* set up system process 0 (swapper)
*/
+ p = &proc[0];
+ p->p_p0br = u.u_pcb.pcb_p0br;
+ p->p_szpt = 1;
+ p->p_addr = uaddr(p);
+ p->p_stat = SRUN;
+ p->p_flag |= SLOAD|SSYS;
+ p->p_nice = NZERO;
+ setredzone(p->p_addr, (caddr_t)&u);
+ u.u_procp = p;
+ MALLOC(pgrphash[0], struct pgrp *, sizeof (struct pgrp),
+ M_PGRP, M_NOWAIT);
+ if ((pg = pgrphash[0]) == NULL)
+ panic("no space to craft zero'th process group");
+ pg->pg_id = 0;
+ pg->pg_hforw = 0;
+ pg->pg_mem = p;
+ pg->pg_jobc = 0;
+ p->p_pgrp = pg;
+ p->p_pgrpnxt = 0;
+ MALLOC(pg->pg_session, struct session *, sizeof (struct session),
+ M_SESSION, M_NOWAIT);
+ if (pg->pg_session == NULL)
+ panic("no space to craft zero'th session");
+ pg->pg_session->s_count = 1;
+ pg->pg_session->s_leader = 0;
+ /*
+ * These assume that the u. area is always mapped
+ * to the same virtual address. Otherwise must be
+ * handled when copying the u. area in newproc().
+ */
+ u.u_nd.ni_iov = &u.u_nd.ni_iovec;
+ u.u_ap = u.u_arg;
+ u.u_nd.ni_iovcnt = 1;
- proc[0].p_p0br = (struct pte *)mfpr(P0BR);
- proc[0].p_szpt = 1;
- proc[0].p_addr = uaddr(&proc[0]);
- proc[0].p_stat = SRUN;
- proc[0].p_flag |= SLOAD|SSYS;
- proc[0].p_nice = NZERO;
- u.u_procp = &proc[0];
- u.u_cmask = CMASK;
- clkstart();
-
+ u.u_cmask = cmask;
+ u.u_lastfile = -1;
+ for (i = 1; i < NGROUPS; i++)
+ u.u_groups[i] = NOGROUP;
+ for (i = 0; i < sizeof(u.u_rlimit)/sizeof(u.u_rlimit[0]); i++)
+ u.u_rlimit[i].rlim_cur = u.u_rlimit[i].rlim_max =
+ RLIM_INFINITY;
/*
- * Initialize devices and
- * set up 'known' i-nodes
+ * configure virtual memory system,
+ * set vm rlimits
*/
+ vminit();
- ihinit();
- bhinit();
+#if defined(QUOTA)
+ qtinit();
+ p->p_quota = u.u_quota = getquota(0, 0, Q_NDQ);
+#endif
+ startrtclock();
+#if defined(vax)
+#include "kg.h"
+#if NKG > 0
+ startkgclock();
+#endif
+#endif
+
+ /*
+ * Initialize tables, protocols, and set up well-known inodes.
+ */
+ mbinit();
cinit();
- binit();
- bswinit();
- iinit();
- rootdir = iget(rootdev, (ino_t)ROOTINO);
- rootdir->i_flag &= ~ILOCK;
- u.u_cdir = iget(rootdev, (ino_t)ROOTINO);
- u.u_cdir->i_flag &= ~ILOCK;
+#include "sl.h"
+#if NSL > 0
+ slattach(); /* XXX */
+#endif
+#if NLOOP > 0
+ loattach(); /* XXX */
+#endif
+ /*
+ * Block reception of incoming packets
+ * until protocols have been initialized.
+ */
+ s = splimp();
+ ifinit();
+ domaininit();
+ splx(s);
+ pqinit();
+ xinit();
+ ihinit();
+ swapinit();
+ nchinit();
+#ifdef GPROF
+ kmstartup();
+#endif
+
+ fs = mountfs(rootdev, boothowto & RB_RDONLY, (struct inode *)0);
+ if (fs == 0)
+ panic("iinit");
+ bcopy("/", fs->fs_fsmnt, 2);
+
+ inittodr(fs->fs_time);
+ boottime = time;
+
+/* kick off timeout driven events by calling first time */
+ roundrobin();
+ schedcpu();
+ schedpaging();
+
+/* set up the root file system */
+ rootdir = iget(rootdev, fs, (ino_t)ROOTINO);
+ iunlock(rootdir);
+ u.u_cdir = iget(rootdev, fs, (ino_t)ROOTINO);
+ iunlock(u.u_cdir);
u.u_rdir = NULL;
+
u.u_dmap = zdmap;
u.u_smap = zdmap;
+ enablertclock(); /* enable realtime clock interrupts */
+ /*
+ * make init process
+ */
+
+ proc[0].p_szpt = CLSIZE;
+ if (newproc(0)) {
+ expand(clrnd((int)btoc(szicode)), 0);
+ (void) swpexpand(u.u_dsize, (size_t)0, &u.u_dmap, &u.u_smap);
+ (void) copyout((caddr_t)icode, (caddr_t)0, (unsigned)szicode);
+ /*
+ * Return goes to loc. 0 of user init
+ * code just copied out.
+ */
+ return;
+ }
/*
* make page-out daemon (process 2)
- * the daemon has ctopt(NSWBUF*CLSIZE*KLMAX) pages of page
+ * the daemon has ctopt(nswbuf*CLSIZE*KLMAX) pages of page
* table so that it can map dirty pages into
* its address space during asychronous pushes.
*/
-
- mpid = 1;
- proc[0].p_szpt = clrnd(ctopt(NSWBUF*CLSIZE*KLMAX + UPAGES));
- proc[1].p_stat = SZOMB; /* force it to be in proc slot 2 */
+ proc[0].p_szpt = clrnd(ctopt(nswbuf*CLSIZE*KLMAX + UPAGES));
if (newproc(0)) {
proc[2].p_flag |= SLOAD|SSYS;
- proc[2].p_dsize = u.u_dsize = NSWBUF*CLSIZE*KLMAX;
+ proc[2].p_dsize = u.u_dsize = nswbuf*CLSIZE*KLMAX;
pageout();
+ /*NOTREACHED*/
}
/*
- * make init process and
* enter scheduling loop
*/
-
- mpid = 0;
- proc[1].p_stat = 0;
- proc[0].p_szpt = CLSIZE;
- if (newproc(0)) {
- expand(clrnd((int)btoc(szicode)), P0BR);
- (void) copyout((caddr_t)icode, (caddr_t)0, (unsigned)szicode);
- /*
- * Return goes to loc. 0 of user init
- * code just copied out.
- */
- return;
- }
proc[0].p_szpt = 1;
sched();
}
/*
- * iinit is called once (from main)
- * very early in initialization.
- * It reads the root's super block
- * and initializes the current date
- * from the last modified date.
- *
- * panic: iinit -- cannot read the super
- * block. Usually because of an IO error.
+ * Initialize hash links for buffers.
*/
-iinit()
+bhinit()
{
- register struct buf *cp, *bp;
- register struct filsys *fp;
- register unsigned i, j;
-
- (*bdevsw[major(rootdev)].d_open)(rootdev, 1);
- bp = bread(rootdev, SUPERB);
- cp = geteblk();
- if(u.u_error)
- panic("iinit");
- bcopy(bp->b_un.b_addr, cp->b_un.b_addr, sizeof(struct filsys));
- brelse(bp);
- mount[0].m_bufp = cp;
- mount[0].m_dev = rootdev;
- fp = cp->b_un.b_filsys;
- fp->s_flock = 0;
- fp->s_ilock = 0;
- fp->s_ronly = 0;
- fp->s_lasti = 1;
- fp->s_nbehind = 0;
- /* on boot, read VAX TODR register (GMT 10 ms.
- * clicks into current year) and set software time
- * in 'int time' (GMT seconds since year YRREF)
- */
- for (i = 0 , j = YRREF ; j < YRCURR ; j++)
- i += (SECYR + (j%4?0:SECDAY)) ;
- time = udiv(mfpr(TODR),100) + i ;
- bootime = time;
-}
+ register int i;
+ register struct bufhd *bp;
-/*
- * This is the set of buffers proper, whose heads
- * were declared in buf.h. There can exist buffer
- * headers not pointing here that are used purely
- * as arguments to the I/O routines to describe
- * I/O to be done-- e.g. swap headers swbuf[] for
- * swapping.
- */
-char buffers[NBUF][BSIZE];
+ for (bp = bufhash, i = 0; i < BUFHSZ; i++, bp++)
+ bp->b_forw = bp->b_back = (struct buf *)bp;
+}
/*
* Initialize the buffer I/O system by freeing
* all buffers and setting all device buffer lists to empty.
- *
- * SHOULD USE MEMALL HERE!!!
*/
binit()
{
- register struct buf *bp;
- register struct buf *dp;
+ register struct buf *bp, *dp;
register int i;
- struct bdevsw *bdp;
+ int base, residual;
- bfreelist.b_forw = bfreelist.b_back =
- bfreelist.av_forw = bfreelist.av_back = &bfreelist;
- for (i=0; i<NBUF; i++) {
+ for (dp = bfreelist; dp < &bfreelist[BQUEUES]; dp++) {
+ dp->b_forw = dp->b_back = dp->av_forw = dp->av_back = dp;
+ dp->b_flags = B_HEAD;
+ }
+ base = bufpages / nbuf;
+ residual = bufpages % nbuf;
+ for (i = 0; i < nbuf; i++) {
bp = &buf[i];
bp->b_dev = NODEV;
- bp->b_un.b_addr = buffers[i];
- bp->b_back = &bfreelist;
- bp->b_forw = bfreelist.b_forw;
- bfreelist.b_forw->b_back = bp;
- bfreelist.b_forw = bp;
- bp->b_flags = B_BUSY;
+ bp->b_bcount = 0;
+ bp->b_un.b_addr = buffers + i * MAXBSIZE;
+ if (i < residual)
+ bp->b_bufsize = (base + 1) * CLBYTES;
+ else
+ bp->b_bufsize = base * CLBYTES;
+ binshash(bp, &bfreelist[BQ_AGE]);
+ bp->b_flags = B_BUSY|B_INVAL;
brelse(bp);
}
- for (bdp = bdevsw; bdp->d_open; bdp++) {
- dp = bdp->d_tab;
- if(dp) {
- dp->b_forw = dp;
- dp->b_back = dp;
- }
- nblkdev++;
- }
}
/*
+ * Set up swap devices.
* Initialize linked list of free swap
* headers. These do not actually point
* to buffers, but rather to pages that
* are being swapped in and out.
*/
-bswinit()
+swapinit()
{
register int i;
+ register struct buf *sp = swbuf;
+ struct swdevt *swp;
+ int error;
+
+ /*
+ * Count swap devices, and adjust total swap space available.
+ * Some of this space will not be available until a swapon()
+ * system is issued, usually when the system goes multi-user.
+ */
+ nswdev = 0;
+ nswap = 0;
+ for (swp = swdevt; swp->sw_dev; swp++) {
+ nswdev++;
+ if (swp->sw_nblks > nswap)
+ nswap = swp->sw_nblks;
+ }
+ if (nswdev == 0)
+ panic("swapinit");
+ if (nswdev > 1)
+ nswap = ((nswap + dmmax - 1) / dmmax) * dmmax;
+ nswap *= nswdev;
+ /*
+ * If there are multiple swap areas,
+ * allow more paging operations per second.
+ */
+ if (nswdev > 1)
+ maxpgio = (maxpgio * (2 * nswdev - 1)) / 2;
+ if (error = swfree(0)) {
+ printf("swfree errno %d\n", error); /* XXX */
+ panic("swapinit swfree 0");
+ }
+
+ /*
+ * Now set up swap buffer headers.
+ */
+ bswlist.av_forw = sp;
+ for (i=0; i<nswbuf-1; i++, sp++)
+ sp->av_forw = sp+1;
+ sp->av_forw = NULL;
+}
- bswlist.av_forw = &swbuf[0];
- for (i=0; i<NSWBUF-1; i++)
- swbuf[i].av_forw = &swbuf[i+1];
- swbuf[NSWBUF-1].av_forw = NULL;
+/*
+ * Initialize clist by freeing all character blocks, then count
+ * number of character devices. (Once-only routine)
+ */
+cinit()
+{
+ register int ccp;
+ register struct cblock *cp;
+
+ ccp = (int)cfree;
+ ccp = (ccp+CROUND) & ~CROUND;
+ for(cp=(struct cblock *)ccp; cp < &cfree[nclist-1]; cp++) {
+ cp->c_next = cfreelist;
+ cfreelist = cp;
+ cfreecount += CBSIZE;
+ }
}