14ea7633eSAndrew Jones #include <libcflat.h> 24ea7633eSAndrew Jones #include <asm/smp.h> 34ea7633eSAndrew Jones #include <asm/cpumask.h> 44ea7633eSAndrew Jones #include <asm/barrier.h> 54ea7633eSAndrew Jones 64ea7633eSAndrew Jones #define LOOP_SIZE 10000000 74ea7633eSAndrew Jones 84ea7633eSAndrew Jones struct lock_ops { 94ea7633eSAndrew Jones void (*lock)(int *v); 104ea7633eSAndrew Jones void (*unlock)(int *v); 114ea7633eSAndrew Jones }; 124ea7633eSAndrew Jones static struct lock_ops lock_ops; 134ea7633eSAndrew Jones 144ea7633eSAndrew Jones static void gcc_builtin_lock(int *lock_var) 154ea7633eSAndrew Jones { 164ea7633eSAndrew Jones while (__sync_lock_test_and_set(lock_var, 1)); 174ea7633eSAndrew Jones } 184ea7633eSAndrew Jones static void gcc_builtin_unlock(int *lock_var) 194ea7633eSAndrew Jones { 204ea7633eSAndrew Jones __sync_lock_release(lock_var); 214ea7633eSAndrew Jones } 224ea7633eSAndrew Jones static void none_lock(int *lock_var) 234ea7633eSAndrew Jones { 2462423b6eSPaolo Bonzini while (*(volatile int *)lock_var != 0); 2562423b6eSPaolo Bonzini *(volatile int *)lock_var = 1; 264ea7633eSAndrew Jones } 274ea7633eSAndrew Jones static void none_unlock(int *lock_var) 284ea7633eSAndrew Jones { 2962423b6eSPaolo Bonzini *(volatile int *)lock_var = 0; 304ea7633eSAndrew Jones } 314ea7633eSAndrew Jones 324ea7633eSAndrew Jones static int global_a, global_b; 334ea7633eSAndrew Jones static int global_lock; 344ea7633eSAndrew Jones 354ea7633eSAndrew Jones static cpumask_t smp_test_complete; 364ea7633eSAndrew Jones 374ea7633eSAndrew Jones static void test_spinlock(void) 384ea7633eSAndrew Jones { 394ea7633eSAndrew Jones int i, errors = 0; 404ea7633eSAndrew Jones int cpu = smp_processor_id(); 414ea7633eSAndrew Jones 424ea7633eSAndrew Jones printf("CPU%d online\n", cpu); 434ea7633eSAndrew Jones 444ea7633eSAndrew Jones for (i = 0; i < LOOP_SIZE; i++) { 454ea7633eSAndrew Jones 464ea7633eSAndrew Jones lock_ops.lock(&global_lock); 474ea7633eSAndrew Jones 484ea7633eSAndrew Jones if (global_a == (cpu + 1) % 2) { 494ea7633eSAndrew Jones global_a = 1; 504ea7633eSAndrew Jones global_b = 0; 514ea7633eSAndrew Jones } else { 524ea7633eSAndrew Jones global_a = 0; 534ea7633eSAndrew Jones global_b = 1; 544ea7633eSAndrew Jones } 554ea7633eSAndrew Jones 564ea7633eSAndrew Jones if (global_a == global_b) 574ea7633eSAndrew Jones errors++; 584ea7633eSAndrew Jones 594ea7633eSAndrew Jones lock_ops.unlock(&global_lock); 604ea7633eSAndrew Jones } 61*d637cb11SAndrew Jones report("CPU%d: Done - Errors: %d", errors == 0, cpu, errors); 624ea7633eSAndrew Jones 634ea7633eSAndrew Jones cpumask_set_cpu(cpu, &smp_test_complete); 644ea7633eSAndrew Jones if (cpu != 0) 654ea7633eSAndrew Jones halt(); 664ea7633eSAndrew Jones } 674ea7633eSAndrew Jones 684ea7633eSAndrew Jones int main(int argc, char **argv) 694ea7633eSAndrew Jones { 704ea7633eSAndrew Jones int cpu; 714ea7633eSAndrew Jones 726ffea954SAndrew Jones if (argc > 1 && strcmp(argv[1], "bad") != 0) { 734ea7633eSAndrew Jones lock_ops.lock = gcc_builtin_lock; 744ea7633eSAndrew Jones lock_ops.unlock = gcc_builtin_unlock; 754ea7633eSAndrew Jones } else { 764ea7633eSAndrew Jones lock_ops.lock = none_lock; 774ea7633eSAndrew Jones lock_ops.unlock = none_unlock; 784ea7633eSAndrew Jones } 794ea7633eSAndrew Jones 804ea7633eSAndrew Jones for_each_present_cpu(cpu) { 814ea7633eSAndrew Jones if (cpu == 0) 824ea7633eSAndrew Jones continue; 834ea7633eSAndrew Jones smp_boot_secondary(cpu, test_spinlock); 844ea7633eSAndrew Jones } 854ea7633eSAndrew Jones 864ea7633eSAndrew Jones test_spinlock(); 874ea7633eSAndrew Jones 884ea7633eSAndrew Jones while (!cpumask_full(&smp_test_complete)) 894ea7633eSAndrew Jones cpu_relax(); 904ea7633eSAndrew Jones 914ea7633eSAndrew Jones return report_summary(); 924ea7633eSAndrew Jones } 93