shithub: nix

Download patch

ref: db55afd4a5f5297bce2b5a21427fc36d5f8d7a9c
parent: f1d768235e45e9489e04cb46705e7b065855aaa6
author: glenda <glenda@cirno>
date: Fri May 3 17:24:20 EDT 2024

add files, clean up, closer to building

--- a/sys/src/nix/pc64/acore.c
+++ b/sys/src/nix/pc64/acore.c
@@ -1,21 +1,20 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
+#include	"u.h"
+#include	"tos.h"
+#include	"../port/lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"io.h"
+#include	"../port/pci.h"
+#include	"ureg.h"
+#include	"pool.h"
 
-#include <tos.h>
-#include <pool.h>
-#include "amd64.h"
-#include "ureg.h"
-#include "io.h"
-#include "../port/pmc.h"
-
 /*
  * NIX code run at the AC.
  * This is the "AC kernel".
  */
 
+#define DBG print
 /*
  * FPU:
  *
@@ -52,8 +51,9 @@
 }
 
 void
-testicc(int i)
+testicc(int )
 {
+/* TODO: testicc code
 	Mach *mp;
 
 	if((mp = sys->machptr[i]) != nil && mp->online != 0){
@@ -68,6 +68,7 @@
 		mp->icc->fn = testiccfn;
 		mwait(&mp->icc->fn);
 	}
+*/
 }
 
 /*
@@ -77,16 +78,30 @@
 static void
 acstackok(void)
 {
+	panic("acstackok");
+/*
 	char dummy;
 	char *sstart;
 
-	sstart = (char *)m - PGSZ - 4*PTSZ - MACHSTKSZ;
+	sstart = (char *)m - BY2PG - 4*PTSZ - MACHSTKSZ;
 	if(&dummy < sstart + 4*KiB){
 		print("ac kernel stack overflow, cpu%d stopped\n", m->machno);
-		DONE();
+		panic("DONE();");
 	}
+*/
 }
 
+void
+acmmuswitch(void)
+{
+	extern Page mach0pml4;
+
+//	DBG("acmmuswitch mpl4 %#p mach0pml4 %#p m0pml4 %#p\n", m->pml4->pa, mach0pml4.pa, sys->machptr[0]->pml4->pa);
+
+
+panic("	cr3put(m->pml4->pa);");
+}
+
 /*
  * Main scheduling loop done by the application core.
  * Some of functions run will not return.
@@ -112,17 +127,6 @@
 	}
 }
 
-void
-acmmuswitch(void)
-{
-	extern Page mach0pml4;
-
-	DBG("acmmuswitch mpl4 %#p mach0pml4 %#p m0pml4 %#p\n", m->pml4->pa, mach0pml4.pa, sys->machptr[0]->pml4->pa);
-
-
-	cr3put(m->pml4->pa);
-}
-
 /*
  * Beware: up is not set when this function is called.
  */
@@ -164,7 +168,7 @@
 
 	n = nil;
 
-	_pmcupdate(m);
+	//_pmcupdate(m);
 	if(m->proc != nil){
 		m->proc->nactrap++;
 		m->proc->actime1 = fastticks(nil);
@@ -180,23 +184,23 @@
 		}
 	}
 	switch(u->type){
-	case IdtDF:
+	case Vector2F:
 		print("AC: double fault\n");
 		dumpregs(u);
 		ndnr();
-	case IdtIPI:
+	case 62: //IdtIPI:
 		m->intr++;
 		DBG("actrap: cpu%d: IPI\n", m->machno);
-		apiceoi(IdtIPI);
+		apiceoi(62);
 		break;
-	case IdtTIMER:
-		apiceoi(IdtTIMER);
+	case 50: //IdtTIMER:
+		apiceoi(50);
 		panic("timer interrupt in an AC");
 		break;
-	case IdtPF:
+	case VectorPF:
 		/* this case is here for debug only */
 		m->pfault++;
-		DBG("actrap: cpu%d: PF cr2 %#ullx\n", m->machno, cr2get());
+		DBG("actrap: cpu%d: PF cr2 %#ullx\n", m->machno, getcr2());
 		break;
 	default:
 		print("actrap: cpu%d: %ulld\n", m->machno, u->type);
@@ -203,7 +207,7 @@
 	}
 Post:
 	m->icc->rc = ICCTRAP;
-	m->cr2 = cr2get();
+	m->cr2 = getcr2();
 	memmove(m->proc->dbgreg, u, sizeof *u);
 	m->icc->note = n;
 	fpuprocsave(m->proc);
@@ -241,7 +245,7 @@
 	p->actime1 = fastticks(nil);
 	m->syscall++;	/* would also count it in the TS core */
 	m->icc->rc = ICCSYSCALL;
-	m->cr2 = cr2get();
+	m->cr2 = getcr2();
 	fpuprocsave(p);
 	_pmcupdate(m);
 	mfence();
--- a/sys/src/nix/pc64/dat.h
+++ b/sys/src/nix/pc64/dat.h
@@ -27,6 +27,8 @@
 #pragma incomplete Pcidev
 #pragma incomplete Ureg
 
+#include "nix.h"
+
 #define MAXSYSARG	5	/* for mount(fd, afd, mpt, flag, arg) */
 
 /*
--- a/sys/src/nix/pc64/nix.h
+++ b/sys/src/nix/pc64/nix.h
@@ -1,6 +1,42 @@
+typedef struct NIX NIX;
+typedef struct ICC ICC;
+typedef struct ICCparms ICCparms;
+
 typedef struct ACVctl {
 	char*	(*f)(Ureg*,void*);
 	void*	a;
 	int	vno;
 	char	name[KNAMELEN];		/* of driver */
