shithub: riscv

Download patch

ref: 3aeca15d3c8647db5e7c76dadbc62cf3067791f4
parent: 26a8accad26267678c240e48a8544a208d9ba571
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Mar 10 19:16:47 EDT 2014

5e: trap unaligned memory access

--- a/sys/src/cmd/5e/arm.c
+++ b/sys/src/cmd/5e/arm.c
@@ -25,6 +25,15 @@
 	suicide("undefined instruction %8ux @ %8ux", instr, P->R[15] - 4);
 }
 
+u32int
+evenaddr(u32int addr, u32int mask)
+{
+	if((addr & mask) == 0)
+		return addr;
+	suicide("unaligned access %8ux @ %8ux\n", addr, P->R[15] - 4);
+	return addr & ~mask;
+}
+
 static u32int
 doshift(u32int instr)
 {
@@ -81,6 +90,8 @@
 		addr = *Rn;
 	if(instr & fP)
 		addr += offset;
+	if((instr & fB) == 0)
+		addr = evenaddr(addr, 3);
 	targ = vaddr(addr, 4, &seg);
 	switch(instr & (fB | fL)) {
 	case 0:
@@ -112,7 +123,7 @@
 static void
 swap(u32int instr)
 {
-	u32int *Rm, *Rn, *Rd, *targ, tmp;
+	u32int *Rm, *Rn, *Rd, *targ, addr, tmp;
 	Segment *seg;
 	
 	Rm = P->R + (instr & 15);
@@ -120,7 +131,10 @@
 	Rn = P->R + ((instr >> 16) & 15);
 	if(Rm == P->R + 15 || Rd == P->R + 15 || Rn == P->R + 15)
 		invalid(instr);
-	targ = (u32int *) vaddr(*Rn, 4, &seg);
+	addr = *Rn;
+	if((instr & fB) == 0)
+		addr = evenaddr(addr, 3);
+	targ = (u32int *) vaddr(addr, 4, &seg);
 	lock(&seg->lock);
 	if(instr & fB) {
 		tmp = *(u8int*) targ;
@@ -255,6 +269,8 @@
 	target = *Rn;
 	if(instr & fP)
 		target += offset;
+	if(instr & fH)
+		target = evenaddr(target, 1);
 	switch(instr & (fSg | fH | fL)) {
 	case fSg: *(u8int*) vaddr(target, 1, &seg) = *Rd; break;
 	case fSg | fL: *Rd = (long) *(char*) vaddr(target, 1, &seg); break;
@@ -281,7 +297,7 @@
 	Rn = P->R + ((instr >> 16) & 15);
 	if(Rn == P->R + 15 || instr & (1<<15))
 		sysfatal("R15 block");
-	targ = *Rn;
+	targ = evenaddr(*Rn, 3);
 	if(instr & fU) {
 		for(i = 0; i < 16; i++) {
 			if(!(instr & (1<<i)))
@@ -374,7 +390,7 @@
 static void
 singleex(u32int instr)
 {
-	u32int *Rn, *Rd, *Rm, *targ;
+	u32int *Rn, *Rd, *Rm, *targ, addr;
 	Segment *seg;
 	
 	Rd = P->R + ((instr >> 12) & 15);
@@ -381,8 +397,9 @@
 	Rn = P->R + ((instr >> 16) & 15);
 	if(Rd == P->R + 15 || Rn == P->R + 15)
 		invalid(instr);
+	addr = evenaddr(*Rn, 3);
 	if(instr & fS) {
-		targ = vaddr(*Rn, 4, &seg);
+		targ = vaddr(addr, 4, &seg);
 		lock(&seg->lock);
 		*Rd = *targ;
 		segunlock(seg);
@@ -390,7 +407,7 @@
 		Rm = P->R + (instr & 15);
 		if(Rm == P->R + 15)
 			invalid(instr);
-		targ = vaddr(*Rn, 4, &seg);
+		targ = vaddr(addr, 4, &seg);
 		if(canlock(&seg->lock)) {
 			*Rd = 1;
 		} else {
--- a/sys/src/cmd/5e/fns.h
+++ b/sys/src/cmd/5e/fns.h
@@ -32,6 +32,7 @@
 void dump(void);
 void resetfpa(void);
 void invalid(u32int);
+u32int evenaddr(u32int,u32int);
 void fpatransfer(u32int);
 void fpaoperation(u32int);
 void fparegtransfer(u32int);
--- a/sys/src/cmd/5e/proc.c
+++ b/sys/src/cmd/5e/proc.c
@@ -107,7 +107,7 @@
 {
 	ulong tos, sp, ap, size, i, len;
 	
-	tos = mach->utop - sizeof(Tos) * 2;
+	tos = (mach->utop & ~7) - sizeof(Tos) * 2;
 	sp = tos;
 	
 	size = 8;
@@ -139,7 +139,7 @@
 {
 	ulong tos;
 
-	tos = mach->utop - sizeof(Tos) * 2;
+	tos = (mach->utop & ~7) - sizeof(Tos) * 2;
 	((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = P->pid;
 }
 
--- a/sys/src/cmd/5e/vfp.c
+++ b/sys/src/cmd/5e/vfp.c
@@ -55,8 +55,7 @@
 	sz = instr & (1<<8);
 	if((instr & (1<<23)) == 0)
 		off = -off;
-	ea = vaddr(P->R[n] + off, 8, &seg);
-
+	ea = vaddr(evenaddr(P->R[n] + off, sz ? 7 : 3), 8, &seg);
 	switch((instr>>20)&0x3){
 	case 0:
 		if(sz)