1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
296d01610SSam bobroff /* Test context switching to see if the DSCR SPR is correctly preserved
396d01610SSam bobroff  * when within a transaction.
496d01610SSam bobroff  *
596d01610SSam bobroff  * Note: We assume that the DSCR has been left at the default value (0)
696d01610SSam bobroff  * for all CPUs.
796d01610SSam bobroff  *
896d01610SSam bobroff  * Method:
996d01610SSam bobroff  *
1096d01610SSam bobroff  * Set a value into the DSCR.
1196d01610SSam bobroff  *
1296d01610SSam bobroff  * Start a transaction, and suspend it (*).
1396d01610SSam bobroff  *
1496d01610SSam bobroff  * Hard loop checking to see if the transaction has become doomed.
1596d01610SSam bobroff  *
1696d01610SSam bobroff  * Now that we *may* have been preempted, record the DSCR and TEXASR SPRS.
1796d01610SSam bobroff  *
1896d01610SSam bobroff  * If the abort was because of a context switch, check the DSCR value.
1996d01610SSam bobroff  * Otherwise, try again.
2096d01610SSam bobroff  *
2196d01610SSam bobroff  * (*) If the transaction is not suspended we can't see the problem because
2296d01610SSam bobroff  * the transaction abort handler will restore the DSCR to it's checkpointed
2396d01610SSam bobroff  * value before we regain control.
2496d01610SSam bobroff  */
2596d01610SSam bobroff 
2696d01610SSam bobroff #include <inttypes.h>
2796d01610SSam bobroff #include <stdio.h>
2896d01610SSam bobroff #include <stdlib.h>
2996d01610SSam bobroff #include <assert.h>
3096d01610SSam bobroff #include <asm/tm.h>
3196d01610SSam bobroff 
32aa83f3d8SMichael Ellerman #include "utils.h"
33b319ee84SMichael Ellerman #include "tm.h"
3499597cedSSam Bobroff #include "../pmu/lib.h"
35aa83f3d8SMichael Ellerman 
3696d01610SSam bobroff #define SPRN_DSCR       0x03
3796d01610SSam bobroff 
test_body(void)38aa83f3d8SMichael Ellerman int test_body(void)
39aa83f3d8SMichael Ellerman {
4096d01610SSam bobroff 	uint64_t rv, dscr1 = 1, dscr2, texasr;
4196d01610SSam bobroff 
42b319ee84SMichael Ellerman 	SKIP_IF(!have_htm());
43*e42edf9bSJordan Niethe 	SKIP_IF(htm_is_synthetic());
44b319ee84SMichael Ellerman 
4596d01610SSam bobroff 	printf("Check DSCR TM context switch: ");
4696d01610SSam bobroff 	fflush(stdout);
4796d01610SSam bobroff 	for (;;) {
4896d01610SSam bobroff 		asm __volatile__ (
4996d01610SSam bobroff 			/* set a known value into the DSCR */
5096d01610SSam bobroff 			"ld      3, %[dscr1];"
5196d01610SSam bobroff 			"mtspr   %[sprn_dscr], 3;"
5296d01610SSam bobroff 
53fe06fe86SMichael Ellerman 			"li      %[rv], 1;"
5496d01610SSam bobroff 			/* start and suspend a transaction */
55da3ddc3bSRashmica Gupta 			"tbegin.;"
5696d01610SSam bobroff 			"beq     1f;"
57da3ddc3bSRashmica Gupta 			"tsuspend.;"
5896d01610SSam bobroff 
5996d01610SSam bobroff 			/* hard loop until the transaction becomes doomed */
6096d01610SSam bobroff 			"2: ;"
61da3ddc3bSRashmica Gupta 			"tcheck 0;"
6296d01610SSam bobroff 			"bc      4, 0, 2b;"
6396d01610SSam bobroff 
6496d01610SSam bobroff 			/* record DSCR and TEXASR */
6596d01610SSam bobroff 			"mfspr   3, %[sprn_dscr];"
6696d01610SSam bobroff 			"std     3, %[dscr2];"
6796d01610SSam bobroff 			"mfspr   3, %[sprn_texasr];"
6896d01610SSam bobroff 			"std     3, %[texasr];"
6996d01610SSam bobroff 
70da3ddc3bSRashmica Gupta 			"tresume.;"
71da3ddc3bSRashmica Gupta 			"tend.;"
7296d01610SSam bobroff 			"li      %[rv], 0;"
7396d01610SSam bobroff 			"1: ;"
7496d01610SSam bobroff 			: [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr)
7596d01610SSam bobroff 			: [dscr1]"m"(dscr1)
7696d01610SSam bobroff 			, [sprn_dscr]"i"(SPRN_DSCR), [sprn_texasr]"i"(SPRN_TEXASR)
7796d01610SSam bobroff 			: "memory", "r3"
7896d01610SSam bobroff 		);
7996d01610SSam bobroff 		assert(rv); /* make sure the transaction aborted */
8096d01610SSam bobroff 		if ((texasr >> 56) != TM_CAUSE_RESCHED) {
8196d01610SSam bobroff 			continue;
8296d01610SSam bobroff 		}
8396d01610SSam bobroff 		if (dscr2 != dscr1) {
8496d01610SSam bobroff 			printf(" FAIL\n");
85aa83f3d8SMichael Ellerman 			return 1;
8696d01610SSam bobroff 		} else {
8796d01610SSam bobroff 			printf(" OK\n");
88aa83f3d8SMichael Ellerman 			return 0;
8996d01610SSam bobroff 		}
9096d01610SSam bobroff 	}
9196d01610SSam bobroff }
92aa83f3d8SMichael Ellerman 
tm_resched_dscr(void)9399597cedSSam Bobroff static int tm_resched_dscr(void)
94aa83f3d8SMichael Ellerman {
9599597cedSSam Bobroff 	return eat_cpu(test_body);
9699597cedSSam Bobroff }
9799597cedSSam Bobroff 
main(int argc,const char * argv[])9899597cedSSam Bobroff int main(int argc, const char *argv[])
9999597cedSSam Bobroff {
10099597cedSSam Bobroff 	return test_harness(tm_resched_dscr, "tm_resched_dscr");
101aa83f3d8SMichael Ellerman }
102