diff options
Diffstat (limited to 'emu')
| -rw-r--r-- | emu/AIX/asm-power.s | 108 | ||||
| -rw-r--r-- | emu/AIX/cmd.c | 213 | ||||
| -rw-r--r-- | emu/AIX/deveia.c | 40 | ||||
| -rw-r--r-- | emu/AIX/devfs.c | 7 | ||||
| -rw-r--r-- | emu/AIX/emu | 104 | ||||
| -rw-r--r-- | emu/AIX/emu-g | 100 | ||||
| -rw-r--r-- | emu/AIX/mkfile | 52 | ||||
| -rw-r--r-- | emu/AIX/mkfile-power | 0 | ||||
| -rw-r--r-- | emu/AIX/os.c | 300 | ||||
| -rw-r--r-- | emu/AIX/segflush-power.c | 33 |
10 files changed, 957 insertions, 0 deletions
diff --git a/emu/AIX/asm-power.s b/emu/AIX/asm-power.s new file mode 100644 index 00000000..024c058b --- /dev/null +++ b/emu/AIX/asm-power.s @@ -0,0 +1,108 @@ +.set r0,0; .set SP,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set fp0,0; .set fp1,1; .set fp2,2; .set fp3,3; .set fp4,4 +.set fp5,5; .set fp6,6; .set fp7,7; .set fp8,8; .set fp9,9 +.set fp10,10; .set fp11,11; .set fp12,12; .set fp13,13; .set fp14,14 +.set fp15,15; .set fp16,16; .set fp17,17; .set fp18,18; .set fp19,19 +.set fp20,20; .set fp21,21; .set fp22,22; .set fp23,23; .set fp24,24 +.set fp25,25; .set fp26,26; .set fp27,27; .set fp28,28; .set fp29,29 +.set fp30,30; .set fp31,31 +.set v0,0; .set v1,1; .set v2,2; .set v3,3; .set v4,4 +.set v5,5; .set v6,6; .set v7,7; .set v8,8; .set v9,9 +.set v10,10; .set v11,11; .set v12,12; .set v13,13; .set v14,14 +.set v15,15; .set v16,16; .set v17,17; .set v18,18; .set v19,19 +.set v20,20; .set v21,21; .set v22,22; .set v23,23; .set v24,24 +.set v25,25; .set v26,26; .set v27,27; .set v28,28; .set v29,29 +.set v30,30; .set v31,31 +.set LR,8; .set CTR,9; .set TID,17; .set DSISR,18; .set DAR,19; .set TO_RTCU,20 + +.machine "ppc" + + .align 2 + .globl .FPsave +.FPsave: + stfd fp14,0*8(r3) + stfd fp15,1*8(r3) + stfd fp16,2*8(r3) + stfd fp17,3*8(r3) + stfd fp18,4*8(r3) + stfd fp19,5*8(r3) + stfd fp20,6*8(r3) + stfd fp21,7*8(r3) + stfd fp22,8*8(r3) + stfd fp23,9*8(r3) + stfd fp24,10*8(r3) + stfd fp25,11*8(r3) + stfd fp26,12*8(r3) + stfd fp27,13*8(r3) + stfd fp28,14*8(r3) + stfd fp29,15*8(r3) + stfd fp30,16*8(r3) + stfd fp31,17*8(r3) + blr + + .align 2 + .globl .FPrestore +.FPrestore: + lfd fp14,0*8(r3) + lfd fp15,1*8(r3) + lfd fp16,2*8(r3) + lfd fp17,3*8(r3) + lfd fp18,4*8(r3) + lfd fp19,5*8(r3) + lfd fp20,6*8(r3) + lfd fp21,7*8(r3) + lfd fp22,8*8(r3) + lfd fp23,9*8(r3) + lfd fp24,10*8(r3) + lfd fp25,11*8(r3) + lfd fp26,12*8(r3) + lfd fp27,13*8(r3) + lfd fp28,14*8(r3) + lfd fp29,15*8(r3) + lfd fp30,16*8(r3) + lfd fp31,17*8(r3) + blr + + .align 2 + .globl ._tas +._tas: + sync + mr r4, r3 + addi r5,0,0x1 +_tas_1: + lwarx r3, 0, r4 + cmpwi r3, 0 + bne- _tas_2 + stwcx. r5, 0, r4 + bne- _tas_1 +_tas_2: + sync + blr + + .align 2 + .globl .executeonnewstack +.executeonnewstack: + mr SP,r3 # change stacks + stwu LR,-16(SP) # save lr to aid the traceback + li r0,0 + stw r0,20(SP) + mr r3,r5 + mtctr r4 + bctrl # tramp(arg) + br + + .align 2 + .globl .unlockandexit +.unlockandexit: + li r0,0x0 + stw r0,0(r3) # unlock + li r0,1 # sys exit; 234 is exit group + li r3,0 # exit status + sc + br diff --git a/emu/AIX/cmd.c b/emu/AIX/cmd.c new file mode 100644 index 00000000..ed4cabab --- /dev/null +++ b/emu/AIX/cmd.c @@ -0,0 +1,213 @@ +#include <sys/types.h> +#include <signal.h> +#include <pwd.h> +#include <sys/resource.h> +#include <sys/wait.h> +#include <fcntl.h> + +#include "dat.h" +#include "fns.h" +#include "error.h" + +enum +{ + Debug = 0 +}; + +/* + * os-specific devcmd support. + * this version should be reasonably portable across Unix systems. + */ +typedef struct Targ Targ; +struct Targ +{ + int fd[3]; /* fd[0] is standard input, fd[1] is standard output, fd[2] is standard error */ + char** args; + char* dir; + int pid; + int wfd; /* child writes errors that occur after the fork or on exec */ + int uid; + int gid; +}; + +extern int gidnobody; +extern int uidnobody; + +static int +childproc(Targ *t) +{ + int i, nfd; + + if(Debug) + print("devcmd: '%s'", t->args[0]); + + nfd = getdtablesize(); + for(i = 0; i < nfd; i++) + if(i != t->fd[0] && i != t->fd[1] && i != t->fd[2] && i != t->wfd) + close(i); + + dup2(t->fd[0], 0); + dup2(t->fd[1], 1); + dup2(t->fd[2], 2); + close(t->fd[0]); + close(t->fd[1]); + close(t->fd[2]); + + /* should have an auth file to do host-specific authorisation? */ + if(t->gid != -1){ + if(setgid(t->gid) < 0 && getegid() == 0){ + fprint(t->wfd, "can't set gid %d: %s", t->gid, strerror(errno)); + _exit(1); + } + } + + if(t->uid != -1){ + if(setuid(t->uid) < 0 && geteuid() == 0){ + fprint(t->wfd, "can't set uid %d: %s", t->uid, strerror(errno)); + _exit(1); + } + } + + if(t->dir != nil && chdir(t->dir) < 0){ + fprint(t->wfd, "can't chdir to %s: %s", t->dir, strerror(errno)); + _exit(1); + } + + signal(SIGPIPE, SIG_DFL); + + execvp(t->args[0], t->args); + if(Debug) + print("execvp: %s\n",strerror(errno)); + fprint(t->wfd, "exec failed: %s", strerror(errno)); + + _exit(1); +} + +void* +oscmd(char **args, int nice, char *dir, int *fd) +{ + Targ *t; + int r, fd0[2], fd1[2], fd2[2], wfd[2], n, pid; + + t = mallocz(sizeof(*t), 1); + if(t == nil) + return nil; + + fd0[0] = fd0[1] = -1; + fd1[0] = fd1[1] = -1; + fd2[0] = fd2[1] = -1; + wfd[0] = wfd[1] = -1; + if(pipe(fd0) < 0 || pipe(fd1) < 0 || pipe(fd2) < 0 || pipe(wfd) < 0) + goto Error; + if(fcntl(wfd[1], F_SETFD, FD_CLOEXEC) < 0) /* close on exec to give end of file on success */ + goto Error; + + t->fd[0] = fd0[0]; + t->fd[1] = fd1[1]; + t->fd[2] = fd2[1]; + t->wfd = wfd[1]; + t->args = args; + t->dir = dir; + t->gid = up->env->gid; + if(t->gid == -1) + t->gid = gidnobody; + t->uid = up->env->uid; + if(t->uid == -1) + t->uid = uidnobody; + + signal(SIGCHLD, SIG_DFL); + switch(pid = fork()) { + case -1: + goto Error; + case 0: + setpgid(0, getpid()); + if(nice) + oslopri(); + childproc(t); + _exit(1); + default: + t->pid = pid; + if(Debug) + print("cmd pid %d\n", t->pid); + break; + } + + close(fd0[0]); + close(fd1[1]); + close(fd2[1]); + close(wfd[1]); + + n = read(wfd[0], up->genbuf, sizeof(up->genbuf)-1); + close(wfd[0]); + if(n > 0){ + close(fd0[1]); + close(fd1[0]); + close(fd2[0]); + free(t); + up->genbuf[n] = 0; + if(Debug) + print("oscmd: bad exec: %q\n", up->genbuf); + error(up->genbuf); + return nil; + } + + fd[0] = fd0[1]; + fd[1] = fd1[0]; + fd[2] = fd2[0]; + return t; + +Error: + r = errno; + if(Debug) + print("oscmd: %q\n",strerror(r)); + close(fd0[0]); + close(fd0[1]); + close(fd1[0]); + close(fd1[1]); + close(fd2[0]); + close(fd2[1]); + close(wfd[0]); + close(wfd[1]); + error(strerror(r)); + return nil; +} + +int +oscmdkill(void *a) +{ + Targ *t = a; + + if(Debug) + print("kill: %d\n", t->pid); + return kill(-t->pid, SIGTERM); +} + +int +oscmdwait(void *a, char *buf, int n) +{ + Targ *t = a; + int s; + + if(waitpid(t->pid, &s, 0) == -1){ + if(Debug) + print("wait error: %d [in %d] %q\n", t->pid, getpid(), strerror(errno)); + return -1; + } + if(WIFEXITED(s)){ + if(WEXITSTATUS(s) == 0) + return snprint(buf, n, "%d 0 0 0 ''", t->pid); + return snprint(buf, n, "%d 0 0 0 'exit: %d'", t->pid, WEXITSTATUS(s)); + } + if(WIFSIGNALED(s)){ + if(WTERMSIG(s) == SIGTERM || WTERMSIG(s) == SIGKILL) + return snprint(buf, n, "%d 0 0 0 killed", t->pid); + return snprint(buf, n, "%d 0 0 0 'signal: %d'", t->pid, WTERMSIG(s)); + } + return snprint(buf, n, "%d 0 0 0 'odd status: 0x%x'", t->pid, s); +} + +void +oscmdfree(void *a) +{ + free(a); +} diff --git a/emu/AIX/deveia.c b/emu/AIX/deveia.c new file mode 100644 index 00000000..3e00ca3f --- /dev/null +++ b/emu/AIX/deveia.c @@ -0,0 +1,40 @@ +/* + * AIX serial port definitions + */ + +static char *sysdev[] = { + "/dev/tty0", + "/dev/tty1", + "/dev/tty2", + "/dev/tty3", + "/dev/tty4", + "/dev/tty5", + "/dev/tty6", + "/dev/tty7", +}; + +#include <sys/ioctl.h> +#include "deveia-posix.c" +#include "deveia-bsd.c" + + +static struct tcdef_t bps[] = { + {0, B0}, + {50, B50}, + {75, B75}, + {110, B110}, + {134, B134}, + {150, B150}, + {200, B200}, + {300, B300}, + {600, B600}, + {1200, B1200}, + {1800, B1800}, + {2400, B2400}, + {4800, B4800}, + {9600, B9600}, + {19200, B19200}, + {38400, B38400}, + {-1, -1} +}; + diff --git a/emu/AIX/devfs.c b/emu/AIX/devfs.c new file mode 100644 index 00000000..194c1090 --- /dev/null +++ b/emu/AIX/devfs.c @@ -0,0 +1,7 @@ +#include "devfs-posix.c" + +static vlong +osdisksize(int fd) +{ + return 0; +} diff --git a/emu/AIX/emu b/emu/AIX/emu new file mode 100644 index 00000000..43f6e128 --- /dev/null +++ b/emu/AIX/emu @@ -0,0 +1,104 @@ +dev + root + cons + env + mnt + pipe + prog + prof + srv + dup + ssl + cap + fs + cmd cmd + indir + + draw win-x11a + pointer + snarf + + ip ipif6-posix ipaux + eia + mem + +lib + interp + tk + freetype + math + draw + + memlayer + memdraw + keyring + sec + mp + + 9 + +link + +mod + sys + draw + + tk + math + srv srv + keyring + crypt + ipints + loader + freetype + +port + alloc + cache + chan + dev + devtab + + dial + dis + discall + env + error + errstr + exception + exportfs + inferno + latin1 + main + parse + pgrp + print + proc + qio + random + sysfile + uqid + +code + +init + emuinit + +root + /dev / + /fd / + /prog / + /prof / + /net / + /net.alt / + /chan / + /nvfs / + /env / +# /dis +# /n +# /icons +# /osinit.dis +# /dis/emuinit.dis +# /dis/lib/auth.dis +# /dis/lib/ssl.dis +# /n/local / diff --git a/emu/AIX/emu-g b/emu/AIX/emu-g new file mode 100644 index 00000000..41831fa9 --- /dev/null +++ b/emu/AIX/emu-g @@ -0,0 +1,100 @@ +env + X11LIBS= +dev + root + cons + env + mnt + pipe + prog + prof + srv + dup + ssl + cap + fs + cmd cmd + indir + + ip ipif6-posix ipaux + eia + mem + +lib + interp + math + keyring + sec + mp + + 9 + +link + +mod + sys + math + srv srv + keyring + crypt + ipints + loader + +port + alloc + cache + chan + dev + devtab + + dial + dis + discall + env + error + errstr + exception + exportfs + inferno + latin1 + main + parse + pgrp + print + proc + qio + random + sysfile + uqid + +code + void setpointer(int x, int y){USED(x); USED(y);} + ulong strtochan(char *s){USED(s); return ~0;} + +init + emuinit + +root + /dev / + /fd / + /prog / + /prof / + /net / + /net.alt / + /chan / + /nvfs / + /env / +# /chan +# /dev +# /dis +# /env +# /n +# /net +# /nvfs / +# /prog +# /icons +# /osinit.dis +# /dis/emuinit.dis +# /dis/lib/auth.dis +# /dis/lib/ssl.dis +# /n/local / diff --git a/emu/AIX/mkfile b/emu/AIX/mkfile new file mode 100644 index 00000000..2089bd28 --- /dev/null +++ b/emu/AIX/mkfile @@ -0,0 +1,52 @@ +SYSTARG=AIX +<../../mkconfig +SYSTARG=AIX + +#Configurable parameters + +CONF=emu #default configuration +CONFLIST=emu +CLEANCONFLIST= + +INSTALLDIR=$ROOT/$SYSTARG/$OBJTYPE/bin #path of directory where kernel is installed + +#end configurable parameters + +X11LIBS= -lX11 -lXext + +<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE #set vars based on target system + +<| $SHELLNAME ../port/mkdevlist $CONF #sets $IP, $DEVS, $PORT, $LIBS +<mkfile-$OBJTYPE + +OBJ=\ + asm-$OBJTYPE.$O\ + $ARCHFILES\ + os.$O\ + kproc-pthreads.$O\ + segflush-$OBJTYPE.$O\ + $CONF.root.$O\ + lock.$O\ + $DEVS\ + $PORT\ + +LIBNAMES=${LIBS:%=lib%.a} + +HFILES=\ + +CFLAGS='-DROOT="'$ROOT'"' -DEMU -I. -I../port -I$ROOT/$SYSTARG/$OBJTYPE/include -I$ROOT/include -I$ROOT/libinterp $CTHREADFLAGS $CFLAGS $EMUOPTIONS +SYSLIBS= $X11LIBS -lm -lpthread +KERNDATE=`{$NDATE} + +default:V: $O.$CONF + +$O.$CONF: $OBJ $CONF.c $CONF.root.h $LIBNAMES + $CC $CFLAGS '-DKERNDATE='$KERNDATE $CONF.c + $LD $LDFLAGS -o $target $OBJ $CONF.$O $LIBFILES $SYSLIBS + +install:V: $O.$CONF + cp $O.$CONF $INSTALLDIR/$CONF + +<../port/portmkfile + +devfs.$O: ../port/devfs-posix.c diff --git a/emu/AIX/mkfile-power b/emu/AIX/mkfile-power new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/emu/AIX/mkfile-power diff --git a/emu/AIX/os.c b/emu/AIX/os.c new file mode 100644 index 00000000..83bf0901 --- /dev/null +++ b/emu/AIX/os.c @@ -0,0 +1,300 @@ +#include <sys/types.h> +#include <time.h> +#include <termios.h> +#include <signal.h> +#include <pwd.h> +#include <sched.h> +#include <sys/resource.h> +#include <sys/wait.h> +#include <sys/time.h> + +#include <stdint.h> + +#include "dat.h" +#include "fns.h" +#include "error.h" + +#include <semaphore.h> + +#include <raise.h> + +enum +{ + DELETE = 0x7f, + CTRLC = 'C'-'@', + NSTACKSPERALLOC = 16, + X11STACK= 256*1024 +}; +char *hosttype = "Linux"; + +typedef sem_t Sem; + +extern int dflag; + +int gidnobody = -1; +int uidnobody = -1; +static struct termios tinit; + +static void +sysfault(char *what, void *addr) +{ + char buf[64]; + + snprint(buf, sizeof(buf), "sys: %s%#p", what, addr); + disfault(nil, buf); +} + +static void +trapILL(int signo, siginfo_t *si, void *a) +{ + USED(signo); + USED(a); + sysfault("illegal instruction pc=", si->si_addr); +} + +static int +isnilref(siginfo_t *si) +{ + return si != 0 && (si->si_addr == (void*)~(uintptr_t)0 || (uintptr_t)si->si_addr < 512); +} + +static void +trapmemref(int signo, siginfo_t *si, void *a) +{ + USED(a); /* ucontext_t*, could fetch pc in machine-dependent way */ + if(isnilref(si)) + disfault(nil, exNilref); + else if(signo == SIGBUS) + sysfault("bad address addr=", si->si_addr); /* eg, misaligned */ + else + sysfault("segmentation violation addr=", si->si_addr); +} + +static void +trapFPE(int signo, siginfo_t *si, void *a) +{ + char buf[64]; + + USED(signo); + USED(a); + snprint(buf, sizeof(buf), "sys: fp: exception status=%.4lux pc=%#p", getfsr(), si->si_addr); + disfault(nil, buf); +} + +static void +trapUSR1(int signo) +{ + int intwait; + + USED(signo); + + intwait = up->intwait; + up->intwait = 0; /* clear it to let proc continue in osleave */ + + if(up->type != Interp) /* Used to unblock pending I/O */ + return; + + if(intwait == 0) /* Not posted so it's a sync error */ + disfault(nil, Eintr); /* Should never happen */ +} + +void +oslongjmp(void *regs, osjmpbuf env, int val) +{ + USED(regs); + siglongjmp(env, val); +} + +static void +termset(void) +{ + struct termios t; + + tcgetattr(0, &t); + tinit = t; + t.c_lflag &= ~(ICANON|ECHO|ISIG); + t.c_cc[VMIN] = 1; + t.c_cc[VTIME] = 0; + tcsetattr(0, TCSANOW, &t); +} + +static void +termrestore(void) +{ + tcsetattr(0, TCSANOW, &tinit); +} + +void +cleanexit(int x) +{ + USED(x); + + if(up->intwait) { + up->intwait = 0; + return; + } + + if(dflag == 0) + termrestore(); + + kill(0, SIGKILL); + exit(0); +} + +void +osreboot(char *file, char **argv) +{ + if(dflag == 0) + termrestore(); + execvp(file, argv); + error("reboot failure"); +} + +void +libinit(char *imod) +{ + struct sigaction act; + struct passwd *pw; + Proc *p; + char sys[64]; + + setsid(); + + gethostname(sys, sizeof(sys)); + kstrdup(&ossysname, sys); + pw = getpwnam("nobody"); + if(pw != nil) { + uidnobody = pw->pw_uid; + gidnobody = pw->pw_gid; + } + + if(dflag == 0) + termset(); + + memset(&act, 0, sizeof(act)); + act.sa_handler = trapUSR1; + sigaction(SIGUSR1, &act, nil); + + act.sa_handler = SIG_IGN; + sigaction(SIGCHLD, &act, nil); + + /* + * For the correct functioning of devcmd in the + * face of exiting slaves + */ + signal(SIGPIPE, SIG_IGN); + if(signal(SIGTERM, SIG_IGN) != SIG_IGN) + signal(SIGTERM, cleanexit); + if(signal(SIGINT, SIG_IGN) != SIG_IGN) + signal(SIGINT, cleanexit); + + if(sflag == 0) { + act.sa_flags = SA_SIGINFO; + act.sa_sigaction = trapILL; + sigaction(SIGILL, &act, nil); + act.sa_sigaction = trapFPE; + sigaction(SIGFPE, &act, nil); + act.sa_sigaction = trapmemref; + sigaction(SIGBUS, &act, nil); + sigaction(SIGSEGV, &act, nil); + act.sa_flags &= ~SA_SIGINFO; + } + + p = newproc(); + kprocinit(p); + + pw = getpwuid(getuid()); + if(pw != nil) + kstrdup(&eve, pw->pw_name); + else + print("cannot getpwuid\n"); + + p->env->uid = getuid(); + p->env->gid = getgid(); + + emuinit(imod); +} + +int +readkbd(void) +{ + int n; + char buf[1]; + + n = read(0, buf, sizeof(buf)); + if(n < 0) + print("keyboard close (n=%d, %s)\n", n, strerror(errno)); + if(n <= 0) + pexit("keyboard thread", 0); + + switch(buf[0]) { + case '\r': + buf[0] = '\n'; + break; + case DELETE: + buf[0] = 'H' - '@'; + break; + case CTRLC: + cleanexit(0); + break; + } + return buf[0]; +} + +/* + * Return an abitrary millisecond clock time + */ +long +osmillisec(void) +{ + static long sec0 = 0, usec0; + struct timeval t; + + if(gettimeofday(&t,(struct timezone*)0)<0) + return 0; + + if(sec0 == 0) { + sec0 = t.tv_sec; + usec0 = t.tv_usec; + } + return (t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000; +} + +/* + * Return the time since the epoch in nanoseconds and microseconds + * The epoch is defined at 1 Jan 1970 + */ +vlong +osnsec(void) +{ + struct timeval t; + + gettimeofday(&t, nil); + return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000; +} + +vlong +osusectime(void) +{ + struct timeval t; + + gettimeofday(&t, nil); + return (vlong)t.tv_sec * 1000000 + t.tv_usec; +} + +int +osmillisleep(ulong milsec) +{ + struct timespec time; + + time.tv_sec = milsec/1000; + time.tv_nsec= (milsec%1000)*1000000; + nanosleep(&time, NULL); + return 0; +} + +int +limbosleep(ulong milsec) +{ + return osmillisleep(milsec); +} diff --git a/emu/AIX/segflush-power.c b/emu/AIX/segflush-power.c new file mode 100644 index 00000000..5029b0aa --- /dev/null +++ b/emu/AIX/segflush-power.c @@ -0,0 +1,33 @@ +#include <sys/types.h> + +#include "dat.h" + + +/* + * from geoff collyer's port + * invalidate instruction cache and write back data cache from a to a+n-1, + * at least. + */ +int +segflush(void *a, ulong n) +{ + ulong *p; + + // cache blocks are often eight words (32 bytes) long, sometimes 16 bytes. + // need to determine it dynamically? + for (p = (ulong *)((ulong)a & ~7UL); (char *)p < (char *)a + n; p++) + __asm__("dcbst 0,r0\n\t" // not dcbf, which writes back, then invalidates + "icbi 0,r0\n\t" + : // no output + : "ar" (p) + ); + __asm__("sync\n\t" + : // no output + : + ); + __asm__("isync\n\t" + : // no output + : + ); + return 0; +} |
