summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-04-28 16:24:32 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2023-04-28 16:24:32 -0700
commit70cc1b5307e8ee3076fdf2ecbeb89eb973aa0ff7 (patch)
tree6928e81a009668e6af4ca7408db2c35549a0f433 /tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
parent5ea8abf589f2974d65460a1ffa0c303763e958da (diff)
parent169f8997968ab620d750d9a45e15c5288d498356 (diff)
Merge tag 'powerpc-6.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc updates from Michael Ellerman: - Add support for building the kernel using PC-relative addressing on Power10. - Allow HV KVM guests on Power10 to use prefixed instructions. - Unify support for the P2020 CPU (85xx) into a single machine description. - Always build the 64-bit kernel with 128-bit long double. - Drop support for several obsolete 2000's era development boards as identified by Paul Gortmaker. - A series fixing VFIO on Power since some generic changes. - Various other small features and fixes. Thanks to Alexey Kardashevskiy, Andrew Donnellan, Benjamin Gray, Bo Liu, Christophe Leroy, Dan Carpenter, David Binderman, Ira Weiny, Joel Stanley, Kajol Jain, Kautuk Consul, Liang He, Luis Chamberlain, Masahiro Yamada, Michael Neuling, Nathan Chancellor, Nathan Lynch, Nicholas Miehlbradt, Nicholas Piggin, Nick Desaulniers, Nysal Jan K.A, Pali Rohár, Paul Gortmaker, Paul Mackerras, Petr Vaněk, Randy Dunlap, Rob Herring, Sachin Sant, Sean Christopherson, Segher Boessenkool, and Timothy Pearson. * tag 'powerpc-6.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (156 commits) powerpc/64s: Disable pcrel code model on Clang powerpc: Fix merge conflict between pcrel and copy_thread changes powerpc/configs/powernv: Add IGB=y powerpc/configs/64s: Drop JFS Filesystem powerpc/configs/64s: Use EXT4 to mount EXT2 filesystems powerpc/configs: Make pseries_defconfig an alias for ppc64le_guest powerpc/configs: Make pseries_le an alias for ppc64le_guest powerpc/configs: Incorporate generic kvm_guest.config into guest configs powerpc/configs: Add IBMVETH=y and IBMVNIC=y to guest configs powerpc/configs/64s: Enable Device Mapper options powerpc/configs/64s: Enable PSTORE powerpc/configs/64s: Enable VLAN support powerpc/configs/64s: Enable BLK_DEV_NVME powerpc/configs/64s: Drop REISERFS powerpc/configs/64s: Use SHA512 for module signatures powerpc/configs/64s: Enable IO_STRICT_DEVMEM powerpc/configs/64s: Enable SCHEDSTATS powerpc/configs/64s: Enable DEBUG_VM & other options powerpc/configs/64s: Enable EMULATED_STATS powerpc/configs/64s: Enable KUNIT and most tests ...
Diffstat (limited to 'tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c')
-rw-r--r--tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c169
1 files changed, 136 insertions, 33 deletions
diff --git a/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c b/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
index 32fcf2b324b1..e2268e9183a8 100644
--- a/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
+++ b/tools/testing/selftests/powerpc/dscr/dscr_explicit_test.c
@@ -7,64 +7,167 @@
* privilege state SPR and the problem state SPR for this purpose.
*
* When using the privilege state SPR, the instructions such as
- * mfspr or mtspr are priviledged and the kernel emulates them
- * for us. Instructions using problem state SPR can be exuecuted
+ * mfspr or mtspr are privileged and the kernel emulates them
+ * for us. Instructions using problem state SPR can be executed
* directly without any emulation if the HW supports them. Else
* they also get emulated by the kernel.
*
* Copyright 2012, Anton Blanchard, IBM Corporation.
* Copyright 2015, Anshuman Khandual, IBM Corporation.
*/
+
+#define _GNU_SOURCE
+
#include "dscr.h"
+#include "utils.h"
+
+#include <pthread.h>
+#include <sched.h>
+#include <semaphore.h>
-int dscr_explicit(void)
+void *dscr_explicit_lockstep_thread(void *args)
{
- unsigned long i, dscr = 0;
+ sem_t *prev = (sem_t *)args;
+ sem_t *next = (sem_t *)args + 1;
+ unsigned long expected_dscr = 0;
+
+ set_dscr(expected_dscr);
+ srand(gettid());
+
+ for (int i = 0; i < COUNT; i++) {
+ FAIL_IF_EXIT(sem_wait(prev));
+
+ FAIL_IF_EXIT(expected_dscr != get_dscr());
+ FAIL_IF_EXIT(expected_dscr != get_dscr_usr());
+
+ expected_dscr = (expected_dscr + 1) % DSCR_MAX;
+ set_dscr(expected_dscr);
+
+ FAIL_IF_EXIT(sem_post(next));
+ }
+
+ return NULL;
+}
+
+int dscr_explicit_lockstep_test(void)
+{
+ pthread_t thread;
+ sem_t semaphores[2];
+ sem_t *prev = &semaphores[1]; /* reversed prev/next than for the other thread */
+ sem_t *next = &semaphores[0];
+ unsigned long expected_dscr = 0;
SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
- srand(getpid());
- set_dscr(dscr);
+ srand(gettid());
+ set_dscr(expected_dscr);
- for (i = 0; i < COUNT; i++) {
- unsigned long cur_dscr, cur_dscr_usr;
- double ret = uniform_deviate(rand());
+ FAIL_IF(sem_init(prev, 0, 0));
+ FAIL_IF(sem_init(next, 0, 1)); /* other thread starts first */
+ FAIL_IF(bind_to_cpu(BIND_CPU_ANY) < 0);
+ FAIL_IF(pthread_create(&thread, NULL, dscr_explicit_lockstep_thread, (void *)semaphores));
- if (ret < 0.001) {
- dscr++;
- if (dscr > DSCR_MAX)
- dscr = 0;
+ for (int i = 0; i < COUNT; i++) {
+ FAIL_IF(sem_wait(prev));
- set_dscr(dscr);
- }
+ FAIL_IF(expected_dscr != get_dscr());
+ FAIL_IF(expected_dscr != get_dscr_usr());
- cur_dscr = get_dscr();
- if (cur_dscr != dscr) {
- fprintf(stderr, "Kernel DSCR should be %ld but "
- "is %ld\n", dscr, cur_dscr);
- return 1;
- }
+ expected_dscr = (expected_dscr - 1) % DSCR_MAX;
+ set_dscr(expected_dscr);
+
+ FAIL_IF(sem_post(next));
+ }
+
+ FAIL_IF(pthread_join(thread, NULL));
+ FAIL_IF(sem_destroy(prev));
+ FAIL_IF(sem_destroy(next));
+
+ return 0;
+}
+
+struct random_thread_args {
+ pthread_t thread_id;
+ bool do_yields;
+ pthread_barrier_t *barrier;
+};
+
+void *dscr_explicit_random_thread(void *in)
+{
+ struct random_thread_args *args = (struct random_thread_args *)in;
+ unsigned long expected_dscr = 0;
+ int err;
+
+ srand(gettid());
+
+ err = pthread_barrier_wait(args->barrier);
+ FAIL_IF_EXIT(err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD);
- ret = uniform_deviate(rand());
- if (ret < 0.001) {
- dscr++;
- if (dscr > DSCR_MAX)
- dscr = 0;
+ for (int i = 0; i < COUNT; i++) {
+ expected_dscr = rand() % DSCR_MAX;
+ set_dscr(expected_dscr);
- set_dscr_usr(dscr);
+ for (int j = rand() % 5; j > 0; --j) {
+ FAIL_IF_EXIT(get_dscr() != expected_dscr);
+ FAIL_IF_EXIT(get_dscr_usr() != expected_dscr);
+
+ if (args->do_yields && rand() % 2)
+ sched_yield();
}
- cur_dscr_usr = get_dscr_usr();
- if (cur_dscr_usr != dscr) {
- fprintf(stderr, "User DSCR should be %ld but "
- "is %ld\n", dscr, cur_dscr_usr);
- return 1;
+ expected_dscr = rand() % DSCR_MAX;
+ set_dscr_usr(expected_dscr);
+
+ for (int j = rand() % 5; j > 0; --j) {
+ FAIL_IF_EXIT(get_dscr() != expected_dscr);
+ FAIL_IF_EXIT(get_dscr_usr() != expected_dscr);
+
+ if (args->do_yields && rand() % 2)
+ sched_yield();
}
}
+
+ return NULL;
+}
+
+int dscr_explicit_random_test(void)
+{
+ struct random_thread_args threads[THREADS];
+ pthread_barrier_t barrier;
+
+ SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
+
+ FAIL_IF(pthread_barrier_init(&barrier, NULL, THREADS));
+
+ for (int i = 0; i < THREADS; i++) {
+ threads[i].do_yields = i % 2 == 0;
+ threads[i].barrier = &barrier;
+
+ FAIL_IF(pthread_create(&threads[i].thread_id, NULL,
+ dscr_explicit_random_thread, (void *)&threads[i]));
+ }
+
+ for (int i = 0; i < THREADS; i++)
+ FAIL_IF(pthread_join(threads[i].thread_id, NULL));
+
+ FAIL_IF(pthread_barrier_destroy(&barrier));
+
return 0;
}
int main(int argc, char *argv[])
{
- return test_harness(dscr_explicit, "dscr_explicit_test");
+ unsigned long orig_dscr_default = 0;
+ int err = 0;
+
+ if (have_hwcap2(PPC_FEATURE2_DSCR))
+ orig_dscr_default = get_default_dscr();
+
+ err |= test_harness(dscr_explicit_lockstep_test, "dscr_explicit_lockstep_test");
+ err |= test_harness(dscr_explicit_random_test, "dscr_explicit_random_test");
+
+ if (have_hwcap2(PPC_FEATURE2_DSCR))
+ set_default_dscr(orig_dscr_default);
+
+ return err;
}