crypto: x86 - exit fpu context earlier in ECB/CBC macros
authorPeter Lafreniere <peter@n8pjl.ca>
Sat, 21 Jan 2023 18:34:50 +0000 (13:34 -0500)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 3 Feb 2023 04:54:54 +0000 (12:54 +0800)
Currently the ecb/cbc macros hold fpu context unnecessarily when using
scalar cipher routines (e.g. when handling odd sizes of blocks per walk).

Change the macros to drop fpu context as soon as the fpu is out of use.

No performance impact found (on Intel Haswell).

Signed-off-by: Peter Lafreniere <peter@n8pjl.ca>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
arch/x86/crypto/ecb_cbc_helpers.h

index eaa15c7b29d62962bc51151396d8593cda0caff1..11955bd01af136fcd1e6d6f9396d0411def24461 100644 (file)
 
 #define ECB_WALK_START(req, bsize, fpu_blocks) do {                    \
        void *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));   \
+       const int __fpu_blocks = (fpu_blocks);                          \
        const int __bsize = (bsize);                                    \
        struct skcipher_walk walk;                                      \
        int err = skcipher_walk_virt(&walk, (req), false);              \
        while (walk.nbytes > 0) {                                       \
                unsigned int nbytes = walk.nbytes;                      \
-               bool do_fpu = (fpu_blocks) != -1 &&                     \
-                             nbytes >= (fpu_blocks) * __bsize;         \
+               bool do_fpu = __fpu_blocks != -1 &&                     \
+                             nbytes >= __fpu_blocks * __bsize;         \
                const u8 *src = walk.src.virt.addr;                     \
                u8 *dst = walk.dst.virt.addr;                           \
                u8 __maybe_unused buf[(bsize)];                         \
 } while (0)
 
 #define ECB_BLOCK(blocks, func) do {                                   \
-       while (nbytes >= (blocks) * __bsize) {                          \
+       const int __blocks = (blocks);                                  \
+       if (do_fpu && __blocks < __fpu_blocks) {                        \
+               kernel_fpu_end();                                       \
+               do_fpu = false;                                         \
+       }                                                               \
+       while (nbytes >= __blocks * __bsize) {                          \
                (func)(ctx, dst, src);                                  \
                ECB_WALK_ADVANCE(blocks);                               \
        }                                                               \
 } while (0)
 
 #define CBC_DEC_BLOCK(blocks, func) do {                               \
-       while (nbytes >= (blocks) * __bsize) {                          \
+       const int __blocks = (blocks);                                  \
+       if (do_fpu && __blocks <  __fpu_blocks) {                       \
+               kernel_fpu_end();                                       \
+               do_fpu = false;                                         \
+       }                                                               \
+       while (nbytes >= __blocks * __bsize) {                          \
                const u8 *__iv = src + ((blocks) - 1) * __bsize;        \
                if (dst == src)                                         \
                        __iv = memcpy(buf, __iv, __bsize);              \