brintos

brintos / linux-shallow public Read only

0
0
Text · 4.1 KiB · e2268e9 Raw
174 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * POWER Data Stream Control Register (DSCR) explicit test4 *5 * This test modifies the DSCR value using mtspr instruction and6 * verifies the change with mfspr instruction. It uses both the7 * privilege state SPR and the problem state SPR for this purpose.8 *9 * When using the privilege state SPR, the instructions such as10 * mfspr or mtspr are privileged and the kernel emulates them11 * for us. Instructions using problem state SPR can be executed12 * directly without any emulation if the HW supports them. Else13 * 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_SOURCE20 21#include "dscr.h"22#include "utils.h"23 24#include <pthread.h>25#include <sched.h>26#include <semaphore.h>27 28void *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 52int 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 89struct random_thread_args {90	pthread_t thread_id;91	bool do_yields;92	pthread_barrier_t *barrier;93};94 95void *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 133int 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 158int 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}174