x86: vm86 cleanups
Subsystems (3)
PATCH v2 1/1 x86: vm86 cleanups
The goal of this set of patches is to change vm86 support to return to userspace with the normal exit paths instead of leaving data on the kernel stack and jumping directly into the exit asm routines. This fixes issues like ptrace and syscall auditing not working with vm86, and makes possible cleanups in the syscall exit work code.
Changes from v1:
- Added first two patches
- Changed userspace access to copy each field explicitly instead of relying on the same order of members in the structure.
In-Reply-To:
PATCH 1/7 x86/vm86: Clean up saved_fs/gs
There is no need to save FS and non-lazy GS outside the 32-bit regs. Lazy GS still needs to be saved because it wasn't saved on syscall entry.
--- arch/x86/include/asm/processor.h | 3 ++- arch/x86/kernel/vm86_32.c | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-)
arch/x86/include/asm/processor.h +2 -1
@@ -410,9 +410,10 @@ struct thread_struct {unsigned long v86flags;unsigned long v86mask;unsigned long saved_sp0; -unsigned int saved_fs; +#ifdef CONFIG_X86_32_LAZY_GS unsigned int saved_gs;#endif +#endif /* IO permissions: */ unsigned long *io_bitmap_ptr;unsigned long iopl;
arch/x86/kernel/vm86_32.c +2 -4
@@ -159,8 +159,7 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs) ret =KVM86 ->regs32; - ret->fs = current->thread.saved_fs; -set_user_gs (ret, current->thread.saved_gs); +lazy_load_gs (current->thread.saved_gs);return ret; }
@@ -315,8 +314,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk*/ 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); +lazy_save_gs (tsk->thread.saved_gs); tss = &per_cpu (cpu_tss,get_cpu ()); tsk->thread.sp0 = (unsigned long ) &info->VM86_TSS_ESP0;
Signature · 1 line
2.4.3
Re: [PATCH 1/7] x86/vm86: Clean up saved_fs/gs
Quoted 2 lines · Brian Gerst
There is no need to save FS and non-lazy GS outside the 32-bit regs. Lazy GS still needs to be saved because it wasn't saved on syscall entry.
I think I'm missing something. Why can't you just lazy_save_gs into regs32->gs?
--Andy
Re: [PATCH 1/7] x86/vm86: Clean up saved_fs/gs
Quoted 7 lines · Andy Lutomirski
Quoted 2 lines · Brian Gerst
There is no need to save FS and non-lazy GS outside the 32-bit regs. Lazy GS still needs to be saved because it wasn't saved on syscall entry.
I think I'm missing something. Why can't you just
lazy_save_gsintoregs32->gs?--Andy
That is probably a better idea. The gs field exists in pt_regs but is unused in lazy mode. Could also change switch_to() to store GS in pt_regs instead of thread.gs, which would simplify ptrace a bit.
--
Brian Gerst
PATCH 2/7 x86/vm86: Preserve orig_ax
In reply to Brian GerstThere is no legitimate reason for usermode to modify the orig_ax field on entry to vm86 mode, so copy it from the 32-bit regs.
--- arch/x86/kernel/vm86_32.c | 2 ++ 1 file changed, 2 insertions(+)
arch/x86/kernel/vm86_32.c +2 -0
@@ -294,6 +294,8 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk info->regs.pt.flags |= info->regs32->flags & ~SAFE_MASK ; info->regs.pt.flags |=X86_VM_MASK ; + info->regs.pt.orig_ax = info->regs32->orig_ax; +switch (info->cpu_type) {case CPU_286 : tsk->thread.v86mask =0 ;
Signature · 1 line
2.4.3
Re: [PATCH 2/7] x86/vm86: Preserve orig_ax
Quoted 2 lines · Brian Gerst
There is no legitimate reason for usermode to modify the
orig_axfield on entry to vm86 mode, so copy it from the 32-bit regs.
Looks good.
--Andy
PATCH 3/7 x86/vm86: Move userspace accesses to do_sys_vm86()
In reply to Brian GerstMove the userspace accesses down into the common function in preparation for the next set of patches.
--- arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/vm86_32.c | 176 +++++++++++++++++++-------------------- 2 files changed, 89 insertions(+), 89 deletions(-)
arch/x86/include/asm/processor.h +1 -1
@@ -405,7 +405,7 @@ struct thread_struct {unsigned long error_code;#ifdef CONFIG_X86_32 /* Virtual 86 mode info */ -struct vm86_struct __user *vm86_info; +struct vm86plus_struct __user *vm86_info;unsigned long screen_bitmap;unsigned long v86flags;unsigned long v86mask;
arch/x86/kernel/vm86_32.c +88 -88
237 lines not on this page · raw message
Signature · 1 line
2.4.3
Re: [PATCH 3/7] x86/vm86: Move userspace accesses to do_sys_vm86()
Quoted 2 lines · Brian Gerst
Move the userspace accesses down into the common function in preparation for the next set of patches.
Nice!
Could you improve the changelog a bit? You're really changing the way it works (in a good way).
arch/x86/kernel/vm86_32.c struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs) · line 114
Quoted 7 lines
arch/x86/kernel/vm86_32.c +3
-4-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); -if (tmp) { +set_flags (regs->pt.flags,VEFLAGS ,X86_EFLAGS_VIF | tsk->thread.v86mask); + user = tsk->thread.vm86_info; + put_user_try {
I think that put_user_try/put_user_ex requires access_ok.
arch/x86/kernel/vm86_32.c SYSCALL_DEFINE2(vm86, unsigned long, cmd, unsigned long, arg) · line 244
Quoted 2 lines
arch/x86/kernel/vm86_32.c +2
-0+ get_user_try { +unsigned short seg;
This also needs access_ok, I think.
--Andy
Re: [PATCH 3/7] x86/vm86: Move userspace accesses to do_sys_vm86()
Quoted 18 lines · Andy Lutomirski
Quoted 2 lines · Brian Gerst
Move the userspace accesses down into the common function in preparation for the next set of patches.
Nice!
Could you improve the changelog a bit? You're really changing the way it works (in a good way).
arch/x86/kernel/vm86_32.c struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs) · line 114
Quoted 7 lines
arch/x86/kernel/vm86_32.c +3
-4-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); -if (tmp) { +set_flags (regs->pt.flags,VEFLAGS ,X86_EFLAGS_VIF | tsk->thread.v86mask); + user = tsk->thread.vm86_info; + put_user_try {
Quoted 7 lines
I think that put_user_try/put_user_ex requires
access_ok.arch/x86/kernel/vm86_32.c SYSCALL_DEFINE2(vm86, unsigned long, cmd, unsigned long, arg) · line 244
Quoted 2 lines
arch/x86/kernel/vm86_32.c +2
-0+ get_user_try { +unsigned short seg;This also needs
access_ok, I think.
Good catch. I modeled this off restore_sigcontext(), but the access_ok() is actually in the caller.
--
Brian Gerst
PATCH 4/7 x86/vm86: Move vm86 fields out of thread_struct
In reply to Brian GerstAllocate a separate structure for the vm86 fields.
--- arch/x86/include/asm/processor.h | 12 ++-------- arch/x86/include/asm/vm86.h | 11 +++++++++ arch/x86/kernel/process.c | 7 ++++++ arch/x86/kernel/vm86_32.c | 51 +++++++++++++++++++++++----------------- arch/x86/mm/fault.c | 4 ++-- 5 files changed, 52 insertions(+), 33 deletions(-)
arch/x86/include/asm/processor.h +2 -10
@@ -403,16 +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 vm86plus_struct __user *vm86_info; -unsigned long screen_bitmap; -unsigned long v86flags; -unsigned long v86mask; -unsigned long saved_sp0; -#ifdef CONFIG_X86_32_LAZY_GS -unsigned int saved_gs; -#endif +struct kernel_vm86_info *vm86;#endif /* IO permissions: */ unsigned long *io_bitmap_ptr;
@@ -717,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, \ }
arch/x86/include/asm/vm86.h +11 -0
@@ -58,6 +58,17 @@ struct kernel_vm86_struct {*/ }; +struct kernel_vm86_info { +struct vm86plus_struct __user *vm86_info; +unsigned long screen_bitmap; +unsigned long v86flags; +unsigned long v86mask; +unsigned long saved_sp0; +#ifdef CONFIG_X86_32_LAZY_GS +unsigned int saved_gs; +#endif +}; +#ifdef CONFIG_VM86 void handle_vm86_fault (struct kernel_vm86_regs *,long );
arch/x86/kernel/process.c +7 -0
@@ -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); }
arch/x86/kernel/vm86_32.c +30 -21
152 lines not on this page · raw message
arch/x86/mm/fault.c +2 -2
@@ -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)
Signature · 1 line
2.4.3
Re: [PATCH 4/7] x86/vm86: Move vm86 fields out of thread_struct
arch/x86/mm/fault.c check_v8086_mode(struct pt_regs *regs, unsigned long address, · line 320
Quoted 13 lines · Brian Gerst
Allocate a separate structure for the vm86 fields.
arch/x86/mm/fault.c +1
-1@@ -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 ;
What's this for? Shouldn't that "if (!v8086_mode(regs) || WARN_ON(!tsk->thread.vm86))"?
--Andy
PATCH 5/7 x86/vm86: Move fields from kernel_vm86_struct
In reply to Brian GerstMove the non-regs fields to the off-stack data.
--- arch/x86/include/asm/vm86.h | 16 ++++++++-------- arch/x86/kernel/vm86_32.c | 40 +++++++++++++++++++++------------------- 2 files changed, 29 insertions(+), 27 deletions(-)
arch/x86/include/asm/vm86.h +8 -8
@@ -38,13 +38,7 @@ struct kernel_vm86_struct {* Therefore, pt_regs in fact points to a complete 'kernel_vm86_struct' * in kernelspace, hence we need not reget the data from userspace. */ -#define VM86_TSS_ESP0 flags -unsigned long flags; -unsigned long screen_bitmap; -unsigned long cpu_type; -struct revectored_struct int_revectored; -struct revectored_struct int21_revectored; -struct vm86plus_info_struct vm86plus; +#define VM86_TSS_ESP0 regs32struct pt_regs *regs32;/* here we save the pointer to the old regs */ /* * The below is not part of the structure, but the stack layout continues
@@ -60,13 +54,19 @@ struct kernel_vm86_struct {struct kernel_vm86_info {struct vm86plus_struct __user *vm86_info; -unsigned long screen_bitmap;unsigned long v86flags;unsigned long v86mask;unsigned long saved_sp0;#ifdef CONFIG_X86_32_LAZY_GS unsigned int saved_gs;#endif + +unsigned long flags; +unsigned long screen_bitmap; +unsigned long cpu_type; +struct revectored_struct int_revectored; +struct revectored_struct int21_revectored; +struct vm86plus_info_struct vm86plus; };#ifdef CONFIG_VM86
arch/x86/kernel/vm86_32.c +21 -19
@@ -68,7 +68,6 @@#define KVM86 ((struct kernel_vm86_struct *)regs) -#define VMPI KVM86->vm86plus/*
@@ -270,25 +269,27 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus,get_user_ex (info->regs.fs, &v86->regs.fs);get_user_ex (info->regs.gs, &v86->regs.gs); -get_user_ex (info->flags, &v86->flags); -get_user_ex (info->screen_bitmap, &v86->screen_bitmap); -get_user_ex (info->cpu_type, &v86->cpu_type); +get_user_ex (vm86->flags, &v86->flags); +get_user_ex (vm86->screen_bitmap, &v86->screen_bitmap); +get_user_ex (vm86->cpu_type, &v86->cpu_type); }get_user_catch (err);if (err)return err; -if (copy_from_user (&info->int_revectored, &v86->int_revectored, +if (copy_from_user (&vm86->int_revectored, &v86->int_revectored,sizeof (struct revectored_struct )))return -EFAULT ; -if (copy_from_user (&info->int21_revectored, &v86->int21_revectored, +if (copy_from_user (&vm86->int21_revectored, &v86->int21_revectored,sizeof (struct revectored_struct )))return -EFAULT ;if (plus) { -if (copy_from_user (&info->vm86plus, &v86->vm86plus, +if (copy_from_user (&vm86->vm86plus, &v86->vm86plus,sizeof (struct vm86plus_info_struct )))return -EFAULT ; - info->vm86plus.is_vm86pus =1 ; - } + vm86->vm86plus.is_vm86pus =1 ; + }else +memset (&vm86->vm86plus,0 , +sizeof (struct vm86plus_info_struct )); info->regs32 =current_pt_regs (); vm86->vm86_info = v86;
@@ -305,7 +306,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus, info->regs.pt.orig_ax = info->regs32->orig_ax; -switch (info->cpu_type) { +switch (vm86->cpu_type) {case CPU_286 : vm86->v86mask =0 ;break ;
@@ -334,8 +335,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus,load_sp0 (tss, &tsk->thread);put_cpu (); - vm86->screen_bitmap = info->screen_bitmap; -if (info->flags &VM86_SCREEN_BITMAP ) +if (vm86->flags &VM86_SCREEN_BITMAP )mark_screen_rdonly (tsk->mm);/*call __audit_syscall_exit since we do not exit via the normal paths */
@@ -527,12 +527,13 @@ static void do_int(struct kernel_vm86_regs *regs, int i, {unsigned long __user *intr_ptr;unsigned long segoffs; +struct kernel_vm86_info *vm86 = current->thread.vm86;if (regs->pt.cs ==BIOSSEG ) goto cannot_handle; -if (is_revectored (i, &KVM86 ->int_revectored)) +if (is_revectored (i, &vm86->int_revectored)) goto cannot_handle; -if (i ==0x21 &&is_revectored (AH (regs), &KVM86 ->int21_revectored)) +if (i ==0x21 &&is_revectored (AH (regs), &vm86->int21_revectored)) goto cannot_handle; intr_ptr = (unsigned long __user *) (i <<2 );if (get_user (segoffs, intr_ptr))
@@ -556,7 +557,7 @@ cannot_handle:int handle_vm86_trap (struct kernel_vm86_regs *regs,long error_code,int trapno) { -if (VMPI .is_vm86pus) { +if (current->thread.vm86->vm86plus.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
@@ -583,12 +584,13 @@ void handle_vm86_fault(struct kernel_vm86_regs *regs, long error_code)unsigned char __user *ssp;unsigned short ip, sp, orig_flags;int data32, pref_done; +struct vm86plus_info_struct *vmpi = ¤t->thread.vm86->vm86plus;#define CHECK_IF_IN_TRAP \ - if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \ + if (vmpi->vm86dbg_active && vmpi->vm86dbg_TFpendig) \ newflags |= X86_EFLAGS_TF#define VM86_FAULT_RETURN do { \ - if (VMPI.force_return_for_pic && (VEFLAGS & (X86_EFLAGS_IF | X86_EFLAGS_VIF))) \ + if (vmpi->force_return_for_pic && (VEFLAGS & (X86_EFLAGS_IF | X86_EFLAGS_VIF))) \ return_to_32bit(regs, VM86_PICRETURN); \ if (orig_flags & X86_EFLAGS_TF) \ handle_vm86_trap(regs, 0, 1); \
@@ -658,8 +660,8 @@ void handle_vm86_fault(struct kernel_vm86_regs *regs, long error_code)case 0xcd : {int intno =popb (csp, ip, simulate_sigsegv);IP (regs) = ip; -if (VMPI .vm86dbg_active) { -if ((1 << (intno &7 )) &VMPI .vm86dbg_intxxtab[intno >>3 ]) +if (vmpi->vm86dbg_active) { +if ((1 << (intno &7 )) & vmpi->vm86dbg_intxxtab[intno >>3 ])return_to_32bit (regs, VM86_INTx + (intno <<8 )); }do_int (regs, intno, ssp, sp);
Signature · 1 line
2.4.3
Re: [PATCH 5/7] x86/vm86: Move fields from kernel_vm86_struct
Quoted 1 line · Brian Gerst
Move the non-regs fields to the off-stack data.
Quoted 2 lines
Signed-off-by Brian Gerst <[email protected]>
--Andy
PATCH 6/7 x86/vm86: Eliminate kernel_vm86_struct
In reply to Brian GerstNow there is no vm86-specific data left on the kernel stack while in userspace, except for the 32-bit regs.
--- arch/x86/include/asm/vm86.h | 25 +------------ arch/x86/kernel/vm86_32.c | 91 +++++++++++++++++++-------------------------- 2 files changed, 40 insertions(+), 76 deletions(-)
arch/x86/include/asm/vm86.h +1 -24
@@ -28,32 +28,9 @@ struct kernel_vm86_regs {unsigned short gs, __gsh; }; -struct kernel_vm86_struct { -struct kernel_vm86_regs regs; -/* -* the below part remains on the kernel stack while we are in VM86 mode. -* 'tss.esp0' then contains the address of VM86_TSS_ESP0 below, and when we -* get forced back from VM86, the CPU and "SAVE_ALL" will restore the above -* 'struct kernel_vm86_regs' with the then actual values. -* Therefore, pt_regs in fact points to a complete 'kernel_vm86_struct' -* in kernelspace, hence we need not reget the data from userspace. -*/ -#define VM86_TSS_ESP0 regs32 -struct pt_regs *regs32;/* here we save the pointer to the old regs */ -/* -* The below is not part of the structure, but the stack layout continues -* this way. In front of 'return-eip' may be some data, depending on -* compilation, so we don't rely on this and save the pointer to 'oldregs' -* in 'regs32' above. -* However, with GCC-2.7.2 and the current CFLAGS you see exactly this: - -long return-eip; from call to vm86() -struct pt_regs oldregs; user space registers as saved by syscall -*/ -}; -struct kernel_vm86_info {struct vm86plus_struct __user *vm86_info; +struct pt_regs *regs32;unsigned long v86flags;unsigned long v86mask;unsigned long saved_sp0;
arch/x86/kernel/vm86_32.c +39 -52
178 lines not on this page · raw message
Signature · 1 line
2.4.3
Re: [PATCH 6/7] x86/vm86: Eliminate kernel_vm86_struct
Quoted 3 lines · Brian Gerst
Now there is no vm86-specific data left on the kernel stack while in userspace, except for the 32-bit regs.
Quoted 2 lines
Signed-off-by Brian Gerst <[email protected]>---
PATCH 7/7 x86/vm86: Use the normal pt_regs area for vm86
In reply to Brian GerstChange to use the normal pt_regs area to enter and exit vm86 mode. This is done by increasing the padding at the top of the stack to make room for the extra vm86 segment slots in the IRET frame. It then saves the 32-bit regs in the off-stack vm86 data, and copies in the vm86 regs. Exiting back to 32-bit mode does the reverse. This allows removing the hacks to jump directly into the exit asm code due to having to change the stack pointer. Returning normally from the vm86 syscall and the exception handlers allows things like ptrace and auditing to work properly.
--- arch/x86/entry/entry_32.S | 24 +-------- arch/x86/include/asm/thread_info.h | 11 ++-- arch/x86/include/asm/vm86.h | 6 ++- arch/x86/kernel/signal.c | 3 ++ arch/x86/kernel/vm86_32.c | 106 +++++++++++++++---------------------- 5 files changed, 58 insertions(+), 92 deletions(-)
arch/x86/entry/entry_32.S +1 -23
@@ -525,34 +525,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 # returning to kernel-space or - # vm86-space -1: -#else - movl %esp, %eax -#endif TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) - movb PT_CS(%esp), %bl - andb $SEGMENT_RPL_MASK, %bl - cmpb $USER_RPL, %bl - jb resume_kernel + movl %esp, %eax 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
arch/x86/include/asm/thread_info.h +7 -4
@@ -27,14 +27,17 @@* Without this offset, that can result in a page fault. (We are * careful that, in this case, the value we read doesn't matter.) * -* In vm86 mode, the hardware frame is much longer still, but we neither -* access the extra members from NMI context, nor do we write such a -* frame at sp0 at all. +* In vm86 mode, the hardware frame is much longer still, so add 16 +* bytes to make room for the real-mode segments. * * x86_64 has a fixed-length stack frame. */ #ifdef CONFIG_X86_32 -# define TOP_OF_KERNEL_STACK_PADDING 8 +# ifdef CONFIG_VM86 +# define TOP_OF_KERNEL_STACK_PADDING 16 +# else +# define TOP_OF_KERNEL_STACK_PADDING 8 +# endif #else # define TOP_OF_KERNEL_STACK_PADDING 0#endif
arch/x86/include/asm/vm86.h +4 -2
@@ -30,7 +30,7 @@ struct kernel_vm86_regs {struct kernel_vm86_info {struct vm86plus_struct __user *vm86_info; -struct pt_regs *regs32; +struct pt_regs regs32;unsigned long v86flags;unsigned long v86mask;unsigned long saved_sp0;
@@ -50,7 +50,7 @@ struct kernel_vm86_info {void handle_vm86_fault (struct kernel_vm86_regs *,long );int handle_vm86_trap (struct kernel_vm86_regs *,long ,int ); -struct pt_regs *save_v86_state (struct kernel_vm86_regs *); +void save_v86_state (struct kernel_vm86_regs *,int );struct task_struct ;void release_vm86_irqs (struct task_struct *);
@@ -65,6 +65,8 @@ static inline int handle_vm86_trap(struct kernel_vm86_regs *a, long b, int c)return 0 ; } +static inline void save_v86_state (struct kernel_vm86_regs *,int ) { } +#endif /* CONFIG_VM86 */ #endif /* _ASM_X86_VM86_H */
arch/x86/kernel/signal.c +3 -0
@@ -635,6 +635,9 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)bool stepping, failed;struct fpu *fpu = ¤t->thread.fpu; +if (v8086_mode (regs)) +save_v86_state ((struct kernel_vm86_regs *) regs,VM86_SIGNAL ); +/* Are we from a system call? */ if (syscall_get_nr (current, regs) >=0 ) {/* If so, check system call restarting.. */
arch/x86/kernel/vm86_32.c +43 -63
235 lines not on this page · raw message
Signature · 1 line
2.4.3