Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753148AbbGKGLV (ORCPT ); Sat, 11 Jul 2015 02:11:21 -0400 Received: from mail-yk0-f178.google.com ([209.85.160.178]:33773 "EHLO mail-yk0-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753149AbbGKGLR (ORCPT ); Sat, 11 Jul 2015 02:11:17 -0400 From: Brian Gerst To: x86@kernel.org, linux-kernel@vger.kernel.org Cc: Ingo Molnar , "H. Peter Anvin" , Denys Vlasenko , Andy Lutomirski , Linus Torvalds Subject: [PATCH 2/5] x86/vm86: Move vm86 fields out of thread_struct Date: Sat, 11 Jul 2015 01:09:17 -0400 Message-Id: <1436591360-16210-3-git-send-email-brgerst@gmail.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1436591360-16210-1-git-send-email-brgerst@gmail.com> References: <1436591360-16210-1-git-send-email-brgerst@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8852 Lines: 272 Allocate a separate structure for the vm86 fields. Signed-off-by: Brian Gerst --- arch/x86/include/asm/processor.h | 11 ++------ arch/x86/include/asm/vm86.h | 10 ++++++++ arch/x86/kernel/process.c | 7 +++++ arch/x86/kernel/vm86_32.c | 55 +++++++++++++++++++++++----------------- arch/x86/mm/fault.c | 4 +-- 5 files changed, 53 insertions(+), 34 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 43e6519..8085463 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -403,15 +403,9 @@ struct thread_struct { unsigned long cr2; unsigned long trap_nr; unsigned long error_code; -#ifdef CONFIG_X86_32 +#ifdef CONFIG_VM86 /* Virtual 86 mode info */ - struct vm86_struct __user *vm86_info; - unsigned long screen_bitmap; - unsigned long v86flags; - unsigned long v86mask; - unsigned long saved_sp0; - unsigned int saved_fs; - unsigned int saved_gs; + struct kernel_vm86_info *vm86; #endif /* IO permissions: */ unsigned long *io_bitmap_ptr; @@ -716,7 +710,6 @@ static inline void spin_lock_prefetch(const void *x) #define INIT_THREAD { \ .sp0 = TOP_OF_INIT_STACK, \ - .vm86_info = NULL, \ .sysenter_cs = __KERNEL_CS, \ .io_bitmap_ptr = NULL, \ } diff --git a/arch/x86/include/asm/vm86.h b/arch/x86/include/asm/vm86.h index 1d8de3f..88f14e3 100644 --- a/arch/x86/include/asm/vm86.h +++ b/arch/x86/include/asm/vm86.h @@ -58,6 +58,16 @@ struct kernel_vm86_struct { */ }; +struct kernel_vm86_info { + struct vm86_struct __user *vm86_info; + unsigned long screen_bitmap; + unsigned long v86flags; + unsigned long v86mask; + unsigned long saved_sp0; + unsigned int saved_fs; + unsigned int saved_gs; +}; + #ifdef CONFIG_VM86 void handle_vm86_fault(struct kernel_vm86_regs *, long); diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 9cad694..5dcd037 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -110,6 +110,13 @@ void exit_thread(void) kfree(bp); } +#ifdef CONFIG_VM86 + if (t->vm86) { + kfree(t->vm86); + t->vm86 = NULL; + } +#endif + fpu__drop(fpu); } diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 71a8b0a..8b29c9b 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -81,8 +82,8 @@ /* * 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))) @@ -130,6 +131,7 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs) struct tss_struct *tss; struct pt_regs *ret; unsigned long tmp; + struct kernel_vm86_info *vm86 = current->thread.vm86; /* * This gets called from entry.S with interrupts disabled, but @@ -138,29 +140,29 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs) */ local_irq_enable(); - if (!current->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 | current->thread.v86mask); - tmp = copy_vm86_regs_to_user(¤t->thread.vm86_info->regs, regs); - tmp += put_user(current->thread.screen_bitmap, ¤t->thread.vm86_info->screen_bitmap); + set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | vm86->v86mask); + tmp = copy_vm86_regs_to_user(&vm86->vm86_info->regs, regs); + tmp += put_user(vm86->screen_bitmap, &vm86->vm86_info->screen_bitmap); if (tmp) { pr_alert("could not access userspace vm86_info\n"); do_exit(SIGSEGV); } tss = &per_cpu(cpu_tss, get_cpu()); - current->thread.sp0 = current->thread.saved_sp0; + current->thread.sp0 = vm86->saved_sp0; current->thread.sysenter_cs = __KERNEL_CS; load_sp0(tss, ¤t->thread); - current->thread.saved_sp0 = 0; + vm86->saved_sp0 = 0; put_cpu(); ret = KVM86->regs32; - ret->fs = current->thread.saved_fs; - set_user_gs(ret, current->thread.saved_gs); + ret->fs = vm86->saved_fs; + set_user_gs(ret, vm86->saved_gs); return ret; } @@ -249,8 +251,15 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus, { struct tss_struct *tss; struct task_struct *tsk = current; + struct kernel_vm86_info *vm86 = tsk->thread.vm86; - 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 (plus) { if (copy_vm86_regs_from_user(&info->regs, &v86->regs, @@ -266,7 +275,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus, memset(&info->vm86plus, 0, sizeof(struct vm86plus_info_struct)); } info->regs32 = current_pt_regs(); - tsk->thread.vm86_info = (struct vm86_struct __user *) v86; + vm86->vm86_info = (struct vm86_struct __user *) v86; /* * make sure the vm86() system call doesn't try to do anything silly @@ -290,16 +299,16 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus, 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; } @@ -307,9 +316,9 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus, * Save old state, set default return value (%ax) to 0 (VM86_SIGNAL) */ info->regs32->ax = VM86_SIGNAL; - tsk->thread.saved_sp0 = tsk->thread.sp0; - tsk->thread.saved_fs = info->regs32->fs; - tsk->thread.saved_gs = get_user_gs(info->regs32); + vm86->saved_sp0 = tsk->thread.sp0; + vm86->saved_fs = info->regs32->fs; + vm86->saved_gs = get_user_gs(info->regs32); tss = &per_cpu(cpu_tss, get_cpu()); tsk->thread.sp0 = (unsigned long) &info->VM86_TSS_ESP0; @@ -318,7 +327,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus, 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); @@ -388,7 +397,7 @@ static inline void clear_AC(struct kernel_vm86_regs *regs) 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); @@ -398,7 +407,7 @@ static inline void set_vflags_long(unsigned long flags, struct kernel_vm86_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); @@ -413,7 +422,7 @@ static inline unsigned long get_vflags(struct kernel_vm86_regs *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) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 81dcebf..5196ac4 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -315,12 +315,12 @@ check_v8086_mode(struct pt_regs *regs, unsigned long address, { unsigned long bit; - if (!v8086_mode(regs)) + if (!v8086_mode(regs) || !tsk->thread.vm86) return; bit = (address - 0xA0000) >> PAGE_SHIFT; if (bit < 32) - tsk->thread.screen_bitmap |= 1 << bit; + tsk->thread.vm86->screen_bitmap |= 1 << bit; } static bool low_pfn(unsigned long pfn) -- 2.4.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/