Sam bobroff | 96d0161 | 2014-06-05 16:19:22 +1000 | [diff] [blame^] | 1 | /* Test context switching to see if the DSCR SPR is correctly preserved |
| 2 | * when within a transaction. |
| 3 | * |
| 4 | * Note: We assume that the DSCR has been left at the default value (0) |
| 5 | * for all CPUs. |
| 6 | * |
| 7 | * Method: |
| 8 | * |
| 9 | * Set a value into the DSCR. |
| 10 | * |
| 11 | * Start a transaction, and suspend it (*). |
| 12 | * |
| 13 | * Hard loop checking to see if the transaction has become doomed. |
| 14 | * |
| 15 | * Now that we *may* have been preempted, record the DSCR and TEXASR SPRS. |
| 16 | * |
| 17 | * If the abort was because of a context switch, check the DSCR value. |
| 18 | * Otherwise, try again. |
| 19 | * |
| 20 | * (*) If the transaction is not suspended we can't see the problem because |
| 21 | * the transaction abort handler will restore the DSCR to it's checkpointed |
| 22 | * value before we regain control. |
| 23 | */ |
| 24 | |
| 25 | #include <inttypes.h> |
| 26 | #include <stdio.h> |
| 27 | #include <stdlib.h> |
| 28 | #include <assert.h> |
| 29 | #include <asm/tm.h> |
| 30 | |
| 31 | #define TBEGIN ".long 0x7C00051D ;" |
| 32 | #define TEND ".long 0x7C00055D ;" |
| 33 | #define TCHECK ".long 0x7C00059C ;" |
| 34 | #define TSUSPEND ".long 0x7C0005DD ;" |
| 35 | #define TRESUME ".long 0x7C2005DD ;" |
| 36 | #define SPRN_TEXASR 0x82 |
| 37 | #define SPRN_DSCR 0x03 |
| 38 | |
| 39 | int main(void) { |
| 40 | uint64_t rv, dscr1 = 1, dscr2, texasr; |
| 41 | |
| 42 | printf("Check DSCR TM context switch: "); |
| 43 | fflush(stdout); |
| 44 | for (;;) { |
| 45 | rv = 1; |
| 46 | asm __volatile__ ( |
| 47 | /* set a known value into the DSCR */ |
| 48 | "ld 3, %[dscr1];" |
| 49 | "mtspr %[sprn_dscr], 3;" |
| 50 | |
| 51 | /* start and suspend a transaction */ |
| 52 | TBEGIN |
| 53 | "beq 1f;" |
| 54 | TSUSPEND |
| 55 | |
| 56 | /* hard loop until the transaction becomes doomed */ |
| 57 | "2: ;" |
| 58 | TCHECK |
| 59 | "bc 4, 0, 2b;" |
| 60 | |
| 61 | /* record DSCR and TEXASR */ |
| 62 | "mfspr 3, %[sprn_dscr];" |
| 63 | "std 3, %[dscr2];" |
| 64 | "mfspr 3, %[sprn_texasr];" |
| 65 | "std 3, %[texasr];" |
| 66 | |
| 67 | TRESUME |
| 68 | TEND |
| 69 | "li %[rv], 0;" |
| 70 | "1: ;" |
| 71 | : [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr) |
| 72 | : [dscr1]"m"(dscr1) |
| 73 | , [sprn_dscr]"i"(SPRN_DSCR), [sprn_texasr]"i"(SPRN_TEXASR) |
| 74 | : "memory", "r3" |
| 75 | ); |
| 76 | assert(rv); /* make sure the transaction aborted */ |
| 77 | if ((texasr >> 56) != TM_CAUSE_RESCHED) { |
| 78 | putchar('.'); |
| 79 | fflush(stdout); |
| 80 | continue; |
| 81 | } |
| 82 | if (dscr2 != dscr1) { |
| 83 | printf(" FAIL\n"); |
| 84 | exit(EXIT_FAILURE); |
| 85 | } else { |
| 86 | printf(" OK\n"); |
| 87 | exit(EXIT_SUCCESS); |
| 88 | } |
| 89 | } |
| 90 | } |