diff options
author | davem <davem@cvs.openbsd.org> | 1996-01-14 00:39:19 +0000 |
---|---|---|
committer | davem <davem@cvs.openbsd.org> | 1996-01-14 00:39:19 +0000 |
commit | 1b2c14105180551c765eaaeec49fe51420a7492e (patch) | |
tree | b753b44e4fff5db36043d7030729a265e05feab6 /sys | |
parent | 91703ca9110fc1d4453236b51c3976121762ee57 (diff) |
The sun mmu is very broken, and we all can thank crashme for
helping me find this bug. On execution of an atomic load/store instruction
the chip will only say that a read fault is happening, we then load up a
readonly translation to the accessed page, and we get the fault again still
showing a read-fault. We end up faulting in a loop forever and the process
appears to be completely stuck. The algorithm to fix this problem goes like
this. If we get a non-text fault, and the fault type is VM_PROT_READ, and
the SER_PROT bit is set in the syncronous fault error register, we take
a peek at the instruction at pc. If this instruction is indeed an ldstub
or a swap variant we or in VM_PROT_WRITE to the fault type.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc/sparc/trap.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/sys/arch/sparc/sparc/trap.c b/sys/arch/sparc/sparc/trap.c index 2f6103499da..2925b0adea2 100644 --- a/sys/arch/sparc/sparc/trap.c +++ b/sys/arch/sparc/sparc/trap.c @@ -598,6 +598,22 @@ mem_access_fault(type, ser, v, pc, psr, tf) if (VA_INHOLE(v)) goto fault; ftype = ser & SER_WRITE ? VM_PROT_READ|VM_PROT_WRITE : VM_PROT_READ; + if(ftype == VM_PROT_READ && (ser & SER_PROT) && type != T_TEXTFAULT) { + /* If this is an ldstub or swap instruction + * then we are about to fault in a loop forever + * as only the read part of the fault will be + * reported by the mmu. + */ + int error, insn; + + error = copyin((caddr_t) pc, &insn, sizeof(int)); + if(!error) { + insn = (insn >> 16); /* high word */ + insn &= 0xc168; + if(insn == 0xc068) + ftype |= VM_PROT_WRITE; + } + } va = trunc_page(v); if (psr & PSR_PS) { extern char Lfsbail[]; |