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

event_notifier-posix.c (2742B)


      1/*
      2 * event notifier support
      3 *
      4 * Copyright Red Hat, Inc. 2010
      5 *
      6 * Authors:
      7 *  Michael S. Tsirkin <mst@redhat.com>
      8 *
      9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
     10 * See the COPYING file in the top-level directory.
     11 */
     12
     13#include "qemu/osdep.h"
     14#include "qemu-common.h"
     15#include "qemu/cutils.h"
     16#include "qemu/event_notifier.h"
     17#include "qemu/main-loop.h"
     18
     19#ifdef CONFIG_EVENTFD
     20#include <sys/eventfd.h>
     21#endif
     22
     23#ifdef CONFIG_EVENTFD
     24/*
     25 * Initialize @e with existing file descriptor @fd.
     26 * @fd must be a genuine eventfd object, emulation with pipe won't do.
     27 */
     28void event_notifier_init_fd(EventNotifier *e, int fd)
     29{
     30    e->rfd = fd;
     31    e->wfd = fd;
     32    e->initialized = true;
     33}
     34#endif
     35
     36int event_notifier_init(EventNotifier *e, int active)
     37{
     38    int fds[2];
     39    int ret;
     40
     41#ifdef CONFIG_EVENTFD
     42    ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
     43#else
     44    ret = -1;
     45    errno = ENOSYS;
     46#endif
     47    if (ret >= 0) {
     48        e->rfd = e->wfd = ret;
     49    } else {
     50        if (errno != ENOSYS) {
     51            return -errno;
     52        }
     53        if (qemu_pipe(fds) < 0) {
     54            return -errno;
     55        }
     56        ret = fcntl_setfl(fds[0], O_NONBLOCK);
     57        if (ret < 0) {
     58            ret = -errno;
     59            goto fail;
     60        }
     61        ret = fcntl_setfl(fds[1], O_NONBLOCK);
     62        if (ret < 0) {
     63            ret = -errno;
     64            goto fail;
     65        }
     66        e->rfd = fds[0];
     67        e->wfd = fds[1];
     68    }
     69    e->initialized = true;
     70    if (active) {
     71        event_notifier_set(e);
     72    }
     73    return 0;
     74
     75fail:
     76    close(fds[0]);
     77    close(fds[1]);
     78    return ret;
     79}
     80
     81void event_notifier_cleanup(EventNotifier *e)
     82{
     83    if (!e->initialized) {
     84        return;
     85    }
     86
     87    if (e->rfd != e->wfd) {
     88        close(e->rfd);
     89    }
     90
     91    e->rfd = -1;
     92    close(e->wfd);
     93    e->wfd = -1;
     94    e->initialized = false;
     95}
     96
     97int event_notifier_get_fd(const EventNotifier *e)
     98{
     99    return e->rfd;
    100}
    101
    102int event_notifier_set(EventNotifier *e)
    103{
    104    static const uint64_t value = 1;
    105    ssize_t ret;
    106
    107    if (!e->initialized) {
    108        return -1;
    109    }
    110
    111    do {
    112        ret = write(e->wfd, &value, sizeof(value));
    113    } while (ret < 0 && errno == EINTR);
    114
    115    /* EAGAIN is fine, a read must be pending.  */
    116    if (ret < 0 && errno != EAGAIN) {
    117        return -errno;
    118    }
    119    return 0;
    120}
    121
    122int event_notifier_test_and_clear(EventNotifier *e)
    123{
    124    int value;
    125    ssize_t len;
    126    char buffer[512];
    127
    128    if (!e->initialized) {
    129        return 0;
    130    }
    131
    132    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
    133    value = 0;
    134    do {
    135        len = read(e->rfd, buffer, sizeof(buffer));
    136        value |= (len > 0);
    137    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
    138
    139    return value;
    140}