diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-23 00:30:12 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-23 00:30:12 +0000 |
| commit | 6e425a9de8c003b5a733621a6b6730ec3cc902b8 (patch) | |
| tree | 314123bcab78ff295f38f85f31dc141e5fe22d15 /emu/Linux | |
| parent | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (diff) | |
20061220
Diffstat (limited to 'emu/Linux')
| -rw-r--r-- | emu/Linux/asm-386.S | 6 | ||||
| -rw-r--r-- | emu/Linux/asm-arm.S | 131 | ||||
| -rw-r--r-- | emu/Linux/asm-power.S | 72 | ||||
| -rw-r--r-- | emu/Linux/cmd.c | 26 | ||||
| -rw-r--r-- | emu/Linux/emu-g | 96 | ||||
| -rw-r--r-- | emu/Linux/mkfile | 2 | ||||
| -rw-r--r-- | emu/Linux/os.c | 12 | ||||
| -rw-r--r-- | emu/Linux/segflush-power.c | 27 |
8 files changed, 355 insertions, 17 deletions
diff --git a/emu/Linux/asm-386.S b/emu/Linux/asm-386.S index caa1f79a..31946335 100644 --- a/emu/Linux/asm-386.S +++ b/emu/Linux/asm-386.S @@ -94,12 +94,6 @@ FPrestore: popl %ebp ret - .type getcallerpc,@function - .global getcallerpc -getcallerpc: - movl 4(%ebp), %eax - ret - .type _tas,@function .globl _tas _tas: diff --git a/emu/Linux/asm-arm.S b/emu/Linux/asm-arm.S new file mode 100644 index 00000000..1cdac444 --- /dev/null +++ b/emu/Linux/asm-arm.S @@ -0,0 +1,131 @@ + .file "asm-Linux-arm.S" +#include "syscall.h" + .text + +/* + * void executeonnewstack(void *tos, void (*tramp)(void *arg), void *arg) + */ + + .align 2 + .global executeonnewstack + .type executeonnewstack, %function +executeonnewstack: + @ args = 0, pretend = 0, frame = 12 + @ frame_needed = 1, uses_anonymous_args = 0 + mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4 + sub sp, sp, #12 + str r0, [fp, #-16] /* store tos */ + str r1, [fp, #-20] /* store tramp */ + str r2, [fp, #-24] /* store arg */ + ldr r0, [fp, #-24] /* get arg */ + ldr r2, [fp, #-16] /* get tos */ + mov sp, r2 /* set new stack */ + mov lr, pc + blx r1 /* call tramp*/ + + /* if we return here, tramp didn't do it's job */ + swi SYS_exit + ldmea fp, {fp, sp, pc} + .size executeonnewstack, .-executeonnewstack + +/* + * void unlockandexit(int *key) + * + * NB: the return status may be garbaged if the stack is reused + * between the unlock and the system call, but this should + * not matter since no task is waiting for the result + */ + + .align 2 + .global unlockandexit + .type unlockandexit, %function +unlockandexit: + @ args = 0, pretend = 0, frame = 4 + @ frame_needed = 1, uses_anonymous_args = 0 + mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4 + sub sp, sp, #4 + mov r1, #0 + str r1, [r0] + swi SYS_exit + ldmea fp, {fp, sp, pc} + .size unlockandexit, .-unlockandexit + +/* + * ulong umult(ulong m1, ulong m2, ulong *hi) + */ + + .align 2 + .global umult + .type umult, %function +umult: + @ args = 0, pretend = 0, frame = 12 + @ frame_needed = 1, uses_anonymous_args = 0 + mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4 + sub sp, sp, #12 + str r0, [fp, #-16] + str r1, [fp, #-20] + str r2, [fp, #-24] + ldr r1, [fp, #-16] + ldr r2, [fp, #-20] + umull r0, r3, r1, r2 + ldr r1, [fp, #-24] + str r3, [r1] + ldmea fp, {fp, sp, pc} + .size umult, .-umult + +/* + * void FPsave(void*); + */ + + .align 2 + .global FPsave + .type FPsave, %function +FPsave: + @ args = 0, pretend = 0, frame = 4 + @ frame_needed = 1, uses_anonymous_args = 0 + mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4 + sub sp, sp, #4 + str r0, [fp, #-16] + ldmea fp, {fp, sp, pc} + .size FPsave, .-FPsave + +/* + * void FPrestore(void*); + */ + .align 2 + .global FPrestore + .type FPrestore, %function +FPrestore: + @ args = 0, pretend = 0, frame = 4 + @ frame_needed = 1, uses_anonymous_args = 0 + mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4 + sub sp, sp, #4 + str r0, [fp, #-16] + ldmea fp, {fp, sp, pc} + .size FPrestore, .-FPrestore + +/* + * ulong _tas(ulong*); + */ + .align 2 + .global _tas + .type _tas, %function +_tas: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. + @ lr needed for prologue + mov r3, #1 + swp r0, r3, [r0] + mov pc, lr + .size _tas, .-_tas diff --git a/emu/Linux/asm-power.S b/emu/Linux/asm-power.S new file mode 100644 index 00000000..ff5f97cd --- /dev/null +++ b/emu/Linux/asm-power.S @@ -0,0 +1,72 @@ +#include <asm-ppc/reg.h> + + .file "asm-power.S" + .section ".text" + .align 2 + .globl FPsave + .type FPsave, @function +FPsave: + .set _framesize,0 + mffs f0 + stfd f0,0(r3) + blr + .size FPsave,.-FPsave + + .align 2 + .globl FPrestore +FPrestore: + lfd f0,0(r3) + mtfsf 0xff,f0 + blr + .size FPrestore, .-FPrestore + + .align 2 + .globl _tas +_tas: + sync + mr r4,r3 + addi r5,0,0x1 +1: + lwarx r3,0,r4 + cmpwi r3,0x0 + bne- 2f + stwcx. r5,0,r4 + bne- 1b /* Lost reservation, try again */ +2: + sync + blr + .size _tas,.-_tas + +/* + * void executeonnewstack(void *tos, void (*tramp)(void *arg), void *arg) + */ + .align 2 + .globl executeonnewstack: +executeonnewstack: + mr r1,r3 /* change stacks */ + stwu 1,-16(r1) /* save lr to aid the traceback */ + li r0,0 + stw r0,20(r1) + mr r3,r5 + mtctr r4 + bctrl /* tramp(arg) */ + br . /* failed */ + .size executeonnewstack,.-executeonnewstack + +/* + * void unlockandexit(int *key) + * + * NB: the return status may be garbaged if the stack is reused + * between the unlock and the system call, but this should + * not matter since no task is waiting for the result + */ + .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 . /* not reached */ + .size unlockandexit,.-unlockandexit diff --git a/emu/Linux/cmd.c b/emu/Linux/cmd.c index 2f55c427..0b8c960b 100644 --- a/emu/Linux/cmd.c +++ b/emu/Linux/cmd.c @@ -21,7 +21,7 @@ enum typedef struct Targ Targ; struct Targ { - int fd[2]; /* fd[0] is standard input, fd[1] is standard output */ + int fd[3]; /* fd[0] is standard input, fd[1] is standard output, fd[2] is standard error */ char** args; char* dir; int pid; @@ -43,15 +43,17 @@ childproc(Targ *t) nfd = getdtablesize(); for(i = 0; i < nfd; i++) - if(i != t->fd[0] && i != t->fd[1] && i != t->wfd) + 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[1], 2); + 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)); @@ -82,10 +84,10 @@ childproc(Targ *t) } void* -oscmd(char **args, int nice, char *dir, int *rfd, int *sfd) +oscmd(char **args, int nice, char *dir, int *fd) { Targ *t; - int r, fd0[2], fd1[2], wfd[2], n, pid; + int r, fd0[2], fd1[2], fd2[2], wfd[2], n, pid; t = mallocz(sizeof(*t), 1); if(t == nil) @@ -93,14 +95,16 @@ oscmd(char **args, int nice, char *dir, int *rfd, int *sfd) 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(wfd) < 0) + 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; @@ -130,6 +134,7 @@ oscmd(char **args, int nice, char *dir, int *rfd, int *sfd) close(fd0[0]); close(fd1[1]); + close(fd2[1]); close(wfd[1]); n = read(wfd[0], up->genbuf, sizeof(up->genbuf)-1); @@ -137,6 +142,7 @@ oscmd(char **args, int nice, char *dir, int *rfd, int *sfd) if(n > 0){ close(fd0[1]); close(fd1[0]); + close(fd2[0]); free(t); up->genbuf[n] = 0; if(Debug) @@ -145,19 +151,21 @@ oscmd(char **args, int nice, char *dir, int *rfd, int *sfd) return nil; } - *sfd = fd0[1]; - *rfd = fd1[0]; + fd[0] = fd0[1]; + fd[1] = fd1[0]; + fd[2] = fd2[0]; return t; Error: r = errno; - free(t); 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)); diff --git a/emu/Linux/emu-g b/emu/Linux/emu-g new file mode 100644 index 00000000..8892d7a9 --- /dev/null +++ b/emu/Linux/emu-g @@ -0,0 +1,96 @@ +dev + root + cons + env + mnt + pipe + prog + prof + srv + dup + ssl + cap + fs + cmd cmd + indir + + ip ipif-posix ipaux + eia +# audio audio + mem + +lib + interp + math + keyring + sec + mp + + 9 + +link + +mod + sys + math + srv srv + keyring + loader + +port + alloc + cache + chan + dev + dial + dis + discall + env + error + errstr + exception + exportfs + inferno + latin1 + main + parse + pgrp + print + proc + qio + random + sysfile + uqid + +code + int dontcompile = 1; + int macjit = 1; + void setpointer(int x, int y){USED(x); USED(y);} + ulong strtochan(char *s){USED(s); return ~0;} + +init + emuinit + +root + /dev / + /fd / + /prog / + /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/Linux/mkfile b/emu/Linux/mkfile index fd6e89e7..ee2152d0 100644 --- a/emu/Linux/mkfile +++ b/emu/Linux/mkfile @@ -1,8 +1,6 @@ SYSTARG=Linux -OBJTYPE=386 <../../mkconfig SYSTARG=Linux -OBJTYPE=386 #Configurable parameters diff --git a/emu/Linux/os.c b/emu/Linux/os.c index f541311f..336d0443 100644 --- a/emu/Linux/os.c +++ b/emu/Linux/os.c @@ -521,3 +521,15 @@ stackalloc(Proc *p, void **tos) *(Proc **)rv = p; return rv; } + +#ifdef LINUX_ARM +#define SYS_cacheflush __ARM_NR_cacheflush + +int +segflush(void *a, ulong n) +{ + if(n) + syscall(SYS_cacheflush, a, (char*)a+n-1, 1); + return 0; +} +#endif diff --git a/emu/Linux/segflush-power.c b/emu/Linux/segflush-power.c new file mode 100644 index 00000000..07f9a3cb --- /dev/null +++ b/emu/Linux/segflush-power.c @@ -0,0 +1,27 @@ +/* + * from geoff collyer's port + * invalidate instruction cache and write back data cache from a to a+n-1, + * at least. + */ +void +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 & ~3UL); (char *)p < (char *)a + n; p++) + __asm__("dcbst 0,%0\n\t" // not dcbf, which writes back, then invalidates + "icbi 0,%0\n\t" + : // no output + : "ar" (p) + ); + __asm__("sync\n\t" + : // no output + : + ); + __asm__("isync\n\t" + : // no output + : + ); +} |
