1433d6423SLionel Sambuc /* The kernel call that is implemented in this file:
2433d6423SLionel Sambuc * m_type: SYS_SPROF
3433d6423SLionel Sambuc *
4433d6423SLionel Sambuc * The parameters for this kernel call are:
5433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.action (start/stop profiling)
6433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.mem_size (available memory for data)
7433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.freq (requested sample frequency)
8433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.endpt (endpoint of caller)
9433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.ctl_ptr (location of info struct)
10433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.mem_ptr (location of memory for data)
11433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.intr_type (interrupt source: RTC/NMI)
12433d6423SLionel Sambuc *
13433d6423SLionel Sambuc * Changes:
14433d6423SLionel Sambuc * 14 Aug, 2006 Created (Rogier Meurs)
15433d6423SLionel Sambuc */
16433d6423SLionel Sambuc
17433d6423SLionel Sambuc #include "kernel/system.h"
18433d6423SLionel Sambuc #include "kernel/watchdog.h"
19433d6423SLionel Sambuc
20433d6423SLionel Sambuc #if SPROFILE
21433d6423SLionel Sambuc
22433d6423SLionel Sambuc /* user address to write info struct */
23433d6423SLionel Sambuc static vir_bytes sprof_info_addr_vir;
24433d6423SLionel Sambuc
clean_seen_flag(void)25433d6423SLionel Sambuc static void clean_seen_flag(void)
26433d6423SLionel Sambuc {
27433d6423SLionel Sambuc int i;
28433d6423SLionel Sambuc
29433d6423SLionel Sambuc for (i = 0; i < NR_TASKS + NR_PROCS; i++)
30433d6423SLionel Sambuc proc[i].p_misc_flags &= ~MF_SPROF_SEEN;
31433d6423SLionel Sambuc }
32433d6423SLionel Sambuc
33433d6423SLionel Sambuc /*===========================================================================*
34433d6423SLionel Sambuc * do_sprofile *
35433d6423SLionel Sambuc *===========================================================================*/
do_sprofile(struct proc * caller,message * m_ptr)36433d6423SLionel Sambuc int do_sprofile(struct proc * caller, message * m_ptr)
37433d6423SLionel Sambuc {
38433d6423SLionel Sambuc int proc_nr;
39433d6423SLionel Sambuc int err;
40433d6423SLionel Sambuc
41433d6423SLionel Sambuc switch(m_ptr->m_lsys_krn_sys_sprof.action) {
42433d6423SLionel Sambuc
43433d6423SLionel Sambuc case PROF_START:
44433d6423SLionel Sambuc /* Starting profiling.
45433d6423SLionel Sambuc *
46433d6423SLionel Sambuc * Check if profiling is not already running. Calculate physical
47433d6423SLionel Sambuc * addresses of user pointers. Reset counters. Start CMOS timer.
48433d6423SLionel Sambuc * Turn on profiling.
49433d6423SLionel Sambuc */
50433d6423SLionel Sambuc if (sprofiling) {
51433d6423SLionel Sambuc printf("SYSTEM: start s-profiling: already started\n");
52433d6423SLionel Sambuc return EBUSY;
53433d6423SLionel Sambuc }
54433d6423SLionel Sambuc
55433d6423SLionel Sambuc /* Test endpoint number. */
56433d6423SLionel Sambuc if(!isokendpt(m_ptr->m_lsys_krn_sys_sprof.endpt, &proc_nr))
57433d6423SLionel Sambuc return EINVAL;
58433d6423SLionel Sambuc
59433d6423SLionel Sambuc /* Set parameters for statistical profiler. */
60433d6423SLionel Sambuc sprof_ep = m_ptr->m_lsys_krn_sys_sprof.endpt;
61433d6423SLionel Sambuc sprof_info_addr_vir = m_ptr->m_lsys_krn_sys_sprof.ctl_ptr;
62433d6423SLionel Sambuc sprof_data_addr_vir = m_ptr->m_lsys_krn_sys_sprof.mem_ptr;
63433d6423SLionel Sambuc
64433d6423SLionel Sambuc sprof_info.mem_used = 0;
65433d6423SLionel Sambuc sprof_info.total_samples = 0;
66433d6423SLionel Sambuc sprof_info.idle_samples = 0;
67433d6423SLionel Sambuc sprof_info.system_samples = 0;
68433d6423SLionel Sambuc sprof_info.user_samples = 0;
69433d6423SLionel Sambuc
70433d6423SLionel Sambuc sprof_mem_size =
71433d6423SLionel Sambuc m_ptr->m_lsys_krn_sys_sprof.mem_size < SAMPLE_BUFFER_SIZE ?
72433d6423SLionel Sambuc m_ptr->m_lsys_krn_sys_sprof.mem_size : SAMPLE_BUFFER_SIZE;
73433d6423SLionel Sambuc
74433d6423SLionel Sambuc switch (sprofiling_type = m_ptr->m_lsys_krn_sys_sprof.intr_type) {
75433d6423SLionel Sambuc case PROF_RTC:
76433d6423SLionel Sambuc init_profile_clock(m_ptr->m_lsys_krn_sys_sprof.freq);
77433d6423SLionel Sambuc break;
78433d6423SLionel Sambuc case PROF_NMI:
79433d6423SLionel Sambuc err = nmi_watchdog_start_profiling(
80*373b7939SDavid van Moolenbroek m_ptr->m_lsys_krn_sys_sprof.freq);
81433d6423SLionel Sambuc if (err)
82433d6423SLionel Sambuc return err;
83433d6423SLionel Sambuc break;
84433d6423SLionel Sambuc default:
85433d6423SLionel Sambuc printf("ERROR : unknown profiling interrupt type\n");
86433d6423SLionel Sambuc return EINVAL;
87433d6423SLionel Sambuc }
88433d6423SLionel Sambuc
89433d6423SLionel Sambuc sprofiling = 1;
90433d6423SLionel Sambuc
91433d6423SLionel Sambuc clean_seen_flag();
92433d6423SLionel Sambuc
93433d6423SLionel Sambuc return OK;
94433d6423SLionel Sambuc
95433d6423SLionel Sambuc case PROF_STOP:
96433d6423SLionel Sambuc /* Stopping profiling.
97433d6423SLionel Sambuc *
98433d6423SLionel Sambuc * Check if profiling is indeed running. Turn off profiling.
99433d6423SLionel Sambuc * Stop CMOS timer. Copy info struct to user process.
100433d6423SLionel Sambuc */
101433d6423SLionel Sambuc if (!sprofiling) {
102433d6423SLionel Sambuc printf("SYSTEM: stop s-profiling: not started\n");
103433d6423SLionel Sambuc return EBUSY;
104433d6423SLionel Sambuc }
105433d6423SLionel Sambuc
106433d6423SLionel Sambuc sprofiling = 0;
107433d6423SLionel Sambuc
108433d6423SLionel Sambuc switch (sprofiling_type) {
109433d6423SLionel Sambuc case PROF_RTC:
110433d6423SLionel Sambuc stop_profile_clock();
111433d6423SLionel Sambuc break;
112433d6423SLionel Sambuc case PROF_NMI:
113433d6423SLionel Sambuc nmi_watchdog_stop_profiling();
114433d6423SLionel Sambuc break;
115433d6423SLionel Sambuc }
116433d6423SLionel Sambuc
117433d6423SLionel Sambuc data_copy(KERNEL, (vir_bytes) &sprof_info,
118433d6423SLionel Sambuc sprof_ep, sprof_info_addr_vir, sizeof(sprof_info));
119433d6423SLionel Sambuc data_copy(KERNEL, (vir_bytes) sprof_sample_buffer,
120433d6423SLionel Sambuc sprof_ep, sprof_data_addr_vir, sprof_info.mem_used);
121433d6423SLionel Sambuc
122433d6423SLionel Sambuc clean_seen_flag();
123433d6423SLionel Sambuc
124433d6423SLionel Sambuc return OK;
125433d6423SLionel Sambuc
126433d6423SLionel Sambuc default:
127433d6423SLionel Sambuc return EINVAL;
128433d6423SLionel Sambuc }
129433d6423SLionel Sambuc }
130433d6423SLionel Sambuc
131433d6423SLionel Sambuc #endif /* SPROFILE */
132433d6423SLionel Sambuc
133