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;