diff options
author | Aleksey Gorelov <Aleksey_Gorelov@Phoenix.com> | 2006-06-27 05:53:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-27 20:32:38 -0400 |
commit | 4031ff388138b58e5cd472dccce38828bcb8c706 (patch) | |
tree | f2c88fdcdef3ec9880d23ce271f14e95f7aa1cf5 /arch/i386/kernel/entry.S | |
parent | c723e084606ca1c81e91b80b2c0c44bde7bbc4df (diff) |
[PATCH] fix broken vm86 interrupt/signal handling
Commit c3ff8ec31c1249d268cd11390649768a12bec1b9 ("[PATCH] i386: Don't
miss pending signals returning to user mode after signal processing")
meant that vm86 interrupt/signal handling got broken for the case when
vm86 is called from kernel space.
In this scenario, if signal is pending because of vm86 interrupt,
do_notify_resume/do_signal exits immediately due to user_mode() check,
without processing any signals. Thus, resume_userspace handler is spinning
in a tight loop with signal pending and TIF_SIGPENDING is set. Previously
everything worked Ok.
No in-tree usage of vm86() from kernel space exists, but I've heard
about a number of projects out there which use vm86 calls from kernel,
one of them being this, for instance:
http://dev.gentoo.org/~spock/projects/vesafb-tng/
The following patch fixes the issue.
Signed-off-by: Aleksey Gorelov <aleksey_gorelov@phoenix.com>
Cc: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/entry.S')
-rw-r--r-- | arch/i386/kernel/entry.S | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 8713e0248a0b..e8d2630fd19a 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S | |||
@@ -83,6 +83,12 @@ VM_MASK = 0x00020000 | |||
83 | #define resume_kernel restore_nocheck | 83 | #define resume_kernel restore_nocheck |
84 | #endif | 84 | #endif |
85 | 85 | ||
86 | #ifdef CONFIG_VM86 | ||
87 | #define resume_userspace_sig check_userspace | ||
88 | #else | ||
89 | #define resume_userspace_sig resume_userspace | ||
90 | #endif | ||
91 | |||
86 | #define SAVE_ALL \ | 92 | #define SAVE_ALL \ |
87 | cld; \ | 93 | cld; \ |
88 | pushl %es; \ | 94 | pushl %es; \ |
@@ -211,6 +217,7 @@ ret_from_exception: | |||
211 | preempt_stop | 217 | preempt_stop |
212 | ret_from_intr: | 218 | ret_from_intr: |
213 | GET_THREAD_INFO(%ebp) | 219 | GET_THREAD_INFO(%ebp) |
220 | check_userspace: | ||
214 | movl EFLAGS(%esp), %eax # mix EFLAGS and CS | 221 | movl EFLAGS(%esp), %eax # mix EFLAGS and CS |
215 | movb CS(%esp), %al | 222 | movb CS(%esp), %al |
216 | testl $(VM_MASK | 3), %eax | 223 | testl $(VM_MASK | 3), %eax |
@@ -415,7 +422,7 @@ work_notifysig: # deal with pending signals and | |||
415 | # vm86-space | 422 | # vm86-space |
416 | xorl %edx, %edx | 423 | xorl %edx, %edx |
417 | call do_notify_resume | 424 | call do_notify_resume |
418 | jmp resume_userspace | 425 | jmp resume_userspace_sig |
419 | 426 | ||
420 | ALIGN | 427 | ALIGN |
421 | work_notifysig_v86: | 428 | work_notifysig_v86: |
@@ -428,7 +435,7 @@ work_notifysig_v86: | |||
428 | movl %eax, %esp | 435 | movl %eax, %esp |
429 | xorl %edx, %edx | 436 | xorl %edx, %edx |
430 | call do_notify_resume | 437 | call do_notify_resume |
431 | jmp resume_userspace | 438 | jmp resume_userspace_sig |
432 | #endif | 439 | #endif |
433 | 440 | ||
434 | # perform syscall exit tracing | 441 | # perform syscall exit tracing |