1/*
2 * Copyright (C) SGI 2000
3 *
4 * Written by Dimitris Michailidis (dimitris@engr.sgi.com)
5 * Written by Goutham Rao <goutham.rao@intel.com>
6 */
7
8#ifndef _ASM_KERNPROF_H
9#define _ASM_KERNPROF_H
10#ifdef __KERNEL__
11
12#include <asm/unwind.h>
13#include <asm/system.h>
14#include <asm/ptrace.h>
15
16#ifdef FUNCTIONPC
17#undef FUNCTIONPC
18#endif
19#define FUNCTIONPC(func)	(*(unsigned long *)&(func))
20
21/* We can do 16-bit compare&swap */
22#define __HAVE_ARCH_CMPXCHG16 1
23
24typedef struct unw_frame_info frame_info_t;
25
26/*
27 * default PC resolution for this platform
28 */
29#define DFL_PC_RES 4
30
31#define supports_call_graph prof_have_mcount
32
33#define frame_get_pc(frame) ((frame)->ip)
34
35#define get_prof_freq() HZ
36
37extern void cg_record_arc(unsigned long, unsigned long);
38
39static void do_cg_record_arc(struct unw_frame_info *info, void *arg)
40{
41	unsigned long callee_ip, caller_ip;
42
43	/* First, get the frame for our backtrace_cg_record_arc() caller */
44	unw_get_ip(info, &caller_ip);
45	if (caller_ip == 0  ||  unw_unwind(info) < 0)
46		return;
47
48	/*
49	 * Next, get the frame for the next higher caller -- this is the
50	 * first interesting callee.
51	 */
52	unw_get_ip(info, &caller_ip);
53	if (caller_ip == 0  ||  unw_unwind(info) < 0)
54		return;
55
56	/* Now begin the iteration of walking further up the call graph */
57	do {
58		callee_ip = caller_ip;
59		unw_get_ip(info, &caller_ip);
60
61		if (caller_ip == 0)
62			break;
63
64		if (pc_out_of_range(caller_ip))
65			break;
66
67		cg_record_arc(caller_ip, callee_ip);
68
69	} while (unw_unwind(info) >= 0);
70}
71
72/*
73 *  Record the call graph, which is normally done by backtrace_cg_record_arc(),
74 *  and return 1 to indicate success.  We expect that backtrace_cg_record_arc()
75 *  will next call get_next_frame() and that will *fail*, leaving us with the
76 *  backtrace that do_cg_record_arc() has recorded (above).
77 *  Yes, this is a real hack.
78 */
79static __inline__ int build_fake_frame(frame_info_t *frame)
80{
81	unw_init_running(do_cg_record_arc, 0);
82	return 1;
83}
84
85static __inline__ unsigned long instruction_pointer(struct pt_regs *regs)
86{
87	return regs->cr_iip + (ia64_psr(regs)->ri << 2);
88}
89
90static __inline__ int in_firmware(struct pt_regs *regs)
91{
92	return 0;
93}
94
95static __inline__ void get_top_frame(struct pt_regs *regs, frame_info_t *frame)
96{
97	struct switch_stack *sw = (struct switch_stack *) regs - 1;
98	unw_init_frame_info(frame, current, sw);
99	/* skip over interrupt frame */
100	unw_unwind(frame);
101}
102
103static __inline__ int get_next_frame(frame_info_t *frame)
104{
105	return 0;
106}
107
108#define have_perfctr() 0
109#define valid_perfctr_event(e) 0
110#define valid_perfctr_freq(n) 0
111#define perfctr_reload(x)
112#define __perfctr_stop()
113#define __perfctr_commence(x,y)
114#define setup_profiling_timer(x) (-EINVAL)
115
116#endif /* __KERNEL__ */
117#endif /* !_ASM_KERNPROF_H */
118