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

seqlock.h (2043B)


      1/*
      2 * Seqlock implementation for QEMU
      3 *
      4 * Copyright Red Hat, Inc. 2013
      5 *
      6 * Author:
      7 *  Paolo Bonzini <pbonzini@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
     14#ifndef QEMU_SEQLOCK_H
     15#define QEMU_SEQLOCK_H
     16
     17#include "qemu/atomic.h"
     18#include "qemu/thread.h"
     19#include "qemu/lockable.h"
     20
     21typedef struct QemuSeqLock QemuSeqLock;
     22
     23struct QemuSeqLock {
     24    unsigned sequence;
     25};
     26
     27static inline void seqlock_init(QemuSeqLock *sl)
     28{
     29    sl->sequence = 0;
     30}
     31
     32/* Lock out other writers and update the count.  */
     33static inline void seqlock_write_begin(QemuSeqLock *sl)
     34{
     35    qatomic_set(&sl->sequence, sl->sequence + 1);
     36
     37    /* Write sequence before updating other fields.  */
     38    smp_wmb();
     39}
     40
     41static inline void seqlock_write_end(QemuSeqLock *sl)
     42{
     43    /* Write other fields before finalizing sequence.  */
     44    smp_wmb();
     45
     46    qatomic_set(&sl->sequence, sl->sequence + 1);
     47}
     48
     49/* Lock out other writers and update the count.  */
     50static inline void seqlock_write_lock_impl(QemuSeqLock *sl, QemuLockable *lock)
     51{
     52    qemu_lockable_lock(lock);
     53    seqlock_write_begin(sl);
     54}
     55#define seqlock_write_lock(sl, lock) \
     56    seqlock_write_lock_impl(sl, QEMU_MAKE_LOCKABLE(lock))
     57
     58/* Update the count and release the lock.  */
     59static inline void seqlock_write_unlock_impl(QemuSeqLock *sl, QemuLockable *lock)
     60{
     61    seqlock_write_end(sl);
     62    qemu_lockable_unlock(lock);
     63}
     64#define seqlock_write_unlock(sl, lock) \
     65    seqlock_write_unlock_impl(sl, QEMU_MAKE_LOCKABLE(lock))
     66
     67
     68static inline unsigned seqlock_read_begin(const QemuSeqLock *sl)
     69{
     70    /* Always fail if a write is in progress.  */
     71    unsigned ret = qatomic_read(&sl->sequence);
     72
     73    /* Read sequence before reading other fields.  */
     74    smp_rmb();
     75    return ret & ~1;
     76}
     77
     78static inline int seqlock_read_retry(const QemuSeqLock *sl, unsigned start)
     79{
     80    /* Read other fields before reading final sequence.  */
     81    smp_rmb();
     82    return unlikely(qatomic_read(&sl->sequence) != start);
     83}
     84
     85#endif