* [PATCH v2 3/7] crypto: arm64/aes-blk - expose AES-CTR as synchronous cipher as well
From: Ard Biesheuvel @ 2017-01-11 16:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484152915-26517-1-git-send-email-ard.biesheuvel@linaro.org>
In addition to wrapping the AES-CTR cipher into the async SIMD wrapper,
which exposes it as an async skcipher that defers processing to process
context, expose our AES-CTR implementation directly as a synchronous cipher
as well, but with a lower priority.
This makes the AES-CTR transform usable in places where synchronous
transforms are required, such as the MAC802.11 encryption code, which
executes in sotfirq context, where SIMD processing is allowed on arm64.
Users of the async transform will keep the existing behavior.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/crypto/aes-glue.c | 25 ++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c
index 4e3f8adb1793..5164aaf82c6a 100644
--- a/arch/arm64/crypto/aes-glue.c
+++ b/arch/arm64/crypto/aes-glue.c
@@ -327,6 +327,23 @@ static struct skcipher_alg aes_algs[] = { {
.decrypt = ctr_encrypt,
}, {
.base = {
+ .cra_name = "ctr(aes)",
+ .cra_driver_name = "ctr-aes-" MODE,
+ .cra_priority = PRIO - 1,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx),
+ .cra_alignmask = 7,
+ .cra_module = THIS_MODULE,
+ },
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .chunksize = AES_BLOCK_SIZE,
+ .setkey = skcipher_aes_setkey,
+ .encrypt = ctr_encrypt,
+ .decrypt = ctr_encrypt,
+}, {
+ .base = {
.cra_name = "__xts(aes)",
.cra_driver_name = "__xts-aes-" MODE,
.cra_priority = PRIO,
@@ -350,8 +367,9 @@ static void aes_exit(void)
{
int i;
- for (i = 0; i < ARRAY_SIZE(aes_simd_algs) && aes_simd_algs[i]; i++)
- simd_skcipher_free(aes_simd_algs[i]);
+ for (i = 0; i < ARRAY_SIZE(aes_simd_algs); i++)
+ if (aes_simd_algs[i])
+ simd_skcipher_free(aes_simd_algs[i]);
crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
}
@@ -370,6 +388,9 @@ static int __init aes_init(void)
return err;
for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
+ if (!(aes_algs[i].base.cra_flags & CRYPTO_ALG_INTERNAL))
+ continue;
+
algname = aes_algs[i].base.cra_name + 2;
drvname = aes_algs[i].base.cra_driver_name + 2;
basename = aes_algs[i].base.cra_driver_name;
--
2.7.4
^ permalink raw reply related
* [PATCH v2 2/7] crypto: arm/chacha20 - implement NEON version based on SSE3 code
From: Ard Biesheuvel @ 2017-01-11 16:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484152915-26517-1-git-send-email-ard.biesheuvel@linaro.org>
This is a straight port to ARM/NEON of the x86 SSE3 implementation
of the ChaCha20 stream cipher. It uses the new skcipher walksize
attribute to process the input in strides of 4x the block size.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/crypto/Kconfig | 6 +
arch/arm/crypto/Makefile | 2 +
arch/arm/crypto/chacha20-neon-core.S | 524 ++++++++++++++++++++
arch/arm/crypto/chacha20-neon-glue.c | 128 +++++
4 files changed, 660 insertions(+)
diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig
index 13f1b4c289d4..2f3339f015d3 100644
--- a/arch/arm/crypto/Kconfig
+++ b/arch/arm/crypto/Kconfig
@@ -130,4 +130,10 @@ config CRYPTO_CRC32_ARM_CE
depends on KERNEL_MODE_NEON && CRC32
select CRYPTO_HASH
+config CRYPTO_CHACHA20_NEON
+ tristate "NEON accelerated ChaCha20 symmetric cipher"
+ depends on KERNEL_MODE_NEON
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_CHACHA20
+
endif
diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile
index b578a1820ab1..8d74e55eacd4 100644
--- a/arch/arm/crypto/Makefile
+++ b/arch/arm/crypto/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o
obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o
obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o
obj-$(CONFIG_CRYPTO_SHA512_ARM) += sha512-arm.o
+obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha20-neon.o
ce-obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o
ce-obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
@@ -40,6 +41,7 @@ aes-arm-ce-y := aes-ce-core.o aes-ce-glue.o
ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o
crct10dif-arm-ce-y := crct10dif-ce-core.o crct10dif-ce-glue.o
crc32-arm-ce-y:= crc32-ce-core.o crc32-ce-glue.o
+chacha20-neon-y := chacha20-neon-core.o chacha20-neon-glue.o
quiet_cmd_perl = PERL $@
cmd_perl = $(PERL) $(<) > $(@)
diff --git a/arch/arm/crypto/chacha20-neon-core.S b/arch/arm/crypto/chacha20-neon-core.S
new file mode 100644
index 000000000000..ff1d337bdb4a
--- /dev/null
+++ b/arch/arm/crypto/chacha20-neon-core.S
@@ -0,0 +1,524 @@
+/*
+ * ChaCha20 256-bit cipher algorithm, RFC7539, ARM NEON functions
+ *
+ * Copyright (C) 2016 Linaro, Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on:
+ * ChaCha20 256-bit cipher algorithm, RFC7539, x64 SSE3 functions
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/linkage.h>
+
+ .text
+ .fpu neon
+ .align 5
+
+ENTRY(chacha20_block_xor_neon)
+ // r0: Input state matrix, s
+ // r1: 1 data block output, o
+ // r2: 1 data block input, i
+
+ //
+ // This function encrypts one ChaCha20 block by loading the state matrix
+ // in four NEON registers. It performs matrix operation on four words in
+ // parallel, but requireds shuffling to rearrange the words after each
+ // round.
+ //
+
+ // x0..3 = s0..3
+ add ip, r0, #0x20
+ vld1.32 {q0-q1}, [r0]
+ vld1.32 {q2-q3}, [ip]
+
+ vmov q8, q0
+ vmov q9, q1
+ vmov q10, q2
+ vmov q11, q3
+
+ mov r3, #10
+
+.Ldoubleround:
+ // x0 += x1, x3 = rotl32(x3 ^ x0, 16)
+ vadd.i32 q0, q0, q1
+ veor q4, q3, q0
+ vshl.u32 q3, q4, #16
+ vsri.u32 q3, q4, #16
+
+ // x2 += x3, x1 = rotl32(x1 ^ x2, 12)
+ vadd.i32 q2, q2, q3
+ veor q4, q1, q2
+ vshl.u32 q1, q4, #12
+ vsri.u32 q1, q4, #20
+
+ // x0 += x1, x3 = rotl32(x3 ^ x0, 8)
+ vadd.i32 q0, q0, q1
+ veor q4, q3, q0
+ vshl.u32 q3, q4, #8
+ vsri.u32 q3, q4, #24
+
+ // x2 += x3, x1 = rotl32(x1 ^ x2, 7)
+ vadd.i32 q2, q2, q3
+ veor q4, q1, q2
+ vshl.u32 q1, q4, #7
+ vsri.u32 q1, q4, #25
+
+ // x1 = shuffle32(x1, MASK(0, 3, 2, 1))
+ vext.8 q1, q1, q1, #4
+ // x2 = shuffle32(x2, MASK(1, 0, 3, 2))
+ vext.8 q2, q2, q2, #8
+ // x3 = shuffle32(x3, MASK(2, 1, 0, 3))
+ vext.8 q3, q3, q3, #12
+
+ // x0 += x1, x3 = rotl32(x3 ^ x0, 16)
+ vadd.i32 q0, q0, q1
+ veor q4, q3, q0
+ vshl.u32 q3, q4, #16
+ vsri.u32 q3, q4, #16
+
+ // x2 += x3, x1 = rotl32(x1 ^ x2, 12)
+ vadd.i32 q2, q2, q3
+ veor q4, q1, q2
+ vshl.u32 q1, q4, #12
+ vsri.u32 q1, q4, #20
+
+ // x0 += x1, x3 = rotl32(x3 ^ x0, 8)
+ vadd.i32 q0, q0, q1
+ veor q4, q3, q0
+ vshl.u32 q3, q4, #8
+ vsri.u32 q3, q4, #24
+
+ // x2 += x3, x1 = rotl32(x1 ^ x2, 7)
+ vadd.i32 q2, q2, q3
+ veor q4, q1, q2
+ vshl.u32 q1, q4, #7
+ vsri.u32 q1, q4, #25
+
+ // x1 = shuffle32(x1, MASK(2, 1, 0, 3))
+ vext.8 q1, q1, q1, #12
+ // x2 = shuffle32(x2, MASK(1, 0, 3, 2))
+ vext.8 q2, q2, q2, #8
+ // x3 = shuffle32(x3, MASK(0, 3, 2, 1))
+ vext.8 q3, q3, q3, #4
+
+ subs r3, r3, #1
+ bne .Ldoubleround
+
+ add ip, r2, #0x20
+ vld1.8 {q4-q5}, [r2]
+ vld1.8 {q6-q7}, [ip]
+
+ // o0 = i0 ^ (x0 + s0)
+ vadd.i32 q0, q0, q8
+ veor q0, q0, q4
+
+ // o1 = i1 ^ (x1 + s1)
+ vadd.i32 q1, q1, q9
+ veor q1, q1, q5
+
+ // o2 = i2 ^ (x2 + s2)
+ vadd.i32 q2, q2, q10
+ veor q2, q2, q6
+
+ // o3 = i3 ^ (x3 + s3)
+ vadd.i32 q3, q3, q11
+ veor q3, q3, q7
+
+ add ip, r1, #0x20
+ vst1.8 {q0-q1}, [r1]
+ vst1.8 {q2-q3}, [ip]
+
+ bx lr
+ENDPROC(chacha20_block_xor_neon)
+
+ .align 5
+ENTRY(chacha20_4block_xor_neon)
+ push {r4-r6, lr}
+ mov ip, sp // preserve the stack pointer
+ sub r3, sp, #0x20 // allocate a 32 byte buffer
+ bic r3, r3, #0x1f // aligned to 32 bytes
+ mov sp, r3
+
+ // r0: Input state matrix, s
+ // r1: 4 data blocks output, o
+ // r2: 4 data blocks input, i
+
+ //
+ // This function encrypts four consecutive ChaCha20 blocks by loading
+ // the state matrix in NEON registers four times. The algorithm performs
+ // each operation on the corresponding word of each state matrix, hence
+ // requires no word shuffling. For final XORing step we transpose the
+ // matrix by interleaving 32- and then 64-bit words, which allows us to
+ // do XOR in NEON registers.
+ //
+
+ // x0..15[0-3] = s0..3[0..3]
+ add r3, r0, #0x20
+ vld1.32 {q0-q1}, [r0]
+ vld1.32 {q2-q3}, [r3]
+
+ adr r3, CTRINC
+ vdup.32 q15, d7[1]
+ vdup.32 q14, d7[0]
+ vld1.32 {q11}, [r3, :128]
+ vdup.32 q13, d6[1]
+ vdup.32 q12, d6[0]
+ vadd.i32 q12, q12, q11 // x12 += counter values 0-3
+ vdup.32 q11, d5[1]
+ vdup.32 q10, d5[0]
+ vdup.32 q9, d4[1]
+ vdup.32 q8, d4[0]
+ vdup.32 q7, d3[1]
+ vdup.32 q6, d3[0]
+ vdup.32 q5, d2[1]
+ vdup.32 q4, d2[0]
+ vdup.32 q3, d1[1]
+ vdup.32 q2, d1[0]
+ vdup.32 q1, d0[1]
+ vdup.32 q0, d0[0]
+
+ mov r3, #10
+
+.Ldoubleround4:
+ // x0 += x4, x12 = rotl32(x12 ^ x0, 16)
+ // x1 += x5, x13 = rotl32(x13 ^ x1, 16)
+ // x2 += x6, x14 = rotl32(x14 ^ x2, 16)
+ // x3 += x7, x15 = rotl32(x15 ^ x3, 16)
+ vadd.i32 q0, q0, q4
+ vadd.i32 q1, q1, q5
+ vadd.i32 q2, q2, q6
+ vadd.i32 q3, q3, q7
+
+ veor q12, q12, q0
+ veor q13, q13, q1
+ veor q14, q14, q2
+ veor q15, q15, q3
+
+ vrev32.16 q12, q12
+ vrev32.16 q13, q13
+ vrev32.16 q14, q14
+ vrev32.16 q15, q15
+
+ // x8 += x12, x4 = rotl32(x4 ^ x8, 12)
+ // x9 += x13, x5 = rotl32(x5 ^ x9, 12)
+ // x10 += x14, x6 = rotl32(x6 ^ x10, 12)
+ // x11 += x15, x7 = rotl32(x7 ^ x11, 12)
+ vadd.i32 q8, q8, q12
+ vadd.i32 q9, q9, q13
+ vadd.i32 q10, q10, q14
+ vadd.i32 q11, q11, q15
+
+ vst1.32 {q8-q9}, [sp, :256]
+
+ veor q8, q4, q8
+ veor q9, q5, q9
+ vshl.u32 q4, q8, #12
+ vshl.u32 q5, q9, #12
+ vsri.u32 q4, q8, #20
+ vsri.u32 q5, q9, #20
+
+ veor q8, q6, q10
+ veor q9, q7, q11
+ vshl.u32 q6, q8, #12
+ vshl.u32 q7, q9, #12
+ vsri.u32 q6, q8, #20
+ vsri.u32 q7, q9, #20
+
+ // x0 += x4, x12 = rotl32(x12 ^ x0, 8)
+ // x1 += x5, x13 = rotl32(x13 ^ x1, 8)
+ // x2 += x6, x14 = rotl32(x14 ^ x2, 8)
+ // x3 += x7, x15 = rotl32(x15 ^ x3, 8)
+ vadd.i32 q0, q0, q4
+ vadd.i32 q1, q1, q5
+ vadd.i32 q2, q2, q6
+ vadd.i32 q3, q3, q7
+
+ veor q8, q12, q0
+ veor q9, q13, q1
+ vshl.u32 q12, q8, #8
+ vshl.u32 q13, q9, #8
+ vsri.u32 q12, q8, #24
+ vsri.u32 q13, q9, #24
+
+ veor q8, q14, q2
+ veor q9, q15, q3
+ vshl.u32 q14, q8, #8
+ vshl.u32 q15, q9, #8
+ vsri.u32 q14, q8, #24
+ vsri.u32 q15, q9, #24
+
+ vld1.32 {q8-q9}, [sp, :256]
+
+ // x8 += x12, x4 = rotl32(x4 ^ x8, 7)
+ // x9 += x13, x5 = rotl32(x5 ^ x9, 7)
+ // x10 += x14, x6 = rotl32(x6 ^ x10, 7)
+ // x11 += x15, x7 = rotl32(x7 ^ x11, 7)
+ vadd.i32 q8, q8, q12
+ vadd.i32 q9, q9, q13
+ vadd.i32 q10, q10, q14
+ vadd.i32 q11, q11, q15
+
+ vst1.32 {q8-q9}, [sp, :256]
+
+ veor q8, q4, q8
+ veor q9, q5, q9
+ vshl.u32 q4, q8, #7
+ vshl.u32 q5, q9, #7
+ vsri.u32 q4, q8, #25
+ vsri.u32 q5, q9, #25
+
+ veor q8, q6, q10
+ veor q9, q7, q11
+ vshl.u32 q6, q8, #7
+ vshl.u32 q7, q9, #7
+ vsri.u32 q6, q8, #25
+ vsri.u32 q7, q9, #25
+
+ vld1.32 {q8-q9}, [sp, :256]
+
+ // x0 += x5, x15 = rotl32(x15 ^ x0, 16)
+ // x1 += x6, x12 = rotl32(x12 ^ x1, 16)
+ // x2 += x7, x13 = rotl32(x13 ^ x2, 16)
+ // x3 += x4, x14 = rotl32(x14 ^ x3, 16)
+ vadd.i32 q0, q0, q5
+ vadd.i32 q1, q1, q6
+ vadd.i32 q2, q2, q7
+ vadd.i32 q3, q3, q4
+
+ veor q15, q15, q0
+ veor q12, q12, q1
+ veor q13, q13, q2
+ veor q14, q14, q3
+
+ vrev32.16 q15, q15
+ vrev32.16 q12, q12
+ vrev32.16 q13, q13
+ vrev32.16 q14, q14
+
+ // x10 += x15, x5 = rotl32(x5 ^ x10, 12)
+ // x11 += x12, x6 = rotl32(x6 ^ x11, 12)
+ // x8 += x13, x7 = rotl32(x7 ^ x8, 12)
+ // x9 += x14, x4 = rotl32(x4 ^ x9, 12)
+ vadd.i32 q10, q10, q15
+ vadd.i32 q11, q11, q12
+ vadd.i32 q8, q8, q13
+ vadd.i32 q9, q9, q14
+
+ vst1.32 {q8-q9}, [sp, :256]
+
+ veor q8, q7, q8
+ veor q9, q4, q9
+ vshl.u32 q7, q8, #12
+ vshl.u32 q4, q9, #12
+ vsri.u32 q7, q8, #20
+ vsri.u32 q4, q9, #20
+
+ veor q8, q5, q10
+ veor q9, q6, q11
+ vshl.u32 q5, q8, #12
+ vshl.u32 q6, q9, #12
+ vsri.u32 q5, q8, #20
+ vsri.u32 q6, q9, #20
+
+ // x0 += x5, x15 = rotl32(x15 ^ x0, 8)
+ // x1 += x6, x12 = rotl32(x12 ^ x1, 8)
+ // x2 += x7, x13 = rotl32(x13 ^ x2, 8)
+ // x3 += x4, x14 = rotl32(x14 ^ x3, 8)
+ vadd.i32 q0, q0, q5
+ vadd.i32 q1, q1, q6
+ vadd.i32 q2, q2, q7
+ vadd.i32 q3, q3, q4
+
+ veor q8, q15, q0
+ veor q9, q12, q1
+ vshl.u32 q15, q8, #8
+ vshl.u32 q12, q9, #8
+ vsri.u32 q15, q8, #24
+ vsri.u32 q12, q9, #24
+
+ veor q8, q13, q2
+ veor q9, q14, q3
+ vshl.u32 q13, q8, #8
+ vshl.u32 q14, q9, #8
+ vsri.u32 q13, q8, #24
+ vsri.u32 q14, q9, #24
+
+ vld1.32 {q8-q9}, [sp, :256]
+
+ // x10 += x15, x5 = rotl32(x5 ^ x10, 7)
+ // x11 += x12, x6 = rotl32(x6 ^ x11, 7)
+ // x8 += x13, x7 = rotl32(x7 ^ x8, 7)
+ // x9 += x14, x4 = rotl32(x4 ^ x9, 7)
+ vadd.i32 q10, q10, q15
+ vadd.i32 q11, q11, q12
+ vadd.i32 q8, q8, q13
+ vadd.i32 q9, q9, q14
+
+ vst1.32 {q8-q9}, [sp, :256]
+
+ veor q8, q7, q8
+ veor q9, q4, q9
+ vshl.u32 q7, q8, #7
+ vshl.u32 q4, q9, #7
+ vsri.u32 q7, q8, #25
+ vsri.u32 q4, q9, #25
+
+ veor q8, q5, q10
+ veor q9, q6, q11
+ vshl.u32 q5, q8, #7
+ vshl.u32 q6, q9, #7
+ vsri.u32 q5, q8, #25
+ vsri.u32 q6, q9, #25
+
+ subs r3, r3, #1
+ beq 0f
+
+ vld1.32 {q8-q9}, [sp, :256]
+ b .Ldoubleround4
+
+ // x0[0-3] += s0[0]
+ // x1[0-3] += s0[1]
+ // x2[0-3] += s0[2]
+ // x3[0-3] += s0[3]
+0: ldmia r0!, {r3-r6}
+ vdup.32 q8, r3
+ vdup.32 q9, r4
+ vadd.i32 q0, q0, q8
+ vadd.i32 q1, q1, q9
+ vdup.32 q8, r5
+ vdup.32 q9, r6
+ vadd.i32 q2, q2, q8
+ vadd.i32 q3, q3, q9
+
+ // x4[0-3] += s1[0]
+ // x5[0-3] += s1[1]
+ // x6[0-3] += s1[2]
+ // x7[0-3] += s1[3]
+ ldmia r0!, {r3-r6}
+ vdup.32 q8, r3
+ vdup.32 q9, r4
+ vadd.i32 q4, q4, q8
+ vadd.i32 q5, q5, q9
+ vdup.32 q8, r5
+ vdup.32 q9, r6
+ vadd.i32 q6, q6, q8
+ vadd.i32 q7, q7, q9
+
+ // interleave 32-bit words in state n, n+1
+ vzip.32 q0, q1
+ vzip.32 q2, q3
+ vzip.32 q4, q5
+ vzip.32 q6, q7
+
+ // interleave 64-bit words in state n, n+2
+ vswp d1, d4
+ vswp d3, d6
+ vswp d9, d12
+ vswp d11, d14
+
+ // xor with corresponding input, write to output
+ vld1.8 {q8-q9}, [r2]!
+ veor q8, q8, q0
+ veor q9, q9, q4
+ vst1.8 {q8-q9}, [r1]!
+
+ vld1.32 {q8-q9}, [sp, :256]
+
+ // x8[0-3] += s2[0]
+ // x9[0-3] += s2[1]
+ // x10[0-3] += s2[2]
+ // x11[0-3] += s2[3]
+ ldmia r0!, {r3-r6}
+ vdup.32 q0, r3
+ vdup.32 q4, r4
+ vadd.i32 q8, q8, q0
+ vadd.i32 q9, q9, q4
+ vdup.32 q0, r5
+ vdup.32 q4, r6
+ vadd.i32 q10, q10, q0
+ vadd.i32 q11, q11, q4
+
+ // x12[0-3] += s3[0]
+ // x13[0-3] += s3[1]
+ // x14[0-3] += s3[2]
+ // x15[0-3] += s3[3]
+ ldmia r0!, {r3-r6}
+ vdup.32 q0, r3
+ vdup.32 q4, r4
+ adr r3, CTRINC
+ vadd.i32 q12, q12, q0
+ vld1.32 {q0}, [r3, :128]
+ vadd.i32 q13, q13, q4
+ vadd.i32 q12, q12, q0 // x12 += counter values 0-3
+
+ vdup.32 q0, r5
+ vdup.32 q4, r6
+ vadd.i32 q14, q14, q0
+ vadd.i32 q15, q15, q4
+
+ // interleave 32-bit words in state n, n+1
+ vzip.32 q8, q9
+ vzip.32 q10, q11
+ vzip.32 q12, q13
+ vzip.32 q14, q15
+
+ // interleave 64-bit words in state n, n+2
+ vswp d17, d20
+ vswp d19, d22
+ vswp d25, d28
+ vswp d27, d30
+
+ vmov q4, q1
+
+ vld1.8 {q0-q1}, [r2]!
+ veor q0, q0, q8
+ veor q1, q1, q12
+ vst1.8 {q0-q1}, [r1]!
+
+ vld1.8 {q0-q1}, [r2]!
+ veor q0, q0, q2
+ veor q1, q1, q6
+ vst1.8 {q0-q1}, [r1]!
+
+ vld1.8 {q0-q1}, [r2]!
+ veor q0, q0, q10
+ veor q1, q1, q14
+ vst1.8 {q0-q1}, [r1]!
+
+ vld1.8 {q0-q1}, [r2]!
+ veor q0, q0, q4
+ veor q1, q1, q5
+ vst1.8 {q0-q1}, [r1]!
+
+ vld1.8 {q0-q1}, [r2]!
+ veor q0, q0, q9
+ veor q1, q1, q13
+ vst1.8 {q0-q1}, [r1]!
+
+ vld1.8 {q0-q1}, [r2]!
+ veor q0, q0, q3
+ veor q1, q1, q7
+ vst1.8 {q0-q1}, [r1]!
+
+ vld1.8 {q0-q1}, [r2]
+ veor q0, q0, q11
+ veor q1, q1, q15
+ vst1.8 {q0-q1}, [r1]
+
+ mov sp, ip
+ pop {r4-r6, pc}
+ENDPROC(chacha20_4block_xor_neon)
+
+ .align 4
+CTRINC: .word 0, 1, 2, 3
+
diff --git a/arch/arm/crypto/chacha20-neon-glue.c b/arch/arm/crypto/chacha20-neon-glue.c
new file mode 100644
index 000000000000..592f75ae4fa1
--- /dev/null
+++ b/arch/arm/crypto/chacha20-neon-glue.c
@@ -0,0 +1,128 @@
+/*
+ * ChaCha20 256-bit cipher algorithm, RFC7539, ARM NEON functions
+ *
+ * Copyright (C) 2016 Linaro, Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on:
+ * ChaCha20 256-bit cipher algorithm, RFC7539, SIMD glue code
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <crypto/algapi.h>
+#include <crypto/chacha20.h>
+#include <crypto/internal/skcipher.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+
+asmlinkage void chacha20_block_xor_neon(u32 *state, u8 *dst, const u8 *src);
+asmlinkage void chacha20_4block_xor_neon(u32 *state, u8 *dst, const u8 *src);
+
+static void chacha20_doneon(u32 *state, u8 *dst, const u8 *src,
+ unsigned int bytes)
+{
+ u8 buf[CHACHA20_BLOCK_SIZE];
+
+ while (bytes >= CHACHA20_BLOCK_SIZE * 4) {
+ chacha20_4block_xor_neon(state, dst, src);
+ bytes -= CHACHA20_BLOCK_SIZE * 4;
+ src += CHACHA20_BLOCK_SIZE * 4;
+ dst += CHACHA20_BLOCK_SIZE * 4;
+ state[12] += 4;
+ }
+ while (bytes >= CHACHA20_BLOCK_SIZE) {
+ chacha20_block_xor_neon(state, dst, src);
+ bytes -= CHACHA20_BLOCK_SIZE;
+ src += CHACHA20_BLOCK_SIZE;
+ dst += CHACHA20_BLOCK_SIZE;
+ state[12]++;
+ }
+ if (bytes) {
+ memcpy(buf, src, bytes);
+ chacha20_block_xor_neon(state, buf, buf);
+ memcpy(dst, buf, bytes);
+ }
+}
+
+static int chacha20_neon(struct skcipher_request *req)
+{
+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+ struct chacha20_ctx *ctx = crypto_skcipher_ctx(tfm);
+ struct skcipher_walk walk;
+ u32 state[16];
+ int err;
+
+ if (req->cryptlen <= CHACHA20_BLOCK_SIZE || !may_use_simd())
+ return crypto_chacha20_crypt(req);
+
+ err = skcipher_walk_virt(&walk, req, true);
+
+ crypto_chacha20_init(state, ctx, walk.iv);
+
+ kernel_neon_begin();
+ while (walk.nbytes > 0) {
+ unsigned int nbytes = walk.nbytes;
+
+ if (nbytes < walk.total)
+ nbytes = round_down(nbytes, walk.stride);
+
+ chacha20_doneon(state, walk.dst.virt.addr, walk.src.virt.addr,
+ nbytes);
+ err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
+ }
+ kernel_neon_end();
+
+ return err;
+}
+
+static struct skcipher_alg alg = {
+ .base.cra_name = "chacha20",
+ .base.cra_driver_name = "chacha20-neon",
+ .base.cra_priority = 300,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct chacha20_ctx),
+ .base.cra_alignmask = 1,
+ .base.cra_module = THIS_MODULE,
+
+ .min_keysize = CHACHA20_KEY_SIZE,
+ .max_keysize = CHACHA20_KEY_SIZE,
+ .ivsize = CHACHA20_IV_SIZE,
+ .chunksize = CHACHA20_BLOCK_SIZE,
+ .walksize = 4 * CHACHA20_BLOCK_SIZE,
+ .setkey = crypto_chacha20_setkey,
+ .encrypt = chacha20_neon,
+ .decrypt = chacha20_neon,
+};
+
+static int __init chacha20_simd_mod_init(void)
+{
+ if (!(elf_hwcap & HWCAP_NEON))
+ return -ENODEV;
+
+ return crypto_register_skcipher(&alg);
+}
+
+static void __exit chacha20_simd_mod_fini(void)
+{
+ crypto_unregister_skcipher(&alg);
+}
+
+module_init(chacha20_simd_mod_init);
+module_exit(chacha20_simd_mod_fini);
+
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("chacha20");
--
2.7.4
^ permalink raw reply related
* [PATCH v2 1/7] crypto: arm64/chacha20 - implement NEON version based on SSE3 code
From: Ard Biesheuvel @ 2017-01-11 16:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484152915-26517-1-git-send-email-ard.biesheuvel@linaro.org>
This is a straight port to arm64/NEON of the x86 SSE3 implementation
of the ChaCha20 stream cipher. It uses the new skcipher walksize
attribute to process the input in strides of 4x the block size.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/crypto/Kconfig | 6 +
arch/arm64/crypto/Makefile | 3 +
arch/arm64/crypto/chacha20-neon-core.S | 450 ++++++++++++++++++++
arch/arm64/crypto/chacha20-neon-glue.c | 127 ++++++
4 files changed, 586 insertions(+)
diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig
index 450a85df041a..0bf0f531f539 100644
--- a/arch/arm64/crypto/Kconfig
+++ b/arch/arm64/crypto/Kconfig
@@ -72,4 +72,10 @@ config CRYPTO_CRC32_ARM64
depends on ARM64
select CRYPTO_HASH
+config CRYPTO_CHACHA20_NEON
+ tristate "NEON accelerated ChaCha20 symmetric cipher"
+ depends on KERNEL_MODE_NEON
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_CHACHA20
+
endif
diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
index aa8888d7b744..9d2826c5fccf 100644
--- a/arch/arm64/crypto/Makefile
+++ b/arch/arm64/crypto/Makefile
@@ -41,6 +41,9 @@ sha256-arm64-y := sha256-glue.o sha256-core.o
obj-$(CONFIG_CRYPTO_SHA512_ARM64) += sha512-arm64.o
sha512-arm64-y := sha512-glue.o sha512-core.o
+obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha20-neon.o
+chacha20-neon-y := chacha20-neon-core.o chacha20-neon-glue.o
+
AFLAGS_aes-ce.o := -DINTERLEAVE=4
AFLAGS_aes-neon.o := -DINTERLEAVE=4
diff --git a/arch/arm64/crypto/chacha20-neon-core.S b/arch/arm64/crypto/chacha20-neon-core.S
new file mode 100644
index 000000000000..13c85e272c2a
--- /dev/null
+++ b/arch/arm64/crypto/chacha20-neon-core.S
@@ -0,0 +1,450 @@
+/*
+ * ChaCha20 256-bit cipher algorithm, RFC7539, arm64 NEON functions
+ *
+ * Copyright (C) 2016 Linaro, Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on:
+ * ChaCha20 256-bit cipher algorithm, RFC7539, x64 SSSE3 functions
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/linkage.h>
+
+ .text
+ .align 6
+
+ENTRY(chacha20_block_xor_neon)
+ // x0: Input state matrix, s
+ // x1: 1 data block output, o
+ // x2: 1 data block input, i
+
+ //
+ // This function encrypts one ChaCha20 block by loading the state matrix
+ // in four NEON registers. It performs matrix operation on four words in
+ // parallel, but requires shuffling to rearrange the words after each
+ // round.
+ //
+
+ // x0..3 = s0..3
+ adr x3, ROT8
+ ld1 {v0.4s-v3.4s}, [x0]
+ ld1 {v8.4s-v11.4s}, [x0]
+ ld1 {v12.4s}, [x3]
+
+ mov x3, #10
+
+.Ldoubleround:
+ // x0 += x1, x3 = rotl32(x3 ^ x0, 16)
+ add v0.4s, v0.4s, v1.4s
+ eor v3.16b, v3.16b, v0.16b
+ rev32 v3.8h, v3.8h
+
+ // x2 += x3, x1 = rotl32(x1 ^ x2, 12)
+ add v2.4s, v2.4s, v3.4s
+ eor v4.16b, v1.16b, v2.16b
+ shl v1.4s, v4.4s, #12
+ sri v1.4s, v4.4s, #20
+
+ // x0 += x1, x3 = rotl32(x3 ^ x0, 8)
+ add v0.4s, v0.4s, v1.4s
+ eor v3.16b, v3.16b, v0.16b
+ tbl v3.16b, {v3.16b}, v12.16b
+
+ // x2 += x3, x1 = rotl32(x1 ^ x2, 7)
+ add v2.4s, v2.4s, v3.4s
+ eor v4.16b, v1.16b, v2.16b
+ shl v1.4s, v4.4s, #7
+ sri v1.4s, v4.4s, #25
+
+ // x1 = shuffle32(x1, MASK(0, 3, 2, 1))
+ ext v1.16b, v1.16b, v1.16b, #4
+ // x2 = shuffle32(x2, MASK(1, 0, 3, 2))
+ ext v2.16b, v2.16b, v2.16b, #8
+ // x3 = shuffle32(x3, MASK(2, 1, 0, 3))
+ ext v3.16b, v3.16b, v3.16b, #12
+
+ // x0 += x1, x3 = rotl32(x3 ^ x0, 16)
+ add v0.4s, v0.4s, v1.4s
+ eor v3.16b, v3.16b, v0.16b
+ rev32 v3.8h, v3.8h
+
+ // x2 += x3, x1 = rotl32(x1 ^ x2, 12)
+ add v2.4s, v2.4s, v3.4s
+ eor v4.16b, v1.16b, v2.16b
+ shl v1.4s, v4.4s, #12
+ sri v1.4s, v4.4s, #20
+
+ // x0 += x1, x3 = rotl32(x3 ^ x0, 8)
+ add v0.4s, v0.4s, v1.4s
+ eor v3.16b, v3.16b, v0.16b
+ tbl v3.16b, {v3.16b}, v12.16b
+
+ // x2 += x3, x1 = rotl32(x1 ^ x2, 7)
+ add v2.4s, v2.4s, v3.4s
+ eor v4.16b, v1.16b, v2.16b
+ shl v1.4s, v4.4s, #7
+ sri v1.4s, v4.4s, #25
+
+ // x1 = shuffle32(x1, MASK(2, 1, 0, 3))
+ ext v1.16b, v1.16b, v1.16b, #12
+ // x2 = shuffle32(x2, MASK(1, 0, 3, 2))
+ ext v2.16b, v2.16b, v2.16b, #8
+ // x3 = shuffle32(x3, MASK(0, 3, 2, 1))
+ ext v3.16b, v3.16b, v3.16b, #4
+
+ subs x3, x3, #1
+ b.ne .Ldoubleround
+
+ ld1 {v4.16b-v7.16b}, [x2]
+
+ // o0 = i0 ^ (x0 + s0)
+ add v0.4s, v0.4s, v8.4s
+ eor v0.16b, v0.16b, v4.16b
+
+ // o1 = i1 ^ (x1 + s1)
+ add v1.4s, v1.4s, v9.4s
+ eor v1.16b, v1.16b, v5.16b
+
+ // o2 = i2 ^ (x2 + s2)
+ add v2.4s, v2.4s, v10.4s
+ eor v2.16b, v2.16b, v6.16b
+
+ // o3 = i3 ^ (x3 + s3)
+ add v3.4s, v3.4s, v11.4s
+ eor v3.16b, v3.16b, v7.16b
+
+ st1 {v0.16b-v3.16b}, [x1]
+
+ ret
+ENDPROC(chacha20_block_xor_neon)
+
+ .align 6
+ENTRY(chacha20_4block_xor_neon)
+ // x0: Input state matrix, s
+ // x1: 4 data blocks output, o
+ // x2: 4 data blocks input, i
+
+ //
+ // This function encrypts four consecutive ChaCha20 blocks by loading
+ // the state matrix in NEON registers four times. The algorithm performs
+ // each operation on the corresponding word of each state matrix, hence
+ // requires no word shuffling. For final XORing step we transpose the
+ // matrix by interleaving 32- and then 64-bit words, which allows us to
+ // do XOR in NEON registers.
+ //
+ adr x3, CTRINC // ... and ROT8
+ ld1 {v30.4s-v31.4s}, [x3]
+
+ // x0..15[0-3] = s0..3[0..3]
+ mov x4, x0
+ ld4r { v0.4s- v3.4s}, [x4], #16
+ ld4r { v4.4s- v7.4s}, [x4], #16
+ ld4r { v8.4s-v11.4s}, [x4], #16
+ ld4r {v12.4s-v15.4s}, [x4]
+
+ // x12 += counter values 0-3
+ add v12.4s, v12.4s, v30.4s
+
+ mov x3, #10
+
+.Ldoubleround4:
+ // x0 += x4, x12 = rotl32(x12 ^ x0, 16)
+ // x1 += x5, x13 = rotl32(x13 ^ x1, 16)
+ // x2 += x6, x14 = rotl32(x14 ^ x2, 16)
+ // x3 += x7, x15 = rotl32(x15 ^ x3, 16)
+ add v0.4s, v0.4s, v4.4s
+ add v1.4s, v1.4s, v5.4s
+ add v2.4s, v2.4s, v6.4s
+ add v3.4s, v3.4s, v7.4s
+
+ eor v12.16b, v12.16b, v0.16b
+ eor v13.16b, v13.16b, v1.16b
+ eor v14.16b, v14.16b, v2.16b
+ eor v15.16b, v15.16b, v3.16b
+
+ rev32 v12.8h, v12.8h
+ rev32 v13.8h, v13.8h
+ rev32 v14.8h, v14.8h
+ rev32 v15.8h, v15.8h
+
+ // x8 += x12, x4 = rotl32(x4 ^ x8, 12)
+ // x9 += x13, x5 = rotl32(x5 ^ x9, 12)
+ // x10 += x14, x6 = rotl32(x6 ^ x10, 12)
+ // x11 += x15, x7 = rotl32(x7 ^ x11, 12)
+ add v8.4s, v8.4s, v12.4s
+ add v9.4s, v9.4s, v13.4s
+ add v10.4s, v10.4s, v14.4s
+ add v11.4s, v11.4s, v15.4s
+
+ eor v16.16b, v4.16b, v8.16b
+ eor v17.16b, v5.16b, v9.16b
+ eor v18.16b, v6.16b, v10.16b
+ eor v19.16b, v7.16b, v11.16b
+
+ shl v4.4s, v16.4s, #12
+ shl v5.4s, v17.4s, #12
+ shl v6.4s, v18.4s, #12
+ shl v7.4s, v19.4s, #12
+
+ sri v4.4s, v16.4s, #20
+ sri v5.4s, v17.4s, #20
+ sri v6.4s, v18.4s, #20
+ sri v7.4s, v19.4s, #20
+
+ // x0 += x4, x12 = rotl32(x12 ^ x0, 8)
+ // x1 += x5, x13 = rotl32(x13 ^ x1, 8)
+ // x2 += x6, x14 = rotl32(x14 ^ x2, 8)
+ // x3 += x7, x15 = rotl32(x15 ^ x3, 8)
+ add v0.4s, v0.4s, v4.4s
+ add v1.4s, v1.4s, v5.4s
+ add v2.4s, v2.4s, v6.4s
+ add v3.4s, v3.4s, v7.4s
+
+ eor v12.16b, v12.16b, v0.16b
+ eor v13.16b, v13.16b, v1.16b
+ eor v14.16b, v14.16b, v2.16b
+ eor v15.16b, v15.16b, v3.16b
+
+ tbl v12.16b, {v12.16b}, v31.16b
+ tbl v13.16b, {v13.16b}, v31.16b
+ tbl v14.16b, {v14.16b}, v31.16b
+ tbl v15.16b, {v15.16b}, v31.16b
+
+ // x8 += x12, x4 = rotl32(x4 ^ x8, 7)
+ // x9 += x13, x5 = rotl32(x5 ^ x9, 7)
+ // x10 += x14, x6 = rotl32(x6 ^ x10, 7)
+ // x11 += x15, x7 = rotl32(x7 ^ x11, 7)
+ add v8.4s, v8.4s, v12.4s
+ add v9.4s, v9.4s, v13.4s
+ add v10.4s, v10.4s, v14.4s
+ add v11.4s, v11.4s, v15.4s
+
+ eor v16.16b, v4.16b, v8.16b
+ eor v17.16b, v5.16b, v9.16b
+ eor v18.16b, v6.16b, v10.16b
+ eor v19.16b, v7.16b, v11.16b
+
+ shl v4.4s, v16.4s, #7
+ shl v5.4s, v17.4s, #7
+ shl v6.4s, v18.4s, #7
+ shl v7.4s, v19.4s, #7
+
+ sri v4.4s, v16.4s, #25
+ sri v5.4s, v17.4s, #25
+ sri v6.4s, v18.4s, #25
+ sri v7.4s, v19.4s, #25
+
+ // x0 += x5, x15 = rotl32(x15 ^ x0, 16)
+ // x1 += x6, x12 = rotl32(x12 ^ x1, 16)
+ // x2 += x7, x13 = rotl32(x13 ^ x2, 16)
+ // x3 += x4, x14 = rotl32(x14 ^ x3, 16)
+ add v0.4s, v0.4s, v5.4s
+ add v1.4s, v1.4s, v6.4s
+ add v2.4s, v2.4s, v7.4s
+ add v3.4s, v3.4s, v4.4s
+
+ eor v15.16b, v15.16b, v0.16b
+ eor v12.16b, v12.16b, v1.16b
+ eor v13.16b, v13.16b, v2.16b
+ eor v14.16b, v14.16b, v3.16b
+
+ rev32 v15.8h, v15.8h
+ rev32 v12.8h, v12.8h
+ rev32 v13.8h, v13.8h
+ rev32 v14.8h, v14.8h
+
+ // x10 += x15, x5 = rotl32(x5 ^ x10, 12)
+ // x11 += x12, x6 = rotl32(x6 ^ x11, 12)
+ // x8 += x13, x7 = rotl32(x7 ^ x8, 12)
+ // x9 += x14, x4 = rotl32(x4 ^ x9, 12)
+ add v10.4s, v10.4s, v15.4s
+ add v11.4s, v11.4s, v12.4s
+ add v8.4s, v8.4s, v13.4s
+ add v9.4s, v9.4s, v14.4s
+
+ eor v16.16b, v5.16b, v10.16b
+ eor v17.16b, v6.16b, v11.16b
+ eor v18.16b, v7.16b, v8.16b
+ eor v19.16b, v4.16b, v9.16b
+
+ shl v5.4s, v16.4s, #12
+ shl v6.4s, v17.4s, #12
+ shl v7.4s, v18.4s, #12
+ shl v4.4s, v19.4s, #12
+
+ sri v5.4s, v16.4s, #20
+ sri v6.4s, v17.4s, #20
+ sri v7.4s, v18.4s, #20
+ sri v4.4s, v19.4s, #20
+
+ // x0 += x5, x15 = rotl32(x15 ^ x0, 8)
+ // x1 += x6, x12 = rotl32(x12 ^ x1, 8)
+ // x2 += x7, x13 = rotl32(x13 ^ x2, 8)
+ // x3 += x4, x14 = rotl32(x14 ^ x3, 8)
+ add v0.4s, v0.4s, v5.4s
+ add v1.4s, v1.4s, v6.4s
+ add v2.4s, v2.4s, v7.4s
+ add v3.4s, v3.4s, v4.4s
+
+ eor v15.16b, v15.16b, v0.16b
+ eor v12.16b, v12.16b, v1.16b
+ eor v13.16b, v13.16b, v2.16b
+ eor v14.16b, v14.16b, v3.16b
+
+ tbl v15.16b, {v15.16b}, v31.16b
+ tbl v12.16b, {v12.16b}, v31.16b
+ tbl v13.16b, {v13.16b}, v31.16b
+ tbl v14.16b, {v14.16b}, v31.16b
+
+ // x10 += x15, x5 = rotl32(x5 ^ x10, 7)
+ // x11 += x12, x6 = rotl32(x6 ^ x11, 7)
+ // x8 += x13, x7 = rotl32(x7 ^ x8, 7)
+ // x9 += x14, x4 = rotl32(x4 ^ x9, 7)
+ add v10.4s, v10.4s, v15.4s
+ add v11.4s, v11.4s, v12.4s
+ add v8.4s, v8.4s, v13.4s
+ add v9.4s, v9.4s, v14.4s
+
+ eor v16.16b, v5.16b, v10.16b
+ eor v17.16b, v6.16b, v11.16b
+ eor v18.16b, v7.16b, v8.16b
+ eor v19.16b, v4.16b, v9.16b
+
+ shl v5.4s, v16.4s, #7
+ shl v6.4s, v17.4s, #7
+ shl v7.4s, v18.4s, #7
+ shl v4.4s, v19.4s, #7
+
+ sri v5.4s, v16.4s, #25
+ sri v6.4s, v17.4s, #25
+ sri v7.4s, v18.4s, #25
+ sri v4.4s, v19.4s, #25
+
+ subs x3, x3, #1
+ b.ne .Ldoubleround4
+
+ ld4r {v16.4s-v19.4s}, [x0], #16
+ ld4r {v20.4s-v23.4s}, [x0], #16
+
+ // x12 += counter values 0-3
+ add v12.4s, v12.4s, v30.4s
+
+ // x0[0-3] += s0[0]
+ // x1[0-3] += s0[1]
+ // x2[0-3] += s0[2]
+ // x3[0-3] += s0[3]
+ add v0.4s, v0.4s, v16.4s
+ add v1.4s, v1.4s, v17.4s
+ add v2.4s, v2.4s, v18.4s
+ add v3.4s, v3.4s, v19.4s
+
+ ld4r {v24.4s-v27.4s}, [x0], #16
+ ld4r {v28.4s-v31.4s}, [x0]
+
+ // x4[0-3] += s1[0]
+ // x5[0-3] += s1[1]
+ // x6[0-3] += s1[2]
+ // x7[0-3] += s1[3]
+ add v4.4s, v4.4s, v20.4s
+ add v5.4s, v5.4s, v21.4s
+ add v6.4s, v6.4s, v22.4s
+ add v7.4s, v7.4s, v23.4s
+
+ // x8[0-3] += s2[0]
+ // x9[0-3] += s2[1]
+ // x10[0-3] += s2[2]
+ // x11[0-3] += s2[3]
+ add v8.4s, v8.4s, v24.4s
+ add v9.4s, v9.4s, v25.4s
+ add v10.4s, v10.4s, v26.4s
+ add v11.4s, v11.4s, v27.4s
+
+ // x12[0-3] += s3[0]
+ // x13[0-3] += s3[1]
+ // x14[0-3] += s3[2]
+ // x15[0-3] += s3[3]
+ add v12.4s, v12.4s, v28.4s
+ add v13.4s, v13.4s, v29.4s
+ add v14.4s, v14.4s, v30.4s
+ add v15.4s, v15.4s, v31.4s
+
+ // interleave 32-bit words in state n, n+1
+ zip1 v16.4s, v0.4s, v1.4s
+ zip2 v17.4s, v0.4s, v1.4s
+ zip1 v18.4s, v2.4s, v3.4s
+ zip2 v19.4s, v2.4s, v3.4s
+ zip1 v20.4s, v4.4s, v5.4s
+ zip2 v21.4s, v4.4s, v5.4s
+ zip1 v22.4s, v6.4s, v7.4s
+ zip2 v23.4s, v6.4s, v7.4s
+ zip1 v24.4s, v8.4s, v9.4s
+ zip2 v25.4s, v8.4s, v9.4s
+ zip1 v26.4s, v10.4s, v11.4s
+ zip2 v27.4s, v10.4s, v11.4s
+ zip1 v28.4s, v12.4s, v13.4s
+ zip2 v29.4s, v12.4s, v13.4s
+ zip1 v30.4s, v14.4s, v15.4s
+ zip2 v31.4s, v14.4s, v15.4s
+
+ // interleave 64-bit words in state n, n+2
+ zip1 v0.2d, v16.2d, v18.2d
+ zip2 v4.2d, v16.2d, v18.2d
+ zip1 v8.2d, v17.2d, v19.2d
+ zip2 v12.2d, v17.2d, v19.2d
+ ld1 {v16.16b-v19.16b}, [x2], #64
+
+ zip1 v1.2d, v20.2d, v22.2d
+ zip2 v5.2d, v20.2d, v22.2d
+ zip1 v9.2d, v21.2d, v23.2d
+ zip2 v13.2d, v21.2d, v23.2d
+ ld1 {v20.16b-v23.16b}, [x2], #64
+
+ zip1 v2.2d, v24.2d, v26.2d
+ zip2 v6.2d, v24.2d, v26.2d
+ zip1 v10.2d, v25.2d, v27.2d
+ zip2 v14.2d, v25.2d, v27.2d
+ ld1 {v24.16b-v27.16b}, [x2], #64
+
+ zip1 v3.2d, v28.2d, v30.2d
+ zip2 v7.2d, v28.2d, v30.2d
+ zip1 v11.2d, v29.2d, v31.2d
+ zip2 v15.2d, v29.2d, v31.2d
+ ld1 {v28.16b-v31.16b}, [x2]
+
+ // xor with corresponding input, write to output
+ eor v16.16b, v16.16b, v0.16b
+ eor v17.16b, v17.16b, v1.16b
+ eor v18.16b, v18.16b, v2.16b
+ eor v19.16b, v19.16b, v3.16b
+ eor v20.16b, v20.16b, v4.16b
+ eor v21.16b, v21.16b, v5.16b
+ st1 {v16.16b-v19.16b}, [x1], #64
+ eor v22.16b, v22.16b, v6.16b
+ eor v23.16b, v23.16b, v7.16b
+ eor v24.16b, v24.16b, v8.16b
+ eor v25.16b, v25.16b, v9.16b
+ st1 {v20.16b-v23.16b}, [x1], #64
+ eor v26.16b, v26.16b, v10.16b
+ eor v27.16b, v27.16b, v11.16b
+ eor v28.16b, v28.16b, v12.16b
+ st1 {v24.16b-v27.16b}, [x1], #64
+ eor v29.16b, v29.16b, v13.16b
+ eor v30.16b, v30.16b, v14.16b
+ eor v31.16b, v31.16b, v15.16b
+ st1 {v28.16b-v31.16b}, [x1]
+
+ ret
+ENDPROC(chacha20_4block_xor_neon)
+
+CTRINC: .word 0, 1, 2, 3
+ROT8: .word 0x02010003, 0x06050407, 0x0a09080b, 0x0e0d0c0f
diff --git a/arch/arm64/crypto/chacha20-neon-glue.c b/arch/arm64/crypto/chacha20-neon-glue.c
new file mode 100644
index 000000000000..a7f2337d46cf
--- /dev/null
+++ b/arch/arm64/crypto/chacha20-neon-glue.c
@@ -0,0 +1,127 @@
+/*
+ * ChaCha20 256-bit cipher algorithm, RFC7539, arm64 NEON functions
+ *
+ * Copyright (C) 2016 Linaro, Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on:
+ * ChaCha20 256-bit cipher algorithm, RFC7539, SIMD glue code
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <crypto/algapi.h>
+#include <crypto/chacha20.h>
+#include <crypto/internal/skcipher.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+
+asmlinkage void chacha20_block_xor_neon(u32 *state, u8 *dst, const u8 *src);
+asmlinkage void chacha20_4block_xor_neon(u32 *state, u8 *dst, const u8 *src);
+
+static void chacha20_doneon(u32 *state, u8 *dst, const u8 *src,
+ unsigned int bytes)
+{
+ u8 buf[CHACHA20_BLOCK_SIZE];
+
+ while (bytes >= CHACHA20_BLOCK_SIZE * 4) {
+ chacha20_4block_xor_neon(state, dst, src);
+ bytes -= CHACHA20_BLOCK_SIZE * 4;
+ src += CHACHA20_BLOCK_SIZE * 4;
+ dst += CHACHA20_BLOCK_SIZE * 4;
+ state[12] += 4;
+ }
+ while (bytes >= CHACHA20_BLOCK_SIZE) {
+ chacha20_block_xor_neon(state, dst, src);
+ bytes -= CHACHA20_BLOCK_SIZE;
+ src += CHACHA20_BLOCK_SIZE;
+ dst += CHACHA20_BLOCK_SIZE;
+ state[12]++;
+ }
+ if (bytes) {
+ memcpy(buf, src, bytes);
+ chacha20_block_xor_neon(state, buf, buf);
+ memcpy(dst, buf, bytes);
+ }
+}
+
+static int chacha20_neon(struct skcipher_request *req)
+{
+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+ struct chacha20_ctx *ctx = crypto_skcipher_ctx(tfm);
+ struct skcipher_walk walk;
+ u32 state[16];
+ int err;
+
+ if (req->cryptlen <= CHACHA20_BLOCK_SIZE)
+ return crypto_chacha20_crypt(req);
+
+ err = skcipher_walk_virt(&walk, req, true);
+
+ crypto_chacha20_init(state, ctx, walk.iv);
+
+ kernel_neon_begin();
+ while (walk.nbytes > 0) {
+ unsigned int nbytes = walk.nbytes;
+
+ if (nbytes < walk.total)
+ nbytes = round_down(nbytes, walk.stride);
+
+ chacha20_doneon(state, walk.dst.virt.addr, walk.src.virt.addr,
+ nbytes);
+ err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
+ }
+ kernel_neon_end();
+
+ return err;
+}
+
+static struct skcipher_alg alg = {
+ .base.cra_name = "chacha20",
+ .base.cra_driver_name = "chacha20-neon",
+ .base.cra_priority = 300,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct chacha20_ctx),
+ .base.cra_alignmask = 1,
+ .base.cra_module = THIS_MODULE,
+
+ .min_keysize = CHACHA20_KEY_SIZE,
+ .max_keysize = CHACHA20_KEY_SIZE,
+ .ivsize = CHACHA20_IV_SIZE,
+ .chunksize = CHACHA20_BLOCK_SIZE,
+ .walksize = 4 * CHACHA20_BLOCK_SIZE,
+ .setkey = crypto_chacha20_setkey,
+ .encrypt = chacha20_neon,
+ .decrypt = chacha20_neon,
+};
+
+static int __init chacha20_simd_mod_init(void)
+{
+ if (!(elf_hwcap & HWCAP_ASIMD))
+ return -ENODEV;
+
+ return crypto_register_skcipher(&alg);
+}
+
+static void __exit chacha20_simd_mod_fini(void)
+{
+ crypto_unregister_skcipher(&alg);
+}
+
+module_init(chacha20_simd_mod_init);
+module_exit(chacha20_simd_mod_fini);
+
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("chacha20");
--
2.7.4
^ permalink raw reply related
* [PATCH v2 0/7] crypto: ARM/arm64 - AES and ChaCha20 updates for v4.11
From: Ard Biesheuvel @ 2017-01-11 16:41 UTC (permalink / raw)
To: linux-arm-kernel
This adds ARM and arm64 implementations of ChaCha20, scalar AES and SIMD
AES (using bit slicing). The SIMD algorithms in this series take advantage
of the new skcipher walksize attribute to iterate over the input in the most
efficient manner possible.
Patch #1 adds a NEON implementation of ChaCha20 for ARM.
Patch #2 adds a NEON implementation of ChaCha20 for arm64.
Patch #3 modifies the existing NEON and ARMv8 Crypto Extensions implementations
of AES-CTR to be available as a synchronous skcipher as well. This is intended
for the mac80211 code, which uses synchronous encapsulations of ctr(aes)
[ccm, gcm] in softirq context, during which arm64 supports use of SIMD code.
Patch #4 adds a scalar implementation of AES for arm64, using the key schedule
generation routines and lookup tables of the generic code in crypto/aes_generic.
Patch #5 does the same for ARM, replacing existing scalar code that originated
in the OpenSSL project, and contains redundant key schedule generation routines
and lookup tables (and is slightly slower on modern cores)
Patch #6 replaces the ARM bit sliced NEON code with a new implementation that
has a number of advantages over the original code (which also originated in the
OpenSSL project.) The performance should be identical.
Patch #7 adds a port of the ARM bit-sliced AES code to arm64, in ECB, CBC, CTR
and XTS modes.
Due to the size of patch #7, it may be difficult to apply these patches from
patchwork, so I pushed them here as well:
git://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git crypto-arm-v4.11
https://git.kernel.org/cgit/linux/kernel/git/ardb/linux.git/log/?h=crypto-arm-v4.11
Ard Biesheuvel (7):
crypto: arm64/chacha20 - implement NEON version based on SSE3 code
crypto: arm/chacha20 - implement NEON version based on SSE3 code
crypto: arm64/aes-blk - expose AES-CTR as synchronous cipher as well
crypto: arm64/aes - add scalar implementation
crypto: arm/aes - replace scalar AES cipher
crypto: arm/aes - replace bit-sliced OpenSSL NEON code
crypto: arm64/aes - reimplement bit-sliced ARM/NEON implementation for
arm64
arch/arm/crypto/Kconfig | 27 +-
arch/arm/crypto/Makefile | 11 +-
arch/arm/crypto/aes-armv4.S | 1089 ---------
arch/arm/crypto/aes-cipher-core.S | 179 ++
arch/arm/crypto/aes-cipher-glue.c | 74 +
arch/arm/crypto/aes-neonbs-core.S | 1021 ++++++++
arch/arm/crypto/aes-neonbs-glue.c | 405 ++++
arch/arm/crypto/aes_glue.c | 98 -
arch/arm/crypto/aes_glue.h | 19 -
arch/arm/crypto/aesbs-core.S_shipped | 2548 --------------------
arch/arm/crypto/aesbs-glue.c | 367 ---
arch/arm/crypto/bsaes-armv7.pl | 2471 -------------------
arch/arm/crypto/chacha20-neon-core.S | 524 ++++
arch/arm/crypto/chacha20-neon-glue.c | 128 +
arch/arm64/crypto/Kconfig | 17 +
arch/arm64/crypto/Makefile | 9 +
arch/arm64/crypto/aes-cipher-core.S | 127 +
arch/arm64/crypto/aes-cipher-glue.c | 69 +
arch/arm64/crypto/aes-glue.c | 25 +-
arch/arm64/crypto/aes-neonbs-core.S | 963 ++++++++
arch/arm64/crypto/aes-neonbs-glue.c | 420 ++++
arch/arm64/crypto/chacha20-neon-core.S | 450 ++++
arch/arm64/crypto/chacha20-neon-glue.c | 127 +
23 files changed, 4549 insertions(+), 6619 deletions(-)
delete mode 100644 arch/arm/crypto/aes-armv4.S
create mode 100644 arch/arm/crypto/aes-cipher-core.S
create mode 100644 arch/arm/crypto/aes-cipher-glue.c
create mode 100644 arch/arm/crypto/aes-neonbs-core.S
create mode 100644 arch/arm/crypto/aes-neonbs-glue.c
delete mode 100644 arch/arm/crypto/aes_glue.c
delete mode 100644 arch/arm/crypto/aes_glue.h
delete mode 100644 arch/arm/crypto/aesbs-core.S_shipped
delete mode 100644 arch/arm/crypto/aesbs-glue.c
delete mode 100644 arch/arm/crypto/bsaes-armv7.pl
create mode 100644 arch/arm/crypto/chacha20-neon-core.S
create mode 100644 arch/arm/crypto/chacha20-neon-glue.c
create mode 100644 arch/arm64/crypto/aes-cipher-core.S
create mode 100644 arch/arm64/crypto/aes-cipher-glue.c
create mode 100644 arch/arm64/crypto/aes-neonbs-core.S
create mode 100644 arch/arm64/crypto/aes-neonbs-glue.c
create mode 100644 arch/arm64/crypto/chacha20-neon-core.S
create mode 100644 arch/arm64/crypto/chacha20-neon-glue.c
--
2.7.4
^ permalink raw reply
* [PATCH net-next] net: thunderx: Fix error return code in nicvf_open()
From: Wei Yongjun @ 2017-01-11 16:32 UTC (permalink / raw)
To: linux-arm-kernel
From: Wei Yongjun <weiyongjun1@huawei.com>
Fix to return a negative error code from the error handling
case instead of 0, as done elsewhere in this function.
Fixes: 712c31853440 ("net: thunderx: Program LMAC credits based on MTU")
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 273eafd..a25bb6e 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -1274,7 +1274,8 @@ int nicvf_open(struct net_device *netdev)
/* Configure receive side scaling and MTU */
if (!nic->sqs_mode) {
nicvf_rss_init(nic);
- if (nicvf_update_hw_max_frs(nic, netdev->mtu))
+ err = nicvf_update_hw_max_frs(nic, netdev->mtu);
+ if (err)
goto cleanup;
/* Clear percpu stats */
^ permalink raw reply related
* [kvm-unit-tests PATCH 6/6] run_tests: allow passing of options to QEMU
From: Alex Bennée @ 2017-01-11 16:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170111162841.15569-1-alex.bennee@linaro.org>
This allows additional options to be passed to QEMU. It follows the
convention of passing parameters after a -- to the child process. In
my case I'm using it to toggle MTTCG on an off:
./run_tests.sh -- --accel tcg,thread=multi
Signed-off-by: Alex Benn?e <alex.bennee@linaro.org>
---
v1
- changes from -o to --
- fixed whitespace damage
---
README.md | 6 ++++++
run_tests.sh | 13 +++++++++++--
scripts/functions.bash | 7 ++++---
3 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index fa3a445..1bd6dcb 100644
--- a/README.md
+++ b/README.md
@@ -55,6 +55,12 @@ To extend or disable the timeouts:
TIMEOUT=0 ./run_tests.sh
+Any arguments past the end-of-arguments marker (--) is passed on down
+to the QEMU invocation. This can of course be combined with the other
+modifiers:
+
+ ACCEL=tcg ./run_tests.sh -v -- --accel tcg,thread=multi
+
# Contributing
## Directory structure
diff --git a/run_tests.sh b/run_tests.sh
index 254129d..3270fba 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -13,7 +13,7 @@ function usage()
{
cat <<EOF
-Usage: $0 [-g group] [-h] [-v]
+Usage: $0 [-g group] [-h] [-v] [-- QEMU options]
-g: Only execute tests in the given group
-h: Output this help text
@@ -22,6 +22,8 @@ Usage: $0 [-g group] [-h] [-v]
Set the environment variable QEMU=/path/to/qemu-system-ARCH to
specify the appropriate qemu binary for ARCH-run.
+All options specified after -- are passed on to QEMU.
+
EOF
}
@@ -29,6 +31,7 @@ RUNTIME_arch_run="./$TEST_DIR/run"
source scripts/runtime.bash
while getopts "g:hv" opt; do
+
case $opt in
g)
only_group=$OPTARG
@@ -46,6 +49,12 @@ while getopts "g:hv" opt; do
esac
done
+# Any options left for QEMU?
+shift $((OPTIND-1))
+if [ "$#" -gt 0 ]; then
+ extra_opts="$@"
+fi
+
RUNTIME_log_stderr () { cat >> test.log; }
RUNTIME_log_stdout () {
if [ "$PRETTY_PRINT_STACKS" = "yes" ]; then
@@ -59,4 +68,4 @@ RUNTIME_log_stdout () {
config=$TEST_DIR/unittests.cfg
rm -f test.log
printf "BUILD_HEAD=$(cat build-head)\n\n" > test.log
-for_each_unittest $config run
+for_each_unittest $config run "$extra_opts"
diff --git a/scripts/functions.bash b/scripts/functions.bash
index ee9143c..60fbc6a 100644
--- a/scripts/functions.bash
+++ b/scripts/functions.bash
@@ -3,10 +3,11 @@ function for_each_unittest()
{
local unittests="$1"
local cmd="$2"
+ local extra_opts=$3
local testname
local smp
local kernel
- local opts
+ local opts=$extra_opts
local groups
local arch
local check
@@ -21,7 +22,7 @@ function for_each_unittest()
testname=${BASH_REMATCH[1]}
smp=1
kernel=""
- opts=""
+ opts=$extra_opts
groups=""
arch=""
check=""
@@ -32,7 +33,7 @@ function for_each_unittest()
elif [[ $line =~ ^smp\ *=\ *(.*)$ ]]; then
smp=${BASH_REMATCH[1]}
elif [[ $line =~ ^extra_params\ *=\ *(.*)$ ]]; then
- opts=${BASH_REMATCH[1]}
+ opts="$opts ${BASH_REMATCH[1]}"
elif [[ $line =~ ^groups\ *=\ *(.*)$ ]]; then
groups=${BASH_REMATCH[1]}
elif [[ $line =~ ^arch\ *=\ *(.*)$ ]]; then
--
2.11.0
^ permalink raw reply related
* [kvm-unit-tests PATCH 5/6] docs: mention modifying env vars in README
From: Alex Bennée @ 2017-01-11 16:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170111162841.15569-1-alex.bennee@linaro.org>
I had started adding a series of flags to control the run-time
behaviour of the tests but it was pointed out env vars can already do
that. Mention them in the README so others can find out to.
Signed-off-by: Alex Benn?e <alex.bennee@linaro.org>
---
README.md | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/README.md b/README.md
index 9462824..fa3a445 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,14 @@ environment variable:
QEMU=/tmp/qemu/x86_64-softmmu/qemu-system-x86_64 ./x86-run ./x86/msr.flat
+To force the acceleration mode:
+
+ ACCEL=tcg ./run_tests.sh
+
+To extend or disable the timeouts:
+
+ TIMEOUT=0 ./run_tests.sh
+
# Contributing
## Directory structure
--
2.11.0
^ permalink raw reply related
* [kvm-unit-tests PATCH 4/6] docs: mention checkpatch in the README
From: Alex Bennée @ 2017-01-11 16:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170111162841.15569-1-alex.bennee@linaro.org>
Signed-off-by: Alex Benn?e <alex.bennee@linaro.org>
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 5027b62..9462824 100644
--- a/README.md
+++ b/README.md
@@ -79,3 +79,4 @@ You can add the following to .git/config to do this automatically for you:
[format]
subjectprefix = kvm-unit-tests PATCH
+Please run the kernel's ./scripts/checkpatch.pl on new patches
--
2.11.0
^ permalink raw reply related
* [kvm-unit-tests PATCH 3/6] docs: move README to README.md and symlink
From: Alex Bennée @ 2017-01-11 16:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170111162841.15569-1-alex.bennee@linaro.org>
This allows a slightly nicer formatting of the text when displayed on
some repository hosts. We keep a symlink from README for the
old-school purists.
Signed-off-by: Alex Benn?e <alex.bennee@linaro.org>
---
README | 69 +----------------------------------------------------
README.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+), 68 deletions(-)
mode change 100644 => 120000 README
create mode 100644 README.md
diff --git a/README b/README
deleted file mode 100644
index f8f196d..0000000
--- a/README
+++ /dev/null
@@ -1,68 +0,0 @@
-Welcome to kvm-unit-tests
-
-See http://www.linux-kvm.org/page/KVM-unit-tests for a high-level
-description of this project, as well as running tests and adding
-tests HOWTOs.
-
-This directory contains sources for a kvm test suite.
-
-To create the test images do
- ./configure
- make
-in this directory. Test images are created in ./<ARCH>/*.flat
-
-Then use the runner script to detect the correct invocation and
-invoke the test, e.g.
- ./x86-run ./x86/msr.flat
-or
- ./run_tests.sh
-to run them all.
-
-To select a specific qemu binary, specify the QEMU=<path>
-environment variable, e.g.
- QEMU=/tmp/qemu/x86_64-softmmu/qemu-system-x86_64 ./x86-run ./x86/msr.flat
-
-To create and use standalone tests do
- ./configure
- make standalone
- (send tests/some-test somewhere)
- (go to somewhere)
- ./some-test
-
-'make install' will install all tests in PREFIX/share/kvm-unit-tests/tests,
-each as a standalone test.
-
-Directory structure:
-.: configure script, top-level Makefile, and run_tests.sh
-./scripts: helper scripts for building and running tests
-./lib: general architecture neutral services for the tests
-./lib/<ARCH>: architecture dependent services for the tests
-./<ARCH>: the sources of the tests and the created objects/images
-
-See <ARCH>/README for architecture specific documentation.
-
-CONTRIBUTING:
-=============
-
-Style
------
-
-Currently there is a mix of indentation styles so any changes to
-existing files should be consistent with the existing style. For new
-files:
-
- - C: please use standard linux-with-tabs
- - Shell: use TABs for indentation
-
-Patches
--------
-
-Patches are welcome at the KVM mailing list <kvm@vger.kernel.org>.
-
-Please prefix messages with: [kvm-unit-tests PATCH]
-
-You can add the following to .git/config to do this automatically for you:
-
-[format]
- subjectprefix = kvm-unit-tests PATCH
-
diff --git a/README b/README
new file mode 120000
index 0000000..42061c0
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+README.md
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5027b62
--- /dev/null
+++ b/README.md
@@ -0,0 +1,81 @@
+# Welcome to kvm-unit-tests
+
+See http://www.linux-kvm.org/page/KVM-unit-tests for a high-level
+description of this project, as well as running tests and adding
+tests HOWTOs.
+
+# Building the tests
+
+This directory contains sources for a kvm test suite.
+
+To create the test images do:
+
+ ./configure
+ make
+
+in this directory. Test images are created in ./<ARCH>/*.flat
+
+## Standalone tests
+
+The tests can be built as standalone
+To create and use standalone tests do:
+
+ ./configure
+ make standalone
+ (send tests/some-test somewhere)
+ (go to somewhere)
+ ./some-test
+
+'make install' will install all tests in PREFIX/share/kvm-unit-tests/tests,
+each as a standalone test.
+
+
+# Running the tests
+
+Then use the runner script to detect the correct invocation and
+invoke the test:
+
+ ./x86-run ./x86/msr.flat
+or:
+
+ ./run_tests.sh
+
+to run them all.
+
+To select a specific qemu binary, specify the QEMU=<path>
+environment variable:
+
+ QEMU=/tmp/qemu/x86_64-softmmu/qemu-system-x86_64 ./x86-run ./x86/msr.flat
+
+# Contributing
+
+## Directory structure
+
+ .: configure script, top-level Makefile, and run_tests.sh
+ ./scripts: helper scripts for building and running tests
+ ./lib: general architecture neutral services for the tests
+ ./lib/<ARCH>: architecture dependent services for the tests
+ ./<ARCH>: the sources of the tests and the created objects/images
+
+See <ARCH>/README for architecture specific documentation.
+
+## Style
+
+Currently there is a mix of indentation styles so any changes to
+existing files should be consistent with the existing style. For new
+files:
+
+ - C: please use standard linux-with-tabs
+ - Shell: use TABs for indentation
+
+## Patches
+
+Patches are welcome at the KVM mailing list <kvm@vger.kernel.org>.
+
+Please prefix messages with: [kvm-unit-tests PATCH]
+
+You can add the following to .git/config to do this automatically for you:
+
+ [format]
+ subjectprefix = kvm-unit-tests PATCH
+
--
2.11.0
^ permalink raw reply related
* [kvm-unit-tests PATCH 2/6] lib/pci: fix BAR format strings
From: Alex Bennée @ 2017-01-11 16:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170111162841.15569-1-alex.bennee@linaro.org>
Using %x as a format string is not portable across 32/64 bit builds.
Use explicit PRIx32 format strings like the 64 bit version above.
Signed-off-by: Alex Benn?e <alex.bennee@linaro.org>
---
lib/pci.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/pci.c b/lib/pci.c
index 6416191..597d8f2 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -67,7 +67,7 @@ bool pci_setup_msi(struct pci_dev *dev, uint64_t msi_addr, uint32_t msi_data)
pci_config_writel(addr, offset + PCI_MSI_DATA_32, msi_data);
printf("MSI: dev 0x%x init 32bit address: ", addr);
}
- printf("addr=0x%lx, data=0x%x\n", msi_addr, msi_data);
+ printf("addr=0x%" PRIx64 ", data=0x%" PRIx32 "\n", msi_addr, msi_data);
msi_control |= PCI_MSI_FLAGS_ENABLE;
pci_config_writew(addr, offset + PCI_MSI_FLAGS, msi_control);
@@ -237,7 +237,7 @@ void pci_bar_print(struct pci_dev *dev, int bar_num)
printf("BAR#%d,%d [%" PRIx64 "-%" PRIx64 " ",
bar_num, bar_num + 1, start, end);
} else {
- printf("BAR#%d [%02x-%02x ",
+ printf("BAR#%d [%" PRIx32 "-%" PRIx32 " ",
bar_num, (uint32_t)start, (uint32_t)end);
}
--
2.11.0
^ permalink raw reply related
* [kvm-unit-tests PATCH 1/6] libcflat: add PRI(dux)32 format types
From: Alex Bennée @ 2017-01-11 16:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170111162841.15569-1-alex.bennee@linaro.org>
So we can have portable formatting of uint32_t types. However there is
a catch. Different compilers can use legally subtly different types
though so we need to probe the compiler defined intdef.h first.
Signed-off-by: Alex Benn?e <alex.bennee@linaro.org>
---
Makefile | 1 +
configure | 13 +++++++++++++
lib/libcflat.h | 9 +++++++++
3 files changed, 23 insertions(+)
diff --git a/Makefile b/Makefile
index a32333b..9822d9a 100644
--- a/Makefile
+++ b/Makefile
@@ -55,6 +55,7 @@ CFLAGS += $(fomit_frame_pointer)
CFLAGS += $(fno_stack_protector)
CFLAGS += $(fno_stack_protector_all)
CFLAGS += $(wno_frame_address)
+CFLAGS += $(if $(U32_LONG_FMT),-D__U32_LONG_FMT__,)
CXXFLAGS += $(CFLAGS)
diff --git a/configure b/configure
index 995c8fa..127868c 100755
--- a/configure
+++ b/configure
@@ -109,6 +109,18 @@ if [ -f $testdir/run ]; then
ln -fs $testdir/run $testdir-run
fi
+# check if uint32_t needs a long format modifier
+cat << EOF > lib_test.c
+#include <inttypes.h>
+EOF
+
+$cross_prefix$cc lib_test.c -E | grep "typedef" | grep "long" | grep "uint32_t" &> /dev/null
+exit=$?
+if [ $exit -eq 0 ]; then
+ u32_long=true
+fi
+rm -f lib_test.c
+
# check for dependent 32 bit libraries
if [ "$arch" != "arm" ]; then
cat << EOF > lib_test.c
@@ -155,4 +167,5 @@ TEST_DIR=$testdir
FIRMWARE=$firmware
ENDIAN=$endian
PRETTY_PRINT_STACKS=$pretty_print_stacks
+U32_LONG_FMT=$u32_long
EOF
diff --git a/lib/libcflat.h b/lib/libcflat.h
index 380395f..e80fc50 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -58,12 +58,21 @@ typedef _Bool bool;
#define true 1
#if __SIZEOF_LONG__ == 8
+# define __PRI32_PREFIX
# define __PRI64_PREFIX "l"
# define __PRIPTR_PREFIX "l"
#else
+#if defined(__U32_LONG_FMT__)
+# define __PRI32_PREFIX "l"
+#else
+# define __PRI32_PREFIX
+#endif
# define __PRI64_PREFIX "ll"
# define __PRIPTR_PREFIX
#endif
+#define PRId32 __PRI32_PREFIX "d"
+#define PRIu32 __PRI32_PREFIX "u"
+#define PRIx32 __PRI32_PREFIX "x"
#define PRId64 __PRI64_PREFIX "d"
#define PRIu64 __PRI64_PREFIX "u"
#define PRIx64 __PRI64_PREFIX "x"
--
2.11.0
^ permalink raw reply related
* [kvm-unit-tests PATCH 0/6] Documentation misc fixes
From: Alex Bennée @ 2017-01-11 16:28 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
I broke these out of my earlier MTTCG test series as they are not
strictly related. The libcflat/pci fixes are a result of trying to
cross-compile arm32 binaries on my arm64 box with a arm-none-abi
compiler. I've also tidied up some documentation (along with a
controversial move to Markdown ;-). And finally the run_script now
follows the convention of passing arguments after -- to the child
process.
Alex Benn?e (6):
libcflat: add PRI(dux)32 format types
lib/pci: fix BAR format strings
docs: move README to README.md and symlink
docs: mention checkpatch in the README
docs: mention modifying env vars in README
run_tests: allow passing of options to QEMU
Makefile | 1 +
README | 69 +-----------------------------------
README.md | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++
configure | 13 +++++++
lib/libcflat.h | 9 +++++
lib/pci.c | 4 +--
run_tests.sh | 13 +++++--
scripts/functions.bash | 7 ++--
8 files changed, 137 insertions(+), 75 deletions(-)
mode change 100644 => 120000 README
create mode 100644 README.md
--
2.11.0
^ permalink raw reply
* [PATCH] arm64: dts: exynos: Replace small letter of base address/offset on Exynos5433
From: Krzysztof Kozlowski @ 2017-01-11 16:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484096148-17120-1-git-send-email-cw00.choi@samsung.com>
On Wed, Jan 11, 2017 at 09:55:48AM +0900, Chanwoo Choi wrote:
> This patch replaces the small letter of base address, offset and hex value
> with the capital letter to keep the consistency on Exynos5433.
>
> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
> ---
> arch/arm64/boot/dts/exynos/exynos5433.dtsi | 14 +++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/exynos/exynos5433.dtsi b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
> index abaf6b4d599d..d7ed1a68b6fd 100644
> --- a/arch/arm64/boot/dts/exynos/exynos5433.dtsi
> +++ b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
> @@ -231,7 +231,7 @@
> compatible = "arm,psci";
> method = "smc";
> cpu_off = <0x84000002>;
> - cpu_on = <0xC4000003>;
> + cpu_on = <0xc4000003>;
There is no point of such "improvements". This is just unnecessary
churn.
Sometimes such things are accepted as part of some bigger work (vide
recent Andrzej's sysmmu for HDMI/TV). But on its own? No sense at all.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH v2 5/5] ARM: dts: Add LEGO MINDSTORMS EV3 dts
From: David Lechner @ 2017-01-11 16:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e8136b8a-b8f7-7b1b-693a-955dc17f1de9@ti.com>
On 01/11/2017 04:42 AM, Sekhar Nori wrote:
> On Friday 06 January 2017 10:03 AM, David Lechner wrote:
>
>> + beeper {
>> + compatible = "pwm-beeper";
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&ehrpwm0b_pins>, <&_pins>;
>> + pwms = <&ehrpwm0 1 0 0>;
>> + enable-gpios = <&gpio 111 GPIO_ACTIVE_HIGH>;
>
> Since the enable-gpios binding for pwm beeper is still not accepted, can
> you drop the property or the node itself (if that makes more sense)?
No sound will come out of the speaker without enabling this gpio. So, I
guess I will just drop this node for now.
>
>> +&spi0 {
>> + status = "okay";
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>, <&spi0_cs3_pin>;
>> +
>> + flash at 0 {
>> + compatible = "n25q128a13", "jedec,spi-nor";
>> + reg = <0>;
>> + spi-max-frequency = <50000000>;
>> + ti,spi-wdelay = <8>;
>> +
>> + /* Partitions are based on the official firmware from LEGO */
>> + partitions {
>> + #address-cells = <1>;
>> + #size-cells = <1>;
>> + partition at 0 {
>> + label = "U-Boot";
>> + reg = <0 0x40000>;
>> + };
>> +
>> + partition at 40000 {
>> + label = "U-Boot Env";
>> + reg = <0x40000 0x10000>;
>> + };
>> +
>> + partition at 50000 {
>> + label = "Kernel";
>> + reg = <0x50000 0x200000>;
>> + };
>> +
>> + partition at 250000 {
>> + label = "Filesystem";
>> + reg = <0x250000 0xa50000>;
>> + };
>> +
>> + partition at cb0000 {
>> + label = "Storage";
>> + reg = <0xcb0000 0x2f0000>;
>> + };
>> + };
>> + };
>> +
>> + adc at 3 {
>> + compatible = "ti-ads7957";
>
> So looks like this works because of_register_spi_device() sets up
> modalias of spi device from compatible string. I am fine with it, just
> highlighting it here to make sure this is acceptable practice. I did not
> really find any precedence for using SPI device name as compatible
> property in existing DTS files.
Indeed. It looks like this sort of "trivial" device binding is just used
for i2c devices. I will submit some patches to add proper device tree
bindings and change this to "ti,ads7957".
>
>> + reg = <3>;
>> + spi-max-frequency = <10000000>;
>> + refin-supply = <&adc_ref>;
>> + };
>
> Rest of the patch looks good to me.
>
> Thanks,
> Sekhar
>
^ permalink raw reply
* [PATCH v2] arm64: do not set dma masks that device connection can't handle
From: Arnd Bergmann @ 2017-01-11 16:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <7c6a1523-e41b-ad83-501a-27c260b9f9ee@cogentembedded.com>
On Wednesday, January 11, 2017 3:37:22 PM CET Nikita Yushchenko wrote:
> > I actually have a third variation of this problem involving a PCI root
> > complex which *could* drive full-width (40-bit) addresses, but won't,
> > due to the way its PCI<->AXI interface is programmed. That would require
> > even more complicated dma-ranges handling to describe the windows of
> > valid physical addresses which it *will* pass, so I'm not pressing the
> > issue - let's just get the basic DMA mask case fixed first.
>
> R-Car + NVMe is actually not "basic case".
>
> It has PCI<->AXI interface involved.
> PCI addresses are 64-bit and controller does handle 64-bit addresses
> there. Mapping between PCI addresses and AXI addresses is defined. But
> AXI is 32-bit.
>
> SoC has iommu that probably could be used between PCIe module and RAM.
> Although AFAIK nobody made that working yet.
>
> Board I work with has 4G of RAM, in 4 banks, located at different parts
> of wide address space, and only one of them is below 4G. But if iommu is
> capable of translating addresses such that 4 gigabyte banks map to first
> 4 gigabytes of address space, then all memory will become available for
> DMA from PCIe device.
You can in theory handle this by defining your own platform specific
dma_map_ops, as we used to do in the old days. Unfortunately, the modern
way of using the generic IOVA allocation can't handle really it, so it's
unclear if the work that would be necessary to support it (and the long
term maintenance cost) outweigh the benefits.
The more likely option here is to try harder to get the IOMMU working
(or show that it's impossible but make sure the next chip gets it right).
Arnd
^ permalink raw reply
* [PATCH] clk: stm32f4: avoid uninitialized variable access
From: Gabriel Fernandez @ 2017-01-11 16:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170111134107.3821564-1-arnd@arndb.de>
On 01/11/2017 02:40 PM, Arnd Bergmann wrote:
> The failure path in the newly added function tries to free an
> uninitialized pointer:
>
> drivers/clk/clk-stm32f4.c: In function 'stm32f4_rcc_init':
> drivers/clk/clk-stm32f4.c:1106:4: error: 'gate' may be used uninitialized in this function [-Werror=maybe-uninitialized]
>
> I'm adding an initialization to NULL here to make the kfree()
> succeed, and I'm also rearranging the cleanup so that the
> same kfree() is used for any error path, making the function
> slightly more robust against newly introduced bugs in the
> error handling.
>
> Fixes: daf2d117cbca ("clk: stm32f4: Add lcd-tft clock")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> drivers/clk/clk-stm32f4.c | 12 +++++++-----
> 1 file changed, 7 insertions(+), 5 deletions(-)
>
>
Acked-by: Gabriel Fernandez <gabriel.fernandez@st.com>
^ permalink raw reply
* [PATCH] arm64: assembler: make adr_l work in modules under KASLR
From: Ard Biesheuvel @ 2017-01-11 16:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170111153447.GD26344@leverpostej>
On 11 January 2017 at 15:34, Mark Rutland <mark.rutland@arm.com> wrote:
> On Wed, Jan 11, 2017 at 03:25:09PM +0000, Ard Biesheuvel wrote:
>> On 11 January 2017 at 15:18, Mark Rutland <mark.rutland@arm.com> wrote:
>> > Hi Ard,
>> >
>> > On Wed, Jan 11, 2017 at 02:54:53PM +0000, Ard Biesheuvel wrote:
>> >> When CONFIG_RANDOMIZE_MODULE_REGION_FULL=y, the offset between loaded
>> >> modules and the core kernel may exceed 4 GB, putting symbols exported
>> >> by the core kernel out of the reach of the ordinary adrp/add instruction
>> >> pairs used to generate relative symbol references. So make the adr_l
>> >> macro emit a movz/movk sequence instead when executing in module context.
>> >
>> > AFAICT, we only use adr_l in a few assembly files that shouldn't matter
>> > to modules:
>> >
>> > * arch/arm64/kernel/head.S
>> > * arch/arm64/kernel/sleep.S
>> > * arch/arm64/kvm/hyp-init.S
>> > * arch/arm64/kvm/hyp/hyp-entry.S
>> >
>> > ... so I don't follow why we need this.
>> >
>> > Have I missed something? Or do you intend to use this in module code in
>> > future?
>>
>> Yes. E.g., the scalar AES cipher that I am proposing for v4.11 reuses
>> the lookup tables from crypto/aes_generic.c, which may be built into
>> the core kernel, while the code itself may be built as a module.
>
> Ah, ok.
>
>> But in general, if the macro is available to modules, I would like to
>> make sure that it does not result in code that builds fine but may
>> fail in some cases only at runtime, especially given the fact that
>> there is also a Cortex-A53 erratum regarding adrp instructions, for
>> which reason we build modules with -mcmodel=large (which amounts to
>> the same thing as the patch above)
>>
>> > It seems somewhat surprising to me to have adr_l expand to something
>> > that doesn't use adr/adrp, but that's not necessarily a problem.
>>
>> I did realise that, but I don't think it is a problem tbh.
>
> In this case it should be fine, certainly.
>
> There are cases like the early boot code and hyp code where it's
> critical that we use adr. It's also possible that we might build
> (modular) drivers which want some idmapped code, where we want adr, so
> it seems unfortunate that this depends on howthe code is built.
>
How would /that/ work? Modules are vmalloc'ed, and not covered by the
ID map to begin with, so it is impossible to execute those adr
instructions in a way that would make them return anything other than
the virtual address of the symbol they refer to.
> So, maybe it's better to have a mov_sym helper for this case, to be
> explicit about what we want? That can use either adr* or mov*, or the
> latter consistently.
>
Well, the point is that adr_l should not be used for modules so adding
something that may be used is fine, but that still leaves the risk
that someone may end up using it in a module.
^ permalink raw reply
* [PATCH 04/15] video: fbdev: use permission-specific DEVICE_ATTR variants
From: Bartlomiej Zolnierkiewicz @ 2017-01-11 16:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477769829-22230-5-git-send-email-Julia.Lawall@lip6.fr>
Hi,
On Saturday, October 29, 2016 09:36:58 PM Julia Lawall wrote:
> Use DEVICE_ATTR_RW for read-write attributes. This simplifies the
> source code, improves readbility, and reduces the chance of
> inconsistencies.
>
> The semantic patch that makes this change is as follows:
> (http://coccinelle.lip6.fr/)
>
> // <smpl>
> @rw@
> declarer name DEVICE_ATTR;
> identifier x,x_show,x_store;
> @@
>
> DEVICE_ATTR(x, \(0644\|S_IRUGO|S_IWUSR\), x_show, x_store);
>
> @script:ocaml@
> x << rw.x;
> x_show << rw.x_show;
> x_store << rw.x_store;
> @@
>
> if not (x^"_show" = x_show && x^"_store" = x_store)
> then Coccilib.include_match false
>
> @@
> declarer name DEVICE_ATTR_RW;
> identifier rw.x,rw.x_show,rw.x_store;
> @@
>
> - DEVICE_ATTR(x, \(0644\|S_IRUGO|S_IWUSR\), x_show, x_store);
> + DEVICE_ATTR_RW(x);
> // </smpl>
>
> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
Thanks, patch queued for 4.11.
Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics
> ---
> drivers/video/fbdev/wm8505fb.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/video/fbdev/wm8505fb.c b/drivers/video/fbdev/wm8505fb.c
> index e925619..253ffe9 100644
> --- a/drivers/video/fbdev/wm8505fb.c
> +++ b/drivers/video/fbdev/wm8505fb.c
> @@ -182,7 +182,7 @@ static ssize_t contrast_store(struct device *dev,
> return count;
> }
>
> -static DEVICE_ATTR(contrast, 0644, contrast_show, contrast_store);
> +static DEVICE_ATTR_RW(contrast);
>
> static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
> {
^ permalink raw reply
* [PATCH] ARM: defconfig: qcom: add APQ8060 DragonBoard devices
From: Andy Gross @ 2017-01-11 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <0cd4197f-0055-bd8b-5d8f-dc16e008c46d@baylibre.com>
On Wed, Jan 11, 2017 at 03:11:01PM +0100, Neil Armstrong wrote:
> On 01/11/2017 03:08 PM, Arnd Bergmann wrote:
> > On Wednesday, January 11, 2017 2:19:55 PM CET Linus Walleij wrote:
> >> On Tue, Jan 10, 2017 at 3:53 PM, Andy Gross <andy.gross@linaro.org> wrote:
> >>> On Tue, Jan 10, 2017 at 10:55:21AM +0100, Linus Walleij wrote:
> >>>> This default-enables the devices found on the APQ8060 DragonBoard
> >>>> in the qcom_defconfig:
> >>>>
> >>>> - EBI2 bus
> >>>> - SMSC911x ethernet
> >>>> - LEDs class and PM8058 LEDs driver, trigger and heartbeat
> >>>> trigger (so we get heartbeat on the board by default)
> >>>> - IIO framework, including the HRTimer trigger, KXSD9
> >>>> accelerometer, MPU3050 gyroscope, AK8975 magnetometer and
> >>>> BMP085 pressure sensor
> >>>>
> >>>> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> >>>
> >>> This brings up a point of discussion. Do we even need the qcom_defconfig any
> >>> more? Is everyone comfortable with using the multi_v7_defconfig?
> >
> > I think having one specialized defconfig for the platform is helpful for
> > the build/boot testing, e.g. it can show whether a boot failure with
> > multi_v7_defconfig is the result of a qcom-specific change, or a side-effect
> > of something that was done on another platform.
> >
> >>> Aside from size of the image, i can't think of any other reason to keep around
> >>> the separate qcom file.
> >>
> >> Actually a bit of Arnd/Olof question.
> >>
> >> Bystander opinion below:
> >>
> >> That is pretty much up to the maintainer (you) I guess.
> >> Reasons would be:
> >>
> >> - Lower footprint (because you may not need all stuff selected
> >> as 'y' compiled-in in multi_v7) on some platforms this is even
> >> necessary to get a bootable image or one that will load in
> >> reasonable time.
> >>
> >> - Enable a few things by default (both compiled-in and modules)
> >> that multi_v7 would consider to be littering
> >>
> >> - For "my" systems I usually like them because these defconfigs
> >> have vastly shorter compile time (because so much stuff that
> >> idon't concern me is left out).
> >>
> >> On the other hand: some ARMv7 system maintainers have x86
> >> ambitions: compile once, run everywhere, and certainly that is
> >> the ambition with multi_v7, and if that overshadows all the above,
> >> just kill off qcom_defconfig and be happy :)
> >
> > We recently killed of the Broadcom defconfig file that actually
> > contained some very different platforms that had not much in common
> > besides the company name.
> >
> > I think my preference is to keep it, but if Andy wants it removed
> > and nobody complains, that's fine too.
> >
> > Arnd
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> >
>
> Hi all,
>
> In fact, as far as I remember the multi_v7 did not fit on the MDM9615
> due to it's limited memory available to Linux.
This was mainly a user poll. We'll keep it in as there is at least one user who
cannot use the multiv7 due to size. That alone is enough to keep it around.
Linus, I'll add this to my pull list.
Andy
^ permalink raw reply
* [PATCH] arm64: avoid increasing DMA masks above what hardware supports
From: Nikita Yushchenko @ 2017-01-11 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <c5bada32-fbaf-3631-268b-db49dffe3eb9@arm.com>
11.01.2017 17:50, Robin Murphy ?????:
> On 11/01/17 13:41, Nikita Yushchenko wrote:
>>> Yes, I think that ought to work, although the __iommu_setup_dma_ops()
>>> call will still want a real size reflecting the default mask
>>
>> I see iommu_dma_ops do not define set_dma_mask.
>>
>> So what if setup was done for size reflecting one mask and then driver
>> changes mask? Will things still operate correctly?
>
> We've overridden dma_set_mask() at the function level, so it should
> always apply regardless. Besides, none of the arm64 ops implement
> .set_dma_mask anyway, so we could possibly drop the references to it
> altogether.
>
> Conversely, I suppose we could just implement said callback for
> swiotlb_dma_ops and iommu_dma_ops with the parent_dma_mask-checking
> function and drop the HAVE_ARCH_DMA_SET_MASK override instead. I'm not
> sure which approach is preferable - the latter seems arguably cleaner in
> isolation, but would also be less consistent with how the coherent mask
> has to be handled. Ho hum.
I mean, before patch is applied.
In the current mainline codebase, arm64 iommu does setup dependent on
[default] dma_mask, but does not anyhow react on dma mask change.
I don't know much details about arm64 iommu, but from distant view this
combination looks incorrect:
- if behavior of this hardware should depend on dma_mask of device, then
it should handle mask change,
- if behavior of this hardware should not depend on dma_mask of device,
then what for to pass size to it's setup?
^ permalink raw reply
* [RESEND PATCH v5] arm64: dts: qcom: Add msm8916 CoreSight components
From: Georgi Djakov @ 2017-01-11 15:59 UTC (permalink / raw)
To: linux-arm-kernel
From: "Ivan T. Ivanov" <ivan.ivanov@linaro.org>
Add initial set of CoreSight components found on Qualcomm msm8916 and
apq8016 based platforms, including the DragonBoard 410c board.
Signed-off-by: Ivan T. Ivanov <ivan.ivanov@linaro.org>
Acked-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
Changes since v4: (https://lkml.org/lkml/2016/11/17/533)
* Move everything into the SoC dtsi file as suggested by Stephen Boyd.
* Updated commit message.
* Got Ack from Mathieu.
Changes since v3: (https://lkml.org/lkml/2015/5/11/134)
* Include msm8916-coresight.dtsi into msm8916.dtsi
Changes since v2: (https://lkml.org/lkml/2015/4/29/242)
* Added "1x" to "qcom,coresight-replicator" compatible string, to match what
devicetree bindings documentations says.
arch/arm64/boot/dts/qcom/msm8916.dtsi | 241 ++++++++++++++++++++++++++++++++++
1 file changed, 241 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index f8ff327667c5..014d76e7dddf 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -14,6 +14,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-msm8916.h>
#include <dt-bindings/reset/qcom,gcc-msm8916.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
/ {
model = "Qualcomm Technologies, Inc. MSM8916";
@@ -856,6 +857,246 @@
memory-region = <&mpss_mem>;
};
};
+
+ tpiu at 820000 {
+ compatible = "arm,coresight-tpiu", "arm,primecell";
+ reg = <0x820000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ port {
+ tpiu_in: endpoint {
+ slave-mode;
+ remote-endpoint = <&replicator_out1>;
+ };
+ };
+ };
+
+ funnel at 821000 {
+ compatible = "arm,coresight-funnel", "arm,primecell";
+ reg = <0x821000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /*
+ * Not described input ports:
+ * 0 - connected to Resource and Power Manger CPU ETM
+ * 1 - not-connected
+ * 2 - connected to Modem CPU ETM
+ * 3 - not-connected
+ * 5 - not-connected
+ * 6 - connected trought funnel to Wireless CPU ETM
+ * 7 - connected to STM component
+ */
+
+ port at 4 {
+ reg = <4>;
+ funnel0_in4: endpoint {
+ slave-mode;
+ remote-endpoint = <&funnel1_out>;
+ };
+ };
+ port at 8 {
+ reg = <0>;
+ funnel0_out: endpoint {
+ remote-endpoint = <&etf_in>;
+ };
+ };
+ };
+ };
+
+ replicator at 824000 {
+ compatible = "qcom,coresight-replicator1x", "arm,primecell";
+ reg = <0x824000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port at 0 {
+ reg = <0>;
+ replicator_out0: endpoint {
+ remote-endpoint = <&etr_in>;
+ };
+ };
+ port at 1 {
+ reg = <1>;
+ replicator_out1: endpoint {
+ remote-endpoint = <&tpiu_in>;
+ };
+ };
+ port at 2 {
+ reg = <0>;
+ replicator_in: endpoint {
+ slave-mode;
+ remote-endpoint = <&etf_out>;
+ };
+ };
+ };
+ };
+
+ etf at 825000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0x825000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port at 0 {
+ reg = <0>;
+ etf_out: endpoint {
+ slave-mode;
+ remote-endpoint = <&funnel0_out>;
+ };
+ };
+ port at 1 {
+ reg = <0>;
+ etf_in: endpoint {
+ remote-endpoint = <&replicator_in>;
+ };
+ };
+ };
+ };
+
+ etr at 826000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0x826000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ port {
+ etr_in: endpoint {
+ slave-mode;
+ remote-endpoint = <&replicator_out0>;
+ };
+ };
+ };
+
+ funnel at 841000 { /* APSS funnel only 4 inputs are used */
+ compatible = "arm,coresight-funnel", "arm,primecell";
+ reg = <0x841000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port at 0 {
+ reg = <0>;
+ funnel1_in0: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm0_out>;
+ };
+ };
+ port at 1 {
+ reg = <1>;
+ funnel1_in1: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm1_out>;
+ };
+ };
+ port at 2 {
+ reg = <2>;
+ funnel1_in2: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm2_out>;
+ };
+ };
+ port at 3 {
+ reg = <3>;
+ funnel1_in3: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm3_out>;
+ };
+ };
+ port at 4 {
+ reg = <0>;
+ funnel1_out: endpoint {
+ remote-endpoint = <&funnel0_in4>;
+ };
+ };
+ };
+ };
+
+ etm at 85c000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x85c000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU0>;
+
+ port {
+ etm0_out: endpoint {
+ remote-endpoint = <&funnel1_in0>;
+ };
+ };
+ };
+
+ etm at 85d000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x85d000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU1>;
+
+ port {
+ etm1_out: endpoint {
+ remote-endpoint = <&funnel1_in1>;
+ };
+ };
+ };
+
+ etm at 85e000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x85e000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU2>;
+
+ port {
+ etm2_out: endpoint {
+ remote-endpoint = <&funnel1_in2>;
+ };
+ };
+ };
+
+ etm at 85f000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0x85f000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
+ clock-names = "apb_pclk", "atclk";
+
+ cpu = <&CPU3>;
+
+ port {
+ etm3_out: endpoint {
+ remote-endpoint = <&funnel1_in3>;
+ };
+ };
+ };
};
smd {
^ permalink raw reply related
* [PATCH v3] ARM: dts: qcom: Add apq8064 CoreSight components
From: Georgi Djakov @ 2017-01-11 15:50 UTC (permalink / raw)
To: linux-arm-kernel
From: "Ivan T. Ivanov" <ivan.ivanov@linaro.org>
Add initial set of CoreSight components found on Qualcomm apq8064 based
platforms, including the IFC6410 board.
Signed-off-by: Ivan T. Ivanov <ivan.ivanov@linaro.org>
Acked-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
Changes since v2 (https://lkml.org/lkml/2016/11/21/522)
* Rebase to linux-next
Changes since v1 (https://lkml.org/lkml/2016/11/17/474)
* Moved everything into the SoC dtsi file as suggested by Stephen Boyd.
* Updated commit message.
* Got Ack from Mathieu.
arch/arm/boot/dts/qcom-apq8064.dtsi | 189 +++++++++++++++++++++++++++++++++++-
1 file changed, 185 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 407a4610f4a7..4b77075ef731 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -28,7 +28,7 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu at 0 {
+ CPU0: cpu at 0 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
@@ -39,7 +39,7 @@
cpu-idle-states = <&CPU_SPC>;
};
- cpu at 1 {
+ CPU1: cpu at 1 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
@@ -50,7 +50,7 @@
cpu-idle-states = <&CPU_SPC>;
};
- cpu at 2 {
+ CPU2: cpu at 2 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
@@ -61,7 +61,7 @@
cpu-idle-states = <&CPU_SPC>;
};
- cpu at 3 {
+ CPU3: cpu at 3 {
compatible = "qcom,krait";
enable-method = "qcom,kpss-acc-v1";
device_type = "cpu";
@@ -1420,6 +1420,187 @@
};
};
};
+
+ etb at 1a01000 {
+ compatible = "coresight-etb10", "arm,primecell";
+ reg = <0x1a01000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ port {
+ etb_in: endpoint {
+ slave-mode;
+ remote-endpoint = <&replicator_out0>;
+ };
+ };
+ };
+
+ tpiu at 1a03000 {
+ compatible = "arm,coresight-tpiu", "arm,primecell";
+ reg = <0x1a03000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ port {
+ tpiu_in: endpoint {
+ slave-mode;
+ remote-endpoint = <&replicator_out1>;
+ };
+ };
+ };
+
+ replicator {
+ compatible = "arm,coresight-replicator";
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port at 0 {
+ reg = <0>;
+ replicator_out0: endpoint {
+ remote-endpoint = <&etb_in>;
+ };
+ };
+ port at 1 {
+ reg = <1>;
+ replicator_out1: endpoint {
+ remote-endpoint = <&tpiu_in>;
+ };
+ };
+ port at 2 {
+ reg = <0>;
+ replicator_in: endpoint {
+ slave-mode;
+ remote-endpoint = <&funnel_out>;
+ };
+ };
+ };
+ };
+
+ funnel at 1a04000 {
+ compatible = "arm,coresight-funnel", "arm,primecell";
+ reg = <0x1a04000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /*
+ * Not described input ports:
+ * 2 - connected to STM component
+ * 3 - not-connected
+ * 6 - not-connected
+ * 7 - not-connected
+ */
+ port at 0 {
+ reg = <0>;
+ funnel_in0: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm0_out>;
+ };
+ };
+ port at 1 {
+ reg = <1>;
+ funnel_in1: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm1_out>;
+ };
+ };
+ port at 4 {
+ reg = <4>;
+ funnel_in4: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm2_out>;
+ };
+ };
+ port at 5 {
+ reg = <5>;
+ funnel_in5: endpoint {
+ slave-mode;
+ remote-endpoint = <&etm3_out>;
+ };
+ };
+ port at 8 {
+ reg = <0>;
+ funnel_out: endpoint {
+ remote-endpoint = <&replicator_in>;
+ };
+ };
+ };
+ };
+
+ etm at 1a1c000 {
+ compatible = "arm,coresight-etm3x", "arm,primecell";
+ reg = <0x1a1c000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ cpu = <&CPU0>;
+
+ port {
+ etm0_out: endpoint {
+ remote-endpoint = <&funnel_in0>;
+ };
+ };
+ };
+
+ etm at 1a1d000 {
+ compatible = "arm,coresight-etm3x", "arm,primecell";
+ reg = <0x1a1d000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ cpu = <&CPU1>;
+
+ port {
+ etm1_out: endpoint {
+ remote-endpoint = <&funnel_in1>;
+ };
+ };
+ };
+
+ etm at 1a1e000 {
+ compatible = "arm,coresight-etm3x", "arm,primecell";
+ reg = <0x1a1e000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ cpu = <&CPU2>;
+
+ port {
+ etm2_out: endpoint {
+ remote-endpoint = <&funnel_in4>;
+ };
+ };
+ };
+
+ etm at 1a1f000 {
+ compatible = "arm,coresight-etm3x", "arm,primecell";
+ reg = <0x1a1f000 0x1000>;
+
+ clocks = <&rpmcc RPM_QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ cpu = <&CPU3>;
+
+ port {
+ etm3_out: endpoint {
+ remote-endpoint = <&funnel_in5>;
+ };
+ };
+ };
};
};
#include "qcom-apq8064-pins.dtsi"
^ permalink raw reply related
* [PATCH 10/62] watchdog: coh901327_wdt: Convert to use device managed functions
From: Linus Walleij @ 2017-01-11 15:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484091325-9199-11-git-send-email-linux@roeck-us.net>
On Wed, Jan 11, 2017 at 12:34 AM, Guenter Roeck <linux@roeck-us.net> wrote:
> Use device managed functions to simplify error handling, reduce
> source code size, improve readability, and reduce the likelyhood of bugs.
>
> The conversion was done automatically with coccinelle using the
> following semantic patches. The semantic patches and the scripts used
> to generate this commit log are available at
> https://github.com/groeck/coccinelle-patches
>
> - Use devm_add_action_or_reset() for calls to clk_disable_unprepare
> - Use devm_clk_get() if the device parameter is not NULL
> - Replace 'goto l; ... l: return e;' with 'return e;'
> - Replace 'val = e; return val;' with 'return e;'
> - Replace 'if (e) { return expr; }' with 'if (e) return expr;'
> - Replace request_irq, request_threaded_irq, and request_any_context_irq
> with their device managed equivalent
> - Replace &pdev->dev with dev if 'struct device *dev' is a declared
> variable
> - Use devm_watchdog_register_driver() to register watchdog device
>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH] gpio: mvebu: fix warning when building on 64-bit
From: Linus Walleij @ 2017-01-11 15:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <E1cR5IG-0008Gw-HV@rmk-PC.armlinux.org.uk>
On Tue, Jan 10, 2017 at 11:53 PM, Russell King
<rmk+kernel@armlinux.org.uk> wrote:
> Casting a pointer to an int is not portable, and provokes a compiler
> warning. Cast to unsigned long instead to avoid the warning.
>
> drivers/gpio/gpio-mvebu.c: In function 'mvebu_gpio_probe':
> drivers/gpio/gpio-mvebu.c:662:17: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
> soc_variant = (int) match->data;
> ^
>
> This will be needed when building gpio-mvebu for Armada 7k/8k ARM64
> SoCs.
>
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> ---
> Linus,
>
> I don't think this is necessary to push into -rc, as its not yet used
> on ARM64 - GPIO support is not yet present in the DTS files, and the
> Kconfig doesn't allow the driver to be built on ARM64. Hence, please
> queue for the next merge window as a low priority fix.
Fair enough, queued for next. Thanks!
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH v8 2/5] i2c: Add STM32F4 I2C driver
From: Uwe Kleine-König @ 2017-01-11 15:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOAejn2cDzPgqvWZf7ASvtST+aDeaAebf=1aMWA9Zd8CDg4pmA@mail.gmail.com>
Hello Cedric,
On Wed, Jan 11, 2017 at 03:20:41PM +0100, M'boumba Cedric Madianga wrote:
> >
> >> + */
> >> + reg = i2c_dev->base + STM32F4_I2C_CR1;
> >> + stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
> >> + stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_POS);
> >
> > You could get rid of this, when caching the value of CR1. Would save two
> > register reads here. This doesn't work for all registers, but it should
> > be possible to apply for most of them, maybe enough to get rid of the
> > clr_bits and set_bits function.
>
> I agree at many places I could save registers read by not using
> clr_bits and set_bits function when the registers in question has been
> already read.
> But it is not enough to get rid of the clr_bits and set_bits function.
> For example when calling stm32f4_i2c_terminate_xfer(), the CR1
> register is never read before so set_bits function is useful.
I didn't double check the manual, but I would expect that CR1 isn't
modified by hardware. So you can cache the result in the driver data
structure and do the necessary modifications with that one.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox