All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
To: Dave Hansen <dave.hansen@linux.intel.com>,
	Andy Lutomirski <luto@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>
Cc: x86@kernel.org, Andrey Ryabinin <aryabinin@virtuozzo.com>,
	Alexander Potapenko <glider@google.com>,
	Dmitry Vyukov <dvyukov@google.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>, "H . J . Lu" <hjl.tools@gmail.com>,
	Andi Kleen <ak@linux.intel.com>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Subject: [RFC 9/9] x86/mm: Implement PR_SET/GET_TAGGED_ADDR_CTRL with LAM
Date: Fri,  5 Feb 2021 18:16:30 +0300	[thread overview]
Message-ID: <20210205151631.43511-11-kirill.shutemov@linux.intel.com> (raw)
In-Reply-To: <20210205151631.43511-1-kirill.shutemov@linux.intel.com>

Provide prctl() interface to enabled LAM for user addresses. Depending
how many tag bits requested it may result in enabling LAM_U57 or
LAM_U48.

If LAM_U48 is enabled, the process is no longer able to use full address
space on 5-level paging machine and gets limited to 47-bit VA.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
 arch/x86/include/asm/processor.h |  10 +++
 arch/x86/kernel/process_64.c     | 145 +++++++++++++++++++++++++++++++
 2 files changed, 155 insertions(+)

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 82a08b585818..49fac2cc4329 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -810,6 +810,16 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
 extern int get_tsc_mode(unsigned long adr);
 extern int set_tsc_mode(unsigned int val);
 
+#ifdef CONFIG_X86_64
+long set_tagged_addr_ctrl(unsigned long flags,
+			  int __user *nr_bits, int __user *offset);
+long get_tagged_addr_ctrl(int __user *nr_bits, int __user *offset);
+#define SET_TAGGED_ADDR_CTRL(flags, nr_bits, offset)	\
+	set_tagged_addr_ctrl(flags, nr_bits, offset)
+#define GET_TAGGED_ADDR_CTRL(nr_bits, offset)		\
+	get_tagged_addr_ctrl(nr_bits, offset)
+#endif
+
 DECLARE_PER_CPU(u64, msr_misc_features_shadow);
 
 #ifdef CONFIG_CPU_SUP_AMD
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index df342bedea88..99b87f0e1bc7 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -837,3 +837,148 @@ unsigned long KSTK_ESP(struct task_struct *task)
 {
 	return task_pt_regs(task)->sp;
 }
