Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/807413/?format=api
{ "id": 807413, "url": "http://patchwork.ozlabs.org/api/patches/807413/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/1504066360-30128-18-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-18-git-send-email-paulus@ozlabs.org>", "list_archive_url": "https://lore.kernel.org/linuxppc-dev/1504066360-30128-18-git-send-email-paulus@ozlabs.org/", "date": "2017-08-30T04:12:40", "name": "[v3,17/17] powerpc: Use instruction emulation infrastructure to handle alignment faults", "commit_ref": "31bfdb036f1281831db2532178f0da41f4dc9bed", "pull_url": null, "state": "accepted", "archived": false, "hash": "394aa83d5c229c22c21bd9015e39bd8408e82363", "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-18-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/807413/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/807413/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 3xhtJ05DK3z9sN7\n\tfor <patchwork-incoming@ozlabs.org>;\n\tWed, 30 Aug 2017 14:46:24 +1000 (AEST)", "from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3xhtJ0405lzDqLw\n\tfor <patchwork-incoming@ozlabs.org>;\n\tWed, 30 Aug 2017 14:46:24 +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 3xhsYL3w3rzDqGG\n\tfor <linuxppc-dev@lists.ozlabs.org>;\n\tWed, 30 Aug 2017 14:12:54 +1000 (AEST)", "by ozlabs.org (Postfix)\n\tid 3xhsYL32F5z9sNc; Wed, 30 Aug 2017 14:12:54 +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 3xhsYK6V1Kz9sPt\n\tfor <linuxppc-dev@ozlabs.org>; Wed, 30 Aug 2017 14:12:53 +1000 (AEST)" ], "Authentication-Results": [ "ozlabs.org; dkim=pass (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"kFq+5yjS\";\n\tdkim-atps=neutral", "lists.ozlabs.org; dkim=pass (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"kFq+5yjS\";\n\tdkim-atps=neutral", "lists.ozlabs.org; dkim=pass (2048-bit key;\n\tsecure) header.d=ozlabs.org header.i=@ozlabs.org header.b=\"kFq+5yjS\"; \n\tdkim-atps=neutral" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ozlabs.org; s=201707; \n\tt=1504066373; bh=n2bQg7NPXJ4sncFykAwYIS470nOAhowRQ1/koViqzYE=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=kFq+5yjS66kAsGuMhmDpq5mWoDSVA8CMQ7jelhDsgmkT4YS6rWBkvj3uwbFdq3uix\n\t426pBCx/8t/ekCsiuBMTdmjcH9jC/NhGV9MckCd8lrpfD6remw6rj2OGE7PUZ/EYQW\n\tIvzkMYsjZn0JYYI4Sl9rLf7HjkeV60A/5KIHOKLaj1vnBDVqiKhAjZ9fmA3SDZcKuT\n\tvzDAVwk29kQAjOXF/G+Fkh9Zb8HfoU0nnvqckqmqIutMrw3YiIXRi9MxB6iZCzyoAL\n\tXO+paI5HN1a+Xt8hS7rfJPM5bWGRhUjIGrdEKF/S6Kmnqt90KpLb+L/oGWbSLyiLhM\n\tm58gHWrjBjhOA==", "From": "Paul Mackerras <paulus@ozlabs.org>", "To": "linuxppc-dev@ozlabs.org", "Subject": "[PATCH v3 17/17] powerpc: Use instruction emulation infrastructure\n\tto handle alignment faults", "Date": "Wed, 30 Aug 2017 14:12:40 +1000", "Message-Id": "<1504066360-30128-18-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": "This replaces almost all of the instruction emulation code in\nfix_alignment() with calls to analyse_instr(), emulate_loadstore()\nand emulate_dcbz(). The only emulation code left is the SPE\nemulation code; analyse_instr() etc. do not handle SPE instructions\nat present.\n\nOne result of this is that we can now handle alignment faults on\nall the new VSX load and store instructions that were added in POWER9.\nVSX loads/stores will take alignment faults for unaligned accesses\nto cache-inhibited memory.\n\nAnother effect is that we no longer rely on the DAR and DSISR values\nset by the processor.\n\nWith this, we now need to include the instruction emulation code\nunconditionally.\n\nSigned-off-by: Paul Mackerras <paulus@ozlabs.org>\n---\n arch/powerpc/Kconfig | 4 -\n arch/powerpc/kernel/align.c | 774 ++------------------------------------------\n arch/powerpc/lib/Makefile | 4 +-\n 3 files changed, 34 insertions(+), 748 deletions(-)", "diff": "diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig\nindex bf6abab..9fc3c0b 100644\n--- a/arch/powerpc/Kconfig\n+++ b/arch/powerpc/Kconfig\n@@ -367,10 +367,6 @@ config PPC_ADV_DEBUG_DAC_RANGE\n \tdepends on PPC_ADV_DEBUG_REGS && 44x\n \tdefault y\n \n-config PPC_EMULATE_SSTEP\n-\tbool\n-\tdefault y if KPROBES || UPROBES || XMON || HAVE_HW_BREAKPOINT\n-\n config ZONE_DMA32\n \tbool\n \tdefault y if PPC64\ndiff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c\nindex ec7a8b0..26b9994 100644\n--- a/arch/powerpc/kernel/align.c\n+++ b/arch/powerpc/kernel/align.c\n@@ -27,6 +27,7 @@\n #include <asm/switch_to.h>\n #include <asm/disassemble.h>\n #include <asm/cpu_has_feature.h>\n+#include <asm/sstep.h>\n \n struct aligninfo {\n \tunsigned char len;\n@@ -40,364 +41,9 @@ struct aligninfo {\n #define LD\t0\t/* load */\n #define ST\t1\t/* store */\n #define SE\t2\t/* sign-extend value, or FP ld/st as word */\n-#define F\t4\t/* to/from fp regs */\n-#define U\t8\t/* update index register */\n-#define M\t0x10\t/* multiple load/store */\n #define SW\t0x20\t/* byte swap */\n-#define S\t0x40\t/* single-precision fp or... */\n-#define SX\t0x40\t/* ... byte count in XER */\n-#define HARD\t0x80\t/* string, stwcx. */\n #define E4\t0x40\t/* SPE endianness is word */\n #define E8\t0x80\t/* SPE endianness is double word */\n-#define SPLT\t0x80\t/* VSX SPLAT load */\n-\n-/* DSISR bits reported for a DCBZ instruction: */\n-#define DCBZ\t0x5f\t/* 8xx/82xx dcbz faults when cache not enabled */\n-\n-/*\n- * The PowerPC stores certain bits of the instruction that caused the\n- * alignment exception in the DSISR register. This array maps those\n- * bits to information about the operand length and what the\n- * instruction would do.\n- */\n-static struct aligninfo aligninfo[128] = {\n-\t{ 4, LD },\t\t/* 00 0 0000: lwz / lwarx */\n-\tINVALID,\t\t/* 00 0 0001 */\n-\t{ 4, ST },\t\t/* 00 0 0010: stw */\n-\tINVALID,\t\t/* 00 0 0011 */\n-\t{ 2, LD },\t\t/* 00 0 0100: lhz */\n-\t{ 2, LD+SE },\t\t/* 00 0 0101: lha */\n-\t{ 2, ST },\t\t/* 00 0 0110: sth */\n-\t{ 4, LD+M },\t\t/* 00 0 0111: lmw */\n-\t{ 4, LD+F+S },\t\t/* 00 0 1000: lfs */\n-\t{ 8, LD+F },\t\t/* 00 0 1001: lfd */\n-\t{ 4, ST+F+S },\t\t/* 00 0 1010: stfs */\n-\t{ 8, ST+F },\t\t/* 00 0 1011: stfd */\n-\t{ 16, LD },\t\t/* 00 0 1100: lq */\n-\t{ 8, LD },\t\t/* 00 0 1101: ld/ldu/lwa */\n-\tINVALID,\t\t/* 00 0 1110 */\n-\t{ 8, ST },\t\t/* 00 0 1111: std/stdu */\n-\t{ 4, LD+U },\t\t/* 00 1 0000: lwzu */\n-\tINVALID,\t\t/* 00 1 0001 */\n-\t{ 4, ST+U },\t\t/* 00 1 0010: stwu */\n-\tINVALID,\t\t/* 00 1 0011 */\n-\t{ 2, LD+U },\t\t/* 00 1 0100: lhzu */\n-\t{ 2, LD+SE+U },\t\t/* 00 1 0101: lhau */\n-\t{ 2, ST+U },\t\t/* 00 1 0110: sthu */\n-\t{ 4, ST+M },\t\t/* 00 1 0111: stmw */\n-\t{ 4, LD+F+S+U },\t/* 00 1 1000: lfsu */\n-\t{ 8, LD+F+U },\t\t/* 00 1 1001: lfdu */\n-\t{ 4, ST+F+S+U },\t/* 00 1 1010: stfsu */\n-\t{ 8, ST+F+U },\t\t/* 00 1 1011: stfdu */\n-\t{ 16, LD+F },\t\t/* 00 1 1100: lfdp */\n-\tINVALID,\t\t/* 00 1 1101 */\n-\t{ 16, ST+F },\t\t/* 00 1 1110: stfdp */\n-\tINVALID,\t\t/* 00 1 1111 */\n-\t{ 8, LD },\t\t/* 01 0 0000: ldx */\n-\tINVALID,\t\t/* 01 0 0001 */\n-\t{ 8, ST },\t\t/* 01 0 0010: stdx */\n-\tINVALID,\t\t/* 01 0 0011 */\n-\tINVALID,\t\t/* 01 0 0100 */\n-\t{ 4, LD+SE },\t\t/* 01 0 0101: lwax */\n-\tINVALID,\t\t/* 01 0 0110 */\n-\tINVALID,\t\t/* 01 0 0111 */\n-\t{ 4, LD+M+HARD+SX },\t/* 01 0 1000: lswx */\n-\t{ 4, LD+M+HARD },\t/* 01 0 1001: lswi */\n-\t{ 4, ST+M+HARD+SX },\t/* 01 0 1010: stswx */\n-\t{ 4, ST+M+HARD },\t/* 01 0 1011: stswi */\n-\tINVALID,\t\t/* 01 0 1100 */\n-\t{ 8, LD+U },\t\t/* 01 0 1101: ldu */\n-\tINVALID,\t\t/* 01 0 1110 */\n-\t{ 8, ST+U },\t\t/* 01 0 1111: stdu */\n-\t{ 8, LD+U },\t\t/* 01 1 0000: ldux */\n-\tINVALID,\t\t/* 01 1 0001 */\n-\t{ 8, ST+U },\t\t/* 01 1 0010: stdux */\n-\tINVALID,\t\t/* 01 1 0011 */\n-\tINVALID,\t\t/* 01 1 0100 */\n-\t{ 4, LD+SE+U },\t\t/* 01 1 0101: lwaux */\n-\tINVALID,\t\t/* 01 1 0110 */\n-\tINVALID,\t\t/* 01 1 0111 */\n-\tINVALID,\t\t/* 01 1 1000 */\n-\tINVALID,\t\t/* 01 1 1001 */\n-\tINVALID,\t\t/* 01 1 1010 */\n-\tINVALID,\t\t/* 01 1 1011 */\n-\tINVALID,\t\t/* 01 1 1100 */\n-\tINVALID,\t\t/* 01 1 1101 */\n-\tINVALID,\t\t/* 01 1 1110 */\n-\tINVALID,\t\t/* 01 1 1111 */\n-\tINVALID,\t\t/* 10 0 0000 */\n-\tINVALID,\t\t/* 10 0 0001 */\n-\tINVALID,\t\t/* 10 0 0010: stwcx. */\n-\tINVALID,\t\t/* 10 0 0011 */\n-\tINVALID,\t\t/* 10 0 0100 */\n-\tINVALID,\t\t/* 10 0 0101 */\n-\tINVALID,\t\t/* 10 0 0110 */\n-\tINVALID,\t\t/* 10 0 0111 */\n-\t{ 4, LD+SW },\t\t/* 10 0 1000: lwbrx */\n-\tINVALID,\t\t/* 10 0 1001 */\n-\t{ 4, ST+SW },\t\t/* 10 0 1010: stwbrx */\n-\tINVALID,\t\t/* 10 0 1011 */\n-\t{ 2, LD+SW },\t\t/* 10 0 1100: lhbrx */\n-\t{ 4, LD+SE },\t\t/* 10 0 1101 lwa */\n-\t{ 2, ST+SW },\t\t/* 10 0 1110: sthbrx */\n-\t{ 16, ST },\t\t/* 10 0 1111: stq */\n-\tINVALID,\t\t/* 10 1 0000 */\n-\tINVALID,\t\t/* 10 1 0001 */\n-\tINVALID,\t\t/* 10 1 0010 */\n-\tINVALID,\t\t/* 10 1 0011 */\n-\tINVALID,\t\t/* 10 1 0100 */\n-\tINVALID,\t\t/* 10 1 0101 */\n-\tINVALID,\t\t/* 10 1 0110 */\n-\tINVALID,\t\t/* 10 1 0111 */\n-\tINVALID,\t\t/* 10 1 1000 */\n-\tINVALID,\t\t/* 10 1 1001 */\n-\tINVALID,\t\t/* 10 1 1010 */\n-\tINVALID,\t\t/* 10 1 1011 */\n-\tINVALID,\t\t/* 10 1 1100 */\n-\tINVALID,\t\t/* 10 1 1101 */\n-\tINVALID,\t\t/* 10 1 1110 */\n-\t{ 0, ST+HARD },\t\t/* 10 1 1111: dcbz */\n-\t{ 4, LD },\t\t/* 11 0 0000: lwzx */\n-\tINVALID,\t\t/* 11 0 0001 */\n-\t{ 4, ST },\t\t/* 11 0 0010: stwx */\n-\tINVALID,\t\t/* 11 0 0011 */\n-\t{ 2, LD },\t\t/* 11 0 0100: lhzx */\n-\t{ 2, LD+SE },\t\t/* 11 0 0101: lhax */\n-\t{ 2, ST },\t\t/* 11 0 0110: sthx */\n-\tINVALID,\t\t/* 11 0 0111 */\n-\t{ 4, LD+F+S },\t\t/* 11 0 1000: lfsx */\n-\t{ 8, LD+F },\t\t/* 11 0 1001: lfdx */\n-\t{ 4, ST+F+S },\t\t/* 11 0 1010: stfsx */\n-\t{ 8, ST+F },\t\t/* 11 0 1011: stfdx */\n-\t{ 16, LD+F },\t\t/* 11 0 1100: lfdpx */\n-\t{ 4, LD+F+SE },\t\t/* 11 0 1101: lfiwax */\n-\t{ 16, ST+F },\t\t/* 11 0 1110: stfdpx */\n-\t{ 4, ST+F },\t\t/* 11 0 1111: stfiwx */\n-\t{ 4, LD+U },\t\t/* 11 1 0000: lwzux */\n-\tINVALID,\t\t/* 11 1 0001 */\n-\t{ 4, ST+U },\t\t/* 11 1 0010: stwux */\n-\tINVALID,\t\t/* 11 1 0011 */\n-\t{ 2, LD+U },\t\t/* 11 1 0100: lhzux */\n-\t{ 2, LD+SE+U },\t\t/* 11 1 0101: lhaux */\n-\t{ 2, ST+U },\t\t/* 11 1 0110: sthux */\n-\tINVALID,\t\t/* 11 1 0111 */\n-\t{ 4, LD+F+S+U },\t/* 11 1 1000: lfsux */\n-\t{ 8, LD+F+U },\t\t/* 11 1 1001: lfdux */\n-\t{ 4, ST+F+S+U },\t/* 11 1 1010: stfsux */\n-\t{ 8, ST+F+U },\t\t/* 11 1 1011: stfdux */\n-\tINVALID,\t\t/* 11 1 1100 */\n-\t{ 4, LD+F },\t\t/* 11 1 1101: lfiwzx */\n-\tINVALID,\t\t/* 11 1 1110 */\n-\tINVALID,\t\t/* 11 1 1111 */\n-};\n-\n-/*\n- * The dcbz (data cache block zero) instruction\n- * gives an alignment fault if used on non-cacheable\n- * memory. We handle the fault mainly for the\n- * case when we are running with the cache disabled\n- * for debugging.\n- */\n-static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr)\n-{\n-\tlong __user *p;\n-\tint i, size;\n-\n-#ifdef __powerpc64__\n-\tsize = ppc64_caches.l1d.block_size;\n-#else\n-\tsize = L1_CACHE_BYTES;\n-#endif\n-\tp = (long __user *) (regs->dar & -size);\n-\tif (user_mode(regs) && !access_ok(VERIFY_WRITE, p, size))\n-\t\treturn -EFAULT;\n-\tfor (i = 0; i < size / sizeof(long); ++i)\n-\t\tif (__put_user_inatomic(0, p+i))\n-\t\t\treturn -EFAULT;\n-\treturn 1;\n-}\n-\n-/*\n- * Emulate load & store multiple instructions\n- * On 64-bit machines, these instructions only affect/use the\n- * bottom 4 bytes of each register, and the loads clear the\n- * top 4 bytes of the affected register.\n- */\n-#ifdef __BIG_ENDIAN__\n-#ifdef CONFIG_PPC64\n-#define REG_BYTE(rp, i)\t\t*((u8 *)((rp) + ((i) >> 2)) + ((i) & 3) + 4)\n-#else\n-#define REG_BYTE(rp, i)\t\t*((u8 *)(rp) + (i))\n-#endif\n-#else\n-#define REG_BYTE(rp, i)\t\t(*(((u8 *)((rp) + ((i)>>2)) + ((i)&3))))\n-#endif\n-\n-#define SWIZ_PTR(p)\t\t((unsigned char __user *)((p) ^ swiz))\n-\n-static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,\n-\t\t\t unsigned int reg, unsigned int nb,\n-\t\t\t unsigned int flags, unsigned int instr,\n-\t\t\t unsigned long swiz)\n-{\n-\tunsigned long *rptr;\n-\tunsigned int nb0, i, bswiz;\n-\tunsigned long p;\n-\n-\t/*\n-\t * We do not try to emulate 8 bytes multiple as they aren't really\n-\t * available in our operating environments and we don't try to\n-\t * emulate multiples operations in kernel land as they should never\n-\t * be used/generated there at least not on unaligned boundaries\n-\t */\n-\tif (unlikely((nb > 4) || !user_mode(regs)))\n-\t\treturn 0;\n-\n-\t/* lmw, stmw, lswi/x, stswi/x */\n-\tnb0 = 0;\n-\tif (flags & HARD) {\n-\t\tif (flags & SX) {\n-\t\t\tnb = regs->xer & 127;\n-\t\t\tif (nb == 0)\n-\t\t\t\treturn 1;\n-\t\t} else {\n-\t\t\tunsigned long pc = regs->nip ^ (swiz & 4);\n-\n-\t\t\tif (__get_user_inatomic(instr,\n-\t\t\t\t\t\t(unsigned int __user *)pc))\n-\t\t\t\treturn -EFAULT;\n-\t\t\tif (swiz == 0 && (flags & SW))\n-\t\t\t\tinstr = cpu_to_le32(instr);\n-\t\t\tnb = (instr >> 11) & 0x1f;\n-\t\t\tif (nb == 0)\n-\t\t\t\tnb = 32;\n-\t\t}\n-\t\tif (nb + reg * 4 > 128) {\n-\t\t\tnb0 = nb + reg * 4 - 128;\n-\t\t\tnb = 128 - reg * 4;\n-\t\t}\n-#ifdef __LITTLE_ENDIAN__\n-\t\t/*\n-\t\t * String instructions are endian neutral but the code\n-\t\t * below is not. Force byte swapping on so that the\n-\t\t * effects of swizzling are undone in the load/store\n-\t\t * loops below.\n-\t\t */\n-\t\tflags ^= SW;\n-#endif\n-\t} else {\n-\t\t/* lwm, stmw */\n-\t\tnb = (32 - reg) * 4;\n-\t}\n-\n-\tif (!access_ok((flags & ST ? VERIFY_WRITE: VERIFY_READ), addr, nb+nb0))\n-\t\treturn -EFAULT;\t/* bad address */\n-\n-\trptr = ®s->gpr[reg];\n-\tp = (unsigned long) addr;\n-\tbswiz = (flags & SW)? 3: 0;\n-\n-\tif (!(flags & ST)) {\n-\t\t/*\n-\t\t * This zeroes the top 4 bytes of the affected registers\n-\t\t * in 64-bit mode, and also zeroes out any remaining\n-\t\t * bytes of the last register for lsw*.\n-\t\t */\n-\t\tmemset(rptr, 0, ((nb + 3) / 4) * sizeof(unsigned long));\n-\t\tif (nb0 > 0)\n-\t\t\tmemset(®s->gpr[0], 0,\n-\t\t\t ((nb0 + 3) / 4) * sizeof(unsigned long));\n-\n-\t\tfor (i = 0; i < nb; ++i, ++p)\n-\t\t\tif (__get_user_inatomic(REG_BYTE(rptr, i ^ bswiz),\n-\t\t\t\t\t\tSWIZ_PTR(p)))\n-\t\t\t\treturn -EFAULT;\n-\t\tif (nb0 > 0) {\n-\t\t\trptr = ®s->gpr[0];\n-\t\t\taddr += nb;\n-\t\t\tfor (i = 0; i < nb0; ++i, ++p)\n-\t\t\t\tif (__get_user_inatomic(REG_BYTE(rptr,\n-\t\t\t\t\t\t\t\t i ^ bswiz),\n-\t\t\t\t\t\t\tSWIZ_PTR(p)))\n-\t\t\t\t\treturn -EFAULT;\n-\t\t}\n-\n-\t} else {\n-\t\tfor (i = 0; i < nb; ++i, ++p)\n-\t\t\tif (__put_user_inatomic(REG_BYTE(rptr, i ^ bswiz),\n-\t\t\t\t\t\tSWIZ_PTR(p)))\n-\t\t\t\treturn -EFAULT;\n-\t\tif (nb0 > 0) {\n-\t\t\trptr = ®s->gpr[0];\n-\t\t\taddr += nb;\n-\t\t\tfor (i = 0; i < nb0; ++i, ++p)\n-\t\t\t\tif (__put_user_inatomic(REG_BYTE(rptr,\n-\t\t\t\t\t\t\t\t i ^ bswiz),\n-\t\t\t\t\t\t\tSWIZ_PTR(p)))\n-\t\t\t\t\treturn -EFAULT;\n-\t\t}\n-\t}\n-\treturn 1;\n-}\n-\n-/*\n- * Emulate floating-point pair loads and stores.\n- * Only POWER6 has these instructions, and it does true little-endian,\n- * so we don't need the address swizzling.\n- */\n-static int emulate_fp_pair(unsigned char __user *addr, unsigned int reg,\n-\t\t\t unsigned int flags)\n-{\n-\tchar *ptr0 = (char *) ¤t->thread.TS_FPR(reg);\n-\tchar *ptr1 = (char *) ¤t->thread.TS_FPR(reg+1);\n-\tint i, ret, sw = 0;\n-\n-\tif (reg & 1)\n-\t\treturn 0;\t/* invalid form: FRS/FRT must be even */\n-\tif (flags & SW)\n-\t\tsw = 7;\n-\tret = 0;\n-\tfor (i = 0; i < 8; ++i) {\n-\t\tif (!(flags & ST)) {\n-\t\t\tret |= __get_user(ptr0[i^sw], addr + i);\n-\t\t\tret |= __get_user(ptr1[i^sw], addr + i + 8);\n-\t\t} else {\n-\t\t\tret |= __put_user(ptr0[i^sw], addr + i);\n-\t\t\tret |= __put_user(ptr1[i^sw], addr + i + 8);\n-\t\t}\n-\t}\n-\tif (ret)\n-\t\treturn -EFAULT;\n-\treturn 1;\t/* exception handled and fixed up */\n-}\n-\n-#ifdef CONFIG_PPC64\n-static int emulate_lq_stq(struct pt_regs *regs, unsigned char __user *addr,\n-\t\t\t unsigned int reg, unsigned int flags)\n-{\n-\tchar *ptr0 = (char *)®s->gpr[reg];\n-\tchar *ptr1 = (char *)®s->gpr[reg+1];\n-\tint i, ret, sw = 0;\n-\n-\tif (reg & 1)\n-\t\treturn 0;\t/* invalid form: GPR must be even */\n-\tif (flags & SW)\n-\t\tsw = 7;\n-\tret = 0;\n-\tfor (i = 0; i < 8; ++i) {\n-\t\tif (!(flags & ST)) {\n-\t\t\tret |= __get_user(ptr0[i^sw], addr + i);\n-\t\t\tret |= __get_user(ptr1[i^sw], addr + i + 8);\n-\t\t} else {\n-\t\t\tret |= __put_user(ptr0[i^sw], addr + i);\n-\t\t\tret |= __put_user(ptr1[i^sw], addr + i + 8);\n-\t\t}\n-\t}\n-\tif (ret)\n-\t\treturn -EFAULT;\n-\treturn 1;\t/* exception handled and fixed up */\n-}\n-#endif /* CONFIG_PPC64 */\n \n #ifdef CONFIG_SPE\n \n@@ -636,133 +282,21 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg,\n }\n #endif /* CONFIG_SPE */\n \n-#ifdef CONFIG_VSX\n-/*\n- * Emulate VSX instructions...\n- */\n-static int emulate_vsx(unsigned char __user *addr, unsigned int reg,\n-\t\t unsigned int areg, struct pt_regs *regs,\n-\t\t unsigned int flags, unsigned int length,\n-\t\t unsigned int elsize)\n-{\n-\tchar *ptr;\n-\tunsigned long *lptr;\n-\tint ret = 0;\n-\tint sw = 0;\n-\tint i, j;\n-\n-\t/* userland only */\n-\tif (unlikely(!user_mode(regs)))\n-\t\treturn 0;\n-\n-\tflush_vsx_to_thread(current);\n-\n-\tif (reg < 32)\n-\t\tptr = (char *) ¤t->thread.fp_state.fpr[reg][0];\n-\telse\n-\t\tptr = (char *) ¤t->thread.vr_state.vr[reg - 32];\n-\n-\tlptr = (unsigned long *) ptr;\n-\n-#ifdef __LITTLE_ENDIAN__\n-\tif (flags & SW) {\n-\t\telsize = length;\n-\t\tsw = length-1;\n-\t} else {\n-\t\t/*\n-\t\t * The elements are BE ordered, even in LE mode, so process\n-\t\t * them in reverse order.\n-\t\t */\n-\t\taddr += length - elsize;\n-\n-\t\t/* 8 byte memory accesses go in the top 8 bytes of the VR */\n-\t\tif (length == 8)\n-\t\t\tptr += 8;\n-\t}\n-#else\n-\tif (flags & SW)\n-\t\tsw = elsize-1;\n-#endif\n-\n-\tfor (j = 0; j < length; j += elsize) {\n-\t\tfor (i = 0; i < elsize; ++i) {\n-\t\t\tif (flags & ST)\n-\t\t\t\tret |= __put_user(ptr[i^sw], addr + i);\n-\t\t\telse\n-\t\t\t\tret |= __get_user(ptr[i^sw], addr + i);\n-\t\t}\n-\t\tptr += elsize;\n-#ifdef __LITTLE_ENDIAN__\n-\t\taddr -= elsize;\n-#else\n-\t\taddr += elsize;\n-#endif\n-\t}\n-\n-#ifdef __BIG_ENDIAN__\n-#define VSX_HI 0\n-#define VSX_LO 1\n-#else\n-#define VSX_HI 1\n-#define VSX_LO 0\n-#endif\n-\n-\tif (!ret) {\n-\t\tif (flags & U)\n-\t\t\tregs->gpr[areg] = regs->dar;\n-\n-\t\t/* Splat load copies the same data to top and bottom 8 bytes */\n-\t\tif (flags & SPLT)\n-\t\t\tlptr[VSX_LO] = lptr[VSX_HI];\n-\t\t/* For 8 byte loads, zero the low 8 bytes */\n-\t\telse if (!(flags & ST) && (8 == length))\n-\t\t\tlptr[VSX_LO] = 0;\n-\t} else\n-\t\treturn -EFAULT;\n-\n-\treturn 1;\n-}\n-#endif\n-\n /*\n * Called on alignment exception. Attempts to fixup\n *\n * Return 1 on success\n * Return 0 if unable to handle the interrupt\n * Return -EFAULT if data address is bad\n+ * Other negative return values indicate that the instruction can't\n+ * be emulated, and the process should be given a SIGBUS.\n */\n \n int fix_alignment(struct pt_regs *regs)\n {\n-\tunsigned int instr, nb, flags, instruction = 0;\n-\tunsigned int reg, areg;\n-\tunsigned int dsisr;\n-\tunsigned char __user *addr;\n-\tunsigned long p, swiz;\n-\tint ret, i;\n-\tunion data {\n-\t\tu64 ll;\n-\t\tdouble dd;\n-\t\tunsigned char v[8];\n-\t\tstruct {\n-#ifdef __LITTLE_ENDIAN__\n-\t\t\tint\t low32;\n-\t\t\tunsigned hi32;\n-#else\n-\t\t\tunsigned hi32;\n-\t\t\tint\t low32;\n-#endif\n-\t\t} x32;\n-\t\tstruct {\n-#ifdef __LITTLE_ENDIAN__\n-\t\t\tshort\t low16;\n-\t\t\tunsigned char hi48[6];\n-#else\n-\t\t\tunsigned char hi48[6];\n-\t\t\tshort\t low16;\n-#endif\n-\t\t} x16;\n-\t} data;\n+\tunsigned int instr;\n+\tstruct instruction_op op;\n+\tint r, type;\n \n \t/*\n \t * We require a complete register set, if not, then our assembly\n@@ -770,121 +304,23 @@ int fix_alignment(struct pt_regs *regs)\n \t */\n \tCHECK_FULL_REGS(regs);\n \n-\tdsisr = regs->dsisr;\n-\n-\t/* Some processors don't provide us with a DSISR we can use here,\n-\t * let's make one up from the instruction\n-\t */\n-\tif (cpu_has_feature(CPU_FTR_NODSISRALIGN)) {\n-\t\tunsigned long pc = regs->nip;\n-\n-\t\tif (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE))\n-\t\t\tpc ^= 4;\n-\t\tif (unlikely(__get_user_inatomic(instr,\n-\t\t\t\t\t\t (unsigned int __user *)pc)))\n-\t\t\treturn -EFAULT;\n-\t\tif (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE))\n-\t\t\tinstr = cpu_to_le32(instr);\n-\t\tdsisr = make_dsisr(instr);\n-\t\tinstruction = instr;\n+\tif (unlikely(__get_user(instr, (unsigned int __user *)regs->nip)))\n+\t\treturn -EFAULT;\n+\tif ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) {\n+\t\t/* We don't handle PPC little-endian any more... */\n+\t\tif (cpu_has_feature(CPU_FTR_PPC_LE))\n+\t\t\treturn -EIO;\n+\t\tinstr = swab32(instr);\n \t}\n \n-\t/* extract the operation and registers from the dsisr */\n-\treg = (dsisr >> 5) & 0x1f;\t/* source/dest register */\n-\tareg = dsisr & 0x1f;\t\t/* register to update */\n-\n #ifdef CONFIG_SPE\n \tif ((instr >> 26) == 0x4) {\n+\t\tint reg = (instr >> 21) & 0x1f;\n \t\tPPC_WARN_ALIGNMENT(spe, regs);\n \t\treturn emulate_spe(regs, reg, instr);\n \t}\n #endif\n \n-\tinstr = (dsisr >> 10) & 0x7f;\n-\tinstr |= (dsisr >> 13) & 0x60;\n-\n-\t/* Lookup the operation in our table */\n-\tnb = aligninfo[instr].len;\n-\tflags = aligninfo[instr].flags;\n-\n-\t/*\n-\t * Handle some cases which give overlaps in the DSISR values.\n-\t */\n-\tif (IS_XFORM(instruction)) {\n-\t\tswitch (get_xop(instruction)) {\n-\t\tcase 532:\t/* ldbrx */\n-\t\t\tnb = 8;\n-\t\t\tflags = LD+SW;\n-\t\t\tbreak;\n-\t\tcase 660:\t/* stdbrx */\n-\t\t\tnb = 8;\n-\t\t\tflags = ST+SW;\n-\t\t\tbreak;\n-\t\tcase 20:\t/* lwarx */\n-\t\tcase 84:\t/* ldarx */\n-\t\tcase 116:\t/* lharx */\n-\t\tcase 276:\t/* lqarx */\n-\t\t\treturn 0;\t/* not emulated ever */\n-\t\t}\n-\t}\n-\n-\t/* Byteswap little endian loads and stores */\n-\tswiz = 0;\n-\tif ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) {\n-\t\tflags ^= SW;\n-#ifdef __BIG_ENDIAN__\n-\t\t/*\n-\t\t * So-called \"PowerPC little endian\" mode works by\n-\t\t * swizzling addresses rather than by actually doing\n-\t\t * any byte-swapping. To emulate this, we XOR each\n-\t\t * byte address with 7. We also byte-swap, because\n-\t\t * the processor's address swizzling depends on the\n-\t\t * operand size (it xors the address with 7 for bytes,\n-\t\t * 6 for halfwords, 4 for words, 0 for doublewords) but\n-\t\t * we will xor with 7 and load/store each byte separately.\n-\t\t */\n-\t\tif (cpu_has_feature(CPU_FTR_PPC_LE))\n-\t\t\tswiz = 7;\n-#endif\n-\t}\n-\n-\t/* DAR has the operand effective address */\n-\taddr = (unsigned char __user *)regs->dar;\n-\n-#ifdef CONFIG_VSX\n-\tif ((instruction & 0xfc00003e) == 0x7c000018) {\n-\t\tunsigned int elsize;\n-\n-\t\t/* Additional register addressing bit (64 VSX vs 32 FPR/GPR) */\n-\t\treg |= (instruction & 0x1) << 5;\n-\t\t/* Simple inline decoder instead of a table */\n-\t\t/* VSX has only 8 and 16 byte memory accesses */\n-\t\tnb = 8;\n-\t\tif (instruction & 0x200)\n-\t\t\tnb = 16;\n-\n-\t\t/* Vector stores in little-endian mode swap individual\n-\t\t elements, so process them separately */\n-\t\telsize = 4;\n-\t\tif (instruction & 0x80)\n-\t\t\telsize = 8;\n-\n-\t\tflags = 0;\n-\t\tif ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE))\n-\t\t\tflags |= SW;\n-\t\tif (instruction & 0x100)\n-\t\t\tflags |= ST;\n-\t\tif (instruction & 0x040)\n-\t\t\tflags |= U;\n-\t\t/* splat load needs a special decoder */\n-\t\tif ((instruction & 0x400) == 0){\n-\t\t\tflags |= SPLT;\n-\t\t\tnb = 8;\n-\t\t}\n-\t\tPPC_WARN_ALIGNMENT(vsx, regs);\n-\t\treturn emulate_vsx(addr, reg, areg, regs, flags, nb, elsize);\n-\t}\n-#endif\n \n \t/*\n \t * ISA 3.0 (such as P9) copy, copy_first, paste and paste_last alignment\n@@ -896,173 +332,27 @@ int fix_alignment(struct pt_regs *regs)\n \t * when pasting to a co-processor. Furthermore, paste_last is the\n \t * synchronisation point for preceding copy/paste sequences.\n \t */\n-\tif ((instruction & 0xfc0006fe) == PPC_INST_COPY)\n+\tif ((instr & 0xfc0006fe) == PPC_INST_COPY)\n \t\treturn -EIO;\n \n-\t/* A size of 0 indicates an instruction we don't support, with\n-\t * the exception of DCBZ which is handled as a special case here\n-\t */\n-\tif (instr == DCBZ) {\n-\t\tPPC_WARN_ALIGNMENT(dcbz, regs);\n-\t\treturn emulate_dcbz(regs, addr);\n-\t}\n-\tif (unlikely(nb == 0))\n-\t\treturn 0;\n-\n-\t/* Load/Store Multiple instructions are handled in their own\n-\t * function\n-\t */\n-\tif (flags & M) {\n-\t\tPPC_WARN_ALIGNMENT(multiple, regs);\n-\t\treturn emulate_multiple(regs, addr, reg, nb,\n-\t\t\t\t\tflags, instr, swiz);\n-\t}\n-\n-\t/* Verify the address of the operand */\n-\tif (unlikely(user_mode(regs) &&\n-\t\t !access_ok((flags & ST ? VERIFY_WRITE : VERIFY_READ),\n-\t\t\t\taddr, nb)))\n-\t\treturn -EFAULT;\n-\n-\t/* Force the fprs into the save area so we can reference them */\n-\tif (flags & F) {\n-\t\t/* userland only */\n-\t\tif (unlikely(!user_mode(regs)))\n-\t\t\treturn 0;\n-\t\tflush_fp_to_thread(current);\n-\t}\n+\tr = analyse_instr(&op, regs, instr);\n+\tif (r < 0)\n+\t\treturn -EINVAL;\n \n-\tif (nb == 16) {\n-\t\tif (flags & F) {\n-\t\t\t/* Special case for 16-byte FP loads and stores */\n-\t\t\tPPC_WARN_ALIGNMENT(fp_pair, regs);\n-\t\t\treturn emulate_fp_pair(addr, reg, flags);\n-\t\t} else {\n-#ifdef CONFIG_PPC64\n-\t\t\t/* Special case for 16-byte loads and stores */\n-\t\t\tPPC_WARN_ALIGNMENT(lq_stq, regs);\n-\t\t\treturn emulate_lq_stq(regs, addr, reg, flags);\n-#else\n-\t\t\treturn 0;\n-#endif\n-\t\t}\n-\t}\n-\n-\tPPC_WARN_ALIGNMENT(unaligned, regs);\n-\n-\t/* If we are loading, get the data from user space, else\n-\t * get it from register values\n-\t */\n-\tif (!(flags & ST)) {\n-\t\tunsigned int start = 0;\n-\n-\t\tswitch (nb) {\n-\t\tcase 4:\n-\t\t\tstart = offsetof(union data, x32.low32);\n-\t\t\tbreak;\n-\t\tcase 2:\n-\t\t\tstart = offsetof(union data, x16.low16);\n-\t\t\tbreak;\n-\t\t}\n-\n-\t\tdata.ll = 0;\n-\t\tret = 0;\n-\t\tp = (unsigned long)addr;\n-\n-\t\tfor (i = 0; i < nb; i++)\n-\t\t\tret |= __get_user_inatomic(data.v[start + i],\n-\t\t\t\t\t\t SWIZ_PTR(p++));\n-\n-\t\tif (unlikely(ret))\n-\t\t\treturn -EFAULT;\n-\n-\t} else if (flags & F) {\n-\t\tdata.ll = current->thread.TS_FPR(reg);\n-\t\tif (flags & S) {\n-\t\t\t/* Single-precision FP store requires conversion... */\n-#ifdef CONFIG_PPC_FPU\n-\t\t\tpreempt_disable();\n-\t\t\tenable_kernel_fp();\n-\t\t\tcvt_df(&data.dd, (float *)&data.x32.low32);\n-\t\t\tdisable_kernel_fp();\n-\t\t\tpreempt_enable();\n-#else\n-\t\t\treturn 0;\n-#endif\n-\t\t}\n-\t} else\n-\t\tdata.ll = regs->gpr[reg];\n-\n-\tif (flags & SW) {\n-\t\tswitch (nb) {\n-\t\tcase 8:\n-\t\t\tdata.ll = swab64(data.ll);\n-\t\t\tbreak;\n-\t\tcase 4:\n-\t\t\tdata.x32.low32 = swab32(data.x32.low32);\n-\t\t\tbreak;\n-\t\tcase 2:\n-\t\t\tdata.x16.low16 = swab16(data.x16.low16);\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\n-\t/* Perform other misc operations like sign extension\n-\t * or floating point single precision conversion\n-\t */\n-\tswitch (flags & ~(U|SW)) {\n-\tcase LD+SE:\t/* sign extending integer loads */\n-\tcase LD+F+SE:\t/* sign extend for lfiwax */\n-\t\tif ( nb == 2 )\n-\t\t\tdata.ll = data.x16.low16;\n-\t\telse\t/* nb must be 4 */\n-\t\t\tdata.ll = data.x32.low32;\n-\t\tbreak;\n-\n-\t/* Single-precision FP load requires conversion... */\n-\tcase LD+F+S:\n-#ifdef CONFIG_PPC_FPU\n-\t\tpreempt_disable();\n-\t\tenable_kernel_fp();\n-\t\tcvt_fd((float *)&data.x32.low32, &data.dd);\n-\t\tdisable_kernel_fp();\n-\t\tpreempt_enable();\n-#else\n-\t\treturn 0;\n-#endif\n-\t\tbreak;\n+\ttype = op.type & INSTR_TYPE_MASK;\n+\tif (!OP_IS_LOAD_STORE(type)) {\n+\t\tif (type != CACHEOP + DCBZ)\n+\t\t\treturn -EINVAL;\n+\t\tPPC_WARN_ALIGNMENT(dcbz, regs);\n+\t\tr = emulate_dcbz(op.ea, regs);\n+\t} else {\n+\t\tif (type == LARX || type == STCX)\n+\t\t\treturn -EIO;\n+\t\tPPC_WARN_ALIGNMENT(unaligned, regs);\n+\t\tr = emulate_loadstore(regs, &op);\n \t}\n \n-\t/* Store result to memory or update registers */\n-\tif (flags & ST) {\n-\t\tunsigned int start = 0;\n-\n-\t\tswitch (nb) {\n-\t\tcase 4:\n-\t\t\tstart = offsetof(union data, x32.low32);\n-\t\t\tbreak;\n-\t\tcase 2:\n-\t\t\tstart = offsetof(union data, x16.low16);\n-\t\t\tbreak;\n-\t\t}\n-\n-\t\tret = 0;\n-\t\tp = (unsigned long)addr;\n-\n-\t\tfor (i = 0; i < nb; i++)\n-\t\t\tret |= __put_user_inatomic(data.v[start + i],\n-\t\t\t\t\t\t SWIZ_PTR(p++));\n-\n-\t\tif (unlikely(ret))\n-\t\t\treturn -EFAULT;\n-\t} else if (flags & F)\n-\t\tcurrent->thread.TS_FPR(reg) = data.ll;\n-\telse\n-\t\tregs->gpr[reg] = data.ll;\n-\n-\t/* Update RA as needed */\n-\tif (flags & U)\n-\t\tregs->gpr[areg] = regs->dar;\n-\n-\treturn 1;\n+\tif (!r)\n+\t\treturn 1;\n+\treturn r;\n }\ndiff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile\nindex 400778d..50d5bf9 100644\n--- a/arch/powerpc/lib/Makefile\n+++ b/arch/powerpc/lib/Makefile\n@@ -31,8 +31,8 @@ obj64-$(CONFIG_KPROBES_SANITY_TEST) += test_emulate_step.o\n \n obj-y\t\t\t+= checksum_$(BITS).o checksum_wrappers.o\n \n-obj-$(CONFIG_PPC_EMULATE_SSTEP)\t+= sstep.o ldstfp.o\n-obj64-$(CONFIG_PPC_EMULATE_SSTEP) += quad.o\n+obj-y\t\t\t+= sstep.o ldstfp.o quad.o\n+obj64-y\t\t\t+= quad.o\n \n obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o\n \n", "prefixes": [ "v3", "17/17" ] }