get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 807401,
    "url": "http://patchwork.ozlabs.org/api/patches/807401/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/1504066360-30128-10-git-send-email-paulus@ozlabs.org/",
    "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": "<1504066360-30128-10-git-send-email-paulus@ozlabs.org>",
    "list_archive_url": "https://lore.kernel.org/linuxppc-dev/1504066360-30128-10-git-send-email-paulus@ozlabs.org/",
    "date": "2017-08-30T04:12:32",
    "name": "[v3,09/17] powerpc: Make load/store emulation use larger memory accesses",
    "commit_ref": "e0a0986b446553c6a69fe1bb36250224646b264f",
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "c66d460ba546800abd21d3364961f9cac648bf43",
    "submitter": {
        "id": 67079,
        "url": "http://patchwork.ozlabs.org/api/people/67079/?format=api",
        "name": "Paul Mackerras",
        "email": "paulus@ozlabs.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/1504066360-30128-10-git-send-email-paulus@ozlabs.org/mbox/",
    "series": [
        {
            "id": 522,
            "url": "http://patchwork.ozlabs.org/api/series/522/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=522",
            "date": "2017-08-30T04:12:25",
            "name": "powerpc: Do alignment fixups using analyse_instr etc.",
            "version": 3,
            "mbox": "http://patchwork.ozlabs.org/series/522/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/807401/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/807401/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",
            "linuxppc-dev@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 3xhsxh4YGJz9s9Y\n\tfor <patchwork-incoming@ozlabs.org>;\n\tWed, 30 Aug 2017 14:30:32 +1000 (AEST)",
            "from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3xhsxh37cxzDq5b\n\tfor <patchwork-incoming@ozlabs.org>;\n\tWed, 30 Aug 2017 14:30:32 +1000 (AEST)",
            "from ozlabs.org (bilbo.ozlabs.org [103.22.144.67])\n\t(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 3xhsYH50FxzDqGG\n\tfor <linuxppc-dev@lists.ozlabs.org>;\n\tWed, 30 Aug 2017 14:12:51 +1000 (AEST)",
            "by ozlabs.org (Postfix)\n\tid 3xhsYH4GPfz9sP5; Wed, 30 Aug 2017 14:12:51 +1000 (AEST)",
            "from authenticated.ozlabs.org (localhost [127.0.0.1])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPSA id 3xhsYH34FTz9sNc\n\tfor <linuxppc-dev@ozlabs.org>; Wed, 30 Aug 2017 14:12:51 +1000 (AEST)"
        ],
        "Authentication-Results": [
            "ozlabs.org; dkim=pass (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"Ctt3BIEU\";\n\tdkim-atps=neutral",
            "lists.ozlabs.org; dkim=pass (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"Ctt3BIEU\";\n\tdkim-atps=neutral",
            "lists.ozlabs.org; dkim=pass (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"Ctt3BIEU\"; \n\tdkim-atps=neutral"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ozlabs.org; s=201707; \n\tt=1504066371; bh=5gDcYcWpAEK8RWda6soUu/BH6SD0NuYyJy0u4TYcqjA=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=Ctt3BIEUXBRHW58Oju+Exb2/TJryyRtnZuVzm4ovkfAOdS94yMXRYwo7+WWVXL+3i\n\tSc9OWu81r4Vhfe+2DBjNzPbnyJhaX3F3/TItGuKEQEBys7zcDATshke9Qo1zzQXHIP\n\tGwUygZsBekLGFt1+H5m7J4ycW/nhJuamrqszraRdjG1PJ1AF5EmS2wU8hOTC8Uahmx\n\tO/ANb2SqVt6XBs7RzkEZh3+4IDlyrQxZRMh6+ZH4RSue/i5MZJlrLC6f18mntFxVdZ\n\tZ6I9FU07paDGAS4PAXBG0kNgMFhCCecmR90yAh4Khk0puHDM6Q5ADmodeYupdSBrnZ\n\tlnA7J67+onktw==",
        "From": "Paul Mackerras <paulus@ozlabs.org>",
        "To": "linuxppc-dev@ozlabs.org",
        "Subject": "[PATCH v3 09/17] powerpc: Make load/store emulation use larger\n\tmemory accesses",
        "Date": "Wed, 30 Aug 2017 14:12:32 +1000",
        "Message-Id": "<1504066360-30128-10-git-send-email-paulus@ozlabs.org>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1504066360-30128-1-git-send-email-paulus@ozlabs.org>",
        "References": "<1504066360-30128-1-git-send-email-paulus@ozlabs.org>",
        "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>",
        "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": "At the moment, emulation of loads and stores of up to 8 bytes to\nunaligned addresses on a little-endian system uses a sequence of\nsingle-byte loads or stores to memory.  This is rather inefficient,\nand the code is hard to follow because it has many ifdefs.\nIn addition, the Power ISA has requirements on how unaligned accesses\nare performed, which are not met by doing all accesses as\nsequences of single-byte accesses.\n\nEmulation of VSX loads and stores uses __copy_{to,from}_user,\nwhich means the emulation code has no control on the size of\naccesses.\n\nTo simplify this, we add new copy_mem_in() and copy_mem_out()\nfunctions for accessing memory.  These use a sequence of the largest\npossible aligned accesses, up to 8 bytes (or 4 on 32-bit systems),\nto copy memory between a local buffer and user memory.  We then\nrewrite {read,write}_mem_unaligned and the VSX load/store\nemulation using these new functions.\n\nThese new functions also simplify the code in do_fp_load() and\ndo_fp_store() for the unaligned cases.\n\nSigned-off-by: Paul Mackerras <paulus@ozlabs.org>\n---\n arch/powerpc/lib/sstep.c | 235 +++++++++++++++++++++--------------------------\n 1 file changed, 106 insertions(+), 129 deletions(-)",
    "diff": "diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c\nindex ed2bc4c..6cc2911 100644\n--- a/arch/powerpc/lib/sstep.c\n+++ b/arch/powerpc/lib/sstep.c\n@@ -193,7 +193,6 @@ static nokprobe_inline unsigned long max_align(unsigned long x)\n \treturn x & -x;\t\t/* isolates rightmost bit */\n }\n \n-\n static nokprobe_inline unsigned long byterev_2(unsigned long x)\n {\n \treturn ((x >> 8) & 0xff) | ((x & 0xff) << 8);\n@@ -239,56 +238,69 @@ static nokprobe_inline int read_mem_aligned(unsigned long *dest,\n \treturn err;\n }\n \n-static nokprobe_inline int read_mem_unaligned(unsigned long *dest,\n-\t\t\t\tunsigned long ea, int nb, struct pt_regs *regs)\n+/*\n+ * Copy from userspace to a buffer, using the largest possible\n+ * aligned accesses, up to sizeof(long).\n+ */\n+static int nokprobe_inline copy_mem_in(u8 *dest, unsigned long ea, int nb)\n {\n-\tint err;\n-\tunsigned long x, b, c;\n-#ifdef __LITTLE_ENDIAN__\n-\tint len = nb; /* save a copy of the length for byte reversal */\n-#endif\n+\tint err = 0;\n+\tint c;\n \n-\t/* unaligned, do this in pieces */\n-\tx = 0;\n \tfor (; nb > 0; nb -= c) {\n-#ifdef __LITTLE_ENDIAN__\n-\t\tc = 1;\n-#endif\n-#ifdef __BIG_ENDIAN__\n \t\tc = max_align(ea);\n-#endif\n \t\tif (c > nb)\n \t\t\tc = max_align(nb);\n-\t\terr = read_mem_aligned(&b, ea, c);\n+\t\tswitch (c) {\n+\t\tcase 1:\n+\t\t\terr = __get_user(*dest, (unsigned char __user *) ea);\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\terr = __get_user(*(u16 *)dest,\n+\t\t\t\t\t (unsigned short __user *) ea);\n+\t\t\tbreak;\n+\t\tcase 4:\n+\t\t\terr = __get_user(*(u32 *)dest,\n+\t\t\t\t\t (unsigned int __user *) ea);\n+\t\t\tbreak;\n+#ifdef __powerpc64__\n+\t\tcase 8:\n+\t\t\terr = __get_user(*(unsigned long *)dest,\n+\t\t\t\t\t (unsigned long __user *) ea);\n+\t\t\tbreak;\n+#endif\n+\t\t}\n \t\tif (err)\n \t\t\treturn err;\n-\t\tx = (x << (8 * c)) + b;\n+\t\tdest += c;\n \t\tea += c;\n \t}\n-#ifdef __LITTLE_ENDIAN__\n-\tswitch (len) {\n-\tcase 2:\n-\t\t*dest = byterev_2(x);\n-\t\tbreak;\n-\tcase 4:\n-\t\t*dest = byterev_4(x);\n-\t\tbreak;\n-#ifdef __powerpc64__\n-\tcase 8:\n-\t\t*dest = byterev_8(x);\n-\t\tbreak;\n-#endif\n-\t}\n-#endif\n-#ifdef __BIG_ENDIAN__\n-\t*dest = x;\n-#endif\n \treturn 0;\n }\n \n+static nokprobe_inline int read_mem_unaligned(unsigned long *dest,\n+\t\t\t\t\t      unsigned long ea, int nb,\n+\t\t\t\t\t      struct pt_regs *regs)\n+{\n+\tunion {\n+\t\tunsigned long ul;\n+\t\tu8 b[sizeof(unsigned long)];\n+\t} u;\n+\tint i;\n+\tint err;\n+\n+\tu.ul = 0;\n+\ti = IS_BE ? sizeof(unsigned long) - nb : 0;\n+\terr = copy_mem_in(&u.b[i], ea, nb);\n+\tif (!err)\n+\t\t*dest = u.ul;\n+\treturn err;\n+}\n+\n /*\n  * Read memory at address ea for nb bytes, return 0 for success\n- * or -EFAULT if an error occurred.\n+ * or -EFAULT if an error occurred.  N.B. nb must be 1, 2, 4 or 8.\n+ * If nb < sizeof(long), the result is right-justified on BE systems.\n  */\n static int read_mem(unsigned long *dest, unsigned long ea, int nb,\n \t\t\t      struct pt_regs *regs)\n@@ -325,48 +337,64 @@ static nokprobe_inline int write_mem_aligned(unsigned long val,\n \treturn err;\n }\n \n-static nokprobe_inline int write_mem_unaligned(unsigned long val,\n-\t\t\t\tunsigned long ea, int nb, struct pt_regs *regs)\n+/*\n+ * Copy from a buffer to userspace, using the largest possible\n+ * aligned accesses, up to sizeof(long).\n+ */\n+static int nokprobe_inline copy_mem_out(u8 *dest, unsigned long ea, int nb)\n {\n-\tint err;\n-\tunsigned long c;\n+\tint err = 0;\n+\tint c;\n \n-#ifdef __LITTLE_ENDIAN__\n-\tswitch (nb) {\n-\tcase 2:\n-\t\tval = byterev_2(val);\n-\t\tbreak;\n-\tcase 4:\n-\t\tval = byterev_4(val);\n-\t\tbreak;\n-#ifdef __powerpc64__\n-\tcase 8:\n-\t\tval = byterev_8(val);\n-\t\tbreak;\n-#endif\n-\t}\n-#endif\n-\t/* unaligned or little-endian, do this in pieces */\n \tfor (; nb > 0; nb -= c) {\n-#ifdef __LITTLE_ENDIAN__\n-\t\tc = 1;\n-#endif\n-#ifdef __BIG_ENDIAN__\n \t\tc = max_align(ea);\n-#endif\n \t\tif (c > nb)\n \t\t\tc = max_align(nb);\n-\t\terr = write_mem_aligned(val >> (nb - c) * 8, ea, c);\n+\t\tswitch (c) {\n+\t\tcase 1:\n+\t\t\terr = __put_user(*dest, (unsigned char __user *) ea);\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\terr = __put_user(*(u16 *)dest,\n+\t\t\t\t\t (unsigned short __user *) ea);\n+\t\t\tbreak;\n+\t\tcase 4:\n+\t\t\terr = __put_user(*(u32 *)dest,\n+\t\t\t\t\t (unsigned int __user *) ea);\n+\t\t\tbreak;\n+#ifdef __powerpc64__\n+\t\tcase 8:\n+\t\t\terr = __put_user(*(unsigned long *)dest,\n+\t\t\t\t\t (unsigned long __user *) ea);\n+\t\t\tbreak;\n+#endif\n+\t\t}\n \t\tif (err)\n \t\t\treturn err;\n+\t\tdest += c;\n \t\tea += c;\n \t}\n \treturn 0;\n }\n \n+static nokprobe_inline int write_mem_unaligned(unsigned long val,\n+\t\t\t\t\t       unsigned long ea, int nb,\n+\t\t\t\t\t       struct pt_regs *regs)\n+{\n+\tunion {\n+\t\tunsigned long ul;\n+\t\tu8 b[sizeof(unsigned long)];\n+\t} u;\n+\tint i;\n+\n+\tu.ul = val;\n+\ti = IS_BE ? sizeof(unsigned long) - nb : 0;\n+\treturn copy_mem_out(&u.b[i], ea, nb);\n+}\n+\n /*\n  * Write memory at address ea for nb bytes, return 0 for success\n- * or -EFAULT if an error occurred.\n+ * or -EFAULT if an error occurred.  N.B. nb must be 1, 2, 4 or 8.\n  */\n static int write_mem(unsigned long val, unsigned long ea, int nb,\n \t\t\t       struct pt_regs *regs)\n@@ -389,40 +417,17 @@ static int do_fp_load(int rn, int (*func)(int, unsigned long),\n \t\t\t\tstruct pt_regs *regs)\n {\n \tint err;\n-\tunion {\n-\t\tdouble dbl;\n-\t\tunsigned long ul[2];\n-\t\tstruct {\n-#ifdef __BIG_ENDIAN__\n-\t\t\tunsigned _pad_;\n-\t\t\tunsigned word;\n-#endif\n-#ifdef __LITTLE_ENDIAN__\n-\t\t\tunsigned word;\n-\t\t\tunsigned _pad_;\n-#endif\n-\t\t} single;\n-\t} data;\n-\tunsigned long ptr;\n+\tu8 buf[sizeof(double)] __attribute__((aligned(sizeof(double))));\n \n \tif (!address_ok(regs, ea, nb))\n \t\treturn -EFAULT;\n-\tif ((ea & 3) == 0)\n-\t\treturn (*func)(rn, ea);\n-\tptr = (unsigned long) &data.ul;\n-\tif (sizeof(unsigned long) == 8 || nb == 4) {\n-\t\terr = read_mem_unaligned(&data.ul[0], ea, nb, regs);\n-\t\tif (nb == 4)\n-\t\t\tptr = (unsigned long)&(data.single.word);\n-\t} else {\n-\t\t/* reading a double on 32-bit */\n-\t\terr = read_mem_unaligned(&data.ul[0], ea, 4, regs);\n-\t\tif (!err)\n-\t\t\terr = read_mem_unaligned(&data.ul[1], ea + 4, 4, regs);\n+\tif (ea & 3) {\n+\t\terr = copy_mem_in(buf, ea, nb);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t\tea = (unsigned long) buf;\n \t}\n-\tif (err)\n-\t\treturn err;\n-\treturn (*func)(rn, ptr);\n+\treturn (*func)(rn, ea);\n }\n NOKPROBE_SYMBOL(do_fp_load);\n \n@@ -431,43 +436,15 @@ static int do_fp_store(int rn, int (*func)(int, unsigned long),\n \t\t\t\t struct pt_regs *regs)\n {\n \tint err;\n-\tunion {\n-\t\tdouble dbl;\n-\t\tunsigned long ul[2];\n-\t\tstruct {\n-#ifdef __BIG_ENDIAN__\n-\t\t\tunsigned _pad_;\n-\t\t\tunsigned word;\n-#endif\n-#ifdef __LITTLE_ENDIAN__\n-\t\t\tunsigned word;\n-\t\t\tunsigned _pad_;\n-#endif\n-\t\t} single;\n-\t} data;\n-\tunsigned long ptr;\n+\tu8 buf[sizeof(double)] __attribute__((aligned(sizeof(double))));\n \n \tif (!address_ok(regs, ea, nb))\n \t\treturn -EFAULT;\n \tif ((ea & 3) == 0)\n \t\treturn (*func)(rn, ea);\n-\tptr = (unsigned long) &data.ul[0];\n-\tif (sizeof(unsigned long) == 8 || nb == 4) {\n-\t\tif (nb == 4)\n-\t\t\tptr = (unsigned long)&(data.single.word);\n-\t\terr = (*func)(rn, ptr);\n-\t\tif (err)\n-\t\t\treturn err;\n-\t\terr = write_mem_unaligned(data.ul[0], ea, nb, regs);\n-\t} else {\n-\t\t/* writing a double on 32-bit */\n-\t\terr = (*func)(rn, ptr);\n-\t\tif (err)\n-\t\t\treturn err;\n-\t\terr = write_mem_unaligned(data.ul[0], ea, 4, regs);\n-\t\tif (!err)\n-\t\t\terr = write_mem_unaligned(data.ul[1], ea + 4, 4, regs);\n-\t}\n+\terr = (*func)(rn, (unsigned long) buf);\n+\tif (!err)\n+\t\terr = copy_mem_out(buf, ea, nb);\n \treturn err;\n }\n NOKPROBE_SYMBOL(do_fp_store);\n@@ -2564,7 +2541,7 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n #endif\n #ifdef CONFIG_VSX\n \tcase LOAD_VSX: {\n-\t\tchar mem[16];\n+\t\tu8 mem[16];\n \t\tunion vsx_reg buf;\n \t\tunsigned long msrbit = MSR_VSX;\n \n@@ -2577,7 +2554,7 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \t\tif (!(regs->msr & msrbit))\n \t\t\treturn 0;\n \t\tif (!address_ok(regs, ea, size) ||\n-\t\t    __copy_from_user(mem, (void __user *)ea, size))\n+\t\t    copy_mem_in(mem, ea, size))\n \t\t\treturn 0;\n \n \t\temulate_vsx_load(&op, &buf, mem);\n@@ -2639,7 +2616,7 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n #endif\n #ifdef CONFIG_VSX\n \tcase STORE_VSX: {\n-\t\tchar mem[16];\n+\t\tu8 mem[16];\n \t\tunion vsx_reg buf;\n \t\tunsigned long msrbit = MSR_VSX;\n \n@@ -2656,7 +2633,7 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \n \t\tstore_vsrn(op.reg, &buf);\n \t\temulate_vsx_store(&op, &buf, mem);\n-\t\tif (__copy_to_user((void __user *)ea, mem, size))\n+\t\tif (copy_mem_out(mem, ea, size))\n \t\t\treturn 0;\n \t\tgoto ldst_done;\n \t}\n",
    "prefixes": [
        "v3",
        "09/17"
    ]
}