lkml.org 
[lkml]   [2021]   [Sep]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    SubjectRe: [PATCH 1/4] crypto: nintendo-aes - add a new AES driver
    On Tue, 21 Sept 2021 at 21:47, Emmanuel Gil Peyrot
    <linkmauve@linkmauve.fr> wrote:
    >
    > This engine implements AES in CBC mode, using 128-bit keys only. It is
    > present on both the Wii and the Wii U, and is apparently identical in
    > both consoles.
    >
    > The hardware is capable of firing an interrupt when the operation is
    > done, but this driver currently uses a busy loop, I’m not too sure
    > whether it would be preferable to switch, nor how to achieve that.
    >
    > It also supports a mode where no operation is done, and thus could be
    > used as a DMA copy engine, but I don’t know how to expose that to the
    > kernel or whether it would even be useful.
    >
    > In my testing, on a Wii U, this driver reaches 80.7 MiB/s, while the
    > aes-generic driver only reaches 30.9 MiB/s, so it is a quite welcome
    > speedup.
    >
    > This driver was written based on reversed documentation, see:
    > https://wiibrew.org/wiki/Hardware/AES
    >
    > Signed-off-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
    > Tested-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> # on Wii U
    > ---
    > drivers/crypto/Kconfig | 11 ++
    > drivers/crypto/Makefile | 1 +
    > drivers/crypto/nintendo-aes.c | 273 ++++++++++++++++++++++++++++++++++
    > 3 files changed, 285 insertions(+)
    > create mode 100644 drivers/crypto/nintendo-aes.c
    >
    > diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
    > index 9a4c275a1335..adc94ad7462d 100644
    > --- a/drivers/crypto/Kconfig
    > +++ b/drivers/crypto/Kconfig
    > @@ -871,4 +871,15 @@ config CRYPTO_DEV_SA2UL
    >
    > source "drivers/crypto/keembay/Kconfig"
    >
    > +config CRYPTO_DEV_NINTENDO
    > + tristate "Support for the Nintendo Wii U AES engine"
    > + depends on WII || WIIU || COMPILE_TEST

    This current seteup will allow the driver to be compile tested for
    non-powerpc, which will fail on the dcbf instructions.

    Perhaps use this instead:

    depends on WII || WIIU || (COMPILE_TEST && PPC)

    > + select CRYPTO_AES
    > + help
    > + Say 'Y' here to use the Nintendo Wii or Wii U on-board AES
    > + engine for the CryptoAPI AES algorithm.
    > +
    > + To compile this driver as a module, choose M here: the module
    > + will be called nintendo-aes.
    > +
    > endif # CRYPTO_HW
    > diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
    > index fa22cb19e242..004dae7bbf39 100644
    > --- a/drivers/crypto/Makefile
    > +++ b/drivers/crypto/Makefile
    > @@ -22,6 +22,7 @@ obj-$(CONFIG_CRYPTO_DEV_MARVELL) += marvell/
    > obj-$(CONFIG_CRYPTO_DEV_MXS_DCP) += mxs-dcp.o
    > obj-$(CONFIG_CRYPTO_DEV_NIAGARA2) += n2_crypto.o
    > n2_crypto-y := n2_core.o n2_asm.o
    > +obj-$(CONFIG_CRYPTO_DEV_NINTENDO) += nintendo-aes.o
    > obj-$(CONFIG_CRYPTO_DEV_NX) += nx/
    > obj-$(CONFIG_CRYPTO_DEV_OMAP) += omap-crypto.o
    > obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes-driver.o
    > diff --git a/drivers/crypto/nintendo-aes.c b/drivers/crypto/nintendo-aes.c
    > new file mode 100644
    > index 000000000000..79ae77500999
    > --- /dev/null
    > +++ b/drivers/crypto/nintendo-aes.c
    > @@ -0,0 +1,273 @@
    > +/*
    > + * Copyright (C) 2021 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
    > + *
    > + * This program is free software; you can redistribute it and/or modify
    > + * it under the terms of the GNU General Public License version 2 and
    > + * only version 2 as published by the Free Software Foundation.
    > + *
    > + * This program is distributed in the hope that it will be useful,
    > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    > + * GNU General Public License for more details.
    The kernel uses the SDPX header instead of pasting the text.

    > +static int
    > +do_crypt(const void *src, void *dst, u32 len, u32 flags)
    > +{
    > + u32 blocks = ((len >> 4) - 1) & AES_CTRL_BLOCK;
    > + u32 status;
    > + u32 counter = OP_TIMEOUT;
    > + u32 i;
    > +
    > + /* Flush out all of src, we can’t know whether any of it is in cache */
    > + for (i = 0; i < len; i += 32)
    > + __asm__("dcbf 0, %0" : : "r" (src + i));
    > + __asm__("sync" : : : "memory");

    This could be flush_dcache_range, from asm/cacheflush.h

    > +
    > + /* Set the addresses for DMA */
    > + iowrite32be(virt_to_phys((void *)src), base + AES_SRC);
    > + iowrite32be(virt_to_phys(dst), base + AES_DEST);
    > +
    > + /* Start the operation */
    > + iowrite32be(flags | blocks, base + AES_CTRL);
    > +
    > + /* TODO: figure out how to use interrupts here, this will probably
    > + * lower throughput but let the CPU do other things while the AES
    > + * engine is doing its work. */
    > + do {
    > + status = ioread32be(base + AES_CTRL);
    > + cpu_relax();
    > + } while ((status & AES_CTRL_EXEC) && --counter);

    You could add a msleep in here?

    Consider using readl_poll_timeout().

    Cheers,

    Joel

    > +
    > + /* Do we ever get called with dst ≠ src? If so we have to invalidate
    > + * dst in addition to the earlier flush of src. */
    > + if (unlikely(dst != src)) {
    > + for (i = 0; i < len; i += 32)
    > + __asm__("dcbi 0, %0" : : "r" (dst + i));
    > + __asm__("sync" : : : "memory");
    > + }
    > +
    > + return counter ? 0 : 1;
    > +}

    \
     
     \ /
      Last update: 2021-09-22 04:03    [W:4.091 / U:0.100 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site