Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758831AbbGHTZB (ORCPT ); Wed, 8 Jul 2015 15:25:01 -0400 Received: from mail.kernel.org ([198.145.29.136]:48121 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758432AbbGHTYV (ORCPT ); Wed, 8 Jul 2015 15:24:21 -0400 From: Andy Lutomirski To: x86@kernel.org, linux-kernel@vger.kernel.org Cc: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Weisbecker?= , Rik van Riel , Oleg Nesterov , Denys Vlasenko , Borislav Petkov , Kees Cook , Brian Gerst , Linus Torvalds , Andy Lutomirski Subject: [RFC/PATCH 5/7] x86/vm86: Teach handle_vm86_trap to return to 32bit mode directly Date: Wed, 8 Jul 2015 12:24:02 -0700 Message-Id: X-Mailer: git-send-email 2.4.3 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3747 Lines: 112 The TIF_NOTIFY_RESUME hack it was using was buggy and unsupportable. vm86 mode was completely broken under ptrace, for example, because we'd never make it to v8086 mode. This code is still a huge, scary mess, but at least it's no longer tangled with the exit-to-userspace loop. Signed-off-by: Andy Lutomirski --- arch/x86/entry/entry_32.S | 17 ----------------- arch/x86/kernel/traps.c | 12 ++++++++++++ arch/x86/kernel/vm86_32.c | 8 ++------ 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 66ff9c4055d7..3afd201bce55 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -481,29 +481,12 @@ work_resched: work_notifysig: # deal with pending signals and # notify-resume requests -#ifdef CONFIG_VM86 - testl $X86_EFLAGS_VM, PT_EFLAGS(%esp) - movl %esp, %eax - jnz work_notifysig_v86 # special case for v86 -1: -#else movl %esp, %eax -#endif TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) xorl %edx, %edx call do_notify_resume jmp resume_userspace - -#ifdef CONFIG_VM86 - ALIGN -work_notifysig_v86: - pushl %ecx # save ti_flags for do_notify_resume - call save_v86_state # %eax contains pt_regs pointer - popl %ecx - movl %eax, %esp - jmp 1b -#endif END(work_pending) # perform syscall exit tracing diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 8e65d8a9b8db..f86172d4f5db 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -190,6 +190,13 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, * On nmi (interrupt 2), do_trap should not be called. */ if (trapnr < X86_TRAP_UD) { + /* + * handle_vm86_trap may not return. If that + * happens, then there is no debug stack counter + * (it's a 32-bit kernel) and handle_vm86_trap + * will clear the preempt counter. + */ + if (!handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr)) return 0; @@ -650,6 +657,11 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) preempt_conditional_sti(regs); if (v8086_mode(regs)) { + /* + * handle_vm86_trap may not return. If that happens, then + * there is no debug stack counter (it's a 32-bit kernel) + * and handle_vm86_trap will clear the preempt counter. + */ handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, X86_TRAP_DB); preempt_conditional_cli(regs); diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index fc9db6ef2a95..c526ee34c22d 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -351,6 +351,7 @@ static inline void return_to_32bit(struct kernel_vm86_regs *regs16, int retval) { struct pt_regs *regs32; + preempt_count_set(0); regs32 = save_v86_state(regs16); regs32->ax = retval; __asm__ __volatile__("movl %0,%%esp\n\t" @@ -549,12 +550,7 @@ int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int trapno) { if (VMPI.is_vm86pus) { if ((trapno == 3) || (trapno == 1)) { - KVM86->regs32->ax = VM86_TRAP + (trapno << 8); - /* setting this flag forces the code in entry_32.S to - the path where we call save_v86_state() and change - the stack pointer to KVM86->regs32 */ - set_thread_flag(TIF_NOTIFY_RESUME); - return 0; + return_to_32bit(regs, VM86_TRAP + (trapno << 8)); } do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs)); return 0; -- 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/