1/* 2 * 3 * Copyright (C) SGI 1999, 2000 4 * 5 * Written by Dimitris Michailidis (dimitris@engr.sgi.com) 6 */ 7 8#ifndef _ASM_KERNPROF_H 9#define _ASM_KERNPROF_H 10 11#ifdef __KERNEL__ 12 13#include <asm/system.h> 14#include <asm/ptrace.h> 15#include <asm/msr.h> 16#include <asm/processor.h> 17 18#define DFL_PC_RES 4 /* default PC resolution for this platform */ 19 20/* 21 * When executing in the BIOS or PROM (happens with APM) we get kernel-mode 22 * addresses below &_stext. 23 */ 24#define in_firmware(regs) ((regs)->eip < (unsigned long) &_stext) 25 26struct st_limits { /* valid kernel stack is between bot & top */ 27 unsigned long *top; 28 unsigned long *bot; 29}; 30 31struct frame_info { 32 struct st_limits limits; 33 unsigned long *frame_ptr; /* saved ebp */ 34 unsigned long pc; /* saved eip */ 35}; 36 37typedef struct frame_info frame_info_t; 38 39#define frame_get_pc(p) ((p)->pc) 40 41static __inline__ void get_stack_limits(struct pt_regs *regs, 42 struct st_limits *p) 43{ 44 p->top = ®s->esp; 45 p->bot = (unsigned long *)((unsigned long) current + THREAD_SIZE); 46} 47 48/* 49 * A function sets up its stack frame with the instructions 50 * 51 * pushl %ebp 52 * movl %esp, %ebp 53 * 54 * The timer interrupt may arrive at any time including right at the moment 55 * that the new frame is being set up, so we need to distinguish a few cases. 56 */ 57static __inline__ void get_top_frame(struct pt_regs *regs, frame_info_t *p) 58{ 59 unsigned long pc = regs->eip; 60 61 get_stack_limits(regs, &p->limits); 62 if (*p->limits.top == regs->ebp) { /* between pushl and movl */ 63 p->frame_ptr = p->limits.top; 64 p->pc = pc; 65 } else { 66 p->frame_ptr = (unsigned long *) regs->ebp; 67 if (*(unsigned char *)pc == 0x55) /* right at pushl %ebp */ 68 p->pc = *p->limits.top; 69 else 70 p->pc = pc; 71 } 72} 73 74/* Fabricate a stack frame that is sufficient to begin walking up the stack */ 75static __inline__ int build_fake_frame(frame_info_t *p) 76{ 77 __asm__ __volatile__("movl %%esp,%0" : "=m" (p->limits.top)); 78 p->limits.bot = (unsigned long *)((unsigned long)current + THREAD_SIZE); 79 __asm__ __volatile__("movl %%ebp,%0" : "=m" (p->frame_ptr)); 80 p->pc = (unsigned long)current_text_addr(); 81 return 1; 82} 83 84/* This macro determines whether there are more frames to go on the stack */ 85#define last_frame(p) \ 86 ((p)->frame_ptr < (p)->limits.top || (p)->frame_ptr >= (p)->limits.bot) 87 88static __inline__ int get_next_frame(frame_info_t *p) 89{ 90 if (last_frame(p)) 91 return 0; 92 p->pc = p->frame_ptr[1]; 93 p->frame_ptr = (unsigned long *) *p->frame_ptr; 94 return 1; 95} 96 97/* These are called by mcount() so we want them to be fast. */ 98void cg_record_arc(unsigned long, unsigned long) __attribute__((regparm(2))); 99void record_fn_call(unsigned long, unsigned long) __attribute__((regparm(2))); 100 101#define supports_call_graph (prof_have_mcount && prof_have_frameptr) 102 103#if defined(CONFIG_MCOUNT) 104#define MCOUNT_STEXT_LOCK "call mcount_stext_lock" 105#define MCOUNT_ASM "call mcount_asm" 106#else 107#define MCOUNT_STEXT_LOCK 108#define MCOUNT_ASM 109#endif 110 111/* We can do 16-bit compare&swap */ 112#define __HAVE_ARCH_CMPXCHG16 1 113 114/* 115 * Performance counters are supported only on P6-family systems with local APIC 116 * since we rely on the overflow interrupts. 117 */ 118#ifdef CONFIG_X86_LOCAL_APIC 119#define have_perfctr() (cpu_has_msr && boot_cpu_data.x86 == 6) 120 121#define valid_perfctr_event(e) ((unsigned long)(e) <= 0xFFFFF) 122#define valid_perfctr_freq(n) ((long)(n) >= 0) 123 124#define get_prof_freq() (HZ * prof_multiplier[0]) 125 126#define EVENTSEL0_ENABLE_MASK 0x00500000 127 128#define perfctr_reload(n) wrmsr(MSR_P6_PERFCTR0, -(int)(n), 0) 129#define __perfctr_stop() wrmsr(MSR_P6_EVNTSEL0, 0, 0) 130 131static __inline__ void __perfctr_commence(unsigned int freq, int evt) 132{ 133 perfctr_reload(freq); 134 wrmsr(MSR_P6_EVNTSEL1, 0, 0); 135 wrmsr(MSR_P6_EVNTSEL0, EVENTSEL0_ENABLE_MASK | (evt), 0); 136} 137#else 138#define have_perfctr() 0 139#define valid_perfctr_event(e) 0 140#define valid_perfctr_freq(n) 0 141#define perfctr_reload(x) 142#define __perfctr_stop() 143#define __perfctr_commence(x,y) 144#define get_prof_freq() HZ 145#define setup_profiling_timer(x) (-EINVAL) 146#endif 147 148#endif /* __KERNEL__ */ 149 150#endif /* !_ASM_KERNPROF_H */ 151