diff mbox series

[v3,24/29] crypto: lib/curve25519 - work around Clang stack spilling issue

Message ID 20191007164610.6881-25-ard.biesheuvel@linaro.org (mailing list archive)
State Superseded
Delegated to: Herbert Xu
Headers show
Series crypto: crypto API library interfaces for WireGuard | expand

Commit Message

Ard Biesheuvel Oct. 7, 2019, 4:46 p.m. UTC
Arnd reports that the 32-bit generic library code for Curve25119 ends
up using an excessive amount of stack space when built with Clang:

  lib/crypto/curve25519-fiat32.c:756:6: error: stack frame size
      of 1384 bytes in function 'curve25519_generic'
      [-Werror,-Wframe-larger-than=]

Let's give some hints to the compiler regarding which routines should
not be inlined, to prevent it from running out of registers and spilling
to the stack. The resulting code performs identically under both GCC
and Clang, and makes the warning go away.

Suggested-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 lib/crypto/curve25519-fiat32.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

Comments

Jason A. Donenfeld Oct. 14, 2019, 2:13 p.m. UTC | #1
Hi Ard,

On Mon, Oct 7, 2019 at 6:46 PM Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> Arnd reports that the 32-bit generic library code for Curve25119 ends
> up using an excessive amount of stack space when built with Clang:
>
>   lib/crypto/curve25519-fiat32.c:756:6: error: stack frame size
>       of 1384 bytes in function 'curve25519_generic'
>       [-Werror,-Wframe-larger-than=]
>
> Let's give some hints to the compiler regarding which routines should
> not be inlined, to prevent it from running out of registers and spilling
> to the stack. The resulting code performs identically under both GCC
> and Clang, and makes the warning go away.

Are you *sure* about that? Couldn't we fix clang instead? I'd rather
fixes go there instead of gimping this. The reason is that I noticed
before that this code, performance-wise, was very inlining sensitive.
Can you benchmark this on ARM32-noneon and on MIPS32? If there's a
performance difference there, then maybe you can defer this part of
the series until after the rest lands, and then we'll discuss at
length various strategies? Alternatively, if you benchmark those and
it also makes no difference, then it indeed makes no difference.

Jason
Ard Biesheuvel Oct. 14, 2019, 4:07 p.m. UTC | #2
On Mon, 14 Oct 2019 at 16:14, Jason A. Donenfeld <Jason@zx2c4.com> wrote:
>
> Hi Ard,
>
> On Mon, Oct 7, 2019 at 6:46 PM Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> > Arnd reports that the 32-bit generic library code for Curve25119 ends
> > up using an excessive amount of stack space when built with Clang:
> >
> >   lib/crypto/curve25519-fiat32.c:756:6: error: stack frame size
> >       of 1384 bytes in function 'curve25519_generic'
> >       [-Werror,-Wframe-larger-than=]
> >
> > Let's give some hints to the compiler regarding which routines should
> > not be inlined, to prevent it from running out of registers and spilling
> > to the stack. The resulting code performs identically under both GCC
> > and Clang, and makes the warning go away.
>
> Are you *sure* about that? Couldn't we fix clang instead? I'd rather
> fixes go there instead of gimping this. The reason is that I noticed
> before that this code, performance-wise, was very inlining sensitive.
> Can you benchmark this on ARM32-noneon and on MIPS32? If there's a
> performance difference there, then maybe you can defer this part of
> the series until after the rest lands, and then we'll discuss at
> length various strategies? Alternatively, if you benchmark those and
> it also makes no difference, then it indeed makes no difference.
>

I tested this using a 32-bit ARM VM running under an 64-bit KVM
hypervisor, doing 100 iterations of the selftest.
diff mbox series

Patch

diff --git a/lib/crypto/curve25519-fiat32.c b/lib/crypto/curve25519-fiat32.c
index 1c455207341d..2fde0ec33dbd 100644
--- a/lib/crypto/curve25519-fiat32.c
+++ b/lib/crypto/curve25519-fiat32.c
@@ -223,7 +223,7 @@  static __always_inline void fe_1(fe *h)
 	h->v[0] = 1;
 }
 
-static void fe_add_impl(u32 out[10], const u32 in1[10], const u32 in2[10])
+static noinline void fe_add_impl(u32 out[10], const u32 in1[10], const u32 in2[10])
 {
 	{ const u32 x20 = in1[9];
 	{ const u32 x21 = in1[8];
@@ -266,7 +266,7 @@  static __always_inline void fe_add(fe_loose *h, const fe *f, const fe *g)
 	fe_add_impl(h->v, f->v, g->v);
 }
 
-static void fe_sub_impl(u32 out[10], const u32 in1[10], const u32 in2[10])
+static noinline void fe_sub_impl(u32 out[10], const u32 in1[10], const u32 in2[10])
 {
 	{ const u32 x20 = in1[9];
 	{ const u32 x21 = in1[8];
@@ -309,7 +309,7 @@  static __always_inline void fe_sub(fe_loose *h, const fe *f, const fe *g)
 	fe_sub_impl(h->v, f->v, g->v);
 }
 
-static void fe_mul_impl(u32 out[10], const u32 in1[10], const u32 in2[10])
+static noinline void fe_mul_impl(u32 out[10], const u32 in1[10], const u32 in2[10])
 {
 	{ const u32 x20 = in1[9];
 	{ const u32 x21 = in1[8];
@@ -441,7 +441,7 @@  fe_mul_tll(fe *h, const fe_loose *f, const fe_loose *g)
 	fe_mul_impl(h->v, f->v, g->v);
 }
 
-static void fe_sqr_impl(u32 out[10], const u32 in1[10])
+static noinline void fe_sqr_impl(u32 out[10], const u32 in1[10])
 {
 	{ const u32 x17 = in1[9];
 	{ const u32 x18 = in1[8];
@@ -619,7 +619,7 @@  static __always_inline void fe_invert(fe *out, const fe *z)
  *
  * Preconditions: b in {0,1}
  */
-static __always_inline void fe_cswap(fe *f, fe *g, unsigned int b)
+static noinline void fe_cswap(fe *f, fe *g, unsigned int b)
 {
 	unsigned i;
 	b = 0 - b;