When a kernel thread performs memory access on behalf of a process (like in async I/O, io_uring, etc.) it has to respect tagging setup of the process as user addresses can include tags. Normally, LAM setup is per-thread and recorded in thread flags, but for this use case we also track LAM setup per-mm. mm->context.lam would record LAM that allows the most tag bits among the threads of the mm. The info used by switch_mm_irqs_off() to construct CR3 if the task is kernel thread. Thread flags of the kernel thread get updated according to mm->context.lam. It allows untagged_addr() to work correctly. Signed-off-by: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx> --- arch/x86/include/asm/mmu.h | 1 + arch/x86/mm/tlb.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h index 9257667d13c5..fb05d6a11538 100644 --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h @@ -35,6 +35,7 @@ typedef struct { #ifdef CONFIG_X86_64 /* True if mm supports a task running in 32 bit compatibility mode. */ unsigned short ia32_compat; + u8 lam; #endif struct mutex lock; diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 138d4748aa97..1f9749da12e4 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -176,6 +176,34 @@ static u8 gen_lam(struct task_struct *tsk, struct mm_struct *mm) if (!tsk) return LAM_NONE; + if (tsk->flags & PF_KTHREAD) { + /* + * For kernel thread use the most permissive LAM + * used by the mm. It's required to handle kernel thread + * memory accesses on behalf of a process. + * + * Adjust thread flags accodringly, so untagged_addr() would + * work correctly. + */ + switch (mm->context.lam) { + case LAM_NONE: + clear_thread_flag(TIF_LAM_U48); + clear_thread_flag(TIF_LAM_U57); + return LAM_NONE; + case LAM_U57: + clear_thread_flag(TIF_LAM_U48); + set_thread_flag(TIF_LAM_U57); + return LAM_U57; + case LAM_U48: + set_thread_flag(TIF_LAM_U48); + clear_thread_flag(TIF_LAM_U57); + return LAM_U48; + default: + WARN_ON_ONCE(1); + return LAM_NONE; + } + } + if (test_ti_thread_flag(ti, TIF_LAM_U57)) return LAM_U57; if (test_ti_thread_flag(ti, TIF_LAM_U48)) -- 2.26.2