get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/805294/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 805294,
    "url": "http://patchwork.ozlabs.org/api/patches/805294/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20170824073105.3901-1-jslaby@suse.cz/",
    "project": {
        "id": 2,
        "url": "http://patchwork.ozlabs.org/api/projects/2/?format=api",
        "name": "Linux PPC development",
        "link_name": "linuxppc-dev",
        "list_id": "linuxppc-dev.lists.ozlabs.org",
        "list_email": "linuxppc-dev@lists.ozlabs.org",
        "web_url": "https://github.com/linuxppc/wiki/wiki",
        "scm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git",
        "webscm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/",
        "list_archive_url": "https://lore.kernel.org/linuxppc-dev/",
        "list_archive_url_format": "https://lore.kernel.org/linuxppc-dev/{}/",
        "commit_url_format": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/commit/?id={}"
    },
    "msgid": "<20170824073105.3901-1-jslaby@suse.cz>",
    "list_archive_url": "https://lore.kernel.org/linuxppc-dev/20170824073105.3901-1-jslaby@suse.cz/",
    "date": "2017-08-24T07:31:05",
    "name": "[v2,1/1] futex: remove duplicated code and fix UB",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": false,
    "hash": "3cd76a33d2464f3ba10d4b113f34348fe55d5040",
    "submitter": {
        "id": 1920,
        "url": "http://patchwork.ozlabs.org/api/people/1920/?format=api",
        "name": "Jiri Slaby",
        "email": "jslaby@suse.cz"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20170824073105.3901-1-jslaby@suse.cz/mbox/",
    "series": [],
    "comments": "http://patchwork.ozlabs.org/api/patches/805294/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/805294/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org>",
        "X-Original-To": [
            "patchwork-incoming@ozlabs.org",
            "linuxppc-dev@lists.ozlabs.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@ozlabs.org",
            "linuxppc-dev@lists.ozlabs.org"
        ],
        "Received": [
            "from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68])\n\t(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xdGW35HDpz9sRm\n\tfor <patchwork-incoming@ozlabs.org>;\n\tThu, 24 Aug 2017 17:43:27 +1000 (AEST)",
            "from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3xdGW34K4mzDrbG\n\tfor <patchwork-incoming@ozlabs.org>;\n\tThu, 24 Aug 2017 17:43:27 +1000 (AEST)",
            "from mx1.suse.de (mx2.suse.de [195.135.220.15])\n\t(using TLSv1 with cipher ADH-CAMELLIA256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 3xdGF13pzFzDql8\n\tfor <linuxppc-dev@lists.ozlabs.org>;\n\tThu, 24 Aug 2017 17:31:17 +1000 (AEST)",
            "from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254])\n\tby mx1.suse.de (Postfix) with ESMTP id 1D523AD40;\n\tThu, 24 Aug 2017 07:31:13 +0000 (UTC)"
        ],
        "X-Virus-Scanned": "by amavisd-new at test-mx.suse.de",
        "From": "Jiri Slaby <jslaby@suse.cz>",
        "To": "tglx@linutronix.de",
        "Subject": "[PATCH v2 1/1] futex: remove duplicated code and fix UB",
        "Date": "Thu, 24 Aug 2017 09:31:05 +0200",
        "Message-Id": "<20170824073105.3901-1-jslaby@suse.cz>",
        "X-Mailer": "git-send-email 2.14.1",
        "X-BeenThere": "linuxppc-dev@lists.ozlabs.org",
        "X-Mailman-Version": "2.1.23",
        "Precedence": "list",
        "List-Id": "Linux on PowerPC Developers Mail List\n\t<linuxppc-dev.lists.ozlabs.org>",
        "List-Unsubscribe": "<https://lists.ozlabs.org/options/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.ozlabs.org/pipermail/linuxppc-dev/>",
        "List-Post": "<mailto:linuxppc-dev@lists.ozlabs.org>",
        "List-Help": "<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=help>",
        "List-Subscribe": "<https://lists.ozlabs.org/listinfo/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@lists.ozlabs.org?subject=subscribe>",
        "Cc": "linux-mips@linux-mips.org, Rich Felker <dalias@libc.org>,\n\tlinux-ia64@vger.kernel.org, linux-sh@vger.kernel.org,\n\tpeterz@infradead.org, \n\tWill Deacon <will.deacon@arm.com>, Max Filippov <jcmvbkbc@gmail.com>, \n\tPaul Mackerras <paulus@samba.org>, \"H. Peter Anvin\" <hpa@zytor.com>, \n\tsparclinux@vger.kernel.org, Jiri Slaby <jslaby@suse.cz>,\n\tJonas Bonn <jonas@southpole.se>, linux-s390@vger.kernel.org,\n\tlinux-arch@vger.kernel.org, Yoshinori Sato <ysato@users.sourceforge.jp>, \n\tlinux-hexagon@vger.kernel.org, Helge Deller <deller@gmx.de>,\n\tx86@kernel.org, \n\t\"James E.J. Bottomley\" <jejb@parisc-linux.org>, mingo@redhat.com,\n\tCatalin Marinas <catalin.marinas@arm.com>, dvhart@infradead.org,\n\tMatt Turner <mattst88@gmail.com>, linux-snps-arc@lists.infradead.org, \n\tFenghua Yu <fenghua.yu@intel.com>, Arnd Bergmann <arnd@arndb.de>,\n\tlinux-xtensa@linux-xtensa.org,\n\tStefan Kristiansson <stefan.kristiansson@saunalahti.fi>,\n\topenrisc@lists.librecores.org,\n\tIvan Kokshaysky <ink@jurassic.park.msu.ru>, \n\tStafford Horne <shorne@gmail.com>, linux-arm-kernel@lists.infradead.org, \n\tRichard Henderson <rth@twiddle.net>, Chris Zankel <chris@zankel.net>, \n\tMichal Simek <monstr@monstr.eu>, Tony Luck <tony.luck@intel.com>,\n\tlinux-parisc@vger.kernel.org, Vineet Gupta <vgupta@synopsys.com>,\n\tlinux-kernel@vger.kernel.org, Ralf Baechle <ralf@linux-mips.org>,\n\tRichard Kuo <rkuo@codeaurora.org>, linux-alpha@vger.kernel.org,\n\tMartin Schwidefsky <schwidefsky@de.ibm.com>,\n\tlinuxppc-dev@lists.ozlabs.org, \"David S. Miller\" <davem@davemloft.net>",
        "Errors-To": "linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org",
        "Sender": "\"Linuxppc-dev\"\n\t<linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org>"
    },
    "content": "There is code duplicated over all architecture's headers for\nfutex_atomic_op_inuser. Namely op decoding, access_ok check for uaddr,\nand comparison of the result.\n\nRemove this duplication and leave up to the arches only the needed\nassembly which is now in arch_futex_atomic_op_inuser.\n\nThis effectively distributes the Will Deacon's arm64 fix for undefined\nbehaviour reported by UBSAN to all architectures. The fix was done in\ncommit 5f16a046f8e1 (arm64: futex: Fix undefined behaviour with\nFUTEX_OP_OPARG_SHIFT usage). Look there for an example dump.\n\nAnd as suggested by Thomas, check for negative oparg too, because it was\nalso reported to cause undefined behaviour report.\n\nNote that s390 removed access_ok check in d12a29703 (\"s390/uaccess:\nremove pointless access_ok() checks\") as access_ok there returns true.\nWe introduce it back to the helper for the sake of simplicity (it gets\noptimized away anyway).\n\n[v2]\n- check also for negative values\n- wait for Will's fix to be in upstream\n\nSigned-off-by: Jiri Slaby <jslaby@suse.cz>\nCc: Richard Henderson <rth@twiddle.net>\nCc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>\nCc: Matt Turner <mattst88@gmail.com>\nCc: Vineet Gupta <vgupta@synopsys.com>\nAcked-by: Russell King <rmk+kernel@armlinux.org.uk>\nCc: Catalin Marinas <catalin.marinas@arm.com>\nCc: Will Deacon <will.deacon@arm.com>\nReviewed-by: Darren Hart (VMware) <dvhart@infradead.org>\nCc: Richard Kuo <rkuo@codeaurora.org>\nCc: Tony Luck <tony.luck@intel.com>\nCc: Fenghua Yu <fenghua.yu@intel.com>\nCc: Michal Simek <monstr@monstr.eu>\nCc: Ralf Baechle <ralf@linux-mips.org>\nCc: Jonas Bonn <jonas@southpole.se>\nCc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>\nCc: Stafford Horne <shorne@gmail.com>\nCc: \"James E.J. Bottomley\" <jejb@parisc-linux.org>\nCc: Helge Deller <deller@gmx.de>\nCc: Benjamin Herrenschmidt <benh@kernel.crashing.org>\nCc: Paul Mackerras <paulus@samba.org>\nAcked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)\nCc: Martin Schwidefsky <schwidefsky@de.ibm.com>\nAcked-by: Heiko Carstens <heiko.carstens@de.ibm.com> [s390]\nCc: Yoshinori Sato <ysato@users.sourceforge.jp>\nCc: Rich Felker <dalias@libc.org>\nCc: \"David S. Miller\" <davem@davemloft.net>\nAcked-by: Chris Metcalf <cmetcalf@mellanox.com> [for tile]\nCc: Thomas Gleixner <tglx@linutronix.de>\nCc: Ingo Molnar <mingo@redhat.com>\nCc: \"H. Peter Anvin\" <hpa@zytor.com>\nCc: Chris Zankel <chris@zankel.net>\nCc: Max Filippov <jcmvbkbc@gmail.com>\nCc: Arnd Bergmann <arnd@arndb.de>\nCc: <x86@kernel.org>\nCc: <linux-alpha@vger.kernel.org>\nCc: <linux-kernel@vger.kernel.org>\nCc: <linux-snps-arc@lists.infradead.org>\nCc: <linux-arm-kernel@lists.infradead.org>\nCc: <linux-hexagon@vger.kernel.org>\nCc: <linux-ia64@vger.kernel.org>\nCc: <linux-mips@linux-mips.org>\nCc: <openrisc@lists.librecores.org>\nCc: <linux-parisc@vger.kernel.org>\nCc: <linuxppc-dev@lists.ozlabs.org>\nCc: <linux-s390@vger.kernel.org>\nCc: <linux-sh@vger.kernel.org>\nCc: <sparclinux@vger.kernel.org>\nCc: <linux-xtensa@linux-xtensa.org>\nCc: <linux-arch@vger.kernel.org>\n---\n arch/alpha/include/asm/futex.h      | 26 ++++---------------\n arch/arc/include/asm/futex.h        | 40 ++++-------------------------\n arch/arm/include/asm/futex.h        | 26 +++----------------\n arch/arm64/include/asm/futex.h      | 26 +++----------------\n arch/frv/include/asm/futex.h        |  3 ++-\n arch/frv/kernel/futex.c             | 27 +++-----------------\n arch/hexagon/include/asm/futex.h    | 38 +++-------------------------\n arch/ia64/include/asm/futex.h       | 25 +++----------------\n arch/microblaze/include/asm/futex.h | 38 +++-------------------------\n arch/mips/include/asm/futex.h       | 25 +++----------------\n arch/openrisc/include/asm/futex.h   | 39 +++--------------------------\n arch/parisc/include/asm/futex.h     | 26 +++----------------\n arch/powerpc/include/asm/futex.h    | 26 ++++---------------\n arch/s390/include/asm/futex.h       | 23 ++++-------------\n arch/sh/include/asm/futex.h         | 26 +++----------------\n arch/sparc/include/asm/futex_64.h   | 26 ++++---------------\n arch/tile/include/asm/futex.h       | 40 ++++-------------------------\n arch/x86/include/asm/futex.h        | 40 ++++-------------------------\n arch/xtensa/include/asm/futex.h     | 27 ++++----------------\n include/asm-generic/futex.h         | 50 +++++++------------------------------\n kernel/futex.c                      | 39 +++++++++++++++++++++++++++++\n 21 files changed, 130 insertions(+), 506 deletions(-)",
    "diff": "diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h\nindex fb01dfb760c2..05a70edd57b6 100644\n--- a/arch/alpha/include/asm/futex.h\n+++ b/arch/alpha/include/asm/futex.h\n@@ -25,18 +25,10 @@\n \t:\t\"r\" (uaddr), \"r\"(oparg)\t\t\t\t\\\n \t:\t\"memory\")\n \n-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n+\t\tu32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret;\n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n \n \tpagefault_disable();\n \n@@ -62,17 +54,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/arc/include/asm/futex.h b/arch/arc/include/asm/futex.h\nindex 11e1b1f3acda..eb887dd13e74 100644\n--- a/arch/arc/include/asm/futex.h\n+++ b/arch/arc/include/asm/futex.h\n@@ -73,20 +73,11 @@\n \n #endif\n \n-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n+\t\tu32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret;\n \n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))\n-\t\treturn -EFAULT;\n-\n #ifndef CONFIG_ARC_HAS_LLSC\n \tpreempt_disable();\t/* to guarantee atomic r-m-w of futex op */\n #endif\n@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \tpreempt_enable();\n #endif\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ:\n-\t\t\tret = (oldval == cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_NE:\n-\t\t\tret = (oldval != cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LT:\n-\t\t\tret = (oldval < cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GE:\n-\t\t\tret = (oldval >= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LE:\n-\t\t\tret = (oldval <= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GT:\n-\t\t\tret = (oldval > cmparg);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h\nindex 6795368ad023..cc414382dab4 100644\n--- a/arch/arm/include/asm/futex.h\n+++ b/arch/arm/include/asm/futex.h\n@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,\n #endif /* !SMP */\n \n static inline int\n-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret, tmp;\n \n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n-\n #ifndef CONFIG_SMP\n \tpreempt_disable();\n #endif\n@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n \tpreempt_enable();\n #endif\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h\nindex f32b42e8725d..5bb2fd4674e7 100644\n--- a/arch/arm64/include/asm/futex.h\n+++ b/arch/arm64/include/asm/futex.h\n@@ -48,20 +48,10 @@ do {\t\t\t\t\t\t\t\t\t\\\n } while (0)\n \n static inline int\n-futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)\n+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (int)(encoded_op << 8) >> 20;\n-\tint cmparg = (int)(encoded_op << 20) >> 20;\n \tint oldval = 0, ret, tmp;\n \n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1U << (oparg & 0x1f);\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n-\n \tpagefault_disable();\n \n \tswitch (op) {\n@@ -91,17 +81,9 @@ futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h\nindex 2e1da71e27a4..ab346f5f8820 100644\n--- a/arch/frv/include/asm/futex.h\n+++ b/arch/frv/include/asm/futex.h\n@@ -7,7 +7,8 @@\n #include <asm/errno.h>\n #include <linux/uaccess.h>\n \n-extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);\n+extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n+\t\tu32 __user *uaddr);\n \n static inline int\n futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,\ndiff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c\nindex d155ca9e5098..37f7b2bf7f73 100644\n--- a/arch/frv/kernel/futex.c\n+++ b/arch/frv/kernel/futex.c\n@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_o\n /*\n  * do the futex operations\n  */\n-int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret;\n \n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n-\n \tpagefault_disable();\n \n \tswitch (op) {\n@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS; break;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n \n \treturn ret;\n \n-} /* end futex_atomic_op_inuser() */\n+} /* end arch_futex_atomic_op_inuser() */\ndiff --git a/arch/hexagon/include/asm/futex.h b/arch/hexagon/include/asm/futex.h\nindex 7e597f8434da..c607b77c8215 100644\n--- a/arch/hexagon/include/asm/futex.h\n+++ b/arch/hexagon/include/asm/futex.h\n@@ -31,18 +31,9 @@\n \n \n static inline int\n-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)\n+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret;\n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))\n-\t\treturn -EFAULT;\n \n \tpagefault_disable();\n \n@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ:\n-\t\t\tret = (oldval == cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_NE:\n-\t\t\tret = (oldval != cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LT:\n-\t\t\tret = (oldval < cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GE:\n-\t\t\tret = (oldval >= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LE:\n-\t\t\tret = (oldval <= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GT:\n-\t\t\tret = (oldval > cmparg);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h\nindex 76acbcd5c060..6d67dc1eaf2b 100644\n--- a/arch/ia64/include/asm/futex.h\n+++ b/arch/ia64/include/asm/futex.h\n@@ -45,18 +45,9 @@ do {\t\t\t\t\t\t\t\t\t\\\n } while (0)\n \n static inline int\n-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret;\n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n \n \tpagefault_disable();\n \n@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h\nindex 01848f056f43..a9dad9e5e132 100644\n--- a/arch/microblaze/include/asm/futex.h\n+++ b/arch/microblaze/include/asm/futex.h\n@@ -29,18 +29,9 @@\n })\n \n static inline int\n-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret;\n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n \n \tpagefault_disable();\n \n@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ:\n-\t\t\tret = (oldval == cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_NE:\n-\t\t\tret = (oldval != cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LT:\n-\t\t\tret = (oldval < cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GE:\n-\t\t\tret = (oldval >= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LE:\n-\t\t\tret = (oldval <= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GT:\n-\t\t\tret = (oldval > cmparg);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h\nindex 1de190bdfb9c..a9e61ea54ca9 100644\n--- a/arch/mips/include/asm/futex.h\n+++ b/arch/mips/include/asm/futex.h\n@@ -83,18 +83,9 @@\n }\n \n static inline int\n-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret;\n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n \n \tpagefault_disable();\n \n@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/openrisc/include/asm/futex.h b/arch/openrisc/include/asm/futex.h\nindex 778087341977..8fed278a24b8 100644\n--- a/arch/openrisc/include/asm/futex.h\n+++ b/arch/openrisc/include/asm/futex.h\n@@ -30,20 +30,10 @@\n })\n \n static inline int\n-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret;\n \n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n-\n \tpagefault_disable();\n \n \tswitch (op) {\n@@ -68,30 +58,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ:\n-\t\t\tret = (oldval == cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_NE:\n-\t\t\tret = (oldval != cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LT:\n-\t\t\tret = (oldval < cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GE:\n-\t\t\tret = (oldval >= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LE:\n-\t\t\tret = (oldval <= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GT:\n-\t\t\tret = (oldval > cmparg);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h\nindex 0ba14300cd8e..c601aab2fb36 100644\n--- a/arch/parisc/include/asm/futex.h\n+++ b/arch/parisc/include/asm/futex.h\n@@ -32,22 +32,12 @@ _futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags)\n }\n \n static inline int\n-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n {\n \tunsigned long int flags;\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval, ret;\n \tu32 tmp;\n \n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))\n-\t\treturn -EFAULT;\n-\n \t_futex_spin_lock_irqsave(uaddr, &flags);\n \tpagefault_disable();\n \n@@ -85,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n \tpagefault_enable();\n \t_futex_spin_unlock_irqrestore(uaddr, &flags);\n \n-\tif (ret == 0) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h\nindex eaada6c92344..719ed9b61ea7 100644\n--- a/arch/powerpc/include/asm/futex.h\n+++ b/arch/powerpc/include/asm/futex.h\n@@ -29,18 +29,10 @@\n \t: \"b\" (uaddr), \"i\" (-EFAULT), \"r\" (oparg) \\\n \t: \"cr0\", \"memory\")\n \n-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n+\t\tu32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret;\n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n \n \tpagefault_disable();\n \n@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h\nindex a4811aa0304d..8f8eec9e1198 100644\n--- a/arch/s390/include/asm/futex.h\n+++ b/arch/s390/include/asm/futex.h\n@@ -21,17 +21,12 @@\n \t\t: \"0\" (-EFAULT), \"d\" (oparg), \"a\" (uaddr),\t\t\\\n \t\t  \"m\" (*uaddr) : \"cc\");\n \n-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n+\t\tu32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, newval, ret;\n \n \tload_kernel_asce();\n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n \n \tpagefault_disable();\n \tswitch (op) {\n@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \t}\n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h\nindex 8e26e0ddc872..38a889edc3a6 100644\n--- a/arch/sh/include/asm/futex.h\n+++ b/arch/sh/include/asm/futex.h\n@@ -27,21 +27,12 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,\n \treturn atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);\n }\n \n-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,\n+\t\tu32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tu32 oparg = (encoded_op << 8) >> 20;\n-\tu32 cmparg = (encoded_op << 20) >> 20;\n \tu32 oldval, newval, prev;\n \tint ret;\n \n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n-\n \tpagefault_disable();\n \n \tdo {\n@@ -77,17 +68,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = ((int)oldval < (int)cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = ((int)oldval >= (int)cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = ((int)oldval <= (int)cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = ((int)oldval > (int)cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n \n \treturn ret;\n }\ndiff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h\nindex 4e899b0dabf7..1cfd89d92208 100644\n--- a/arch/sparc/include/asm/futex_64.h\n+++ b/arch/sparc/include/asm/futex_64.h\n@@ -29,22 +29,14 @@\n \t: \"r\" (uaddr), \"r\" (oparg), \"i\" (-EFAULT)\t\\\n \t: \"memory\")\n \n-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n+\t\tu32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret, tem;\n \n-\tif (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))\n-\t\treturn -EFAULT;\n \tif (unlikely((((unsigned long) uaddr) & 0x3UL)))\n \t\treturn -EINVAL;\n \n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n \tpagefault_disable();\n \n \tswitch (op) {\n@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h\nindex e64a1b75fc38..83c1e639b411 100644\n--- a/arch/tile/include/asm/futex.h\n+++ b/arch/tile/include/asm/futex.h\n@@ -106,12 +106,9 @@\n \tlock = __atomic_hashed_lock((int __force *)uaddr)\n #endif\n \n-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,\n+\t\tu32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint uninitialized_var(val), ret;\n \n \t__futex_prolog();\n@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \t/* The 32-bit futex code makes this assumption, so validate it here. */\n \tBUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));\n \n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n-\n \tpagefault_disable();\n \tswitch (op) {\n \tcase FUTEX_OP_SET:\n@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \t}\n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ:\n-\t\t\tret = (val == cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_NE:\n-\t\t\tret = (val != cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LT:\n-\t\t\tret = (val < cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GE:\n-\t\t\tret = (val >= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LE:\n-\t\t\tret = (val <= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GT:\n-\t\t\tret = (val > cmparg);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = val;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h\nindex b4c1f5453436..f4dc9b63bdda 100644\n--- a/arch/x86/include/asm/futex.h\n+++ b/arch/x86/include/asm/futex.h\n@@ -41,20 +41,11 @@\n \t\t       \"+m\" (*uaddr), \"=&r\" (tem)\t\t\\\n \t\t     : \"r\" (oparg), \"i\" (-EFAULT), \"1\" (0))\n \n-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n+\t\tu32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret, tem;\n \n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n-\n \tpagefault_disable();\n \n \tswitch (op) {\n@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ:\n-\t\t\tret = (oldval == cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_NE:\n-\t\t\tret = (oldval != cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LT:\n-\t\t\tret = (oldval < cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GE:\n-\t\t\tret = (oldval >= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_LE:\n-\t\t\tret = (oldval <= cmparg);\n-\t\t\tbreak;\n-\t\tcase FUTEX_OP_CMP_GT:\n-\t\t\tret = (oldval > cmparg);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/arch/xtensa/include/asm/futex.h b/arch/xtensa/include/asm/futex.h\nindex b39531babec0..eaaf1ebcc7a4 100644\n--- a/arch/xtensa/include/asm/futex.h\n+++ b/arch/xtensa/include/asm/futex.h\n@@ -44,18 +44,10 @@\n \t: \"r\" (uaddr), \"I\" (-EFAULT), \"r\" (oparg)\t\\\n \t: \"memory\")\n \n-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n+\t\tu32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret;\n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n \n #if !XCHAL_HAVE_S32C1I\n \treturn -ENOSYS;\n@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (ret)\n-\t\treturn ret;\n+\tif (!ret)\n+\t\t*oval = oldval;\n \n-\tswitch (cmp) {\n-\tcase FUTEX_OP_CMP_EQ: return (oldval == cmparg);\n-\tcase FUTEX_OP_CMP_NE: return (oldval != cmparg);\n-\tcase FUTEX_OP_CMP_LT: return (oldval < cmparg);\n-\tcase FUTEX_OP_CMP_GE: return (oldval >= cmparg);\n-\tcase FUTEX_OP_CMP_LE: return (oldval <= cmparg);\n-\tcase FUTEX_OP_CMP_GT: return (oldval > cmparg);\n-\t}\n-\n-\treturn -ENOSYS;\n+\treturn ret;\n }\n \n static inline int\ndiff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h\nindex bf2d34c9d804..f0d8b1c51343 100644\n--- a/include/asm-generic/futex.h\n+++ b/include/asm-generic/futex.h\n@@ -13,7 +13,7 @@\n  */\n \n /**\n- * futex_atomic_op_inuser() - Atomic arithmetic operation with constant\n+ * arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant\n  *\t\t\t  argument and comparison of the previous\n  *\t\t\t  futex value with another constant.\n  *\n@@ -25,18 +25,11 @@\n  * <0 - On error\n  */\n static inline int\n-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval, ret;\n \tu32 tmp;\n \n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n \tpreempt_disable();\n \tpagefault_disable();\n \n@@ -74,17 +67,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n \tpagefault_enable();\n \tpreempt_enable();\n \n-\tif (ret == 0) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (ret == 0)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \n@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,\n \n #else\n static inline int\n-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)\n {\n-\tint op = (encoded_op >> 28) & 7;\n-\tint cmp = (encoded_op >> 24) & 15;\n-\tint oparg = (encoded_op << 8) >> 20;\n-\tint cmparg = (encoded_op << 20) >> 20;\n \tint oldval = 0, ret;\n-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n-\t\toparg = 1 << oparg;\n-\n-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n-\t\treturn -EFAULT;\n \n \tpagefault_disable();\n \n@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n \n \tpagefault_enable();\n \n-\tif (!ret) {\n-\t\tswitch (cmp) {\n-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n-\t\tdefault: ret = -ENOSYS;\n-\t\t}\n-\t}\n+\tif (!ret)\n+\t\t*oval = oldval;\n+\n \treturn ret;\n }\n \ndiff --git a/kernel/futex.c b/kernel/futex.c\nindex 0939255fc750..3d38eaf05492 100644\n--- a/kernel/futex.c\n+++ b/kernel/futex.c\n@@ -1551,6 +1551,45 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)\n \treturn ret;\n }\n \n+static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)\n+{\n+\tunsigned int op =\t  (encoded_op & 0x70000000) >> 28;\n+\tunsigned int cmp =\t  (encoded_op & 0x0f000000) >> 24;\n+\tint oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 12);\n+\tint cmparg = sign_extend32(encoded_op & 0x00000fff, 12);\n+\tint oldval, ret;\n+\n+\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {\n+\t\tif (oparg < 0 || oparg > 31)\n+\t\t\treturn -EINVAL;\n+\t\toparg = 1 << oparg;\n+\t}\n+\n+\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n+\t\treturn -EFAULT;\n+\n+\tret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tswitch (cmp) {\n+\tcase FUTEX_OP_CMP_EQ:\n+\t\treturn oldval == cmparg;\n+\tcase FUTEX_OP_CMP_NE:\n+\t\treturn oldval != cmparg;\n+\tcase FUTEX_OP_CMP_LT:\n+\t\treturn oldval < cmparg;\n+\tcase FUTEX_OP_CMP_GE:\n+\t\treturn oldval >= cmparg;\n+\tcase FUTEX_OP_CMP_LE:\n+\t\treturn oldval <= cmparg;\n+\tcase FUTEX_OP_CMP_GT:\n+\t\treturn oldval > cmparg;\n+\tdefault:\n+\t\treturn -ENOSYS;\n+\t}\n+}\n+\n /*\n  * Wake up all waiters hashed on the physical page that is mapped\n  * to this virtual address:\n",
    "prefixes": [
        "v2",
        "1/1"
    ]
}