Re: [patch] 2.4.0-test2: %cr4 in a register dump

From: Brian Gerst (bgerst@quark.vpplus.com)
Date: Wed Jul 05 2000 - 21:12:13 EST


Brian Gerst wrote:
>
> Linus Torvalds wrote:
> >
> > On Wed, 5 Jul 2000, Brian Gerst wrote:
> >
> > > How about just trapping the illegal opcode exception then? (patch
> > > untested)
> >
> > Looks fine. Me likee, except for the fact that you should clear %0
> > (otherwise you'll have random crap in the "cr4" variable after a trap - I
> > realize that you zeroed the variable on a C source level, but gcc thinks
> > that your asm-statement will overwrite it, so ...)
> >
> > Linus
>
> Hmm, upon a closer look at the source, the illegal opcode trap isn't
> quite setup to handle kernel faults properly. I assumed it did since I
> got the idea from the 3DNow memcpy code, which uses the illegal opcode
> trap for the "prefetch" instruction. I am working on an updated patch.

As promised here is the updated patch. Previously, if an exception
(other than a general protection fault) occured in kernel mode, the trap
handlers would send a signal to userspace even if an exception handler
was found. Correct me if I'm wrong, but I don't think this should
happen.

-- 

Brian Gerst

diff -urN linux-2.4.0t3p3/arch/i386/kernel/process.c linux-cr4/arch/i386/kernel/process.c --- linux-2.4.0t3p3/arch/i386/kernel/process.c Sat Jun 24 09:09:15 2000 +++ linux-cr4/arch/i386/kernel/process.c Wed Jul 5 20:20:59 2000 @@ -344,7 +344,7 @@ void show_regs(struct pt_regs * regs) { - long cr0 = 0L, cr2 = 0L, cr3 = 0L; + unsigned long cr0, cr2, cr3, cr4; printk("\n"); printk("EIP: %04x:[<%08lx>]",0xffff & regs->xcs,regs->eip); @@ -361,7 +361,18 @@ __asm__("movl %%cr0, %0": "=r" (cr0)); __asm__("movl %%cr2, %0": "=r" (cr2)); __asm__("movl %%cr3, %0": "=r" (cr3)); - printk("CR0: %08lx CR2: %08lx CR3: %08lx\n", cr0, cr2, cr3); + /* This could fault if %cr4 does not exist */ + __asm__("1: movl %%cr4, %0 \n" + "2: \n" + ".section .fixup,\"ax\" \n" + "3: xorl %0, %0 \n" + " jmp 2b \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + ".long 1b,3b \n" + ".previous \n" + : "=r" (cr4)); + printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); } /* diff -urN linux-2.4.0t3p3/arch/i386/kernel/traps.c linux-cr4/arch/i386/kernel/traps.c --- linux-2.4.0t3p3/arch/i386/kernel/traps.c Sat Jun 24 09:09:16 2000 +++ linux-cr4/arch/i386/kernel/traps.c Wed Jul 5 21:50:20 2000 @@ -77,68 +77,6 @@ console_loglevel = 15; } -#define DO_ERROR(trapnr, signr, str, name, tsk) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ -{ \ - tsk->thread.error_code = error_code; \ - tsk->thread.trap_no = trapnr; \ - die_if_no_fixup(str,regs,error_code); \ - force_sig(signr, tsk); \ -} - -#define DO_ERROR_INFO(trapnr, signr, str, name, tsk, sicode, siaddr) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ -{ \ - siginfo_t info; \ - tsk->thread.error_code = error_code; \ - tsk->thread.trap_no = trapnr; \ - die_if_no_fixup(str,regs,error_code); \ - info.si_signo = signr; \ - info.si_errno = 0; \ - info.si_code = sicode; \ - info.si_addr = (void *)siaddr; \ - force_sig_info(signr, &info, tsk); \ -} - -#define DO_VM86_ERROR(trapnr, signr, str, name, tsk) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ -{ \ - lock_kernel(); \ - if (regs->eflags & VM_MASK) { \ - if (!handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr)) \ - goto out; \ - /* else fall through */ \ - } \ - tsk->thread.error_code = error_code; \ - tsk->thread.trap_no = trapnr; \ - force_sig(signr, tsk); \ - die_if_kernel(str,regs,error_code); \ -out: \ - unlock_kernel(); \ -} - -#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, tsk, sicode, siaddr) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ -{ \ - siginfo_t info; \ - lock_kernel(); \ - if (regs->eflags & VM_MASK) { \ - if (!handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr)) \ - goto out; \ - /* else fall through */ \ - } \ - tsk->thread.error_code = error_code; \ - tsk->thread.trap_no = trapnr; \ - info.si_signo = signr; \ - info.si_errno = 0; \ - info.si_code = sicode; \ - info.si_addr = (void *)siaddr; \ - force_sig_info(signr, &info, tsk); \ - die_if_kernel(str,regs,error_code); \ -out: \ - unlock_kernel(); \ -} - asmlinkage void divide_error(void); asmlinkage void debug(void); asmlinkage void nmi(void); @@ -285,20 +223,6 @@ die(str, regs, err); } -static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) -{ - if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs)) - { - unsigned long fixup; - fixup = search_exception_table(regs->eip); - if (fixup) { - regs->eip = fixup; - return; - } - die(str, regs, err); - } -} - static inline unsigned long get_cr2(void) { unsigned long address; @@ -306,6 +230,76 @@ /* get the address */ __asm__("movl %%cr2,%0":"=r" (address)); return address; +} + +static void inline do_trap(int trapnr, int signr, char *str, struct task_struct *tsk, int vm86, + struct pt_regs * regs, long error_code, siginfo_t *info) +{ + unsigned long fixup; + int ret; + + if (vm86 && regs->eflags & VM_MASK) + goto vm86_trap; + if (!(regs->xcs & 3)) + goto kernel_trap; + +trap_signal: + tsk->thread.error_code = error_code; + tsk->thread.trap_no = trapnr; + if (info) + force_sig_info(signr, info, tsk); + else + force_sig(signr, tsk); + return; + +kernel_trap: + fixup = search_exception_table(regs->eip); + if (fixup) + regs->eip = fixup; + else + die(str, regs, error_code); + return; + +vm86_trap: + lock_kernel(); + ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr); + unlock_kernel(); + if (ret) goto trap_signal; + return; +} + +#define DO_ERROR(trapnr, signr, str, name, tsk) \ +asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +{ \ + do_trap(trapnr, signr, str, tsk, 0, regs, error_code, NULL); \ +} + +#define DO_ERROR_INFO(trapnr, signr, str, name, tsk, 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, tsk, 0, regs, error_code, &info); \ +} + +#define DO_VM86_ERROR(trapnr, signr, str, name, tsk) \ +asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +{ \ + do_trap(trapnr, signr, str, tsk, 1, regs, error_code, NULL); \ +} + +#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, tsk, 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, tsk, 1, regs, error_code, &info); \ } DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, current, FPE_INTDIV, regs->eip)

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Jul 07 2000 - 21:00:17 EST