+
+/*
+ * Control the relaxed ABI allowing tagged user addresses into the kernel.
+ */
+static unsigned int tagged_addr_disabled;
+
+static bool lam_u48_allowed(void)
+{
+	struct mm_struct *mm = current->mm;
+
+	if (!full_va_allowed(mm))
+		return true;
+
+	return find_vma(mm, DEFAULT_MAP_WINDOW) == NULL;
+}
+
+#define LAM_U48_BITS 15
+#define LAM_U57_BITS 6
+
+long set_tagged_addr_ctrl(unsigned long flags,
+			  int __user *nr_bits, int __user *offset)
+{
+	int val;
+
+	if (in_32bit_syscall())
+		return -EINVAL;
+	if (flags & ~PR_TAGGED_ADDR_ENABLE)
+		return -EINVAL;
+	if (!boot_cpu_has(X86_FEATURE_LAM))
+		return -ENOTSUPP;
+
+	/* Disable LAM */
+	if (!(flags & PR_TAGGED_ADDR_ENABLE)) {
+		clear_thread_flag(TIF_LAM_U48);
+		clear_thread_flag(TIF_LAM_U57);
+
+		/* Update CR3 */
+		switch_mm(current->mm, current->mm, current);
+
+		return 0;
+	}
+
+	/*
+	 * nr_bits == NULL || offset == NULL assumes ARM TBI (nr_bits == 8,
+	 * offset == 56). LAM cannot provide this.
+	 */
+	if (!nr_bits || !offset)
+		return -EINVAL;
+
+	/*
+	 * Do not allow the enabling of the tagged address ABI if globally
+	 * disabled via sysctl abi.tagged_addr_disabled.
+	 */
+	if (tagged_addr_disabled)
+		return -EINVAL;
+
+	if (get_user(val, nr_bits))
+		return -EFAULT;
+	if (val > LAM_U48_BITS || val < 1)
+		return -EINVAL;
+	if (val > LAM_U57_BITS && !lam_u48_allowed())
+		return -EINVAL;
+
+	val = val > LAM_U57_BITS ? LAM_U48_BITS : LAM_U57_BITS;
+	if (put_user(val, nr_bits) || put_user(63 - val, offset))
+		return -EFAULT;
+
+	if (val == LAM_U57_BITS) {
+		clear_thread_flag(TIF_LAM_U48);
+		set_thread_flag(TIF_LAM_U57);
+		if (current->mm->context.lam == LAM_NONE)
+			current->mm->context.lam = LAM_U57;
+	} else {
+		clear_thread_flag(TIF_LAM_U57);
+		set_thread_flag(TIF_LAM_U48);
+
+		/*
+		 * Do not allow to create a mapping above 47 bit.
+		 *
+		 * It's one way road: once a thread of the process enabled
+		 * LAM_U48, no thread can ever create mapping above 47 bit.
+		 * Even the LAM got disabled later.
+		 */
+		current->mm->context.lam = LAM_U48;
+	}
+
+	/* Update CR3 */
+	switch_mm(current->mm, current->mm, current);
+
+	return 0;
+}
+
+long get_tagged_addr_ctrl(int __user *nr_bits, int __user *offset)
+{
+	if (in_32bit_syscall())
+		return -EINVAL;
+
+	if (test_thread_flag(TIF_LAM_U57)) {
+		if (nr_bits && put_user(LAM_U57_BITS, nr_bits))
+			return -EFAULT;
+		if (offset && put_user(63 - LAM_U57_BITS, offset))
+			return -EFAULT;
+	} else if (test_thread_flag(TIF_LAM_U48)) {
+		if (nr_bits && put_user(LAM_U48_BITS, nr_bits))
+			return -EFAULT;
+		if (offset && put_user(63 - LAM_U48_BITS, offset))
+			return -EFAULT;
+	} else {
+		int max_bits = lam_u48_allowed() ? LAM_U48_BITS : LAM_U57_BITS;
+
+		/* Report maximum tag size */
+		if (nr_bits && put_user(max_bits, nr_bits))
+		    return -EFAULT;
+		return 0;
+	}
+
+	return PR_TAGGED_ADDR_ENABLE;
+}
+
+/*
+ * Global sysctl to disable the tagged user addresses support. This control
+ * only prevents the tagged address ABI enabling via prctl() and does not
+ * disable it for tasks that already opted in to the relaxed ABI.
+ */
+
+static struct ctl_table tagged_addr_sysctl_table[] = {
+	{
+		.procname	= "tagged_addr_disabled",
+		.mode		= 0644,
+		.data		= &tagged_addr_disabled,
+		.maxlen		= sizeof(int),
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= SYSCTL_ZERO,
+		.extra2		= SYSCTL_ONE,
+	},
+	{ }
+};
+
+static int __init tagged_addr_init(void)
+{
+	if (!register_sysctl("abi", tagged_addr_sysctl_table))
+		return -EINVAL;
+	return 0;
+}
+core_initcall(tagged_addr_init);
-- 
2.26.2


  parent reply	other threads:[~2021-02-05 20:15 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-05 15:16 [RFC 0/9] Linear Address Masking enabling Kirill A. Shutemov
2021-02-05 15:16 ` [RFC 1/9] mm, arm64: Update PR_SET/GET_TAGGED_ADDR_CTRL interface Kirill A. Shutemov
2021-02-11 16:57   ` Catalin Marinas
2021-02-11 17:06     ` Dave Hansen
2021-02-11 18:26       ` Catalin Marinas
2021-02-05 15:16 ` [QEMU] x86: Implement Linear Address Masking support Kirill A. Shutemov
2021-02-05 15:16 ` [RFC 2/9] x86/mm: Fix CR3_ADDR_MASK Kirill A. Shutemov
2021-02-05 15:16 ` [RFC 3/9] x86: CPUID and CR3/CR4 flags for Linear Address Masking Kirill A. Shutemov
2021-02-05 15:16 ` [RFC 4/9] x86/mm: Introduce TIF_LAM_U57 and TIF_LAM_U48 Kirill A. Shutemov
2021-02-05 15:16 ` [RFC 5/9] x86/mm: Provide untagged_addr() helper Kirill A. Shutemov
2021-02-05 15:16 ` [RFC 6/9] x86/uaccess: Remove tags from the address before checking Kirill A. Shutemov
2021-02-05 15:16 ` [RFC 7/9] x86/mm: Handle tagged memory accesses from kernel threads Kirill A. Shutemov
2021-02-05 15:16 ` [RFC 8/9] x86/mm: Make LAM_U48 and mappings above 47-bits mutually exclusive Kirill A. Shutemov
2021-02-05 15:16 ` Kirill A. Shutemov [this message]
2021-02-05 15:42   ` [RFC 9/9] x86/mm: Implement PR_SET/GET_TAGGED_ADDR_CTRL with LAM H.J. Lu
2021-02-05 15:42     ` H.J. Lu
2021-02-07  8:07     ` Dmitry Vyukov
2021-02-07  8:07       ` Dmitry Vyukov
2021-02-07 14:09       ` Kirill A. Shutemov
2021-02-07 14:11         ` Dmitry Vyukov
2021-02-07 14:11           ` Dmitry Vyukov
2021-02-05 15:16 ` [QEMU] x86: Implement Linear Address Masking support Kirill A. Shutemov
2021-02-05 15:49 ` [RFC 0/9] Linear Address Masking enabling Peter Zijlstra
2021-02-05 16:01   ` Kirill A. Shutemov
2021-02-05 16:19     ` Peter Zijlstra
2021-02-07  8:24 ` Dmitry Vyukov
2021-02-07  8:24   ` Dmitry Vyukov
2021-02-07 14:11   ` Kirill A. Shutemov
2021-09-21 16:52     ` Dmitry Vyukov
2021-09-21 16:52       ` Dmitry Vyukov
2021-09-21 17:15       ` H.J. Lu
2021-09-21 17:15         ` H.J. Lu
2021-09-22  1:15         ` Zhang, Xiang1
2021-09-22 12:54           ` Dmitry Vyukov
2021-09-22 12:54             ` Dmitry Vyukov
2021-09-22 20:03             ` Dmitry Vyukov
2021-09-22 20:03               ` Dmitry Vyukov
2021-09-22 21:33               ` Kirill A. Shutemov
2021-09-23  0:15               ` H.J. Lu
2021-09-23  0:15                 ` H.J. Lu
2021-09-23  5:35                 ` Dmitry Vyukov
2021-09-23  5:35                   ` Dmitry Vyukov
2021-09-23  0:07             ` H.J. Lu
2021-09-23  0:07               ` H.J. Lu

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=20210205151631.43511-11-kirill.shutemov@linux.intel.com \
    --to=kirill.shutemov@linux.intel.com \
    --cc=ak@linux.intel.com \
    --cc=aryabinin@virtuozzo.com \
    --cc=catalin.marinas@arm.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=dvyukov@google.com \
    --cc=glider@google.com \
    --cc=hjl.tools@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=luto@kernel.org \
    --cc=peterz@infradead.org \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.