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

main.c (7929B)


      1/*
      2 * Copyright 6WIND S.A., 2014
      3 *
      4 * This work is licensed under the terms of the GNU GPL, version 2 or
      5 * (at your option) any later version.  See the COPYING file in the
      6 * top-level directory.
      7 */
      8
      9#include "qemu/osdep.h"
     10#include "qapi/error.h"
     11#include "qemu/cutils.h"
     12#include "qemu/option.h"
     13#include "ivshmem-server.h"
     14
     15#define IVSHMEM_SERVER_DEFAULT_VERBOSE        0
     16#define IVSHMEM_SERVER_DEFAULT_FOREGROUND     0
     17#define IVSHMEM_SERVER_DEFAULT_PID_FILE       "/var/run/ivshmem-server.pid"
     18#define IVSHMEM_SERVER_DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
     19#define IVSHMEM_SERVER_DEFAULT_SHM_PATH       "ivshmem"
     20#define IVSHMEM_SERVER_DEFAULT_SHM_SIZE       (4 * 1024 * 1024)
     21#define IVSHMEM_SERVER_DEFAULT_N_VECTORS      1
     22
     23/* used to quit on signal SIGTERM */
     24static int ivshmem_server_quit;
     25
     26/* arguments given by the user */
     27typedef struct IvshmemServerArgs {
     28    bool verbose;
     29    bool foreground;
     30    const char *pid_file;
     31    const char *unix_socket_path;
     32    const char *shm_path;
     33    bool use_shm_open;
     34    uint64_t shm_size;
     35    unsigned n_vectors;
     36} IvshmemServerArgs;
     37
     38static void
     39ivshmem_server_usage(const char *progname)
     40{
     41    printf("Usage: %s [OPTION]...\n"
     42           "  -h: show this help\n"
     43           "  -v: verbose mode\n"
     44           "  -F: foreground mode (default is to daemonize)\n"
     45           "  -p <pid-file>: path to the PID file (used in daemon mode only)\n"
     46           "     default " IVSHMEM_SERVER_DEFAULT_PID_FILE "\n"
     47           "  -S <unix-socket-path>: path to the unix socket to listen to\n"
     48           "     default " IVSHMEM_SERVER_DEFAULT_UNIX_SOCK_PATH "\n"
     49           "  -M <shm-name>: POSIX shared memory object to use\n"
     50           "     default " IVSHMEM_SERVER_DEFAULT_SHM_PATH "\n"
     51           "  -m <dir-name>: where to create shared memory\n"
     52           "  -l <size>: size of shared memory in bytes\n"
     53           "     suffixes K, M and G can be used, e.g. 1K means 1024\n"
     54           "     default %u\n"
     55           "  -n <nvectors>: number of vectors\n"
     56           "     default %u\n",
     57           progname, IVSHMEM_SERVER_DEFAULT_SHM_SIZE,
     58           IVSHMEM_SERVER_DEFAULT_N_VECTORS);
     59}
     60
     61static void
     62ivshmem_server_help(const char *progname)
     63{
     64    fprintf(stderr, "Try '%s -h' for more information.\n", progname);
     65}
     66
     67/* parse the program arguments, exit on error */
     68static void
     69ivshmem_server_parse_args(IvshmemServerArgs *args, int argc, char *argv[])
     70{
     71    int c;
     72    unsigned long long v;
     73    Error *err = NULL;
     74
     75    while ((c = getopt(argc, argv, "hvFp:S:m:M:l:n:")) != -1) {
     76
     77        switch (c) {
     78        case 'h': /* help */
     79            ivshmem_server_usage(argv[0]);
     80            exit(0);
     81            break;
     82
     83        case 'v': /* verbose */
     84            args->verbose = 1;
     85            break;
     86
     87        case 'F': /* foreground */
     88            args->foreground = 1;
     89            break;
     90
     91        case 'p': /* pid file */
     92            args->pid_file = optarg;
     93            break;
     94
     95        case 'S': /* unix socket path */
     96            args->unix_socket_path = optarg;
     97            break;
     98
     99        case 'M': /* shm name */
    100        case 'm': /* dir name */
    101            args->shm_path = optarg;
    102            args->use_shm_open = c == 'M';
    103            break;
    104
    105        case 'l': /* shm size */
    106            if (!parse_option_size("shm_size", optarg, &args->shm_size,
    107                                   &err)) {
    108                error_report_err(err);
    109                ivshmem_server_help(argv[0]);
    110                exit(1);
    111            }
    112            break;
    113
    114        case 'n': /* number of vectors */
    115            if (parse_uint_full(optarg, &v, 0) < 0) {
    116                fprintf(stderr, "cannot parse n_vectors\n");
    117                ivshmem_server_help(argv[0]);
    118                exit(1);
    119            }
    120            args->n_vectors = v;
    121            break;
    122
    123        default:
    124            ivshmem_server_usage(argv[0]);
    125            exit(1);
    126            break;
    127        }
    128    }
    129
    130    if (args->n_vectors > IVSHMEM_SERVER_MAX_VECTORS) {
    131        fprintf(stderr, "too many requested vectors (max is %d)\n",
    132                IVSHMEM_SERVER_MAX_VECTORS);
    133        ivshmem_server_help(argv[0]);
    134        exit(1);
    135    }
    136
    137    if (args->verbose == 1 && args->foreground == 0) {
    138        fprintf(stderr, "cannot use verbose in daemon mode\n");
    139        ivshmem_server_help(argv[0]);
    140        exit(1);
    141    }
    142}
    143
    144/* wait for events on listening server unix socket and connected client
    145 * sockets */
    146static int
    147ivshmem_server_poll_events(IvshmemServer *server)
    148{
    149    fd_set fds;
    150    int ret = 0, maxfd;
    151
    152    while (!ivshmem_server_quit) {
    153
    154        FD_ZERO(&fds);
    155        maxfd = 0;
    156        ivshmem_server_get_fds(server, &fds, &maxfd);
    157
    158        ret = select(maxfd, &fds, NULL, NULL, NULL);
    159
    160        if (ret < 0) {
    161            if (errno == EINTR) {
    162                continue;
    163            }
    164
    165            fprintf(stderr, "select error: %s\n", strerror(errno));
    166            break;
    167        }
    168        if (ret == 0) {
    169            continue;
    170        }
    171
    172        if (ivshmem_server_handle_fds(server, &fds, maxfd) < 0) {
    173            fprintf(stderr, "ivshmem_server_handle_fds() failed\n");
    174            break;
    175        }
    176    }
    177
    178    return ret;
    179}
    180
    181static void
    182ivshmem_server_quit_cb(int signum)
    183{
    184    ivshmem_server_quit = 1;
    185}
    186
    187int
    188main(int argc, char *argv[])
    189{
    190    IvshmemServer server;
    191    struct sigaction sa, sa_quit;
    192    IvshmemServerArgs args = {
    193        .verbose = IVSHMEM_SERVER_DEFAULT_VERBOSE,
    194        .foreground = IVSHMEM_SERVER_DEFAULT_FOREGROUND,
    195        .pid_file = IVSHMEM_SERVER_DEFAULT_PID_FILE,
    196        .unix_socket_path = IVSHMEM_SERVER_DEFAULT_UNIX_SOCK_PATH,
    197        .shm_path = IVSHMEM_SERVER_DEFAULT_SHM_PATH,
    198        .use_shm_open = true,
    199        .shm_size = IVSHMEM_SERVER_DEFAULT_SHM_SIZE,
    200        .n_vectors = IVSHMEM_SERVER_DEFAULT_N_VECTORS,
    201    };
    202    int ret = 1;
    203
    204    /*
    205     * Do not remove this notice without adding proper error handling!
    206     * Start with handling ivshmem_server_send_one_msg() failure.
    207     */
    208    printf("*** Example code, do not use in production ***\n");
    209
    210    /* parse arguments, will exit on error */
    211    ivshmem_server_parse_args(&args, argc, argv);
    212
    213    /* Ignore SIGPIPE, see this link for more info:
    214     * http://www.mail-archive.com/libevent-users@monkey.org/msg01606.html */
    215    sa.sa_handler = SIG_IGN;
    216    sa.sa_flags = 0;
    217    if (sigemptyset(&sa.sa_mask) == -1 ||
    218        sigaction(SIGPIPE, &sa, 0) == -1) {
    219        perror("failed to ignore SIGPIPE; sigaction");
    220        goto err;
    221    }
    222
    223    sa_quit.sa_handler = ivshmem_server_quit_cb;
    224    sa_quit.sa_flags = 0;
    225    if (sigemptyset(&sa_quit.sa_mask) == -1 ||
    226        sigaction(SIGTERM, &sa_quit, 0) == -1 ||
    227        sigaction(SIGINT, &sa_quit, 0) == -1) {
    228        perror("failed to add signal handler; sigaction");
    229        goto err;
    230    }
    231
    232    /* init the ivshms structure */
    233    if (ivshmem_server_init(&server, args.unix_socket_path,
    234                            args.shm_path, args.use_shm_open,
    235                            args.shm_size, args.n_vectors, args.verbose) < 0) {
    236        fprintf(stderr, "cannot init server\n");
    237        goto err;
    238    }
    239
    240    /* start the ivshmem server (open shm & unix socket) */
    241    if (ivshmem_server_start(&server) < 0) {
    242        fprintf(stderr, "cannot bind\n");
    243        goto err;
    244    }
    245
    246    /* daemonize if asked to */
    247    if (!args.foreground) {
    248        FILE *fp;
    249
    250        if (qemu_daemon(1, 1) < 0) {
    251            fprintf(stderr, "cannot daemonize: %s\n", strerror(errno));
    252            goto err_close;
    253        }
    254
    255        /* write pid file */
    256        fp = fopen(args.pid_file, "w");
    257        if (fp == NULL) {
    258            fprintf(stderr, "cannot write pid file: %s\n", strerror(errno));
    259            goto err_close;
    260        }
    261
    262        fprintf(fp, "%d\n", (int) getpid());
    263        fclose(fp);
    264    }
    265
    266    ivshmem_server_poll_events(&server);
    267    fprintf(stdout, "server disconnected\n");
    268    ret = 0;
    269
    270err_close:
    271    ivshmem_server_close(&server);
    272err:
    273    return ret;
    274}