linux/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Test context switching to see if the DSCR SPR is correctly preserved
   3 * when within a transaction.
   4 *
   5 * Note: We assume that the DSCR has been left at the default value (0)
   6 * for all CPUs.
   7 *
   8 * Method:
   9 *
  10 * Set a value into the DSCR.
  11 *
  12 * Start a transaction, and suspend it (*).
  13 *
  14 * Hard loop checking to see if the transaction has become doomed.
  15 *
  16 * Now that we *may* have been preempted, record the DSCR and TEXASR SPRS.
  17 *
  18 * If the abort was because of a context switch, check the DSCR value.
  19 * Otherwise, try again.
  20 *
  21 * (*) If the transaction is not suspended we can't see the problem because
  22 * the transaction abort handler will restore the DSCR to it's checkpointed
  23 * value before we regain control.
  24 */
  25
  26#include <inttypes.h>
  27#include <stdio.h>
  28#include <stdlib.h>
  29#include <assert.h>
  30#include <asm/tm.h>
  31
  32#include "utils.h"
  33#include "tm.h"
  34#include "../pmu/lib.h"
  35
  36#define SPRN_DSCR       0x03
  37
  38int test_body(void)
  39{
  40        uint64_t rv, dscr1 = 1, dscr2, texasr;
  41
  42        SKIP_IF(!have_htm());
  43        SKIP_IF(htm_is_synthetic());
  44
  45        printf("Check DSCR TM context switch: ");
  46        fflush(stdout);
  47        for (;;) {
  48                asm __volatile__ (
  49                        /* set a known value into the DSCR */
  50                        "ld      3, %[dscr1];"
  51                        "mtspr   %[sprn_dscr], 3;"
  52
  53                        "li      %[rv], 1;"
  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 0;"
  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                        continue;
  82                }
  83                if (dscr2 != dscr1) {
  84                        printf(" FAIL\n");
  85                        return 1;
  86                } else {
  87                        printf(" OK\n");
  88                        return 0;
  89                }
  90        }
  91}
  92
  93static int tm_resched_dscr(void)
  94{
  95        return eat_cpu(test_body);
  96}
  97
  98int main(int argc, const char *argv[])
  99{
 100        return test_harness(tm_resched_dscr, "tm_resched_dscr");
 101}
 102