#include <linux/rwsem.h>
 #include <linux/mutex.h>
 #include <linux/atomic.h>
+#include <linux/bits.h>
+
+/* Uprobes on this MM assume 32-bit code */
+#define MM_CONTEXT_UPROBE_IA32 BIT(0)
+/* vsyscall page is accessible on this MM */
+#define MM_CONTEXT_HAS_VSYSCALL        BIT(1)
 
 /*
  * x86 has arch-specific MMU state beyond what lives in mm_struct.
 #endif
 
 #ifdef CONFIG_X86_64
-       /* True if mm supports a task running in 32 bit compatibility mode. */
-       unsigned short ia32_compat;
+       unsigned short flags;
 #endif
 
        struct mutex lock;
 
 static inline bool is_64bit_mm(struct mm_struct *mm)
 {
        return  !IS_ENABLED(CONFIG_IA32_EMULATION) ||
-               !(mm->context.ia32_compat == TIF_IA32);
+               !(mm->context.flags & MM_CONTEXT_UPROBE_IA32);
 }
 #else
 static inline bool is_64bit_mm(struct mm_struct *mm)
 
        /* Pretend that this comes from a 64bit execve */
        task_pt_regs(current)->orig_ax = __NR_execve;
        current_thread_info()->status &= ~TS_COMPAT;
-
-       /* Ensure the corresponding mm is not marked. */
        if (current->mm)
-               current->mm->context.ia32_compat = 0;
+               current->mm->context.flags = MM_CONTEXT_HAS_VSYSCALL;
 
        /* TBD: overwrites user setup. Should have two bits.
           But 64bit processes have always behaved this way,
        clear_thread_flag(TIF_IA32);
        set_thread_flag(TIF_X32);
        if (current->mm)
-               current->mm->context.ia32_compat = TIF_X32;
+               current->mm->context.flags = 0;
+
        current->personality &= ~READ_IMPLIES_EXEC;
        /*
         * in_32bit_syscall() uses the presence of the x32 syscall bit
 #ifdef CONFIG_IA32_EMULATION
        set_thread_flag(TIF_IA32);
        clear_thread_flag(TIF_X32);
-       if (current->mm)
-               current->mm->context.ia32_compat = TIF_IA32;
+       if (current->mm) {
+               /*
+                * uprobes applied to this MM need to know this and
+                * cannot use user_64bit_mode() at that time.
+                */
+               current->mm->context.flags = MM_CONTEXT_UPROBE_IA32;
+       }
+
        current->personality |= force_personality32;
        /* Prepare the first "return" to user space */
        task_pt_regs(current)->orig_ax = __NR_ia32_execve;