1*433d6423SLionel Sambuc /* The kernel call that is implemented in this file: 2*433d6423SLionel Sambuc * m_type: SYS_SPROF 3*433d6423SLionel Sambuc * 4*433d6423SLionel Sambuc * The parameters for this kernel call are: 5*433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.action (start/stop profiling) 6*433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.mem_size (available memory for data) 7*433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.freq (requested sample frequency) 8*433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.endpt (endpoint of caller) 9*433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.ctl_ptr (location of info struct) 10*433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.mem_ptr (location of memory for data) 11*433d6423SLionel Sambuc * m_lsys_krn_sys_sprof.intr_type (interrupt source: RTC/NMI) 12*433d6423SLionel Sambuc * 13*433d6423SLionel Sambuc * Changes: 14*433d6423SLionel Sambuc * 14 Aug, 2006 Created (Rogier Meurs) 15*433d6423SLionel Sambuc */ 16*433d6423SLionel Sambuc 17*433d6423SLionel Sambuc #include "kernel/system.h" 18*433d6423SLionel Sambuc #include "kernel/watchdog.h" 19*433d6423SLionel Sambuc 20*433d6423SLionel Sambuc #if SPROFILE 21*433d6423SLionel Sambuc 22*433d6423SLionel Sambuc /* user address to write info struct */ 23*433d6423SLionel Sambuc static vir_bytes sprof_info_addr_vir; 24*433d6423SLionel Sambuc 25*433d6423SLionel Sambuc static void clean_seen_flag(void) 26*433d6423SLionel Sambuc { 27*433d6423SLionel Sambuc int i; 28*433d6423SLionel Sambuc 29*433d6423SLionel Sambuc for (i = 0; i < NR_TASKS + NR_PROCS; i++) 30*433d6423SLionel Sambuc proc[i].p_misc_flags &= ~MF_SPROF_SEEN; 31*433d6423SLionel Sambuc } 32*433d6423SLionel Sambuc 33*433d6423SLionel Sambuc /*===========================================================================* 34*433d6423SLionel Sambuc * do_sprofile * 35*433d6423SLionel Sambuc *===========================================================================*/ 36*433d6423SLionel Sambuc int do_sprofile(struct proc * caller, message * m_ptr) 37*433d6423SLionel Sambuc { 38*433d6423SLionel Sambuc int proc_nr; 39*433d6423SLionel Sambuc int err; 40*433d6423SLionel Sambuc 41*433d6423SLionel Sambuc switch(m_ptr->m_lsys_krn_sys_sprof.action) { 42*433d6423SLionel Sambuc 43*433d6423SLionel Sambuc case PROF_START: 44*433d6423SLionel Sambuc /* Starting profiling. 45*433d6423SLionel Sambuc * 46*433d6423SLionel Sambuc * Check if profiling is not already running. Calculate physical 47*433d6423SLionel Sambuc * addresses of user pointers. Reset counters. Start CMOS timer. 48*433d6423SLionel Sambuc * Turn on profiling. 49*433d6423SLionel Sambuc */ 50*433d6423SLionel Sambuc if (sprofiling) { 51*433d6423SLionel Sambuc printf("SYSTEM: start s-profiling: already started\n"); 52*433d6423SLionel Sambuc return EBUSY; 53*433d6423SLionel Sambuc } 54*433d6423SLionel Sambuc 55*433d6423SLionel Sambuc /* Test endpoint number. */ 56*433d6423SLionel Sambuc if(!isokendpt(m_ptr->m_lsys_krn_sys_sprof.endpt, &proc_nr)) 57*433d6423SLionel Sambuc return EINVAL; 58*433d6423SLionel Sambuc 59*433d6423SLionel Sambuc /* Set parameters for statistical profiler. */ 60*433d6423SLionel Sambuc sprof_ep = m_ptr->m_lsys_krn_sys_sprof.endpt; 61*433d6423SLionel Sambuc sprof_info_addr_vir = m_ptr->m_lsys_krn_sys_sprof.ctl_ptr; 62*433d6423SLionel Sambuc sprof_data_addr_vir = m_ptr->m_lsys_krn_sys_sprof.mem_ptr; 63*433d6423SLionel Sambuc 64*433d6423SLionel Sambuc sprof_info.mem_used = 0; 65*433d6423SLionel Sambuc sprof_info.total_samples = 0; 66*433d6423SLionel Sambuc sprof_info.idle_samples = 0; 67*433d6423SLionel Sambuc sprof_info.system_samples = 0; 68*433d6423SLionel Sambuc sprof_info.user_samples = 0; 69*433d6423SLionel Sambuc 70*433d6423SLionel Sambuc sprof_mem_size = 71*433d6423SLionel Sambuc m_ptr->m_lsys_krn_sys_sprof.mem_size < SAMPLE_BUFFER_SIZE ? 72*433d6423SLionel Sambuc m_ptr->m_lsys_krn_sys_sprof.mem_size : SAMPLE_BUFFER_SIZE; 73*433d6423SLionel Sambuc 74*433d6423SLionel Sambuc switch (sprofiling_type = m_ptr->m_lsys_krn_sys_sprof.intr_type) { 75*433d6423SLionel Sambuc case PROF_RTC: 76*433d6423SLionel Sambuc init_profile_clock(m_ptr->m_lsys_krn_sys_sprof.freq); 77*433d6423SLionel Sambuc break; 78*433d6423SLionel Sambuc case PROF_NMI: 79*433d6423SLionel Sambuc err = nmi_watchdog_start_profiling( 80*433d6423SLionel Sambuc _ptr->m_lsys_krn_sys_sprof.freq); 81*433d6423SLionel Sambuc if (err) 82*433d6423SLionel Sambuc return err; 83*433d6423SLionel Sambuc break; 84*433d6423SLionel Sambuc default: 85*433d6423SLionel Sambuc printf("ERROR : unknown profiling interrupt type\n"); 86*433d6423SLionel Sambuc return EINVAL; 87*433d6423SLionel Sambuc } 88*433d6423SLionel Sambuc 89*433d6423SLionel Sambuc sprofiling = 1; 90*433d6423SLionel Sambuc 91*433d6423SLionel Sambuc clean_seen_flag(); 92*433d6423SLionel Sambuc 93*433d6423SLionel Sambuc return OK; 94*433d6423SLionel Sambuc 95*433d6423SLionel Sambuc case PROF_STOP: 96*433d6423SLionel Sambuc /* Stopping profiling. 97*433d6423SLionel Sambuc * 98*433d6423SLionel Sambuc * Check if profiling is indeed running. Turn off profiling. 99*433d6423SLionel Sambuc * Stop CMOS timer. Copy info struct to user process. 100*433d6423SLionel Sambuc */ 101*433d6423SLionel Sambuc if (!sprofiling) { 102*433d6423SLionel Sambuc printf("SYSTEM: stop s-profiling: not started\n"); 103*433d6423SLionel Sambuc return EBUSY; 104*433d6423SLionel Sambuc } 105*433d6423SLionel Sambuc 106*433d6423SLionel Sambuc sprofiling = 0; 107*433d6423SLionel Sambuc 108*433d6423SLionel Sambuc switch (sprofiling_type) { 109*433d6423SLionel Sambuc case PROF_RTC: 110*433d6423SLionel Sambuc stop_profile_clock(); 111*433d6423SLionel Sambuc break; 112*433d6423SLionel Sambuc case PROF_NMI: 113*433d6423SLionel Sambuc nmi_watchdog_stop_profiling(); 114*433d6423SLionel Sambuc break; 115*433d6423SLionel Sambuc } 116*433d6423SLionel Sambuc 117*433d6423SLionel Sambuc data_copy(KERNEL, (vir_bytes) &sprof_info, 118*433d6423SLionel Sambuc sprof_ep, sprof_info_addr_vir, sizeof(sprof_info)); 119*433d6423SLionel Sambuc data_copy(KERNEL, (vir_bytes) sprof_sample_buffer, 120*433d6423SLionel Sambuc sprof_ep, sprof_data_addr_vir, sprof_info.mem_used); 121*433d6423SLionel Sambuc 122*433d6423SLionel Sambuc clean_seen_flag(); 123*433d6423SLionel Sambuc 124*433d6423SLionel Sambuc return OK; 125*433d6423SLionel Sambuc 126*433d6423SLionel Sambuc default: 127*433d6423SLionel Sambuc return EINVAL; 128*433d6423SLionel Sambuc } 129*433d6423SLionel Sambuc } 130*433d6423SLionel Sambuc 131*433d6423SLionel Sambuc #endif /* SPROFILE */ 132*433d6423SLionel Sambuc 133