diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 9f5bd41bf660..b73414eb1c01 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2436,6 +2436,15 @@ config STRICT_SIGALTSTACK_SIZE
 
 source "kernel/livepatch/Kconfig"
 
+config X86_TAGGED_ADDR_ABI
+	bool "Enable the tagged user addresses syscall ABI"
+	depends on X86_64 && CPU_SUP_AMD
+	default y
+	help
+	  When this option is enabled, user applications can opt-in to a
+	  relaxed ABI via prctl() allowing tagged addresses to be passed
+	  to system calls as pointer arguments.
+
 endmenu
 
 config ARCH_HAS_ADD_PAGES
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 2c5f12ae7d04..414e2c039c34 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -863,4 +863,16 @@ bool arch_is_platform_page(u64 paddr);
 #define arch_is_platform_page arch_is_platform_page
 #endif
 
+#ifdef CONFIG_X86_TAGGED_ADDR_ABI
+/* PR_{SET,GET}_TAGGED_ADDR_CTRL prctl */
+long set_tagged_addr_ctrl(struct task_struct *task, unsigned long flags,
+			  int __user *nr_bits, int __user *offset);
+long get_tagged_addr_ctrl(struct task_struct *task,
+			  int __user *nr_bits, int __user *offset);
+#define SET_TAGGED_ADDR_CTRL(flags, nr_bits, offset)	\
+	set_tagged_addr_ctrl(current, flags, nr_bits, offset)
+#define GET_TAGGED_ADDR_CTRL(nr_bits, offset)		\
+	get_tagged_addr_ctrl(current, nr_bits, offset)
+#endif
+
 #endif /* _ASM_X86_PROCESSOR_H */
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index feb2e21c7e09..e415523dc425 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -38,7 +38,8 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un
 static inline bool __range_not_ok(const void __user *addr, unsigned long size,
 				  unsigned long limit)
 {
-	if (test_thread_flag(TIF_TAGGED_ADDR))
+	if (IS_ENABLED(CONFIG_X86_TAGGED_ADDR_ABI) &&
+	    (current->flags & PF_KTHREAD || test_thread_flag(TIF_TAGGED_ADDR)))
 		addr = untagged_addr(addr);
 
 	__chk_user_ptr(addr);
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 81d8ef036637..2bc44efdd994 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -26,6 +26,7 @@
 #include <linux/elf-randomize.h>
 #include <trace/events/power.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/sysctl.h>
 #include <asm/cpu.h>
 #include <asm/apic.h>
 #include <linux/uaccess.h>
@@ -231,6 +232,12 @@ static void pkru_flush_thread(void)
 	pkru_write_default();
 }
 
+static void flush_tagged_addr_state(void)
+{
+	if (IS_ENABLED(CONFIG_X86_TAGGED_ADDR_ABI))
+		clear_thread_flag(TIF_TAGGED_ADDR);
+}
+
 void flush_thread(void)
 {
 	struct task_struct *tsk = current;
@@ -240,6 +247,7 @@ void flush_thread(void)
 
 	fpu_flush_thread();
 	pkru_flush_thread();
+	flush_tagged_addr_state();
 }
 
 void disable_TSC(void)
@@ -1000,3 +1008,129 @@ long do_arch_prctl_common(struct task_struct *task, int option,
 
 	return -EINVAL;
 }
+
+#ifdef CONFIG_X86_TAGGED_ADDR_ABI
+/*
+ * Control the relaxed ABI allowing tagged user addresses into the kernel.
+ */
+static unsigned int tagged_addr_disabled;
+
+#ifdef CONFIG_CPU_SUP_AMD
+#define UAI_TAG_BITS	7
+
+static long amd_set_tagged_addr_ctrl(unsigned long flags, int __user *nr_bits,
+				     int __user *offset)
+{
+	int val;
+
+	if (!boot_cpu_has(X86_FEATURE_UAI))
+		return -EINVAL;
+
+	/* Disable tagging */
+	if (!(flags & PR_TAGGED_ADDR_ENABLE)) {
+		clear_thread_flag(TIF_TAGGED_ADDR);
+		return 0;
+	}
+
+	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 != UAI_TAG_BITS)
+		return -EINVAL;
+
+	if (put_user(val, nr_bits) || put_user(64 - val, offset))
+		return -EFAULT;
+
+	set_thread_flag(TIF_TAGGED_ADDR);
+	return 0;
+}
+
+static long amd_get_tagged_addr_ctrl(int __user *nr_bits, int __user *offset)
+{
+	long ret = 0;
+
+	if (!boot_cpu_has(X86_FEATURE_UAI))
+		return -EINVAL;
+
+	if (test_thread_flag(TIF_TAGGED_ADDR)) {
+		if (nr_bits && put_user(UAI_TAG_BITS, nr_bits))
+			return -EFAULT;
+		if (offset && put_user(64 - UAI_TAG_BITS, offset))
+			return -EFAULT;
+		ret = PR_TAGGED_ADDR_ENABLE;
+	} else {
+		/* Report max tag size */
+		if (nr_bits && put_user(UAI_TAG_BITS, nr_bits))
+			return -EFAULT;
+	}
+	return ret;
+}
+#endif
+
+long set_tagged_addr_ctrl(struct task_struct *task, unsigned long flags,
+			  int __user *nr_bits, int __user *offset)
+{
+	unsigned long valid_mask = PR_TAGGED_ADDR_ENABLE;
+
+	if (in_32bit_syscall())
+		return -EINVAL;
+
+	if (flags & ~valid_mask)
+		return -EINVAL;
+
+	if (IS_ENABLED(CONFIG_CPU_SUP_AMD))
+		return amd_set_tagged_addr_ctrl(flags, nr_bits, offset);
+	else
+		return -EINVAL;
+}
+
+long get_tagged_addr_ctrl(struct task_struct *task,
+			  int __user *nr_bits, int __user *offset)
+{
+
+	if (in_32bit_syscall())
+		return -EINVAL;
+
+	if (IS_ENABLED(CONFIG_CPU_SUP_AMD))
+		return amd_get_tagged_addr_ctrl(nr_bits, offset);
+	else
+		return -EINVAL;
+}
+
+/*
+ * 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);
+#endif	/* CONFIG_X86_TAGGED_ADDR_ABI */
