Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Thu, 19 Sep 2002 18:29:22 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Thu, 19 Sep 2002 18:28:14 -0400 Received: from nameservices.net ([208.234.25.16]:37736 "EHLO opersys.com") by vger.kernel.org with ESMTP id ; Thu, 19 Sep 2002 18:25:15 -0400 Message-ID: <3D8A50C3.5C0DBA5F@opersys.com> Date: Thu, 19 Sep 2002 18:33:39 -0400 From: Karim Yaghmour Reply-To: karim@opersys.com X-Mailer: Mozilla 4.75 [en] (X11; U; Linux 2.4.19 i686) X-Accept-Language: en, French/Canada, French/France, fr-FR, fr-CA MIME-Version: 1.0 To: linux-kernel CC: LTT-Dev Subject: [PATCH] LTT for 2.5.36 4/9: i386 trace support Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 13290 Lines: 456 This patch adds the trace support for the i386. Here are the file modifications: arch/i386/config.in | 2 arch/i386/kernel/entry.S | 18 +++++++ arch/i386/kernel/irq.c | 6 ++ arch/i386/kernel/process.c | 6 ++ arch/i386/kernel/sys_i386.c | 4 + arch/i386/kernel/traps.c | 105 +++++++++++++++++++++++++++++++++++++++++++- arch/i386/mm/fault.c | 11 ++++ include/asm-i386/trace.h | 15 ++++++ 8 files changed, 166 insertions, 1 deletion diff -urpN linux-2.5.36/arch/i386/config.in linux-2.5.36-ltt/arch/i386/config.in --- linux-2.5.36/arch/i386/config.in Tue Sep 17 20:58:50 2002 +++ linux-2.5.36-ltt/arch/i386/config.in Thu Sep 19 16:29:56 2002 @@ -420,6 +420,8 @@ source drivers/usb/Config.in source net/bluetooth/Config.in +source drivers/trace/Config.in + mainmenu_option next_comment comment 'Kernel hacking' if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff -urpN linux-2.5.36/arch/i386/kernel/entry.S linux-2.5.36-ltt/arch/i386/kernel/entry.S --- linux-2.5.36/arch/i386/kernel/entry.S Tue Sep 17 20:58:49 2002 +++ linux-2.5.36-ltt/arch/i386/kernel/entry.S Thu Sep 19 16:29:56 2002 @@ -233,9 +233,27 @@ ENTRY(system_call) testb $_TIF_SYSCALL_TRACE,TI_FLAGS(%ebx) jnz syscall_trace_entry syscall_call: +#if (CONFIG_TRACE || CONFIG_TRACE_MODULE) + movl syscall_entry_trace_active, %eax + cmpl $1, %eax # are we tracing system call entries + jne no_syscall_entry_trace + movl %esp, %eax # copy the stack pointer + pushl %eax # pass the stack pointer copy + call trace_real_syscall_entry + addl $4,%esp # return stack to state before pass +no_syscall_entry_trace: + movl ORIG_EAX(%esp),%eax # restore eax to it's original content +#endif call *sys_call_table(,%eax,4) movl %eax,EAX(%esp) # store the return value syscall_exit: +#if (CONFIG_TRACE || CONFIG_TRACE_MODULE) + movl syscall_exit_trace_active, %eax + cmpl $1, %eax # are we tracing system call exits + jne no_syscall_exit_trace + call trace_real_syscall_exit +no_syscall_exit_trace: +#endif cli # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret diff -urpN linux-2.5.36/arch/i386/kernel/irq.c linux-2.5.36-ltt/arch/i386/kernel/irq.c --- linux-2.5.36/arch/i386/kernel/irq.c Tue Sep 17 20:58:44 2002 +++ linux-2.5.36-ltt/arch/i386/kernel/irq.c Thu Sep 19 16:29:56 2002 @@ -33,6 +33,8 @@ #include #include +#include + #include #include #include @@ -202,6 +204,8 @@ int handle_IRQ_event(unsigned int irq, s { int status = 1; /* Force the "do bottom halves" bit */ + TRACE_IRQ_ENTRY(irq, !(user_mode(regs))); + if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); @@ -213,6 +217,8 @@ int handle_IRQ_event(unsigned int irq, s if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); + + TRACE_IRQ_EXIT(); return status; } diff -urpN linux-2.5.36/arch/i386/kernel/process.c linux-2.5.36-ltt/arch/i386/kernel/process.c --- linux-2.5.36/arch/i386/kernel/process.c Tue Sep 17 20:58:40 2002 +++ linux-2.5.36-ltt/arch/i386/kernel/process.c Thu Sep 19 16:29:56 2002 @@ -34,6 +34,8 @@ #include #include +#include + #include #include #include @@ -505,6 +507,10 @@ int kernel_thread(int (*fn)(void *), voi /* Ok, create the new process.. */ p = do_fork(flags | CLONE_VM, 0, ®s, 0, NULL); +#if (CONFIG_TRACE || CONFIG_TRACE_MODULE) + if(!IS_ERR(p)) + TRACE_PROCESS(TRACE_EV_PROCESS_KTHREAD, p->pid, (int) fn); +#endif return IS_ERR(p) ? PTR_ERR(p) : p->pid; } diff -urpN linux-2.5.36/arch/i386/kernel/sys_i386.c linux-2.5.36-ltt/arch/i386/kernel/sys_i386.c --- linux-2.5.36/arch/i386/kernel/sys_i386.c Tue Sep 17 20:58:55 2002 +++ linux-2.5.36-ltt/arch/i386/kernel/sys_i386.c Thu Sep 19 16:29:56 2002 @@ -19,6 +19,8 @@ #include #include +#include + #include #include @@ -136,6 +138,8 @@ asmlinkage int sys_ipc (uint call, int f version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; + + TRACE_IPC(TRACE_EV_IPC_CALL, call, first); switch (call) { case SEMOP: diff -urpN linux-2.5.36/arch/i386/kernel/traps.c linux-2.5.36-ltt/arch/i386/kernel/traps.c --- linux-2.5.36/arch/i386/kernel/traps.c Tue Sep 17 20:58:47 2002 +++ linux-2.5.36-ltt/arch/i386/kernel/traps.c Thu Sep 19 16:32:38 2002 @@ -28,6 +28,8 @@ #include #endif +#include + #ifdef CONFIG_MCA #include #include @@ -283,6 +285,76 @@ bug: printk("Kernel BUG\n"); } +/* Trace related code */ +#if (CONFIG_TRACE || CONFIG_TRACE_MODULE) +asmlinkage void trace_real_syscall_entry(struct pt_regs *regs) +{ + int use_depth; + int use_bounds; + int depth = 0; + int seek_depth; + unsigned long lower_bound; + unsigned long upper_bound; + unsigned long addr; + unsigned long *stack; + trace_syscall_entry trace_syscall_event; + + /* Set the syscall ID */ + trace_syscall_event.syscall_id = (uint8_t) regs->orig_eax; + + /* Set the address in any case */ + trace_syscall_event.address = regs->eip; + + /* Are we in the kernel (This is a kernel thread)? */ + if (!(regs->xcs & 3)) + /* Don't go digining anywhere */ + goto trace_syscall_end; + + /* Get the trace configuration */ + if (trace_get_config(&use_depth, + &use_bounds, + &seek_depth, + (void *) &lower_bound, + (void *) &upper_bound) < 0) + goto trace_syscall_end; + + /* Do we have to search for an eip address range */ + if ((use_depth == 1) || (use_bounds == 1)) { + /* Start at the top of the stack (bottom address since stacks grow downward) */ + stack = (unsigned long *) regs->esp; + + /* Keep on going until we reach the end of the process' stack limit (wherever it may be) */ + while (!get_user(addr, stack)) { + /* Does this LOOK LIKE an address in the program */ + if ((addr > current->mm->start_code) + && (addr < current->mm->end_code)) { + /* Does this address fit the description */ + if (((use_depth == 1) && (depth == seek_depth)) + || ((use_bounds == 1) && (addr > lower_bound) && (addr < upper_bound))) { + /* Set the address */ + trace_syscall_event.address = addr; + + /* We're done */ + goto trace_syscall_end; + } else + /* We're one depth more */ + depth++; + } + /* Go on to the next address */ + stack++; + } + } +trace_syscall_end: + /* Trace the event */ + trace_event(TRACE_EV_SYSCALL_ENTRY, &trace_syscall_event); +} + +asmlinkage void trace_real_syscall_exit(void) +{ + trace_event(TRACE_EV_SYSCALL_EXIT, NULL); +} +#endif /* (CONFIG_TRACE || CONFIG_TRACE_MODULE) */ + spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char * str, struct pt_regs * regs, long err) @@ -316,6 +388,8 @@ static inline unsigned long get_cr2(void static void inline do_trap(int trapnr, int signr, char *str, int vm86, struct pt_regs * regs, long error_code, siginfo_t *info) { + TRACE_TRAP_ENTRY(trapnr, regs->eip); + if (vm86 && regs->eflags & VM_MASK) goto vm86_trap; @@ -330,6 +404,7 @@ static void inline do_trap(int trapnr, i force_sig_info(signr, info, tsk); else force_sig(signr, tsk); + TRACE_TRAP_EXIT(); return; } @@ -355,14 +430,17 @@ static void inline do_trap(int trapnr, i regs->eip = fixup; else die(str, regs, error_code); + TRACE_TRAP_EXIT(); return; } vm86_trap: { int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr); if (ret) goto trap_signal; + TRACE_TRAP_EXIT(); return; } + TRACE_TRAP_EXIT(); } #define DO_ERROR(trapnr, signr, str, name) \ @@ -422,11 +500,15 @@ asmlinkage void do_general_protection(st current->thread.error_code = error_code; current->thread.trap_no = 13; + TRACE_TRAP_ENTRY(13, regs->eip); force_sig(SIGSEGV, current); + TRACE_TRAP_EXIT(); return; gp_in_vm86: + TRACE_TRAP_ENTRY(13, regs->eip); handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); + TRACE_TRAP_EXIT(); return; gp_in_kernel: @@ -486,6 +568,12 @@ asmlinkage void do_nmi(struct pt_regs * { unsigned char reason = inb(0x61); +#ifndef CONFIG_X86_LOCAL_APIC +/* On an machines with APIC enabled, NMIs are used to implement a watchdog +and will hang the machine if traced. */ + TRACE_TRAP_ENTRY(2, regs->eip); +#endif + ++nmi_count(smp_processor_id()); if (!(reason & 0xc0)) { @@ -496,10 +584,14 @@ asmlinkage void do_nmi(struct pt_regs * */ if (nmi_watchdog) { nmi_watchdog_tick(regs); + TRACE_TRAP_EXIT(); return; } #endif unknown_nmi_error(reason, regs); +#ifndef CONFIG_X86_LOCAL_APIC + TRACE_TRAP_EXIT(); +#endif return; } if (reason & 0x80) @@ -514,6 +606,10 @@ asmlinkage void do_nmi(struct pt_regs * inb(0x71); /* dummy */ outb(0x0f, 0x70); inb(0x71); /* dummy */ + +#ifndef CONFIG_X86_LOCAL_APIC + TRACE_TRAP_EXIT(); +#endif } /* @@ -587,7 +683,9 @@ asmlinkage void do_debug(struct pt_regs */ info.si_addr = ((regs->xcs & 3) == 0) ? (void *)tsk->thread.eip : (void *)regs->eip; + TRACE_TRAP_ENTRY(1, regs->eip); force_sig_info(SIGTRAP, &info, tsk); + TRACE_TRAP_EXIT(); /* Disable additional traps. They'll be re-enabled when * the signal is delivered. @@ -599,7 +697,9 @@ clear_dr7: return; debug_vm86: + TRACE_TRAP_ENTRY(1, regs->eip); handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1); + TRACE_TRAP_EXIT(); return; clear_TF: @@ -748,10 +848,12 @@ asmlinkage void do_simd_coprocessor_erro asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs, long error_code) { + TRACE_TRAP_ENTRY(16, regs->eip); #if 0 /* No need to warn about this any longer. */ printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n"); #endif + TRACE_TRAP_EXIT(); } /* @@ -780,8 +882,10 @@ asmlinkage void math_emulate(long arg) { printk("math-emulation not enabled and no coprocessor found.\n"); printk("killing %s.\n",current->comm); + TRACE_TRAP_ENTRY(7, 0); force_sig(SIGFPE,current); schedule(); + TRACE_TRAP_EXIT(); } #endif /* CONFIG_MATH_EMULATION */ @@ -812,7 +916,6 @@ do { \ :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \ "3" ((char *) (addr)),"2" (__KERNEL_CS << 16)); \ } while (0) - /* * This needs to use 'idt_table' rather than 'idt', and diff -urpN linux-2.5.36/arch/i386/mm/fault.c linux-2.5.36-ltt/arch/i386/mm/fault.c --- linux-2.5.36/arch/i386/mm/fault.c Tue Sep 17 20:58:41 2002 +++ linux-2.5.36-ltt/arch/i386/mm/fault.c Thu Sep 19 16:29:56 2002 @@ -20,6 +20,8 @@ #include #include /* For unblank_screen() */ +#include + #include #include #include @@ -180,6 +182,8 @@ asmlinkage void do_page_fault(struct pt_ mm = tsk->mm; info.si_code = SEGV_MAPERR; + TRACE_TRAP_ENTRY(14, regs->eip); + /* * If we're in an interrupt, have no user context or are running in an * atomic region then we must not take the fault.. @@ -264,6 +268,7 @@ good_area: tsk->thread.screen_bitmap |= 1 << bit; } up_read(&mm->mmap_sem); + TRACE_TRAP_EXIT(); return; /* @@ -283,6 +288,7 @@ bad_area: /* info.si_code has been set above */ info.si_addr = (void *)address; force_sig_info(SIGSEGV, &info, tsk); + TRACE_TRAP_EXIT(); return; } @@ -297,6 +303,7 @@ bad_area: if (nr == 6) { do_invalid_op(regs, 0); + TRACE_TRAP_EXIT(); return; } } @@ -306,6 +313,7 @@ no_context: /* Are we prepared to handle this kernel fault? */ if ((fixup = search_exception_table(regs->eip)) != 0) { regs->eip = fixup; + TRACE_TRAP_EXIT(); return; } @@ -379,6 +387,7 @@ do_sigbus: /* Kernel mode? Handle exceptions or die */ if (!(error_code & 4)) goto no_context; + TRACE_TRAP_EXIT(); return; vmalloc_fault: @@ -412,6 +421,8 @@ vmalloc_fault: pte_k = pte_offset_kernel(pmd_k, address); if (!pte_present(*pte_k)) goto no_context; + TRACE_TRAP_EXIT(); return; } + TRACE_TRAP_EXIT(); } diff -urpN linux-2.5.36/include/asm-i386/trace.h linux-2.5.36-ltt/include/asm-i386/trace.h --- linux-2.5.36/include/asm-i386/trace.h Wed Dec 31 19:00:00 1969 +++ linux-2.5.36-ltt/include/asm-i386/trace.h Thu Sep 19 16:29:56 2002 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-i386/trace.h + * + * Copyright (C) 2002, Karim Yaghmour + * + * i386 definitions for tracing system + */ + +#include + +/* Current arch type */ +#define TRACE_ARCH_TYPE TRACE_ARCH_TYPE_I386 + +/* Current variant type */ +#define TRACE_ARCH_VARIANT TRACE_ARCH_VARIANT_NONE - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/