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.c (2482B)


      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/atomic.h"
      9#include "qemu/thread.h"
     10
     11#ifdef CONFIG_ATOMIC64
     12#error This file must only be compiled if !CONFIG_ATOMIC64
     13#endif
     14
     15/*
     16 * When !CONFIG_ATOMIC64, we serialize both reads and writes with spinlocks.
     17 * We use an array of spinlocks, with padding computed at run-time based on
     18 * the host's dcache line size.
     19 * We point to the array with a void * to simplify the padding's computation.
     20 * Each spinlock is located every lock_size bytes.
     21 */
     22static void *lock_array;
     23static size_t lock_size;
     24
     25/*
     26 * Systems without CONFIG_ATOMIC64 are unlikely to have many cores, so we use a
     27 * small array of locks.
     28 */
     29#define NR_LOCKS 16
     30
     31static QemuSpin *addr_to_lock(const void *addr)
     32{
     33    uintptr_t a = (uintptr_t)addr;
     34    uintptr_t idx;
     35
     36    idx = a >> qemu_dcache_linesize_log;
     37    idx ^= (idx >> 8) ^ (idx >> 16);
     38    idx &= NR_LOCKS - 1;
     39    return lock_array + idx * lock_size;
     40}
     41
     42#define GEN_READ(name, type)                    \
     43    type name(const type *ptr)                  \
     44    {                                           \
     45        QemuSpin *lock = addr_to_lock(ptr);     \
     46        type ret;                               \
     47                                                \
     48        qemu_spin_lock(lock);                   \
     49        ret = *ptr;                             \
     50        qemu_spin_unlock(lock);                 \
     51        return ret;                             \
     52    }
     53
     54GEN_READ(qatomic_read_i64, int64_t)
     55GEN_READ(qatomic_read_u64, uint64_t)
     56#undef GEN_READ
     57
     58#define GEN_SET(name, type)                     \
     59    void name(type *ptr, type val)              \
     60    {                                           \
     61        QemuSpin *lock = addr_to_lock(ptr);     \
     62                                                \
     63        qemu_spin_lock(lock);                   \
     64        *ptr = val;                             \
     65        qemu_spin_unlock(lock);                 \
     66    }
     67
     68GEN_SET(qatomic_set_i64, int64_t)
     69GEN_SET(qatomic_set_u64, uint64_t)
     70#undef GEN_SET
     71
     72void qatomic64_init(void)
     73{
     74    int i;
     75
     76    lock_size = ROUND_UP(sizeof(QemuSpin), qemu_dcache_linesize);
     77    lock_array = qemu_memalign(qemu_dcache_linesize, lock_size * NR_LOCKS);
     78    for (i = 0; i < NR_LOCKS; i++) {
     79        QemuSpin *lock = lock_array + i * lock_size;
     80
     81        qemu_spin_init(lock);
     82    }
     83}