xref: /linux/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21554f21aSAnshuman Khandual /*
31554f21aSAnshuman Khandual  * POWER Data Stream Control Register (DSCR) explicit test
41554f21aSAnshuman Khandual  *
51554f21aSAnshuman Khandual  * This test modifies the DSCR value using mtspr instruction and
61554f21aSAnshuman Khandual  * verifies the change with mfspr instruction. It uses both the
71554f21aSAnshuman Khandual  * privilege state SPR and the problem state SPR for this purpose.
81554f21aSAnshuman Khandual  *
91554f21aSAnshuman Khandual  * When using the privilege state SPR, the instructions such as
1015f0c260SBenjamin Gray  * mfspr or mtspr are privileged and the kernel emulates them
1115f0c260SBenjamin Gray  * for us. Instructions using problem state SPR can be executed
121554f21aSAnshuman Khandual  * directly without any emulation if the HW supports them. Else
131554f21aSAnshuman Khandual  * they also get emulated by the kernel.
141554f21aSAnshuman Khandual  *
151554f21aSAnshuman Khandual  * Copyright 2012, Anton Blanchard, IBM Corporation.
161554f21aSAnshuman Khandual  * Copyright 2015, Anshuman Khandual, IBM Corporation.
171554f21aSAnshuman Khandual  */
181554f21aSAnshuman Khandual 
19fda81588SBenjamin Gray #define _GNU_SOURCE
20fda81588SBenjamin Gray 
21fda81588SBenjamin Gray #include "dscr.h"
22fda81588SBenjamin Gray #include "utils.h"
23fda81588SBenjamin Gray 
24fda81588SBenjamin Gray #include <pthread.h>
25fda81588SBenjamin Gray #include <sched.h>
26fda81588SBenjamin Gray #include <semaphore.h>
27fda81588SBenjamin Gray 
dscr_explicit_lockstep_thread(void * args)28fda81588SBenjamin Gray void *dscr_explicit_lockstep_thread(void *args)
29fda81588SBenjamin Gray {
30fda81588SBenjamin Gray 	sem_t *prev = (sem_t *)args;
31fda81588SBenjamin Gray 	sem_t *next = (sem_t *)args + 1;
32fda81588SBenjamin Gray 	unsigned long expected_dscr = 0;
33fda81588SBenjamin Gray 
34fda81588SBenjamin Gray 	set_dscr(expected_dscr);
35fda81588SBenjamin Gray 	srand(gettid());
36fda81588SBenjamin Gray 
37fda81588SBenjamin Gray 	for (int i = 0; i < COUNT; i++) {
38fda81588SBenjamin Gray 		FAIL_IF_EXIT(sem_wait(prev));
39fda81588SBenjamin Gray 
40fda81588SBenjamin Gray 		FAIL_IF_EXIT(expected_dscr != get_dscr());
41fda81588SBenjamin Gray 		FAIL_IF_EXIT(expected_dscr != get_dscr_usr());
42fda81588SBenjamin Gray 
43fda81588SBenjamin Gray 		expected_dscr = (expected_dscr + 1) % DSCR_MAX;
44fda81588SBenjamin Gray 		set_dscr(expected_dscr);
45fda81588SBenjamin Gray 
46fda81588SBenjamin Gray 		FAIL_IF_EXIT(sem_post(next));
47fda81588SBenjamin Gray 	}
48fda81588SBenjamin Gray 
49fda81588SBenjamin Gray 	return NULL;
50fda81588SBenjamin Gray }
51fda81588SBenjamin Gray 
dscr_explicit_lockstep_test(void)52fda81588SBenjamin Gray int dscr_explicit_lockstep_test(void)
53fda81588SBenjamin Gray {
54fda81588SBenjamin Gray 	pthread_t thread;
55fda81588SBenjamin Gray 	sem_t semaphores[2];
56fda81588SBenjamin Gray 	sem_t *prev = &semaphores[1];  /* reversed prev/next than for the other thread */
57fda81588SBenjamin Gray 	sem_t *next = &semaphores[0];
58fda81588SBenjamin Gray 	unsigned long expected_dscr = 0;
59fda81588SBenjamin Gray 
60fda81588SBenjamin Gray 	SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
61fda81588SBenjamin Gray 
62fda81588SBenjamin Gray 	srand(gettid());
63fda81588SBenjamin Gray 	set_dscr(expected_dscr);
64fda81588SBenjamin Gray 
65fda81588SBenjamin Gray 	FAIL_IF(sem_init(prev, 0, 0));
66fda81588SBenjamin Gray 	FAIL_IF(sem_init(next, 0, 1));  /* other thread starts first */
67fda81588SBenjamin Gray 	FAIL_IF(bind_to_cpu(BIND_CPU_ANY) < 0);
68fda81588SBenjamin Gray 	FAIL_IF(pthread_create(&thread, NULL, dscr_explicit_lockstep_thread, (void *)semaphores));
69fda81588SBenjamin Gray 
70fda81588SBenjamin Gray 	for (int i = 0; i < COUNT; i++) {
71fda81588SBenjamin Gray 		FAIL_IF(sem_wait(prev));
72fda81588SBenjamin Gray 
73fda81588SBenjamin Gray 		FAIL_IF(expected_dscr != get_dscr());
74fda81588SBenjamin Gray 		FAIL_IF(expected_dscr != get_dscr_usr());
75fda81588SBenjamin Gray 
76fda81588SBenjamin Gray 		expected_dscr = (expected_dscr - 1) % DSCR_MAX;
77fda81588SBenjamin Gray 		set_dscr(expected_dscr);
78fda81588SBenjamin Gray 
79fda81588SBenjamin Gray 		FAIL_IF(sem_post(next));
80fda81588SBenjamin Gray 	}
81fda81588SBenjamin Gray 
82fda81588SBenjamin Gray 	FAIL_IF(pthread_join(thread, NULL));
83fda81588SBenjamin Gray 	FAIL_IF(sem_destroy(prev));
84fda81588SBenjamin Gray 	FAIL_IF(sem_destroy(next));
85fda81588SBenjamin Gray 
86fda81588SBenjamin Gray 	return 0;
87fda81588SBenjamin Gray }
88fda81588SBenjamin Gray 
89*3067b89aSBenjamin Gray struct random_thread_args {
90*3067b89aSBenjamin Gray 	pthread_t thread_id;
91*3067b89aSBenjamin Gray 	bool do_yields;
92*3067b89aSBenjamin Gray 	pthread_barrier_t *barrier;
93*3067b89aSBenjamin Gray };
94*3067b89aSBenjamin Gray 
dscr_explicit_random_thread(void * in)95*3067b89aSBenjamin Gray void *dscr_explicit_random_thread(void *in)
96*3067b89aSBenjamin Gray {
97*3067b89aSBenjamin Gray 	struct random_thread_args *args = (struct random_thread_args *)in;
98*3067b89aSBenjamin Gray 	unsigned long expected_dscr = 0;
99*3067b89aSBenjamin Gray 	int err;
100*3067b89aSBenjamin Gray 
101*3067b89aSBenjamin Gray 	srand(gettid());
102*3067b89aSBenjamin Gray 
103*3067b89aSBenjamin Gray 	err = pthread_barrier_wait(args->barrier);
104*3067b89aSBenjamin Gray 	FAIL_IF_EXIT(err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD);
105*3067b89aSBenjamin Gray 
106*3067b89aSBenjamin Gray 	for (int i = 0; i < COUNT; i++) {
107*3067b89aSBenjamin Gray 		expected_dscr = rand() % DSCR_MAX;
108*3067b89aSBenjamin Gray 		set_dscr(expected_dscr);
109*3067b89aSBenjamin Gray 
110*3067b89aSBenjamin Gray 		for (int j = rand() % 5; j > 0; --j) {
111*3067b89aSBenjamin Gray 			FAIL_IF_EXIT(get_dscr() != expected_dscr);
112*3067b89aSBenjamin Gray 			FAIL_IF_EXIT(get_dscr_usr() != expected_dscr);
113*3067b89aSBenjamin Gray 
114*3067b89aSBenjamin Gray 			if (args->do_yields && rand() % 2)
115*3067b89aSBenjamin Gray 				sched_yield();
116*3067b89aSBenjamin Gray 		}
117*3067b89aSBenjamin Gray 
118*3067b89aSBenjamin Gray 		expected_dscr = rand() % DSCR_MAX;
119*3067b89aSBenjamin Gray 		set_dscr_usr(expected_dscr);
120*3067b89aSBenjamin Gray 
121*3067b89aSBenjamin Gray 		for (int j = rand() % 5; j > 0; --j) {
122*3067b89aSBenjamin Gray 			FAIL_IF_EXIT(get_dscr() != expected_dscr);
123*3067b89aSBenjamin Gray 			FAIL_IF_EXIT(get_dscr_usr() != expected_dscr);
124*3067b89aSBenjamin Gray 
125*3067b89aSBenjamin Gray 			if (args->do_yields && rand() % 2)
126*3067b89aSBenjamin Gray 				sched_yield();
127*3067b89aSBenjamin Gray 		}
128*3067b89aSBenjamin Gray 	}
129*3067b89aSBenjamin Gray 
130*3067b89aSBenjamin Gray 	return NULL;
131*3067b89aSBenjamin Gray }
132*3067b89aSBenjamin Gray 
dscr_explicit_random_test(void)133fda81588SBenjamin Gray int dscr_explicit_random_test(void)
1341554f21aSAnshuman Khandual {
135*3067b89aSBenjamin Gray 	struct random_thread_args threads[THREADS];
136*3067b89aSBenjamin Gray 	pthread_barrier_t barrier;
1371554f21aSAnshuman Khandual 
1384c3c3c50SMichael Ellerman 	SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
1394c3c3c50SMichael Ellerman 
140*3067b89aSBenjamin Gray 	FAIL_IF(pthread_barrier_init(&barrier, NULL, THREADS));
1411554f21aSAnshuman Khandual 
142*3067b89aSBenjamin Gray 	for (int i = 0; i < THREADS; i++) {
143*3067b89aSBenjamin Gray 		threads[i].do_yields = i % 2 == 0;
144*3067b89aSBenjamin Gray 		threads[i].barrier = &barrier;
1451554f21aSAnshuman Khandual 
146*3067b89aSBenjamin Gray 		FAIL_IF(pthread_create(&threads[i].thread_id, NULL,
147*3067b89aSBenjamin Gray 				       dscr_explicit_random_thread, (void *)&threads[i]));
1481554f21aSAnshuman Khandual 	}
1491554f21aSAnshuman Khandual 
150*3067b89aSBenjamin Gray 	for (int i = 0; i < THREADS; i++)
151*3067b89aSBenjamin Gray 		FAIL_IF(pthread_join(threads[i].thread_id, NULL));
1521554f21aSAnshuman Khandual 
153*3067b89aSBenjamin Gray 	FAIL_IF(pthread_barrier_destroy(&barrier));
1541554f21aSAnshuman Khandual 
1551554f21aSAnshuman Khandual 	return 0;
1561554f21aSAnshuman Khandual }
1571554f21aSAnshuman Khandual 
main(int argc,char * argv[])1581554f21aSAnshuman Khandual int main(int argc, char *argv[])
1591554f21aSAnshuman Khandual {
160fda81588SBenjamin Gray 	unsigned long orig_dscr_default = 0;
161fda81588SBenjamin Gray 	int err = 0;
162fda81588SBenjamin Gray 
163fda81588SBenjamin Gray 	if (have_hwcap2(PPC_FEATURE2_DSCR))
164fda81588SBenjamin Gray 		orig_dscr_default = get_default_dscr();
165fda81588SBenjamin Gray 
166fda81588SBenjamin Gray 	err |= test_harness(dscr_explicit_lockstep_test, "dscr_explicit_lockstep_test");
167fda81588SBenjamin Gray 	err |= test_harness(dscr_explicit_random_test, "dscr_explicit_random_test");
168fda81588SBenjamin Gray 
169fda81588SBenjamin Gray 	if (have_hwcap2(PPC_FEATURE2_DSCR))
170fda81588SBenjamin Gray 		set_default_dscr(orig_dscr_default);
171fda81588SBenjamin Gray 
172fda81588SBenjamin Gray 	return err;
1731554f21aSAnshuman Khandual }
174