/* * Probe timing-dependent bugs in Maverick FPU * as used in Cirrus Logic EP93xx chips. * * cc -mcpu=ep9312 -mfpu=maverick and -mfloat-abi=softfp if using EABI. * * erratum 4: maverick data operation into maverick register followed by * 64-bit store of that register to RAM without 7 intervening NOPs may write * garbage in the second, most significant, word. * * Haven't managed to spring the bug yet... * * Martin Guy 5 Oct 2007 - 1 Apr 2008 */ #include #include /* Somewhere to examine the teo 32-bit words of a 64-bit value */ union { unsigned long long ll; struct { unsigned long l0, l1; } l; } in, out; /* bug4_*() routines copy the contents of "in" to "out". If we hit the bug, * the most significant word (the dead bodi) should come out as garbage * at certain distances between the data instr and the 64-bit store. */ main() { crunch_fwden(); in.ll = 0xdeadb0d176543210ULL; printf(" %x %x\n", in.l.l0, in.l.l1); out.ll = 0; bug4_0(); printf("0 %x %x\n", out.l.l0, out.l.l1); out.ll = 0; bug4_1(); printf("1 %x %x\n", out.l.l0, out.l.l1); out.ll = 0; bug4_2(); printf("2 %x %x\n", out.l.l0, out.l.l1); out.ll = 0; bug4_3(); printf("3 %x %x\n", out.l.l0, out.l.l1); out.ll = 0; bug4_4(); printf("4 %x %x\n", out.l.l0, out.l.l1); out.ll = 0; bug4_5(); printf("5 %x %x\n", out.l.l0, out.l.l1); out.ll = 0; bug4_6(); printf("6 %x %x\n", out.l.l0, out.l.l1); out.ll = 0; bug4_7(); printf("7 %x %x\n", out.l.l0, out.l.l1); exit(0); } bug4_0() { asm("ldr r0, =in"); asm("ldr r1, =out"); asm("cfldr64 mvdx0, [r0]"); asm("cfsh64 mvdx1, mvdx0, #0"); asm("cfstr64 mvdx1, [r1]"); } bug4_1() { asm("ldr r0, =in"); asm("ldr r1, =out"); asm("cfldr64 mvdx0, [r0]"); asm("cfsh64 mvdx1, mvdx0, #0"); asm("nop"); asm("cfstr64 mvdx1, [r1]"); } bug4_2() { asm("ldr r0, =in"); asm("ldr r1, =out"); asm("cfldr64 mvdx0, [r0]"); asm("cfsh64 mvdx1, mvdx0, #0"); asm("nop"); asm("nop"); asm("cfstr64 mvdx1, [r1]"); } bug4_3() { asm("ldr r0, =in"); asm("ldr r1, =out"); asm("cfldr64 mvdx0, [r0]"); asm("cfsh64 mvdx1, mvdx0, #0"); asm("nop"); asm("nop"); asm("nop"); asm("cfstr64 mvdx1, [r1]"); } bug4_4() { asm("ldr r0, =in"); asm("ldr r1, =out"); asm("cfldr64 mvdx0, [r0]"); asm("cfsh64 mvdx1, mvdx0, #0"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("cfstr64 mvdx1, [r1]"); } bug4_5() { asm("ldr r0, =in"); asm("ldr r1, =out"); asm("cfldr64 mvdx0, [r0]"); asm("cfsh64 mvdx1, mvdx0, #0"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("cfstr64 mvdx1, [r1]"); } bug4_6() { asm("ldr r0, =in"); asm("ldr r1, =out"); asm("cfldr64 mvdx0, [r0]"); asm("cfsh64 mvdx1, mvdx0, #0"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("cfstr64 mvdx1, [r1]"); } bug4_7() { asm("ldr r0, =in"); asm("ldr r1, =out"); asm("cfldr64 mvdx0, [r0]"); asm("cfsh64 mvdx1, mvdx0, #0"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("cfstr64 mvdx1, [r1]"); } bug4_8() { asm("ldr r0, =in"); asm("ldr r1, =out"); asm("cfldr64 mvdx0, [r0]"); asm("cfsh64 mvdx1, mvdx0, #0"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("cfstr64 mvdx1, [r1]"); } bug4_9() { asm("ldr r0, =in"); asm("ldr r1, =out"); asm("cfldr64 mvdx0, [r0]"); asm("cfsh64 mvdx1, mvdx0, #0"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("cfstr64 mvdx1, [r1]"); } /* Enable forwarding in Maverick Crunch processor */ crunch_fwden() { asm("cfmv32sc mvdx0, dspsc"); /* Read DSPSC contents */ \ asm("cfmvrdl r0, mvd0"); /* Move LSW to ARM */ \ asm("orr r0, r0, #0x4000"); /* Set forwarding bit */ \ asm("cfmvdlr mvd0, r0"); /* Move ARM to LSW */ \ asm("cfmvsc32 dspsc, mvdx0"); /* Write DSPSC contents */ }