get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2183225,
    "url": "http://patchwork.ozlabs.org/api/patches/2183225/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20260112192035.10427-14-ebiggers@kernel.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": "<20260112192035.10427-14-ebiggers@kernel.org>",
    "list_archive_url": "https://lore.kernel.org/linuxppc-dev/20260112192035.10427-14-ebiggers@kernel.org/",
    "date": "2026-01-12T19:20:11",
    "name": "[v2,13/35] lib/crypto: powerpc/aes: Migrate POWER8 optimized code into library",
    "commit_ref": null,
    "pull_url": null,
    "state": "handled-elsewhere",
    "archived": false,
    "hash": "4a6621738141792298d8e4583e69406326b7935b",
    "submitter": {
        "id": 74690,
        "url": "http://patchwork.ozlabs.org/api/people/74690/?format=api",
        "name": "Eric Biggers",
        "email": "ebiggers@kernel.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20260112192035.10427-14-ebiggers@kernel.org/mbox/",
    "series": [
        {
            "id": 488089,
            "url": "http://patchwork.ozlabs.org/api/series/488089/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=488089",
            "date": "2026-01-12T19:19:58",
            "name": "AES library improvements",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/488089/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2183225/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2183225/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linuxppc-dev+bounces-15582-incoming=patchwork.ozlabs.org@lists.ozlabs.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "linuxppc-dev@lists.ozlabs.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=MSivp2FB;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org\n (client-ip=2404:9400:21b9:f100::1; helo=lists.ozlabs.org;\n envelope-from=linuxppc-dev+bounces-15582-incoming=patchwork.ozlabs.org@lists.ozlabs.org;\n receiver=patchwork.ozlabs.org)",
            "lists.ozlabs.org;\n arc=none smtp.remote-ip=172.234.252.31",
            "lists.ozlabs.org;\n dmarc=pass (p=quarantine dis=none) header.from=kernel.org",
            "lists.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=MSivp2FB;\n\tdkim-atps=neutral",
            "lists.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=kernel.org\n (client-ip=172.234.252.31; helo=sea.source.kernel.org;\n envelope-from=ebiggers@kernel.org; receiver=lists.ozlabs.org)"
        ],
        "Received": [
            "from lists.ozlabs.org (lists.ozlabs.org\n [IPv6:2404:9400:21b9:f100::1])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4dqj7P35ntz1xpY\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 13 Jan 2026 06:27:13 +1100 (AEDT)",
            "from boromir.ozlabs.org (localhost [127.0.0.1])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 4dqj3d6fLNz3c3l;\n\tTue, 13 Jan 2026 06:23:57 +1100 (AEDT)",
            "from sea.source.kernel.org (sea.source.kernel.org [172.234.252.31])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 4dqj3c5vMkz3c2G\n\tfor <linuxppc-dev@lists.ozlabs.org>; Tue, 13 Jan 2026 06:23:56 +1100 (AEDT)",
            "from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58])\n\tby sea.source.kernel.org (Postfix) with ESMTP id 46CB64439B;\n\tMon, 12 Jan 2026 19:23:25 +0000 (UTC)",
            "by smtp.kernel.org (Postfix) with ESMTPSA id 9B57AC19424;\n\tMon, 12 Jan 2026 19:23:24 +0000 (UTC)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=lists.ozlabs.org; s=201707; t=1768245837;\n\tcv=none;\n b=C4EOLxMYd5edSHAGVo8d1lfwEbXd4xi27PYGlG2rsnfx5q1lFD7Q0gDC1eHzox6yM8O+YhV0MnQ0haHyQz414kYpwMzUcHQ4ZVgcId34hRpO4g0qo92J0rQRS91OR4JYCZB1+WE1o7rN4NtGt1hWnSaFZQMG+1z95MFDHXJCfEMhCD1MD8Pby4M0Ybej80V8JDSJ66uOF2+HPOlF9O3t9cFhgWTe41R8Mwl2lu0Sw39ukSaM7CGMDVXzbNWNAwmPlhqpYL9Za+UbN9l8ldZQ50GojyBGA19yP4QazKL1pAxAl/lSGdcO2iaIdgeZumqzkSiPTIao+WignnSKbJmX8w==",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=lists.ozlabs.org; s=201707;\n\tt=1768245837; c=relaxed/relaxed;\n\tbh=oWJ7DzghdubaFBYHSoPzqXAOtlBUhg6MFS4nsMB8Fw8=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=Z4u+xz1b6nh6TGOKFLNCu5xPGrw+EfItrHgemSqWpAoMpRglIhMyQXRXq9PwWLh5lXDkKkSXA5SiN0nXDzcerjZOyzXW/Z1ArNiZ2MvqrYNkOKDHdhfzZDCaanFRqNcNqRSOMccVt7WyQRm9MJVOzcI6X5G6r/8k5Lj+y7QTwv0q/d5pftio8xjM0NtBS/MEpdrFSgiGtpw7UubwXhZPkB9lqNtTUD07zQl1EWgEac387cku3rIOXZ+hR7W4UxYcBxJSunjPrXHg+4RNLwWWyecj6g7qkA1MP+tA3DAOmfDd3e2Ins7Gqq2NlsEl3imAGT4JookZAyBXYBeKQTuX1g==",
        "ARC-Authentication-Results": "i=1; lists.ozlabs.org;\n dmarc=pass (p=quarantine dis=none) header.from=kernel.org;\n dkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=MSivp2FB; dkim-atps=neutral;\n spf=pass (client-ip=172.234.252.31; helo=sea.source.kernel.org;\n envelope-from=ebiggers@kernel.org;\n receiver=lists.ozlabs.org) smtp.mailfrom=kernel.org",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1768245805;\n\tbh=7DeMmPlKgeVeGQUGcYRh7ztvjFtTSjiZ3ICz7lX67LU=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=MSivp2FBUadzYzkunMya/Z3/yNtrdYy6hKsUVy7tDoJWrdaYhUC/iZI/cgdjNczjt\n\t rPce8/G7ANnwT+ya7QrlinzSwudlJ6AB7MLa0L330+ftKxnuF7MT+87r8bOryppL1B\n\t pKgT4zOvMaxcTD4MpbaeqU4o1WoWE3fnndQ6Hh8QwR9avwWoseP3xj9ZxJlLtYxX9a\n\t F10Co9/N1x14vBETMby0KqHU6/euQkn6hbaqu3amxZBf1B0QxU/gu+IU2mEmW0SkCX\n\t XAUc3o3AYCe1gCFpTpxZ180mD8a/zwhbZBFYWs/PN8aDw+rOUCWOVnDmMsJP5VwHrg\n\t L59V9xL7/hIHA==",
        "From": "Eric Biggers <ebiggers@kernel.org>",
        "To": "linux-crypto@vger.kernel.org",
        "Cc": "linux-kernel@vger.kernel.org,\n\tArd Biesheuvel <ardb@kernel.org>,\n\t\"Jason A . Donenfeld\" <Jason@zx2c4.com>,\n\tHerbert Xu <herbert@gondor.apana.org.au>,\n\tlinux-arm-kernel@lists.infradead.org,\n\tlinuxppc-dev@lists.ozlabs.org,\n\tlinux-riscv@lists.infradead.org,\n\tlinux-s390@vger.kernel.org,\n\tsparclinux@vger.kernel.org,\n\tx86@kernel.org,\n\tHolger Dengler <dengler@linux.ibm.com>,\n\tHarald Freudenberger <freude@linux.ibm.com>,\n\tEric Biggers <ebiggers@kernel.org>",
        "Subject": "[PATCH v2 13/35] lib/crypto: powerpc/aes: Migrate POWER8 optimized\n code into library",
        "Date": "Mon, 12 Jan 2026 11:20:11 -0800",
        "Message-ID": "<20260112192035.10427-14-ebiggers@kernel.org>",
        "X-Mailer": "git-send-email 2.52.0",
        "In-Reply-To": "<20260112192035.10427-1-ebiggers@kernel.org>",
        "References": "<20260112192035.10427-1-ebiggers@kernel.org>",
        "X-Mailing-List": "linuxppc-dev@lists.ozlabs.org",
        "List-Id": "<linuxppc-dev.lists.ozlabs.org>",
        "List-Help": "<mailto:linuxppc-dev+help@lists.ozlabs.org>",
        "List-Owner": "<mailto:linuxppc-dev+owner@lists.ozlabs.org>",
        "List-Post": "<mailto:linuxppc-dev@lists.ozlabs.org>",
        "List-Archive": "<https://lore.kernel.org/linuxppc-dev/>,\n  <https://lists.ozlabs.org/pipermail/linuxppc-dev/>",
        "List-Subscribe": "<mailto:linuxppc-dev+subscribe@lists.ozlabs.org>,\n  <mailto:linuxppc-dev+subscribe-digest@lists.ozlabs.org>,\n  <mailto:linuxppc-dev+subscribe-nomail@lists.ozlabs.org>",
        "List-Unsubscribe": "<mailto:linuxppc-dev+unsubscribe@lists.ozlabs.org>",
        "Precedence": "list",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-Spam-Status": "No, score=-0.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED,\n\tDKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS\n\tautolearn=disabled version=4.0.1 OzLabs 8",
        "X-Spam-Checker-Version": "SpamAssassin 4.0.1 (2024-03-25) on lists.ozlabs.org"
    },
    "content": "Move the POWER8 AES assembly code into lib/crypto/, wire the key\nexpansion and single-block en/decryption functions up to the AES library\nAPI, and remove the superseded \"p8_aes\" crypto_cipher algorithm.\n\nThe result is that both the AES library and crypto_cipher APIs are now\noptimized for POWER8, whereas previously only crypto_cipher was (and\noptimizations weren't enabled by default, which this commit fixes too).\n\nNote that many of the functions in the POWER8 assembly code are still\nused by the AES mode implementations in arch/powerpc/crypto/.  For now,\njust export these functions.  These exports will go away once the AES\nmodes are migrated to the library as well.  (Trying to split up the\nassembly file seemed like much more trouble than it would be worth.)\n\nAnother challenge with this code is that the POWER8 assembly code uses a\ncustom format for the expanded AES key.  Since that code is imported\nfrom OpenSSL and is also targeted to POWER8 (rather than POWER9 which\nhas better data movement and byteswap instructions), that is not easily\nchanged.  For now I've just kept the custom format.  To maintain full\ncorrectness, this requires executing some slow fallback code in the case\nwhere the usability of VSX changes between key expansion and use.  This\nshould be tolerable, as this case shouldn't happen in practice.\n\nAcked-by: Ard Biesheuvel <ardb@kernel.org>\nSigned-off-by: Eric Biggers <ebiggers@kernel.org>\n---\n arch/powerpc/crypto/Makefile                  |   7 +-\n arch/powerpc/crypto/aes.c                     | 134 --------------\n arch/powerpc/crypto/aesp8-ppc.h               |  23 ---\n arch/powerpc/crypto/vmx.c                     |  10 +-\n include/crypto/aes.h                          |  41 +++++\n lib/crypto/Kconfig                            |   2 +-\n lib/crypto/Makefile                           |  14 +-\n lib/crypto/powerpc/.gitignore                 |   2 +\n lib/crypto/powerpc/aes.h                      | 164 ++++++++++++++++++\n .../crypto/powerpc}/aesp8-ppc.pl              |   1 +\n 10 files changed, 226 insertions(+), 172 deletions(-)\n delete mode 100644 arch/powerpc/crypto/aes.c\n create mode 100644 lib/crypto/powerpc/.gitignore\n rename {arch/powerpc/crypto => lib/crypto/powerpc}/aesp8-ppc.pl (99%)",
    "diff": "diff --git a/arch/powerpc/crypto/Makefile b/arch/powerpc/crypto/Makefile\nindex e22310da86b5..3ac0886282a2 100644\n--- a/arch/powerpc/crypto/Makefile\n+++ b/arch/powerpc/crypto/Makefile\n@@ -9,11 +9,11 @@ obj-$(CONFIG_CRYPTO_AES_PPC_SPE) += aes-ppc-spe.o\n obj-$(CONFIG_CRYPTO_AES_GCM_P10) += aes-gcm-p10-crypto.o\n obj-$(CONFIG_CRYPTO_DEV_VMX_ENCRYPT) += vmx-crypto.o\n \n aes-ppc-spe-y := aes-spe-glue.o\n aes-gcm-p10-crypto-y := aes-gcm-p10-glue.o aes-gcm-p10.o ghashp10-ppc.o aesp10-ppc.o\n-vmx-crypto-objs := vmx.o aesp8-ppc.o ghashp8-ppc.o aes.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o\n+vmx-crypto-objs := vmx.o ghashp8-ppc.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o\n \n ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)\n override flavour := linux-ppc64le\n else\n ifdef CONFIG_PPC64_ELF_ABI_V2\n@@ -24,17 +24,16 @@ endif\n endif\n \n quiet_cmd_perl = PERL    $@\n       cmd_perl = $(PERL) $< $(flavour) > $@\n \n-targets += aesp10-ppc.S ghashp10-ppc.S aesp8-ppc.S ghashp8-ppc.S\n+targets += aesp10-ppc.S ghashp10-ppc.S ghashp8-ppc.S\n \n $(obj)/aesp10-ppc.S $(obj)/ghashp10-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE\n \t$(call if_changed,perl)\n \n-$(obj)/aesp8-ppc.S $(obj)/ghashp8-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE\n+$(obj)/ghashp8-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE\n \t$(call if_changed,perl)\n \n OBJECT_FILES_NON_STANDARD_aesp10-ppc.o := y\n OBJECT_FILES_NON_STANDARD_ghashp10-ppc.o := y\n-OBJECT_FILES_NON_STANDARD_aesp8-ppc.o := y\n OBJECT_FILES_NON_STANDARD_ghashp8-ppc.o := y\ndiff --git a/arch/powerpc/crypto/aes.c b/arch/powerpc/crypto/aes.c\ndeleted file mode 100644\nindex b7192ee719fc..000000000000\n--- a/arch/powerpc/crypto/aes.c\n+++ /dev/null\n@@ -1,134 +0,0 @@\n-// SPDX-License-Identifier: GPL-2.0-only\n-/*\n- * AES routines supporting VMX instructions on the Power 8\n- *\n- * Copyright (C) 2015 International Business Machines Inc.\n- *\n- * Author: Marcelo Henrique Cerri <mhcerri@br.ibm.com>\n- */\n-\n-#include <asm/simd.h>\n-#include <asm/switch_to.h>\n-#include <crypto/aes.h>\n-#include <crypto/internal/cipher.h>\n-#include <crypto/internal/simd.h>\n-#include <linux/err.h>\n-#include <linux/kernel.h>\n-#include <linux/module.h>\n-#include <linux/uaccess.h>\n-\n-#include \"aesp8-ppc.h\"\n-\n-struct p8_aes_ctx {\n-\tstruct crypto_cipher *fallback;\n-\tstruct p8_aes_key enc_key;\n-\tstruct p8_aes_key dec_key;\n-};\n-\n-static int p8_aes_init(struct crypto_tfm *tfm)\n-{\n-\tconst char *alg = crypto_tfm_alg_name(tfm);\n-\tstruct crypto_cipher *fallback;\n-\tstruct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);\n-\n-\tfallback = crypto_alloc_cipher(alg, 0, CRYPTO_ALG_NEED_FALLBACK);\n-\tif (IS_ERR(fallback)) {\n-\t\tprintk(KERN_ERR\n-\t\t       \"Failed to allocate transformation for '%s': %ld\\n\",\n-\t\t       alg, PTR_ERR(fallback));\n-\t\treturn PTR_ERR(fallback);\n-\t}\n-\n-\tcrypto_cipher_set_flags(fallback,\n-\t\t\t\tcrypto_cipher_get_flags((struct\n-\t\t\t\t\t\t\t crypto_cipher *)\n-\t\t\t\t\t\t\ttfm));\n-\tctx->fallback = fallback;\n-\n-\treturn 0;\n-}\n-\n-static void p8_aes_exit(struct crypto_tfm *tfm)\n-{\n-\tstruct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);\n-\n-\tif (ctx->fallback) {\n-\t\tcrypto_free_cipher(ctx->fallback);\n-\t\tctx->fallback = NULL;\n-\t}\n-}\n-\n-static int p8_aes_setkey(struct crypto_tfm *tfm, const u8 *key,\n-\t\t\t unsigned int keylen)\n-{\n-\tint ret;\n-\tstruct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);\n-\n-\tpreempt_disable();\n-\tpagefault_disable();\n-\tenable_kernel_vsx();\n-\tret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key);\n-\tret |= aes_p8_set_decrypt_key(key, keylen * 8, &ctx->dec_key);\n-\tdisable_kernel_vsx();\n-\tpagefault_enable();\n-\tpreempt_enable();\n-\n-\tret |= crypto_cipher_setkey(ctx->fallback, key, keylen);\n-\n-\treturn ret ? -EINVAL : 0;\n-}\n-\n-static void p8_aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)\n-{\n-\tstruct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);\n-\n-\tif (!crypto_simd_usable()) {\n-\t\tcrypto_cipher_encrypt_one(ctx->fallback, dst, src);\n-\t} else {\n-\t\tpreempt_disable();\n-\t\tpagefault_disable();\n-\t\tenable_kernel_vsx();\n-\t\taes_p8_encrypt(src, dst, &ctx->enc_key);\n-\t\tdisable_kernel_vsx();\n-\t\tpagefault_enable();\n-\t\tpreempt_enable();\n-\t}\n-}\n-\n-static void p8_aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)\n-{\n-\tstruct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);\n-\n-\tif (!crypto_simd_usable()) {\n-\t\tcrypto_cipher_decrypt_one(ctx->fallback, dst, src);\n-\t} else {\n-\t\tpreempt_disable();\n-\t\tpagefault_disable();\n-\t\tenable_kernel_vsx();\n-\t\taes_p8_decrypt(src, dst, &ctx->dec_key);\n-\t\tdisable_kernel_vsx();\n-\t\tpagefault_enable();\n-\t\tpreempt_enable();\n-\t}\n-}\n-\n-struct crypto_alg p8_aes_alg = {\n-\t.cra_name = \"aes\",\n-\t.cra_driver_name = \"p8_aes\",\n-\t.cra_module = THIS_MODULE,\n-\t.cra_priority = 1000,\n-\t.cra_type = NULL,\n-\t.cra_flags = CRYPTO_ALG_TYPE_CIPHER | CRYPTO_ALG_NEED_FALLBACK,\n-\t.cra_alignmask = 0,\n-\t.cra_blocksize = AES_BLOCK_SIZE,\n-\t.cra_ctxsize = sizeof(struct p8_aes_ctx),\n-\t.cra_init = p8_aes_init,\n-\t.cra_exit = p8_aes_exit,\n-\t.cra_cipher = {\n-\t\t       .cia_min_keysize = AES_MIN_KEY_SIZE,\n-\t\t       .cia_max_keysize = AES_MAX_KEY_SIZE,\n-\t\t       .cia_setkey = p8_aes_setkey,\n-\t\t       .cia_encrypt = p8_aes_encrypt,\n-\t\t       .cia_decrypt = p8_aes_decrypt,\n-\t},\n-};\ndiff --git a/arch/powerpc/crypto/aesp8-ppc.h b/arch/powerpc/crypto/aesp8-ppc.h\nindex 0bea010128cb..6862c605cc33 100644\n--- a/arch/powerpc/crypto/aesp8-ppc.h\n+++ b/arch/powerpc/crypto/aesp8-ppc.h\n@@ -1,31 +1,8 @@\n /* SPDX-License-Identifier: GPL-2.0 */\n #include <linux/types.h>\n #include <crypto/aes.h>\n \n-struct p8_aes_key {\n-\tu8 key[AES_MAX_KEYLENGTH];\n-\tint rounds;\n-};\n-\n extern struct shash_alg p8_ghash_alg;\n-extern struct crypto_alg p8_aes_alg;\n extern struct skcipher_alg p8_aes_cbc_alg;\n extern struct skcipher_alg p8_aes_ctr_alg;\n extern struct skcipher_alg p8_aes_xts_alg;\n-\n-int aes_p8_set_encrypt_key(const u8 *userKey, const int bits,\n-\t\t\t   struct p8_aes_key *key);\n-int aes_p8_set_decrypt_key(const u8 *userKey, const int bits,\n-\t\t\t   struct p8_aes_key *key);\n-void aes_p8_encrypt(const u8 *in, u8 *out, const struct p8_aes_key *key);\n-void aes_p8_decrypt(const u8 *in, u8 *out, const struct p8_aes_key *key);\n-void aes_p8_cbc_encrypt(const u8 *in, u8 *out, size_t len,\n-\t\t\tconst struct p8_aes_key *key, u8 *iv, const int enc);\n-void aes_p8_ctr32_encrypt_blocks(const u8 *in, u8 *out, size_t len,\n-\t\t\t\t const struct p8_aes_key *key, const u8 *iv);\n-void aes_p8_xts_encrypt(const u8 *in, u8 *out, size_t len,\n-\t\t\tconst struct p8_aes_key *key1,\n-\t\t\tconst struct p8_aes_key *key2, u8 *iv);\n-void aes_p8_xts_decrypt(const u8 *in, u8 *out, size_t len,\n-\t\t\tconst struct p8_aes_key *key1,\n-\t\t\tconst struct p8_aes_key *key2, u8 *iv);\ndiff --git a/arch/powerpc/crypto/vmx.c b/arch/powerpc/crypto/vmx.c\nindex 0b725e826388..7d2beb774f99 100644\n--- a/arch/powerpc/crypto/vmx.c\n+++ b/arch/powerpc/crypto/vmx.c\n@@ -25,17 +25,13 @@ static int __init p8_init(void)\n \n \tret = crypto_register_shash(&p8_ghash_alg);\n \tif (ret)\n \t\tgoto err;\n \n-\tret = crypto_register_alg(&p8_aes_alg);\n-\tif (ret)\n-\t\tgoto err_unregister_ghash;\n-\n \tret = crypto_register_skcipher(&p8_aes_cbc_alg);\n \tif (ret)\n-\t\tgoto err_unregister_aes;\n+\t\tgoto err_unregister_ghash;\n \n \tret = crypto_register_skcipher(&p8_aes_ctr_alg);\n \tif (ret)\n \t\tgoto err_unregister_aes_cbc;\n \n@@ -47,12 +43,10 @@ static int __init p8_init(void)\n \n err_unregister_aes_ctr:\n \tcrypto_unregister_skcipher(&p8_aes_ctr_alg);\n err_unregister_aes_cbc:\n \tcrypto_unregister_skcipher(&p8_aes_cbc_alg);\n-err_unregister_aes:\n-\tcrypto_unregister_alg(&p8_aes_alg);\n err_unregister_ghash:\n \tcrypto_unregister_shash(&p8_ghash_alg);\n err:\n \treturn ret;\n }\n@@ -60,11 +54,10 @@ static int __init p8_init(void)\n static void __exit p8_exit(void)\n {\n \tcrypto_unregister_skcipher(&p8_aes_xts_alg);\n \tcrypto_unregister_skcipher(&p8_aes_ctr_alg);\n \tcrypto_unregister_skcipher(&p8_aes_cbc_alg);\n-\tcrypto_unregister_alg(&p8_aes_alg);\n \tcrypto_unregister_shash(&p8_ghash_alg);\n }\n \n module_cpu_feature_match(PPC_MODULE_FEATURE_VEC_CRYPTO, p8_init);\n module_exit(p8_exit);\n@@ -72,6 +65,5 @@ module_exit(p8_exit);\n MODULE_AUTHOR(\"Marcelo Cerri<mhcerri@br.ibm.com>\");\n MODULE_DESCRIPTION(\"IBM VMX cryptographic acceleration instructions \"\n \t\t   \"support on Power 8\");\n MODULE_LICENSE(\"GPL\");\n MODULE_VERSION(\"1.0.0\");\n-MODULE_IMPORT_NS(\"CRYPTO_INTERNAL\");\ndiff --git a/include/crypto/aes.h b/include/crypto/aes.h\nindex c893c9214cb7..bff71cfaedeb 100644\n--- a/include/crypto/aes.h\n+++ b/include/crypto/aes.h\n@@ -16,26 +16,51 @@\n #define AES_KEYSIZE_256\t\t32\n #define AES_BLOCK_SIZE\t\t16\n #define AES_MAX_KEYLENGTH\t(15 * 16)\n #define AES_MAX_KEYLENGTH_U32\t(AES_MAX_KEYLENGTH / sizeof(u32))\n \n+/*\n+ * The POWER8 VSX optimized AES assembly code is borrowed from OpenSSL and\n+ * inherits OpenSSL's AES_KEY format, which stores the number of rounds after\n+ * the round keys.  That assembly code is difficult to change.  So for\n+ * compatibility purposes we reserve space for the extra nrounds field on PPC64.\n+ *\n+ * Note: when prepared for decryption, the round keys are just the reversed\n+ * standard round keys, not the round keys for the Equivalent Inverse Cipher.\n+ */\n+struct p8_aes_key {\n+\tu32 rndkeys[AES_MAX_KEYLENGTH_U32];\n+\tint nrounds;\n+};\n+\n union aes_enckey_arch {\n \tu32 rndkeys[AES_MAX_KEYLENGTH_U32];\n #ifdef CONFIG_CRYPTO_LIB_AES_ARCH\n #if defined(CONFIG_PPC) && defined(CONFIG_SPE)\n \t/* Used unconditionally (when SPE AES code is enabled in kconfig) */\n \tu32 spe_enc_key[AES_MAX_KEYLENGTH_U32] __aligned(8);\n+#elif defined(CONFIG_PPC)\n+\t/*\n+\t * Kernels that include the POWER8 VSX optimized AES code use this field\n+\t * when that code is usable at key preparation time.  Otherwise they\n+\t * fall back to rndkeys.  In the latter case, p8.nrounds (which doesn't\n+\t * overlap rndkeys) is set to 0 to differentiate the two formats.\n+\t */\n+\tstruct p8_aes_key p8;\n #endif\n #endif /* CONFIG_CRYPTO_LIB_AES_ARCH */\n };\n \n union aes_invkey_arch {\n \tu32 inv_rndkeys[AES_MAX_KEYLENGTH_U32];\n #ifdef CONFIG_CRYPTO_LIB_AES_ARCH\n #if defined(CONFIG_PPC) && defined(CONFIG_SPE)\n \t/* Used unconditionally (when SPE AES code is enabled in kconfig) */\n \tu32 spe_dec_key[AES_MAX_KEYLENGTH_U32] __aligned(8);\n+#elif defined(CONFIG_PPC)\n+\t/* Used conditionally, analogous to aes_enckey_arch::p8 */\n+\tstruct p8_aes_key p8;\n #endif\n #endif /* CONFIG_CRYPTO_LIB_AES_ARCH */\n };\n \n /**\n@@ -153,10 +178,26 @@ void ppc_crypt_ctr(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, u32 bytes,\n \t\t   u8 *iv);\n void ppc_encrypt_xts(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, u32 bytes,\n \t\t     u8 *iv, u32 *key_twk);\n void ppc_decrypt_xts(u8 *out, const u8 *in, u32 *key_dec, u32 rounds, u32 bytes,\n \t\t     u8 *iv, u32 *key_twk);\n+int aes_p8_set_encrypt_key(const u8 *userKey, const int bits,\n+\t\t\t   struct p8_aes_key *key);\n+int aes_p8_set_decrypt_key(const u8 *userKey, const int bits,\n+\t\t\t   struct p8_aes_key *key);\n+void aes_p8_encrypt(const u8 *in, u8 *out, const struct p8_aes_key *key);\n+void aes_p8_decrypt(const u8 *in, u8 *out, const struct p8_aes_key *key);\n+void aes_p8_cbc_encrypt(const u8 *in, u8 *out, size_t len,\n+\t\t\tconst struct p8_aes_key *key, u8 *iv, const int enc);\n+void aes_p8_ctr32_encrypt_blocks(const u8 *in, u8 *out, size_t len,\n+\t\t\t\t const struct p8_aes_key *key, const u8 *iv);\n+void aes_p8_xts_encrypt(const u8 *in, u8 *out, size_t len,\n+\t\t\tconst struct p8_aes_key *key1,\n+\t\t\tconst struct p8_aes_key *key2, u8 *iv);\n+void aes_p8_xts_decrypt(const u8 *in, u8 *out, size_t len,\n+\t\t\tconst struct p8_aes_key *key1,\n+\t\t\tconst struct p8_aes_key *key2, u8 *iv);\n #endif\n \n /**\n  * aes_preparekey() - Prepare an AES key for encryption and decryption\n  * @key: (output) The key structure to initialize\ndiff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig\nindex cfc6171203d0..a0f1c105827e 100644\n--- a/lib/crypto/Kconfig\n+++ b/lib/crypto/Kconfig\n@@ -14,11 +14,11 @@ config CRYPTO_LIB_AES\n config CRYPTO_LIB_AES_ARCH\n \tbool\n \tdepends on CRYPTO_LIB_AES && !UML && !KMSAN\n \tdefault y if ARM\n \tdefault y if ARM64\n-\tdefault y if PPC && SPE\n+\tdefault y if PPC && (SPE || (PPC64 && VSX))\n \n config CRYPTO_LIB_AESCFB\n \ttristate\n \tselect CRYPTO_LIB_AES\n \tselect CRYPTO_LIB_UTILS\ndiff --git a/lib/crypto/Makefile b/lib/crypto/Makefile\nindex d68fde004104..16140616ace8 100644\n--- a/lib/crypto/Makefile\n+++ b/lib/crypto/Makefile\n@@ -33,11 +33,23 @@ ifeq ($(CONFIG_PPC),y)\n ifeq ($(CONFIG_SPE),y)\n libaes-y += powerpc/aes-spe-core.o \\\n \t    powerpc/aes-spe-keys.o \\\n \t    powerpc/aes-spe-modes.o \\\n \t    powerpc/aes-tab-4k.o\n-endif\n+else\n+libaes-y += powerpc/aesp8-ppc.o\n+aes-perlasm-flavour-y := linux-ppc64\n+aes-perlasm-flavour-$(CONFIG_PPC64_ELF_ABI_V2) := linux-ppc64-elfv2\n+aes-perlasm-flavour-$(CONFIG_CPU_LITTLE_ENDIAN) := linux-ppc64le\n+quiet_cmd_perlasm_aes = PERLASM $@\n+      cmd_perlasm_aes = $(PERL) $< $(aes-perlasm-flavour-y) $@\n+# Use if_changed instead of cmd, in case the flavour changed.\n+$(obj)/powerpc/aesp8-ppc.S: $(src)/powerpc/aesp8-ppc.pl FORCE\n+\t$(call if_changed,perlasm_aes)\n+targets += powerpc/aesp8-ppc.S\n+OBJECT_FILES_NON_STANDARD_powerpc/aesp8-ppc.o := y\n+endif # !CONFIG_SPE\n endif # CONFIG_PPC\n \n endif # CONFIG_CRYPTO_LIB_AES_ARCH\n \n ################################################################################\ndiff --git a/lib/crypto/powerpc/.gitignore b/lib/crypto/powerpc/.gitignore\nnew file mode 100644\nindex 000000000000..598ca7aff6b1\n--- /dev/null\n+++ b/lib/crypto/powerpc/.gitignore\n@@ -0,0 +1,2 @@\n+# SPDX-License-Identifier: GPL-2.0-only\n+aesp8-ppc.S\ndiff --git a/lib/crypto/powerpc/aes.h b/lib/crypto/powerpc/aes.h\nindex cf22020f9050..42e0a993c619 100644\n--- a/lib/crypto/powerpc/aes.h\n+++ b/lib/crypto/powerpc/aes.h\n@@ -1,17 +1,20 @@\n /* SPDX-License-Identifier: GPL-2.0-only */\n /*\n  * Copyright (c) 2015 Markus Stockhausen <stockhausen@collogia.de>\n+ * Copyright (C) 2015 International Business Machines Inc.\n  * Copyright 2026 Google LLC\n  */\n #include <asm/simd.h>\n #include <asm/switch_to.h>\n #include <linux/cpufeature.h>\n #include <linux/jump_label.h>\n #include <linux/preempt.h>\n #include <linux/uaccess.h>\n \n+#ifdef CONFIG_SPE\n+\n EXPORT_SYMBOL_GPL(ppc_expand_key_128);\n EXPORT_SYMBOL_GPL(ppc_expand_key_192);\n EXPORT_SYMBOL_GPL(ppc_expand_key_256);\n EXPORT_SYMBOL_GPL(ppc_generate_decrypt_key);\n EXPORT_SYMBOL_GPL(ppc_encrypt_ecb);\n@@ -70,5 +73,166 @@ static void aes_decrypt_arch(const struct aes_key *key,\n {\n \tspe_begin();\n \tppc_decrypt_aes(out, in, key->inv_k.spe_dec_key, key->nrounds / 2 - 1);\n \tspe_end();\n }\n+\n+#else /* CONFIG_SPE */\n+\n+static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_vec_crypto);\n+\n+EXPORT_SYMBOL_GPL(aes_p8_set_encrypt_key);\n+EXPORT_SYMBOL_GPL(aes_p8_set_decrypt_key);\n+EXPORT_SYMBOL_GPL(aes_p8_encrypt);\n+EXPORT_SYMBOL_GPL(aes_p8_decrypt);\n+EXPORT_SYMBOL_GPL(aes_p8_cbc_encrypt);\n+EXPORT_SYMBOL_GPL(aes_p8_ctr32_encrypt_blocks);\n+EXPORT_SYMBOL_GPL(aes_p8_xts_encrypt);\n+EXPORT_SYMBOL_GPL(aes_p8_xts_decrypt);\n+\n+static inline bool is_vsx_format(const struct p8_aes_key *key)\n+{\n+\treturn key->nrounds != 0;\n+}\n+\n+/*\n+ * Convert a round key from VSX to generic format by reflecting the 16 bytes,\n+ * and (if apply_inv_mix=true) applying InvMixColumn to each column.\n+ *\n+ * It would be nice if the VSX and generic key formats would be compatible.  But\n+ * that's very difficult to do, with the assembly code having been borrowed from\n+ * OpenSSL and also targeted to POWER8 rather than POWER9.\n+ *\n+ * Fortunately, this conversion should only be needed in extremely rare cases,\n+ * possibly not at all in practice.  It's just included for full correctness.\n+ */\n+static void rndkey_from_vsx(u32 out[4], const u32 in[4], bool apply_inv_mix)\n+{\n+\tu32 k0 = swab32(in[0]);\n+\tu32 k1 = swab32(in[1]);\n+\tu32 k2 = swab32(in[2]);\n+\tu32 k3 = swab32(in[3]);\n+\n+\tif (apply_inv_mix) {\n+\t\tk0 = inv_mix_columns(k0);\n+\t\tk1 = inv_mix_columns(k1);\n+\t\tk2 = inv_mix_columns(k2);\n+\t\tk3 = inv_mix_columns(k3);\n+\t}\n+\tout[0] = k3;\n+\tout[1] = k2;\n+\tout[2] = k1;\n+\tout[3] = k0;\n+}\n+\n+static void aes_preparekey_arch(union aes_enckey_arch *k,\n+\t\t\t\tunion aes_invkey_arch *inv_k,\n+\t\t\t\tconst u8 *in_key, int key_len, int nrounds)\n+{\n+\tconst int keybits = 8 * key_len;\n+\tint ret;\n+\n+\tif (static_branch_likely(&have_vec_crypto) && likely(may_use_simd())) {\n+\t\tpreempt_disable();\n+\t\tpagefault_disable();\n+\t\tenable_kernel_vsx();\n+\t\tret = aes_p8_set_encrypt_key(in_key, keybits, &k->p8);\n+\t\t/*\n+\t\t * aes_p8_set_encrypt_key() should never fail here, since the\n+\t\t * key length was already validated.\n+\t\t */\n+\t\tWARN_ON_ONCE(ret);\n+\t\tif (inv_k) {\n+\t\t\tret = aes_p8_set_decrypt_key(in_key, keybits,\n+\t\t\t\t\t\t     &inv_k->p8);\n+\t\t\t/* ... and likewise for aes_p8_set_decrypt_key(). */\n+\t\t\tWARN_ON_ONCE(ret);\n+\t\t}\n+\t\tdisable_kernel_vsx();\n+\t\tpagefault_enable();\n+\t\tpreempt_enable();\n+\t} else {\n+\t\taes_expandkey_generic(k->rndkeys,\n+\t\t\t\t      inv_k ? inv_k->inv_rndkeys : NULL,\n+\t\t\t\t      in_key, key_len);\n+\t\t/* Mark the key as using the generic format. */\n+\t\tk->p8.nrounds = 0;\n+\t\tif (inv_k)\n+\t\t\tinv_k->p8.nrounds = 0;\n+\t}\n+}\n+\n+static void aes_encrypt_arch(const struct aes_enckey *key,\n+\t\t\t     u8 out[AES_BLOCK_SIZE],\n+\t\t\t     const u8 in[AES_BLOCK_SIZE])\n+{\n+\tif (static_branch_likely(&have_vec_crypto) &&\n+\t    likely(is_vsx_format(&key->k.p8) && may_use_simd())) {\n+\t\tpreempt_disable();\n+\t\tpagefault_disable();\n+\t\tenable_kernel_vsx();\n+\t\taes_p8_encrypt(in, out, &key->k.p8);\n+\t\tdisable_kernel_vsx();\n+\t\tpagefault_enable();\n+\t\tpreempt_enable();\n+\t} else if (unlikely(is_vsx_format(&key->k.p8))) {\n+\t\t/*\n+\t\t * This handles (the hopefully extremely rare) case where a key\n+\t\t * was prepared using the VSX optimized format, then encryption\n+\t\t * is done in a context that cannot use VSX instructions.\n+\t\t */\n+\t\tu32 rndkeys[AES_MAX_KEYLENGTH_U32];\n+\n+\t\tfor (int i = 0; i < 4 * (key->nrounds + 1); i += 4)\n+\t\t\trndkey_from_vsx(&rndkeys[i],\n+\t\t\t\t\t&key->k.p8.rndkeys[i], false);\n+\t\taes_encrypt_generic(rndkeys, key->nrounds, out, in);\n+\t} else {\n+\t\taes_encrypt_generic(key->k.rndkeys, key->nrounds, out, in);\n+\t}\n+}\n+\n+static void aes_decrypt_arch(const struct aes_key *key, u8 out[AES_BLOCK_SIZE],\n+\t\t\t     const u8 in[AES_BLOCK_SIZE])\n+{\n+\tif (static_branch_likely(&have_vec_crypto) &&\n+\t    likely(is_vsx_format(&key->inv_k.p8) && may_use_simd())) {\n+\t\tpreempt_disable();\n+\t\tpagefault_disable();\n+\t\tenable_kernel_vsx();\n+\t\taes_p8_decrypt(in, out, &key->inv_k.p8);\n+\t\tdisable_kernel_vsx();\n+\t\tpagefault_enable();\n+\t\tpreempt_enable();\n+\t} else if (unlikely(is_vsx_format(&key->inv_k.p8))) {\n+\t\t/*\n+\t\t * This handles (the hopefully extremely rare) case where a key\n+\t\t * was prepared using the VSX optimized format, then decryption\n+\t\t * is done in a context that cannot use VSX instructions.\n+\t\t */\n+\t\tu32 inv_rndkeys[AES_MAX_KEYLENGTH_U32];\n+\t\tint i;\n+\n+\t\trndkey_from_vsx(&inv_rndkeys[0],\n+\t\t\t\t&key->inv_k.p8.rndkeys[0], false);\n+\t\tfor (i = 4; i < 4 * key->nrounds; i += 4) {\n+\t\t\trndkey_from_vsx(&inv_rndkeys[i],\n+\t\t\t\t\t&key->inv_k.p8.rndkeys[i], true);\n+\t\t}\n+\t\trndkey_from_vsx(&inv_rndkeys[i],\n+\t\t\t\t&key->inv_k.p8.rndkeys[i], false);\n+\t\taes_decrypt_generic(inv_rndkeys, key->nrounds, out, in);\n+\t} else {\n+\t\taes_decrypt_generic(key->inv_k.inv_rndkeys, key->nrounds,\n+\t\t\t\t    out, in);\n+\t}\n+}\n+\n+#define aes_mod_init_arch aes_mod_init_arch\n+static void aes_mod_init_arch(void)\n+{\n+\tif (cpu_has_feature(CPU_FTR_ARCH_207S) &&\n+\t    (cur_cpu_spec->cpu_user_features2 & PPC_FEATURE2_VEC_CRYPTO))\n+\t\tstatic_branch_enable(&have_vec_crypto);\n+}\n+\n+#endif /* !CONFIG_SPE */\ndiff --git a/arch/powerpc/crypto/aesp8-ppc.pl b/lib/crypto/powerpc/aesp8-ppc.pl\nsimilarity index 99%\nrename from arch/powerpc/crypto/aesp8-ppc.pl\nrename to lib/crypto/powerpc/aesp8-ppc.pl\nindex f729589d792e..253a06758057 100644\n--- a/arch/powerpc/crypto/aesp8-ppc.pl\n+++ b/lib/crypto/powerpc/aesp8-ppc.pl\n@@ -103,10 +103,11 @@ if ($flavour =~ /64/) {\n $LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0;\n \n $0 =~ m/(.*[\\/\\\\])[^\\/\\\\]+$/; $dir=$1;\n ( $xlate=\"${dir}ppc-xlate.pl\" and -f $xlate ) or\n ( $xlate=\"${dir}../../perlasm/ppc-xlate.pl\" and -f $xlate) or\n+( $xlate=\"${dir}../../../arch/powerpc/crypto/ppc-xlate.pl\" and -f $xlate) or\n die \"can't locate ppc-xlate.pl\";\n \n open STDOUT,\"| $^X $xlate $flavour \".shift || die \"can't call $xlate: $!\";\n \n $FRAME=8*$SIZE_T;\n",
    "prefixes": [
        "v2",
        "13/35"
    ]
}