From patchwork Tue Apr 1 13:47:37 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 3923351 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id CEBA29F2F7 for ; Tue, 1 Apr 2014 13:51:11 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D5B00203B6 for ; Tue, 1 Apr 2014 13:51:10 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A73A920259 for ; Tue, 1 Apr 2014 13:51:09 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WUz3p-0007Vr-N9; Tue, 01 Apr 2014 13:49:06 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WUz3X-0001uj-3e; Tue, 01 Apr 2014 13:48:47 +0000 Received: from mail-wg0-f44.google.com ([74.125.82.44]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WUz2y-0001oX-Hg for linux-arm-kernel@lists.infradead.org; Tue, 01 Apr 2014 13:48:20 +0000 Received: by mail-wg0-f44.google.com with SMTP id m15so7330485wgh.15 for ; Tue, 01 Apr 2014 06:47:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=xbGlLhFYF2k9Sp+7Tnq+XCqqaYc1m3sSXbX1Ci01nFo=; b=A5kYLTkHCle1YZElPGKvHCWeFAgJolZng6PJB3KA1DA6b1FnxOqfiB1v55JFY/4KCg lN0gEE6qwztzM0p9V9swLnkSKmikbXdJCoG0N0T7lXMsq2yNuVS0aIIdUrUoJpNmEl6t V/j09MVRn0vieOz3IBCHmgo5KU3aEctoYXpA5J3N8IL1H3v4yV3slPkXitpayfXTsP8I lIfFbJes9r/kPh0spDTgjyEJHgUI3ROh3P1+fw4aJG31mDXoLBFbpOIub7nOR2rZfdit lcKqSvSCyp5bXT9EwjOT3JU5TiVC1Hf1PRIq2bvLTplbQbnzecPwdEwCAeHXgjKSw/Ye /Srw== X-Gm-Message-State: ALoCoQmrhpnXGI42EKcW33J22DCOP2SvKeLBqxm72j8Rtj8+JHCxl6gvyHVAEUefD18mnQyo+Qj5 X-Received: by 10.180.12.115 with SMTP id x19mr20272757wib.19.1396360072220; Tue, 01 Apr 2014 06:47:52 -0700 (PDT) Received: from ards-macbook-pro.local ([95.129.121.210]) by mx.google.com with ESMTPSA id 48sm40727180eee.2.2014.04.01.06.47.51 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 01 Apr 2014 06:47:51 -0700 (PDT) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org, catalin.marinas@arm.com, nico@linaro.org Subject: [PATCH v3 5/7] arm64/crypto: add voluntary preemption to Crypto Extensions SHA1 Date: Tue, 1 Apr 2014 15:47:37 +0200 Message-Id: <1396360059-31949-6-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1396360059-31949-1-git-send-email-ard.biesheuvel@linaro.org> References: <1396360059-31949-1-git-send-email-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140401_094812_809925_C22E0825 X-CRM114-Status: GOOD ( 14.81 ) X-Spam-Score: -2.6 (--) Cc: Ard Biesheuvel X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The Crypto Extensions based SHA1 implementation uses the NEON register file, and hence runs with preemption disabled. This patch adds a TIF_NEED_RESCHED check to its inner loop so we at least give up the CPU voluntarily when if we are running in process context and have been tagged for preemption by the scheduler. Signed-off-by: Ard Biesheuvel --- arch/arm64/crypto/sha1-ce-core.S | 19 ++++++++-------- arch/arm64/crypto/sha1-ce-glue.c | 49 +++++++++++++++++++++++++++++++--------- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/arch/arm64/crypto/sha1-ce-core.S b/arch/arm64/crypto/sha1-ce-core.S index bd4af29f2722..831e332f9331 100644 --- a/arch/arm64/crypto/sha1-ce-core.S +++ b/arch/arm64/crypto/sha1-ce-core.S @@ -66,8 +66,8 @@ .word 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 /* - * void sha1_ce_transform(int blocks, u8 const *src, u32 *state, - * u8 *head, long bytes) + * int sha1_ce_transform(int blocks, u8 const *src, u32 *state, + * u8 *head, long bytes, struct thread_info *ti) */ ENTRY(sha1_ce_transform) /* load round constants */ @@ -127,7 +127,13 @@ CPU_LE( rev32 v11.16b, v11.16b ) add dgbv.2s, dgbv.2s, dg1v.2s add dgav.4s, dgav.4s, dg0v.4s - cbnz w0, 0b + cbz w0, 4f + b_if_no_resched x5, x8, 0b + + /* store new state */ +3: str dga, [x2] + str dgb, [x2, #16] + ret /* * Final block: add padding and total bit count. @@ -135,7 +141,7 @@ CPU_LE( rev32 v11.16b, v11.16b ) * size was not a round multiple of the block size, and the padding is * handled by the C code. */ - cbz x4, 3f +4: cbz x4, 3b movi v9.2d, #0 mov x8, #0x80000000 movi v10.2d, #0 @@ -145,9 +151,4 @@ CPU_LE( rev32 v11.16b, v11.16b ) mov v11.d[0], xzr mov v11.d[1], x7 b 2b - - /* store new state */ -3: str dga, [x2] - str dgb, [x2, #16] - ret ENDPROC(sha1_ce_transform) diff --git a/arch/arm64/crypto/sha1-ce-glue.c b/arch/arm64/crypto/sha1-ce-glue.c index 6fe83f37a750..69850a163668 100644 --- a/arch/arm64/crypto/sha1-ce-glue.c +++ b/arch/arm64/crypto/sha1-ce-glue.c @@ -20,8 +20,8 @@ MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions"); MODULE_AUTHOR("Ard Biesheuvel "); MODULE_LICENSE("GPL v2"); -asmlinkage void sha1_ce_transform(int blocks, u8 const *src, u32 *state, - u8 *head, long bytes); +asmlinkage int sha1_ce_transform(int blocks, u8 const *src, u32 *state, + u8 *head, long bytes, struct thread_info *ti); static int sha1_init(struct shash_desc *desc) { @@ -42,6 +42,7 @@ static int sha1_update(struct shash_desc *desc, const u8 *data, sctx->count += len; if ((partial + len) >= SHA1_BLOCK_SIZE) { + struct thread_info *ti = NULL; int blocks; if (partial) { @@ -52,16 +53,30 @@ static int sha1_update(struct shash_desc *desc, const u8 *data, len -= p; } + /* + * Pass current's thread info pointer to sha1_ce_transform() + * below if we want it to play nice under preemption. + */ + if ((IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY) || + IS_ENABLED(CONFIG_PREEMPT)) && !in_interrupt()) + ti = current_thread_info(); + blocks = len / SHA1_BLOCK_SIZE; len %= SHA1_BLOCK_SIZE; - kernel_neon_begin_partial(16); - sha1_ce_transform(blocks, data, sctx->state, - partial ? sctx->buffer : NULL, 0); - kernel_neon_end(); + do { + int rem; + + kernel_neon_begin_partial(16); + rem = sha1_ce_transform(blocks, data, sctx->state, + partial ? sctx->buffer : NULL, + 0, ti); + kernel_neon_end(); - data += blocks * SHA1_BLOCK_SIZE; - partial = 0; + data += (blocks - rem) * SHA1_BLOCK_SIZE; + blocks = rem; + partial = 0; + } while (unlikely(ti && blocks > 0)); } if (len) memcpy(sctx->buffer + partial, data, len); @@ -94,6 +109,7 @@ static int sha1_finup(struct shash_desc *desc, const u8 *data, unsigned int len, u8 *out) { struct sha1_state *sctx = shash_desc_ctx(desc); + struct thread_info *ti = NULL; __be32 *dst = (__be32 *)out; int blocks; int i; @@ -111,9 +127,20 @@ static int sha1_finup(struct shash_desc *desc, const u8 *data, */ blocks = len / SHA1_BLOCK_SIZE; - kernel_neon_begin_partial(16); - sha1_ce_transform(blocks, data, sctx->state, NULL, len); - kernel_neon_end(); + if ((IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY) || + IS_ENABLED(CONFIG_PREEMPT)) && !in_interrupt()) + ti = current_thread_info(); + + do { + int rem; + + kernel_neon_begin_partial(16); + rem = sha1_ce_transform(blocks, data, sctx->state, + NULL, len, ti); + kernel_neon_end(); + data += (blocks - rem) * SHA1_BLOCK_SIZE; + blocks = rem; + } while (unlikely(ti && blocks > 0)); for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++) put_unaligned_be32(sctx->state[i], dst++);