xref: /openbmc/qemu/tests/tcg/i386/test-flags.c (revision effd60c8)
1 #define _GNU_SOURCE
2 #include <sys/mman.h>
3 #include <signal.h>
4 #include <stdio.h>
5 #include <assert.h>
6 
7 volatile unsigned long flags;
8 volatile unsigned long flags_after;
9 int *addr;
10 
11 void sigsegv(int sig, siginfo_t *info, ucontext_t *uc)
12 {
13     flags = uc->uc_mcontext.gregs[REG_EFL];
14     mprotect(addr, 4096, PROT_READ|PROT_WRITE);
15 }
16 
17 int main()
18 {
19     struct sigaction sa = { .sa_handler = (void *)sigsegv, .sa_flags = SA_SIGINFO };
20     sigaction(SIGSEGV, &sa, NULL);
21 
22     /* fault in the page then protect it */
23     addr = mmap (NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
24     *addr = 0x1234;
25     mprotect(addr, 4096, PROT_READ);
26 
27     asm("# set flags to all ones    \n"
28         "mov $-1, %%eax             \n"
29         "movq addr, %%rdi           \n"
30         "sahf                       \n"
31         "sub %%eax, (%%rdi)         \n"
32         "pushf                      \n"
33         "pop  flags_after(%%rip)    \n" : : : "eax", "edi", "memory");
34 
35     /* OF can have any value before the SUB instruction.  */
36     assert((flags & 0xff) == 0xd7 && (flags_after & 0x8ff) == 0x17);
37 }
38