diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-03-10 23:16:47 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-03-10 23:16:47 +0100 |
commit | 3aeca15d3c8647db5e7c76dadbc62cf3067791f4 (patch) | |
tree | 9e12710622e118a55a9cc91db635369b41894c8b /sys/src/cmd/5e | |
parent | 26a8accad26267678c240e48a8544a208d9ba571 (diff) |
5e: trap unaligned memory access
Diffstat (limited to 'sys/src/cmd/5e')
-rw-r--r-- | sys/src/cmd/5e/arm.c | 29 | ||||
-rw-r--r-- | sys/src/cmd/5e/fns.h | 1 | ||||
-rw-r--r-- | sys/src/cmd/5e/proc.c | 4 | ||||
-rw-r--r-- | sys/src/cmd/5e/vfp.c | 3 |
4 files changed, 27 insertions, 10 deletions
diff --git a/sys/src/cmd/5e/arm.c b/sys/src/cmd/5e/arm.c index ae4e21d6e..83e43ab4c 100644 --- a/sys/src/cmd/5e/arm.c +++ b/sys/src/cmd/5e/arm.c @@ -25,6 +25,15 @@ invalid(u32int instr) 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 @@ single(u32int instr) 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 @@ single(u32int instr) 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 @@ swap(u32int instr) 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 @@ halfword(u32int instr) 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 @@ block(u32int instr) 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,15 +390,16 @@ multiplylong(u32int instr) static void singleex(u32int instr) { - u32int *Rn, *Rd, *Rm, *targ; + u32int *Rn, *Rd, *Rm, *targ, addr; Segment *seg; Rd = P->R + ((instr >> 12) & 15); 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 @@ singleex(u32int instr) 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 { diff --git a/sys/src/cmd/5e/fns.h b/sys/src/cmd/5e/fns.h index 6ee3d8631..724775b6e 100644 --- a/sys/src/cmd/5e/fns.h +++ b/sys/src/cmd/5e/fns.h @@ -32,6 +32,7 @@ void addnote(char *); void dump(void); void resetfpa(void); void invalid(u32int); +u32int evenaddr(u32int,u32int); void fpatransfer(u32int); void fpaoperation(u32int); void fparegtransfer(u32int); diff --git a/sys/src/cmd/5e/proc.c b/sys/src/cmd/5e/proc.c index b5df57fd2..32c9f783a 100644 --- a/sys/src/cmd/5e/proc.c +++ b/sys/src/cmd/5e/proc.c @@ -107,7 +107,7 @@ initstack(int argc, char **argv) { 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 @@ inittos(void) { ulong tos; - tos = mach->utop - sizeof(Tos) * 2; + tos = (mach->utop & ~7) - sizeof(Tos) * 2; ((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = P->pid; } diff --git a/sys/src/cmd/5e/vfp.c b/sys/src/cmd/5e/vfp.c index 40193d777..2ab755a09 100644 --- a/sys/src/cmd/5e/vfp.c +++ b/sys/src/cmd/5e/vfp.c @@ -55,8 +55,7 @@ vfprmtransfer(u32int instr) 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) |