ref: 8d93ccdbb2a2dee8d2eb1387da1b316fdf84b208
parent: fed44bd6dee3c21a0b5ac0c11c13b4271e20f6f3
author: halfwit <michaelmisch1985@gmail.com>
date: Wed Jul 16 10:49:21 EDT 2025
Modifications and updates as part of a rework around emulating using an embedded 5e
--- a/include/lib.h
+++ b/include/lib.h
@@ -314,10 +314,7 @@
extern int getfields(char*, char**, int, int, char*);
extern char* utfecpy(char*, char*, char*);
extern int tas(int*);
-extern void trampoline(void*);
-extern void start(uintptr_t entry, Tos *, int, char *[]);
-extern long sysintercept(void*, void*, void*, void*, void*, void*, void*);
-extern int patch(void*, int);
+extern int cas(int *, int, int);
extern void quotefmtinstall(void);
extern int dec64(uchar*, int, char*, int);
extern int enc64(char*, int, uchar*, int);
--- /dev/null
+++ b/include/proc.h
@@ -1,0 +1,2 @@
+extern void step(void);
+int loadtext(char *, int, char **);
--- a/kern/Makefile
+++ b/kern/Makefile
@@ -5,6 +5,7 @@
OFILES=\
alloc.$O\
allocb.$O\
+ arm.$O\
await.$O\
chan.$O\
data.$O\
@@ -29,7 +30,10 @@
postnote.$O\
procinit.$O\
notify.$O\
+ rendez.$O\
rwlock.$O\
+ seg.$O\
+ sema.$O\
sleep.$O\
stub.$O\
syscall.$O\
--- /dev/null
+++ b/kern/arm.c
@@ -1,0 +1,580 @@
+#include <u.h>
+#include <lib.h>
+#include "dat.h"
+#include "fns.h"
+#include "proc.h"
+
+enum {+ fI = 1<<25,
+ fP = 1<<24,
+ fLi = 1<<24,
+ fU = 1<<23,
+ fB = 1<<22,
+ fW = 1<<21,
+ fL = 1<<20,
+ fS = 1<<20,
+ fSg = 1<<6,
+ fH = 1<<5,
+};
+
+void
+invalid(u32int instr)
+{+ fprint(2, "undefined instruction %8ux @ %8ux", instr, up->R[15] - 4);
+}
+
+u32int
+evenaddr(u32int addr, u32int mask)
+{+ if((addr & mask) == 0)
+ return addr;
+ return addr & ~mask;
+}
+
+static u32int
+doshift(u32int instr, uint *carry)
+{+ ulong amount, val;
+
+ val = up->R[instr & 15];
+ if(instr & (1<<4)) {+ if(instr & (1<<7))
+ invalid(instr);
+ amount = up->R[(instr >> 8) & 15] & 0xFF;
+ if(amount == 0)
+ return val;
+ } else {+ amount = (instr >> 7) & 31;
+ if(amount == 0 && (instr & (3<<5)) != 0)
+ amount = 32;
+ }
+ switch((instr >> 5) & 3) {+ default:
+ if(amount == 0)
+ return val;
+ if(amount < 32) {+ *carry = (val >> (32 - amount)) & 1;
+ return val << amount;
+ }
+ *carry = val & 1;
+ return 0;
+ case 1:
+ if(amount < 32){+ *carry = (val >> (amount - 1)) & 1;
+ return val >> amount;
+ }
+ *carry = val >> 31;
+ return 0;
+ case 2:
+ if(amount < 32){+ *carry = (val >> (amount - 1)) & 1;
+ return ((long) val) >> amount;
+ }
+ if((long)val < 0){+ *carry = 1;
+ return -1;
+ }
+ *carry = 0;
+ return 0;
+ case 3:
+ amount &= 31;
+ if(amount){+ *carry = (val >> (amount - 1)) & 1;
+ return (val >> amount) | (val << (32 - amount));
+ }
+ amount = *carry & 1;
+ *carry = val & 1;
+ return (val>>1) | (amount<<31);
+ }
+}
+
+static void
+single(u32int instr)
+{+ long offset;
+ u32int addr;
+ u32int *Rn, *Rd;
+ void *targ;
+ Segment *seg;
+
+ if(instr & fI) {+ uint carry = 0;
+ if(instr & (1<<4))
+ invalid(instr);
+ offset = doshift(instr, &carry);
+ } else
+ offset = instr & ((1<<12) - 1);
+ if(!(instr & fU))
+ offset = - offset;
+ Rn = up->R + ((instr >> 16) & 15);
+ Rd = up->R + ((instr >> 12) & 15);
+ if((instr & (fW | fP)) == fW)
+ invalid(instr);
+ if(Rn == up->R + 15) {+ if(instr & fW)
+ invalid(instr);
+ addr = up->R[15] + 4;
+ }
+ else
+ addr = *Rn;
+ if(instr & fP)
+ addr += offset;
+ if((instr & fB) == 0)
+ addr = evenaddr(addr, 3);
+ targ = vaddr(addr, (instr & fB) == 0 ? 4 : 1, &seg);
+ switch(instr & (fB | fL)) {+ case 0:
+ *(u32int*) targ = *Rd;
+ break;
+ case fB:
+ *(uint*) targ = *Rd;
+ break;
+ case fL:
+ *Rd = *(u32int*) targ;
+ break;
+ case fB | fL:
+ *Rd = *(uint*) targ;
+ break;
+ }
+ if(Rd == up->R + 15 && !(instr & fL)) {+ if(instr & fB)
+ *(uint*) targ += 8;
+ else
+ *(u32int*) targ += 8;
+ }
+ segunlock(seg);
+ if(!(instr & fP))
+ addr += offset;
+ if((instr & fW) || !(instr & fP))
+ *Rn = addr;
+}
+
+static void
+swap(u32int instr)
+{+ u32int *Rm, *Rn, *Rd, *targ, addr, old, new;
+ Segment *seg;
+
+ Rm = up->R + (instr & 15);
+ Rd = up->R + ((instr >> 12) & 15);
+ Rn = up->R + ((instr >> 16) & 15);
+ if(Rm == up->R + 15 || Rd == up->R + 15 || Rn == up->R + 15)
+ invalid(instr);
+ addr = *Rn;
+ if((instr & fB) == 0)
+ addr = evenaddr(addr, 3);
+ targ = (u32int *) vaddr(addr & ~3, 4, &seg);
+ do {+ old = *targ;
+ new = *Rm;
+ if(instr & fB){+ new &= 0xFF;
+ new <<= 8*(addr&3);
+ new |= old & ~(0xFF << 8*(addr&3));
+ }
+ } while(!cas((int*)targ, old, new));
+ if(instr & fB) {+ old >>= 8*(addr&3);
+ old &= 0xFF;
+ }
+ *Rd = old;
+ segunlock(seg);
+}
+
+static u32int
+add(u32int a, u32int b, uint type, uint *carry, uint *overflow)
+{+ u32int res1;
+ u64int res2;
+
+ if(type) {+ res2 = (u64int)a - b + *carry - 1;
+ res1 = res2;
+ if(((a ^ b) & (1<<31)) && !((b ^ res1) & (1<<31))) *overflow = 1;
+ else *overflow = 0;
+ if(res2 & 0x100000000LL) *carry = 0;
+ else *carry = 1;
+ } else {+ res2 = (u64int)a + b + *carry;
+ res1 = res2;
+ if(!((a ^ b) & (1<<31)) && ((b ^ res1) & (1<<31))) *overflow = 1;
+ else *overflow = 0;
+ if(res2 & 0x100000000LL) *carry = 1;
+ else *carry = 0;
+ }
+ return res1;
+}
+
+static void
+alu(u32int instr)
+{+ u32int Rn, *Rd, operand, shift, result, op;
+ uint carry, overflow;
+
+ Rn = up->R[(instr >> 16) & 15];
+ Rd = up->R + ((instr >> 12) & 15);
+ if(((instr >> 16) & 15) == 15) {+ Rn += 4;
+ if(!(instr & fI) && (instr & (1<<4)))
+ Rn += 4;
+ }
+ if(Rd == up->R + 15 && (instr & fS))
+ invalid(instr);
+
+ carry = (up->CPSR & flC) != 0;
+ overflow = (up->CPSR & flV) != 0;
+
+ if(instr & fI) {+ operand = instr & 0xFF;
+ shift = ((instr >> 8) & 15) << 1;
+ if(shift){+ operand = (operand >> shift) | (operand << (32 - shift));
+ carry = operand >> 31;
+ }
+ } else
+ operand = doshift(instr, &carry);
+
+ op = (instr >> 21) & 15;
+ if(op >= 8 && op <= 11 && !(instr & fS)){+ fprint(2, "no PSR transfers plz");
+ return;
+ }
+ if(op >= 5 && op < 8)
+ carry = (up->CPSR & flC) != 0;
+ switch(op) {+ case 0: case 8: result = Rn & operand; break;
+ case 1: case 9: result = Rn ^ operand; break;
+ case 2: case 10: carry = 1; case 6: result = add(Rn, operand, 1, &carry, &overflow); break;
+ case 3: carry = 1; case 7: result = add(operand, Rn, 1, &carry, &overflow); break;
+ case 4: case 11: carry = 0; case 5: result = add(operand, Rn, 0, &carry, &overflow); break;
+ case 12: result = Rn | operand; break;
+ case 13: result = operand; break;
+ case 14: result = Rn & ~operand; break;
+ case 15: result = ~operand; break;
+ default: result = 0; /* never happens */
+ }
+ if(instr & fS) {+ up->CPSR &= ~FLAGS;
+ if(result == 0)
+ up->CPSR |= flZ;
+ if(result & (1<<31))
+ up->CPSR |= flN;
+ if(carry)
+ up->CPSR |= flC;
+ if(overflow)
+ up->CPSR |= flV;
+ }
+ if(op < 8 || op >= 12)
+ *Rd = result;
+}
+
+static void
+branch(u32int instr)
+{+ long offset;
+
+ offset = instr & ((1<<24) - 1);
+ if(offset & (1<<23))
+ offset |= ~((1 << 24) - 1);
+ offset *= 4;
+ if(instr & fLi)
+ up->R[14] = up->R[15];
+ up->R[15] += offset + 4;
+}
+
+static void
+halfword(u32int instr)
+{+ u32int offset, target, *Rn, *Rd;
+ Segment *seg;
+
+ if(instr & (1<<22)) {+ offset = (instr & 15) | ((instr >> 4) & 0xF0);
+ } else {+ if((instr & 15) == 15)
+ invalid(instr);
+ offset = up->R[instr & 15];
+ }
+ if(!(instr & fU))
+ offset = - offset;
+ if(!(instr & fP) && (instr & fW))
+ invalid(instr);
+ Rn = up->R + ((instr >> 16) & 15);
+ Rd = up->R + ((instr >> 12) & 15);
+ if(Rn == up->R + 15 || Rd == up->R + 15)
+ fprint(2, "R15 in halfword");
+ target = *Rn;
+ if(instr & fP)
+ target += offset;
+ if(instr & fH)
+ target = evenaddr(target, 1);
+ switch(instr & (fSg | fH | fL)) {+ case fSg: *(uint*) vaddr(target, 1, &seg) = *Rd; break;
+ case fSg | fL: *Rd = (long) *(char*) vaddr(target, 1, &seg); break;
+ case fH: case fSg | fH: *(uint16_t*) vaddr(target, 2, &seg) = *Rd; break;
+ case fH | fL: *Rd = *(uint16_t*) vaddr(target, 2, &seg); break;
+ case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, 2, &seg); break;
+ }
+ segunlock(seg);
+ if(!(instr & fP))
+ target += offset;
+ if(!(instr & fP) || (instr & fW))
+ *Rn = target;
+}
+
+static void
+block(u32int instr)
+{+ int i;
+ u32int targ, *Rn;
+ Segment *seg;
+
+ print("Checking invalid\n");+ if(instr & (1<<22))
+ invalid(instr);
+
+ Rn = up->R +((instr >> 16) & 15);
+ if(Rn == up->R + 15 || instr & (1<<15))
+ print("R15 in block");+ targ = evenaddr(*Rn, 3);
+ if(instr & fU) {+ for(i = 0; i < 16; i++) {+ if(!(instr & (1<<i)))
+ continue;
+ if(instr & fP)
+ targ += 4;
+ if(instr & fL)
+ up->R[i] = *(u32int*) vaddr(targ, 4, &seg);
+ else
+ *(u32int*) vaddr(targ, 4, &seg) = up->R[i];
+ segunlock(seg);
+ if(!(instr & fP))
+ targ += 4;
+ }
+ } else {+ for(i = 15; i >= 0; i--) {+ if(!(instr & (1<<i)))
+ continue;
+ if(instr & fP)
+ targ -= 4;
+ if(instr & fL)
+ up->R[i] = *(u32int*) vaddr(targ, 4, &seg);
+ else
+ *(u32int*) vaddr(targ, 4, &seg) = up->R[i];
+ segunlock(seg);
+ if(!(instr & fP))
+ targ -= 4;
+ }
+ }
+ if(instr & fW)
+ *Rn = targ;
+ print("Farnished\n");+}
+
+static void
+multiply(u32int instr)
+{+ u32int *Rd, *Rn, *Rs, *Rm, res;
+
+ Rm = up->R + (instr & 15);
+ Rs = up->R + ((instr >> 8) & 15);
+ Rn = up->R + ((instr >> 12) & 15);
+ Rd = up->R + ((instr >> 16) & 15);
+ if(Rd == Rm || Rm == up->R + 15 || Rs == up->R + 15 || Rn == up->R + 15 || Rd == up->R + 15)
+ invalid(instr);
+ res = *Rm * *Rs;
+ if(instr & (1<<21))
+ res += *Rn;
+ *Rd = res;
+ if(instr & (1<<20)) {+ up->CPSR &= ~(flN | flZ);
+ if(res & (1<<31))
+ up->CPSR |= flN;
+ if(res == 0)
+ up->CPSR |= flZ;
+ }
+}
+
+static void
+multiplylong(u32int instr)
+{+ u32int *RdH, *RdL, *Rs, *Rm;
+ u64int res;
+
+ Rm = up->R + (instr & 15);
+ Rs = up->R + ((instr >> 8) & 15);
+ RdL = up->R + ((instr >> 12) & 15);
+ RdH = up->R + ((instr >> 16) & 15);
+ if(RdL == RdH || RdH == Rm || RdL == Rm || Rm == up->R + 15 || Rs == up->R + 15 || RdL == up->R + 15 || RdH == up->R + 15)
+ invalid(instr);
+ if(instr & (1<<22))
+ res = ((vlong)*(int*)Rs) * *(int*)Rm;
+ else {+ res = *Rs;
+ res *= *Rm;
+ }
+ if(instr & (1<<21)) {+ res += *RdL;
+ res += ((uvlong)*RdH) << 32;
+ }
+ *RdL = res;
+ *RdH = res >> 32;
+ if(instr & (1<<20)) {+ up->CPSR &= ~FLAGS;
+ if(res == 0)
+ up->CPSR |= flN;
+ if(res & (1LL<<63))
+ up->CPSR |= flV;
+ }
+}
+
+static void
+singleex(u32int instr)
+{+ u32int *Rn, *Rd, *Rm, *targ, addr;
+ Segment *seg;
+
+ Rd = up->R + ((instr >> 12) & 15);
+ Rn = up->R + ((instr >> 16) & 15);
+ if(Rd == up->R + 15 || Rn == up->R + 15)
+ invalid(instr);
+ addr = evenaddr(*Rn, 3);
+ if(instr & fS) {+ targ = vaddr(addr, 4, &seg);
+ *Rd = *targ;
+ up->lladdr = addr;
+ up->llval = *Rd;
+ segunlock(seg);
+ } else {+ Rm = up->R + (instr & 15);
+ if(Rm == up->R + 15)
+ invalid(instr);
+ targ = vaddr(addr, 4, &seg);
+
+ /*
+ * this is not quite correct as we will succeed even
+ * if the value was modified and then restored to its
+ * original value but good enough approximation for
+ * libc's _tas(), _cas() and _xinc()/_xdec().
+ */
+ *Rd = addr != up->lladdr || !cas((int*)targ, up->llval, *Rm);
+ segunlock(seg);
+ clrex();
+ }
+}
+
+void
+clrex(void)
+{+ up->lladdr = 0;
+ up->llval = 0;
+}
+
+static void
+barrier(void)
+{+ static Lock l;
+
+ lock(&l);
+ unlock(&l);
+}
+
+int
+step(void)
+{+ u32int instr;
+ Segment *seg;
+print("Grabbing instruction\n");+ instr = *(u32int*) vaddr(up->R[15], 4, &seg);
+print("Grabbed instruction\n");+ segunlock(seg);
+
+ up->R[15] += 4;
+ switch(instr >> 28) {+ case 0x0: if(!(up->CPSR & flZ)) return 1; break;
+ case 0x1: if(up->CPSR & flZ) return 1; break;
+ case 0x2: if(!(up->CPSR & flC)) return 1; break;
+ case 0x3: if(up->CPSR & flC) return 1; break;
+ case 0x4: if(!(up->CPSR & flN)) return 1; break;
+ case 0x5: if(up->CPSR & flN) return 1; break;
+ case 0x6: if(!(up->CPSR & flV)) return 1; break;
+ case 0x7: if(up->CPSR & flV) return 1; break;
+ case 0x8: if(!(up->CPSR & flC) || (up->CPSR & flZ)) return 1; break;
+ case 0x9: if((up->CPSR & flC) && !(up->CPSR & flZ)) return 1; break;
+ case 0xA: if(!(up->CPSR & flN) != !(up->CPSR & flV)) return 1; break;
+ case 0xB: if(!(up->CPSR & flN) == !(up->CPSR & flV)) return 1; break;
+ case 0xC: if((up->CPSR & flZ) || !(up->CPSR & flN) != !(up->CPSR & flV)) return 1; break;
+ case 0xD: if(!(up->CPSR & flZ) && !(up->CPSR & flN) == !(up->CPSR & flV)) return 1; break;
+ case 0xE: break;
+ case 0xF:
+ switch(instr & 0xFFF000F0){+ case 0xF5700010: /* CLREX */
+ print("clrex\n");+ //clrex();
+ return 1;
+ case 0xF5700040: /* DSB */
+ case 0xF5700050: /* DMB */
+ case 0xF5700060: /* ISB */
+ print("barrier\n");+ //barrier();
+ return 1;
+ }
+ default:
+ fprint(2, "condition code %x not implemented (instr %ux, ps %ux)", instr >> 28, instr, up->R[15]);
+ return 0;
+ }
+ if((instr & 0x0FB00FF0) == 0x01000090)
+ print("Swap\n");+ //swap(instr);
+ else if((instr & 0x0FE000F0) == 0x01800090)
+ print("Singleex\n");+ //singleex(instr);
+ else if((instr & 0x0FC000F0) == 0x90)
+ print("Multiply\n");+ //multiply(instr);
+ else if((instr & 0x0F8000F0) == 0x800090)
+ print("Multiplylong\n");+ //multiplylong(instr);
+ else if((instr & ((1<<26) | (1<<27))) == (1 << 26))
+ print("Single\n");+ //single(instr);
+ else if((instr & 0x0E000090) == 0x90 && (instr & 0x60))
+ print("Halfword\n");+ //halfword(instr);
+ else if((instr & ((1<<26) | (1<<27))) == 0)
+ print("Alu\n");+ //alu(instr);
+ else if((instr & (7<<25)) == (5 << 25))
+ print("Branch\n");+ //branch(instr);
+ else if((instr & (15<<24)) == (15 << 24))
+ print("Syscall\n");+ //_syscall();
+ else if((instr & (7<<25)) == (4 << 25))
+ print("Block\n");+ //block(instr);
+ else if((instr & 0x0E000F00) == 0x0C000100)
+ print("Fpatransfer\n");+ //fpatransfer(instr);
+ else if((instr & 0x0E000F10) == 0x0E000100)
+ print("Fpaoperation\n");+ //fpaoperation(instr);
+ else if((instr & 0x0E000F10) == 0x0E000110)
+ print("Fparegtransfer\n");+ //fparegtransfer(instr);
+ else if((instr & 0x0F000A10) == 0x0E000A00)
+ print("Vfpoperation\n");+ //vfpoperation(instr);
+ else if((instr & 0x0F000F10) == 0x0E000A10)
+ print("Vfpregtransfer\n");+ //vfpregtransfer(instr);
+ else if((instr & 0x0F000A00) == 0x0D000A00)
+ print("Vfprmtransfer\n");+ //vfprmtransfer(instr);
+ else {+ print("Invalid\n");+ invalid(instr);
+ return 0;
+ }
+ return 1;
+}
\ No newline at end of file
--- a/kern/dat.h
+++ b/kern/dat.h
@@ -1,7 +1,6 @@
#define KNAMELEN 28 /* max length of name held in kernel */
//#define BLOCKALIGN 8
-typedef struct Binary Binary;
typedef struct Block Block;
typedef struct Chan Chan;
typedef struct Cmdbuf Cmdbuf;
@@ -120,16 +119,21 @@
Bpktck = (1<<5), /* packet checksum */
};
-/* Not using segments, so this is our holder */
-struct Binary
-{- uintptr entry;
- uintptr text;
- uintptr data;
- uintptr bss;
- uintptr bs;
- uintptr ts;
- uintptr ds;
+enum {+ STACKSIZE = 0x100000,
+ NAMEMAX = 27,
+ NSMAX = 1000,
+ NNOTE = 5,
+ NSLOG = 7,
+ SEGNUM = 8,
+ Nfpregs = 16,
+ NSCACHE = (1<<NSLOG),
+
+ flN = 1<<31,
+ flZ = 1<<30,
+ flC = 1<<29,
+ flV = 1<<28,
+ FLAGS = flN | flZ | flC | flV,
};
struct Block
@@ -232,14 +236,6 @@
Qid qid[1];
};
-enum
-{- NSMAX = 1000,
- NSLOG = 7,
- NSCACHE = (1<<NSLOG),
- NNOTE = 5,
-};
-
struct Mntwalk /* state for /proc/#/ns */
{int cddone;
@@ -359,7 +355,7 @@
SEGDATA,
SEGBSS,
SEGSTACK,
- SEGNUM = 8,
+ SEGFLLOCK = 1,
};
@@ -383,7 +379,7 @@
Lock rlock; /* sync sleep/wakeup with postnote */
Rendez *r; /* rendezvous point slept on */
- Rendez sleep; /* place for syssleep/debug */
+ Rendez rsleep; /* place for syssleep/debug */
int notepending; /* note issued but not acted on */
int kp; /* true if a kernel process */
@@ -401,10 +397,16 @@
char genbuf[128]; /* buffer used e.g. for last name element from namec */
char text[KNAMELEN];
+
u32int lladdr; /* LL/SC emulation */
u32int llval;
+ u32int CPSR; /* status register */
+ u32int FPSR;
+ double F[Nfpregs];
+ int fd; /* fd for syscall emulation */
+
/* Notes */
u32int notehandler;
int innote;
@@ -415,19 +417,16 @@
Chan *dot;
Proc *qnext;
- Binary *bin;
-
+
void (*fn)(void*);
void *arg;
char oproc[1024]; /* reserved for os */
- u32int CPSR; /* status register for step */
- /* TODO: Multiarch */
+
u32int R[16]; /* general purpose registers / PC (R15) */
Segment *S[SEGNUM];
};
-
struct Segment {Ref ref;
int flags;
@@ -529,3 +528,4 @@
};
extern Kmesg kmesg;
+
--- a/kern/devmnt.c
+++ b/kern/devmnt.c
@@ -744,7 +744,7 @@
}
lock(&m->lk);
- r->z = &up->sleep;
+ r->z = &up->rsleep;
r->m = m;
r->list = m->queue;
m->queue = r;
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -2,13 +2,14 @@
Block* adjustblock(Block*, int);
Block* allocb(int);
-int blocklen(Block*);
+int blocklen(Block*);
+void *bufifnec(u32int, int, int *);
char* chanpath(Chan*);
-int cangetc(void*);
-int canlock(Lock*);
-int canputc(void*);
-int canqlock(QLock*);
-int canrlock(RWlock*);
+int cangetc(void*);
+int canlock(Lock*);
+int canputc(void*);
+int canqlock(QLock*);
+int canrlock(RWlock*);
void chandevinit(void);
void chandevreset(void);
void chandevshutdown(void);
@@ -17,8 +18,9 @@
void checkb(Block*, char*);
Chan* cclone(Chan*);
void cclose(Chan*);
-char* clipread(void);
-int clipwrite(char*);
+char* clipread(void);
+int clipwrite(char*);
+void clrex(void);
void closeegrp(Egrp*);
void closefgrp(Fgrp*);
void closemount(Mount*);
@@ -25,22 +27,24 @@
void closepgrp(Pgrp*);
void closergrp(Rgrp*);
void cmderror(Cmdbuf*, char*);
-int cmount(Chan*, Chan*, int, char*);
+int cmount(Chan*, Chan*, int, char*);
Block* concatblock(Block*);
+void copyback(u32int, int, void *);
Block* copyblock(Block*, int);
+void *copyifnec(u32int, int, int *);
void cunmount(Chan*, Chan*);
-int decref(Ref*);
+int decref(Ref*);
Chan* devattach(int, char*);
Block* devbread(Chan*, long, ulong);
long devbwrite(Chan*, Block*, ulong);
Chan* devclone(Chan*);
-int devconfig(int, char *, DevConf *);
+int devconfig(int, char *, DevConf *);
Chan* devcreate(Chan*, char*, int, ulong);
void devdir(Chan*, Qid, char*, vlong, char*, long, Dir*);
long devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
Devgen devgen;
void devinit(void);
-int devno(int, int);
+int devno(int, int);
Chan* devopen(Chan*, int, Dirtab*, int, Devgen*);
void devpermcheck(char*, ulong, int);
void devpower(int);
@@ -47,24 +51,30 @@
void devremove(Chan*);
void devreset(void);
void devshutdown(void);
-int devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*);
+int devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*);
Walkqid* devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
-int devwstat(Chan*, uchar*, int);
+int devwstat(Chan*, uchar*, int);
Dir* dirchanstat(Chan*);
void drawcmap(void);
+void donote(char *, ulong);
Fgrp* dupfgrp(Fgrp*);
-int emptystr(char*);
+int emptystr(char*);
void envcpy(Egrp*, Egrp*);
-int eqchan(Chan*, Chan*, int);
-int eqqid(Qid, Qid);
+int eqchan(Chan*, Chan*, int);
+int eqqid(Qid, Qid);
void error(char*);
+u32int evenaddr(u32int,u32int);
void exhausted(char*);
void exit(int);
void fdclose(int, int);
Chan* fdtochan(int, int, int, int);
+void fpatransfer(u32int);
+void fpaoperation(u32int);
+void fparegtransfer(u32int);
void free(void*);
void freeb(Block*);
void freeblist(Block*);
+void freesegs(void);
uintptr getmalloctag(void*);
uintptr getrealloctag(void*);
void gotolabel(Label*);
@@ -74,14 +84,15 @@
Block* iallocb(int);
void ilock(Lock*);
void iunlock(Lock*);
-int incref(Ref*);
-int iprint(char*, ...);
+int incref(Ref*);
+void invalid(u32int);
+int iprint(char*, ...);
void isdir(Chan*);
-int iseve(void);
+int iseve(void);
#define islo() (0)
-int kbdputc(Queue*, int);
+int kbdputc(Queue*, int);
void kbdkey(Rune, int);
-int kproc(char*, void(*)(void*), void*);
+int kproc(char*, void(*)(void*), void*);
void ksetenv(char*, char*, int);
void kstrcpy(char*, char*, int);
void kstrdup(char**, char*);
@@ -108,7 +119,8 @@
void muxclose(Mnt*);
Chan* namec(char*, int, int, ulong);
Chan* newchan(void);
-int newfd(Chan*);
+Segment *newseg(u32int, u32int, int);
+int newfd(Chan*);
Mhead* newmhead(Chan*);
Mount* newmount(Chan*, int, char*);
Path* newpath(char*);
@@ -117,10 +129,10 @@
Proc* newproc(void);
char* nextelem(char*, char*);
void nexterror(void);
-int openmode(ulong);
+int openmode(ulong);
void* oscmd(char**, int, char*, Chan**);
-int oscmdwait(void*, char*, int);
-int oscmdkill(void*);
+int oscmdwait(void*, char*, int);
+int oscmdkill(void*);
void oscmdfree(void*);
void oserrstr(void);
void oserror(void);
@@ -132,48 +144,48 @@
void pathclose(Path*);
void pexit(char*, int);
void printinit(void);
-int procindex(ulong);
+int procindex(ulong);
void pgrpcpy(Pgrp*, Pgrp*);
void pgrpnote(ulong, char*, long, int);
Pgrp* pgrptab(int);
#define poperror() up->nerrlab--
-int postnote(Proc*, int, char*, int);
-int pprint(char*, ...);
-int procfdprint(Chan*, int, int, char*, int);
+int postnote(Proc*, int, char*, int);
+int pprint(char*, ...);
+int procfdprint(Chan*, int, int, char*, int);
void procinit0(void);
Proc* proctab(int);
void procwired(Proc*, int);
-int pullblock(Block**, int);
+int pullblock(Block**, int);
Block* pullupblock(Block*, int);
Block* pullupqueue(Queue*, int);
void putmhead(Mhead*);
void putstr(char*);
void putstrn(char*, int);
-Label* pwaserror(void);
+Label* pwaserror(void);
long readblist(Block*, uchar*, long, ulong);
-int qaddlist(Queue*, Block*);
+int qaddlist(Queue*, Block*);
Block* qbread(Queue*, int);
long qbwrite(Queue*, Block*);
Queue* qbypass(void (*)(void*, Block*), void*);
-int qcanread(Queue*);
+int qcanread(Queue*);
void qclose(Queue*);
-int qconsume(Queue*, void*, int);
+int qconsume(Queue*, void*, int);
Block* qcopy(Queue*, int, ulong);
-int qdiscard(Queue*, int);
+int qdiscard(Queue*, int);
void qflush(Queue*);
void qfree(Queue*);
-int qfull(Queue*);
+int qfull(Queue*);
Block* qget(Queue*);
-void qhangup(Queue*, char*);
-int qisclosed(Queue*);
+void qhangup(Queue*, char*);
+int qisclosed(Queue*);
void qinit(void);
-int qiwrite(Queue*, void*, int);
-int qlen(Queue*);
+int qiwrite(Queue*, void*, int);
+int qlen(Queue*);
void qlock(QLock*);
Queue* qopen(int, int, void (*)(void*), void*);
-int qpass(Queue*, Block*);
-int qpassnolim(Queue*, Block*);
-int qproduce(Queue*, void*, int);
+int qpass(Queue*, Block*);
+int qpassnolim(Queue*, Block*);
+int qproduce(Queue*, void*, int);
void qputback(Queue*, Block*);
long qread(Queue*, void*, int);
Block* qremove(Queue*);
@@ -180,21 +192,24 @@
void qreopen(Queue*);
void qsetlimit(Queue*, int);
void qunlock(QLock*);
-int qwindow(Queue*);
-int qwrite(Queue*, void*, int);
+int qwindow(Queue*);
+int qwrite(Queue*, void*, int);
void qnoblock(Queue*, int);
void randominit(void);
ulong randomread(void*, ulong);
-int readnum(ulong, char*, ulong, ulong, int);
-int readstr(ulong, char*, ulong, char*);
-int return0(void*);
+int readnum(ulong, char*, ulong, ulong, int);
+int readstr(ulong, char*, ulong, char*);
+int return0(void*);
void rlock(RWlock*);
void runlock(RWlock*);
-extern void (*screenputs)(char*, int);
+extern void (*screenputs)(char*, int);
void* secalloc(ulong);
void secfree(void*);
long seconds(void);
-int setlabel(Label*);
+void segunlock(Segment*);
+int semacquire(long*, int);
+int semrelease(long*, long);
+int setlabel(Label*);
void setmalloctag(void*, uintptr);
void setrealloctag(void*, uintptr);
long showfilewrite(char*, int);
@@ -201,33 +216,37 @@
char* skipslash(char*);
void sleep(Rendez*, int(*)(void*), void*);
void* smalloc(ulong);
-int splhi(void);
-int spllo(void);
+int splhi(void);
+int spllo(void);
void splx(int);
+int step(void);
+void _syscall(void);
Block* trimblock(Block*, int, int);
long unionread(Chan*, void*, long);
void unlock(Lock*);
+void *vaddr(u32int, u32int, Segment **);
+void *vaddrnol(u32int, u32int);
#define validaddr(one, two, three);
void validname(char*, int);
char* validnamedup(char*, int);
void validstat(uchar*, int);
+void vfpregtransfer(u32int);
+void vfprmtransfer(u32int);
+void vfpoperation(u32int);
void* vmemchr(void*, int, ulong);
Proc* wakeup(Rendez*);
-int walk(Chan**, char**, int, int, int*);
-#define waserror() (setjmp(pwaserror()->buf))
+int walk(Chan**, char**, int, int, int*);
+#define waserror() (setjmp(pwaserror()->buf))
void wlock(RWlock*);
void wunlock(RWlock*);
void osyield(void);
void osmsleep(int);
-ulong ticks(void);
-void osproc(Proc*);
-void *osbuildmem(Chan *, uintptr, uintptr, uintptr, int, uintptr);
-void osprepmem(void*, uintptr, uintptr, uintptr, uintptr);
-void osnewproc(Proc*);
-void osclrmem(uintptr, uintptr);
-void procsleep(void);
-void procwakeup(Proc*);
-void osinit(void);
-void screeninit(void);
+ulong ticks(void);
+void osproc(Proc*);
+void osnewproc(Proc*);
+void procsleep(void);
+void procwakeup(Proc*);
+void osinit(void);
+void screeninit(void);
extern void terminit(void);
extern void setterm(int);
--- a/kern/posix.c
+++ b/kern/posix.c
@@ -266,88 +266,6 @@
return snprint(status, nstatus, "%d 0 0 0 'odd status: 0x%x'", pid, s);
}
-void
-osclrmem(uintptr mem, uintptr ms)
-{-
- if(mem)
-#if defined __APPLE__
- mach_vm_deallocate(task, (mach_vm_address_t)mem, (mach_vm_size_t)ms);
-#else
- munmap((void*)mem, ms);
-#endif
-}
-
-void *
-osbuildmem(Chan *tc, uintptr ts, uintptr ds, uintptr bss, int offset, uintptr align)
-{- int n;
- void *exec, *binary;
- size_t total_size;
-
- /* Read in initial datum */
- exec = mallocz(ts+ds, 1);
- n = devtab[tc->type]->read(tc, exec, ts+ds, offset);
- if(!exec || n < (ts+ds) || n < 0)
- error("read error: %r");-
-#if defined __APPLE__
- kern_return_t kr;
- mach_vm_address_t base = 0;
- mach_vm_size_t size = (mach_vm_size_t)(n + bss + align);
-
- kr = mach_vm_allocate(task, &base, size, VM_FLAGS_ANYWHERE);
- if(kr != KERN_SUCCESS)
- error("unable to allocate: %r");-
- binary = (void*)base;
-#else
- /* Contiguous memory block - start with RW for setup */
- binary = mmap(nil, n+bss+align, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
- if(binary == MAP_FAILED)
- error("Failed: %r");-#endif
- /* Copy the binary data (text + data sections) */
- memcpy(binary, exec, n);
- free(exec);
- return binary;
-}
-
-void
-osprepmem(void *base, uintptr b, uintptr text, uintptr data, uintptr bss)
-{- uintptr *ptr, end, offset;
-
- end = (uintptr)b+text+data;
- offset = (uintptr)b;
-
- /* If we needed to align, copy the data to the aligned location */
- if(b != (uintptr)base)
- memmove((void*)b, base, text+data);
-
- /* Zero out BSS section at aligned location */
- memset((void*)b + text + data, 0, bss);
-
- /* Patch the text + data sections to meet our new base */
- for(ptr = (uintptr*)b; (uintptr)ptr < end; ptr++) {- uintptr val = *ptr;
- if(val >= UTZERO && val <= (UTZERO + text + data)) {- *ptr = val + offset;
- }
- }
-
-#if defined __APPLE__
- kern_return_t kr;
- kr = mach_vm_protect(task, (mach_vm_address_t)b, (mach_vm_size_t)text, FALSE, VM_PROT_READ|VM_PROT_EXECUTE);
- if(kr != KERN_SUCCESS)
- print("Unable to vm_protect aligned text section: %s\n", mach_error_string(kr));-#else
- /* Set proper memory permissions for aligned sections */
- if(mprotect((void*)b, text, PROT_READ|PROT_EXEC) != 0)
- print("Unable to mprotect aligned text section: %r\n");-#endif
-}
-
int
oscmdkill(void *c)
{--- /dev/null
+++ b/kern/seg.c
@@ -1,0 +1,136 @@
+#include <u.h>
+#include <lib.h>
+#include "dat.h"
+#include "fns.h"
+
+// TODO: Update to 64 bit
+Segment *
+newseg(u32int start, u32int size, int idx)
+{+ Segment *s;
+
+ s = mallocz(sizeof *s, 1);
+ incref(&s->ref);
+ s->start = start;
+ s->size = size;
+ s->dref = malloc(size + sizeof(Ref));
+ memset(s->dref, 0, sizeof(Ref));
+ incref(s->dref);
+ s->data = s->dref + 1;
+ if(idx == SEGBSS)
+ s->flags = SEGFLLOCK;
+ up->S[idx] = s;
+ return s;
+}
+
+void
+freesegs(void)
+{+ Segment **s, *ss;
+
+ for(s = up->S; s < up->S + SEGNUM; s++) {+ if(*s == nil)
+ continue;
+ ss = *s;
+ if(decref((*s)->dref) == 0)
+ free((*s)->dref);
+ if(decref(&ss->ref) == 0)
+ free(*s);
+ *s = nil;
+ }
+}
+
+void *
+vaddr(u32int addr, u32int len, Segment **seg)
+{+ Segment **ss, *s;
+ for(ss = up->S; ss < up->S + SEGNUM; ss++) {+ if(*ss == nil)
+ continue;
+ s = *ss;
+ if(addr >= s->start && addr < s->start + s->size) {+ if(addr + len > s->start + s->size)
+ break;
+ if(s->flags & SEGFLLOCK)
+ rlock(&s->rw);
+ *seg = s;
+ return (char *)s->data + (addr - s->start);
+ }
+ }
+ fprint(2, "fault %.8ux (%d) @ %.8ux", addr, len, up->R[15]);
+ return nil;
+}
+
+void *
+vaddrnol(u32int addr, u32int len)
+{+ Segment *seg;
+ void *ret;
+
+ ret = vaddr(addr, len, &seg);
+ segunlock(seg);
+ return ret;
+}
+
+/* might be made a macro for hurr durr performance */
+void
+segunlock(Segment *s)
+{+ if(s->flags & SEGFLLOCK)
+ runlock(&s->rw);
+}
+
+void *
+copyifnec(u32int addr, int len, int *copied)
+{+ void *targ, *ret;
+ Segment *seg;
+
+ targ = vaddr(addr, len > 0 ? len : 0, &seg);
+ if((seg->flags & SEGFLLOCK) == 0) {+ *copied = 0;
+ return targ;
+ }
+ if(len < 0)
+ len = strlen(targ) + 1;
+ ret = malloc(len);
+ setmalloctag(ret, getcallerpc(&addr));
+ memcpy(ret, targ, len);
+ segunlock(seg);
+ *copied = 1;
+ return ret;
+}
+
+void *
+bufifnec(u32int addr, int len, int *buffered)
+{+ void *targ, *v;
+ Segment *seg;
+
+ targ = vaddr(addr, len, &seg);
+ if((seg->flags & SEGFLLOCK) == 0) {+ *buffered = 0;
+ return targ;
+ }
+ segunlock(seg);
+ *buffered = 1;
+ v = malloc(len);
+ setmalloctag(v, getcallerpc(&addr));
+ return v;
+}
+
+void
+copyback(u32int addr, int len, void *data)
+{+ void *targ;
+ Segment *seg;
+
+ if(len <= 0) {+ free(data);
+ return;
+ }
+ targ = vaddr(addr, len, &seg);
+ memmove(targ, data, len);
+ segunlock(seg);
+ free(data);
+}
\ No newline at end of file
--- /dev/null
+++ b/kern/sema.c
@@ -1,0 +1,188 @@
+/* Semaphore implementation for Plan 9 emulator */
+
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "user.h"
+
+/* Semaphore wait queue entry */
+typedef struct Semwait Semwait;
+struct Semwait {+ Semwait *next;
+ Proc *proc;
+ long *addr;
+};
+
+static Lock semlock;
+static Semwait *semwait;
+
+
+/*
+ * Semaphore sleep condition function
+ * Called by sleep() to check if we should continue sleeping
+ */
+int
+semwakeup(void *arg)
+{+ long *addr = (long*)arg;
+
+ /* Return 0 to continue sleeping, 1 to wake up */
+ return *addr > 0;
+}
+
+/*
+ * semacquire - acquire semaphore
+ * addr: pointer to semaphore counter
+ * block: 1 to block if unavailable, 0 to return immediately
+ *
+ * Returns: 0 on success, -1 on error
+ */
+int
+semacquire(long *addr, int block)
+{+ Semwait *w, **l;
+
+ if(addr == nil) {+ werrstr("semacquire: nil address");+ return -1;
+ }
+
+ lock(&semlock);
+
+ /* Try to decrement the semaphore */
+ if(*addr > 0) {+ (*addr)--;
+ unlock(&semlock);
+ return 0;
+ }
+
+ /* Semaphore is 0, can't acquire */
+ if(!block) {+ unlock(&semlock);
+ werrstr("semacquire: would block");+ return -1;
+ }
+
+ /* Block until semaphore is available */
+ w = malloc(sizeof(Semwait));
+ if(w == nil) {+ unlock(&semlock);
+ werrstr("semacquire: out of memory");+ return -1;
+ }
+
+ w->addr = addr;
+ w->proc = up;
+ w->next = semwait;
+ semwait = w;
+
+ /* Use the existing sleep rendezvous mechanism */
+ up->state = Wakeme;
+ unlock(&semlock);
+
+ /* Sleep on the semaphore address as rendezvous point */
+ if(waserror()) {+ /* Interrupted - remove from wait queue */
+ lock(&semlock);
+ for(l = &semwait; *l; l = &(*l)->next) {+ if(*l == w) {+ *l = w->next;
+ break;
+ }
+ }
+ unlock(&semlock);
+ free(w);
+ nexterror();
+ }
+
+ ksleep(&up->rsleep, semwakeup, addr);
+ poperror();
+
+ return 0;
+}
+
+/*
+ * semrelease - release semaphore
+ * addr: pointer to semaphore counter
+ * count: number of times to increment semaphore
+ *
+ * Returns: 0 on success, -1 on error
+ */
+int
+semrelease(long *addr, long count)
+{+ Semwait *w, **l;
+ Proc *p;
+
+ if(addr == nil) {+ werrstr("semrelease: nil address");+ return -1;
+ }
+
+ if(count <= 0) {+ werrstr("semrelease: bad count");+ return -1;
+ }
+
+ lock(&semlock);
+
+ /* Increment the semaphore counter */
+ *addr += count;
+
+ /* Wake up waiting processes */
+ l = &semwait;
+ while(*l && count > 0) {+ w = *l;
+ if(w->addr == addr) {+ /* Remove from wait list */
+ *l = w->next;
+
+ /* Wake up the process */
+ p = w->proc;
+ wakeup(&p->rsleep);
+
+ free(w);
+ count--;
+ (*addr)--; /* Process will consume one count */
+ } else {+ l = &w->next;
+ }
+ }
+
+ unlock(&semlock);
+ return 0;
+}
+
+/*
+ * Helper function to clean up semaphore waiters when process exits
+ * Call this from your process cleanup code
+ */
+void
+cleansemwait(Proc *p)
+{+ Semwait *w, **l;
+
+ lock(&semlock);
+ l = &semwait;
+ while(*l) {+ w = *l;
+ if(w->proc == p) {+ *l = w->next;
+ free(w);
+ } else {+ l = &w->next;
+ }
+ }
+ unlock(&semlock);
+}
+
+/*
+ * Initialize semaphore system - call during startup
+ */
+void
+seminit(void)
+{+ semwait = nil;
+}
\ No newline at end of file
--- /dev/null
+++ b/kern/sys.h
@@ -1,0 +1,52 @@
+#define SYSR1 0
+#define _ERRSTR 1
+#define BIND 2
+#define CHDIR 3
+#define CLOSE 4
+#define DUP 5
+#define ALARM 6
+#define EXEC 7
+#define EXITS 8
+#define _FSESSION 9
+#define FAUTH 10
+#define _FSTAT 11
+#define SEGBRK 12
+#define _MOUNT 13
+#define OPEN 14
+#define _READ 15
+#define OSEEK 16
+#define SLEEP 17
+#define _STAT 18
+#define RFORK 19
+#define _WRITE 20
+#define PIPE 21
+#define CREATE 22
+#define FD2PATH 23
+#define BRK_ 24
+#define REMOVE 25
+#define _WSTAT 26
+#define _FWSTAT 27
+#define NOTIFY 28
+#define NOTED 29
+#define SEGATTACH 30
+#define SEGDETACH 31
+#define SEGFREE 32
+#define SEGFLUSH 33
+#define RENDEZVOUS 34
+#define UNMOUNT 35
+#define _WAIT 36
+#define SEMACQUIRE 37
+#define SEMRELEASE 38
+#define SEEK 39
+#define FVERSION 40
+#define ERRSTR 41
+#define STAT 42
+#define FSTAT 43
+#define WSTAT 44
+#define FWSTAT 45
+#define MOUNT 46
+#define AWAIT 47
+#define PREAD 50
+#define PWRITE 51
+#define TSEMACQUIRE 52
+#define _NSEC 53
\ No newline at end of file
--- a/kern/syscall.c
+++ b/kern/syscall.c
@@ -4,92 +4,650 @@
#include "fns.h"
#include "error.h"
#include "user.h"
+#include "sys.h"
-long
-sysintercept(void* r0, void* r1, void* r2, void* r3, void* r4, void* r5, void* r6)
+static u32int
+arg(int n)
{- print("Interception %d\n", r0);- long ret = -1;
- switch((int)r0){- case 0: /* SYSR1 */
- ret = 0;
- break;
- case 1: /* _ERRSTR */
- ret = errstr((char*)r1, 64);
- break;
- case 2: /* BIND */
- ret = bind((char*) r1, (char*)r2, (int) r3);
- break;
- case 3: /* CHDIR */
- ret = chdir((char *)r1);
- break;
- case 4: /* CLOSE */
- ret = close((int)r1);
- break;
- case 5: /* DUP */
- ret = dup((int)r1, (int)r2);
- break;
- case 6: /* ALARM */
- ret = alarm((int) r1);
- break;
- case 7: /* EXEC */
- ret = exec((int) r1, (char**)r2);
- break;
- case 8: /* EXITS */
- exits((char*)r1);
- ret = 0;
- break;
- case 9: /* _FSESSION */
- //ret = fsession();
- break;
- case 10: /* FAUTH */
- // ret = fauth();
- break;
- case 11: /* _FSTAT */
- ret = fstat((int) r1, (char*) r2, (int)r3);
- break;
- case 12: /* SEGBRK */
- case 13: /* _MOUNT */
- case 14: /* OPEN */
- case 15: /* _READ */
- case 16: /* OSEEK */
- case 17: /* SLEEP */
- case 18: /* _STAT */
- case 19: /* RFORK */
- case 20: /* _WRITE */
- case 21: /* PIPE */
- case 22: /* CREATE */
- case 23: /* FD2PATH */
- case 24: /* BRK_ */
- case 25: /* REMOVE */
- case 26: /* _WSTAT */
- case 27: /* _FWSAT */
- case 28: /* NOTIFY */
- case 29: /* NOTED */
- case 30: /* SEGATTACH */
- case 31: /* SEGDETACH */
- case 32: /* SEGFREE */
- case 33: /* SEGFLUSH */
- case 34: /* RENDEZVOUS */
- case 35: /* UNMOUNT */
- case 36: /* _WAIT */
- case 37: /* SEMACQUIRE */
- case 38: /* SEMRELEASE */
- case 39: /* SEEK */
- case 40: /* FVERSION */
- case 41: /* ERRSTR */
- case 42: /* STAT */
- case 43: /* FSTAT */
- case 44: /* WSTAT */
- case 45: /* FWSTAT */
- case 46: /* MOUNT */
- case 47: /* AWAIT */
- case 50: /* PREAD */
- case 51: /* PWRITE */
- case 52: /* TSEMACQUIRE */
- case 53: /* _NSEC */
- break;
- }
+ /* no locking necessary, since we're on the stack */
+ return *(u32int*) vaddrnol(up->R[13] + 4 + 4 * n, 4);
+}
- return ret;
+static u64int
+argv(int n)
+{+ return arg(n) | ((u64int)arg(n+1) << 32);
}
+
+u32int
+noteerr(u32int x, u32int y)
+{+ if(((int)x) >= ((int)y))
+ return x;
+ rerrstr(up->errstr, ERRMAX);
+ return x;
+}
+
+void
+cherrstr(char *str, ...)
+{+ va_list va;
+
+ va_start(va, str);
+ vsnprint(up->errstr, ERRMAX, str, va);
+ va_end(va);
+}
+
+static void
+_sysopen(void)
+{+ u32int name, flags;
+ char *namet;
+ int fd, copied;
+
+ name = arg(0);
+ flags = arg(1);
+ namet = copyifnec(name, -1, &copied);
+ fd = open(namet, flags);
+ if(copied)
+ free(namet);
+ if(fd < 0) {+ noteerr(0, 1);
+ up->R[0] = fd;
+ return;
+ }
+ up->R[0] = fd;
+}
+
+static void
+_syscreate(void)
+{+ u32int name, flags, perm;
+ char *namet;
+ int fd, copied;
+
+ name = arg(0);
+ flags = arg(1);
+ perm = arg(2);
+ namet = copyifnec(name, -1, &copied);
+ fd = create(namet, flags, perm);
+ if(copied)
+ free(namet);
+ if(fd < 0) {+ noteerr(0, 1);
+ up->R[0] = fd;
+ return;
+ }
+ up->R[0] = fd;
+}
+
+static void
+_sysclose(void)
+{+ u32int fd;
+
+ fd = arg(0);
+ up->R[0] = noteerr(close(fd), 0);
+}
+
+static void
+_syspread(void)
+{+ int buffered;
+ u32int fd, size, buf;
+ u64int off;
+ void *targ;
+
+ fd = arg(0);
+ buf = arg(1);
+ size = arg(2);
+ off = argv(3);
+ targ = bufifnec(buf, size, &buffered);
+ up->R[0] = noteerr(pread(fd, targ, size, off), size);
+ if(buffered)
+ copyback(buf, up->R[0], targ);
+}
+
+static void
+_syspwrite(void)
+{+ u32int fd, size, buf;
+ u64int off;
+ int copied;
+ void *buft;
+
+ fd = arg(0);
+ buf = arg(1);
+ size = arg(2);
+ off = argv(3);
+ buft = copyifnec(buf, size, &copied);
+ up->R[0] = noteerr(pwrite(fd, buft, size, off), size);
+ if(copied)
+ free(buft);
+}
+
+static void
+_sysseek(void)
+{+ u32int fd, type;
+ vlong n, *ret;
+ Segment *seg;
+
+ ret = vaddr(arg(0), 8, &seg);
+ fd = arg(1);
+ n = argv(2);
+ type = arg(4);
+ *ret = seek(fd, n, type);
+ if(*ret < 0) noteerr(0, 1);
+ segunlock(seg);
+}
+
+static void
+_sysfd2path(void)
+{+ u32int fd, buf, nbuf;
+ void *buft;
+ int buffered;
+
+ fd = arg(0);
+ buf = arg(1);
+ nbuf = arg(2);
+ buft = bufifnec(buf, nbuf, &buffered);
+ up->R[0] = noteerr(fd2path(fd, buft, nbuf), 0);
+ if(buffered)
+ copyback(buf, nbuf, buft);
+}
+
+static void
+_sysstat(void)
+{+ u32int name, edir, nedir;
+ char *namet;
+ void *edirt;
+ int copied, buffered;
+
+ name = arg(0);
+ namet = copyifnec(name, -1, &copied);
+ edir = arg(1);
+ nedir = arg(2);
+ edirt = bufifnec(edir, nedir, &buffered);
+ up->R[0] = noteerr(sysstat(namet, edirt, nedir), nedir);
+ if(copied)
+ free(namet);
+ if(buffered)
+ copyback(edir, up->R[0], edirt);
+}
+
+static void
+_sysfstat(void)
+{+ u32int fd, edir, nedir;
+ void *edirt;
+ int buffered;
+
+ fd = arg(0);
+ edir = arg(1);
+ nedir = arg(2);
+ edirt = bufifnec(edir, nedir, &buffered);
+ up->R[0] = noteerr(sysfstat(fd, edirt, nedir), nedir);
+ if(buffered)
+ copyback(edir, up->R[0], edirt);
+}
+
+static void
+_syswstat(void)
+{+ u32int name, edir, nedir;
+ char *namet;
+ void *edirt;
+ int copied, copied2;
+
+ name = arg(0);
+ namet = copyifnec(name, -1, &copied);
+ edir = arg(1);
+ nedir = arg(2);
+ edirt = copyifnec(edir, nedir, &copied2);
+ up->R[0] = noteerr(syswstat(namet, edirt, nedir), nedir);
+ if(copied)
+ free(namet);
+ if(copied2)
+ free(edirt);
+}
+
+static void
+_sysfwstat(void)
+{+ u32int fd, edir, nedir;
+ void *edirt;
+ int copied;
+
+ fd = arg(0);
+ edir = arg(1);
+ nedir = arg(2);
+ edirt = copyifnec(edir, nedir, &copied);
+ up->R[0] = noteerr(sysfwstat(fd, edirt, nedir), nedir);
+ if(copied)
+ free(edirt);
+}
+
+// TODO: This may be better done as a longjmp back
+static void
+_sysexits(void)
+{+ if(arg(0) == 0)
+ exits(nil);
+ else
+ exits(vaddrnol(arg(0), 0));
+}
+
+static void
+_sysbrk(void)
+{+ ulong v;
+ Segment *s;
+
+ v = arg(0);
+ v = v + 7 & -8;
+ if(v >= up->S[SEGSTACK]->start)
+ fprint(2, "bss > stack, wtf?");
+ if(v < up->S[SEGBSS]->start)
+ fprint(2, "bss length < 0, wtf?");
+ s = up->S[SEGBSS];
+ wlock(&s->rw);
+ s->dref = realloc(s->dref, v - s->start + sizeof(Ref));
+ if(s->dref == nil)
+ fprint(2, "error reallocating");
+ s->data = s->dref + 1;
+ if(s->size < v - s->start)
+ memset((char*)s->data + s->size, 0, v - s->start - s->size);
+ s->size = v - s->start;
+ up->R[0] = 0;
+ wunlock(&s->rw);
+}
+
+static void
+_syserrstr(void)
+{+ char buf[ERRMAX], *srct;
+ u32int src, len;
+ int copied;
+
+ src = arg(0);
+ len = arg(1);
+ srct = copyifnec(src, len, &copied);
+ strcpy(buf, up->errstr);
+ utfecpy(up->errstr, up->errstr + ERRMAX, srct);
+ utfecpy(srct, srct + len, buf);
+ if(copied)
+ copyback(src, len, srct);
+ up->R[0] = 0;
+}
+
+static void
+_syschdir(void)
+{+ u32int dir;
+ char *dirt;
+ int copied;
+
+ dir = arg(0);
+ dirt = copyifnec(dir, -1, &copied);
+ up->R[0] = noteerr(syschdir(dirt), 0);
+ if(copied)
+ free(dirt);
+}
+
+static void
+_sysnotify(void)
+{+ u32int handler;
+
+ handler = arg(0);
+ up->notehandler = handler;
+ up->R[0] = 0;
+}
+
+static void
+_sysnoted(void)
+{+ u32int v;
+
+ v = arg(0);
+ if(up->innote)
+ longjmp(up->notejmp, v + 1);
+ cherrstr("the front fell off");+ up->R[0] = -1;
+}
+
+
+static void
+_sysrfork(void)
+{+ u32int flags;
+ int rc, i;
+ Segment *s, *t;
+ Proc *p;
+ int old;
+
+ flags = arg(0);
+
+ if((flags & (RFFDG | RFCFDG)) == (RFFDG | RFCFDG) ||
+ (flags & (RFNAMEG | RFCNAMEG)) == (RFNAMEG | RFCNAMEG) ||
+ (flags & (RFENVG | RFCENVG)) == (RFENVG | RFCENVG)) {+ up->R[0] = -1;
+ cherrstr("bad arg in syscall");+ return;
+ }
+ if((flags & RFPROC) == 0) {+ if(flags & RFFDG) {+ old = up->fd;
+ up->fd = copyfd(up->fd);
+ fddecref(old);
+ }
+ if(flags & RFCFDG) {+ old = up->fd;
+ //up->fd = newfd();
+ fddecref(old);
+ }
+ up->R[0] = noteerr(rfork(flags), 0);
+ return;
+ }
+ //incref(&nproc);
+ p = emallocz(sizeof(Proc));
+ memcpy(p, up, sizeof(Proc));
+ for(i = 0; i < SEGNUM; i++) {+ s = p->S[i];
+ if(s == nil)
+ continue;
+ if((flags & RFMEM) == 0 && i != SEGTEXT || i == SEGSTACK) {+ t = emallocz(sizeof(Segment));
+ incref(t);
+ t->size = s->size;
+ t->start = s->start;
+ t->dref = emalloc(sizeof(Ref) + s->size);
+ memset(t->dref, 0, sizeof(Ref));
+ incref(t->dref);
+ t->data = t->dref + 1;
+ memcpy(t->data, s->data, s->size);
+ p->S[i] = t;
+ } else {+ incref(s->dref);
+ incref(s);
+ }
+ }
+
+ if(flags & RFFDG)
+ p->fd = copyfd(up->fd);
+ //else if(flags & RFCFDG)
+ // p->fd = newfd();
+ //else
+ // incref(up->fd);
+
+ //incref(up->path);
+ rc = rfork(RFMEM | flags);
+ if(rc < 0) /* this should NEVER happen */
+ sysfatal("rfork failed wtf: %r");+ if(rc == 0) {+ // up = p;
+ //atexit(cleanup);
+ up->pid = getpid();
+ inittos();
+ // addproc(P);
+ }
+ up->R[0] = rc;
+}
+
+
+static void
+_sysexec(void)
+{+ u32int name, argv, *argvt;
+ char *namet, **argvv;
+ int i, argc, rc;
+ Segment *seg1, *seg2;
+
+ name = arg(0);
+ argv = arg(1);
+ namet = strdup(vaddr(name, 0, &seg1));
+ segunlock(seg1);
+ argvt = vaddr(argv, 0, &seg1);
+ for(argc = 0; argvt[argc]; argc++)
+ ;
+ argvv = emalloc(sizeof(char *) * argc);
+ for(i = 0; i < argc; i++) {+ argvv[i] = strdup(vaddr(argvt[i], 0, &seg2));
+ segunlock(seg2);
+ }
+ segunlock(seg1);
+ rc = loadtext(namet, argc, argvv);
+ for(i = 0; i < argc; i++)
+ free(argvv[i]);
+ free(argvv);
+ if(rc < 0)
+ up->R[0] = noteerr(rc, 0);
+ free(namet);
+}
+
+static void
+_sysawait(void)
+{+ u32int s, n;
+ void *st;
+ int buffered;
+
+ s = arg(0);
+ n = arg(1);
+ st = bufifnec(s, n, &buffered);
+ up->R[0] = noteerr(await(st, n), 0);
+ if(buffered)
+ copyback(s, up->R[0], st);
+}
+
+static void
+_syspipe(void)
+{+ u32int fd, *fdt;
+ int buffered;
+
+ fd = arg(0);
+ fdt = bufifnec(fd, 8, &buffered);
+ up->R[0] = noteerr(syspipe((int *) fdt), 0);
+ if(buffered)
+ copyback(fd, 8, fdt);
+}
+
+static void
+_sysdup(void)
+{+ u32int oldfd, newfd;
+
+ oldfd = arg(0);
+ newfd = arg(1);
+ up->R[0] = noteerr(dup2(oldfd, newfd), 0);
+}
+
+static void
+_syssleep(void)
+{+ u32int n;
+
+ n = arg(0);
+ osmsleep(n);
+ up->R[0] = 0;
+}
+
+static void
+_sysrendezvous(void)
+{+ u32int tag, value;
+
+ tag = arg(0);
+ value = arg(1);
+ up->R[0] = (u32int) (uintptr)sysrendezvous((void *)tag, (void *)value);
+ if(up->R[0] == ~0)
+ noteerr(0, 1);
+}
+
+static void
+_sysmount(void)
+{+ u32int fd, afd, old, flag, aname;
+ char *oldt, *anamet;
+ int copiedold, copiedaname;
+
+ fd = arg(0);
+ afd = arg(1);
+ old = arg(2);
+ flag = arg(3);
+ aname = arg(4);
+ oldt = copyifnec(old, -1, &copiedold);
+ if(aname) {+ anamet = copyifnec(aname, -1, &copiedaname);
+ } else {+ anamet = nil;
+ copiedaname = 0;
+ }
+ up->R[0] = noteerr(sysmount(fd, afd, oldt, flag, anamet), 0);
+ if(copiedold)
+ free(oldt);
+ if(copiedaname)
+ free(anamet);
+}
+
+static void
+_sysbind(void)
+{+ u32int name, old, flags;
+ char *namet, *oldt;
+ int copiedname, copiedold;
+
+ name = arg(0);
+ old = arg(1);
+ flags = arg(2);
+ namet = copyifnec(name, -1, &copiedname);
+ oldt = copyifnec(old, -1, &copiedold);
+ up->R[0] = noteerr(sysbind(namet, oldt, flags), 0);
+ if(copiedname)
+ free(namet);
+ if(copiedold)
+ free(oldt);
+}
+
+static void
+_sysunmount(void)
+{+ u32int name, old;
+ char *namet, *oldt;
+ int copiedname, copiedold;
+
+ name = arg(0);
+ old = arg(1);
+ oldt = copyifnec(old, -1, &copiedold);
+ if(name == 0) {+ namet = nil;
+ copiedname = 0;
+ up->R[0] = noteerr(sysunmount(nil, oldt), 0);
+ } else {+ namet = copyifnec(name, -1, &copiedname);
+ up->R[0] = noteerr(sysunmount(namet, oldt), 0);
+ }
+ if(copiedold)
+ free(oldt);
+ if(copiedname)
+ free(namet);
+}
+
+static void
+_sysremove(void)
+{+ u32int file;
+ char *filet;
+ int copied;
+
+ file = arg(0);
+ filet = copyifnec(file, -1, &copied);
+ up->R[0] = noteerr(sysremove(filet), 0);
+ if(copied)
+ free(filet);
+}
+
+static void
+_sysalarm(void)
+{+ u32int msec;
+
+ msec = arg(0);
+ up->R[0] = alarm(msec);
+}
+
+static void
+_syssemacquire(void)
+{+ u32int addr, block;
+ long *addrt;
+
+ addr = arg(0);
+ block = arg(1);
+ addrt = vaddrnol(addr, 4);
+ // Still need semaphores
+ up->R[0] = noteerr(semacquire(addrt, block), 0);
+}
+
+static void
+_syssemrelease(void)
+{+ u32int addr, count;
+ long *addrt;
+ Segment *seg;
+
+ addr = arg(0);
+ count = arg(1);
+ addrt = vaddr(addr, 4, &seg);
+ // Still need semaphores
+ up->R[0] = noteerr(semrelease(addrt, count), 0);
+ segunlock(seg);
+}
+
+void
+_syscall(void)
+{+ u32int n;
+ static void (*calls[])(void) = {+ [EXITS] = _sysexits,
+ [CLOSE] = _sysclose,
+ [OPEN] = _sysopen,
+ [CREATE] = _syscreate,
+ [PREAD] = _syspread,
+ [PWRITE] = _syspwrite,
+ [BRK_] = _sysbrk,
+ [ERRSTR] = _syserrstr,
+ [STAT] = _sysstat,
+ [FSTAT] = _sysfstat,
+ [WSTAT] = _syswstat,
+ [FWSTAT] = _sysfwstat,
+ [SEEK] = _sysseek,
+ [CHDIR] = _syschdir,
+ [FD2PATH] = _sysfd2path,
+ [NOTIFY] = _sysnotify,
+ [NOTED] = _sysnoted,
+ [RFORK] = _sysrfork,
+ [EXEC] = _sysexec,
+ [AWAIT] = _sysawait,
+ [PIPE] = _syspipe,
+ [SLEEP] = _syssleep,
+ [RENDEZVOUS] = _sysrendezvous,
+ [BIND] = _sysbind,
+ [UNMOUNT] = _sysunmount,
+ [DUP] = _sysdup,
+ [MOUNT] = _sysmount,
+ [REMOVE] = _sysremove,
+ [ALARM] = _sysalarm,
+ [SEMACQUIRE] = _syssemacquire,
+ [SEMRELEASE] = _syssemrelease,
+ };
+
+ n = up->R[0];
+ if(n >= nelem(calls) || calls[n] == nil)
+ fprint(2, "no such syscall %d @ %#ux", n, up->R[15] - 4);
+ calls[n]();
+}
\ No newline at end of file
--- a/kern/sysproc.c
+++ b/kern/sysproc.c
@@ -5,6 +5,7 @@
#include "error.h"
#include "user.h"
#include "mem.h"
+#include "sys.h"
#include <a.out.h>
#include <signal.h>
#include <sys/mman.h>
@@ -20,33 +21,13 @@
USED(x);
}
-static void
-sigsegv(int sig)
+static u32int
+arg(int n)
{- print("Segfault: %d: %r\n", sig);- longjmp(exec_jmp, 2);
+ /* no locking necessary, since we're on the stack */
+ return *(u32int*) vaddrnol(up->R[13] + 4 + 4 * n, 4);
}
-static void
-sigquit(int sig)
-{- print("Sigquittin': %r\n");- longjmp(exec_jmp, 1);
-}
-
-static void
-sigbus(int sig)
-{- print("Bussin': %r\n");- longjmp(exec_jmp, 2);
-}
-
-static void
-sigsys(int sig)
-{- print("We here!!! sig %d\n", sig);-}
-
int
sysrfork(int flags)
{@@ -188,15 +169,6 @@
| (uvlong)p[7];
}
-void
-evenaddr(uintptr addr)
-{- if(addr & 3){- postnote(up, 1, "sys: odd address", NDebug);
- error(Ebadarg);
- }
-}
-
void*
vmemchr(void *s, int c, ulong n)
{@@ -222,125 +194,196 @@
}
#undef read
-int
-sysexec(int argc, char **argv)
+/* Load text and data segments into memory */
+
+
+/* the following code is not for the weak of heart */
+void
+donote(char *msg, ulong type)
{- union {- struct {- Exec ex;
- uvlong hdr[1];
- } ehdr;
- char buf[256];
- } u;
- void (*_main)(int, char*[]);
- char line[256];
- char *progarg[32+1];
- char *file, *elem;
- void *base;
- Chan *tc;
- ulong magic;
- uintptr t, b, entry, text, data, bss, align;
- int n, indir;
+ int rc;
+ u32int *ureg, *sp, uregp, msgp;
+ char *msgb;
- elem = nil;
- align = BY2PG-1;
- indir = 0;
- file = argv[0];
+ print("In donote\n");+ if(up->notehandler == 0)
+ exits(msg);
- 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(u.ehdr);
- }
- if(entry < text)
- error(Ebadexec);
- text += beswal(u.ehdr.ex.text);
- if(text <= entry || text >= (USTKTOP-USTKSIZE))
- error(Ebadexec);
- switch(magic){- case S_MAGIC:
- align = 0x1fffff;
- break;
- case P_MAGIC:
- case V_MAGIC:
- align = 0x3fff;
- break;
- case R_MAGIC:
- align = 0xffff;
- break;
- }
- break;
- }
- }
- if(indir++)
- error(Ebadexec);
+ clrex();
+ uregp = up->R[13] - 18 * 4;
+ ureg = vaddrnol(uregp, 18 * 4);
+ memcpy(ureg, up->R, 15 * 4);
+ ureg[15] = type;
+ ureg[16] = up->CPSR;
+ ureg[17] = up->R[15];
+ up->R[13] = uregp;
+ msgp = up->R[13] -= ERRMAX;
+ msgb = vaddrnol(msgp, ERRMAX);
+ strncpy(msgb, msg, ERRMAX);
+ up->R[13] -= 3 * 4;
+ sp = vaddrnol(up->R[13], 3 * 4);
+ sp[0] = 0;
+ sp[2] = msgp;
+ up->R[0] = uregp;
+ up->R[15] = up->notehandler;
+ up->innote = 1;
+ switch(rc = setjmp(up->notejmp) - 1) {+ case -1:
+ for(;;) {+ step();
+ }
+ case NDFLT:
+ exits(msg);
+ case NCONT:
+ break;
+ default:
+ sysfatal("unhandled noted argument %d", rc);+ }
+ up->innote = 0;
+ ureg = vaddrnol(uregp, 18 * 4); /* just to be sure */
+ memcpy(up->R, ureg, 15 * 4);
+ up->CPSR = ureg[16];
+ up->R[15] = ureg[17];
+}
- memmove(line, u.buf, sizeof(u.buf));
- n = shargs(line, n, progarg, nelem(progarg));
- if(n < 1)
- error(Ebadexec);
- progarg[n++] = file;
- progarg[n] = nil;
- file = progarg[0];
- progarg[0] = elem;
- poperror();
- cclose(tc);
- }
- text -= UTZERO;
- entry -= UTZERO;
- data = beswal(u.ehdr.ex.data);
- bss = beswal(u.ehdr.ex.bss);
+static void
+initstack(int argc, char **argv)
+{+ ulong tos, sp, ap, size, i, len;
+
+ tos = USTKTOP - sizeof(Tos) * 2;
+ sp = tos;
+
+ size = 8;
+ for(i = 0; i < argc; i++)
+ size += strlen(argv[i]) + 5;
+
+ sp -= size;
+ sp &= ~7;
+ up->R[0] = tos;
+ up->R[1] = USTKTOP - 4;
+ up->R[13] = sp;
+
+ *(ulong *) vaddrnol(sp, 4) = argc;
+ sp += 4;
+ ap = sp + (argc + 1) * 4;
+ for(i = 0; i < argc; i++) {+ *(ulong *) vaddrnol(sp, 4) = ap;
+ sp += 4;
+ len = strlen(argv[i]) + 1;
+ memcpy(vaddrnol(ap, len), argv[i], len);
+ ap += len;
+ }
+ *(ulong *) vaddrnol(sp, 4) = 0;
+ inittos();
+}
- /* Set up text, data, and bss. OS dependent. */
- base = osbuildmem(tc, text, data, bss, sizeof(u.ehdr), align);
- b = ((uintptr)base + align) & ~align;
- /* Handle alignment, BSS setup, and memory protection. OS dependent. */
- osprepmem(base, b, text, data, bss);
+void
+inittos(void)
+{+ ulong tos;
- poperror();
- cclose(tc);
+ tos = USTKTOP - sizeof(Tos) * 2;
+ ((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = up->pid;
+}
- /* Meaningful signals to us */
- signal(SIGSEGV, sigsegv);
- signal(SIGQUIT, sigquit);
- signal(SIGINT, sigquit);
- signal(SIGSYS, sigsys);
- signal(SIGBUS, sigbus);
+// TODO: fd has to go away here.
+static int
+loadscript(int fd, char *file, int argc, char **argv)
+{+ char buf[513], *p, **q, **nargv;
+ int rc, nargc, i;
+
+ seek(fd, 0, 0);
+ rc = readn(fd, buf, 512);
+ if(rc <= 0)
+ goto invalid;
+ close(fd);
+ buf[rc] = 0;
+ p = strchr(buf, '\n');
+ if(p == nil)
+ goto invalid;
+ *p = 0;
+ while(isspace(*--p))
+ *p = 0;
+ nargc = 0;
+ p = buf + 2;
+ while(*p) {+ while(*p && isspace(*p))
+ p++;
+ nargc++;
+ while(*p && !isspace(*p))
+ p++;
+ }
+ if(nargc == 0)
+ goto invalid;
+ nargv = emallocz(sizeof(char *) * (nargc + argc));
+ q = nargv;
+ p = buf + 2;
+ while(*p) {+ while(*p && isspace(*p))
+ p++;
+ *(p-1) = 0;
+ *q++ = p;
+ while(*p && !isspace(*p))
+ p++;
+ }
+ *q++ = file;
+ for(i = 1; i < argc; i++)
+ *q++ = argv[i];
+ rc = loadtext(*nargv, argc + nargc, nargv);
+ free(nargv);
+ return rc;
- switch(setjmp(exec_jmp)) {- case 0:
- print("Base %p, Aligned base %p, Entry offset %lx, Text %lx\n", base, (void*)b, entry, text);+invalid:
+ werrstr("exec header invalid");+ return -1;
+}
- _main = (void (*)(int, char*[]))(b+entry);
- _main(argc, argv);
+int
+loadtext(char *file, int argc, char **argv)
+{+ Segment *text, *data, *bss;
+ char buf[2];
+ Chan *tc;
+ int n;
+ union {+ struct {+ Exec ex;
+ uvlong hdr[1];
+ } ehdr;
+ char buf[256];
+ } u;
- longjmp(exec_jmp, 1);
- break;
- case 1:
- osclrmem((uintptr)b, text+data+bss);
- break;
- case 2:
- //error("Signal: %r");- return -1;
- }
+ tc = namec(file, Aopen, OEXEC, 0);
+ n = devtab[tc->type]->read(tc, u.buf, sizeof(u.buf), 0);
- return 0;
-}
\ No newline at end of file
+ copyname(file);
+ up->notehandler = up->innote = up->notein = up->noteout = 0;
+ freesegs();
+ memset(up->R, 0, sizeof(up->R));
+ up->CPSR = 0;
+ // Read instead with beswav(whatever)
+ //text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT);
+ //data = newseg(fp.dataddr, fp.datsz, SEGDATA);
+ //bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS);
+ //newseg(USTKTOP - STACKSIZE, STACKSIZE, SEGSTACK);
+ // This also doesn't work, we want to read in the devtab way
+ //seek(fd, fp.txtoff - fp.hdrsz, 0);
+ //if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)
+ // sysfatal("%r");+ //seek(fd, fp.datoff, 0);
+ //if(readn(fd, data->data, fp.datsz) < fp.datsz)
+ // sysfatal("%r");+ //memset(bss->data, 0, bss->size);
+ //up->R[15] = fp.entry;
+ //if(havesymbols && syminit(fd, &fp) < 0)
+ // fprint(2, "initializing symbol table: %r\n");
+ //close(fd);
+ fdclear(up->fd);
+ initstack(argc, argv);
+ resetfpa();
+ return 0;
+}
--- a/main.c
+++ b/main.c
@@ -5,9 +5,9 @@
#include "user.h"
#include "drawcpu.h"
#include "arg.h"
+#include "proc.h"
char *argv0;
-char *dbgfile = "./debug.log";
int debug;
void
@@ -48,12 +48,24 @@
exit(1);
}
+int
+notehandler(void *, char *note)
+{+ if(strncmp(note, "sys:", 4) == 0)
+ return 0;
+
+ if(strncmp(note, "emu:", 4) == 0)
+ exits(note);
+ addnote(note);
+ return 1;
+}
+
int
main(int argc, char **argv)
{extern ulong kerndate;
- char *path;
+ char *path, *file;
path = nil;
kerndate = seconds();
@@ -98,14 +110,25 @@
if(path != nil)
bind(path, "/bin", MAFTER);
- char *cmd[] = {- // Substitute the real path to a useful binary here
- // It should be a 9front binary for the architecture
- // of the host machine (the one you're compiling on)
- "./Users/halfwit/Downloads/drawcpu/bin/echo",
- "hi"
- };
+ if(**argv == '/' || **argv == '.' || **argv == '#') {+ // TODO: Export loadtext from the kernel
+ if(loadtext(*argv, argc, argv) < 0)
+ sysfatal("loadtext: %r");+ return;
+ }
+ file = smprint("/bin/%s", *argv);+ if(loadtext(file, argc, argv) < 0)
+ sysfatal("loadtext: %r");+ free(file);
- exec(2, cmd);
- _exit(0);
+ // TODO: Export step() from the kernel
+ atnotify(notehandler, 1);
+ for(;;) {+ // Kernel step, while this greys kernelspace/userspace this is the cleaner approach
+ step();
+ while((up->notein - up->noteout) % NNOTE) {+ donote(up->notes[up->noteout % NNOTE], 0);
+ ainc(&up->noteout);
+ }
+ }
}
--- a/posix-amd64/Makefile
+++ b/posix-amd64/Makefile
@@ -7,7 +7,7 @@
OFILES=\
getcallerpc.$O\
tas.$O\
- trampoline.$O\
+ cas.$O\
default: $(LIB)
$(LIB): $(OFILES)
--- a/posix-amd64/trampoline.c
+++ /dev/null
@@ -1,79 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "../kern/fns.h"
-#include "mem.h"
-
-/* TODO: This is not arm64 code, this is amd64 code */
-extern void asm_syscall_hook(void);
-void ____asm_syscall_hook(void)
-{- /*
- * asm_syscall_hook is the address where the
- * trampoline code first jumps to.
- *
- * the procedure below calls the C function
- * namded syscall_hook.
- *
- * at the entry point of this,
- * the register values follow the calling convention
- * of the system calls. the following transforms
- * to the calling convention of the C functions.
- *
- * we do this just for writing the hook in C.
- * so, this part would not be performance optimal.
- */
- asm volatile (
- ".globl asm_syscall_hook \n\t"
- "asm_syscall_hook: \n\t"
- "movq (%rsp), %rcx \n\t"
- "pushq %rbp \n\t"
- "movq %rsp, %rbp \n\t"
- "subq $16,%rsp \n\t"
- "movq %rcx,8(%rsp) \n\t"
- "movq %r9,(%rsp) \n\t"
- "movq %r8, %r9 \n\t"
- "movq %r10, %r8 \n\t"
- "movq %rdx, %rcx \n\t"
- "movq %rsi, %rdx \n\t"
- "movq %rdi, %rsi \n\t"
- "movq %rax, %rdi \n\t"
- "call syscall \n\t"
- "leaveq \n\t"
- "retq \n\t"
- );
-}
-
-int
-trampoline(void *text)
-{- int i;
- for(i = 0; i < _NSYS; i++)
- ((uint8_t *)text)[i] = 0x90;
-
- /* Preserve redzone */
- ((uint8_t*)text)[_NSYS + 0x00] = 0x48;
- ((uint8_t *) text)[_NSYS + 0x01] = 0x81;
- ((uint8_t *) text)[_NSYS + 0x02] = 0xec;
- ((uint8_t *) text)[_NSYS + 0x03] = 0x80;
- ((uint8_t *) text)[_NSYS + 0x04] = 0x00;
- ((uint8_t *) text)[_NSYS + 0x05] = 0x00;
- ((uint8_t *) text)[_NSYS + 0x06] = 0x00;
-
- /* 49 bb [64-bit addr (8-byte)] movabs [64-bit addr (8-byte)],%r11 */
- ((uint8_t *) text)[_NSYS + 0x07] = 0x49;
- ((uint8_t *) text)[_NSYS + 0x08] = 0xbb;
- ((uint8_t *) text)[_NSYS + 0x09] = ((uint64_t) asm_syscall_hook >> (8 * 0)) & 0xff;
- ((uint8_t *) text)[_NSYS + 0x0a] = ((uint64_t) asm_syscall_hook >> (8 * 1)) & 0xff;
- ((uint8_t *) text)[_NSYS + 0x0b] = ((uint64_t) asm_syscall_hook >> (8 * 2)) & 0xff;
- ((uint8_t *) text)[_NSYS + 0x0c] = ((uint64_t) asm_syscall_hook >> (8 * 3)) & 0xff;
- ((uint8_t *) text)[_NSYS + 0x0d] = ((uint64_t) asm_syscall_hook >> (8 * 4)) & 0xff;
- ((uint8_t *) text)[_NSYS + 0x0e] = ((uint64_t) asm_syscall_hook >> (8 * 5)) & 0xff;
- ((uint8_t *) text)[_NSYS + 0x0f] = ((uint64_t) asm_syscall_hook >> (8 * 6)) & 0xff;
- ((uint8_t *) text)[_NSYS + 0x10] = ((uint64_t) asm_syscall_hook >> (8 * 7)) & 0xff;
-
- // 41 ff e3 jmp *%r11
- ((uint8_t *) text)[_NSYS + 0x11] = 0x41;
- ((uint8_t *) text)[_NSYS + 0x12] = 0xff;
- ((uint8_t *) text)[_NSYS + 0x13] = 0xe3;
- return i + 0x13;
-}
--- a/posix-arm/Makefile
+++ b/posix-arm/Makefile
@@ -7,6 +7,7 @@
OFILES=\
getcallerpc.$O\
tas.$O\
+ cas.$O\
default: $(LIB)
$(LIB): $(OFILES)
--- /dev/null
+++ b/posix-arm/cas.c
@@ -1,0 +1,36 @@
+#include "u.h"
+#include "libc.h"
+
+int
+cas(int *x, int old, int new)
+{+ int v, t;
+
+#if ARMv5
+ __asm__(
+ "1: ldr %0, [%2]\n"
+ " cmp %0, %3\n"
+ " bne 2f\n"
+ " swp %1, %4, [%2]\n"
+ " cmp %1, %3\n"
+ " bne 1b\n"
+ "2:"
+ : "=&r" (v), "=&r" (t)
+ : "r" (x), "r" (old), "r" (new)
+ : "cc", "memory"
+ );
+#else
+ __asm__ (
+ "1: ldrex %0, [%2]\n"
+ " cmp %0, %3\n"
+ " bne 2f\n"
+ " strex %1, %4, [%2]\n"
+ " teq %1, #0\n"
+ " bne 1b\n"
+ "2:"
+ : "=&r" (v), "=&r" (t)
+ : "r" (x), "r" (old), "r" (new)
+ : "cc");
+#endif
+ return (v == old);
+}
\ No newline at end of file
--- a/posix-arm64/Makefile
+++ b/posix-arm64/Makefile
@@ -7,9 +7,7 @@
OFILES=\
getcallerpc.$O\
tas.$O\
- trampoline.$O\
- patch.$O\
- start.$O\
+ cas.$O\
default: $(LIB)
$(LIB): $(OFILES)
--- /dev/null
+++ b/posix-arm64/cas.c
@@ -1,0 +1,30 @@
+#include "u.h"
+#include "libc.h"
+
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+
+int
+cas(int *x, int old, int new)
+{+#if __has_builtin(__atomic_compare_exchange_n) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7)))
+ return __atomic_compare_exchange_n(x, &old, new, 0, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
+#else
+ int v, t;
+
+ __asm__ (
+ "1: ldxr %0, [%3]\n"
+ " cmp %0, %4\n"
+ " bne 2f\n"
+ " stxr %w1, %5, [%3]\n"
+ " cmp %1, #0\n"
+ " bne 1b\n"
+ "2:"
+ : "=&r" (v), "=&r" (t)
+ : "m" (*x), "r" (x), "r" (old), "r" (new)
+ : "cc");
+
+ return (v == old);
+#endif
+}
\ No newline at end of file
--- a/posix-arm64/mem.h
+++ b/posix-arm64/mem.h
@@ -1,4 +1,3 @@
-#define AOUT_MAGIC (R_MAGIC)
/*
* Memory and machine-specific definitions. Used in C and assembler.
*/
--- a/posix-arm64/patch.c
+++ /dev/null
@@ -1,23 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "mem.h"
-
-int
-patch(void* text, int size)
-{- ulong i;
- int ret = -1;
- for(i = 0; i < size - BY2WD; i++){- // MOV X0, #immediate (could be D2800000 | syscall_number)
- // BL X0 (could be D4000010 | offset)
- // 0xD63F0000 is our BLR X0
- // This sets up our jmp to the trampoline code
- if ((*(ulong*)&text[i] & 0xFFFF0000) == 0xD2800000 && (*(ulong*)&text[i+BY2SE] & 0xFFFF0000) == 0xD4000000) {- ulong *ptr = (ulong*)&text[i+BY2SE];
- *ptr &= 0xFFFF0000;
- *ptr |= 0xD63F0000;
- ret++;
- }
- }
- return ret;
-}
--- a/posix-arm64/start.c
+++ /dev/null
@@ -1,42 +1,0 @@
-#include "u.h"
-#include "libc.h"
-void start(uintptr_t entry, Tos *_tos, int argc, char *argv[])
-{- register uintptr_t r0 asm("x0") = entry;- register Tos *r1 asm("x1") = _tos;- register int r2 asm("w2") = argc;- register char **r3 asm("x3") = argv;-
- __asm__ __volatile__ (
- // Load values into registers
- "mov x0, %0\n\t"
- "mov x1, %1\n\t"
- "mov w2, %w2\n\t"
- "mov x3, %3\n\t"
-
- // push argv onto stack
- "mov x4, x2\n\t"
- "add x4, x4, #1\n\t"
- "lsl x4, x4, #3\n\t"
- "sub sp, sp, x4\n\t"
- "mov x5, sp\n\t"
- "mov x6, x3\n\t"
-
- // copy argv in at a time
- "copy_argv_loop:\n\t"
- "ldr x7, [x6], #8\n\t"
- "str x7, [x5], #8\n\t"
- "subs x4, x4, #1\n\t"
- "bne copy_argv_loop\n\t"
-
- // push argc onto stack
- "sub sp, sp, #4\n\t"
- "str w2, [sp]\n\t"
-
- // jump to entry point
- "br x0\n\t"
- "ret\n\t"
- :
- : "r"(r0), "r"(r1), "r"(r2), "r"(r3)
- : "x4", "x5", "x6", "x7");
-}
\ No newline at end of file
--- a/posix-arm64/trampoline.c
+++ /dev/null
@@ -1,75 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "mem.h"
-
-void asm_syscall_hook(void)
-{- print("In hook somehow\n");- __asm__ __volatile__ (
- "asm_syscall_hook:\r\n"
- "stp x29, x30, [sp, #-16]!\r\n" // Save frame pointer and link register
- "mov x29, sp\r\n" // Set up frame pointer
- "sub sp, sp, #32\r\n" // Allocate 32 bytes on stack
- "stp x8, x0, [sp, #16]\r\n" // Save x8 (syscall number) and x0
- "stp x1, x2, [sp]\r\n" // Save x1 and x2
- "mov x1, x0\r\n" // Shift arguments: x0 -> x1
- "mov x2, x1\r\n" // x1 -> x2
- "mov x3, x2\r\n" // x2 -> x3
- "mov x4, x3\r\n" // x3 -> x4
- "mov x5, x4\r\n" // x4 -> x5
- "mov x6, x5\r\n" // x5 -> x6
- "mov x0, x8\r\n" // Move syscall number to x0
- "bl _sysintercept\r\n" // Call syscall function
- "ldp x1, x2, [sp]\r\n" // Restore original x1 and x2
- "ldp x8, x3, [sp, #16]\r\n" // Restore original x8 and load original x0 into x3
- "mov x1, x3\r\n" // Restore original x0 to x1 (new x0 is return value)
- "ldp x29, x30, [sp], #48\r\n" // Restore frame pointer and link register, and deallocate stack
- "ret\r\n"
- );
-}
-
-/**
- * based on https://github.com/yasukata/zpoline/blob/master/main.c
- * This will add NOP into the first 53 sections of text
- * When a syscall is patched, it will instead jump here
- * From the NOP slide, it then calls into asm_syscall_hook which in turn calls sysintercept
- */
-void
-trampoline(void *text)
-{- void *hook_address = (void*)&asm_syscall_hook;
- uint8_t code[] = {- // 53 nop instructions to catch the 9 syscalls (0xd503201f each)
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
- 0x1f, 0x20, 0x03, 0xd5,
- // Main code
- 0xff, 0x43, 0x00, 0xd1, // sub sp, sp, #0x80
- 0x00, 0x00, 0x00, 0x90, // adrp x11, 0 (placeholder)
- 0x0b, 0x00, 0x00, 0x91, // add x11, x11, :lo12:0 (placeholder)
- 0x60, 0x01, 0x3f, 0xd6 // br x11
- };
-
- // Calculate the relative address for adrp
- uintptr_t adrp_offset = ((uintptr_t)hook_address >> 12) & 0x7FFFF;
- code[216] |= (adrp_offset & 0xFF);
- code[217] |= ((adrp_offset >> 8) & 0x7F) << 1;
-
- // Set the low 12 bits for add
- uintptr_t add_offset = (uintptr_t)hook_address & 0xFFF;
- code[220] |= (add_offset & 0xFF);
- code[221] |= (add_offset >> 8) << 2;
-
- memcpy(text, code, sizeof(code));
-}
--
⑨