-} ACVctl;
\ No newline at end of file
+} ACVctl;
+
+struct NIX
+{
+	ICC*	icc;			/* inter-core call */
+	int	nixtype;	
+};
+
+/*
+ * Inter core calls
+ */
+enum
+{
+	ICCLNSZ =	128,	/* Cache line size for inter core calls */
+
+
+	ICCOK = 0,		/* Return codes: Ok; trap; syscall */
+	ICCTRAP,
+	ICCSYSCALL
+};
+
+struct ICC
+{
+	/* fn is kept in its own cache line */
+	union{
+		void	(*fn)(void);
+		uchar	_ln1_[ICCLNSZ];
+	};
+	int	flushtlb;	/* on the AC, before running fn */
+	int	rc;		/* return code from AC to TC */
+	char*	note;		/* to be posted in the TC after returning */
+	uchar	data[ICCLNSZ];	/* sent to the AC */
+};
--- a/sys/src/nix/pc64/nixmkfile
+++ b/sys/src/nix/pc64/nixmkfile
@@ -1,1 +1,168 @@
-<mkfile
+CONF=pc64
+CONFLIST=pc64 pccpu64
+
+objtype=amd64
+</$objtype/mkfile
+p=9
+
+# must match mem.h
+KTZERO=0xffffffff80110000
+APBOOTSTRAP=0xffffffff80007000
+REBOOTADDR=0x11000
+
+DEVS=`{rc ../port/mkdevlist $CONF}
+
+PORT=\
+	alarm.$O\
+	alloc.$O\
+	allocb.$O\
+	auth.$O\
+	cache.$O\
+	chan.$O\
+	dev.$O\
+	edf.$O\
+	fault.$O\
+	iomap.$O\
+	memmap.$O\
+	page.$O\
+	parse.$O\
+	pgrp.$O\
+	portclock.$O\
+	print.$O\
+	proc.$O\
+	qio.$O\
+	qlock.$O\
+	random.$O\
+	rdb.$O\
+	rebootcmd.$O\
+	segment.$O\
+	syscallfmt.$O\
+	sysfile.$O\
+	sysproc.$O\
+	taslock.$O\
+	tod.$O\
+	xalloc.$O\
+	userinit.$O\
+
+OBJ=\
+	l.$O\
+	cga.$O\
+	fpu.$O\
+	i8253.$O\
+	i8259.$O\
+	main.$O\
+	memory.$O\
+	mmu.$O\
+	irq.$O\
+	trap.$O\
+	bootargs.$O\
+	$CONF.root.$O\
+	$CONF.rootc.$O\
+	$DEVS\
+	$PORT\
+	acore.$O\
+
+LIB=\
+	/$objtype/lib/libmemlayer.a\
+	/$objtype/lib/libmemdraw.a\
+	/$objtype/lib/libdraw.a\
+	/$objtype/lib/libip.a\
+	/$objtype/lib/libsec.a\
+	/$objtype/lib/libmp.a\
+	/$objtype/lib/libc.a\
+	/$objtype/lib/libfis.a\
+	/$objtype/lib/libaml.a\
+	/$objtype/lib/libdtracy.a\
+
+ETHER=`{cd ../pc; echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
+AUDIO=`{cd ../pc; echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'}
+VGA=`{cd ../pc; echo devvga.c screen.c vga*.c | sed 's/\.c/.'$O'/g'}
+SDEV=`{cd ../pc; echo sd*.c | sed 's/\.c/.'$O'/g'}
+
+$p$CONF:	$OBJ $CONF.$O $LIB
+	$LD -o $target -T$KTZERO -R4096 -l $prereq
+	size $target
+
+install:V:	$p$CONF
+	cp $p$CONF /$objtype/
+	for(i in $EXTRACOPIES)
+		import $i / /n/$i && cp $p$CONF $p$CONF.gz /n/$i/$objtype/
+
+
+# copies generated by the rule below
+PCHEADERS=usbehci.h screen.h mp.h io.h ahci.h \
+	yukdump.h
+
+REPCH=`{echo $PCHEADERS | sed 's/\.h//g; s/ /|/g'}
+^($REPCH)\.h:R:	../pc/\1.h
+	cp $prereq .
+
+REPCC=`{../port/mkfilelist ../pc}
+^($REPCC)\.$O:R:	'../pc/\1.c'
+	$CC $CFLAGS -I. -. ../pc/$stem1.c
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+
+l.$O rebootcode.$O apbootstrap.$O:	mem.h
+
+$ETHER: 			../port/etherif.h ../port/netif.h
+$AUDIO:				../port/audioif.h
+ether8003.$O ether8390.$O:	ether8390.h
+etheryuk.$O:			yukdump.h
+$VGA mouse.$O:			screen.h /sys/include/memdraw.h
+vgavesa.$O:			/386/include/ureg.h
+
+mp.$O:				mp.h apbootstrap.i
+apic.$O squidboy.$O:		mp.h
+archmp.$O archacpi.$O:		mp.h
+
+sd53c8xx.$O:			../pc/sd53c8xx.i
+../pc/sd53c8xx.i:		../pc/sd53c8xx.n
+	cd ../pc && mk sd53c8xx.i
+
+$SDEV pmmc.$O:			../port/sd.h
+sdiahci.$O:			ahci.h
+devaoe.$O sdaoe.$O:		../port/aoe.h
+main.$O:			rebootcode.i
+
+devusb.$O usbuhci.$O usbohci.$O usbehci.$O usbehcipc.$O usbxhci.$O: ../port/usb.h
+usbehci.$O usbehcipc.$O:	usbehci.h
+
+trap.$O main.$O:		/sys/include/tos.h
+
+ether8169.$O:			../port/ethermii.h
+etherdp83820.$O:		../port/ethermii.h
+etherigbe.$O:			../port/ethermii.h
+ethervgbe.$O:			../port/ethermii.h
+ethervt6102.$O:			../port/ethermii.h
+ethervt6105m.$O:		../port/ethermii.h
+
+etherwpi.$O:			../port/wifi.h
+etherrt2860.$O: 		../port/wifi.h
+
+initcode.out:		init9.$O initcode.$O /$objtype/lib/libc.a
+	$LD -l -R1 -s -o $target $prereq
+
+$O.rebootcode:		rebootcode.$O
+	$LD -l -R1 -s -o $target -T$REBOOTADDR $prereq
+rebootcode.out:		$O.rebootcode
+	dd -if $prereq(1) -of $target -bs 1 -iseek 40
+
+$O.apbootstrap:		apbootstrap.$O
+	$LD -l -R1 -s -o $target -T$APBOOTSTRAP $prereq
+apbootstrap.out:	$O.apbootstrap
+	dd -if $prereq(1) -of $target -bs 1 -iseek 40
+
+sd53c8xx.i:	sd53c8xx.n
+	aux/na $prereq > $target
+
+acid:V:
+	$CC -a -w main.c>acid
+
+%.clean:V:
+	rm -f $stem.c [9bz]$stem [9bz]$stem.gz boot$stem.* $O.rebootcode $O.apbootstrap $PCHEADERS
+
+
+
--- /dev/null
+++ b/sys/src/nix/port/portdat.h
@@ -1,0 +1,1049 @@
+typedef struct Alarms	Alarms;
+typedef struct Block	Block;
+typedef struct Chan	Chan;
+typedef struct Cmdbuf	Cmdbuf;
+typedef struct Cmdtab	Cmdtab;
+typedef struct Confmem	Confmem;
+typedef struct Dev	Dev;
+typedef struct Dirtab	Dirtab;
+typedef struct Edf	Edf;
+typedef struct Egrp	Egrp;
+typedef struct Evalue	Evalue;
+typedef struct Fgrp	Fgrp;
+typedef struct DevConf	DevConf;
+typedef struct Image	Image;
+typedef struct Log	Log;
+typedef struct Logflag	Logflag;
+typedef struct Mntcache Mntcache;
+typedef struct Mount	Mount;
+typedef struct Mntrah	Mntrah;
+typedef struct Mntrpc	Mntrpc;
+typedef struct Mntproc	Mntproc;
+typedef struct Mnt	Mnt;
+typedef struct Mhead	Mhead;
+typedef struct Note	Note;
+typedef struct Page	Page;
+typedef struct Path	Path;
+typedef struct Palloc	Palloc;
+typedef struct Perf	Perf;
+typedef struct PhysUart	PhysUart;
+typedef struct Pgrp	Pgrp;
+typedef struct Physseg	Physseg;
+typedef struct Proc	Proc;
+typedef struct Pte	Pte;
+typedef struct PMach	PMach;
+typedef struct QLock	QLock;
+typedef struct Queue	Queue;
+typedef struct Ref	Ref;
+typedef struct Rendez	Rendez;
+typedef struct Rendezq	Rendezq;
+typedef struct Rgrp	Rgrp;
+typedef struct RWlock	RWlock;
+typedef struct Sargs	Sargs;
+typedef struct Schedq	Schedq;
+typedef struct Segment	Segment;
+typedef struct Segio	Segio;
+typedef struct Sema	Sema;
+typedef struct Timer	Timer;
+typedef struct Timers	Timers;
+typedef struct Uart	Uart;
+typedef struct Waitq	Waitq;
+typedef struct Walkqid	Walkqid;
+typedef struct Watchpt	Watchpt;
+typedef struct Watchdog	Watchdog;
+typedef int    Devgen(Chan*, char*, Dirtab*, int, int, Dir*);
+
+#pragma incomplete DevConf
+#pragma incomplete Edf
+#pragma incomplete Mntcache
+#pragma incomplete Mntrpc
+#pragma incomplete Queue
+#pragma incomplete Timers
+
+#include <fcall.h>
+
+struct Ref
+{
+	long	ref;
+};
+
+struct Rendez
+{
+	Lock;
+	Proc	*p;
+};
+
+struct QLock
+{
+	Lock	use;		/* to access Qlock structure */
+	Proc	*head;		/* next process waiting for object */
+	Proc	*tail;		/* last process waiting for object */
+	uintptr	pc;		/* pc of owner */
+	int	locked;		/* flag */
+};
+
+struct Rendezq
+{
+	QLock;
+	Rendez;
+};
+
+struct RWlock
+{
+	Lock	use;
+	Proc	*head;		/* list of waiting processes */
+	Proc	*tail;
+	uintptr	wpc;		/* pc of writer */
+	int	writer;		/* number of writers */
+	int	readers;	/* number of readers */
+};
+
+struct Alarms
+{
+	QLock;
+	Proc	*head;
+};
+
+struct Sargs
+{
+	uchar	args[MAXSYSARG*BY2WD];
+};
+
+/*
+ * Access types in namec & channel flags
+ */
+enum
+{
+	Aaccess,			/* as in stat, wstat */
+	Abind,				/* for left-hand-side of bind */
+	Atodir,				/* as in chdir */
+	Aopen,				/* for i/o */
+	Amount,				/* to be mounted or mounted upon */
+	Acreate,			/* is to be created */
+	Aremove,			/* will be removed by caller */
+	Aunmount,			/* unmount arg[0] */
+
+	COPEN	= 0x0001,		/* for i/o */
+	CMSG	= 0x0002,		/* the message channel for a mount */
+/*rsc	CCREATE	= 0x0004,		/* permits creation if c->mnt */
+	CCEXEC	= 0x0008,		/* close on exec (per file descriptor) */
+	CFREE	= 0x0010,		/* not in use */
+	CRCLOSE	= 0x0020,		/* remove on close */
+	CCACHE	= 0x0080,		/* client cache */
+};
+
+/* flag values */
+enum
+{
+	BINTR	=	(1<<0),
+	BFREE	=	(1<<1),
+	Bipck	=	(1<<2),		/* ip checksum */
+	Budpck	=	(1<<3),		/* udp checksum */
+	Btcpck	=	(1<<4),		/* tcp checksum */
+	Bpktck	=	(1<<5),		/* packet checksum */
+};
+
+struct Block
+{
+	Block*	next;
+	Block*	list;
+	uchar*	rp;			/* first unconsumed byte */
+	uchar*	wp;			/* first empty byte */
+	uchar*	lim;			/* 1 past the end of the buffer */
+	uchar*	base;			/* start of the buffer */
+	void	(*free)(Block*);
+	ushort	flag;
+	ushort	checksum;		/* IP checksum of complete packet (minus media header) */
+};
+
+#define BLEN(s)	((s)->wp - (s)->rp)
+#define BALLOC(s) ((s)->lim - (s)->base)
+
+struct Chan
+{
+	Ref;
+	Lock;
+	Chan*	next;			/* allocation */
+	Chan*	link;
+	vlong	offset;			/* in fd */
+	vlong	devoffset;		/* in underlying device; see read */
+	ushort	type;
+	ulong	dev;
+	ushort	mode;			/* read/write */
+	ushort	flag;
+	Qid	qid;
+	int	fid;			/* for devmnt */
+	ulong	iounit;			/* chunk size for i/o; 0==default */
+	Mhead*	umh;			/* mount point that derived Chan; used in unionread */
+	Chan*	umc;			/* channel in union; held for union read */
+	QLock	umqlock;		/* serialize unionreads */
+	int	uri;			/* union read index */
+	int	dri;			/* devdirread index */
+	uchar*	dirrock;		/* directory entry rock for translations */
+	int	nrock;
+	int	mrock;
+	QLock	rockqlock;
+	int	ismtpt;
+	Mntcache*mcp;			/* Mount cache pointer */
+	Mnt*	mux;			/* Mnt for clients using me for messages */
+	union {
+		void*	aux;
+		ulong	mid;		/* for ns in devproc */
+	};
+	Chan*	mchan;			/* channel to mounted server */
+	Qid	mqid;			/* qid of root of mount point */
+	Path*	path;
+	char*	srvname;		/* /srv/name when posted */
+};
+
+struct Path
+{
+	Ref;
+	char	*s;
+	Chan	**mtpt;			/* mtpt history */
+	int	len;			/* strlen(s) */
+	int	alen;			/* allocated length of s */
+	int	mlen;			/* number of path elements */
+	int	malen;			/* allocated length of mtpt */
+};
+
+struct Dev
+{
+	int	dc;
+	char*	name;
+
+	void	(*reset)(void);
+	void	(*init)(void);
+	void	(*shutdown)(void);
+	Chan*	(*attach)(char*);
+	Walkqid*(*walk)(Chan*, Chan*, char**, int);
+	int	(*stat)(Chan*, uchar*, int);
+	Chan*	(*open)(Chan*, int);
+	Chan*	(*create)(Chan*, char*, int, ulong);
+	void	(*close)(Chan*);
+	long	(*read)(Chan*, void*, long, vlong);
+	Block*	(*bread)(Chan*, long, ulong);
+	long	(*write)(Chan*, void*, long, vlong);
+	long	(*bwrite)(Chan*, Block*, ulong);
+	void	(*remove)(Chan*);
+	int	(*wstat)(Chan*, uchar*, int);
+	void	(*power)(int);	/* power mgt: power(1) => on, power (0) => off */
+	int	(*config)(int, char*, DevConf*);	/* returns nil on error */
+};
+
+struct Dirtab
+{
+	char	name[KNAMELEN];
+	Qid	qid;
+	vlong	length;
+	long	perm;
+};
+
+struct Walkqid
+{
+	Chan	*clone;
+	int	nqid;
+	Qid	qid[1];
+};
+
+struct Mount
+{
+	uvlong	mountid;
+	int	mflag;
+	Mount*	next;
+	Mount*	order;
+	Chan*	to;			/* channel replacing channel */
+	char*	spec;
+};
+
+struct Mhead
+{
+	Ref;
+	RWlock	lock;
+	Chan*	from;			/* channel mounted upon */
+	Mount*	mount;			/* what's mounted upon it */
+	Mhead*	hash;			/* Hash chain */
+};
+
+struct Mntrah
+{
+	Rendez;
+
+	ulong	vers;
+
+	vlong	off;
+	vlong	seq;
+
+	uint	i;
+	Mntrpc	*r[8];
+};
+
+struct Mntproc
+{
+	Rendez;
+
+	Mnt	*m;
+	Mntrpc	*r;
+	void	*a;
+	void	(*f)(Mntrpc*, void*);
+};
+
+struct Mnt
+{
+	Lock;
+	/* references are counted using c->ref; channels on this mount point incref(c->mchan) == Mnt.c */
+	Chan	*c;		/* Channel to file service */
+	Proc	*rip;		/* Reader in progress */
+	Mntrpc	*queue;		/* Queue of pending requests on this channel */
+	Mntproc	defered[8];	/* Worker processes for defered RPCs (read ahead) */
+	ulong	id;		/* Multiplexer id for channel check */
+	Mnt	*list;		/* Free list */
+	int	flags;		/* cache */
+	int	msize;		/* data + IOHDRSZ */
+	char	*version;	/* 9P version */
+	Queue	*q;		/* input queue */
+};
+
+enum
+{
+	NUser,				/* note provided externally */
+	NExit,				/* deliver note quietly */
+	NDebug,				/* print debug message */
+};
+
+struct Note
+{
+	char	msg[ERRMAX];
+	int	flag;			/* whether system posted it */
+	Ref;
+};
+
+enum
+{
+	PG_MOD		= 0x01,		/* software modified bit */
+	PG_REF		= 0x02,		/* software referenced bit */
+	PG_PRIV		= 0x04,		/* private page */
+};
+
+struct Page
+{
+	Ref;
+	Page	*next;			/* Free list or Hash chains */
+	uintptr	pa;			/* Physical address in memory */
+	uintptr	va;			/* Virtual address for user */
+	uintptr	daddr;			/* Disc address on swap */
+	Image	*image;			/* Associated text or swap image */
+	ushort	refage;			/* Swap reference age */
+	char	modref;			/* Simulated modify/reference bits */
+	char	color;			/* Cache coloring */
+
+#ifndef inittxtflush
+	/* Flush icache bitmap for putmmu() */
+	ulong	txtflush[(MAXMACH+31)/32];
+
+#define inittxtflush(p)	memset((p)->txtflush, 0, sizeof((p)->txtflush))
+#define settxtflush(p, c) if(c) memset((p)->txtflush, ~0, sizeof((p)->txtflush))
+#define needtxtflush(p)	((p)->txtflush[m->machno>>5] & (1 << (m->machno&0x1F)))
+#define donetxtflush(p)	((p)->txtflush[m->machno>>5] &= ~(1 << (m->machno&0x1F)))
+#endif
+};
+
+struct Swapalloc
+{
+	Lock;				/* Free map lock */
+	int	free;			/* currently free swap pages */
+	uchar*	swmap;			/* Base of swap map in memory */
+	uchar*	alloc;			/* Round robin allocator */
+	uchar*	last;			/* Speed swap allocation */
+	uchar*	top;			/* Top of swap map */
+	Rendez	r;			/* Pager kproc idle sleep */
+	ulong	highwater;		/* Pager start threshold */
+	ulong	headroom;		/* Space pager frees under highwater */
+	ulong	xref;			/* Ref count for all map refs >= 255 */
+}swapalloc;
+
+struct Pte
+{
+	Page	*pages[PTEPERTAB];	/* Page map for this chunk of pte */
+	Page	**first;		/* First used entry */
+	Page	**last;			/* Last used entry */
+};
+
+/* Segment types */
+enum
+{
+	SG_TYPE		= 07,		/* Mask type of segment */
+	SG_TEXT		= 00,
+	SG_DATA		= 01,
+	SG_BSS		= 02,
+	SG_STACK	= 03,
+	SG_SHARED	= 04,
+	SG_PHYSICAL	= 05,
+	SG_FIXED	= 06,
+	SG_STICKY	= 07,
+
+	SG_RONLY	= 0040,		/* Segment is read only */
+	SG_CEXEC	= 0100,		/* Detach at exec */
+	SG_FAULT	= 0200,		/* Fault on access */
+	SG_CACHED	= 0400,		/* Normal cached memory */
+	SG_DEVICE	= 01000,	/* Memory mapped device */
+	SG_NOEXEC	= 02000,	/* No execute */
+};
+
+#define PG_ONSWAP	1
+#define onswap(s)	(((uintptr)s)&PG_ONSWAP)
+#define pagedout(s)	(((uintptr)s)==0 || onswap(s))
+#define swapaddr(s)	(((uintptr)s)&~PG_ONSWAP)
+
+#define SEGMAXSIZE	(1ULL*SEGMAPSIZE*PTEMAPMEM)
+
+struct Physseg
+{
+	int	attr;			/* Segment attributes */
+	char	*name;			/* Attach name */
+	uintptr	pa;			/* Physical address */
+	uintptr	size;			/* Maximum segment size in bytes */
+};
+
+struct Sema
+{
+	Rendez;
+	long	*addr;
+	int	waiting;
+	Sema	*next;
+	Sema	*prev;
+};
+
+struct Segment
+{
+	Ref;
+	QLock;
+	int	type;		/* segment type */
+	uintptr	base;		/* virtual base */
+	uintptr	top;		/* virtual top */
+	ulong	size;		/* size in pages */
+	uintptr	fstart;		/* start address in file for demand load */
+	uintptr	flen;		/* length of segment in file */
+	int	flushme;	/* maintain icache for this segment */
+	Image	*image;		/* text in file attached to this segment */
+	Physseg *pseg;
+	ulong*	profile;	/* Tick profile area */
+	Pte	**map;
+	int	mapsize;
+	Pte	*ssegmap[SSEGMAPSIZE];
+	Sema	sema;
+	ulong	mark;		/* portcountrefs */
+};
+
+struct Segio
+{
+	QLock;
+	Rendez	cmdwait;
+	Rendez	replywait;
+
+	Proc	*p;		/* segmentio kproc */
+	Segment	*s;
+
+	char	*data;
+	char	*addr;
+	int	dlen;
+	int	cmd;
+	char	*err;
+};
+
+enum
+{
+	RENDLOG	=	5,
+	RENDHASH =	1<<RENDLOG,	/* Hash to lookup rendezvous tags */
+	MNTLOG	=	5,
+	MNTHASH =	1<<MNTLOG,	/* Hash to walk mount table */
+	NFD =		100,		/* per process file descriptors */
+	PGHLOG  =	9,
+	PGHSIZE	=	1<<PGHLOG,	/* Page hash for image lookup */
+	ENVLOG =	5,
+	ENVHASH =	1<<ENVLOG,	/* Egrp hash for variable lookup */
+};
+#define REND(p,s)	((p)->rendhash[(s)&((1<<RENDLOG)-1)])
+#define MOUNTH(p,qid)	((p)->mnthash[(qid).path&((1<<MNTLOG)-1)])
+#define PGHASH(i,daddr)	((i)->pghash[((daddr)>>PGSHIFT)&(PGHSIZE-1)])
+
+struct Image
+{
+	Ref;
+	Lock;
+	Chan	*c;			/* channel to text file, nil when not used */
+	Qid 	qid;			/* Qid for page cache coherence */
+	ulong	dev;			/* Device id of owning channel */
+	ushort	type;			/* Device type of owning channel */
+	char	notext;			/* no file associated */
+	Segment *s;			/* TEXT segment for image if running */
+	Image	*hash;			/* Qid hash chains */
+	Image	*next;			/* Free list */
+	long	pgref;			/* number of cached pages (pgref <= ref) */
+	Page	*pghash[PGHSIZE];	/* page cache */
+};
+
+
+struct Pgrp
+{
+	Ref;
+	RWlock	ns;			/* Namespace n read/one write lock */
+	u64int	notallowed[4];		/* Room for 256 devices */
+	Mhead	*mnthash[MNTHASH];
+};
+
+struct Rgrp
+{
+	Ref;
+	Lock;
+	Proc	*rendhash[RENDHASH];	/* Rendezvous tag hash */
+};
+
+struct Evalue
+{
+	char	*value;
+	int	len;
+	ulong	vers;
+	uvlong	path;			/* qid.path: Egrp.path << 32 | index (of Egrp.ent[]) */
+	Evalue	*hash;
+	char	name[];
+};
+
+struct Egrp
+{
+	Ref;
+	RWlock;
+	Evalue	**ent;
+	int	nent;			/* numer of slots in ent[] */
+	int	low;			/* lowest free index in ent[] */
+	int	alloc;			/* bytes allocated for env */
+	ulong	path;			/* generator for qid path */
+	ulong	vers;			/* of Egrp */
+	Evalue	*hash[ENVHASH];		/* hashtable for name lookup */
+};
+
+struct Fgrp
+{
+	Ref;
+	Lock;
+	Chan	**fd;
+	uchar	*flag;			/* per file-descriptor flags (CCEXEC) */
+	int	nfd;			/* number allocated */
+	int	maxfd;			/* highest fd in use */
+	int	exceed;			/* debugging */
+};
+
+enum
+{
+	DELTAFD	= 20		/* incremental increase in Fgrp.fd's */
+};
+
+struct Palloc
+{
+	Lock;
+	Page	*head;			/* freelist head */
+	ulong	freecount;		/* how many pages on free list now */
+	Page	*pages;			/* array of all pages */
+	ulong	user;			/* how many user pages */
+	Rendezq		pwait[2];	/* Queues of procs waiting for memory */
+};
+
+struct Waitq
+{
+	Waitmsg	w;
+	Waitq	*next;
+};
+
+/*
+ * fasttick timer interrupts
+ */
+enum {
+	/* Mode */
+	Trelative,	/* timer programmed in ns from now */
+	Tperiodic,	/* periodic timer, period in ns */
+};
+
+struct Timer
+{
+	/* Public interface */
+	int	tmode;		/* See above */
+	vlong	tns;		/* meaning defined by mode */
+	void	(*tf)(Ureg*, Timer*);
+	void	*ta;
+	/* Internal */
+	Lock;
+	Mach	*tactive;	/* The cpu that tf is active on */
+	Timers	*tt;		/* Timers queue this timer runs on */
+	Tval	tticks;		/* tns converted to ticks */
+	Tval	twhen;		/* ns represented in fastticks */
+	Timer	*tnext;
+};
+
+enum
+{
+	RFNAMEG		= (1<<0),
+	RFENVG		= (1<<1),
+	RFFDG		= (1<<2),
+	RFNOTEG		= (1<<3),
+	RFPROC		= (1<<4),
+	RFMEM		= (1<<5),
+	RFNOWAIT	= (1<<6),
+	RFCNAMEG	= (1<<10),
+	RFCENVG		= (1<<11),
+	RFCFDG		= (1<<12),
+	RFREND		= (1<<13),
+	RFNOMNT		= (1<<14),
+};
+
+/*
+ *  process memory segments - NSEG always last !
+ */
+enum
+{
+	SSEG, TSEG, DSEG, BSEG, ESEG, LSEG, SEG1, SEG2, SEG3, SEG4, NSEG
+};
+
+enum
+{
+	Dead = 0,		/* Process states */
+	Moribund,
+	New,
+	Ready,
+	Scheding,
+	Running,
+	Queueing,
+	QueueingR,
+	QueueingW,
+	Wakeme,
+	Broken,
+	Stopped,
+	Rendezvous,
+	Waitrelease,
+
+	Proc_stopme = 1, 	/* devproc requests */
+	Proc_exitme,
+	Proc_traceme,
+	Proc_exitbig,
+	Proc_tracesyscall,
+
+	TUser = 0, 		/* Proc.time */
+	TSys,
+	TReal,
+	TCUser,
+	TCSys,
+	TCReal,
+
+	NERR = 32,
+	NNOTE = 5,
+
+	Npriq		= 20,		/* number of scheduler priority levels */
+	Nrq		= Npriq+2,	/* number of priority levels including real time */
+	PriRelease	= Npriq,	/* released edf processes */
+	PriEdf		= Npriq+1,	/* active edf processes */
+	PriNormal	= 10,		/* base priority for normal processes */
+	PriExtra	= Npriq-1,	/* edf processes at high best-effort pri */
+	PriKproc	= 13,		/* base priority for kernel processes */
+	PriRoot		= 13,		/* base priority for root processes */
+};
+
+struct Schedq
+{
+	Lock;
+	Proc*	head;
+	Proc*	tail;
+	int	n;
+};
+
+struct Proc
+{
+	Label	sched;		/* known to l.s */
+
+	Mach	*mach;		/* machine running this proc */
+	char	*text;
+	char	*user;
+
+	char	*args;
+	int	nargs;		/* number of bytes of args */
+	int	setargs;	/* process changed its args */
+
+	Proc	*rnext;		/* next process in run queue */
+	Proc	*qnext;		/* next process on queue for a QLock */
+
+	char	*psstate;	/* What /proc/#/status reports */
+	int	state;
+
+	ulong	pid;
+	ulong	noteid;		/* Equivalent of note group */
+	ulong	parentpid;
+	ulong	index;
+
+	Proc	*parent;	/* Process to send wait record on exit */
+	Lock	exl;		/* Lock count and waitq */
+	Waitq	*waitq;		/* Exited processes wait children */
+	int	nchild;		/* Number of living children */
+	int	nwait;		/* Number of uncollected wait records */
+	QLock	qwaitr;
+	Rendez	waitr;		/* Place to hang out in wait */
+
+	QLock	seglock;	/* locked whenever seg[] changes */
+	Segment	*seg[NSEG];
+
+	Pgrp	*pgrp;		/* Process group for namespace */
+	Egrp 	*egrp;		/* Environment group */
+	Fgrp	*fgrp;		/* File descriptor group */
+	Rgrp	*rgrp;		/* Rendez group */
+
+	Fgrp	*closingfgrp;	/* used during teardown */
+
+	int	insyscall;
+	ulong	time[6];	/* User, Sys, Real; child U, S, R */
+
+	uvlong	kentry;		/* Kernel entry time stamp (for profiling) */
+	/*
+	 * pcycles: cycles spent in this process (updated on procswitch)
+	 * when this is the current proc and we're in the kernel
+	 * (procrestores outnumber procsaves by one)
+	 * the number of cycles spent in the proc is pcycles + cycles()
+	 * when this is not the current process or we're in user mode
+	 * (procrestores and procsaves balance), it is pcycles.
+	 */
+	vlong	pcycles;
+
+	QLock	debug;		/* to access debugging elements of User */
+	Proc	*pdbg;		/* the debugging process */
+	ulong	procmode;	/* proc device default file mode */
+	int	privatemem;	/* proc does not let anyone read mem */
+	int	noswap;		/* process is not swappable */
+	int	hang;		/* hang at next exec for debug */
+	int	procctl;	/* Control for /proc debugging */
+	uintptr	pc;		/* DEBUG only */
+
+	Lock	rlock;		/* sync sleep/wakeup with procinterrupt */
+	Rendez	*r;		/* rendezvous point slept on */
+	Rendez	sleep;		/* place for syssleep/debug */
+	int	notepending;	/* note issued but not acted on */
+	int	kp;		/* true if a kernel process */
+	Proc	*palarm;	/* Next alarm time */
+	ulong	alarm;		/* Time of call */
+	int	newtlb;		/* Pager has changed my pte's, I must flush */
+
+	uintptr	rendtag;	/* Tag for rendezvous */
+	uintptr	rendval;	/* Value for rendezvous */
+	Proc	*rendhash;	/* Hash list for tag values */
+
+	Timer;			/* For tsleep and real-time */
+	Rendez	*trend;
+	int	(*tfn)(void*);
+	void	(*kpfun)(void*);
+	void	*kparg;
+
+	Sargs	s;		/* syscall arguments */
+	int	scallnr;	/* sys call number */
+	int	nerrlab;
+	Label	errlab[NERR];
+	char	*syserrstr;	/* last error from a system call, errbuf0 or 1 */
+	char	*errstr;	/* reason we're unwinding the error stack, errbuf1 or 0 */
+	char	errbuf0[ERRMAX];
+	char	errbuf1[ERRMAX];
+	char	genbuf[128];	/* buffer used e.g. for last name element from namec */
+	Chan	*slash;
+	Chan	*dot;
+
+	Note	*lastnote;
+	Note	*note[NNOTE];
+	short	nnote;
+	short	notified;	/* sysnoted is due */
+	int	(*notify)(void*, char*);
+
+	Mach	*wired;
+	Mach	*mp;		/* machine this process last ran on */
+
+	Lock	*lastlock;	/* debugging */
+	Lock	*lastilock;	/* debugging */
+
+	int	nlocks;		/* number of locks held by proc */
+
+	ulong	delaysched;
+	ulong	priority;	/* priority level */
+	ulong	basepri;	/* base priority level */
+	uchar	fixedpri;	/* priority level doesn't change */
+	ulong	cpu;		/* cpu average */
+	ulong	lastupdate;
+	uchar	yield;		/* non-zero if the process just did a sleep(0) */
+	int	preempted;	/* true if this process hasn't finished the interrupt
+				 *  that last preempted it
+				 */
+	Edf	*edf;		/* if non-null, real-time proc, edf contains scheduling params */
+	int	trace;		/* process being traced? */
+
+	uintptr	qpc;		/* pc calling last blocking qlock */
+	QLock	*eql;		/* interruptable eqlock */
+
+	void	*ureg;		/* User registers for notes */
+	void	*dbgreg;	/* User registers for devproc */
+
+	PFPU;			/* machine specific fpu state */
+	PMMU;			/* machine specific mmu state */
+
+	char	*syscalltrace;	/* syscall trace */
+	
+	Watchpt	*watchpt;	/* watchpoints */
+	int	nwatchpt;
+
+	/* NIX */
+	uvlong nactrap;
+	uvlong actime;
+	uvlong actime1;
+};
+
+enum
+{
+	PRINTSIZE =	256,
+	NUMSIZE	=	12,		/* size of formatted number */
+	MB =		(1024*1024),
+	/* READSTR was 1000, which is way too small for usb's ctl file */
+	READSTR =	8000,		/* temporary buffer size for device reads */
+};
+
+extern	Conf	conf;
+extern	char*	conffile;
+extern	int	cpuserver;
+extern	Dev*	devtab[];
+extern	char*	eve;
+extern	char	hostdomain[];
+extern	uchar	initcode[];
+extern	Queue*	kprintoq;
+extern	int	nsyscall;
+extern	Palloc	palloc;
+extern	int	panicking;
+extern	Queue*	serialoq;
+extern	char*	statename[];
+extern	Image	swapimage;
+extern	Image	fscache;
+extern	char*	sysname;
+extern	uint	qiomaxatomic;
+extern	char*	sysctab[];
+
+enum
+{
+	LRESPROF	= 3,
+};
+
+/*
+ *  action log
+ */
+struct Log {
+	Lock;
+	int	opens;
+	char*	buf;
+	char	*end;
+	char	*rptr;
+	int	len;
+	int	nlog;
+	int	minread;
+
+	int	logmask;	/* mask of things to debug */
+
+	QLock	readq;
+	Rendez	readr;
+};
+
+struct Logflag {
+	char*	name;
+	int	mask;
+};
+
+enum
+{
+	NCMDFIELD = 128
+};
+
+struct Cmdbuf
+{
+	char	*buf;
+	char	**f;
+	int	nf;
+};
+
+struct Cmdtab
+{
+	int	index;	/* used by client to switch on result */
+	char	*cmd;	/* command name */
+	int	narg;	/* expected #args; 0 ==> variadic */
+};
+
+/*
+ *  routines to access UART hardware
+ */
+struct PhysUart
+{
+	char*	name;
+	Uart*	(*pnp)(void);
+	void	(*enable)(Uart*, int);
+	void	(*disable)(Uart*);
+	void	(*kick)(Uart*);
+	void	(*dobreak)(Uart*, int);
+	int	(*baud)(Uart*, int);
+	int	(*bits)(Uart*, int);
+	int	(*stop)(Uart*, int);
+	int	(*parity)(Uart*, int);
+	void	(*modemctl)(Uart*, int);
+	void	(*rts)(Uart*, int);
+	void	(*dtr)(Uart*, int);
+	long	(*status)(Uart*, void*, long, long);
+	void	(*fifo)(Uart*, int);
+	void	(*power)(Uart*, int);
+	int	(*getc)(Uart*);	/* polling versions, for iprint, rdb */
+	void	(*putc)(Uart*, int);
+};
+
+enum {
+	Stagesize=	2048
+};
+
+/*
+ *  software UART
+ */
+struct Uart
+{
+	void*	regs;			/* hardware stuff */
+	void*	saveregs;		/* place to put registers on power down */
+	char*	name;			/* internal name */
+	ulong	freq;			/* clock frequency */
+	int	bits;			/* bits per character */
+	int	stop;			/* stop bits */
+	int	parity;			/* even, odd or no parity */
+	int	baud;			/* baud rate */
+	PhysUart*phys;
+	int	console;		/* used as a serial console */
+	int	special;		/* internal kernel device */
+	Uart*	next;			/* list of allocated uarts */
+
+	QLock;
+	int	type;			/* ?? */
+	int	dev;
+	int	opens;
+
+	int	enabled;
+	Uart	*elist;			/* next enabled interface */
+
+	int	perr;			/* parity errors */
+	int	ferr;			/* framing errors */
+	int	oerr;			/* rcvr overruns */
+	int	berr;			/* no input buffers */
+	int	serr;			/* input queue overflow */
+
+	/* buffers */
+	int	(*putc)(Queue*, int);
+	Queue	*iq;
+	Queue	*oq;
+
+	Lock	rlock;
+	uchar	istage[Stagesize];
+	uchar	*iw;
+	uchar	*ir;
+	uchar	*ie;
+
+	Lock	tlock;			/* transmit */
+	uchar	ostage[Stagesize];
+	uchar	*op;
+	uchar	*oe;
+	int	drain;
+
+	int	modem;			/* hardware flow control on */
+	int	xonoff;			/* software flow control on */
+	int	blocked;
+	int	cts, dsr, dcd;	/* keep track of modem status */ 
+	int	ctsbackoff;
+	int	hup_dsr, hup_dcd;	/* send hangup upstream? */
+	int	dohup;
+
+	Rendez	r;
+};
+
+extern	Uart*	consuart;
+
+/*
+ *  performance timers, all units in perfticks
+ */
+struct Perf
+{
+	ulong	intrts;		/* time of last interrupt */
+	ulong	inintr;		/* time since last clock tick in interrupt handlers */
+	ulong	avg_inintr;	/* avg time per clock tick in interrupt handlers */
+	ulong	inidle;		/* time since last clock tick in idle loop */
+	ulong	avg_inidle;	/* avg time per clock tick in idle loop */
+	ulong	last;		/* value of perfticks() at last clock tick */
+	ulong	period;		/* perfticks() per clock tick */
+};
+
+struct Watchdog
+{
+	void	(*enable)(void);	/* watchdog enable */
+	void	(*disable)(void);	/* watchdog disable */
+	void	(*restart)(void);	/* watchdog restart */
+	void	(*stat)(char*, char*);	/* watchdog statistics */
+};
+
+struct Watchpt
+{
+	enum {
+		WATCHRD = 1,
+		WATCHWR = 2,
+		WATCHEX = 4,
+	} type;
+	uintptr addr, len;
+};
+
+struct PMach
+{
+	Proc*	readied;		/* for runproc */
+	Label	sched;			/* scheduler wakeup */
+	ulong	ticks;			/* of the clock since boot time */
+	ulong	schedticks;		/* next forced context switch */
+
+	int	pfault;
+	int	cs;
+	int	syscall;
+	int	load;
+	int	intr;
+	int	ilockdepth;
+
+	int	flushmmu;		/* make current proc flush it's mmu state */
+
+	int	tlbfault;
+	int	tlbpurge;
+
+	Perf	perf;			/* performance counters */
+
+	uvlong	cyclefreq;		/* Frequency of user readable cycle counter */
+};
+
+/* queue state bits,  Qmsg, Qcoalesce, and Qkick can be set in qopen */
+enum
+{
+	/* Queue.state */
+	Qstarve		= (1<<0),	/* consumer starved */
+	Qmsg		= (1<<1),	/* message stream */
+	Qclosed		= (1<<2),	/* queue has been closed/hungup */
+	Qflow		= (1<<3),	/* producer flow controlled */
+	Qcoalesce	= (1<<4),	/* coallesce packets on read */
+	Qkick		= (1<<5),	/* always call the kick routine after qwrite */
+};
+
+#define DEVDOTDOT -1
+
+#pragma	varargck	type	"I"	uchar*
+#pragma	varargck	type	"V"	uchar*
+#pragma	varargck	type	"E"	uchar*
+#pragma	varargck	type	"M"	uchar*
+
+/*
+ * Log console output so it can be retrieved via /dev/kmesg.
+ * This is good for catching boot-time messages after the fact.
+ */
+struct {
+	Lock lk;
+	uint n;
+	char buf[16384];
+} kmesg;