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