xref: /openbmc/qemu/tests/tcg/multiarch/tb-link.c (revision 361b056fe9dd830b421fe8959682dc5a3c35a32c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Verify that a single TB spin-loop is properly invalidated,
4  * releasing the thread from the spin-loop.
5  */
6 
7 #include <assert.h>
8 #include <sys/mman.h>
9 #include <pthread.h>
10 #include <stdint.h>
11 #include <stdbool.h>
12 #include <unistd.h>
13 #include <sched.h>
14 
15 
16 #ifdef __x86_64__
17 #define READY   0x000047c6      /* movb $0,0(%rdi) */
18 #define LOOP    0xfceb9090      /* 1: nop*2; jmp 1b */
19 #define RETURN  0x909090c3      /* ret; nop*3 */
20 #define NOP     0x90909090      /* nop*4 */
21 #elif defined(__aarch64__)
22 #define READY   0x3900001f      /* strb wzr,[x0] */
23 #define LOOP    0x14000000      /* b . */
24 #define RETURN  0xd65f03c0      /* ret */
25 #define NOP     0xd503201f      /* nop */
26 #elif defined(__riscv)
27 #define READY   0x00050023      /* sb zero, (a0) */
28 #define LOOP    0x0000006f      /* jal zero, #0 */
29 #define RETURN  0x00008067      /* jalr zero, ra, 0 */
30 #define NOP     0x00000013      /* nop */
31 #endif
32 
33 
34 int main()
35 {
36 #ifdef READY
37     int tmp;
38     pthread_t thread_id;
39     bool hold = true;
40     uint32_t *buf;
41 
42     buf = mmap(NULL, 3 * sizeof(uint32_t),
43                PROT_READ | PROT_WRITE | PROT_EXEC,
44                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
45     assert(buf != MAP_FAILED);
46 
47     buf[0] = READY;
48     buf[1] = LOOP;
49     buf[2] = RETURN;
50 
51     alarm(2);
52 
53     tmp = pthread_create(&thread_id, NULL, (void *(*)(void *))buf, &hold);
54     assert(tmp == 0);
55 
56     while (hold) {
57         sched_yield();
58     }
59 
60     buf[1] = NOP;
61     __builtin___clear_cache(&buf[1], &buf[2]);
62 
63     tmp = pthread_join(thread_id, NULL);
64     assert(tmp == 0);
65 #endif
66     return 0;
67 }
68