mpc8xx DCBZ (&friends) hw bug. Tests, analysis + conclusions.

Joakim Tjernlund joakim.tjernlund at lumentis.se
Thu Apr 3 22:50:26 EST 2003


> 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/





More information about the Linuxppc-embedded mailing list