* [PATCH 1/5] cpu: move arch_cpu_uevent() to generic code
2014-01-29 16:50 [PATCH 0/5] generic CPU feature based udev module autoprobing Ard Biesheuvel
@ 2014-01-29 16:50 ` Ard Biesheuvel
2014-01-29 16:50 ` [PATCH 2/5] cpu: add generic support for CPU feature based module autoloading Ard Biesheuvel
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Ard Biesheuvel @ 2014-01-29 16:50 UTC (permalink / raw)
To: linux-arm-kernel
Only x86 implements arch_cpu_uevent(), and there is nothing arch
specific about it, so move it to drivers/base/cpu.c and rename
it to cpu_uevent().
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/x86/kernel/cpu/match.c | 11 -----------
drivers/base/cpu.c | 15 ++++++++++++++-
include/linux/cpu.h | 1 -
3 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c
index 36565373af87..ab6082a9020e 100644
--- a/arch/x86/kernel/cpu/match.c
+++ b/arch/x86/kernel/cpu/match.c
@@ -78,14 +78,3 @@ ssize_t arch_print_cpu_modalias(struct device *dev,
*buf++ = '\n';
return buf - bufptr;
}
-
-int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
- if (buf) {
- arch_print_cpu_modalias(NULL, NULL, buf);
- add_uevent_var(env, "MODALIAS=%s", buf);
- kfree(buf);
- }
- return 0;
-}
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index f48370dfc908..270649012e64 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -286,6 +286,19 @@ static void cpu_device_release(struct device *dev)
*/
}
+#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
+static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (buf) {
+ arch_print_cpu_modalias(NULL, NULL, buf);
+ add_uevent_var(env, "MODALIAS=%s", buf);
+ kfree(buf);
+ }
+ return 0;
+}
+#endif
+
/*
* register_cpu - Setup a sysfs device for a CPU.
* @cpu - cpu->hotpluggable field set to 1 will generate a control file in
@@ -307,7 +320,7 @@ int register_cpu(struct cpu *cpu, int num)
cpu->dev.offline = !cpu_online(num);
cpu->dev.of_node = of_get_cpu_node(num, NULL);
#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
- cpu->dev.bus->uevent = arch_cpu_uevent;
+ cpu->dev.bus->uevent = cpu_uevent;
#endif
cpu->dev.groups = common_cpu_attr_groups;
if (cpu->hotpluggable)
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 03e235ad1bba..dcc4a0d9c45f 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -47,7 +47,6 @@ extern ssize_t arch_cpu_release(const char *, size_t);
struct notifier_block;
#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
-extern int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env);
extern ssize_t arch_print_cpu_modalias(struct device *dev,
struct device_attribute *attr,
char *bufptr);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 2/5] cpu: add generic support for CPU feature based module autoloading
2014-01-29 16:50 [PATCH 0/5] generic CPU feature based udev module autoprobing Ard Biesheuvel
2014-01-29 16:50 ` [PATCH 1/5] cpu: move arch_cpu_uevent() to generic code Ard Biesheuvel
@ 2014-01-29 16:50 ` Ard Biesheuvel
2014-02-03 17:13 ` Ard Biesheuvel
2014-01-29 16:50 ` [PATCH 3/5] x86: align x86 arch with generic CPU modalias handling Ard Biesheuvel
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Ard Biesheuvel @ 2014-01-29 16:50 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds support for advertising optional CPU features over udev using
the modalias, and for declaring compatibility with/dependency upon such a
feature in a module.
This feature can be enabled by setting CONFIG_GENERIC_CPU_AUTOPROBE for the
architecture, and supplying a file <asm/cpufeature.h> which defines how the
numbers used in the modalias string map to actual CPU features.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
drivers/base/Kconfig | 8 ++++++
drivers/base/cpu.c | 39 +++++++++++++++++++++----
include/linux/cpufeature.h | 60 +++++++++++++++++++++++++++++++++++++++
include/linux/mod_devicetable.h | 9 ++++++
scripts/mod/devicetable-offsets.c | 3 ++
scripts/mod/file2alias.c | 10 +++++++
6 files changed, 123 insertions(+), 6 deletions(-)
create mode 100644 include/linux/cpufeature.h
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index ec36e7772e57..3f0d3732df7f 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -185,6 +185,14 @@ config GENERIC_CPU_DEVICES
bool
default n
+config HAVE_CPU_AUTOPROBE
+ def_bool ARCH_HAS_CPU_AUTOPROBE
+
+config GENERIC_CPU_AUTOPROBE
+ bool
+ depends on !ARCH_HAS_CPU_AUTOPROBE
+ select HAVE_CPU_AUTOPROBE
+
config SOC_BUS
bool
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 270649012e64..8a38bf8c792f 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -15,6 +15,7 @@
#include <linux/percpu.h>
#include <linux/acpi.h>
#include <linux/of.h>
+#include <linux/cpufeature.h>
#include "base.h"
@@ -286,12 +287,38 @@ static void cpu_device_release(struct device *dev)
*/
}
-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
+#ifdef CONFIG_HAVE_CPU_AUTOPROBE
+#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
+static ssize_t print_cpu_modalias(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t n;
+ u32 i;
+
+ n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:",
+ CPU_FEATURE_TYPEVAL);
+
+ for (i = 0; i < MAX_CPU_FEATURES; i++)
+ if (cpu_have_feature(i)) {
+ if (PAGE_SIZE < n + sizeof(",XXXX\n")) {
+ WARN(1, "CPU features overflow page\n");
+ break;
+ }
+ n += sprintf(&buf[n], ",%04X", i);
+ }
+ buf[n++] = '\n';
+ return n;
+}
+#else
+#define print_cpu_modalias arch_print_cpu_modalias
+#endif
+
static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
{
char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (buf) {
- arch_print_cpu_modalias(NULL, NULL, buf);
+ print_cpu_modalias(NULL, NULL, buf);
add_uevent_var(env, "MODALIAS=%s", buf);
kfree(buf);
}
@@ -319,7 +346,7 @@ int register_cpu(struct cpu *cpu, int num)
cpu->dev.offline_disabled = !cpu->hotpluggable;
cpu->dev.offline = !cpu_online(num);
cpu->dev.of_node = of_get_cpu_node(num, NULL);
-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
+#ifdef CONFIG_HAVE_CPU_AUTOPROBE
cpu->dev.bus->uevent = cpu_uevent;
#endif
cpu->dev.groups = common_cpu_attr_groups;
@@ -343,8 +370,8 @@ struct device *get_cpu_device(unsigned cpu)
}
EXPORT_SYMBOL_GPL(get_cpu_device);
-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
-static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
+#ifdef CONFIG_HAVE_CPU_AUTOPROBE
+static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
#endif
static struct attribute *cpu_root_attrs[] = {
@@ -357,7 +384,7 @@ static struct attribute *cpu_root_attrs[] = {
&cpu_attrs[2].attr.attr,
&dev_attr_kernel_max.attr,
&dev_attr_offline.attr,
-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
+#ifdef CONFIG_HAVE_CPU_AUTOPROBE
&dev_attr_modalias.attr,
#endif
NULL
diff --git a/include/linux/cpufeature.h b/include/linux/cpufeature.h
new file mode 100644
index 000000000000..c4d4eb8ac9fe
--- /dev/null
+++ b/include/linux/cpufeature.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef __LINUX_CPUFEATURE_H
+#define __LINUX_CPUFEATURE_H
+
+#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
+
+#include <linux/mod_devicetable.h>
+#include <asm/cpufeature.h>
+
+/*
+ * Macros imported from <asm/cpufeature.h>:
+ * - cpu_feature(x) ordinal value of feature called 'x'
+ * - cpu_have_feature(u32 n) whether feature #n is available
+ * - MAX_CPU_FEATURES upper bound for feature ordinal values
+ * Optional:
+ * - CPU_FEATURE_TYPEFMT format string fragment for printing the cpu type
+ * - CPU_FEATURE_TYPEVAL set of values matching the format string above
+ */
+
+#ifndef CPU_FEATURE_TYPEFMT
+#define CPU_FEATURE_TYPEFMT "%s"
+#endif
+
+#ifndef CPU_FEATURE_TYPEVAL
+#define CPU_FEATURE_TYPEVAL ELF_PLATFORM
+#endif
+
+/*
+ * Use module_cpu_feature_match(feature, module_init_function) to
+ * declare that
+ * a) the module shall be probed upon discovery of CPU feature 'feature'
+ * (typically at boot time using udev)
+ * b) the module must not be loaded if CPU feature 'feature' is not present
+ * (not even by manual insmod).
+ *
+ * For a list of legal values for 'feature', please consult the file
+ * 'asm/cpufeature.h' of your favorite architecture.
+ */
+#define module_cpu_feature_match(x, __init) \
+static struct cpu_feature const cpu_feature_match_ ## x[] = \
+ { { .feature = cpu_feature(x) }, { } }; \
+MODULE_DEVICE_TABLE(cpu, cpu_feature_match_ ## x); \
+ \
+static int cpu_feature_match_ ## x ## _init(void) \
+{ \
+ if (!cpu_have_feature(cpu_feature(x))) \
+ return -ENODEV; \
+ return __init(); \
+} \
+module_init(cpu_feature_match_ ## x ## _init)
+
+#endif
+#endif
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 45e921401b06..f2ac87c613a5 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -564,6 +564,15 @@ struct x86_cpu_id {
#define X86_MODEL_ANY 0
#define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */
+/*
+ * Generic table type for matching CPU features.
+ * @feature: the bit number of the feature (0 - 65535)
+ */
+
+struct cpu_feature {
+ __u16 feature;
+};
+
#define IPACK_ANY_FORMAT 0xff
#define IPACK_ANY_ID (~0)
struct ipack_device_id {
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index bb5d115ca671..f282516acc7b 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -174,6 +174,9 @@ int main(void)
DEVID_FIELD(x86_cpu_id, model);
DEVID_FIELD(x86_cpu_id, vendor);
+ DEVID(cpu_feature);
+ DEVID_FIELD(cpu_feature, feature);
+
DEVID(mei_cl_device_id);
DEVID_FIELD(mei_cl_device_id, name);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 23708636b05c..8a69005228d8 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1135,6 +1135,16 @@ static int do_x86cpu_entry(const char *filename, void *symval,
}
ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
+/* LOOKS like cpu:type:*:feature:*FEAT* */
+static int do_cpu_entry(const char *filename, void *symval, char *alias)
+{
+ DEF_FIELD(symval, cpu_feature, feature);
+
+ sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
+ return 1;
+}
+ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry);
+
/* Looks like: mei:S */
static int do_mei_entry(const char *filename, void *symval,
char *alias)
--
1.8.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 2/5] cpu: add generic support for CPU feature based module autoloading
2014-01-29 16:50 ` [PATCH 2/5] cpu: add generic support for CPU feature based module autoloading Ard Biesheuvel
@ 2014-02-03 17:13 ` Ard Biesheuvel
0 siblings, 0 replies; 11+ messages in thread
From: Ard Biesheuvel @ 2014-02-03 17:13 UTC (permalink / raw)
To: linux-arm-kernel
Hello Greg,
Would you care to comment on this patch?
It adds some Kconfig clutter, but this is removed again in the next patch
(http://marc.info/?l=linux-arm-kernel&m=139101443708663&w=2),
which has already been acked by hpa here:
http://marc.info/?l=linux-arm-kernel&m=139101589509168&w=2
Example enabling it for arm64:
http://marc.info/?l=linux-arm-kernel&m=139101486308822&w=2
Example using it (optional AES instructions on arm64):
http://marc.info/?l=linux-arm-kernel&m=139101446008665&w=2
Best regards,
Ard.
On 29 January 2014 17:50, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> This patch adds support for advertising optional CPU features over udev using
> the modalias, and for declaring compatibility with/dependency upon such a
> feature in a module.
>
> This feature can be enabled by setting CONFIG_GENERIC_CPU_AUTOPROBE for the
> architecture, and supplying a file <asm/cpufeature.h> which defines how the
> numbers used in the modalias string map to actual CPU features.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> drivers/base/Kconfig | 8 ++++++
> drivers/base/cpu.c | 39 +++++++++++++++++++++----
> include/linux/cpufeature.h | 60 +++++++++++++++++++++++++++++++++++++++
> include/linux/mod_devicetable.h | 9 ++++++
> scripts/mod/devicetable-offsets.c | 3 ++
> scripts/mod/file2alias.c | 10 +++++++
> 6 files changed, 123 insertions(+), 6 deletions(-)
> create mode 100644 include/linux/cpufeature.h
>
> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
> index ec36e7772e57..3f0d3732df7f 100644
> --- a/drivers/base/Kconfig
> +++ b/drivers/base/Kconfig
> @@ -185,6 +185,14 @@ config GENERIC_CPU_DEVICES
> bool
> default n
>
> +config HAVE_CPU_AUTOPROBE
> + def_bool ARCH_HAS_CPU_AUTOPROBE
> +
> +config GENERIC_CPU_AUTOPROBE
> + bool
> + depends on !ARCH_HAS_CPU_AUTOPROBE
> + select HAVE_CPU_AUTOPROBE
> +
> config SOC_BUS
> bool
>
> diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
> index 270649012e64..8a38bf8c792f 100644
> --- a/drivers/base/cpu.c
> +++ b/drivers/base/cpu.c
> @@ -15,6 +15,7 @@
> #include <linux/percpu.h>
> #include <linux/acpi.h>
> #include <linux/of.h>
> +#include <linux/cpufeature.h>
>
> #include "base.h"
>
> @@ -286,12 +287,38 @@ static void cpu_device_release(struct device *dev)
> */
> }
>
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
> +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
> +static ssize_t print_cpu_modalias(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + ssize_t n;
> + u32 i;
> +
> + n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:",
> + CPU_FEATURE_TYPEVAL);
> +
> + for (i = 0; i < MAX_CPU_FEATURES; i++)
> + if (cpu_have_feature(i)) {
> + if (PAGE_SIZE < n + sizeof(",XXXX\n")) {
> + WARN(1, "CPU features overflow page\n");
> + break;
> + }
> + n += sprintf(&buf[n], ",%04X", i);
> + }
> + buf[n++] = '\n';
> + return n;
> +}
> +#else
> +#define print_cpu_modalias arch_print_cpu_modalias
> +#endif
> +
> static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
> {
> char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
> if (buf) {
> - arch_print_cpu_modalias(NULL, NULL, buf);
> + print_cpu_modalias(NULL, NULL, buf);
> add_uevent_var(env, "MODALIAS=%s", buf);
> kfree(buf);
> }
> @@ -319,7 +346,7 @@ int register_cpu(struct cpu *cpu, int num)
> cpu->dev.offline_disabled = !cpu->hotpluggable;
> cpu->dev.offline = !cpu_online(num);
> cpu->dev.of_node = of_get_cpu_node(num, NULL);
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
> cpu->dev.bus->uevent = cpu_uevent;
> #endif
> cpu->dev.groups = common_cpu_attr_groups;
> @@ -343,8 +370,8 @@ struct device *get_cpu_device(unsigned cpu)
> }
> EXPORT_SYMBOL_GPL(get_cpu_device);
>
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> -static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
> +static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
> #endif
>
> static struct attribute *cpu_root_attrs[] = {
> @@ -357,7 +384,7 @@ static struct attribute *cpu_root_attrs[] = {
> &cpu_attrs[2].attr.attr,
> &dev_attr_kernel_max.attr,
> &dev_attr_offline.attr,
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
> &dev_attr_modalias.attr,
> #endif
> NULL
> diff --git a/include/linux/cpufeature.h b/include/linux/cpufeature.h
> new file mode 100644
> index 000000000000..c4d4eb8ac9fe
> --- /dev/null
> +++ b/include/linux/cpufeature.h
> @@ -0,0 +1,60 @@
> +/*
> + * Copyright (C) 2014 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.
> + */
> +
> +#ifndef __LINUX_CPUFEATURE_H
> +#define __LINUX_CPUFEATURE_H
> +
> +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
> +
> +#include <linux/mod_devicetable.h>
> +#include <asm/cpufeature.h>
> +
> +/*
> + * Macros imported from <asm/cpufeature.h>:
> + * - cpu_feature(x) ordinal value of feature called 'x'
> + * - cpu_have_feature(u32 n) whether feature #n is available
> + * - MAX_CPU_FEATURES upper bound for feature ordinal values
> + * Optional:
> + * - CPU_FEATURE_TYPEFMT format string fragment for printing the cpu type
> + * - CPU_FEATURE_TYPEVAL set of values matching the format string above
> + */
> +
> +#ifndef CPU_FEATURE_TYPEFMT
> +#define CPU_FEATURE_TYPEFMT "%s"
> +#endif
> +
> +#ifndef CPU_FEATURE_TYPEVAL
> +#define CPU_FEATURE_TYPEVAL ELF_PLATFORM
> +#endif
> +
> +/*
> + * Use module_cpu_feature_match(feature, module_init_function) to
> + * declare that
> + * a) the module shall be probed upon discovery of CPU feature 'feature'
> + * (typically at boot time using udev)
> + * b) the module must not be loaded if CPU feature 'feature' is not present
> + * (not even by manual insmod).
> + *
> + * For a list of legal values for 'feature', please consult the file
> + * 'asm/cpufeature.h' of your favorite architecture.
> + */
> +#define module_cpu_feature_match(x, __init) \
> +static struct cpu_feature const cpu_feature_match_ ## x[] = \
> + { { .feature = cpu_feature(x) }, { } }; \
> +MODULE_DEVICE_TABLE(cpu, cpu_feature_match_ ## x); \
> + \
> +static int cpu_feature_match_ ## x ## _init(void) \
> +{ \
> + if (!cpu_have_feature(cpu_feature(x))) \
> + return -ENODEV; \
> + return __init(); \
> +} \
> +module_init(cpu_feature_match_ ## x ## _init)
> +
> +#endif
> +#endif
> diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
> index 45e921401b06..f2ac87c613a5 100644
> --- a/include/linux/mod_devicetable.h
> +++ b/include/linux/mod_devicetable.h
> @@ -564,6 +564,15 @@ struct x86_cpu_id {
> #define X86_MODEL_ANY 0
> #define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */
>
> +/*
> + * Generic table type for matching CPU features.
> + * @feature: the bit number of the feature (0 - 65535)
> + */
> +
> +struct cpu_feature {
> + __u16 feature;
> +};
> +
> #define IPACK_ANY_FORMAT 0xff
> #define IPACK_ANY_ID (~0)
> struct ipack_device_id {
> diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
> index bb5d115ca671..f282516acc7b 100644
> --- a/scripts/mod/devicetable-offsets.c
> +++ b/scripts/mod/devicetable-offsets.c
> @@ -174,6 +174,9 @@ int main(void)
> DEVID_FIELD(x86_cpu_id, model);
> DEVID_FIELD(x86_cpu_id, vendor);
>
> + DEVID(cpu_feature);
> + DEVID_FIELD(cpu_feature, feature);
> +
> DEVID(mei_cl_device_id);
> DEVID_FIELD(mei_cl_device_id, name);
>
> diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
> index 23708636b05c..8a69005228d8 100644
> --- a/scripts/mod/file2alias.c
> +++ b/scripts/mod/file2alias.c
> @@ -1135,6 +1135,16 @@ static int do_x86cpu_entry(const char *filename, void *symval,
> }
> ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
>
> +/* LOOKS like cpu:type:*:feature:*FEAT* */
> +static int do_cpu_entry(const char *filename, void *symval, char *alias)
> +{
> + DEF_FIELD(symval, cpu_feature, feature);
> +
> + sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
> + return 1;
> +}
> +ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry);
> +
> /* Looks like: mei:S */
> static int do_mei_entry(const char *filename, void *symval,
> char *alias)
> --
> 1.8.3.2
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/5] x86: align x86 arch with generic CPU modalias handling
2014-01-29 16:50 [PATCH 0/5] generic CPU feature based udev module autoprobing Ard Biesheuvel
2014-01-29 16:50 ` [PATCH 1/5] cpu: move arch_cpu_uevent() to generic code Ard Biesheuvel
2014-01-29 16:50 ` [PATCH 2/5] cpu: add generic support for CPU feature based module autoloading Ard Biesheuvel
@ 2014-01-29 16:50 ` Ard Biesheuvel
2014-01-29 17:16 ` H. Peter Anvin
2014-01-29 16:50 ` [PATCH 4/5] arm64: enable generic CPU feature modalias matching for this arch Ard Biesheuvel
2014-01-29 16:50 ` [PATCH 5/5] arm64: add Crypto Extensions based synchronous core AES cipher Ard Biesheuvel
4 siblings, 1 reply; 11+ messages in thread
From: Ard Biesheuvel @ 2014-01-29 16:50 UTC (permalink / raw)
To: linux-arm-kernel
The x86 CPU feature modalias handling existed before it was reimplemented
generically. This patch aligns the x86 handling so that it
(a) reuses some more code that is now generic;
(b) uses the generic format for the modalias module metadata entry, i.e., it
now uses 'cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:,XXXX,YYYY' instead of
the 'x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature,XXXX,YYYY' that was
used before.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/x86/Kconfig | 4 +---
arch/x86/include/asm/cpufeature.h | 7 +++++++
arch/x86/kernel/cpu/match.c | 31 -------------------------------
drivers/base/Kconfig | 5 -----
drivers/base/cpu.c | 10 +++-------
include/linux/cpu.h | 6 ------
scripts/mod/file2alias.c | 10 +++++-----
7 files changed, 16 insertions(+), 57 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 940e50ebfafa..7d3b7907a10c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -127,6 +127,7 @@ config X86
select HAVE_DEBUG_STACKOVERFLOW
select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64
select HAVE_CC_STACKPROTECTOR
+ select GENERIC_CPU_AUTOPROBE
config INSTRUCTION_DECODER
def_bool y
@@ -195,9 +196,6 @@ config ARCH_HAS_CPU_RELAX
config ARCH_HAS_CACHE_LINE_SIZE
def_bool y
-config ARCH_HAS_CPU_AUTOPROBE
- def_bool y
-
config HAVE_SETUP_PER_CPU_AREA
def_bool y
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index e099f9502ace..d86dc3deea6a 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -541,6 +541,13 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
#define static_cpu_has_bug(bit) static_cpu_has((bit))
#define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit))
+#define MAX_CPU_FEATURES (NCAPINTS * 32)
+#define cpu_have_feature boot_cpu_has
+
+#define CPU_FEATURE_TYPEFMT "x86,ven%04Xfam%04Xmod%04X"
+#define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \
+ boot_cpu_data.x86_model
+
#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
#endif /* _ASM_X86_CPUFEATURE_H */
diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c
index ab6082a9020e..afa9f0d487ea 100644
--- a/arch/x86/kernel/cpu/match.c
+++ b/arch/x86/kernel/cpu/match.c
@@ -47,34 +47,3 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
return NULL;
}
EXPORT_SYMBOL(x86_match_cpu);
-
-ssize_t arch_print_cpu_modalias(struct device *dev,
- struct device_attribute *attr,
- char *bufptr)
-{
- int size = PAGE_SIZE;
- int i, n;
- char *buf = bufptr;
-
- n = snprintf(buf, size, "x86cpu:vendor:%04X:family:%04X:"
- "model:%04X:feature:",
- boot_cpu_data.x86_vendor,
- boot_cpu_data.x86,
- boot_cpu_data.x86_model);
- size -= n;
- buf += n;
- size -= 1;
- for (i = 0; i < NCAPINTS*32; i++) {
- if (boot_cpu_has(i)) {
- n = snprintf(buf, size, ",%04X", i);
- if (n >= size) {
- WARN(1, "x86 features overflow page\n");
- break;
- }
- size -= n;
- buf += n;
- }
- }
- *buf++ = '\n';
- return buf - bufptr;
-}
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 3f0d3732df7f..8fa8deab6449 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -185,13 +185,8 @@ config GENERIC_CPU_DEVICES
bool
default n
-config HAVE_CPU_AUTOPROBE
- def_bool ARCH_HAS_CPU_AUTOPROBE
-
config GENERIC_CPU_AUTOPROBE
bool
- depends on !ARCH_HAS_CPU_AUTOPROBE
- select HAVE_CPU_AUTOPROBE
config SOC_BUS
bool
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 8a38bf8c792f..006b1bc5297d 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -287,7 +287,6 @@ static void cpu_device_release(struct device *dev)
*/
}
-#ifdef CONFIG_HAVE_CPU_AUTOPROBE
#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
static ssize_t print_cpu_modalias(struct device *dev,
struct device_attribute *attr,
@@ -310,9 +309,6 @@ static ssize_t print_cpu_modalias(struct device *dev,
buf[n++] = '\n';
return n;
}
-#else
-#define print_cpu_modalias arch_print_cpu_modalias
-#endif
static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
{
@@ -346,7 +342,7 @@ int register_cpu(struct cpu *cpu, int num)
cpu->dev.offline_disabled = !cpu->hotpluggable;
cpu->dev.offline = !cpu_online(num);
cpu->dev.of_node = of_get_cpu_node(num, NULL);
-#ifdef CONFIG_HAVE_CPU_AUTOPROBE
+#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
cpu->dev.bus->uevent = cpu_uevent;
#endif
cpu->dev.groups = common_cpu_attr_groups;
@@ -370,7 +366,7 @@ struct device *get_cpu_device(unsigned cpu)
}
EXPORT_SYMBOL_GPL(get_cpu_device);
-#ifdef CONFIG_HAVE_CPU_AUTOPROBE
+#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
#endif
@@ -384,7 +380,7 @@ static struct attribute *cpu_root_attrs[] = {
&cpu_attrs[2].attr.attr,
&dev_attr_kernel_max.attr,
&dev_attr_offline.attr,
-#ifdef CONFIG_HAVE_CPU_AUTOPROBE
+#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
&dev_attr_modalias.attr,
#endif
NULL
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index dcc4a0d9c45f..03e962e23eaf 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -46,12 +46,6 @@ extern ssize_t arch_cpu_release(const char *, size_t);
#endif
struct notifier_block;
-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
-extern ssize_t arch_print_cpu_modalias(struct device *dev,
- struct device_attribute *attr,
- char *bufptr);
-#endif
-
/*
* CPU notifier priorities.
*/
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 8a69005228d8..5fdad833f951 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1110,7 +1110,7 @@ static int do_amba_entry(const char *filename,
}
ADD_TO_DEVTABLE("amba", amba_id, do_amba_entry);
-/* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,*
+/* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,*
* All fields are numbers. It would be nicer to use strings for vendor
* and feature, but getting those out of the build system here is too
* complicated.
@@ -1124,10 +1124,10 @@ static int do_x86cpu_entry(const char *filename, void *symval,
DEF_FIELD(symval, x86_cpu_id, model);
DEF_FIELD(symval, x86_cpu_id, vendor);
- strcpy(alias, "x86cpu:");
- ADD(alias, "vendor:", vendor != X86_VENDOR_ANY, vendor);
- ADD(alias, ":family:", family != X86_FAMILY_ANY, family);
- ADD(alias, ":model:", model != X86_MODEL_ANY, model);
+ strcpy(alias, "cpu:type:x86,");
+ ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor);
+ ADD(alias, "fam", family != X86_FAMILY_ANY, family);
+ ADD(alias, "mod", model != X86_MODEL_ANY, model);
strcat(alias, ":feature:*");
if (feature != X86_FEATURE_ANY)
sprintf(alias + strlen(alias), "%04X*", feature);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 3/5] x86: align x86 arch with generic CPU modalias handling
2014-01-29 16:50 ` [PATCH 3/5] x86: align x86 arch with generic CPU modalias handling Ard Biesheuvel
@ 2014-01-29 17:16 ` H. Peter Anvin
0 siblings, 0 replies; 11+ messages in thread
From: H. Peter Anvin @ 2014-01-29 17:16 UTC (permalink / raw)
To: linux-arm-kernel
On 01/29/2014 08:50 AM, Ard Biesheuvel wrote:
> The x86 CPU feature modalias handling existed before it was reimplemented
> generically. This patch aligns the x86 handling so that it
> (a) reuses some more code that is now generic;
> (b) uses the generic format for the modalias module metadata entry, i.e., it
> now uses 'cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:,XXXX,YYYY' instead of
> the 'x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature,XXXX,YYYY' that was
> used before.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Looks good, although I have not tested it.
Acked-by: H. Peter Anvin <hpa@linux.intel.com>
-hpa
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 4/5] arm64: enable generic CPU feature modalias matching for this arch
2014-01-29 16:50 [PATCH 0/5] generic CPU feature based udev module autoprobing Ard Biesheuvel
` (2 preceding siblings ...)
2014-01-29 16:50 ` [PATCH 3/5] x86: align x86 arch with generic CPU modalias handling Ard Biesheuvel
@ 2014-01-29 16:50 ` Ard Biesheuvel
2014-01-29 16:50 ` [PATCH 5/5] arm64: add Crypto Extensions based synchronous core AES cipher Ard Biesheuvel
4 siblings, 0 replies; 11+ messages in thread
From: Ard Biesheuvel @ 2014-01-29 16:50 UTC (permalink / raw)
To: linux-arm-kernel
This enables support for the generic CPU feature modalias implementation that
wires up optional CPU features to udev based module autoprobing.
A file <asm/cpufeatures.h> is provided that maps CPU feature numbers to
elf_hwcap bits, which is the standard way on arm64 to advertise optional CPU
features both internally and to user space.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/cpufeature.h | 30 ++++++++++++++++++++++++++++++
2 files changed, 31 insertions(+)
create mode 100644 arch/arm64/include/asm/cpufeature.h
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index dd4327f09ba4..e339099b6fbd 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -16,6 +16,7 @@ config ARM64
select DCACHE_WORD_ACCESS
select GENERIC_CLOCKEVENTS
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+ select GENERIC_CPU_AUTOPROBE
select GENERIC_IOMAP
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
new file mode 100644
index 000000000000..1d902efa201d
--- /dev/null
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef __ASM_CPUFEATURE_H
+#define __ASM_CPUFEATURE_H
+
+#include <asm/elf.h>
+#include <asm/hwcap.h>
+
+/*
+ * In the arm64 world (as in the ARM world), elf_hwcap is used both internally
+ * in the kernel and for user space to keep track of which optional features
+ * are supported by the current system. So let's map feature 'x' to HWCAP_x.
+ * Note that HWCAP_x constants are bit fields so we need to take the log.
+ */
+
+#define MAX_CPU_FEATURES sizeof(elf_hwcap)
+#define cpu_feature(x) ((unsigned int)ilog2(HWCAP_ ## x))
+
+static inline bool cpu_have_feature(unsigned int num)
+{
+ return !!(elf_hwcap & (1 << num));
+}
+
+#endif
--
1.8.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5/5] arm64: add Crypto Extensions based synchronous core AES cipher
2014-01-29 16:50 [PATCH 0/5] generic CPU feature based udev module autoprobing Ard Biesheuvel
` (3 preceding siblings ...)
2014-01-29 16:50 ` [PATCH 4/5] arm64: enable generic CPU feature modalias matching for this arch Ard Biesheuvel
@ 2014-01-29 16:50 ` Ard Biesheuvel
2014-01-30 18:56 ` Will Deacon
4 siblings, 1 reply; 11+ messages in thread
From: Ard Biesheuvel @ 2014-01-29 16:50 UTC (permalink / raw)
To: linux-arm-kernel
This implements the core AES cipher using the Crypto Extensions,
using only NEON registers q0 and q1.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/Makefile | 1 +
arch/arm64/crypto/Makefile | 13 +++++
arch/arm64/crypto/aes-ce-cipher.c | 103 ++++++++++++++++++++++++++++++++++++++
crypto/Kconfig | 6 +++
4 files changed, 123 insertions(+)
create mode 100644 arch/arm64/crypto/Makefile
create mode 100644 arch/arm64/crypto/aes-ce-cipher.c
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 2fceb71ac3b7..8185a913c5ed 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -45,6 +45,7 @@ export TEXT_OFFSET GZFLAGS
core-y += arch/arm64/kernel/ arch/arm64/mm/
core-$(CONFIG_KVM) += arch/arm64/kvm/
core-$(CONFIG_XEN) += arch/arm64/xen/
+core-$(CONFIG_CRYPTO) += arch/arm64/crypto/
libs-y := arch/arm64/lib/ $(libs-y)
libs-y += $(LIBGCC)
diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
new file mode 100644
index 000000000000..ac58945c50b3
--- /dev/null
+++ b/arch/arm64/crypto/Makefile
@@ -0,0 +1,13 @@
+#
+# linux/arch/arm64/crypto/Makefile
+#
+# Copyright (C) 2013 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.
+#
+
+obj-$(CONFIG_CRYPTO_AES_ARM64_CE) += aes-ce-cipher.o
+
+CFLAGS_aes-ce-cipher.o += -march=armv8-a+crypto
diff --git a/arch/arm64/crypto/aes-ce-cipher.c b/arch/arm64/crypto/aes-ce-cipher.c
new file mode 100644
index 000000000000..b5a5d5d6e4b8
--- /dev/null
+++ b/arch/arm64/crypto/aes-ce-cipher.c
@@ -0,0 +1,103 @@
+/*
+ * linux/arch/arm64/crypto/aes-ce-cipher.c
+ *
+ * Copyright (C) 2013 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.
+ */
+
+#include <asm/neon.h>
+#include <crypto/aes.h>
+#include <linux/crypto.h>
+#include <linux/module.h>
+#include <linux/cpufeature.h>
+
+MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL");
+
+static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
+{
+ struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ u32 rounds = 6 + ctx->key_length / 4;
+
+ kernel_neon_begin();
+
+ __asm__(" ld1 {v0.16b}, [%[in]] ;"
+ " ld1 {v1.16b}, [%[key]], #16 ;"
+ "0: aese v0.16b, v1.16b ;"
+ " subs %[rounds], %[rounds], #1 ;"
+ " ld1 {v1.16b}, [%[key]], #16 ;"
+ " beq 1f ;"
+ " aesmc v0.16b, v0.16b ;"
+ " b 0b ;"
+ "1: eor v0.16b, v0.16b, v1.16b ;"
+ " st1 {v0.16b}, [%[out]] ;"
+ : :
+ [out] "r"(dst),
+ [in] "r"(src),
+ [rounds] "r"(rounds),
+ [key] "r"(ctx->key_enc)
+ : "cc");
+
+ kernel_neon_end();
+}
+
+static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
+{
+ struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ u32 rounds = 6 + ctx->key_length / 4;
+
+ kernel_neon_begin();
+
+ __asm__(" ld1 {v0.16b}, [%[in]] ;"
+ " ld1 {v1.16b}, [%[key]], #16 ;"
+ "0: aesd v0.16b, v1.16b ;"
+ " ld1 {v1.16b}, [%[key]], #16 ;"
+ " subs %[rounds], %[rounds], #1 ;"
+ " beq 1f ;"
+ " aesimc v0.16b, v0.16b ;"
+ " b 0b ;"
+ "1: eor v0.16b, v0.16b, v1.16b ;"
+ " st1 {v0.16b}, [%[out]] ;"
+ : :
+ [out] "r"(dst),
+ [in] "r"(src),
+ [rounds] "r"(rounds),
+ [key] "r"(ctx->key_dec)
+ : "cc");
+
+ kernel_neon_end();
+}
+
+static struct crypto_alg aes_alg = {
+ .cra_name = "aes",
+ .cra_driver_name = "aes-ce",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_cipher = {
+ .cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cia_setkey = crypto_aes_set_key,
+ .cia_encrypt = aes_cipher_encrypt,
+ .cia_decrypt = aes_cipher_decrypt
+ }
+};
+
+static int __init aes_mod_init(void)
+{
+ return crypto_register_alg(&aes_alg);
+}
+
+static void __exit aes_mod_exit(void)
+{
+ crypto_unregister_alg(&aes_alg);
+}
+
+module_cpu_feature_match(AES, aes_mod_init);
+module_exit(aes_mod_exit);
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 7bcb70d216e1..f1d98bc346b6 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -791,6 +791,12 @@ config CRYPTO_AES_ARM_BS
This implementation does not rely on any lookup tables so it is
believed to be invulnerable to cache timing attacks.
+config CRYPTO_AES_ARM64_CE
+ tristate "Synchronous AES cipher using ARMv8 Crypto Extensions"
+ depends on ARM64 && KERNEL_MODE_NEON
+ select CRYPTO_ALGAPI
+ select CRYPTO_AES
+
config CRYPTO_ANUBIS
tristate "Anubis cipher algorithm"
select CRYPTO_ALGAPI
--
1.8.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5/5] arm64: add Crypto Extensions based synchronous core AES cipher
2014-01-29 16:50 ` [PATCH 5/5] arm64: add Crypto Extensions based synchronous core AES cipher Ard Biesheuvel
@ 2014-01-30 18:56 ` Will Deacon
2014-01-30 19:20 ` Ard Biesheuvel
0 siblings, 1 reply; 11+ messages in thread
From: Will Deacon @ 2014-01-30 18:56 UTC (permalink / raw)
To: linux-arm-kernel
Hi Ard,
On Wed, Jan 29, 2014 at 04:50:46PM +0000, Ard Biesheuvel wrote:
> diff --git a/arch/arm64/crypto/aes-ce-cipher.c b/arch/arm64/crypto/aes-ce-cipher.c
> new file mode 100644
> index 000000000000..b5a5d5d6e4b8
> --- /dev/null
> +++ b/arch/arm64/crypto/aes-ce-cipher.c
> @@ -0,0 +1,103 @@
> +/*
> + * linux/arch/arm64/crypto/aes-ce-cipher.c
> + *
> + * Copyright (C) 2013 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.
> + */
> +
> +#include <asm/neon.h>
> +#include <crypto/aes.h>
> +#include <linux/crypto.h>
> +#include <linux/module.h>
> +#include <linux/cpufeature.h>
> +
> +MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions");
> +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
> +MODULE_LICENSE("GPL");
> +
> +static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
> +{
> + struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
> + u32 rounds = 6 + ctx->key_length / 4;
Can you document these constants please?
> +
> + kernel_neon_begin();
> +
> + __asm__(" ld1 {v0.16b}, [%[in]] ;"
> + " ld1 {v1.16b}, [%[key]], #16 ;"
> + "0: aese v0.16b, v1.16b ;"
> + " subs %[rounds], %[rounds], #1 ;"
> + " ld1 {v1.16b}, [%[key]], #16 ;"
> + " beq 1f ;"
> + " aesmc v0.16b, v0.16b ;"
> + " b 0b ;"
> + "1: eor v0.16b, v0.16b, v1.16b ;"
> + " st1 {v0.16b}, [%[out]] ;"
> + : :
> + [out] "r"(dst),
> + [in] "r"(src),
> + [rounds] "r"(rounds),
> + [key] "r"(ctx->key_enc)
> + : "cc");
You probably need a memory output to stop this being re-ordered by the
compiler. Can GCC not generate the addressing modes you need directly,
allowing you to avoid moving everything into registers?
> + kernel_neon_end();
> +}
> +
> +static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
> +{
> + struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
> + u32 rounds = 6 + ctx->key_length / 4;
> +
> + kernel_neon_begin();
> +
> + __asm__(" ld1 {v0.16b}, [%[in]] ;"
> + " ld1 {v1.16b}, [%[key]], #16 ;"
> + "0: aesd v0.16b, v1.16b ;"
> + " ld1 {v1.16b}, [%[key]], #16 ;"
> + " subs %[rounds], %[rounds], #1 ;"
> + " beq 1f ;"
> + " aesimc v0.16b, v0.16b ;"
> + " b 0b ;"
> + "1: eor v0.16b, v0.16b, v1.16b ;"
> + " st1 {v0.16b}, [%[out]] ;"
> + : :
> + [out] "r"(dst),
> + [in] "r"(src),
> + [rounds] "r"(rounds),
> + [key] "r"(ctx->key_dec)
> + : "cc");
Same comments here.
FWIW: I spoke to the guy at ARM who designed the crypto instructions and he
reckons your code works :)
Cheers,
Will "got a B in maths" Deacon
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 5/5] arm64: add Crypto Extensions based synchronous core AES cipher
2014-01-30 18:56 ` Will Deacon
@ 2014-01-30 19:20 ` Ard Biesheuvel
2014-02-03 16:17 ` Will Deacon
0 siblings, 1 reply; 11+ messages in thread
From: Ard Biesheuvel @ 2014-01-30 19:20 UTC (permalink / raw)
To: linux-arm-kernel
On 30 January 2014 19:56, Will Deacon <will.deacon@arm.com> wrote:
> Hi Ard,
>
> On Wed, Jan 29, 2014 at 04:50:46PM +0000, Ard Biesheuvel wrote:
>> diff --git a/arch/arm64/crypto/aes-ce-cipher.c b/arch/arm64/crypto/aes-ce-cipher.c
>> new file mode 100644
>> index 000000000000..b5a5d5d6e4b8
>> --- /dev/null
>> +++ b/arch/arm64/crypto/aes-ce-cipher.c
>> @@ -0,0 +1,103 @@
>> +/*
>> + * linux/arch/arm64/crypto/aes-ce-cipher.c
>> + *
>> + * Copyright (C) 2013 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.
>> + */
>> +
>> +#include <asm/neon.h>
>> +#include <crypto/aes.h>
>> +#include <linux/crypto.h>
>> +#include <linux/module.h>
>> +#include <linux/cpufeature.h>
>> +
>> +MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions");
>> +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
>> +MODULE_LICENSE("GPL");
>> +
>> +static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
>> +{
>> + struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
>> + u32 rounds = 6 + ctx->key_length / 4;
>
> Can you document these constants please?
>
Sure.
>> +
>> + kernel_neon_begin();
>> +
>> + __asm__(" ld1 {v0.16b}, [%[in]] ;"
>> + " ld1 {v1.16b}, [%[key]], #16 ;"
>> + "0: aese v0.16b, v1.16b ;"
>> + " subs %[rounds], %[rounds], #1 ;"
>> + " ld1 {v1.16b}, [%[key]], #16 ;"
>> + " beq 1f ;"
>> + " aesmc v0.16b, v0.16b ;"
>> + " b 0b ;"
>> + "1: eor v0.16b, v0.16b, v1.16b ;"
>> + " st1 {v0.16b}, [%[out]] ;"
>> + : :
>> + [out] "r"(dst),
>> + [in] "r"(src),
>> + [rounds] "r"(rounds),
>> + [key] "r"(ctx->key_enc)
>> + : "cc");
>
> You probably need a memory output to stop this being re-ordered by the
> compiler. Can GCC not generate the addressing modes you need directly,
> allowing you to avoid moving everything into registers?
>
Would a memory clobber work as well?
Re addressing modes: I would prefer to explicitly use v0 and v1, I
have another patch pending that allows partial saves/restores of the
NEON register file when called from interrupt context. I suppose I
could use 'register asm("v0")' or something like that, but that won't
make it any prettier.
>
>> + kernel_neon_end();
>> +}
>> +
>> +static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
>> +{
>> + struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
>> + u32 rounds = 6 + ctx->key_length / 4;
>> +
>> + kernel_neon_begin();
>> +
>> + __asm__(" ld1 {v0.16b}, [%[in]] ;"
>> + " ld1 {v1.16b}, [%[key]], #16 ;"
>> + "0: aesd v0.16b, v1.16b ;"
>> + " ld1 {v1.16b}, [%[key]], #16 ;"
>> + " subs %[rounds], %[rounds], #1 ;"
>> + " beq 1f ;"
>> + " aesimc v0.16b, v0.16b ;"
>> + " b 0b ;"
>> + "1: eor v0.16b, v0.16b, v1.16b ;"
>> + " st1 {v0.16b}, [%[out]] ;"
>> + : :
>> + [out] "r"(dst),
>> + [in] "r"(src),
>> + [rounds] "r"(rounds),
>> + [key] "r"(ctx->key_dec)
>> + : "cc");
>
> Same comments here.
>
> FWIW: I spoke to the guy at ARM who designed the crypto instructions and he
> reckons your code works :)
>
Good!
Care to comment on the rest of the series?
Cheers.
Ard.
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 5/5] arm64: add Crypto Extensions based synchronous core AES cipher
2014-01-30 19:20 ` Ard Biesheuvel
@ 2014-02-03 16:17 ` Will Deacon
0 siblings, 0 replies; 11+ messages in thread
From: Will Deacon @ 2014-02-03 16:17 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Jan 30, 2014 at 07:20:38PM +0000, Ard Biesheuvel wrote:
> On 30 January 2014 19:56, Will Deacon <will.deacon@arm.com> wrote:
> > On Wed, Jan 29, 2014 at 04:50:46PM +0000, Ard Biesheuvel wrote:
> >> +static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
> >> +{
> >> + struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
> >> + u32 rounds = 6 + ctx->key_length / 4;
> >
> > Can you document these constants please?
> >
>
> Sure.
Thanks.
> >> +
> >> + kernel_neon_begin();
> >> +
> >> + __asm__(" ld1 {v0.16b}, [%[in]] ;"
> >> + " ld1 {v1.16b}, [%[key]], #16 ;"
> >> + "0: aese v0.16b, v1.16b ;"
> >> + " subs %[rounds], %[rounds], #1 ;"
> >> + " ld1 {v1.16b}, [%[key]], #16 ;"
> >> + " beq 1f ;"
> >> + " aesmc v0.16b, v0.16b ;"
> >> + " b 0b ;"
> >> + "1: eor v0.16b, v0.16b, v1.16b ;"
> >> + " st1 {v0.16b}, [%[out]] ;"
> >> + : :
> >> + [out] "r"(dst),
> >> + [in] "r"(src),
> >> + [rounds] "r"(rounds),
> >> + [key] "r"(ctx->key_enc)
> >> + : "cc");
> >
> > You probably need a memory output to stop this being re-ordered by the
> > compiler. Can GCC not generate the addressing modes you need directly,
> > allowing you to avoid moving everything into registers?
> >
>
> Would a memory clobber work as well?
It would, but it could lead to suboptimal code generation by GCC (although
neon_{begin,end} may well stop GCC in its tracks anyway, so worth looking at
the disassembly).
> Re addressing modes: I would prefer to explicitly use v0 and v1, I
> have another patch pending that allows partial saves/restores of the
> NEON register file when called from interrupt context. I suppose I
> could use 'register asm("v0")' or something like that, but that won't
> make it any prettier.
It's not the use of v0/v1 that I was objecting to. I was hoping that we
could describe [in] and [out] as memory operands, so that GCC could
potentially reduce register usage for base + offset style addressing modes.
Unfortunately, I don't think we have such a constraint for AArch64 :(
If the disassembly looks ok, the "memory" clobber is probably our best bet.
Will
^ permalink raw reply [flat|nested] 11+ messages in thread