#include <linux/ptrace.h>
 #include <linux/audit.h>
 #include <linux/stddef.h>
+#include <linux/slab.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
 /*
  * virtual flags (16 and 32-bit versions)
  */
-#define VFLAGS (*(unsigned short *)&(current->thread.v86flags))
-#define VEFLAGS        (current->thread.v86flags)
+#define VFLAGS (*(unsigned short *)&(current->thread.vm86->v86flags))
+#define VEFLAGS        (current->thread.vm86->v86flags)
 
 #define set_flags(X, new, mask) \
 ((X) = ((X) & ~(mask)) | ((new) & (mask)))
        struct pt_regs *ret;
        struct task_struct *tsk = current;
        struct vm86plus_struct __user *user;
+       struct vm86 *vm86 = current->thread.vm86;
        long err = 0;
 
        /*
         */
        local_irq_enable();
 
-       if (!tsk->thread.vm86_info) {
+       if (!vm86 || !vm86->vm86_info) {
                pr_alert("no vm86_info: BAD\n");
                do_exit(SIGSEGV);
        }
-       set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | tsk->thread.v86mask);
-       user = tsk->thread.vm86_info;
+       set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | vm86->v86mask);
+       user = vm86->vm86_info;
 
        if (!access_ok(VERIFY_WRITE, user, VMPI.is_vm86pus ?
                       sizeof(struct vm86plus_struct) :
                put_user_ex(regs->fs, &user->regs.fs);
                put_user_ex(regs->gs, &user->regs.gs);
 
-               put_user_ex(tsk->thread.screen_bitmap, &user->screen_bitmap);
+               put_user_ex(vm86->screen_bitmap, &user->screen_bitmap);
        } put_user_catch(err);
        if (err) {
                pr_alert("could not access userspace vm86_info\n");
        }
 
        tss = &per_cpu(cpu_tss, get_cpu());
-       tsk->thread.sp0 = tsk->thread.saved_sp0;
+       tsk->thread.sp0 = vm86->saved_sp0;
        tsk->thread.sysenter_cs = __KERNEL_CS;
        load_sp0(tss, &tsk->thread);
-       tsk->thread.saved_sp0 = 0;
+       vm86->saved_sp0 = 0;
        put_cpu();
 
        ret = KVM86->regs32;
 {
        struct tss_struct *tss;
        struct task_struct *tsk = current;
+       struct vm86 *vm86 = tsk->thread.vm86;
        unsigned long err = 0;
 
-       if (tsk->thread.saved_sp0)
+       if (!vm86) {
+               if (!(vm86 = kzalloc(sizeof(*vm86), GFP_KERNEL)))
+                       return -ENOMEM;
+               tsk->thread.vm86 = vm86;
+       }
+       if (vm86->saved_sp0)
                return -EPERM;
 
        if (!access_ok(VERIFY_READ, v86, plus ?
        }
 
        info->regs32 = current_pt_regs();
-       tsk->thread.vm86_info = v86;
+       vm86->vm86_info = v86;
 
 /*
  * The flags register is also special: we cannot trust that the user
 
        switch (info->cpu_type) {
        case CPU_286:
-               tsk->thread.v86mask = 0;
+               vm86->v86mask = 0;
                break;
        case CPU_386:
-               tsk->thread.v86mask = X86_EFLAGS_NT | X86_EFLAGS_IOPL;
+               vm86->v86mask = X86_EFLAGS_NT | X86_EFLAGS_IOPL;
                break;
        case CPU_486:
-               tsk->thread.v86mask = X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
+               vm86->v86mask = X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
                break;
        default:
-               tsk->thread.v86mask = X86_EFLAGS_ID | X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
+               vm86->v86mask = X86_EFLAGS_ID | X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
                break;
        }
 
  * Save old state, set default return value (%ax) to 0 (VM86_SIGNAL)
  */
        info->regs32->ax = VM86_SIGNAL;
-       tsk->thread.saved_sp0 = tsk->thread.sp0;
+       vm86->saved_sp0 = tsk->thread.sp0;
        lazy_save_gs(info->regs32->gs);
 
        tss = &per_cpu(cpu_tss, get_cpu());
        load_sp0(tss, &tsk->thread);
        put_cpu();
 
-       tsk->thread.screen_bitmap = info->screen_bitmap;
+       vm86->screen_bitmap = info->screen_bitmap;
        if (info->flags & VM86_SCREEN_BITMAP)
                mark_screen_rdonly(tsk->mm);
 
 
 static inline void set_vflags_long(unsigned long flags, struct kernel_vm86_regs *regs)
 {
-       set_flags(VEFLAGS, flags, current->thread.v86mask);
+       set_flags(VEFLAGS, flags, current->thread.vm86->v86mask);
        set_flags(regs->pt.flags, flags, SAFE_MASK);
        if (flags & X86_EFLAGS_IF)
                set_IF(regs);
 
 static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs *regs)
 {
-       set_flags(VFLAGS, flags, current->thread.v86mask);
+       set_flags(VFLAGS, flags, current->thread.vm86->v86mask);
        set_flags(regs->pt.flags, flags, SAFE_MASK);
        if (flags & X86_EFLAGS_IF)
                set_IF(regs);
        if (VEFLAGS & X86_EFLAGS_VIF)
                flags |= X86_EFLAGS_IF;
        flags |= X86_EFLAGS_IOPL;
-       return flags | (VEFLAGS & current->thread.v86mask);
+       return flags | (VEFLAGS & current->thread.vm86->v86mask);
 }
 
 static inline int is_revectored(int nr, struct revectored_struct *bitmap)