lkml.org 
[lkml]   [2003]   [Jan]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] Cleanup vm86 fault handling
This patch makes handle_vm86_trap() accept or reject traps, instead of 
handling it in do_trap(). This enables some extra cleanups with the
general protection fault and cache flush fault.

--
Brian Gerst
diff -urN linux-a1/arch/i386/kernel/traps.c linux-b1/arch/i386/kernel/traps.c
--- linux-a1/arch/i386/kernel/traps.c Sat Jan 11 03:29:47 2003
+++ linux-b1/arch/i386/kernel/traps.c Sat Jan 11 03:30:22 2003
@@ -258,12 +258,6 @@
do_exit(SIGSEGV);
}

-static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
-{
- if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs))
- die(str, regs, err);
-}
-
static inline unsigned long get_cr2(void)
{
unsigned long address;
@@ -273,14 +267,11 @@
return address;
}

-static inline void do_trap(int trapnr, int signr, char *str, int vm86,
+static inline void do_trap(int trapnr, int signr, char *str,
struct pt_regs * regs, long error_code, siginfo_t *info)
{
- if (regs->eflags & VM_MASK) {
- if (vm86)
- goto vm86_trap;
- goto trap_signal;
- }
+ if (regs->eflags & VM_MASK)
+ goto vm86_trap;

if (!(regs->xcs & 3))
goto kernel_trap;
@@ -303,8 +294,8 @@
}

vm86_trap: {
- int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr);
- if (ret) goto trap_signal;
+ if (handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr))
+ goto trap_signal;
return;
}
}
@@ -312,7 +303,7 @@
#define DO_ERROR(trapnr, signr, str, name) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
{ \
- do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
+ do_trap(trapnr, signr, str, regs, error_code, NULL); \
}

#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
@@ -323,61 +314,23 @@
info.si_errno = 0; \
info.si_code = sicode; \
info.si_addr = (void *)siaddr; \
- do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
-}
-
-#define DO_VM86_ERROR(trapnr, signr, str, name) \
-asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
-{ \
- do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
+ do_trap(trapnr, signr, str, regs, error_code, &info); \
}

-#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
-asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
-{ \
- siginfo_t info; \
- info.si_signo = signr; \
- info.si_errno = 0; \
- info.si_code = sicode; \
- info.si_addr = (void *)siaddr; \
- do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
-}
-
-DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip)
-DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
-DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
-DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
+DO_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip)
+DO_ERROR( 3, SIGTRAP, "int3", int3)
+DO_ERROR( 4, SIGSEGV, "overflow", overflow)
+DO_ERROR( 5, SIGSEGV, "bounds", bounds)
DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
-DO_VM86_ERROR( 7, SIGSEGV, "device not available", device_not_available)
+DO_ERROR( 7, SIGSEGV, "device not available", device_not_available)
DO_ERROR( 8, SIGSEGV, "double fault", double_fault)
DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
+DO_ERROR(13, SIGSEGV, "general protection fault", general_protection)
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2())

-asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
-{
- if (regs->eflags & VM_MASK)
- goto gp_in_vm86;
-
- if (!(regs->xcs & 3))
- goto gp_in_kernel;
-
- current->thread.error_code = error_code;
- current->thread.trap_no = 13;
- force_sig(SIGSEGV, current);
- return;
-
-gp_in_vm86:
- handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
- return;
-
-gp_in_kernel:
- if (!fixup_exception(regs))
- die("general protection fault", regs, error_code);
-}
-
static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
{
printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
@@ -703,15 +656,7 @@
* Handle strange cache flush from user space exception
* in all other cases. This is undocumented behaviour.
*/
- if (regs->eflags & VM_MASK) {
- handle_vm86_fault((struct kernel_vm86_regs *)regs,
- error_code);
- return;
- }
- die_if_kernel("cache flush denied", regs, error_code);
- current->thread.trap_no = 19;
- current->thread.error_code = error_code;
- force_sig(SIGSEGV, current);
+ do_trap(19, SIGSEGV, "cache flush denied", regs, error_code, NULL);
}
}

diff -urN linux-a1/arch/i386/kernel/vm86.c linux-b1/arch/i386/kernel/vm86.c
--- linux-a1/arch/i386/kernel/vm86.c Sat Jan 11 03:25:01 2003
+++ linux-b1/arch/i386/kernel/vm86.c Sat Jan 11 03:30:22 2003
@@ -502,6 +502,21 @@

int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno)
{
+ switch(trapno) {
+ case 13:
+ case 19:
+ handle_vm86_fault(regs, error_code);
+ return 0;
+ case 0:
+ case 1:
+ case 3:
+ case 4:
+ case 7:
+ break;
+ default:
+ return 1;
+ };
+
if (VMPI.is_vm86pus) {
if ( (trapno==3) || (trapno==1) )
return_to_32bit(regs, VM86_TRAP + (trapno << 8));
\
 
 \ /
  Last update: 2005-03-22 13:32    [W:0.024 / U:3.584 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site