From: Dave Martin <Dave.Martin@arm.com>
To: linux-arm-kernel@lists.infradead.org
Cc: Will Deacon <will.deacon@arm.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Marc Zyngier <Marc.Zyngier@arm.com>,
Ard Biesheuvel <ard.biesheuvel@linaro.org>,
Florian Weimer <fweimer@redhat.com>,
Joseph Myers <joseph@codesourcery.com>,
Szabolcs Nagy <szabolcs.nagy@arm.com>,
Alan Hayward <alan.hayward@arm.com>, Yao Qi <Yao.Qi@arm.com>,
gdb@sourceware.org
Subject: [RFC PATCH v2 37/41] arm64/sve: Enable default vector length control via procfs
Date: Wed, 22 Mar 2017 14:54:00 -0000 [thread overview]
Message-ID: <1490194274-30569-38-git-send-email-Dave.Martin@arm.com> (raw)
In-Reply-To: <1490194274-30569-1-git-send-email-Dave.Martin@arm.com>
This patch makes the default SVE vector length at exec() for user tasks
controllable via procfs, in /proc/cpu/sve_default_vector_length.
Limited effort is made to return sensible errors when writing the
procfs file, and anyway the value gets silently clamped to the
maximum VL supported by the platform: users should close and reopen
the file and read back to see the result.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
arch/arm64/kernel/fpsimd.c | 162 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 160 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 982b1d7..ddb651a 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -22,8 +22,12 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/prctl.h>
+#include <linux/proc_fs.h>
#include <linux/sched/signal.h>
+#include <linux/seq_file.h>
#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
#include <linux/hardirq.h>
#include <asm/fpsimd.h>
@@ -100,6 +104,8 @@ static DEFINE_PER_CPU(struct fpsimd_state *, fpsimd_last_state);
/* Maximum supported vector length across all CPUs (initially poisoned) */
int sve_max_vl = -1;
+/* Default VL for tasks that don't set it explicitly: */
+int sve_default_vl = -1;
void *__sve_state(struct task_struct *task)
{
@@ -334,13 +340,154 @@ int sve_get_task_vl(struct task_struct *task)
return sve_prctl_status(task);
}
+#ifdef CONFIG_PROC_FS
+
+struct default_vl_write_state {
+ bool invalid;
+ size_t len;
+ char buf[40]; /* enough for "0x" + 64-bit hex integer + NUL */
+};
+
+static int sve_default_vl_show(struct seq_file *s, void *data)
+{
+ seq_printf(s, "%d\n", sve_default_vl);
+ return 0;
+}
+
+static ssize_t sve_default_vl_write(struct file *f, const char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct default_vl_write_state *state =
+ ((struct seq_file *)f->private_data)->private;
+ long ret;
+
+ if (!size)
+ return 0;
+
+ if (*pos > sizeof(state->buf) ||
+ size >= sizeof(state->buf) - *pos) {
+ ret = -ENOSPC;
+ goto error;
+ }
+
+ ret = copy_from_user(state->buf + *pos, buf, size);
+ if (ret > 0)
+ ret = -EINVAL;
+ if (ret)
+ goto error;
+
+ *pos += size;
+ if (*pos > state->len)
+ state->len = *pos;
+
+ return size;
+
+error:
+ state->invalid = true;
+ return ret;
+}
+
+static int sve_default_vl_release(struct inode *i, struct file *f)
+{
+ int ret = 0;
+ int t;
+ unsigned long value;
+ struct default_vl_write_state *state =
+ ((struct seq_file *)f->private_data)->private;
+
+ if (!(f->f_mode & FMODE_WRITE))
+ goto out;
+
+ if (state->invalid)
+ goto out;
+
+ if (state->len >= sizeof(state->buf)) {
+ WARN_ON(1);
+ state->len = sizeof(state->buf) - 1;
+ }
+
+ state->buf[state->len] = '\0';
+ t = kstrtoul(state->buf, 0, &value);
+ if (t)
+ ret = t;
+
+ if (!sve_vl_valid(value))
+ ret = -EINVAL;
+
+ if (!sve_vl_valid(sve_max_vl)) {
+ WARN_ON(1);
+ ret = -EINVAL;
+ }
+
+ if (value > sve_max_vl)
+ value = sve_max_vl;
+
+ if (!ret)
+ sve_default_vl = value;
+
+out:
+ t = seq_release_private(i, f);
+ return ret ? ret : t;
+}
+
+static int sve_default_vl_open(struct inode *i, struct file *f)
+{
+ struct default_vl_write_state *data = NULL;
+ int ret;
+
+ if (f->f_mode & FMODE_WRITE) {
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->invalid = false;
+ data->len = 0;
+ }
+
+ ret = single_open(f, sve_default_vl_show, data);
+ if (ret)
+ kfree(data);
+
+ return ret;
+}
+
+static const struct file_operations sve_default_vl_fops = {
+ .open = sve_default_vl_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = sve_default_vl_release,
+ .write = sve_default_vl_write,
+};
+
+static int __init sve_procfs_init(void)
+{
+ struct proc_dir_entry *dir;
+
+ /* This should be moved elsewhere is anything else ever uses it: */
+ dir = proc_mkdir("cpu", NULL);
+ if (!dir)
+ return -ENOMEM;
+
+ if (!proc_create("sve_default_vector_length",
+ S_IRUGO | S_IWUSR, dir, &sve_default_vl_fops))
+ return -ENOMEM;
+
+ return 0;
+}
+
+#else /* ! CONFIG_PROC_FS && CONFIG_ARM64_SVE */
+static int __init sve_procfs_init(void) { return 0; }
+#endif /* ! CONFIG_PROC_FS && CONFIG_ARM64_SVE */
+
#else /* ! CONFIG_ARM64_SVE */
/* Dummy declarations for usage protected with IS_ENABLED(CONFIG_ARM64_SVE): */
extern int sve_max_vl;
+extern int sve_default_vl;
extern void clear_sve_regs(struct task_struct *task);
extern void *sve_pffr(struct task_struct *task);
extern void fpsimd_to_sve(struct task_struct *task);
+extern int __init sve_procfs_init(void);
/* Functions that map to no-ops without SVE: */
static void sve_to_fpsimd(struct task_struct *task __always_unused) { }
@@ -489,13 +636,13 @@ void fpsimd_flush_thread(void)
clear_sve_regs(current);
current->thread.sve_vl = current->thread.sve_vl_onexec ?
- current->thread.sve_vl_onexec : sve_max_vl;
+ current->thread.sve_vl_onexec : sve_default_vl;
/*
* User tasks must have a valid vector length set, but tasks
* forked early (e.g., init) may not initially have one.
* By now, we will know what the hardware supports, so
- * sve_max_vl should be valid, and thus the above
+ * sve_default_vl should be valid, and thus the above
* assignment should ensure a valid VL for the task.
* If not, something went badly wrong.
*/
@@ -717,6 +864,14 @@ void __init fpsimd_init_task_struct_size(void)
& 0xf) == 1) {
/* FIXME: This should be the minimum across all CPUs */
sve_max_vl = sve_get_vl();
+ sve_default_vl = sve_max_vl;
+
+ /*
+ * To avoid enlarging the signal frame by default, clamp to
+ * 512 bits until/unless overridden by userspace:
+ */
+ if (sve_default_vl > 512 / 8)
+ sve_default_vl = 512 / 8;
BUG_ON(!sve_vl_valid(sve_max_vl));
vq = sve_vq_from_vl(sve_max_vl);
@@ -746,6 +901,9 @@ static int __init fpsimd_init(void)
if (!(elf_hwcap & HWCAP_SVE))
pr_info("Scalable Vector Extension available\n");
+ if (IS_ENABLED(CONFIG_ARM64_SVE) && (elf_hwcap & HWCAP_SVE))
+ return sve_procfs_init();
+
return 0;
}
late_initcall(fpsimd_init);
--
2.1.4
next prev parent reply other threads:[~2017-03-22 14:54 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-22 14:51 [RFC PATCH v2 00/41] Scalable Vector Extension (SVE) core support Dave Martin
2017-03-22 14:54 ` [RFC PATCH v2 36/41] arm64/sve: ptrace: Wire up vector length control and reporting Dave Martin
2017-03-22 14:54 ` [RFC PATCH v2 41/41] arm64/sve: Documentation: Add overview of the SVE userspace ABI Dave Martin
2017-03-22 14:54 ` Dave Martin [this message]
2017-03-31 15:28 ` [RFC PATCH v2 00/41] Scalable Vector Extension (SVE) core support Ard Biesheuvel
[not found] ` <20170403094501.GN3750@e103592.cambridge.arm.com>
2017-04-03 10:01 ` Ard Biesheuvel
2017-04-03 10:52 ` Dave Martin
2017-04-03 10:55 ` Ard Biesheuvel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1490194274-30569-38-git-send-email-Dave.Martin@arm.com \
--to=dave.martin@arm.com \
--cc=Marc.Zyngier@arm.com \
--cc=Yao.Qi@arm.com \
--cc=alan.hayward@arm.com \
--cc=ard.biesheuvel@linaro.org \
--cc=catalin.marinas@arm.com \
--cc=fweimer@redhat.com \
--cc=gdb@sourceware.org \
--cc=joseph@codesourcery.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=szabolcs.nagy@arm.com \
--cc=will.deacon@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox