From patchwork Wed Mar 22 14:51:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Martin X-Patchwork-Id: 9639191 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A14AF602CB for ; Wed, 22 Mar 2017 15:08:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 904A42845C for ; Wed, 22 Mar 2017 15:08:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 832082846F; Wed, 22 Mar 2017 15:08:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id EFE062845C for ; Wed, 22 Mar 2017 15:08:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=zV8gJLAxvd2guUNKvR+z3vGA4ON0ON9cCALhOkxwumw=; b=St4kR4yKjAN3aU+aHBPVtb8fiu ZpZUAj2ORHlK1dBVebCwqvoHXjVfIMZx71lxvNUbFHC893TgMQ+vbkCXNvEXAit28Qs3gNPHvk233 gEr7mqt3h3uBRD8j8x80wC5HF+eJ4Ehpz+PVzPb4WypzQNP19WZi9zLY7gtyqQnd621uIxV+5ouN2 i/nWdsw2lWLf7WQsXeS50WZ8nSsUedz+PNmcU8HZS93T5etbeDEBBKlgp5cJICaAw0nj5K6D5H1Sx H3K0iv+/6RzgJiNam3C9UHPX+O0hBnGdYhLDRrMYTisyHuxCqI3l2rYxaflyqGvRSEcnAeLU2GXR6 4AOsOx+Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cqhsH-0005Lc-Ke; Wed, 22 Mar 2017 15:08:33 +0000 Received: from casper.infradead.org ([2001:770:15f::2]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cqhri-0004A1-6Y for linux-arm-kernel@bombadil.infradead.org; Wed, 22 Mar 2017 15:07:58 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=SY1q9DJnTIAof9ELPnmkDu789NJfmEQADvWxhZxJCvo=; b=QtXTSrREmJqcO0NYfNadtdX0+ n9vmypwBheYdNtX3oYeyYR2X2Pg5A0TsuhUK1jvJlm7tu9sZQntAiF3TFZZLarLylj45pHXDjYzPs O0MCRCuNvoxKBs9/l+8W1tAZg/d/QjbOlRqOLW6uNhETk+Nw3zLdB/dmgrRNgZU2c6g4heNT9EGHN wUxESUPsTokMDrPT0D0YW38du1VsU73hnb6Q2mdYFknEw66vgDkhZXtt9+/awWSTZBND3KrVFtg9q gBo9MBNldw8VS1+reAfuzDhtjqXbLRLLf5/gfc/dXnc6eDoDipWDguFYG9skjL97w0z0JFM65k3gy 6pMHVjEjw==; Received: from foss.arm.com ([217.140.101.70]) by casper.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cqhes-00023b-4J for linux-arm-kernel@lists.infradead.org; Wed, 22 Mar 2017 14:54:44 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 5A4401597; Wed, 22 Mar 2017 07:54:21 -0700 (PDT) Received: from e103592.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id A222A3F575; Wed, 22 Mar 2017 07:54:19 -0700 (PDT) From: Dave Martin To: linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 37/41] arm64/sve: Enable default vector length control via procfs Date: Wed, 22 Mar 2017 14:51:07 +0000 Message-Id: <1490194274-30569-38-git-send-email-Dave.Martin@arm.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1490194274-30569-1-git-send-email-Dave.Martin@arm.com> References: <1490194274-30569-1-git-send-email-Dave.Martin@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170322_145442_449594_8C793640 X-CRM114-Status: GOOD ( 23.11 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Florian Weimer , gdb@sourceware.org, Ard Biesheuvel , Marc Zyngier , Catalin Marinas , Yao Qi , Will Deacon , Szabolcs Nagy , Alan Hayward , Joseph Myers MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 #include #include +#include #include +#include #include +#include +#include #include #include @@ -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);