qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

commpage.c (2265B)


      1 /*
      2  * Verify the COMMPAGE emulation
      3  *
      4  * The ARM commpage is a set of user space helper functions provided
      5  * by the kernel in an effort to ease portability of user space code
      6  * between different CPUs with potentially different capabilities. It
      7  * is a 32 bit invention and similar to the vdso segment in many ways.
      8  *
      9  * The ABI is documented in the Linux kernel:
     10  *     Documentation/arm/kernel_userspace_helpers.rst
     11  *
     12  * Copyright (c) 2020 Linaro Ltd
     13  *
     14  * SPDX-License-Identifier: GPL-2.0-or-later
     15  */
     16 
     17 #include <stdlib.h>
     18 #include <stdio.h>
     19 #include <stdint.h>
     20 
     21 #define ARM_COMMPAGE      (0xffff0f00u)
     22 #define ARM_KUSER_VERSION (*(int32_t *)(ARM_COMMPAGE + 0xfc))
     23 typedef void * (get_tls_fn)(void);
     24 #define ARM_KUSER_GET_TLS (*(get_tls_fn *)(ARM_COMMPAGE + 0xe0))
     25 typedef int (cmpxchg_fn)(int oldval, int newval, volatile int *ptr);
     26 #define ARM_KUSER_CMPXCHG (*(cmpxchg_fn *)(ARM_COMMPAGE + 0xc0))
     27 typedef void (dmb_fn)(void);
     28 #define ARM_KUSER_DMB (*(dmb_fn *)(ARM_COMMPAGE + 0xa0))
     29 typedef int (cmpxchg64_fn)(const int64_t *oldval,
     30                            const int64_t *newval,
     31                            volatile int64_t *ptr);
     32 #define ARM_KUSER_CMPXCHG64 (*(cmpxchg64_fn *)(ARM_COMMPAGE + 0x60))
     33 
     34 #define fail_unless(x)                                                  \
     35     do {                                                                \
     36         if (!(x)) {                                                     \
     37             fprintf(stderr, "FAILED at %s:%d\n", __FILE__, __LINE__);   \
     38             exit(EXIT_FAILURE);                                         \
     39         }                                                               \
     40     } while (0)
     41 
     42 
     43 int main(int argc, char *argv[argc])
     44 {
     45     void *kuser_tls;
     46     int val = 1;
     47     const int64_t oldval = 1, newval = 2;
     48     int64_t val64 = 1;
     49 
     50     fail_unless(ARM_KUSER_VERSION == 0x5);
     51     kuser_tls = ARM_KUSER_GET_TLS();
     52     printf("TLS = %p\n", kuser_tls);
     53     fail_unless(kuser_tls != 0);
     54     fail_unless(ARM_KUSER_CMPXCHG(1, 2, &val) == 0);
     55     printf("val = %d\n", val);
     56     /* this is a crash test, not checking an actual barrier occurs */
     57     ARM_KUSER_DMB();
     58     fail_unless(ARM_KUSER_CMPXCHG64(&oldval, &newval, &val64) == 0);
     59     printf("val64 = %lld\n", val64);
     60     return 0;
     61 }