]> Git Repo - J-linux.git/blob - tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux...
[J-linux.git] / tools / testing / selftests / powerpc / dscr / dscr_explicit_test.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * POWER Data Stream Control Register (DSCR) explicit test
4  *
5  * This test modifies the DSCR value using mtspr instruction and
6  * verifies the change with mfspr instruction. It uses both the
7  * privilege state SPR and the problem state SPR for this purpose.
8  *
9  * When using the privilege state SPR, the instructions such as
10  * mfspr or mtspr are privileged and the kernel emulates them
11  * for us. Instructions using problem state SPR can be executed
12  * directly without any emulation if the HW supports them. Else
13  * they also get emulated by the kernel.
14  *
15  * Copyright 2012, Anton Blanchard, IBM Corporation.
16  * Copyright 2015, Anshuman Khandual, IBM Corporation.
17  */
18
19 #define _GNU_SOURCE
20
21 #include "dscr.h"
22 #include "utils.h"
23
24 #include <pthread.h>
25 #include <sched.h>
26 #include <semaphore.h>
27
28 void *dscr_explicit_lockstep_thread(void *args)
29 {
30         sem_t *prev = (sem_t *)args;
31         sem_t *next = (sem_t *)args + 1;
32         unsigned long expected_dscr = 0;
33
34         set_dscr(expected_dscr);
35         srand(gettid());
36
37         for (int i = 0; i < COUNT; i++) {
38                 FAIL_IF_EXIT(sem_wait(prev));
39
40                 FAIL_IF_EXIT(expected_dscr != get_dscr());
41                 FAIL_IF_EXIT(expected_dscr != get_dscr_usr());
42
43                 expected_dscr = (expected_dscr + 1) % DSCR_MAX;
44                 set_dscr(expected_dscr);
45
46                 FAIL_IF_EXIT(sem_post(next));
47         }
48
49         return NULL;
50 }
51
52 int dscr_explicit_lockstep_test(void)
53 {
54         pthread_t thread;
55         sem_t semaphores[2];
56         sem_t *prev = &semaphores[1];  /* reversed prev/next than for the other thread */
57         sem_t *next = &semaphores[0];
58         unsigned long expected_dscr = 0;
59
60         SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
61
62         srand(gettid());
63         set_dscr(expected_dscr);
64
65         FAIL_IF(sem_init(prev, 0, 0));
66         FAIL_IF(sem_init(next, 0, 1));  /* other thread starts first */
67         FAIL_IF(bind_to_cpu(BIND_CPU_ANY) < 0);
68         FAIL_IF(pthread_create(&thread, NULL, dscr_explicit_lockstep_thread, (void *)semaphores));
69
70         for (int i = 0; i < COUNT; i++) {
71                 FAIL_IF(sem_wait(prev));
72
73                 FAIL_IF(expected_dscr != get_dscr());
74                 FAIL_IF(expected_dscr != get_dscr_usr());
75
76                 expected_dscr = (expected_dscr - 1) % DSCR_MAX;
77                 set_dscr(expected_dscr);
78
79                 FAIL_IF(sem_post(next));
80         }
81
82         FAIL_IF(pthread_join(thread, NULL));
83         FAIL_IF(sem_destroy(prev));
84         FAIL_IF(sem_destroy(next));
85
86         return 0;
87 }
88
89 struct random_thread_args {
90         pthread_t thread_id;
91         bool do_yields;
92         pthread_barrier_t *barrier;
93 };
94
95 void *dscr_explicit_random_thread(void *in)
96 {
97         struct random_thread_args *args = (struct random_thread_args *)in;
98         unsigned long expected_dscr = 0;
99         int err;
100
101         srand(gettid());
102
103         err = pthread_barrier_wait(args->barrier);
104         FAIL_IF_EXIT(err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD);
105
106         for (int i = 0; i < COUNT; i++) {
107                 expected_dscr = rand() % DSCR_MAX;
108                 set_dscr(expected_dscr);
109
110                 for (int j = rand() % 5; j > 0; --j) {
111                         FAIL_IF_EXIT(get_dscr() != expected_dscr);
112                         FAIL_IF_EXIT(get_dscr_usr() != expected_dscr);
113
114                         if (args->do_yields && rand() % 2)
115                                 sched_yield();
116                 }
117
118                 expected_dscr = rand() % DSCR_MAX;
119                 set_dscr_usr(expected_dscr);
120
121                 for (int j = rand() % 5; j > 0; --j) {
122                         FAIL_IF_EXIT(get_dscr() != expected_dscr);
123                         FAIL_IF_EXIT(get_dscr_usr() != expected_dscr);
124
125                         if (args->do_yields && rand() % 2)
126                                 sched_yield();
127                 }
128         }
129
130         return NULL;
131 }
132
133 int dscr_explicit_random_test(void)
134 {
135         struct random_thread_args threads[THREADS];
136         pthread_barrier_t barrier;
137
138         SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
139
140         FAIL_IF(pthread_barrier_init(&barrier, NULL, THREADS));
141
142         for (int i = 0; i < THREADS; i++) {
143                 threads[i].do_yields = i % 2 == 0;
144                 threads[i].barrier = &barrier;
145
146                 FAIL_IF(pthread_create(&threads[i].thread_id, NULL,
147                                        dscr_explicit_random_thread, (void *)&threads[i]));
148         }
149
150         for (int i = 0; i < THREADS; i++)
151                 FAIL_IF(pthread_join(threads[i].thread_id, NULL));
152
153         FAIL_IF(pthread_barrier_destroy(&barrier));
154
155         return 0;
156 }
157
158 int main(int argc, char *argv[])
159 {
160         unsigned long orig_dscr_default = 0;
161         int err = 0;
162
163         if (have_hwcap2(PPC_FEATURE2_DSCR))
164                 orig_dscr_default = get_default_dscr();
165
166         err |= test_harness(dscr_explicit_lockstep_test, "dscr_explicit_lockstep_test");
167         err |= test_harness(dscr_explicit_random_test, "dscr_explicit_random_test");
168
169         if (have_hwcap2(PPC_FEATURE2_DSCR))
170                 set_default_dscr(orig_dscr_default);
171
172         return err;
173 }
This page took 0.037499 seconds and 4 git commands to generate.