[PATCH v1 2/4] x86/process: Add a debug interface to change LAM tag width

From: Maciej Wieczor-Retman

Date: Fri Feb 20 2026 - 07:49:38 EST


From: Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx>

While shortening the tag bits to converge the specifications of LAM and
ChkTag, the 6 bit wide LAM (Linear Address Masking) tags should still be
available to use. Since using this tag width is likely going to be for
debug purposes only, using debugfs is the best choice.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx>
---
arch/x86/kernel/process_64.c | 56 ++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)

diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 04968b303e66..2f9f74cddd2a 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -41,6 +41,7 @@
#include <linux/ftrace.h>
#include <linux/syscalls.h>
#include <linux/iommu.h>
+#include <linux/debugfs.h>

#include <asm/processor.h>
#include <asm/pkru.h>
@@ -802,6 +803,61 @@ static long prctl_map_vdso(const struct vdso_image *image, unsigned long addr)

unsigned long lam_available_bits = LAM_DEFAULT_BITS;

+static ssize_t lam_bits_read_file(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char buf[2];
+ unsigned int len;
+
+ len = sprintf(buf, "%ld\n", lam_available_bits);
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+/*
+ * Writing a number to this file changes the used lam tag width. Valid values
+ * are 4 bit tag width and 6 bit tag width - the second, non-default one is
+ * meant mostly for debug and shall be deprecated in the future.
+ */
+static ssize_t lam_bits_write_file(struct file *file,
+ const char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ char buf[32];
+ ssize_t len;
+ int ceiling;
+ u8 bits;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ if (kstrtou8(buf, 0, &bits))
+ return -EINVAL;
+
+ switch (bits) {
+ case LAM_DEFAULT_BITS:
+ case LAM_MAX_BITS:
+ lam_available_bits = bits;
+ return count;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct file_operations fops_lam_bits = {
+ .read = lam_bits_read_file,
+ .write = lam_bits_write_file,
+};
+
+static int __init create_lam_available_bits(void)
+{
+ debugfs_create_file("lam_available_bits", 0600,
+ arch_debugfs_dir, NULL, &fops_lam_bits);
+ return 0;
+}
+late_initcall(create_lam_available_bits);
+
static void enable_lam_func(void *__mm)
{
struct mm_struct *mm = __mm;
--
2.53.0