cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

futex.h (2655B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef _ASM_GENERIC_FUTEX_H
      3#define _ASM_GENERIC_FUTEX_H
      4
      5#include <linux/futex.h>
      6#include <linux/uaccess.h>
      7#include <asm/errno.h>
      8
      9#ifndef futex_atomic_cmpxchg_inatomic
     10#ifndef CONFIG_SMP
     11/*
     12 * The following implementation only for uniprocessor machines.
     13 * It relies on preempt_disable() ensuring mutual exclusion.
     14 *
     15 */
     16#define futex_atomic_cmpxchg_inatomic(uval, uaddr, oldval, newval) \
     17	futex_atomic_cmpxchg_inatomic_local(uval, uaddr, oldval, newval)
     18#define arch_futex_atomic_op_inuser(op, oparg, oval, uaddr) \
     19	futex_atomic_op_inuser_local(op, oparg, oval, uaddr)
     20#endif /* CONFIG_SMP */
     21#endif
     22
     23/**
     24 * futex_atomic_op_inuser_local() - Atomic arithmetic operation with constant
     25 *			  argument and comparison of the previous
     26 *			  futex value with another constant.
     27 *
     28 * @encoded_op:	encoded operation to execute
     29 * @uaddr:	pointer to user space address
     30 *
     31 * Return:
     32 * 0 - On success
     33 * -EFAULT - User access resulted in a page fault
     34 * -EAGAIN - Atomic operation was unable to complete due to contention
     35 * -ENOSYS - Operation not supported
     36 */
     37static inline int
     38futex_atomic_op_inuser_local(int op, u32 oparg, int *oval, u32 __user *uaddr)
     39{
     40	int oldval, ret;
     41	u32 tmp;
     42
     43	preempt_disable();
     44
     45	ret = -EFAULT;
     46	if (unlikely(get_user(oldval, uaddr) != 0))
     47		goto out_pagefault_enable;
     48
     49	ret = 0;
     50	tmp = oldval;
     51
     52	switch (op) {
     53	case FUTEX_OP_SET:
     54		tmp = oparg;
     55		break;
     56	case FUTEX_OP_ADD:
     57		tmp += oparg;
     58		break;
     59	case FUTEX_OP_OR:
     60		tmp |= oparg;
     61		break;
     62	case FUTEX_OP_ANDN:
     63		tmp &= ~oparg;
     64		break;
     65	case FUTEX_OP_XOR:
     66		tmp ^= oparg;
     67		break;
     68	default:
     69		ret = -ENOSYS;
     70	}
     71
     72	if (ret == 0 && unlikely(put_user(tmp, uaddr) != 0))
     73		ret = -EFAULT;
     74
     75out_pagefault_enable:
     76	preempt_enable();
     77
     78	if (ret == 0)
     79		*oval = oldval;
     80
     81	return ret;
     82}
     83
     84/**
     85 * futex_atomic_cmpxchg_inatomic_local() - Compare and exchange the content of the
     86 *				uaddr with newval if the current value is
     87 *				oldval.
     88 * @uval:	pointer to store content of @uaddr
     89 * @uaddr:	pointer to user space address
     90 * @oldval:	old value
     91 * @newval:	new value to store to @uaddr
     92 *
     93 * Return:
     94 * 0 - On success
     95 * -EFAULT - User access resulted in a page fault
     96 * -EAGAIN - Atomic operation was unable to complete due to contention
     97 */
     98static inline int
     99futex_atomic_cmpxchg_inatomic_local(u32 *uval, u32 __user *uaddr,
    100			      u32 oldval, u32 newval)
    101{
    102	u32 val;
    103
    104	preempt_disable();
    105	if (unlikely(get_user(val, uaddr) != 0)) {
    106		preempt_enable();
    107		return -EFAULT;
    108	}
    109
    110	if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) {
    111		preempt_enable();
    112		return -EFAULT;
    113	}
    114
    115	*uval = val;
    116	preempt_enable();
    117
    118	return 0;
    119}
    120
    121#endif