162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Test context switching to see if the DSCR SPR is correctly preserved 362306a36Sopenharmony_ci * when within a transaction. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Note: We assume that the DSCR has been left at the default value (0) 662306a36Sopenharmony_ci * for all CPUs. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Method: 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Set a value into the DSCR. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Start a transaction, and suspend it (*). 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Hard loop checking to see if the transaction has become doomed. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Now that we *may* have been preempted, record the DSCR and TEXASR SPRS. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * If the abort was because of a context switch, check the DSCR value. 1962306a36Sopenharmony_ci * Otherwise, try again. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * (*) If the transaction is not suspended we can't see the problem because 2262306a36Sopenharmony_ci * the transaction abort handler will restore the DSCR to it's checkpointed 2362306a36Sopenharmony_ci * value before we regain control. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <inttypes.h> 2762306a36Sopenharmony_ci#include <stdio.h> 2862306a36Sopenharmony_ci#include <stdlib.h> 2962306a36Sopenharmony_ci#include <assert.h> 3062306a36Sopenharmony_ci#include <asm/tm.h> 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#include "utils.h" 3362306a36Sopenharmony_ci#include "tm.h" 3462306a36Sopenharmony_ci#include "../pmu/lib.h" 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define SPRN_DSCR 0x03 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ciint test_body(void) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci uint64_t rv, dscr1 = 1, dscr2, texasr; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci SKIP_IF(!have_htm()); 4362306a36Sopenharmony_ci SKIP_IF(htm_is_synthetic()); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci printf("Check DSCR TM context switch: "); 4662306a36Sopenharmony_ci fflush(stdout); 4762306a36Sopenharmony_ci for (;;) { 4862306a36Sopenharmony_ci asm __volatile__ ( 4962306a36Sopenharmony_ci /* set a known value into the DSCR */ 5062306a36Sopenharmony_ci "ld 3, %[dscr1];" 5162306a36Sopenharmony_ci "mtspr %[sprn_dscr], 3;" 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci "li %[rv], 1;" 5462306a36Sopenharmony_ci /* start and suspend a transaction */ 5562306a36Sopenharmony_ci "tbegin.;" 5662306a36Sopenharmony_ci "beq 1f;" 5762306a36Sopenharmony_ci "tsuspend.;" 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* hard loop until the transaction becomes doomed */ 6062306a36Sopenharmony_ci "2: ;" 6162306a36Sopenharmony_ci "tcheck 0;" 6262306a36Sopenharmony_ci "bc 4, 0, 2b;" 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci /* record DSCR and TEXASR */ 6562306a36Sopenharmony_ci "mfspr 3, %[sprn_dscr];" 6662306a36Sopenharmony_ci "std 3, %[dscr2];" 6762306a36Sopenharmony_ci "mfspr 3, %[sprn_texasr];" 6862306a36Sopenharmony_ci "std 3, %[texasr];" 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci "tresume.;" 7162306a36Sopenharmony_ci "tend.;" 7262306a36Sopenharmony_ci "li %[rv], 0;" 7362306a36Sopenharmony_ci "1: ;" 7462306a36Sopenharmony_ci : [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr) 7562306a36Sopenharmony_ci : [dscr1]"m"(dscr1) 7662306a36Sopenharmony_ci , [sprn_dscr]"i"(SPRN_DSCR), [sprn_texasr]"i"(SPRN_TEXASR) 7762306a36Sopenharmony_ci : "memory", "r3" 7862306a36Sopenharmony_ci ); 7962306a36Sopenharmony_ci assert(rv); /* make sure the transaction aborted */ 8062306a36Sopenharmony_ci if ((texasr >> 56) != TM_CAUSE_RESCHED) { 8162306a36Sopenharmony_ci continue; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci if (dscr2 != dscr1) { 8462306a36Sopenharmony_ci printf(" FAIL\n"); 8562306a36Sopenharmony_ci return 1; 8662306a36Sopenharmony_ci } else { 8762306a36Sopenharmony_ci printf(" OK\n"); 8862306a36Sopenharmony_ci return 0; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic int tm_resched_dscr(void) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci return eat_cpu(test_body); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ciint main(int argc, const char *argv[]) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci return test_harness(tm_resched_dscr, "tm_resched_dscr"); 10162306a36Sopenharmony_ci} 102