18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Test context switching to see if the DSCR SPR is correctly preserved 38c2ecf20Sopenharmony_ci * when within a transaction. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Note: We assume that the DSCR has been left at the default value (0) 68c2ecf20Sopenharmony_ci * for all CPUs. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Method: 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Set a value into the DSCR. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Start a transaction, and suspend it (*). 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Hard loop checking to see if the transaction has become doomed. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * Now that we *may* have been preempted, record the DSCR and TEXASR SPRS. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * If the abort was because of a context switch, check the DSCR value. 198c2ecf20Sopenharmony_ci * Otherwise, try again. 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * (*) If the transaction is not suspended we can't see the problem because 228c2ecf20Sopenharmony_ci * the transaction abort handler will restore the DSCR to it's checkpointed 238c2ecf20Sopenharmony_ci * value before we regain control. 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <inttypes.h> 278c2ecf20Sopenharmony_ci#include <stdio.h> 288c2ecf20Sopenharmony_ci#include <stdlib.h> 298c2ecf20Sopenharmony_ci#include <assert.h> 308c2ecf20Sopenharmony_ci#include <asm/tm.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include "utils.h" 338c2ecf20Sopenharmony_ci#include "tm.h" 348c2ecf20Sopenharmony_ci#include "../pmu/lib.h" 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define SPRN_DSCR 0x03 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ciint test_body(void) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci uint64_t rv, dscr1 = 1, dscr2, texasr; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci SKIP_IF(!have_htm()); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci printf("Check DSCR TM context switch: "); 458c2ecf20Sopenharmony_ci fflush(stdout); 468c2ecf20Sopenharmony_ci for (;;) { 478c2ecf20Sopenharmony_ci asm __volatile__ ( 488c2ecf20Sopenharmony_ci /* set a known value into the DSCR */ 498c2ecf20Sopenharmony_ci "ld 3, %[dscr1];" 508c2ecf20Sopenharmony_ci "mtspr %[sprn_dscr], 3;" 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci "li %[rv], 1;" 538c2ecf20Sopenharmony_ci /* start and suspend a transaction */ 548c2ecf20Sopenharmony_ci "tbegin.;" 558c2ecf20Sopenharmony_ci "beq 1f;" 568c2ecf20Sopenharmony_ci "tsuspend.;" 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci /* hard loop until the transaction becomes doomed */ 598c2ecf20Sopenharmony_ci "2: ;" 608c2ecf20Sopenharmony_ci "tcheck 0;" 618c2ecf20Sopenharmony_ci "bc 4, 0, 2b;" 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci /* record DSCR and TEXASR */ 648c2ecf20Sopenharmony_ci "mfspr 3, %[sprn_dscr];" 658c2ecf20Sopenharmony_ci "std 3, %[dscr2];" 668c2ecf20Sopenharmony_ci "mfspr 3, %[sprn_texasr];" 678c2ecf20Sopenharmony_ci "std 3, %[texasr];" 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci "tresume.;" 708c2ecf20Sopenharmony_ci "tend.;" 718c2ecf20Sopenharmony_ci "li %[rv], 0;" 728c2ecf20Sopenharmony_ci "1: ;" 738c2ecf20Sopenharmony_ci : [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr) 748c2ecf20Sopenharmony_ci : [dscr1]"m"(dscr1) 758c2ecf20Sopenharmony_ci , [sprn_dscr]"i"(SPRN_DSCR), [sprn_texasr]"i"(SPRN_TEXASR) 768c2ecf20Sopenharmony_ci : "memory", "r3" 778c2ecf20Sopenharmony_ci ); 788c2ecf20Sopenharmony_ci assert(rv); /* make sure the transaction aborted */ 798c2ecf20Sopenharmony_ci if ((texasr >> 56) != TM_CAUSE_RESCHED) { 808c2ecf20Sopenharmony_ci continue; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci if (dscr2 != dscr1) { 838c2ecf20Sopenharmony_ci printf(" FAIL\n"); 848c2ecf20Sopenharmony_ci return 1; 858c2ecf20Sopenharmony_ci } else { 868c2ecf20Sopenharmony_ci printf(" OK\n"); 878c2ecf20Sopenharmony_ci return 0; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic int tm_resched_dscr(void) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci return eat_cpu(test_body); 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ciint main(int argc, const char *argv[]) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci return test_harness(tm_resched_dscr, "tm_resched_dscr"); 1008c2ecf20Sopenharmony_ci} 101