]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blame - arch/parisc/include/asm/futex.h
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[mirror_ubuntu-kernels.git] / arch / parisc / include / asm / futex.h
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
342a0497
CD
2#ifndef _ASM_PARISC_FUTEX_H
3#define _ASM_PARISC_FUTEX_H
4732efbe 4
342a0497 5#ifdef __KERNEL__
4732efbe 6
342a0497 7#include <linux/futex.h>
730f412c 8#include <linux/uaccess.h>
d9ba5fe7 9#include <asm/atomic.h>
342a0497 10#include <asm/errno.h>
342a0497 11
8b232816
JDA
12/* The following has to match the LWS code in syscall.S. We have
13 sixteen four-word locks. */
14
15static inline void
16_futex_spin_lock_irqsave(u32 __user *uaddr, unsigned long int *flags)
17{
18 extern u32 lws_lock_start[];
19 long index = ((long)uaddr & 0xf0) >> 2;
20 arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
21 local_irq_save(*flags);
22 arch_spin_lock(s);
23}
24
25static inline void
26_futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags)
27{
28 extern u32 lws_lock_start[];
29 long index = ((long)uaddr & 0xf0) >> 2;
30 arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
31 arch_spin_unlock(s);
32 local_irq_restore(*flags);
33}
34
342a0497 35static inline int
30d6e0a4 36arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
342a0497 37{
d9ba5fe7 38 unsigned long int flags;
99aed91a
JDA
39 int oldval, ret;
40 u32 tmp;
41
99aed91a 42 _futex_spin_lock_irqsave(uaddr, &flags);
a866374a 43 pagefault_disable();
342a0497 44
99aed91a
JDA
45 ret = -EFAULT;
46 if (unlikely(get_user(oldval, uaddr) != 0))
47 goto out_pagefault_enable;
48
49 ret = 0;
50 tmp = oldval;
d9ba5fe7 51
342a0497
CD
52 switch (op) {
53 case FUTEX_OP_SET:
99aed91a 54 tmp = oparg;
d9ba5fe7 55 break;
342a0497 56 case FUTEX_OP_ADD:
99aed91a 57 tmp += oparg;
d9ba5fe7 58 break;
342a0497 59 case FUTEX_OP_OR:
99aed91a 60 tmp |= oparg;
d9ba5fe7 61 break;
342a0497 62 case FUTEX_OP_ANDN:
99aed91a 63 tmp &= ~oparg;
d9ba5fe7 64 break;
342a0497 65 case FUTEX_OP_XOR:
99aed91a 66 tmp ^= oparg;
d9ba5fe7 67 break;
342a0497
CD
68 default:
69 ret = -ENOSYS;
70 }
71
99aed91a
JDA
72 if (ret == 0 && unlikely(put_user(tmp, uaddr) != 0))
73 ret = -EFAULT;
d9ba5fe7 74
99aed91a 75out_pagefault_enable:
a866374a 76 pagefault_enable();
99aed91a 77 _futex_spin_unlock_irqrestore(uaddr, &flags);
342a0497 78
30d6e0a4
JS
79 if (!ret)
80 *oval = oldval;
81
342a0497
CD
82 return ret;
83}
84
342a0497 85static inline int
8d7718aa
ML
86futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
87 u32 oldval, u32 newval)
342a0497 88{
8d7718aa 89 u32 val;
d9ba5fe7 90 unsigned long flags;
342a0497 91
c20a84c9
KM
92 /* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
93 * our gateway page, and causes no end of trouble...
94 */
db68ce10 95 if (uaccess_kernel() && !uaddr)
c20a84c9
KM
96 return -EFAULT;
97
8d7718aa 98 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
342a0497
CD
99 return -EFAULT;
100
d9ba5fe7
CD
101 /* HPPA has no cmpxchg in hardware and therefore the
102 * best we can do here is use an array of locks. The
103 * lock selected is based on a hash of the userspace
104 * address. This should scale to a couple of CPUs.
105 */
106
8b232816 107 _futex_spin_lock_irqsave(uaddr, &flags);
99aed91a
JDA
108 if (unlikely(get_user(val, uaddr) != 0)) {
109 _futex_spin_unlock_irqrestore(uaddr, &flags);
110 return -EFAULT;
111 }
d9ba5fe7 112
99aed91a
JDA
113 if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) {
114 _futex_spin_unlock_irqrestore(uaddr, &flags);
115 return -EFAULT;
116 }
d9ba5fe7 117
37a9d912 118 *uval = val;
8b232816 119 _futex_spin_unlock_irqrestore(uaddr, &flags);
d9ba5fe7 120
99aed91a 121 return 0;
342a0497
CD
122}
123
c20a84c9
KM
124#endif /*__KERNEL__*/
125#endif /*_ASM_PARISC_FUTEX_H*/