xref: /kvm-unit-tests/arm/spinlock-test.c (revision 232f404a76d6f531036f06044bd173197894eda7)
1 /*
2  * Spinlock test
3  *
4  * This code is based on code from the tcg_baremetal_tests.
5  *
6  * Copyright (C) 2015 Virtual Open Systems SAS
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 
13 #include <libcflat.h>
14 #include <asm/smp.h>
15 #include <asm/cpumask.h>
16 #include <asm/barrier.h>
17 
18 #define LOOP_SIZE 10000000
19 
20 struct lock_ops {
21 	void (*lock)(int *v);
22 	void (*unlock)(int *v);
23 };
24 static struct lock_ops lock_ops;
25 
26 static void gcc_builtin_lock(int *lock_var)
27 {
28 	while (__sync_lock_test_and_set(lock_var, 1));
29 }
30 static void gcc_builtin_unlock(int *lock_var)
31 {
32 	__sync_lock_release(lock_var);
33 }
34 static void none_lock(int *lock_var)
35 {
36 	while (*(volatile int *)lock_var != 0);
37 	*(volatile int *)lock_var = 1;
38 }
39 static void none_unlock(int *lock_var)
40 {
41 	*(volatile int *)lock_var = 0;
42 }
43 
44 static int global_a, global_b;
45 static int global_lock;
46 
47 static cpumask_t smp_test_complete;
48 
49 static void test_spinlock(void)
50 {
51 	int i, errors = 0;
52 	int cpu = smp_processor_id();
53 
54 	printf("CPU%d online\n", cpu);
55 
56 	for (i = 0; i < LOOP_SIZE; i++) {
57 
58 		lock_ops.lock(&global_lock);
59 
60 		if (global_a == (cpu + 1) % 2) {
61 			global_a = 1;
62 			global_b = 0;
63 		} else {
64 			global_a = 0;
65 			global_b = 1;
66 		}
67 
68 		if (global_a == global_b)
69 			errors++;
70 
71 		lock_ops.unlock(&global_lock);
72 	}
73 	report("CPU%d: Done - Errors: %d", errors == 0, cpu, errors);
74 
75 	cpumask_set_cpu(cpu, &smp_test_complete);
76 	if (cpu != 0)
77 		halt();
78 }
79 
80 int main(int argc, char **argv)
81 {
82 	int cpu;
83 
84 	if (argc > 1 && strcmp(argv[1], "bad") != 0) {
85 		lock_ops.lock = gcc_builtin_lock;
86 		lock_ops.unlock = gcc_builtin_unlock;
87 	} else {
88 		lock_ops.lock = none_lock;
89 		lock_ops.unlock = none_unlock;
90 	}
91 
92 	for_each_present_cpu(cpu) {
93 		if (cpu == 0)
94 			continue;
95 		smp_boot_secondary(cpu, test_spinlock);
96 	}
97 
98 	test_spinlock();
99 
100 	while (!cpumask_full(&smp_test_complete))
101 		cpu_relax();
102 
103 	return report_summary();
104 }
105