cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

compatfd.c (2304B)


      1/*
      2 * signalfd/eventfd compatibility
      3 *
      4 * Copyright IBM, Corp. 2008
      5 *
      6 * Authors:
      7 *  Anthony Liguori   <aliguori@us.ibm.com>
      8 *
      9 * This work is licensed under the terms of the GNU GPL, version 2.  See
     10 * the COPYING file in the top-level directory.
     11 *
     12 * Contributions after 2012-01-13 are licensed under the terms of the
     13 * GNU GPL, version 2 or (at your option) any later version.
     14 */
     15
     16#include "qemu/osdep.h"
     17#include "qemu/thread.h"
     18
     19#if defined(CONFIG_SIGNALFD)
     20#include <sys/syscall.h>
     21#endif
     22
     23struct sigfd_compat_info {
     24    sigset_t mask;
     25    int fd;
     26};
     27
     28static void *sigwait_compat(void *opaque)
     29{
     30    struct sigfd_compat_info *info = opaque;
     31
     32    while (1) {
     33        int sig;
     34        int err;
     35
     36        err = sigwait(&info->mask, &sig);
     37        if (err != 0) {
     38            if (errno == EINTR) {
     39                continue;
     40            } else {
     41                return NULL;
     42            }
     43        } else {
     44            struct qemu_signalfd_siginfo buffer;
     45            size_t offset = 0;
     46
     47            memset(&buffer, 0, sizeof(buffer));
     48            buffer.ssi_signo = sig;
     49
     50            while (offset < sizeof(buffer)) {
     51                ssize_t len;
     52
     53                len = write(info->fd, (char *)&buffer + offset,
     54                            sizeof(buffer) - offset);
     55                if (len == -1 && errno == EINTR) {
     56                    continue;
     57                }
     58
     59                if (len <= 0) {
     60                    return NULL;
     61                }
     62
     63                offset += len;
     64            }
     65        }
     66    }
     67}
     68
     69static int qemu_signalfd_compat(const sigset_t *mask)
     70{
     71    struct sigfd_compat_info *info;
     72    QemuThread thread;
     73    int fds[2];
     74
     75    info = g_malloc(sizeof(*info));
     76
     77    if (pipe(fds) == -1) {
     78        g_free(info);
     79        return -1;
     80    }
     81
     82    qemu_set_cloexec(fds[0]);
     83    qemu_set_cloexec(fds[1]);
     84
     85    memcpy(&info->mask, mask, sizeof(*mask));
     86    info->fd = fds[1];
     87
     88    qemu_thread_create(&thread, "signalfd_compat", sigwait_compat, info,
     89                       QEMU_THREAD_DETACHED);
     90
     91    return fds[0];
     92}
     93
     94int qemu_signalfd(const sigset_t *mask)
     95{
     96#if defined(CONFIG_SIGNALFD)
     97    int ret;
     98
     99    ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8);
    100    if (ret != -1) {
    101        qemu_set_cloexec(ret);
    102        return ret;
    103    }
    104#endif
    105
    106    return qemu_signalfd_compat(mask);
    107}