Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/807402/?format=api
{ "id": 807402, "url": "http://patchwork.ozlabs.org/api/patches/807402/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/1504066360-30128-11-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-11-git-send-email-paulus@ozlabs.org>", "list_archive_url": "https://lore.kernel.org/linuxppc-dev/1504066360-30128-11-git-send-email-paulus@ozlabs.org/", "date": "2017-08-30T04:12:33", "name": "[v3,10/17] powerpc: Emulate FP/vector/VSX loads/stores correctly when regs not live", "commit_ref": "c22435a5f3d8f85ea162ae523a6ba60a58521ba5", "pull_url": null, "state": "accepted", "archived": false, "hash": "48d910ac4eed2eb22f83f0be00684dc5e6a759dd", "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-11-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/807402/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/807402/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 [IPv6:2401:3900:2:1::3])\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 3xht0G0XGmz9s9Y\n\tfor <patchwork-incoming@ozlabs.org>;\n\tWed, 30 Aug 2017 14:32:46 +1000 (AEST)", "from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3xht0F5CSzzDqJ8\n\tfor <patchwork-incoming@ozlabs.org>;\n\tWed, 30 Aug 2017 14:32:45 +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 3xhsYH6nNLzDqGG\n\tfor <linuxppc-dev@lists.ozlabs.org>;\n\tWed, 30 Aug 2017 14:12:51 +1000 (AEST)", "by ozlabs.org (Postfix)\n\tid 3xhsYH5pwcz9sNc; 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 3xhsYH4d6Sz9sPt\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=\"YZP4b83e\";\n\tdkim-atps=neutral", "lists.ozlabs.org; dkim=pass (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"YZP4b83e\";\n\tdkim-atps=neutral", "lists.ozlabs.org; dkim=pass (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"YZP4b83e\"; \n\tdkim-atps=neutral" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ozlabs.org; s=201707; \n\tt=1504066371; bh=fmrAnXog31kwzy4N9aZ5TPIUWB62sjqp1Ck22mnN5bk=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=YZP4b83e5LX+S9fme891925ptBM4R/1+voiTdLjlMEnFWk+X7zXSpiC9ZH16sh0rT\n\tGA/R33bqEzTfRk+K0YbmkZKJCPaqrSbdMNhAx6eDMxkV6Vj/bv/uFCm44dm8tSHgD5\n\t1d2D0WJNwFzFjD2TBa1DQirdZO7p094Yut2XzxAXxBgkTC1gYgvk1VXFE+y9sSZ7H0\n\tUNdYu7GclqEazve7J75Q8VDeqV0p5LCGHv6MuycRcAzHl92FwKYZu5fhToC97waiXM\n\ttTjOK2u+YDZ6wleNtaKJuxo6W7u1HE1zVrv/Uhqcg4rMPWmHD418Ox6jMG4KaL18zk\n\tJkafZzZhFcqVg==", "From": "Paul Mackerras <paulus@ozlabs.org>", "To": "linuxppc-dev@ozlabs.org", "Subject": "[PATCH v3 10/17] powerpc: Emulate FP/vector/VSX loads/stores\n\tcorrectly when regs not live", "Date": "Wed, 30 Aug 2017 14:12:33 +1000", "Message-Id": "<1504066360-30128-11-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 present, the analyse_instr/emulate_step code checks for the\nrelevant MSR_FP/VEC/VSX bit being set when a FP/VMX/VSX load\nor store is decoded, but doesn't recheck the bit before reading or\nwriting the relevant FP/VMX/VSX register in emulate_step().\n\nSince we don't have preemption disabled, it is possible that we get\npreempted between checking the MSR bit and doing the register access.\nIf that happened, then the registers would have been saved to the\nthread_struct for the current process. Accesses to the CPU registers\nwould then potentially read stale values, or write values that would\nnever be seen by the user process.\n\nAnother way that the registers can become non-live is if a page\nfault occurs when accessing user memory, and the page fault code\ncalls a copy routine that wants to use the VMX or VSX registers.\n\nTo fix this, the code for all the FP/VMX/VSX loads gets restructured\nso that it forms an image in a local variable of the desired register\ncontents, then disables preemption, checks the MSR bit and either\nsets the CPU register or writes the value to the thread struct.\nSimilarly, the code for stores checks the MSR bit, copies either the\nCPU register or the thread struct to a local variable, then reenables\npreemption and then copies the register image to memory.\n\nIf the instruction being emulated is in the kernel, then we must not\nuse the register values in the thread_struct. In this case, if the\nrelevant MSR enable bit is not set, then emulate_step refuses to\nemulate the instruction.\n\nSigned-off-by: Paul Mackerras <paulus@ozlabs.org>\n---\n arch/powerpc/include/asm/sstep.h | 1 +\n arch/powerpc/lib/ldstfp.S | 241 +++++++--------------------------------\n arch/powerpc/lib/sstep.c | 228 +++++++++++++++++++++++++-----------\n 3 files changed, 203 insertions(+), 267 deletions(-)", "diff": "diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h\nindex 4fcc2c9..474a992 100644\n--- a/arch/powerpc/include/asm/sstep.h\n+++ b/arch/powerpc/include/asm/sstep.h\n@@ -119,6 +119,7 @@ union vsx_reg {\n \tunsigned long d[2];\n \tfloat\tfp[4];\n \tdouble\tdp[2];\n+\t__vector128 v;\n };\n \n /*\ndiff --git a/arch/powerpc/lib/ldstfp.S b/arch/powerpc/lib/ldstfp.S\nindex 6840911..7b5cf5e 100644\n--- a/arch/powerpc/lib/ldstfp.S\n+++ b/arch/powerpc/lib/ldstfp.S\n@@ -21,27 +21,19 @@\n \n #define STKFRM\t(PPC_MIN_STKFRM + 16)\n \n-\t.macro\tinst32\top\n-reg = 0\n-\t.rept\t32\n-20:\t\\op\treg,0,r4\n-\tb\t3f\n-\tEX_TABLE(20b,99f)\n-reg = reg + 1\n-\t.endr\n-\t.endm\n-\n-/* Get the contents of frN into fr0; N is in r3. */\n+/* Get the contents of frN into *p; N is in r3 and p is in r4. */\n _GLOBAL(get_fpr)\n \tmflr\tr0\n+\tmfmsr\tr6\n+\tori\tr7, r6, MSR_FP\n+\tMTMSRD(r7)\n+\tisync\n \trlwinm\tr3,r3,3,0xf8\n \tbcl\t20,31,1f\n-\tblr\t\t\t/* fr0 is already in fr0 */\n-\tnop\n-reg = 1\n-\t.rept\t31\n-\tfmr\tfr0,reg\n-\tblr\n+reg = 0\n+\t.rept\t32\n+\tstfd\treg, 0(r4)\n+\tb\t2f\n reg = reg + 1\n \t.endr\n 1:\tmflr\tr5\n@@ -49,18 +41,23 @@ reg = reg + 1\n \tmtctr\tr5\n \tmtlr\tr0\n \tbctr\n+2:\tMTMSRD(r6)\n+\tisync\n+\tblr\n \n-/* Put the contents of fr0 into frN; N is in r3. */\n+/* Put the contents of *p into frN; N is in r3 and p is in r4. */\n _GLOBAL(put_fpr)\n \tmflr\tr0\n+\tmfmsr\tr6\n+\tori\tr7, r6, MSR_FP\n+\tMTMSRD(r7)\n+\tisync\n \trlwinm\tr3,r3,3,0xf8\n \tbcl\t20,31,1f\n-\tblr\t\t\t/* fr0 is already in fr0 */\n-\tnop\n-reg = 1\n-\t.rept\t31\n-\tfmr\treg,fr0\n-\tblr\n+reg = 0\n+\t.rept\t32\n+\tlfd\treg, 0(r4)\n+\tb\t2f\n reg = reg + 1\n \t.endr\n 1:\tmflr\tr5\n@@ -68,127 +65,24 @@ reg = reg + 1\n \tmtctr\tr5\n \tmtlr\tr0\n \tbctr\n-\n-/* Load FP reg N from float at *p. N is in r3, p in r4. */\n-_GLOBAL(do_lfs)\n-\tPPC_STLU r1,-STKFRM(r1)\n-\tmflr\tr0\n-\tPPC_STL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n-\tmfmsr\tr6\n-\tori\tr7,r6,MSR_FP\n-\tcmpwi\tcr7,r3,0\n-\tMTMSRD(r7)\n-\tisync\n-\tbeq\tcr7,1f\n-\tstfd\tfr0,STKFRM-16(r1)\n-1:\tli\tr9,-EFAULT\n-2:\tlfs\tfr0,0(r4)\n-\tli\tr9,0\n-3:\tbl\tput_fpr\n-\tbeq\tcr7,4f\n-\tlfd\tfr0,STKFRM-16(r1)\n-4:\tPPC_LL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n-\tmtlr\tr0\n-\tMTMSRD(r6)\n-\tisync\n-\tmr\tr3,r9\n-\taddi\tr1,r1,STKFRM\n-\tblr\n-\tEX_TABLE(2b,3b)\n-\n-/* Load FP reg N from double at *p. N is in r3, p in r4. */\n-_GLOBAL(do_lfd)\n-\tPPC_STLU r1,-STKFRM(r1)\n-\tmflr\tr0\n-\tPPC_STL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n-\tmfmsr\tr6\n-\tori\tr7,r6,MSR_FP\n-\tcmpwi\tcr7,r3,0\n-\tMTMSRD(r7)\n-\tisync\n-\tbeq\tcr7,1f\n-\tstfd\tfr0,STKFRM-16(r1)\n-1:\tli\tr9,-EFAULT\n-2:\tlfd\tfr0,0(r4)\n-\tli\tr9,0\n-3:\tbeq\tcr7,4f\n-\tbl\tput_fpr\n-\tlfd\tfr0,STKFRM-16(r1)\n-4:\tPPC_LL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n-\tmtlr\tr0\n-\tMTMSRD(r6)\n-\tisync\n-\tmr\tr3,r9\n-\taddi\tr1,r1,STKFRM\n-\tblr\n-\tEX_TABLE(2b,3b)\n-\n-/* Store FP reg N to float at *p. N is in r3, p in r4. */\n-_GLOBAL(do_stfs)\n-\tPPC_STLU r1,-STKFRM(r1)\n-\tmflr\tr0\n-\tPPC_STL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n-\tmfmsr\tr6\n-\tori\tr7,r6,MSR_FP\n-\tcmpwi\tcr7,r3,0\n-\tMTMSRD(r7)\n-\tisync\n-\tbeq\tcr7,1f\n-\tstfd\tfr0,STKFRM-16(r1)\n-\tbl\tget_fpr\n-1:\tli\tr9,-EFAULT\n-2:\tstfs\tfr0,0(r4)\n-\tli\tr9,0\n-3:\tbeq\tcr7,4f\n-\tlfd\tfr0,STKFRM-16(r1)\n-4:\tPPC_LL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n-\tmtlr\tr0\n-\tMTMSRD(r6)\n+2:\tMTMSRD(r6)\n \tisync\n-\tmr\tr3,r9\n-\taddi\tr1,r1,STKFRM\n \tblr\n-\tEX_TABLE(2b,3b)\n \n-/* Store FP reg N to double at *p. N is in r3, p in r4. */\n-_GLOBAL(do_stfd)\n-\tPPC_STLU r1,-STKFRM(r1)\n+#ifdef CONFIG_ALTIVEC\n+/* Get the contents of vrN into *p; N is in r3 and p is in r4. */\n+_GLOBAL(get_vr)\n \tmflr\tr0\n-\tPPC_STL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n \tmfmsr\tr6\n-\tori\tr7,r6,MSR_FP\n-\tcmpwi\tcr7,r3,0\n+\toris\tr7, r6, MSR_VEC@h\n \tMTMSRD(r7)\n \tisync\n-\tbeq\tcr7,1f\n-\tstfd\tfr0,STKFRM-16(r1)\n-\tbl\tget_fpr\n-1:\tli\tr9,-EFAULT\n-2:\tstfd\tfr0,0(r4)\n-\tli\tr9,0\n-3:\tbeq\tcr7,4f\n-\tlfd\tfr0,STKFRM-16(r1)\n-4:\tPPC_LL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n-\tmtlr\tr0\n-\tMTMSRD(r6)\n-\tisync\n-\tmr\tr3,r9\n-\taddi\tr1,r1,STKFRM\n-\tblr\n-\tEX_TABLE(2b,3b)\n-\n-#ifdef CONFIG_ALTIVEC\n-/* Get the contents of vrN into v0; N is in r3. Doesn't touch r3 or r4. */\n-_GLOBAL(get_vr)\n-\tmflr\tr0\n \trlwinm\tr6,r3,3,0xf8\n \tbcl\t20,31,1f\n-\tblr\t\t\t/* v0 is already in v0 */\n-\tnop\n-reg = 1\n-\t.rept\t31\n-\tvor\tv0,reg,reg\t/* assembler doesn't know vmr? */\n-\tblr\n+reg = 0\n+\t.rept\t32\n+\tstvx\treg, 0, r4\n+\tb\t2f\n reg = reg + 1\n \t.endr\n 1:\tmflr\tr5\n@@ -196,18 +90,23 @@ reg = reg + 1\n \tmtctr\tr5\n \tmtlr\tr0\n \tbctr\n+2:\tMTMSRD(r6)\n+\tisync\n+\tblr\n \n-/* Put the contents of v0 into vrN; N is in r3. Doesn't touch r3 or r4. */\n+/* Put the contents of *p into vrN; N is in r3 and p is in r4. */\n _GLOBAL(put_vr)\n \tmflr\tr0\n+\tmfmsr\tr6\n+\toris\tr7, r6, MSR_VEC@h\n+\tMTMSRD(r7)\n+\tisync\n \trlwinm\tr6,r3,3,0xf8\n \tbcl\t20,31,1f\n-\tblr\t\t\t/* v0 is already in v0 */\n-\tnop\n-reg = 1\n-\t.rept\t31\n-\tvor\treg,v0,v0\n-\tblr\n+reg = 0\n+\t.rept\t32\n+\tlvx\treg, 0, r4\n+\tb\t2f\n reg = reg + 1\n \t.endr\n 1:\tmflr\tr5\n@@ -215,62 +114,9 @@ reg = reg + 1\n \tmtctr\tr5\n \tmtlr\tr0\n \tbctr\n-\n-/* Load vector reg N from *p. N is in r3, p in r4. */\n-_GLOBAL(do_lvx)\n-\tPPC_STLU r1,-STKFRM(r1)\n-\tmflr\tr0\n-\tPPC_STL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n-\tmfmsr\tr6\n-\toris\tr7,r6,MSR_VEC@h\n-\tcmpwi\tcr7,r3,0\n-\tli\tr8,STKFRM-16\n-\tMTMSRD(r7)\n-\tisync\n-\tbeq\tcr7,1f\n-\tstvx\tv0,r1,r8\n-1:\tli\tr9,-EFAULT\n-2:\tlvx\tv0,0,r4\n-\tli\tr9,0\n-3:\tbeq\tcr7,4f\n-\tbl\tput_vr\n-\tlvx\tv0,r1,r8\n-4:\tPPC_LL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n-\tmtlr\tr0\n-\tMTMSRD(r6)\n-\tisync\n-\tmr\tr3,r9\n-\taddi\tr1,r1,STKFRM\n-\tblr\n-\tEX_TABLE(2b,3b)\n-\n-/* Store vector reg N to *p. N is in r3, p in r4. */\n-_GLOBAL(do_stvx)\n-\tPPC_STLU r1,-STKFRM(r1)\n-\tmflr\tr0\n-\tPPC_STL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n-\tmfmsr\tr6\n-\toris\tr7,r6,MSR_VEC@h\n-\tcmpwi\tcr7,r3,0\n-\tli\tr8,STKFRM-16\n-\tMTMSRD(r7)\n-\tisync\n-\tbeq\tcr7,1f\n-\tstvx\tv0,r1,r8\n-\tbl\tget_vr\n-1:\tli\tr9,-EFAULT\n-2:\tstvx\tv0,0,r4\n-\tli\tr9,0\n-3:\tbeq\tcr7,4f\n-\tlvx\tv0,r1,r8\n-4:\tPPC_LL\tr0,STKFRM+PPC_LR_STKOFF(r1)\n-\tmtlr\tr0\n-\tMTMSRD(r6)\n+2:\tMTMSRD(r6)\n \tisync\n-\tmr\tr3,r9\n-\taddi\tr1,r1,STKFRM\n \tblr\n-\tEX_TABLE(2b,3b)\n #endif /* CONFIG_ALTIVEC */\n \n #ifdef CONFIG_VSX\n@@ -363,7 +209,6 @@ _GLOBAL(store_vsrn)\n \tmr\tr3,r9\n \taddi\tr1,r1,STKFRM\n \tblr\n-\tEX_TABLE(2b,3b)\n #endif /* CONFIG_VSX */\n \n /* Convert single-precision to double, without disturbing FPRs. */\ndiff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c\nindex 6cc2911..91ae031 100644\n--- a/arch/powerpc/lib/sstep.c\n+++ b/arch/powerpc/lib/sstep.c\n@@ -36,12 +36,10 @@ extern char system_call_common[];\n /*\n * Functions in ldstfp.S\n */\n-extern int do_lfs(int rn, unsigned long ea);\n-extern int do_lfd(int rn, unsigned long ea);\n-extern int do_stfs(int rn, unsigned long ea);\n-extern int do_stfd(int rn, unsigned long ea);\n-extern int do_lvx(int rn, unsigned long ea);\n-extern int do_stvx(int rn, unsigned long ea);\n+extern void get_fpr(int rn, double *p);\n+extern void put_fpr(int rn, const double *p);\n+extern void get_vr(int rn, __vector128 *p);\n+extern void put_vr(int rn, __vector128 *p);\n extern void load_vsrn(int vsr, const void *p);\n extern void store_vsrn(int vsr, void *p);\n extern void conv_sp_to_dp(const float *sp, double *dp);\n@@ -409,63 +407,108 @@ NOKPROBE_SYMBOL(write_mem);\n \n #ifdef CONFIG_PPC_FPU\n /*\n- * Check the address and alignment, and call func to do the actual\n- * load or store.\n+ * These access either the real FP register or the image in the\n+ * thread_struct, depending on regs->msr & MSR_FP.\n */\n-static int do_fp_load(int rn, int (*func)(int, unsigned long),\n-\t\t\t\tunsigned long ea, int nb,\n-\t\t\t\tstruct pt_regs *regs)\n+static int do_fp_load(int rn, unsigned long ea, int nb, struct pt_regs *regs)\n {\n \tint err;\n-\tu8 buf[sizeof(double)] __attribute__((aligned(sizeof(double))));\n+\tunion {\n+\t\tfloat f;\n+\t\tdouble d;\n+\t\tunsigned long l;\n+\t\tu8 b[sizeof(double)];\n+\t} u;\n \n \tif (!address_ok(regs, ea, nb))\n \t\treturn -EFAULT;\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-\treturn (*func)(rn, ea);\n+\terr = copy_mem_in(u.b, ea, nb);\n+\tif (err)\n+\t\treturn err;\n+\tpreempt_disable();\n+\tif (nb == 4)\n+\t\tconv_sp_to_dp(&u.f, &u.d);\n+\tif (regs->msr & MSR_FP)\n+\t\tput_fpr(rn, &u.d);\n+\telse\n+\t\tcurrent->thread.TS_FPR(rn) = u.l;\n+\tpreempt_enable();\n+\treturn 0;\n }\n NOKPROBE_SYMBOL(do_fp_load);\n \n-static int do_fp_store(int rn, int (*func)(int, unsigned long),\n-\t\t\t\t unsigned long ea, int nb,\n-\t\t\t\t struct pt_regs *regs)\n+static int do_fp_store(int rn, unsigned long ea, int nb, struct pt_regs *regs)\n {\n-\tint err;\n-\tu8 buf[sizeof(double)] __attribute__((aligned(sizeof(double))));\n+\tunion {\n+\t\tfloat f;\n+\t\tdouble d;\n+\t\tunsigned long l;\n+\t\tu8 b[sizeof(double)];\n+\t} u;\n \n \tif (!address_ok(regs, ea, nb))\n \t\treturn -EFAULT;\n-\tif ((ea & 3) == 0)\n-\t\treturn (*func)(rn, ea);\n-\terr = (*func)(rn, (unsigned long) buf);\n-\tif (!err)\n-\t\terr = copy_mem_out(buf, ea, nb);\n-\treturn err;\n+\tpreempt_disable();\n+\tif (regs->msr & MSR_FP)\n+\t\tget_fpr(rn, &u.d);\n+\telse\n+\t\tu.l = current->thread.TS_FPR(rn);\n+\tif (nb == 4)\n+\t\tconv_dp_to_sp(&u.d, &u.f);\n+\tpreempt_enable();\n+\treturn copy_mem_out(u.b, ea, nb);\n }\n NOKPROBE_SYMBOL(do_fp_store);\n #endif\n \n #ifdef CONFIG_ALTIVEC\n /* For Altivec/VMX, no need to worry about alignment */\n-static nokprobe_inline int do_vec_load(int rn, int (*func)(int, unsigned long),\n-\t\t\t\t unsigned long ea, struct pt_regs *regs)\n+static nokprobe_inline int do_vec_load(int rn, unsigned long ea,\n+\t\t\t\t int size, struct pt_regs *regs)\n {\n+\tint err;\n+\tunion {\n+\t\t__vector128 v;\n+\t\tu8 b[sizeof(__vector128)];\n+\t} u = {};\n+\n \tif (!address_ok(regs, ea & ~0xfUL, 16))\n \t\treturn -EFAULT;\n-\treturn (*func)(rn, ea);\n+\t/* align to multiple of size */\n+\tea &= ~(size - 1);\n+\terr = copy_mem_in(u.b, ea, size);\n+\tif (err)\n+\t\treturn err;\n+\n+\tpreempt_disable();\n+\tif (regs->msr & MSR_VEC)\n+\t\tput_vr(rn, &u.v);\n+\telse\n+\t\tcurrent->thread.vr_state.vr[rn] = u.v;\n+\tpreempt_enable();\n+\treturn 0;\n }\n \n-static nokprobe_inline int do_vec_store(int rn, int (*func)(int, unsigned long),\n-\t\t\t\t unsigned long ea, struct pt_regs *regs)\n+static nokprobe_inline int do_vec_store(int rn, unsigned long ea,\n+\t\t\t\t\tint size, struct pt_regs *regs)\n {\n+\tunion {\n+\t\t__vector128 v;\n+\t\tu8 b[sizeof(__vector128)];\n+\t} u;\n+\n \tif (!address_ok(regs, ea & ~0xfUL, 16))\n \t\treturn -EFAULT;\n-\treturn (*func)(rn, ea);\n+\t/* align to multiple of size */\n+\tea &= ~(size - 1);\n+\n+\tpreempt_disable();\n+\tif (regs->msr & MSR_VEC)\n+\t\tget_vr(rn, &u.v);\n+\telse\n+\t\tu.v = current->thread.vr_state.vr[rn];\n+\tpreempt_enable();\n+\treturn copy_mem_out(u.b, ea, size);\n }\n #endif /* CONFIG_ALTIVEC */\n \n@@ -658,6 +701,68 @@ void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,\n }\n EXPORT_SYMBOL_GPL(emulate_vsx_store);\n NOKPROBE_SYMBOL(emulate_vsx_store);\n+\n+static nokprobe_inline int do_vsx_load(struct instruction_op *op,\n+\t\t\t\t unsigned long ea, struct pt_regs *regs)\n+{\n+\tint reg = op->reg;\n+\tu8 mem[16];\n+\tunion vsx_reg buf;\n+\tint size = GETSIZE(op->type);\n+\n+\tif (!address_ok(regs, ea, size) || copy_mem_in(mem, ea, size))\n+\t\treturn -EFAULT;\n+\n+\temulate_vsx_load(op, &buf, mem);\n+\tpreempt_disable();\n+\tif (reg < 32) {\n+\t\t/* FP regs + extensions */\n+\t\tif (regs->msr & MSR_FP) {\n+\t\t\tload_vsrn(reg, &buf);\n+\t\t} else {\n+\t\t\tcurrent->thread.fp_state.fpr[reg][0] = buf.d[0];\n+\t\t\tcurrent->thread.fp_state.fpr[reg][1] = buf.d[1];\n+\t\t}\n+\t} else {\n+\t\tif (regs->msr & MSR_VEC)\n+\t\t\tload_vsrn(reg, &buf);\n+\t\telse\n+\t\t\tcurrent->thread.vr_state.vr[reg - 32] = buf.v;\n+\t}\n+\tpreempt_enable();\n+\treturn 0;\n+}\n+\n+static nokprobe_inline int do_vsx_store(struct instruction_op *op,\n+\t\t\t\t\tunsigned long ea, struct pt_regs *regs)\n+{\n+\tint reg = op->reg;\n+\tu8 mem[16];\n+\tunion vsx_reg buf;\n+\tint size = GETSIZE(op->type);\n+\n+\tif (!address_ok(regs, ea, size))\n+\t\treturn -EFAULT;\n+\n+\tpreempt_disable();\n+\tif (reg < 32) {\n+\t\t/* FP regs + extensions */\n+\t\tif (regs->msr & MSR_FP) {\n+\t\t\tstore_vsrn(reg, &buf);\n+\t\t} else {\n+\t\t\tbuf.d[0] = current->thread.fp_state.fpr[reg][0];\n+\t\t\tbuf.d[1] = current->thread.fp_state.fpr[reg][1];\n+\t\t}\n+\t} else {\n+\t\tif (regs->msr & MSR_VEC)\n+\t\t\tstore_vsrn(reg, &buf);\n+\t\telse\n+\t\t\tbuf.v = current->thread.vr_state.vr[reg - 32];\n+\t}\n+\tpreempt_enable();\n+\temulate_vsx_store(op, &buf, mem);\n+\treturn copy_mem_out(mem, ea, size);\n+}\n #endif /* CONFIG_VSX */\n \n #define __put_user_asmx(x, addr, err, op, cr)\t\t\\\n@@ -2524,25 +2629,26 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \n #ifdef CONFIG_PPC_FPU\n \tcase LOAD_FP:\n-\t\tif (!(regs->msr & MSR_FP))\n+\t\t/*\n+\t\t * If the instruction is in userspace, we can emulate it even\n+\t\t * if the VMX state is not live, because we have the state\n+\t\t * stored in the thread_struct. If the instruction is in\n+\t\t * the kernel, we must not touch the state in the thread_struct.\n+\t\t */\n+\t\tif (!(regs->msr & MSR_PR) && !(regs->msr & MSR_FP))\n \t\t\treturn 0;\n-\t\tif (size == 4)\n-\t\t\terr = do_fp_load(op.reg, do_lfs, ea, size, regs);\n-\t\telse\n-\t\t\terr = do_fp_load(op.reg, do_lfd, ea, size, regs);\n+\t\terr = do_fp_load(op.reg, ea, size, regs);\n \t\tgoto ldst_done;\n #endif\n #ifdef CONFIG_ALTIVEC\n \tcase LOAD_VMX:\n-\t\tif (!(regs->msr & MSR_VEC))\n+\t\tif (!(regs->msr & MSR_PR) && !(regs->msr & MSR_VEC))\n \t\t\treturn 0;\n-\t\terr = do_vec_load(op.reg, do_lvx, ea, regs);\n+\t\terr = do_vec_load(op.reg, ea, size, regs);\n \t\tgoto ldst_done;\n #endif\n #ifdef CONFIG_VSX\n \tcase LOAD_VSX: {\n-\t\tu8 mem[16];\n-\t\tunion vsx_reg buf;\n \t\tunsigned long msrbit = MSR_VSX;\n \n \t\t/*\n@@ -2551,14 +2657,9 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \t\t */\n \t\tif (op.reg >= 32 && (op.vsx_flags & VSX_CHECK_VEC))\n \t\t\tmsrbit = MSR_VEC;\n-\t\tif (!(regs->msr & msrbit))\n+\t\tif (!(regs->msr & MSR_PR) && !(regs->msr & msrbit))\n \t\t\treturn 0;\n-\t\tif (!address_ok(regs, 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-\t\tload_vsrn(op.reg, &buf);\n+\t\terr = do_vsx_load(&op, ea, regs);\n \t\tgoto ldst_done;\n \t}\n #endif\n@@ -2599,25 +2700,20 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \n #ifdef CONFIG_PPC_FPU\n \tcase STORE_FP:\n-\t\tif (!(regs->msr & MSR_FP))\n+\t\tif (!(regs->msr & MSR_PR) && !(regs->msr & MSR_FP))\n \t\t\treturn 0;\n-\t\tif (size == 4)\n-\t\t\terr = do_fp_store(op.reg, do_stfs, ea, size, regs);\n-\t\telse\n-\t\t\terr = do_fp_store(op.reg, do_stfd, ea, size, regs);\n+\t\terr = do_fp_store(op.reg, ea, size, regs);\n \t\tgoto ldst_done;\n #endif\n #ifdef CONFIG_ALTIVEC\n \tcase STORE_VMX:\n-\t\tif (!(regs->msr & MSR_VEC))\n+\t\tif (!(regs->msr & MSR_PR) && !(regs->msr & MSR_VEC))\n \t\t\treturn 0;\n-\t\terr = do_vec_store(op.reg, do_stvx, ea, regs);\n+\t\terr = do_vec_store(op.reg, ea, size, regs);\n \t\tgoto ldst_done;\n #endif\n #ifdef CONFIG_VSX\n \tcase STORE_VSX: {\n-\t\tu8 mem[16];\n-\t\tunion vsx_reg buf;\n \t\tunsigned long msrbit = MSR_VSX;\n \n \t\t/*\n@@ -2626,15 +2722,9 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)\n \t\t */\n \t\tif (op.reg >= 32 && (op.vsx_flags & VSX_CHECK_VEC))\n \t\t\tmsrbit = MSR_VEC;\n-\t\tif (!(regs->msr & msrbit))\n-\t\t\treturn 0;\n-\t\tif (!address_ok(regs, ea, size))\n-\t\t\treturn 0;\n-\n-\t\tstore_vsrn(op.reg, &buf);\n-\t\temulate_vsx_store(&op, &buf, mem);\n-\t\tif (copy_mem_out(mem, ea, size))\n+\t\tif (!(regs->msr & MSR_PR) && !(regs->msr & msrbit))\n \t\t\treturn 0;\n+\t\terr = do_vsx_store(&op, ea, regs);\n \t\tgoto ldst_done;\n \t}\n #endif\n", "prefixes": [ "v3", "10/17" ] }