Skip to content

Commit 2f8794b

Browse files
kirylhansendc
authored andcommitted
x86/mm: Provide arch_prctl() interface for LAM
Add a few of arch_prctl() handles: - ARCH_ENABLE_TAGGED_ADDR enabled LAM. The argument is required number of tag bits. It is rounded up to the nearest LAM mode that can provide it. For now only LAM_U57 is supported, with 6 tag bits. - ARCH_GET_UNTAG_MASK returns untag mask. It can indicates where tag bits located in the address. - ARCH_GET_MAX_TAG_BITS returns the maximum tag bits user can request. Zero if LAM is not supported. Signed-off-by: Kirill A. Shutemov <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Tested-by: Alexander Potapenko <[email protected]> Link: https://lore.kernel.org/all/20230312112612.31869-9-kirill.shutemov%40linux.intel.com
1 parent e0bddc1 commit 2f8794b

File tree

4 files changed

+63
-1
lines changed

4 files changed

+63
-1
lines changed

arch/x86/include/asm/mmu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#define MM_CONTEXT_UPROBE_IA32 0
1313
/* vsyscall page is accessible on this MM */
1414
#define MM_CONTEXT_HAS_VSYSCALL 1
15+
/* Do not allow changing LAM mode */
16+
#define MM_CONTEXT_LOCK_LAM 2
1517

1618
/*
1719
* x86 has arch-specific MMU state beyond what lives in mm_struct.

arch/x86/include/uapi/asm/prctl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@
2020
#define ARCH_MAP_VDSO_32 0x2002
2121
#define ARCH_MAP_VDSO_64 0x2003
2222

23+
#define ARCH_GET_UNTAG_MASK 0x4001
24+
#define ARCH_ENABLE_TAGGED_ADDR 0x4002
25+
#define ARCH_GET_MAX_TAG_BITS 0x4003
26+
2327
#endif /* _ASM_X86_PRCTL_H */

arch/x86/kernel/process.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
163163

164164
savesegment(es, p->thread.es);
165165
savesegment(ds, p->thread.ds);
166+
167+
if (p->mm && (clone_flags & (CLONE_VM | CLONE_VFORK)) == CLONE_VM)
168+
set_bit(MM_CONTEXT_LOCK_LAM, &p->mm->context.flags);
166169
#else
167170
p->thread.sp0 = (unsigned long) (childregs + 1);
168171
savesegment(gs, p->thread.gs);

arch/x86/kernel/process_64.c

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,48 @@ static long prctl_map_vdso(const struct vdso_image *image, unsigned long addr)
743743
}
744744
#endif
745745

746+
#ifdef CONFIG_ADDRESS_MASKING
747+
748+
#define LAM_U57_BITS 6
749+
750+
static int prctl_enable_tagged_addr(struct mm_struct *mm, unsigned long nr_bits)
751+
{
752+
if (!cpu_feature_enabled(X86_FEATURE_LAM))
753+
return -ENODEV;
754+
755+
/* PTRACE_ARCH_PRCTL */
756+
if (current->mm != mm)
757+
return -EINVAL;
758+
759+
if (mmap_write_lock_killable(mm))
760+
return -EINTR;
761+
762+
if (test_bit(MM_CONTEXT_LOCK_LAM, &mm->context.flags)) {
763+
mmap_write_unlock(mm);
764+
return -EBUSY;
765+
}
766+
767+
if (!nr_bits) {
768+
mmap_write_unlock(mm);
769+
return -EINVAL;
770+
} else if (nr_bits <= LAM_U57_BITS) {
771+
mm->context.lam_cr3_mask = X86_CR3_LAM_U57;
772+
mm->context.untag_mask = ~GENMASK(62, 57);
773+
} else {
774+
mmap_write_unlock(mm);
775+
return -EINVAL;
776+
}
777+
778+
write_cr3(__read_cr3() | mm->context.lam_cr3_mask);
779+
set_tlbstate_lam_mode(mm);
780+
set_bit(MM_CONTEXT_LOCK_LAM, &mm->context.flags);
781+
782+
mmap_write_unlock(mm);
783+
784+
return 0;
785+
}
786+
#endif
787+
746788
long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2)
747789
{
748790
int ret = 0;
@@ -830,7 +872,18 @@ long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2)
830872
case ARCH_MAP_VDSO_64:
831873
return prctl_map_vdso(&vdso_image_64, arg2);
832874
#endif
833-
875+
#ifdef CONFIG_ADDRESS_MASKING
876+
case ARCH_GET_UNTAG_MASK:
877+
return put_user(task->mm->context.untag_mask,
878+
(unsigned long __user *)arg2);
879+
case ARCH_ENABLE_TAGGED_ADDR:
880+
return prctl_enable_tagged_addr(task->mm, arg2);
881+
case ARCH_GET_MAX_TAG_BITS:
882+
if (!cpu_feature_enabled(X86_FEATURE_LAM))
883+
return put_user(0, (unsigned long __user *)arg2);
884+
else
885+
return put_user(LAM_U57_BITS, (unsigned long __user *)arg2);
886+
#endif
834887
default:
835888
ret = -EINVAL;
836889
break;

0 commit comments

Comments
 (0)