parisc: Don't disable interrupts in cmpxchg and futex operations
authorDave Anglin <dave.anglin@bell.net>
Wed, 3 Nov 2021 11:49:32 +0000 (12:49 +0100)
committerHelge Deller <deller@gmx.de>
Thu, 4 Nov 2021 10:21:20 +0000 (11:21 +0100)
I no longer think interrupts can be disabled in the futex and cmpxchg
operations because of COW breaks.  This not ideal but I suspect it's the
best we can do.

For the cmpxchg operations in syscall.S, we rely on the code to not
schedule off the gateway page.  For the futex, I added code to disable
preemption.

So far, I haven't seen the warnings with the attached change but the
change is only lightly tested.

Signed-off-by: Dave Anglin <dave.anglin@bell.net>
Signed-off-by: Helge Deller <deller@gmx.de>
arch/parisc/include/asm/futex.h
arch/parisc/kernel/syscall.S

index e38a118..70cf8f0 100644 (file)
    sixteen four-word locks. */
 
 static inline void
-_futex_spin_lock_irqsave(u32 __user *uaddr, unsigned long int *flags)
+_futex_spin_lock(u32 __user *uaddr)
 {
        extern u32 lws_lock_start[];
        long index = ((long)uaddr & 0x3f8) >> 1;
        arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
-       local_irq_save(*flags);
+       preempt_disable();
        arch_spin_lock(s);
 }
 
 static inline void
-_futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags)
+_futex_spin_unlock(u32 __user *uaddr)
 {
        extern u32 lws_lock_start[];
        long index = ((long)uaddr & 0x3f8) >> 1;
        arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
        arch_spin_unlock(s);
-       local_irq_restore(*flags);
+       preempt_enable();
 }
 
 static inline int
 arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
 {
-       unsigned long int flags;
        int oldval, ret;
        u32 tmp;
 
-       _futex_spin_lock_irqsave(uaddr, &flags);
-
        ret = -EFAULT;
+
+       _futex_spin_lock(uaddr);
        if (unlikely(get_user(oldval, uaddr) != 0))
                goto out_pagefault_enable;
 
@@ -70,7 +69,7 @@ arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
                ret = -EFAULT;
 
 out_pagefault_enable:
-       _futex_spin_unlock_irqrestore(uaddr, &flags);
+       _futex_spin_unlock(uaddr);
 
        if (!ret)
                *oval = oldval;
@@ -83,7 +82,6 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                              u32 oldval, u32 newval)
 {
        u32 val;
-       unsigned long flags;
 
        /* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
         * our gateway page, and causes no end of trouble...
@@ -100,19 +98,19 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
         * address. This should scale to a couple of CPUs.
         */
 
-       _futex_spin_lock_irqsave(uaddr, &flags);
+       _futex_spin_lock(uaddr);
        if (unlikely(get_user(val, uaddr) != 0)) {
-               _futex_spin_unlock_irqrestore(uaddr, &flags);
+               _futex_spin_unlock(uaddr);
                return -EFAULT;
        }
 
        if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) {
-               _futex_spin_unlock_irqrestore(uaddr, &flags);
+               _futex_spin_unlock(uaddr);
                return -EFAULT;
        }
 
        *uval = val;
-       _futex_spin_unlock_irqrestore(uaddr, &flags);
+       _futex_spin_unlock(uaddr);
 
        return 0;
 }
index ec9675f..4fb3b6a 100644 (file)
@@ -597,13 +597,11 @@ cas_nocontend:
 # endif
 /* ENABLE_LWS_DEBUG */
 
-       rsm     PSW_SM_I, %r0                           /* Disable interrupts */
        /* COW breaks can cause contention on UP systems */
        LDCW    0(%sr2,%r20), %r28                      /* Try to acquire the lock */
        cmpb,<>,n       %r0, %r28, cas_action           /* Did we get it? */
 cas_wouldblock:
        ldo     2(%r0), %r28                            /* 2nd case */
-       ssm     PSW_SM_I, %r0
        b       lws_exit                                /* Contended... */
        ldo     -EAGAIN(%r0), %r21                      /* Spin in userspace */
 
@@ -639,8 +637,6 @@ cas_action:
        /* Clear thread register indicator */
        stw     %r0, 4(%sr2,%r20)
 #endif
-       /* Enable interrupts */
-       ssm     PSW_SM_I, %r0
        /* Return to userspace, set no error */
        b       lws_exit
        copy    %r0, %r21
@@ -652,7 +648,6 @@ cas_action:
 #if ENABLE_LWS_DEBUG
        stw     %r0, 4(%sr2,%r20)
 #endif
-       ssm     PSW_SM_I, %r0
        b       lws_exit
        ldo     -EFAULT(%r0),%r21       /* set errno */
        nop
@@ -764,13 +759,11 @@ cas2_lock_start:
        shlw    %r20, 4, %r20
        add     %r20, %r28, %r20
 
-       rsm     PSW_SM_I, %r0                   /* Disable interrupts */
        /* COW breaks can cause contention on UP systems */
        LDCW    0(%sr2,%r20), %r28              /* Try to acquire the lock */
        cmpb,<>,n       %r0, %r28, cas2_action  /* Did we get it? */
 cas2_wouldblock:
        ldo     2(%r0), %r28                    /* 2nd case */
-       ssm     PSW_SM_I, %r0
        b       lws_exit                        /* Contended... */
        ldo     -EAGAIN(%r0), %r21              /* Spin in userspace */
 
@@ -850,8 +843,6 @@ cas2_action:
 cas2_end:
        /* Free lock */
        stw,ma  %r20, 0(%sr2,%r20)
-       /* Enable interrupts */
-       ssm     PSW_SM_I, %r0
        /* Return to userspace, set no error */
        b       lws_exit
        copy    %r0, %r21
@@ -860,7 +851,6 @@ cas2_end:
        /* Error occurred on load or store */
        /* Free lock */
        stw,ma  %r20, 0(%sr2,%r20)
-       ssm     PSW_SM_I, %r0
        ldo     1(%r0),%r28
        b       lws_exit
        ldo     -EFAULT(%r0),%r21       /* set errno */