code: plan9front

Download patch

ref: 6b4a9c5d8d291ce15e9f31cb130537fe47a9688e
parent: 575015d2b023e5707293830186581f03c33aa90a
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Jun 19 10:43:32 EDT 2015

5e: implement DSB,DMB,ISB and CLREX instructions

--- a/sys/src/cmd/5e/5e.c
+++ b/sys/src/cmd/5e/5e.c
@@ -36,6 +36,7 @@
 	if(P == nil)
 		return;
 
+	clrex();
 	remproc(P);
 	decref(&nproc);
 	freesegs();
--- a/sys/src/cmd/5e/arm.c
+++ b/sys/src/cmd/5e/arm.c
@@ -134,6 +134,7 @@
 	addr = *Rn;
 	if((instr & fB) == 0)
 		addr = evenaddr(addr, 3);
+	clrex();
 	targ = (u32int *) vaddr(addr, 4, &seg);
 	lock(&seg->lock);
 	if(instr & fB) {
@@ -400,8 +401,10 @@
 		invalid(instr);
 	addr = evenaddr(*Rn, 3);
 	if(instr & fS) {
+		clrex();
 		targ = vaddr(addr, 4, &seg);
 		lock(&seg->lock);
+		P->excl = seg;
 		*Rd = *targ;
 		segunlock(seg);
 	} else {
@@ -410,17 +413,40 @@
 			invalid(instr);
 		targ = vaddr(addr, 4, &seg);
 		if(canlock(&seg->lock)) {
+			unlock(&seg->lock);
 			*Rd = 1;
+		} else if(P->excl != seg) {
+			*Rd = 1;
 		} else {
 			*targ = *Rm;
-			unlock(&seg->lock);
 			*Rd = 0;
 		}
 		segunlock(seg);
+		clrex();
 	}
 }
 
 void
+clrex(void)
+{
+	Segment *seg;
+
+	seg = P->excl;
+	P->excl = nil;
+	if(seg != nil)
+		unlock(&seg->lock);
+}
+
+static void
+barrier(void)
+{
+	static Lock l;
+
+	lock(&l);
+	unlock(&l);
+}
+
+void
 step(void)
 {
 	u32int instr;
@@ -463,7 +489,18 @@
 	case 0xC: if((P->CPSR & flZ) || !(P->CPSR & flN) != !(P->CPSR & flV)) return; break;
 	case 0xD: if(!(P->CPSR & flZ) && !(P->CPSR & flN) == !(P->CPSR & flV)) return; break;
 	case 0xE: break;
-	default: sysfatal("condition code %x not implemented", instr >> 28);
+	case 0xF:
+		switch(instr & 0xFFF000F0){
+		case 0xF5700010:	/* CLREX */
+			clrex();
+			return;
+		case 0xF5700040:	/* DSB */
+		case 0xF5700050:	/* DMB */
+		case 0xF5700060:	/* ISB */
+			barrier();
+			return;
+		}
+	default: sysfatal("condition code %x not implemented (instr %ux, ps %ux)", instr >> 28, instr, P->R[15]);
 	}
 	if((instr & 0x0FB00FF0) == 0x01000090)
 		swap(instr);
--- a/sys/src/cmd/5e/dat.h
+++ b/sys/src/cmd/5e/dat.h
@@ -31,9 +31,10 @@
 	Ref *path;		/* Ref + string data */
 
 	Segment *S[SEGNUM];	/* memory */
+	Segment *excl;		/* recently acquired exclusive access */
 	u32int R[16];		/* general purpose registers / PC (R15) */
 	u32int CPSR;		/* status register */
-	
+
 	u32int FPSR;
 	long double F[Nfpregs];
 
--- a/sys/src/cmd/5e/fns.h
+++ b/sys/src/cmd/5e/fns.h
@@ -17,6 +17,7 @@
 int iscexec(Fd *, int);
 void setcexec(Fd *, int, int);
 void cleanup(void);
+void clrex(void);
 void segunlock(Segment *);
 void *copyifnec(u32int, int, int *);
 void *bufifnec(u32int, int, int *);
--- a/sys/src/cmd/5e/proc.c
+++ b/sys/src/cmd/5e/proc.c
@@ -378,6 +378,7 @@
 	if(P->notehandler == 0)
 		exits(msg);
 
+	clrex();
 	uregp = P->R[13] - 18 * 4;
 	ureg = vaddrnol(uregp, 18 * 4);
 	memcpy(ureg, P->R, 15 * 4);