linux-bk/arch/x86_64/kernel/traps.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/x86-64/traps.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
   6 *
   7 *  Pentium III FXSR, SSE support
   8 *      Gareth Hughes <gareth@valinux.com>, May 2000
   9 *
  10 *  $Id: traps.c,v 1.36 2002/03/24 11:09:10 ak Exp $
  11 */
  12
  13/*
  14 * 'Traps.c' handles hardware traps and faults after we have saved some
  15 * state in 'entry.S'.
  16 */
  17#include <linux/config.h>
  18#include <linux/sched.h>
  19#include <linux/kernel.h>
  20#include <linux/string.h>
  21#include <linux/errno.h>
  22#include <linux/ptrace.h>
  23#include <linux/timer.h>
  24#include <linux/mm.h>
  25#include <linux/init.h>
  26#include <linux/delay.h>
  27#include <linux/spinlock.h>
  28#include <linux/interrupt.h>
  29#include <linux/module.h>
  30#include <linux/moduleparam.h>
  31
  32#include <asm/system.h>
  33#include <asm/uaccess.h>
  34#include <asm/io.h>
  35#include <asm/atomic.h>
  36#include <asm/debugreg.h>
  37#include <asm/desc.h>
  38#include <asm/i387.h>
  39#include <asm/kdebug.h>
  40#include <asm/processor.h>
  41
  42#include <asm/smp.h>
  43#include <asm/pgalloc.h>
  44#include <asm/pda.h>
  45#include <asm/proto.h>
  46#include <asm/nmi.h>
  47
  48#include <linux/irq.h>
  49
  50
  51extern struct gate_struct idt_table[256]; 
  52
  53asmlinkage void divide_error(void);
  54asmlinkage void debug(void);
  55asmlinkage void nmi(void);
  56asmlinkage void int3(void);
  57asmlinkage void overflow(void);
  58asmlinkage void bounds(void);
  59asmlinkage void invalid_op(void);
  60asmlinkage void device_not_available(void);
  61asmlinkage void double_fault(void);
  62asmlinkage void coprocessor_segment_overrun(void);
  63asmlinkage void invalid_TSS(void);
  64asmlinkage void segment_not_present(void);
  65asmlinkage void stack_segment(void);
  66asmlinkage void general_protection(void);
  67asmlinkage void page_fault(void);
  68asmlinkage void coprocessor_error(void);
  69asmlinkage void simd_coprocessor_error(void);
  70asmlinkage void reserved(void);
  71asmlinkage void alignment_check(void);
  72asmlinkage void machine_check(void);
  73asmlinkage void spurious_interrupt_bug(void);
  74asmlinkage void call_debug(void);
  75
  76struct notifier_block *die_chain;
  77static DEFINE_SPINLOCK(die_notifier_lock);
  78
  79int register_die_notifier(struct notifier_block *nb)
  80{
  81        int err = 0;
  82        unsigned long flags;
  83        spin_lock_irqsave(&die_notifier_lock, flags);
  84        err = notifier_chain_register(&die_chain, nb);
  85        spin_unlock_irqrestore(&die_notifier_lock, flags);
  86        return err;
  87}
  88
  89static inline void conditional_sti(struct pt_regs *regs)
  90{
  91        if (regs->eflags & X86_EFLAGS_IF)
  92                local_irq_enable();
  93}
  94
  95static int kstack_depth_to_print = 10;
  96
  97#ifdef CONFIG_KALLSYMS
  98#include <linux/kallsyms.h> 
  99int printk_address(unsigned long address)
 100{ 
 101        unsigned long offset = 0, symsize;
 102        const char *symname;
 103        char *modname;
 104        char *delim = ":"; 
 105        char namebuf[128];
 106
 107        symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf); 
 108        if (!symname) 
 109                return printk("[<%016lx>]", address);
 110        if (!modname) 
 111                modname = delim = "";           
 112        return printk("<%016lx>{%s%s%s%s%+ld}",
 113                      address,delim,modname,delim,symname,offset); 
 114} 
 115#else
 116int printk_address(unsigned long address)
 117{ 
 118        return printk("[<%016lx>]", address);
 119} 
 120#endif
 121
 122unsigned long *in_exception_stack(int cpu, unsigned long stack) 
 123{ 
 124        int k;
 125        for (k = 0; k < N_EXCEPTION_STACKS; k++) {
 126                struct tss_struct *tss = &per_cpu(init_tss, cpu);
 127                unsigned long end = tss->ist[k] + EXCEPTION_STKSZ;
 128
 129                if (stack >= tss->ist[k]  && stack <= end)
 130                        return (unsigned long *)end;
 131        }
 132        return NULL;
 133} 
 134
 135/*
 136 * x86-64 can have upto three kernel stacks: 
 137 * process stack
 138 * interrupt stack
 139 * severe exception (double fault, nmi, stack fault) hardware stack
 140 * Check and process them in order.
 141 */
 142
 143void show_trace(unsigned long *stack)
 144{
 145        unsigned long addr;
 146        unsigned long *irqstack, *irqstack_end, *estack_end;
 147        const int cpu = safe_smp_processor_id();
 148        int i;
 149
 150        printk("\nCall Trace:");
 151        i = 0; 
 152        
 153        estack_end = in_exception_stack(cpu, (unsigned long)stack); 
 154        if (estack_end) { 
 155                while (stack < estack_end) { 
 156                        addr = *stack++; 
 157                        if (__kernel_text_address(addr)) {
 158                                i += printk_address(addr);
 159                                i += printk(" "); 
 160                                if (i > 50) {
 161                                        printk("\n"); 
 162                                        i = 0;
 163                                }
 164                        }
 165                }
 166                i += printk(" <EOE> "); 
 167                i += 7;
 168                stack = (unsigned long *) estack_end[-2]; 
 169        }  
 170
 171        irqstack_end = (unsigned long *) (cpu_pda[cpu].irqstackptr);
 172        irqstack = (unsigned long *) (cpu_pda[cpu].irqstackptr - IRQSTACKSIZE + 64);
 173
 174        if (stack >= irqstack && stack < irqstack_end) {
 175                printk("<IRQ> ");  
 176                while (stack < irqstack_end) {
 177                        addr = *stack++;
 178                        /*
 179                         * If the address is either in the text segment of the
 180                         * kernel, or in the region which contains vmalloc'ed
 181                         * memory, it *may* be the address of a calling
 182                         * routine; if so, print it so that someone tracing
 183                         * down the cause of the crash will be able to figure
 184                         * out the call path that was taken.
 185                         */
 186                         if (__kernel_text_address(addr)) {
 187                                 i += printk_address(addr);
 188                                 i += printk(" "); 
 189                                 if (i > 50) { 
 190                                        printk("\n       ");
 191                                         i = 0;
 192                                 } 
 193                        }
 194                } 
 195                stack = (unsigned long *) (irqstack_end[-1]);
 196                printk(" <EOI> ");
 197                i += 7;
 198        } 
 199
 200        while (((long) stack & (THREAD_SIZE-1)) != 0) {
 201                addr = *stack++;
 202                if (__kernel_text_address(addr)) {
 203                        i += printk_address(addr);
 204                        i += printk(" "); 
 205                        if (i > 50) { 
 206                                printk("\n       ");
 207                                         i = 0;
 208                        } 
 209                }
 210        }
 211        printk("\n");
 212}
 213
 214void show_stack(struct task_struct *tsk, unsigned long * rsp)
 215{
 216        unsigned long *stack;
 217        int i;
 218        const int cpu = safe_smp_processor_id();
 219        unsigned long *irqstack_end = (unsigned long *) (cpu_pda[cpu].irqstackptr);
 220        unsigned long *irqstack = (unsigned long *) (cpu_pda[cpu].irqstackptr - IRQSTACKSIZE);    
 221
 222        // debugging aid: "show_stack(NULL, NULL);" prints the
 223        // back trace for this cpu.
 224
 225        if (rsp == NULL) {
 226                if (tsk)
 227                        rsp = (unsigned long *)tsk->thread.rsp;
 228                else
 229                        rsp = (unsigned long *)&rsp;
 230        }
 231
 232        stack = rsp;
 233        for(i=0; i < kstack_depth_to_print; i++) {
 234                if (stack >= irqstack && stack <= irqstack_end) {
 235                        if (stack == irqstack_end) {
 236                                stack = (unsigned long *) (irqstack_end[-1]);
 237                                printk(" <EOI> ");
 238                        }
 239                } else {
 240                if (((long) stack & (THREAD_SIZE-1)) == 0)
 241                        break;
 242                }
 243                if (i && ((i % 4) == 0))
 244                        printk("\n       ");
 245                printk("%016lx ", *stack++);
 246        }
 247        show_trace((unsigned long *)rsp);
 248}
 249
 250/*
 251 * The architecture-independent dump_stack generator
 252 */
 253void dump_stack(void)
 254{
 255        unsigned long dummy;
 256        show_trace(&dummy);
 257}
 258
 259EXPORT_SYMBOL(dump_stack);
 260
 261void show_registers(struct pt_regs *regs)
 262{
 263        int i;
 264        int in_kernel = (regs->cs & 3) == 0;
 265        unsigned long rsp;
 266        const int cpu = safe_smp_processor_id(); 
 267        struct task_struct *cur = cpu_pda[cpu].pcurrent; 
 268
 269                rsp = regs->rsp;
 270
 271        printk("CPU %d ", cpu);
 272        __show_regs(regs);
 273        printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
 274                cur->comm, cur->pid, cur->thread_info, cur);
 275
 276        /*
 277         * When in-kernel, we also print out the stack and code at the
 278         * time of the fault..
 279         */
 280        if (in_kernel) {
 281
 282                printk("Stack: ");
 283                show_stack(NULL, (unsigned long*)rsp);
 284
 285                printk("\nCode: ");
 286                if(regs->rip < PAGE_OFFSET)
 287                        goto bad;
 288
 289                for(i=0;i<20;i++)
 290                {
 291                        unsigned char c;
 292                        if(__get_user(c, &((unsigned char*)regs->rip)[i])) {
 293bad:
 294                                printk(" Bad RIP value.");
 295                                break;
 296                        }
 297                        printk("%02x ", c);
 298                }
 299        }
 300        printk("\n");
 301}       
 302
 303void handle_BUG(struct pt_regs *regs)
 304{ 
 305        struct bug_frame f;
 306        char tmp;
 307
 308        if (regs->cs & 3)
 309                return; 
 310        if (__copy_from_user(&f, (struct bug_frame *) regs->rip, 
 311                             sizeof(struct bug_frame)))
 312                return; 
 313        if ((unsigned long)f.filename < __PAGE_OFFSET || 
 314            f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) 
 315                return;
 316        if (__get_user(tmp, f.filename))
 317                f.filename = "unmapped filename"; 
 318        printk("----------- [cut here ] --------- [please bite here ] ---------\n");
 319        printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line);
 320} 
 321
 322void out_of_line_bug(void)
 323{ 
 324        BUG(); 
 325} 
 326
 327static DEFINE_SPINLOCK(die_lock);
 328static int die_owner = -1;
 329
 330void oops_begin(void)
 331{
 332        int cpu = safe_smp_processor_id(); 
 333        /* racy, but better than risking deadlock. */ 
 334        local_irq_disable();
 335        if (!spin_trylock(&die_lock)) { 
 336                if (cpu == die_owner) 
 337                        /* nested oops. should stop eventually */;
 338                else
 339                        spin_lock(&die_lock); 
 340        }
 341        die_owner = cpu; 
 342        console_verbose();
 343        bust_spinlocks(1); 
 344}
 345
 346void oops_end(void)
 347{ 
 348        die_owner = -1;
 349        bust_spinlocks(0); 
 350        spin_unlock(&die_lock); 
 351        local_irq_enable();     /* make sure back scroll still works */
 352        if (panic_on_oops)
 353                panic("Oops"); 
 354} 
 355
 356void __die(const char * str, struct pt_regs * regs, long err)
 357{
 358        static int die_counter;
 359        printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter);
 360#ifdef CONFIG_PREEMPT
 361        printk("PREEMPT ");
 362#endif
 363#ifdef CONFIG_SMP
 364        printk("SMP ");
 365#endif
 366#ifdef CONFIG_DEBUG_PAGEALLOC
 367        printk("DEBUG_PAGEALLOC");
 368#endif
 369        printk("\n");
 370        notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
 371        show_registers(regs);
 372        /* Executive summary in case the oops scrolled away */
 373        printk(KERN_ALERT "RIP ");
 374        printk_address(regs->rip); 
 375        printk(" RSP <%016lx>\n", regs->rsp); 
 376}
 377
 378void die(const char * str, struct pt_regs * regs, long err)
 379{
 380        oops_begin();
 381        handle_BUG(regs);
 382        __die(str, regs, err);
 383        oops_end();
 384        do_exit(SIGSEGV); 
 385}
 386static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
 387{
 388        if (!(regs->eflags & VM_MASK) && (regs->cs == __KERNEL_CS))
 389                die(str, regs, err);
 390}
 391
 392void die_nmi(char *str, struct pt_regs *regs)
 393{
 394        oops_begin();
 395        /*
 396         * We are in trouble anyway, lets at least try
 397         * to get a message out.
 398         */
 399        printk(str, safe_smp_processor_id());
 400        show_registers(regs);
 401        if (panic_on_timeout || panic_on_oops)
 402                panic("nmi watchdog");
 403        printk("console shuts up ...\n");
 404        oops_end();
 405        do_exit(SIGSEGV);
 406}
 407
 408static void do_trap(int trapnr, int signr, char *str, 
 409                           struct pt_regs * regs, long error_code, siginfo_t *info)
 410{
 411        conditional_sti(regs);
 412
 413#ifdef CONFIG_CHECKING
 414       { 
 415               unsigned long gs; 
 416               struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); 
 417               rdmsrl(MSR_GS_BASE, gs); 
 418               if (gs != (unsigned long)pda) { 
 419                       wrmsrl(MSR_GS_BASE, pda); 
 420                       printk("%s: wrong gs %lx expected %p rip %lx\n", str, gs, pda,
 421                              regs->rip);
 422               }
 423       }
 424#endif
 425
 426        if ((regs->cs & 3)  != 0) { 
 427                struct task_struct *tsk = current;
 428
 429                if (exception_trace && unhandled_signal(tsk, signr))
 430                        printk(KERN_INFO
 431                               "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n",
 432                               tsk->comm, tsk->pid, str,
 433                               regs->rip,regs->rsp,error_code); 
 434
 435                tsk->thread.error_code = error_code;
 436                tsk->thread.trap_no = trapnr;
 437                if (info)
 438                        force_sig_info(signr, info, tsk);
 439                else
 440                        force_sig(signr, tsk);
 441                return;
 442        }
 443
 444
 445        /* kernel trap */ 
 446        {            
 447                const struct exception_table_entry *fixup;
 448                fixup = search_exception_tables(regs->rip);
 449                if (fixup) {
 450                        regs->rip = fixup->fixup;
 451                } else  
 452                        die(str, regs, error_code);
 453                return;
 454        }
 455}
 456
 457#define DO_ERROR(trapnr, signr, str, name) \
 458asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 459{ \
 460        if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
 461                                                        == NOTIFY_STOP) \
 462                return; \
 463        do_trap(trapnr, signr, str, regs, error_code, NULL); \
 464}
 465
 466#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
 467asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 468{ \
 469        siginfo_t info; \
 470        info.si_signo = signr; \
 471        info.si_errno = 0; \
 472        info.si_code = sicode; \
 473        info.si_addr = (void __user *)siaddr; \
 474        if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
 475                                                        == NOTIFY_STOP) \
 476                return; \
 477        do_trap(trapnr, signr, str, regs, error_code, &info); \
 478}
 479
 480DO_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->rip)
 481DO_ERROR( 4, SIGSEGV, "overflow", overflow)
 482DO_ERROR( 5, SIGSEGV, "bounds", bounds)
 483DO_ERROR_INFO( 6, SIGILL,  "invalid operand", invalid_op, ILL_ILLOPN, regs->rip)
 484DO_ERROR( 7, SIGSEGV, "device not available", device_not_available)
 485DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
 486DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
 487DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 488DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
 489DO_ERROR(18, SIGSEGV, "reserved", reserved)
 490
 491#define DO_ERROR_STACK(trapnr, signr, str, name) \
 492asmlinkage void *do_##name(struct pt_regs * regs, long error_code) \
 493{ \
 494        struct pt_regs *pr = ((struct pt_regs *)(current->thread.rsp0))-1; \
 495        if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
 496                                                        == NOTIFY_STOP) \
 497                return regs; \
 498        if (regs->cs & 3) { \
 499                memcpy(pr, regs, sizeof(struct pt_regs)); \
 500                regs = pr; \
 501        } \
 502        do_trap(trapnr, signr, str, regs, error_code, NULL); \
 503        return regs;            \
 504}
 505
 506DO_ERROR_STACK(12, SIGBUS,  "stack segment", stack_segment)
 507DO_ERROR_STACK( 8, SIGSEGV, "double fault", double_fault)
 508
 509asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
 510{
 511        conditional_sti(regs);
 512
 513#ifdef CONFIG_CHECKING
 514       { 
 515               unsigned long gs; 
 516               struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); 
 517               rdmsrl(MSR_GS_BASE, gs); 
 518               if (gs != (unsigned long)pda) { 
 519                       wrmsrl(MSR_GS_BASE, pda); 
 520                       oops_in_progress++;
 521                       printk("general protection handler: wrong gs %lx expected %p\n", gs, pda);
 522                       oops_in_progress--;
 523               }
 524       }
 525#endif
 526
 527        if ((regs->cs & 3)!=0) { 
 528                struct task_struct *tsk = current;
 529
 530                if (exception_trace && unhandled_signal(tsk, SIGSEGV))
 531                        printk(KERN_INFO
 532                       "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n",
 533                               tsk->comm, tsk->pid,
 534                               regs->rip,regs->rsp,error_code); 
 535
 536                tsk->thread.error_code = error_code;
 537                tsk->thread.trap_no = 13;
 538                force_sig(SIGSEGV, tsk);
 539                return;
 540        } 
 541
 542        /* kernel gp */
 543        {
 544                const struct exception_table_entry *fixup;
 545                fixup = search_exception_tables(regs->rip);
 546                if (fixup) {
 547                        regs->rip = fixup->fixup;
 548                        return;
 549                }
 550                if (notify_die(DIE_GPF, "general protection fault", regs,
 551                                        error_code, 13, SIGSEGV) == NOTIFY_STOP)
 552                        return;
 553                die("general protection fault", regs, error_code);
 554        }
 555}
 556
 557static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
 558{
 559        printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
 560        printk("You probably have a hardware problem with your RAM chips\n");
 561
 562        /* Clear and disable the memory parity error line. */
 563        reason = (reason & 0xf) | 4;
 564        outb(reason, 0x61);
 565}
 566
 567static void io_check_error(unsigned char reason, struct pt_regs * regs)
 568{
 569        printk("NMI: IOCK error (debug interrupt?)\n");
 570        show_registers(regs);
 571
 572        /* Re-enable the IOCK line, wait for a few seconds */
 573        reason = (reason & 0xf) | 8;
 574        outb(reason, 0x61);
 575        mdelay(2000);
 576        reason &= ~8;
 577        outb(reason, 0x61);
 578}
 579
 580static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
 581{       printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
 582        printk("Dazed and confused, but trying to continue\n");
 583        printk("Do you have a strange power saving mode enabled?\n");
 584}
 585
 586asmlinkage void default_do_nmi(struct pt_regs *regs)
 587{
 588        unsigned char reason = 0;
 589
 590        /* Only the BSP gets external NMIs from the system.  */
 591        if (!smp_processor_id())
 592                reason = get_nmi_reason();
 593
 594        if (!(reason & 0xc0)) {
 595                if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
 596                                                                == NOTIFY_STOP)
 597                        return;
 598#ifdef CONFIG_X86_LOCAL_APIC
 599                /*
 600                 * Ok, so this is none of the documented NMI sources,
 601                 * so it must be the NMI watchdog.
 602                 */
 603                if (nmi_watchdog > 0) {
 604                        nmi_watchdog_tick(regs,reason);
 605                        return;
 606                }
 607#endif
 608                unknown_nmi_error(reason, regs);
 609                return;
 610        }
 611        if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
 612                return; 
 613
 614        /* AK: following checks seem to be broken on modern chipsets. FIXME */
 615
 616        if (reason & 0x80)
 617                mem_parity_error(reason, regs);
 618        if (reason & 0x40)
 619                io_check_error(reason, regs);
 620
 621        /*
 622         * Reassert NMI in case it became active meanwhile
 623         * as it's edge-triggered.
 624         */
 625        outb(0x8f, 0x70);
 626        inb(0x71);              /* dummy */
 627        outb(0x0f, 0x70);
 628        inb(0x71);              /* dummy */
 629}
 630
 631asmlinkage void do_int3(struct pt_regs * regs, long error_code)
 632{
 633        if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
 634                return;
 635        }
 636        do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
 637        return;
 638}
 639
 640/* runs on IST stack. */
 641asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code)
 642{
 643        struct pt_regs *pr;
 644        unsigned long condition;
 645        struct task_struct *tsk = current;
 646        siginfo_t info;
 647
 648        pr = (struct pt_regs *)(current->thread.rsp0)-1;
 649        if (regs->cs & 3) {
 650                memcpy(pr, regs, sizeof(struct pt_regs));
 651                regs = pr;
 652        }       
 653
 654#ifdef CONFIG_CHECKING
 655       { 
 656               /* RED-PEN interaction with debugger - could destroy gs */
 657               unsigned long gs; 
 658               struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); 
 659               rdmsrl(MSR_GS_BASE, gs); 
 660               if (gs != (unsigned long)pda) { 
 661                       wrmsrl(MSR_GS_BASE, pda); 
 662                       printk("debug handler: wrong gs %lx expected %p\n", gs, pda);
 663               }
 664       }
 665#endif
 666
 667        asm("movq %%db6,%0" : "=r" (condition));
 668
 669        if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
 670                                                SIGTRAP) == NOTIFY_STOP) {
 671                return regs;
 672        }
 673        conditional_sti(regs);
 674
 675        /* Mask out spurious debug traps due to lazy DR7 setting */
 676        if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
 677                if (!tsk->thread.debugreg7) { 
 678                        goto clear_dr7;
 679                }
 680        }
 681
 682        tsk->thread.debugreg6 = condition;
 683
 684        /* Mask out spurious TF errors due to lazy TF clearing */
 685        if ((condition & DR_STEP) &&
 686            (notify_die(DIE_DEBUGSTEP, "debugstep", regs, condition,
 687                        1, SIGTRAP) != NOTIFY_STOP)) {
 688                /*
 689                 * The TF error should be masked out only if the current
 690                 * process is not traced and if the TRAP flag has been set
 691                 * previously by a tracing process (condition detected by
 692                 * the PT_DTRACE flag); remember that the i386 TRAP flag
 693                 * can be modified by the process itself in user mode,
 694                 * allowing programs to debug themselves without the ptrace()
 695                 * interface.
 696                 */
 697                if ((regs->cs & 3) == 0)
 698                       goto clear_TF_reenable;
 699                if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
 700                        goto clear_TF;
 701        }
 702
 703        /* Ok, finally something we can handle */
 704        tsk->thread.trap_no = 1;
 705        tsk->thread.error_code = error_code;
 706        info.si_signo = SIGTRAP;
 707        info.si_errno = 0;
 708        info.si_code = TRAP_BRKPT;
 709        if ((regs->cs & 3) == 0) 
 710                goto clear_dr7; 
 711
 712        info.si_addr = (void __user *)regs->rip;
 713        force_sig_info(SIGTRAP, &info, tsk);    
 714clear_dr7:
 715        asm volatile("movq %0,%%db7"::"r"(0UL));
 716        notify_die(DIE_DEBUG, "debug", regs, condition, 1, SIGTRAP);
 717        return regs;
 718
 719clear_TF_reenable:
 720        set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
 721
 722clear_TF:
 723        /* RED-PEN could cause spurious errors */
 724        if (notify_die(DIE_DEBUG, "debug2", regs, condition, 1, SIGTRAP) 
 725                                                                != NOTIFY_STOP)
 726        regs->eflags &= ~TF_MASK;
 727        return regs;    
 728}
 729
 730static int kernel_math_error(struct pt_regs *regs, char *str)
 731{
 732        const struct exception_table_entry *fixup;
 733        fixup = search_exception_tables(regs->rip);
 734        if (fixup) {
 735                regs->rip = fixup->fixup;
 736                return 1;
 737        }
 738        notify_die(DIE_GPF, str, regs, 0, 16, SIGFPE);
 739#if 0
 740        /* This should be a die, but warn only for now */
 741        die(str, regs, 0);
 742#else
 743        printk(KERN_DEBUG "%s: %s at ", current->comm, str);
 744        printk_address(regs->rip);
 745        printk("\n");
 746#endif
 747        return 0;
 748}
 749
 750/*
 751 * Note that we play around with the 'TS' bit in an attempt to get
 752 * the correct behaviour even in the presence of the asynchronous
 753 * IRQ13 behaviour
 754 */
 755asmlinkage void do_coprocessor_error(struct pt_regs *regs)
 756{
 757        void __user *rip = (void __user *)(regs->rip);
 758        struct task_struct * task;
 759        siginfo_t info;
 760        unsigned short cwd, swd;
 761
 762        conditional_sti(regs);
 763        if ((regs->cs & 3) == 0 &&
 764            kernel_math_error(regs, "kernel x87 math error"))
 765                return;
 766
 767        /*
 768         * Save the info for the exception handler and clear the error.
 769         */
 770        task = current;
 771        save_init_fpu(task);
 772        task->thread.trap_no = 16;
 773        task->thread.error_code = 0;
 774        info.si_signo = SIGFPE;
 775        info.si_errno = 0;
 776        info.si_code = __SI_FAULT;
 777        info.si_addr = rip;
 778        /*
 779         * (~cwd & swd) will mask out exceptions that are not set to unmasked
 780         * status.  0x3f is the exception bits in these regs, 0x200 is the
 781         * C1 reg you need in case of a stack fault, 0x040 is the stack
 782         * fault bit.  We should only be taking one exception at a time,
 783         * so if this combination doesn't produce any single exception,
 784         * then we have a bad program that isn't synchronizing its FPU usage
 785         * and it will suffer the consequences since we won't be able to
 786         * fully reproduce the context of the exception
 787         */
 788        cwd = get_fpu_cwd(task);
 789        swd = get_fpu_swd(task);
 790        switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
 791                case 0x000:
 792                default:
 793                        break;
 794                case 0x001: /* Invalid Op */
 795                case 0x041: /* Stack Fault */
 796                case 0x241: /* Stack Fault | Direction */
 797                        info.si_code = FPE_FLTINV;
 798                        break;
 799                case 0x002: /* Denormalize */
 800                case 0x010: /* Underflow */
 801                        info.si_code = FPE_FLTUND;
 802                        break;
 803                case 0x004: /* Zero Divide */
 804                        info.si_code = FPE_FLTDIV;
 805                        break;
 806                case 0x008: /* Overflow */
 807                        info.si_code = FPE_FLTOVF;
 808                        break;
 809                case 0x020: /* Precision */
 810                        info.si_code = FPE_FLTRES;
 811                        break;
 812        }
 813        force_sig_info(SIGFPE, &info, task);
 814}
 815
 816asmlinkage void bad_intr(void)
 817{
 818        printk("bad interrupt"); 
 819}
 820
 821asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
 822{
 823        void __user *rip = (void __user *)(regs->rip);
 824        struct task_struct * task;
 825        siginfo_t info;
 826        unsigned short mxcsr;
 827
 828        conditional_sti(regs);
 829        if ((regs->cs & 3) == 0 &&
 830                kernel_math_error(regs, "simd math error"))
 831                return;
 832
 833        /*
 834         * Save the info for the exception handler and clear the error.
 835         */
 836        task = current;
 837        save_init_fpu(task);
 838        task->thread.trap_no = 19;
 839        task->thread.error_code = 0;
 840        info.si_signo = SIGFPE;
 841        info.si_errno = 0;
 842        info.si_code = __SI_FAULT;
 843        info.si_addr = rip;
 844        /*
 845         * The SIMD FPU exceptions are handled a little differently, as there
 846         * is only a single status/control register.  Thus, to determine which
 847         * unmasked exception was caught we must mask the exception mask bits
 848         * at 0x1f80, and then use these to mask the exception bits at 0x3f.
 849         */
 850        mxcsr = get_fpu_mxcsr(task);
 851        switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
 852                case 0x000:
 853                default:
 854                        break;
 855                case 0x001: /* Invalid Op */
 856                        info.si_code = FPE_FLTINV;
 857                        break;
 858                case 0x002: /* Denormalize */
 859                case 0x010: /* Underflow */
 860                        info.si_code = FPE_FLTUND;
 861                        break;
 862                case 0x004: /* Zero Divide */
 863                        info.si_code = FPE_FLTDIV;
 864                        break;
 865                case 0x008: /* Overflow */
 866                        info.si_code = FPE_FLTOVF;
 867                        break;
 868                case 0x020: /* Precision */
 869                        info.si_code = FPE_FLTRES;
 870                        break;
 871        }
 872        force_sig_info(SIGFPE, &info, task);
 873}
 874
 875asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs)
 876{
 877}
 878
 879asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
 880{
 881}
 882
 883/*
 884 *  'math_state_restore()' saves the current math information in the
 885 * old math state array, and gets the new ones from the current task
 886 *
 887 * Careful.. There are problems with IBM-designed IRQ13 behaviour.
 888 * Don't touch unless you *really* know how it works.
 889 */
 890asmlinkage void math_state_restore(void)
 891{
 892        struct task_struct *me = current;
 893        clts();                 /* Allow maths ops (or we recurse) */
 894
 895        if (!used_math())
 896                init_fpu(me);
 897        restore_fpu_checking(&me->thread.i387.fxsave);
 898        me->thread_info->status |= TS_USEDFPU;
 899}
 900
 901void do_call_debug(struct pt_regs *regs) 
 902{ 
 903        notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); 
 904}
 905
 906void __init trap_init(void)
 907{
 908        set_intr_gate(0,&divide_error);
 909        set_intr_gate_ist(1,&debug,DEBUG_STACK);
 910        set_intr_gate_ist(2,&nmi,NMI_STACK);
 911        set_system_gate(3,&int3);
 912        set_system_gate(4,&overflow);   /* int4-5 can be called from all */
 913        set_system_gate(5,&bounds);
 914        set_intr_gate(6,&invalid_op);
 915        set_intr_gate(7,&device_not_available);
 916        set_intr_gate_ist(8,&double_fault, DOUBLEFAULT_STACK);
 917        set_intr_gate(9,&coprocessor_segment_overrun);
 918        set_intr_gate(10,&invalid_TSS);
 919        set_intr_gate(11,&segment_not_present);
 920        set_intr_gate_ist(12,&stack_segment,STACKFAULT_STACK);
 921        set_intr_gate(13,&general_protection);
 922        set_intr_gate(14,&page_fault);
 923        set_intr_gate(15,&spurious_interrupt_bug);
 924        set_intr_gate(16,&coprocessor_error);
 925        set_intr_gate(17,&alignment_check);
 926#ifdef CONFIG_X86_MCE
 927        set_intr_gate_ist(18,&machine_check, MCE_STACK); 
 928#endif
 929        set_intr_gate(19,&simd_coprocessor_error);
 930
 931#ifdef CONFIG_IA32_EMULATION
 932        set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
 933#endif
 934       
 935        set_intr_gate(KDB_VECTOR, call_debug);
 936       
 937        /*
 938         * Should be a barrier for any external CPU state.
 939         */
 940        cpu_init();
 941}
 942
 943
 944/* Actual parsing is done early in setup.c. */
 945static int __init oops_dummy(char *s)
 946{ 
 947        panic_on_oops = 1;
 948        return -1; 
 949} 
 950__setup("oops=", oops_dummy); 
 951
 952static int __init kstack_setup(char *s)
 953{
 954        kstack_depth_to_print = simple_strtoul(s,NULL,0);
 955        return 0;
 956}
 957__setup("kstack=", kstack_setup);
 958
 959
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.