1*354b5c19SPierrick Bouvier /* 2*354b5c19SPierrick Bouvier * SPDX-License-Identifier: GPL-2.0-or-later 3*354b5c19SPierrick Bouvier * 4*354b5c19SPierrick Bouvier * Check if we detect all memory accesses expected using plugin API. 5*354b5c19SPierrick Bouvier * Used in conjunction with ./check-plugin-mem-access.sh check script. 6*354b5c19SPierrick Bouvier * Output of this program is the list of patterns expected in plugin output. 7*354b5c19SPierrick Bouvier * 8*354b5c19SPierrick Bouvier * 8,16,32 load/store are tested for all arch. 9*354b5c19SPierrick Bouvier * 64,128 load/store are tested for aarch64/x64. 10*354b5c19SPierrick Bouvier * atomic operations (8,16,32,64) are tested for x64 only. 11*354b5c19SPierrick Bouvier */ 12*354b5c19SPierrick Bouvier 13*354b5c19SPierrick Bouvier #include <pthread.h> 14*354b5c19SPierrick Bouvier #include <stdint.h> 15*354b5c19SPierrick Bouvier #include <stdio.h> 16*354b5c19SPierrick Bouvier #include <stdlib.h> 17*354b5c19SPierrick Bouvier 18*354b5c19SPierrick Bouvier #if defined(__x86_64__) 19*354b5c19SPierrick Bouvier #include <emmintrin.h> 20*354b5c19SPierrick Bouvier #elif defined(__aarch64__) 21*354b5c19SPierrick Bouvier #include <arm_neon.h> 22*354b5c19SPierrick Bouvier #endif /* __x86_64__ */ 23*354b5c19SPierrick Bouvier 24*354b5c19SPierrick Bouvier static void *data; 25*354b5c19SPierrick Bouvier 26*354b5c19SPierrick Bouvier /* ,store_u8,.*,8,store,0xf1 */ 27*354b5c19SPierrick Bouvier #define PRINT_EXPECTED(function, type, value, action) \ 28*354b5c19SPierrick Bouvier do { \ 29*354b5c19SPierrick Bouvier printf(",%s,.*,%d,%s,%s\n", \ 30*354b5c19SPierrick Bouvier #function, (int) sizeof(type) * 8, action, value); \ 31*354b5c19SPierrick Bouvier } \ 32*354b5c19SPierrick Bouvier while (0) 33*354b5c19SPierrick Bouvier 34*354b5c19SPierrick Bouvier #define DEFINE_STORE(name, type, value) \ 35*354b5c19SPierrick Bouvier \ 36*354b5c19SPierrick Bouvier static void print_expected_store_##name(void) \ 37*354b5c19SPierrick Bouvier { \ 38*354b5c19SPierrick Bouvier PRINT_EXPECTED(store_##name, type, #value, "store"); \ 39*354b5c19SPierrick Bouvier } \ 40*354b5c19SPierrick Bouvier \ 41*354b5c19SPierrick Bouvier static void store_##name(void) \ 42*354b5c19SPierrick Bouvier { \ 43*354b5c19SPierrick Bouvier *((type *)data) = value; \ 44*354b5c19SPierrick Bouvier print_expected_store_##name(); \ 45*354b5c19SPierrick Bouvier } 46*354b5c19SPierrick Bouvier 47*354b5c19SPierrick Bouvier #define DEFINE_ATOMIC_OP(name, type, value) \ 48*354b5c19SPierrick Bouvier \ 49*354b5c19SPierrick Bouvier static void print_expected_atomic_op_##name(void) \ 50*354b5c19SPierrick Bouvier { \ 51*354b5c19SPierrick Bouvier PRINT_EXPECTED(atomic_op_##name, type, "0x0*42", "load"); \ 52*354b5c19SPierrick Bouvier PRINT_EXPECTED(atomic_op_##name, type, #value, "store"); \ 53*354b5c19SPierrick Bouvier } \ 54*354b5c19SPierrick Bouvier \ 55*354b5c19SPierrick Bouvier static void atomic_op_##name(void) \ 56*354b5c19SPierrick Bouvier { \ 57*354b5c19SPierrick Bouvier *((type *)data) = 0x42; \ 58*354b5c19SPierrick Bouvier __sync_val_compare_and_swap((type *)data, 0x42, value); \ 59*354b5c19SPierrick Bouvier print_expected_atomic_op_##name(); \ 60*354b5c19SPierrick Bouvier } 61*354b5c19SPierrick Bouvier 62*354b5c19SPierrick Bouvier #define DEFINE_LOAD(name, type, value) \ 63*354b5c19SPierrick Bouvier \ 64*354b5c19SPierrick Bouvier static void print_expected_load_##name(void) \ 65*354b5c19SPierrick Bouvier { \ 66*354b5c19SPierrick Bouvier PRINT_EXPECTED(load_##name, type, #value, "load"); \ 67*354b5c19SPierrick Bouvier } \ 68*354b5c19SPierrick Bouvier \ 69*354b5c19SPierrick Bouvier static void load_##name(void) \ 70*354b5c19SPierrick Bouvier { \ 71*354b5c19SPierrick Bouvier \ 72*354b5c19SPierrick Bouvier /* volatile forces load to be generated. */ \ 73*354b5c19SPierrick Bouvier volatile type src = *((type *) data); \ 74*354b5c19SPierrick Bouvier volatile type dest = src; \ 75*354b5c19SPierrick Bouvier (void)src, (void)dest; \ 76*354b5c19SPierrick Bouvier print_expected_load_##name(); \ 77*354b5c19SPierrick Bouvier } 78*354b5c19SPierrick Bouvier 79*354b5c19SPierrick Bouvier DEFINE_STORE(u8, uint8_t, 0xf1) 80*354b5c19SPierrick Bouvier DEFINE_LOAD(u8, uint8_t, 0xf1) 81*354b5c19SPierrick Bouvier DEFINE_STORE(u16, uint16_t, 0xf123) 82*354b5c19SPierrick Bouvier DEFINE_LOAD(u16, uint16_t, 0xf123) 83*354b5c19SPierrick Bouvier DEFINE_STORE(u32, uint32_t, 0xff112233) 84*354b5c19SPierrick Bouvier DEFINE_LOAD(u32, uint32_t, 0xff112233) 85*354b5c19SPierrick Bouvier 86*354b5c19SPierrick Bouvier #if defined(__x86_64__) || defined(__aarch64__) 87*354b5c19SPierrick Bouvier DEFINE_STORE(u64, uint64_t, 0xf123456789abcdef) 88*354b5c19SPierrick Bouvier DEFINE_LOAD(u64, uint64_t, 0xf123456789abcdef) 89*354b5c19SPierrick Bouvier 90*354b5c19SPierrick Bouvier static void print_expected_store_u128(void) 91*354b5c19SPierrick Bouvier { 92*354b5c19SPierrick Bouvier PRINT_EXPECTED(store_u128, __int128, 93*354b5c19SPierrick Bouvier "0xf122334455667788f123456789abcdef", "store"); 94*354b5c19SPierrick Bouvier } 95*354b5c19SPierrick Bouvier 96*354b5c19SPierrick Bouvier static void store_u128(void) 97*354b5c19SPierrick Bouvier { 98*354b5c19SPierrick Bouvier #ifdef __x86_64__ 99*354b5c19SPierrick Bouvier _mm_store_si128(data, _mm_set_epi32(0xf1223344, 0x55667788, 100*354b5c19SPierrick Bouvier 0xf1234567, 0x89abcdef)); 101*354b5c19SPierrick Bouvier #else 102*354b5c19SPierrick Bouvier const uint32_t init[4] = {0x89abcdef, 0xf1234567, 0x55667788, 0xf1223344}; 103*354b5c19SPierrick Bouvier uint32x4_t vec = vld1q_u32(init); 104*354b5c19SPierrick Bouvier vst1q_u32(data, vec); 105*354b5c19SPierrick Bouvier #endif /* __x86_64__ */ 106*354b5c19SPierrick Bouvier print_expected_store_u128(); 107*354b5c19SPierrick Bouvier } 108*354b5c19SPierrick Bouvier 109*354b5c19SPierrick Bouvier static void print_expected_load_u128(void) 110*354b5c19SPierrick Bouvier { 111*354b5c19SPierrick Bouvier PRINT_EXPECTED(load_u128, __int128, 112*354b5c19SPierrick Bouvier "0xf122334455667788f123456789abcdef", "load"); 113*354b5c19SPierrick Bouvier } 114*354b5c19SPierrick Bouvier 115*354b5c19SPierrick Bouvier static void load_u128(void) 116*354b5c19SPierrick Bouvier { 117*354b5c19SPierrick Bouvier #ifdef __x86_64__ 118*354b5c19SPierrick Bouvier __m128i var = _mm_load_si128(data); 119*354b5c19SPierrick Bouvier #else 120*354b5c19SPierrick Bouvier uint32x4_t var = vld1q_u32(data); 121*354b5c19SPierrick Bouvier #endif 122*354b5c19SPierrick Bouvier (void) var; 123*354b5c19SPierrick Bouvier print_expected_load_u128(); 124*354b5c19SPierrick Bouvier } 125*354b5c19SPierrick Bouvier #endif /* __x86_64__ || __aarch64__ */ 126*354b5c19SPierrick Bouvier 127*354b5c19SPierrick Bouvier #if defined(__x86_64__) 128*354b5c19SPierrick Bouvier DEFINE_ATOMIC_OP(u8, uint8_t, 0xf1) 129*354b5c19SPierrick Bouvier DEFINE_ATOMIC_OP(u16, uint16_t, 0xf123) 130*354b5c19SPierrick Bouvier DEFINE_ATOMIC_OP(u32, uint32_t, 0xff112233) 131*354b5c19SPierrick Bouvier DEFINE_ATOMIC_OP(u64, uint64_t, 0xf123456789abcdef) 132*354b5c19SPierrick Bouvier #endif /* __x86_64__ */ 133*354b5c19SPierrick Bouvier 134*354b5c19SPierrick Bouvier static void *f(void *p) 135*354b5c19SPierrick Bouvier { 136*354b5c19SPierrick Bouvier return NULL; 137*354b5c19SPierrick Bouvier } 138*354b5c19SPierrick Bouvier 139*354b5c19SPierrick Bouvier int main(void) 140*354b5c19SPierrick Bouvier { 141*354b5c19SPierrick Bouvier /* 142*354b5c19SPierrick Bouvier * We force creation of a second thread to enable cpu flag CF_PARALLEL. 143*354b5c19SPierrick Bouvier * This will generate atomic operations when needed. 144*354b5c19SPierrick Bouvier */ 145*354b5c19SPierrick Bouvier pthread_t thread; 146*354b5c19SPierrick Bouvier pthread_create(&thread, NULL, &f, NULL); 147*354b5c19SPierrick Bouvier pthread_join(thread, NULL); 148*354b5c19SPierrick Bouvier 149*354b5c19SPierrick Bouvier /* allocate storage up to 128 bits */ 150*354b5c19SPierrick Bouvier data = malloc(16); 151*354b5c19SPierrick Bouvier 152*354b5c19SPierrick Bouvier store_u8(); 153*354b5c19SPierrick Bouvier load_u8(); 154*354b5c19SPierrick Bouvier 155*354b5c19SPierrick Bouvier store_u16(); 156*354b5c19SPierrick Bouvier load_u16(); 157*354b5c19SPierrick Bouvier 158*354b5c19SPierrick Bouvier store_u32(); 159*354b5c19SPierrick Bouvier load_u32(); 160*354b5c19SPierrick Bouvier 161*354b5c19SPierrick Bouvier #if defined(__x86_64__) || defined(__aarch64__) 162*354b5c19SPierrick Bouvier store_u64(); 163*354b5c19SPierrick Bouvier load_u64(); 164*354b5c19SPierrick Bouvier 165*354b5c19SPierrick Bouvier store_u128(); 166*354b5c19SPierrick Bouvier load_u128(); 167*354b5c19SPierrick Bouvier #endif /* __x86_64__ || __aarch64__ */ 168*354b5c19SPierrick Bouvier 169*354b5c19SPierrick Bouvier #if defined(__x86_64__) 170*354b5c19SPierrick Bouvier atomic_op_u8(); 171*354b5c19SPierrick Bouvier atomic_op_u16(); 172*354b5c19SPierrick Bouvier atomic_op_u32(); 173*354b5c19SPierrick Bouvier atomic_op_u64(); 174*354b5c19SPierrick Bouvier #endif /* __x86_64__ */ 175*354b5c19SPierrick Bouvier 176*354b5c19SPierrick Bouvier free(data); 177*354b5c19SPierrick Bouvier } 178