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

atomic64-bench.c (3856B)


      1/*
      2 * Copyright (C) 2018, Emilio G. Cota <cota@braap.org>
      3 *
      4 * License: GNU GPL, version 2 or later.
      5 *   See the COPYING file in the top-level directory.
      6 */
      7#include "qemu/osdep.h"
      8#include "qemu/thread.h"
      9#include "qemu/host-utils.h"
     10#include "qemu/processor.h"
     11
     12struct thread_info {
     13    uint64_t r;
     14    uint64_t accesses;
     15} QEMU_ALIGNED(64);
     16
     17struct count {
     18    int64_t i64;
     19} QEMU_ALIGNED(64);
     20
     21static QemuThread *threads;
     22static struct thread_info *th_info;
     23static unsigned int n_threads = 1;
     24static unsigned int n_ready_threads;
     25static struct count *counts;
     26static unsigned int duration = 1;
     27static unsigned int range = 1024;
     28static bool test_start;
     29static bool test_stop;
     30
     31static const char commands_string[] =
     32    " -d = duration in seconds\n"
     33    " -n = number of threads\n"
     34    " -r = range (will be rounded up to pow2)";
     35
     36static void usage_complete(char *argv[])
     37{
     38    fprintf(stderr, "Usage: %s [options]\n", argv[0]);
     39    fprintf(stderr, "options:\n%s\n", commands_string);
     40}
     41
     42/*
     43 * From: https://en.wikipedia.org/wiki/Xorshift
     44 * This is faster than rand_r(), and gives us a wider range (RAND_MAX is only
     45 * guaranteed to be >= INT_MAX).
     46 */
     47static uint64_t xorshift64star(uint64_t x)
     48{
     49    x ^= x >> 12; /* a */
     50    x ^= x << 25; /* b */
     51    x ^= x >> 27; /* c */
     52    return x * UINT64_C(2685821657736338717);
     53}
     54
     55static void *thread_func(void *arg)
     56{
     57    struct thread_info *info = arg;
     58
     59    qatomic_inc(&n_ready_threads);
     60    while (!qatomic_read(&test_start)) {
     61        cpu_relax();
     62    }
     63
     64    while (!qatomic_read(&test_stop)) {
     65        unsigned int index;
     66
     67        info->r = xorshift64star(info->r);
     68        index = info->r & (range - 1);
     69        qatomic_read_i64(&counts[index].i64);
     70        info->accesses++;
     71    }
     72    return NULL;
     73}
     74
     75static void run_test(void)
     76{
     77    unsigned int i;
     78
     79    while (qatomic_read(&n_ready_threads) != n_threads) {
     80        cpu_relax();
     81    }
     82
     83    qatomic_set(&test_start, true);
     84    g_usleep(duration * G_USEC_PER_SEC);
     85    qatomic_set(&test_stop, true);
     86
     87    for (i = 0; i < n_threads; i++) {
     88        qemu_thread_join(&threads[i]);
     89    }
     90}
     91
     92static void create_threads(void)
     93{
     94    unsigned int i;
     95
     96    threads = g_new(QemuThread, n_threads);
     97    th_info = g_new(struct thread_info, n_threads);
     98    counts = g_malloc0_n(range, sizeof(*counts));
     99
    100    for (i = 0; i < n_threads; i++) {
    101        struct thread_info *info = &th_info[i];
    102
    103        info->r = (i + 1) ^ time(NULL);
    104        info->accesses = 0;
    105        qemu_thread_create(&threads[i], NULL, thread_func, info,
    106                           QEMU_THREAD_JOINABLE);
    107    }
    108}
    109
    110static void pr_params(void)
    111{
    112    printf("Parameters:\n");
    113    printf(" # of threads:      %u\n", n_threads);
    114    printf(" duration:          %u\n", duration);
    115    printf(" ops' range:        %u\n", range);
    116}
    117
    118static void pr_stats(void)
    119{
    120    unsigned long long val = 0;
    121    double tx;
    122    int i;
    123
    124    for (i = 0; i < n_threads; i++) {
    125        val += th_info[i].accesses;
    126    }
    127    tx = val / duration / 1e6;
    128
    129    printf("Results:\n");
    130    printf("Duration:            %u s\n", duration);
    131    printf(" Throughput:         %.2f Mops/s\n", tx);
    132    printf(" Throughput/thread:  %.2f Mops/s/thread\n", tx / n_threads);
    133}
    134
    135static void parse_args(int argc, char *argv[])
    136{
    137    int c;
    138
    139    for (;;) {
    140        c = getopt(argc, argv, "hd:n:r:");
    141        if (c < 0) {
    142            break;
    143        }
    144        switch (c) {
    145        case 'h':
    146            usage_complete(argv);
    147            exit(0);
    148        case 'd':
    149            duration = atoi(optarg);
    150            break;
    151        case 'n':
    152            n_threads = atoi(optarg);
    153            break;
    154        case 'r':
    155            range = pow2ceil(atoi(optarg));
    156            break;
    157        }
    158    }
    159}
    160
    161int main(int argc, char *argv[])
    162{
    163    parse_args(argc, argv);
    164    pr_params();
    165    create_threads();
    166    run_test();
    167    pr_stats();
    168    return 0;
    169}