> CONCLUSION: > > - the only correct workaround for TLBError > is the one I suggested earlier: TLBError > handler has to inspect the faulting opcode > and fixup DAR and MD_EPN based on the GPR > values if the faulting instruction is any > of dcbf, dcbi, dcbst or dcbz. > Performance of this solution could be > improved (eliminate opcode-check in the > vast majority of the cases) by storing > a 'tag' value in DAR.
Hi again I have been hacking on dcxx address decoder. Since assembler isn't my cup of tea, I used C mixed with asm statements. The resulting assembler isn't too bad either IMHO. To load the instruction into r21 I used: mfspr r20,SRR0 andis. r21, r20, 0x8000 beq 56f tophys(r21, r20) lwz r21,0(r21) 56: This only works for kernel space addresses. I can't figure out how to get to user space as well. I can live without user space anyway. I am still thinking about the 'tag'. Since MD_EPN isn't set as well as DAR I thinking about storing a tag in MD_EPN instead. It's less intrusive. Maybe it is enough to look at the valid bit in MD_EPN? What do you think so far? Oh, this should go into the DTLB Error handler. Jocke ======================= dcxx address decoder ========================= #define RA(inst) (((inst) & 0x001F0000) >> 16) #define RA_MASK 0x001F0000 #define RB(inst) (((inst) & 0x0000F800) >> 11) #define RB_MASK 0x0000F800 /* Compile with ppc_8xx-gcc -S -O2 -mregnames dcbz.c -fcall-used-r20 -fcall-used-r21 * to see the resulting assembler */ /* Assumes dcxx instruction in reg 21 when called */ decode_dcxx_and_sum(void) { register unsigned long r21 asm("r21"); /* make it live in reg 21 */ register unsigned long r20 asm("r20"); /* make it live in reg 20 */ asm("mfctr %0\n\t" "stw %0, 16(0)":: "r" (r20)); /* save ctr reg on stack */ r20 = RB(r21) * 8; /* offset into jump table for reg RB */ asm("addi %0, %0, 100f at l":: "r" (r20)); /* add start of table */ asm("mtctr %0":: "r" (r20)); /* load ctr with jump address */ r20 = 0; /* sum starts at zero */ asm("bctr"::); /* jump into table */ /* Below is the jump table. */ asm("100:\n\t" "add %0, %0, 0\n\t" "b 99f\n\t" "add %0, %0, 1\n\t" "b 99f\n\t" "add %0, %0, 2\n\t" "b 99f\n\t" "add %0, %0, 3\n\t" "b 99f\n\t" "add %0, %0, 4\n\t" "b 99f\n\t" "add %0, %0, 5\n\t" "b 99f\n\t" "add %0, %0, 6\n\t" "b 99f\n\t" "add %0, %0, 7\n\t" "b 99f\n\t" "add %0, %0, 8\n\t" "b 99f\n\t" "add %0, %0, 9\n\t" "b 99f\n\t" "add %0, %0, 10\n\t" "b 99f\n\t" "add %0, %0, 11\n\t" "b 99f\n\t" "add %0, %0, 12\n\t" "b 99f\n\t" "99:\n\t" : : "r" (r20)); r21 = RA(r21) * 8; /* offset into jump table for reg RA */ if(r21){ /* if reg zero, don't add it */ asm("addi %0, %0, 100b at l":: "r" (r21)); /* add start of table */ asm("mtctr %0":: "r" (r21)); /* load ctr with jump address */ r21 &= ~RA_MASK; /* make sure we don't execute this mre than once */ asm("bctr":: "r" (r21)); /* jump into table */ } asm("mtdar %0": : "r" (r20)); /* save sum to DAR */ asm("lwz %0, 16(0)\n\t" "mtctr %0" :: "r" (r21)); /* restore ctr reg from stack */ } This is the resulting assembler: .file "dcbz.c" gcc2_compiled.: .section ".text" .align 2 .globl decode_dcxx_and_sum .type decode_dcxx_and_sum, at function decode_dcxx_and_sum: mfctr %r20 stw %r20, 16(0) rlwinm %r20,%r21,24,24,28 addi %r20, %r20, 100f at l mtctr %r20 li %r20,0 bctr 100: add %r20, %r20, 0 b 99f add %r20, %r20, 1 b 99f add %r20, %r20, 2 b 99f add %r20, %r20, 3 b 99f add %r20, %r20, 4 b 99f add %r20, %r20, 5 b 99f add %r20, %r20, 6 b 99f add %r20, %r20, 7 b 99f add %r20, %r20, 8 b 99f add %r20, %r20, 9 b 99f add %r20, %r20, 10 b 99f add %r20, %r20, 11 b 99f add %r20, %r20, 12 b 99f 99: rlwinm. %r21,%r21,19,24,28 bc 12,2,.L3 addi %r21, %r21, 100b at l mtctr %r21 rlwinm %r21,%r21,0,16,10 bctr .L3: mtdar %r20 lwz %r21, 16(0) mtctr %r21 blr .Lfe1: .size decode_dcxx_and_sum,.Lfe1-decode_dcxx_and_sum .ident "GCC: (GNU) 2.95.3 20010315 (release/MontaVista)" ** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/