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 | |
Michael Ellerman | aa83f3d | 2014-06-13 21:16:04 +1000 | [diff] [blame] | 31 | #include "utils.h" |
| 32 | |
Sam bobroff | 96d0161 | 2014-06-05 16:19:22 +1000 | [diff] [blame] | 33 | #define TBEGIN ".long 0x7C00051D ;" |
| 34 | #define TEND ".long 0x7C00055D ;" |
| 35 | #define TCHECK ".long 0x7C00059C ;" |
| 36 | #define TSUSPEND ".long 0x7C0005DD ;" |
| 37 | #define TRESUME ".long 0x7C2005DD ;" |
| 38 | #define SPRN_TEXASR 0x82 |
| 39 | #define SPRN_DSCR 0x03 |
| 40 | |
Michael Ellerman | aa83f3d | 2014-06-13 21:16:04 +1000 | [diff] [blame] | 41 | int test_body(void) |
| 42 | { |
Sam bobroff | 96d0161 | 2014-06-05 16:19:22 +1000 | [diff] [blame] | 43 | uint64_t rv, dscr1 = 1, dscr2, texasr; |
| 44 | |
| 45 | printf("Check DSCR TM context switch: "); |
| 46 | fflush(stdout); |
| 47 | for (;;) { |
| 48 | rv = 1; |
| 49 | asm __volatile__ ( |
| 50 | /* set a known value into the DSCR */ |
| 51 | "ld 3, %[dscr1];" |
| 52 | "mtspr %[sprn_dscr], 3;" |
| 53 | |
| 54 | /* start and suspend a transaction */ |
| 55 | TBEGIN |
| 56 | "beq 1f;" |
| 57 | TSUSPEND |
| 58 | |
| 59 | /* hard loop until the transaction becomes doomed */ |
| 60 | "2: ;" |
| 61 | TCHECK |
| 62 | "bc 4, 0, 2b;" |
| 63 | |
| 64 | /* record DSCR and TEXASR */ |
| 65 | "mfspr 3, %[sprn_dscr];" |
| 66 | "std 3, %[dscr2];" |
| 67 | "mfspr 3, %[sprn_texasr];" |
| 68 | "std 3, %[texasr];" |
| 69 | |
| 70 | TRESUME |
| 71 | TEND |
| 72 | "li %[rv], 0;" |
| 73 | "1: ;" |
| 74 | : [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr) |
| 75 | : [dscr1]"m"(dscr1) |
| 76 | , [sprn_dscr]"i"(SPRN_DSCR), [sprn_texasr]"i"(SPRN_TEXASR) |
| 77 | : "memory", "r3" |
| 78 | ); |
| 79 | assert(rv); /* make sure the transaction aborted */ |
| 80 | if ((texasr >> 56) != TM_CAUSE_RESCHED) { |
| 81 | putchar('.'); |
| 82 | fflush(stdout); |
| 83 | continue; |
| 84 | } |
| 85 | if (dscr2 != dscr1) { |
| 86 | printf(" FAIL\n"); |
Michael Ellerman | aa83f3d | 2014-06-13 21:16:04 +1000 | [diff] [blame] | 87 | return 1; |
Sam bobroff | 96d0161 | 2014-06-05 16:19:22 +1000 | [diff] [blame] | 88 | } else { |
| 89 | printf(" OK\n"); |
Michael Ellerman | aa83f3d | 2014-06-13 21:16:04 +1000 | [diff] [blame] | 90 | return 0; |
Sam bobroff | 96d0161 | 2014-06-05 16:19:22 +1000 | [diff] [blame] | 91 | } |
| 92 | } |
| 93 | } |
Michael Ellerman | aa83f3d | 2014-06-13 21:16:04 +1000 | [diff] [blame] | 94 | |
| 95 | int main(void) |
| 96 | { |
| 97 | return test_harness(test_body, "tm_resched_dscr"); |
| 98 | } |