ref: 9b8e21a6669c6312809b174220fca59728cbb68b
parent: 775400b52c5b473fe1528f3e31283fcfb730c18a
author: halfwit <michaelmisch1985@gmail.com>
date: Sat Jul 27 10:22:01 PDT 2024
Changes to facilitate mem.h and exec
--- a/Make.dragonfly
+++ b/Make.dragonfly
@@ -13,6 +13,7 @@
LDFLAGS=$(PTHREAD)
TARG=drawcpu
AUDIO=none
+ARCH=$(shell uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/')
all: default
--- a/Make.fbdev
+++ b/Make.fbdev
@@ -14,6 +14,7 @@
TARG=drawcpu
# AUDIO=none
AUDIO=alsa
+ARCH=$(shell uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/; s/armv[567].*/arm/; s/aarch64/arm64/')
all: default
--- a/Make.freebsd
+++ b/Make.freebsd
@@ -13,6 +13,7 @@
LDFLAGS=$(PTHREAD)
TARG=drawcpu
AUDIO=unix
+ARCH=$(shell uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/')
all: default
--- a/Make.irix
+++ b/Make.irix
@@ -17,6 +17,7 @@
LDFLAGS=$(PTHREAD)
TARG=drawcpu
MAKE=gmake
+ARCH=mips
all: default
--- a/Make.linux
+++ b/Make.linux
@@ -13,6 +13,7 @@
TARG=drawcpu
# AUDIO=none
AUDIO=pipewire
+ARCH=$(shell uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/; s/armv[567].*/arm/; s/aarch64/arm64/')
all: default
--- a/Make.linux386
+++ b/Make.linux386
@@ -14,6 +14,7 @@
TARG=drawcpu
# AUDIO=none
AUDIO=unix
+ARCH=386
all: default
--- a/Make.netbsd
+++ b/Make.netbsd
@@ -13,6 +13,7 @@
LDFLAGS=$(PTHREAD)
TARG=drawcpu
AUDIO=unix
+ARCH=$(shell uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/')
all: default
--- a/Make.openbsd
+++ b/Make.openbsd
@@ -12,6 +12,7 @@
LDFLAGS=$(PTHREAD)
TARG=drawcpu
AUDIO=sndio
+ARCH=$(shell uname -m|sed 's/i.86/386/; s/macppc/power/; s/socppc/power/; s/x86_64/amd64/; s/sparc64/sun4u/')
all: default
--- a/Make.osx-cocoa
+++ b/Make.osx-cocoa
@@ -12,6 +12,7 @@
LDFLAGS=$(PTHREAD)
TARG=drawcpu
AUDIO=none
+ARCH=$(shell uname -m|sed 's/i.86/386/;s/x86_64/amd64/')
all: default
--- a/Make.pthread
+++ b/Make.pthread
@@ -15,6 +15,7 @@
TARG=drawcpu
# AUDIO=none
AUDIO=unix
+ARCH=$(shell uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/; s/armv[567].*/arm/; s/aarch64/arm64/')
all: default
--- a/Make.unix
+++ b/Make.unix
@@ -15,6 +15,7 @@
TARG=drawcpu
# AUDIO=none
AUDIO=unix
+ARCH=$(shell uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/; s/armv[567].*/arm/; s/aarch64/arm64/')
all: default
--- a/Make.win32
+++ b/Make.win32
@@ -30,6 +30,7 @@
#IP=win32
#OS=win32
#GUI=win32
+ARCH=386
all: default
--- a/Make.win64
+++ b/Make.win64
@@ -20,6 +20,7 @@
LDADD=-lgdi32 -lws2_32 -lwinmm -mwindows
TARG=drawcpu.exe
XOFILES=glenda-t.$O
+ARCH=386
all: default
--- a/TODO
+++ b/TODO
@@ -1,10 +1,12 @@
TODO:
+ - [ ] Look into args address space prior to hitting exec
+ - [ ] /env/fn# to init functions?
- [ ] set up initial connection before handing over to an rc session, to set up binds and mounts
- - [x] remove rc builtins
- - [ ] Import $objtype/bin from 9front instead of builtins
- - [ ] Adapt github.com/michaelforney/nine to load and execute our binaries --> into the rc code for exec, instead of what they have
- - [ ] Check the magic, run a normal exec if it's not a plan9 or p9p binary, or try wrapping everything we run
+ - [ ] Import our $objtype/bin and /rc from 9front instead of builtins, -f $9filesys
+ - [x] remove rc builtins, possibly add os() as it uses devcmd locally, if needed
+ - [ ] Adapt github.com/michaelforney/nine to load and execute our binaries (exec)
- [x] start.s in libmachdep for each posix-target, just do like tas.c
+ - investigate if we want to run this another way instead!
- [ ] darwin will use mach_vm_-family of functions, else we use mmap
- [ ] have it export a var service=unix
- [ ] Some people probably want aan?
--- /dev/null
+++ b/include/a.out.h
@@ -1,0 +1,48 @@
+typedef struct Exec Exec;
+struct Exec
+{
+ long magic; /* magic number */
+ long text; /* size of text segment */
+ long data; /* size of initialized data */
+ long bss; /* size of uninitialized data */
+ long syms; /* size of symbol table */
+ long entry; /* entry point */
+ long spsz; /* size of pc/sp offset table */
+ long pcsz; /* size of pc/line number table */
+};
+
+#define HDR_MAGIC 0x00008000 /* header expansion */
+
+#define _MAGIC(f, b) ((f)|((((4*(b))+0)*(b))+7))
+#define A_MAGIC _MAGIC(0, 8) /* 68020 */
+#define I_MAGIC _MAGIC(0, 11) /* intel 386 */
+#define J_MAGIC _MAGIC(0, 12) /* intel 960 (retired) */
+#define K_MAGIC _MAGIC(0, 13) /* sparc */
+#define V_MAGIC _MAGIC(0, 16) /* mips 3000 BE */
+#define X_MAGIC _MAGIC(0, 17) /* att dsp 3210 (retired) */
+#define M_MAGIC _MAGIC(0, 18) /* mips 4000 BE */
+#define D_MAGIC _MAGIC(0, 19) /* amd 29000 (retired) */
+#define E_MAGIC _MAGIC(0, 20) /* arm */
+#define Q_MAGIC _MAGIC(0, 21) /* powerpc */
+#define N_MAGIC _MAGIC(0, 22) /* mips 4000 LE */
+#define L_MAGIC _MAGIC(0, 23) /* dec alpha (retired) */
+#define P_MAGIC _MAGIC(0, 24) /* mips 3000 LE */
+#define U_MAGIC _MAGIC(0, 25) /* sparc64 */
+#define S_MAGIC _MAGIC(HDR_MAGIC, 26) /* amd64 */
+#define T_MAGIC _MAGIC(HDR_MAGIC, 27) /* powerpc64 */
+#define R_MAGIC _MAGIC(HDR_MAGIC, 28) /* arm64 */
+
+#define MIN_MAGIC 8
+#define MAX_MAGIC 28 /* <= 90 */
+
+#define DYN_MAGIC 0x80000000 /* dlm */
+
+typedef struct Sym Sym;
+struct Sym
+{
+ vlong value;
+ uint sig;
+ char type;
+ char *name;
+};
+
--- a/include/u.h
+++ b/include/u.h
@@ -10,9 +10,11 @@
#undef close
#undef create
#undef dup
+#undef exec
#undef export
#undef fstat
#undef fwstat
+#undef memchr
#undef mount
#undef open
#undef start
--- a/include/user.h
+++ b/include/user.h
@@ -1,4 +1,4 @@
-/* sys calls */
+/* sys calls */
#define bind sysbind
#define chdir syschdir
#define close sysclose
@@ -5,11 +5,13 @@
#define create syscreate
#define dup sysdup
#define export sysexport
+#define exec sysexec
#define getwd sysgetwd
#define fd2path sysfd2path
#define fstat sysfstat
#define fwstat sysfwstat
#define mount sysmount
+#define memchr sysmemchr
#define open sysopen
#define read sysread
#define remove sysremove
@@ -38,10 +40,12 @@
extern int create(char*, int, ulong);
extern int dup(int, int);
extern int export(int);
+extern int exec(va_list);
extern int fd2path(int, char*, int);
extern int fstat(int, uchar*, int);
extern int fwstat(int, uchar*, int);
extern char* getwd(char *, int);
+extern void* memchr(void *, int, ulong);
extern int mount(int, int, char*, int, char*);
extern int unmount(char*, char*);
extern int open(char*, int);
--- a/kern/Makefile
+++ b/kern/Makefile
@@ -23,6 +23,7 @@
dirread.$O\
error.$O\
getwd.$O\
+ memchr.$O\
parse.$O\
pgrp.$O\
postnote.$O\
@@ -33,6 +34,7 @@
sleep.$O\
stub.$O\
sysfile.$O\
+ sysproc.$O\
time.$O\
qio.$O\
qlock.$O\
@@ -46,5 +48,5 @@
$(RANLIB) $(LIB)
%.$O: %.c
- $(CC) $(CFLAGS) $*.c
+ $(CC) $(CFLAGS) -I../$(OS)-$(ARCH) $*.c
--- a/kern/allocb.c
+++ b/kern/allocb.c
@@ -3,6 +3,7 @@
#include "dat.h"
#include "fns.h"
#include "error.h"
+#include "mem.h"
enum
{
--- a/kern/dat.h
+++ b/kern/dat.h
@@ -1,6 +1,6 @@
#define KNAMELEN 28 /* max length of name held in kernel */
-#define BLOCKALIGN 8
+//#define BLOCKALIGN 8
typedef struct Block Block;
typedef struct Chan Chan;
@@ -29,6 +29,7 @@
typedef struct Ref Ref;
typedef struct Rendez Rendez;
typedef struct Rgrp Rgrp;
+typedef struct Segment Segment;
typedef struct RWlock RWlock;
typedef struct Waitq Waitq;
typedef struct Walkqid Walkqid;
@@ -347,6 +348,45 @@
Wakeme,
};
+/* 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 */
+};
+
+/*
+ * process memory segments - NSEG always last !
+ */
+enum
+{
+ SSEG, TSEG, DSEG, BSEG, ESEG, LSEG, SEG1, SEG2, SEG3, SEG4, NSEG
+};
+
+struct Segment
+{
+ QLock ql;
+ int type; /* segment type */
+ uintptr base; /* virtual base */
+ uintptr top; /* virtual top */
+ ulong size; /* size in pages */
+ int fd;
+};
+
struct Proc
{
uint state;
@@ -367,6 +407,9 @@
void* rendtag; /* Tag for rendezvous */
void* rendval; /* Value for rendezvous */
Proc *rendhash; /* Hash list for tag values */
+
+ QLock seglock; /* locked whenever seg[] changes */
+ Segment *seg[NSEG];
int nerrlab;
Label errlab[NERR];
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -1,4 +1,4 @@
-#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
+//#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
Block* adjustblock(Block*, int);
Block* allocb(int);
@@ -198,6 +198,9 @@
void setrealloctag(void*, uintptr);
long showfilewrite(char*, int);
char* skipslash(char*);
+Segment* dupseg(Segment**, int, int);
+Segment* newseg(int, uintptr, ulong);
+Segment* seg(Proc*, uintptr, int);
void sleep(Rendez*, int(*)(void*), void*);
void* smalloc(ulong);
int splhi(void);
@@ -206,11 +209,11 @@
Block* trimblock(Block*, int, int);
long unionread(Chan*, void*, long);
void unlock(Lock*);
-#define validaddr(a, b, c)
+void validaddr(uintptr, ulong, int);
void validname(char*, int);
char* validnamedup(char*, int);
void validstat(uchar*, int);
-void* vmemchr(void*, int, int);
+void* vmemchr(void*, int, ulong);
Proc* wakeup(Rendez*);
int walk(Chan**, char**, int, int, int*);
#define waserror() (setjmp(pwaserror()->buf))
--- /dev/null
+++ b/kern/memchr.c
@@ -1,0 +1,21 @@
+#include <u.h>
+#include <libc.h>
+
+void*
+sysmemchr(void *ap, int c, ulong n)
+{
+ uchar *sp;
+ ulong i;
+
+ i = n;
+
+ sp = (uchar *)ap;
+ c &= 0xFF;
+ while(i > 0) {
+ printf("%d %d %c\n", c, i, *sp);
+ if(*sp++ == c)
+ return sp-1;
+ i--;
+ }
+ return 0;
+}
\ No newline at end of file
--- a/kern/posix.c
+++ b/kern/posix.c
@@ -13,6 +13,7 @@
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/select.h>
+#include <sys/mman.h>
#include <signal.h>
#include <pwd.h>
#include <errno.h>
@@ -21,6 +22,7 @@
#include "lib.h"
#include "dat.h"
#include "fns.h"
+#include "mem.h"
typedef struct Oproc Oproc;
struct Oproc
@@ -324,3 +326,33 @@
t.c_lflag |= (ECHO|ICANON);
tcsetattr(0, TCSAFLUSH, &t);
}
+
+Segment *
+newseg(int type, uintptr base, ulong size)
+{
+ Segment *s;
+ int fd;
+
+ // NOTE: This path may not be perfectly portable
+ fd = shm_open("drawcpu", O_CREAT | O_RDWR, 0600);
+ if(fd < 0)
+ error("shm_open failed");
+
+ if(ftruncate(fd, size) < 0)
+ error("truncate failed");
+
+ // tidy up the fs entry
+ shm_unlink("drawcpu");
+
+ s = malloc(sizeof(Segment));
+ if(s == nil)
+ error("out of memory");
+
+ s->type = type;
+ s->base = base;
+ s->size = size;
+ s->top = base+(size*BY2WD);
+ s->fd = fd;
+
+ return s;
+}
\ No newline at end of file
--- a/kern/procinit.c
+++ b/kern/procinit.c
@@ -3,6 +3,7 @@
#include "dat.h"
#include "fns.h"
#include "error.h"
+#include "mem.h"
void
procinit0(void)
@@ -34,6 +35,13 @@
p->syserrstr = p->errbuf0;
p->errstr = p->errbuf1;
strcpy(p->text, "drawcpu");
+ p->seg[SSEG] = newseg(SG_STACK | SG_NOEXEC, USTKTOP-USTKSIZE, USTKSIZE / BY2PG);
+ p->seg[TSEG] = newseg(SG_TEXT | SG_RONLY, UTZERO, 1);
+
+ // See /sys/src/9/port/userinit.c
+ //page = newpage(1, 0, UTZERO);
+ // [...]
+ //segpage(p->seg[TSEG], p);
osnewproc(p);
return p;
}
--- a/kern/sysfile.c
+++ b/kern/sysfile.c
@@ -19,6 +19,10 @@
#undef fwstat
#undef iounit
+// NOTE: We don't use the kernel segments outside of exec
+#undef validaddr
+#define validaddr(a, b, c)
+
/*
* The sys*() routines needn't poperror() as they return directly to syscall().
*/
@@ -293,8 +297,8 @@
return fd;
}
-static void
-_fdclose(int fd, int flag)
+void
+fdclose(int fd, int flag)
{
int i;
Chan *c;
@@ -326,7 +330,7 @@
_sysclose(int fd)
{
fdtochan(fd, -1, 0, 0);
- _fdclose(fd, 0);
+ fdclose(fd, 0);
return 0;
}
@@ -589,7 +593,7 @@
uint l;
l = n;
- validaddr(buf, l, 1);
+ validaddr((uintptr)buf, l, 1);
c = fdtochan(fd, -1, 0, 1);
if(waserror()) {
cclose(c);
@@ -608,8 +612,8 @@
uint l;
l = n;
- validaddr(buf, l, 1);
- validaddr(name, 1, 0);
+ validaddr((uintptr)buf, l, 1);
+ validaddr((uintptr)name, 1, 0);
c = namec(name, Aaccess, 0, 0);
if(waserror()){
cclose(c);
@@ -626,7 +630,7 @@
{
Chan *c;
- validaddr(name, 1, 0);
+ validaddr((uintptr)name, 1, 0);
c = namec(name, Atodir, 0, 0);
cclose(up->dot);
@@ -696,7 +700,7 @@
poperror();
cclose(c0);
if(ismount){
- _fdclose(fd, 0);
+ fdclose(fd, 0);
poperror();
free(spec);
}
@@ -729,7 +733,7 @@
cclose(cmount);
nexterror();
}
- validaddr(old, 1, 0);
+ validaddr((uintptr)old, 1, 0);
/*
* This has to be namec(..., Aopen, ...) because
* if arg[0] is something like /srv/cs or /fd/0,
@@ -767,7 +771,7 @@
cclose(c);
nexterror();
}
- validaddr(name, 1, 0);
+ validaddr((uintptr)name, 1, 0);
c = namec(name, Acreate, mode, perm);
fd = newfd(c);
if(fd < 0)
@@ -806,7 +810,7 @@
l = n;
validstat(buf, l);
- validaddr(name, 1, 0);
+ validaddr((uintptr)name, 1, 0);
c = namec(name, Aaccess, 0, 0);
if(waserror()){
cclose(c);
@@ -825,7 +829,7 @@
uint l;
l = n;
- validaddr(buf, l, 0);
+ validaddr((uintptr)buf, l, 0);
validstat(buf, l);
c = fdtochan(fd, -1, 1, 1);
if(waserror()) {
--- /dev/null
+++ b/kern/sysproc.c
@@ -1,0 +1,306 @@
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "user.h"
+#include "mem.h"
+#include <a.out.h>
+
+static int
+shargs(char *s, int n, char **ap, int nap)
+{
+ char *p;
+ int i;
+
+ if(n <= 2 || s[0] != '#' || s[1] != '!')
+ return -1;
+ s += 2;
+ n -= 2; /* skip #! */
+ if((p = memchr(s, '\n', n)) == nil)
+ return 0;
+ *p = 0;
+ i = tokenize(s, ap, nap-1);
+ ap[i] = nil;
+ return i;
+}
+
+ulong
+beswal(ulong l)
+{
+ uchar *p;
+
+ p = (uchar*)&l;
+ return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
+}
+
+uvlong
+beswav(uvlong v)
+{
+ uchar *p;
+
+ p = (uchar*)&v;
+ return ((uvlong)p[0]<<56) | ((uvlong)p[1]<<48) | ((uvlong)p[2]<<40)
+ | ((uvlong)p[3]<<32) | ((uvlong)p[4]<<24)
+ | ((uvlong)p[5]<<16) | ((uvlong)p[6]<<8)
+ | (uvlong)p[7];
+}
+
+void
+evenaddr(uintptr addr)
+{
+ if(addr & 3){
+ postnote(up, 1, "sys: odd address", NDebug);
+ error(Ebadarg);
+ }
+}
+
+Segment *
+seg(Proc *p, uintptr addr, int dolock)
+{
+ Segment **s, **et, *n;
+
+ et = &p->seg[NSEG];
+ for(s = p->seg; s < et; s++) {
+ if((n = *s) == nil)
+ continue;
+ print("Here %x %x %x\n", addr, n->base, n->top);
+ if(addr >= n->base && addr < n->top) {
+ if(dolock == 0)
+ return n;
+
+ qlock(&n->ql);
+ if(addr >= n->base && addr < n->top)
+ return n;
+ qunlock(&n->ql);
+ }
+ }
+
+ return nil;
+}
+
+int
+okaddr(uintptr addr, ulong len, int wr)
+{
+ Segment *s;
+
+ if((long)len >= 0 && len <= -addr)
+ for(;;) {
+ s = seg(up, addr, 0);
+ if(s == nil)
+ print("Nil seg\n");
+ if(s == nil || (wr && (s->type&SG_RONLY)))
+ break;
+ print("Here\n");
+ if((ulong)addr+len > s->top) {
+ len -= s->top - (ulong)addr;
+ addr = s->top;
+ print("Looping\n");
+ continue;
+ }
+ print("Good!\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+validaddr(uintptr addr, ulong len, int wr)
+{
+ if(!okaddr(addr, len, wr)) {
+ pprint("suicide: invalid address\n");
+ postnote(up, 1, "sys: bad address in syscall", NDebug);
+ error(Ebadarg);
+ }
+}
+
+/*
+ * &s[0] is known to be a valid address.
+ */
+void*
+vmemchr(void *s, int c, ulong n)
+{
+ uintptr a;
+ ulong m, i;
+ void *t;
+
+ i = n;
+ a = (uintptr)s;
+ for(;;){
+ m = BY2PG - (a & (BY2PG-1));
+ if(i <= m)
+ break;
+ /* spans pages; handle this page */
+ t = memchr((void*)a, c, m);
+ if(t != nil)
+ return t;
+ a += m;
+ i -= m;
+ if(a < KZERO)
+ validaddr(a, 1, 0);
+ }
+print(" returning\n");
+ /* fits in one page */
+ return memchr((void*)a, c, i);
+}
+
+#undef read
+int
+sysexec(va_list list)
+{
+ union {
+ struct {
+ Exec ex;
+ uvlong hdr[1];
+ } ehdr;
+ char buf[256];
+ } u;
+ char line[256];
+ char *progarg[32+1];
+ volatile char *args, *file0, *elem;
+ char **argv, **argp, **argp0;
+ char *a, *e, *file;
+ Chan *tc;
+ ulong magic, nbytes, nargs;
+ uintptr t, d, b, entry, text, align, data, bss, bssend;
+ int n, indir;
+
+ args = elem = nil;
+ file0 = va_arg(list, char*);
+ validaddr((uintptr)file0, 1, 0);
+ argp0 = va_arg(list, char**);
+ evenaddr((uintptr)argp0);
+ validaddr((uintptr)argp0, 2*BY2WD, 0);
+ if(*argp0 == nil)
+ error(Ebadarg);
+ file0 = validnamedup(file0, 1);
+ if(waserror()){
+ free(file0);
+ free(elem);
+ free(args);
+ /* Disaster after commit */
+ if(up->seg[SSEG] == nil)
+ pexit(up->errstr, 1);
+ nexterror();
+ }
+
+ align = BY2PG-1;
+ indir = 0;
+ file = file0;
+ for(;;){
+ tc = namec(file, Aopen, OEXEC, 0);
+ if(waserror()){
+ cclose(tc);
+ nexterror();
+ }
+ if(!indir)
+ kstrdup(&elem, up->genbuf);
+
+ n = devtab[tc->type]->read(tc, u.buf, sizeof(u.buf), 0);
+ if (n >= sizeof(Exec)){
+ magic = beswal(u.ehdr.ex.magic);
+ if(magic & AOUT_MAGIC) {
+ if(magic & HDR_MAGIC){
+ if(n < sizeof(u.ehdr))
+ error(Ebadexec);
+ entry = beswav(u.ehdr.hdr[0]);
+ text = UTZERO+sizeof(u.ehdr);
+ } else {
+ entry = beswal(u.ehdr.ex.entry);
+ text = UTZERO+sizeof(Exec);
+ }
+ if(entry < text)
+ error(Ebadexec);
+
+ text += beswal(u.ehdr.ex.text);
+ // Shouldn't have to cast to ulong here, unsure why it's needed
+ if((ulong)text <= (ulong)entry || (ulong)text >= (USTKTOP-USTKSIZE))
+ error(Ebadexec);
+ switch(magic){
+ case S_MAGIC: /* 2MB segment alignment for amd64 */
+ align = 0x1fffff;
+ break;
+ case P_MAGIC: /* 16K segment alignment for spim */
+ case V_MAGIC: /* 16K segment alignment for mips */
+ align = 0x3fff;
+ break;
+ case R_MAGIC: /* 64K segment alignment for arm64 */
+ align = 0xffff;
+ break;
+ }
+
+ break; /* for binary */
+ }
+ }
+ if(indir++)
+ error(Ebadexec);
+
+ /* Process #!/bin/sh args */
+ memmove(line, u.buf, n);
+ n = shargs(line, n, progarg, nelem(progarg));
+ if(n < 1)
+ error(Ebadexec);
+
+ /* First arg becomes complete file name */
+ progarg[n++] = file;
+ progarg[n] = nil;
+ argp0++;
+ file = progarg[0];
+ progarg[0] = elem;
+ poperror();
+ cclose(tc);
+ }
+
+ t = (text+align) & ~align;
+ text -= UTZERO;
+ data = beswal(u.ehdr.ex.data);
+ bss = beswal(u.ehdr.ex.bss);
+ align = BY2PG-1;
+ d = (t + data + align) & ~align;
+ bssend = t + data + bss;
+ b = (bssend + align) & ~align;
+ if(t >= (ulong)(USTKTOP-USTKSIZE) || d >= (ulong)(USTKTOP-USTKSIZE) || b >= (ulong)(USTKTOP-USTKSIZE))
+ error(Ebadexec);
+
+ /* Args: pass 1: count */
+ nbytes = sizeof(Tos);
+ nargs = 0;
+ if(indir){
+ argp = progarg;
+ while(*argp != nil){
+ a = *argp++;
+ nbytes += strlen(a)+1;
+ nargs++;
+ }
+ }
+ argp = argp0;
+
+ while(*argp != nil){
+ a = *argp++;
+
+ if(((uintptr)argp&(BY2PG-1)) < BY2WD)
+ validaddr((uintptr)argp, BY2WD, 0);
+ validaddr((uintptr)a, 1, 0);
+
+ e = vmemchr(a, 0, USTKSIZE);
+ if(e == nil)
+ error(Ebadarg);
+
+ nbytes += (e - a) + 1;
+ if(nbytes >= USTKSIZE)
+ error(Enovmem);
+ nargs++;
+ }
+
+ print("%d args\n", nargs);
+
+ // End of the road cleanup
+ poperror(); // tc
+ cclose(tc);
+
+ poperror(); // file0
+ free(file0);
+
+ return 0;
+}
\ No newline at end of file
--- a/main.c
+++ b/main.c
@@ -57,6 +57,7 @@
chandevinit();
quotefmtinstall();
+ // TODO: Add cons to dev tree so we can open them below correctly
if(bind("#c", "/dev", MBEFORE) < 0)
panic("bind #c: %r");
if(bind("#e", "/env", MREPL|MCREATE) < 0)
@@ -65,14 +66,13 @@
panic("bind #I: %r");
if(bind("#U", "/root", MREPL|MCREATE) < 0)
panic("bind #U: %r");
- if(bind("/root", "/", MAFTER) < 0)
- panic("bind /root: %r");
bind("#C", "/", MAFTER);
+ //bind("#F", "/fd", MBEFORE)
/* We have to be a bit pedantic about the fds, leave 0, 1, 2 alone */
ifd = open("/dev/null", OREAD);
ofd = open("/dev/null", OWRITE);
- efd = open("/devnull", OWRITE);
+ efd = open("/dev/null", OWRITE);
if(argc == 2 && strcmp(argv[1], "-D") == 0)
dfd = create("/Users/halfwit/Work/drawcpu/error.log", OWRITE, 0644);
else
@@ -87,6 +87,9 @@
". <{n=`{read} && ! ~ $#n 0 && read -c $n} >[2=1]"
};
+ if(bind("/root", "/", MAFTER) < 0)
+ panic("bind /root: %r");
+
runcommand(3, cmd, dfd);
_exit(0);
}
--- /dev/null
+++ b/posix-arm64/mem.h
@@ -1,0 +1,152 @@
+#define AOUT_MAGIC (R_MAGIC)
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+#define KiB 1024u /* Kibi 0x0000000000000400 */
+#define MiB 1048576u /* Mebi 0x0000000000100000 */
+#define GiB 1073741824u /* Gibi 000000000040000000 */
+
+/*
+ * Sizes:
+ * L0 L1 L2 L3
+ * 4K 2M 1G 512G
+ * 16K 32M 64G 128T
+ * 64K 512M 4T -
+ */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define BY2PG (1ULL<<PGSHIFT) /* bytes per page */
+#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
+#define PGROUND(s) ROUND(s, BY2PG)
+
+/* effective virtual address space */
+#define EVASHIFT 36
+#define EVAMASK ((1ULL<<EVASHIFT)-1)
+
+#define PTSHIFT (PGSHIFT-3)
+#define PTLEVELS (((EVASHIFT-PGSHIFT)+PTSHIFT-1)/PTSHIFT)
+#define PTLX(v, l) ((((v) & EVAMASK) >> (PGSHIFT + (l)*PTSHIFT)) & ((1 << PTSHIFT)-1))
+#define PGLSZ(l) (1ULL << (PGSHIFT + (l)*PTSHIFT))
+
+#define PTL1X(v, l) (L1TABLEX(v, l) | PTLX(v, l))
+#define L1TABLEX(v, l) (L1TABLE(v, l) << PTSHIFT)
+#define L1TABLES ((-KSEG0+PGLSZ(2)-1)/PGLSZ(2))
+#define L1TABLE(v, l) (L1TABLES - ((PTLX(v, 2) % L1TABLES) >> (((l)-1)*PTSHIFT)) + (l)-1)
+#define L1TOPSIZE (1ULL << (EVASHIFT - PTLEVELS*PTSHIFT))
+
+#define MAXMACH 16 /* max # cpus system can run */
+#define MACHSIZE (8*KiB)
+
+#define KSTACK (8*KiB)
+#define STACKALIGN(sp) ((sp) & ~7) /* bug: assure with alloc */
+#define TRAPFRAMESIZE (38*8)
+
+#define DTBADDR 0x40000000
+
+#define VDRAM (0xFFFFFFFFC0000000ULL) /* 0x40000000 - 0x80000000 */
+#define KTZERO (VDRAM + 0x100000) /* 0x40100000 - kernel text start */
+
+#define PHYSIO 0x8000000
+#define PHYSIOEND 0x10000000
+
+#define VIRTIO (0xFFFFFFFFB0000000ULL)
+
+#define KZERO (0xFFFFFFFF80000000ULL) /* 0x00000000 - kernel address space */
+
+#define VMAP (0xFFFFFFFF00000000ULL) /* 0x00000000 - 0x40000000 */
+
+#define KMAPEND (0xFFFFFFFF00000000ULL) /* 0x140000000 */
+#define KMAP (0xFFFFFFFE00000000ULL) /* 0x40000000 */
+
+#define KLIMIT (VDRAM - KZERO + KMAPEND - KMAP) /* 0x140000000 */
+
+#define KSEG0 (0xFFFFFFFE00000000ULL)
+
+/* temporary identity map for TTBR0 (using only top-level) */
+#define L1BOT ((L1-L1TOPSIZE)&-BY2PG)
+
+/* shared kernel page table for TTBR1 */
+#define L1 (L1TOP-L1SIZE)
+#define L1SIZE ((L1TABLES+PTLEVELS-2)*BY2PG)
+#define L1TOP ((MACHADDR(MAXMACH-1)-L1TOPSIZE)&-BY2PG)
+
+#define MACHADDR(n) (KTZERO-((n)+1)*MACHSIZE)
+
+#define CONFADDR (VDRAM + 0x10000) /* 0x40010000 */
+
+#define BOOTARGS ((char*)CONFADDR)
+#define BOOTARGSLEN 0x10000
+
+#define REBOOTADDR (VDRAM-KZERO + 0x20000) /* 0x40020000 */
+
+#define UZERO 0ULL /* user segment */
+#define UTZERO (UZERO+0x10000) /* user text start */
+#define USTKTOP ((EVAMASK>>1)-0xFFFF) /* user segment end +1 */
+#define USTKSIZE (16*1024*1024) /* user stack size */
+
+#define BLOCKALIGN 64 /* only used in allocb.c */
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BY2SE 4
+#define BY2WD 8
+#define BY2V 8 /* only used in xalloc.c */
+
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 8192
+#define SSEGMAPSIZE 16
+#define PPN(x) ((x)&~(BY2PG-1))
+
+#define SHARE_NONE 0
+#define SHARE_OUTER 2
+#define SHARE_INNER 3
+
+#define CACHE_UC 0
+#define CACHE_WB 1
+#define CACHE_WT 2
+#define CACHE_WB_NA 3
+
+#define MA_MEM_WB 0
+#define MA_MEM_WT 1
+#define MA_MEM_UC 2
+#define MA_DEV_nGnRnE 3
+#define MA_DEV_nGnRE 4
+#define MA_DEV_nGRE 5
+#define MA_DEV_GRE 6
+
+#define PTEVALID 1
+#define PTEBLOCK 0
+#define PTETABLE 2
+#define PTEPAGE 2
+
+#define PTEMA(x) ((x)<<2)
+#define PTEAP(x) ((x)<<6)
+#define PTESH(x) ((x)<<8)
+
+#define PTEAF (1<<10)
+#define PTENG (1<<11)
+#define PTEPXN (1ULL<<53)
+#define PTEUXN (1ULL<<54)
+
+#define PTEKERNEL PTEAP(0)
+#define PTEUSER PTEAP(1)
+#define PTEWRITE PTEAP(0)
+#define PTERONLY PTEAP(2)
+#define PTENOEXEC (PTEPXN|PTEUXN)
+
+#define PTECACHED PTEMA(MA_MEM_WB)
+#define PTEWT PTEMA(MA_MEM_WT)
+#define PTEUNCACHED PTEMA(MA_MEM_UC)
+#define PTEDEVICE PTEMA(MA_DEV_nGnRE)
+
+/*
+ * Physical machine information from here on.
+ * PHYS addresses as seen from the arm cpu.
+ * BUS addresses as seen from peripherals
+ */
+#define PHYSDRAM 0
+
+#define MIN(a, b) ((a) < (b)? (a): (b))
+#define MAX(a, b) ((a) > (b)? (a): (b))
\ No newline at end of file
--- a/rc/drawcpu.c
+++ b/rc/drawcpu.c
@@ -56,12 +56,13 @@
static void
execfinit(void)
{
- char *cmds = estrdup("for(i in '/env/fn#'*){. -bq $i}\n");
- int line = runq->line;
- poplist();
- execcmds(openiocore(cmds, strlen(cmds)), estrdup(srcfile(runq)), runq->local, runq->redir);
- runq->lex->line = line;
- runq->lex->qflag = 1;
+ // TODO: /env/fn# is empty
+ //char *cmds = estrdup("for(i in '/env/fn#'*){. -bq $i}\n");
+ //int line = runq->line;
+ //poplist();
+ //execcmds(openiocore(cmds, strlen(cmds)), estrdup(srcfile(runq)), runq->local, runq->redir);
+ //runq->lex->line = line;
+ //runq->lex->qflag = 1;
}
static void
@@ -263,9 +264,7 @@
void
Exec(char **argv)
{
- // TODO: this will call our vm code
- // execvm();
- execvp(argv[0], argv+1);
+ exec(argv);
}
int