perfmon_default_smpl.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /*
  2. * Copyright (C) 2002-2003 Hewlett-Packard Co
  3. * Stephane Eranian <eranian@hpl.hp.com>
  4. *
  5. * This file implements the default sampling buffer format
  6. * for the Linux/ia64 perfmon-2 subsystem.
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/types.h>
  10. #include <linux/module.h>
  11. #include <linux/config.h>
  12. #include <linux/init.h>
  13. #include <asm/delay.h>
  14. #include <linux/smp.h>
  15. #include <asm/perfmon.h>
  16. #include <asm/perfmon_default_smpl.h>
  17. MODULE_AUTHOR("Stephane Eranian <eranian@hpl.hp.com>");
  18. MODULE_DESCRIPTION("perfmon default sampling format");
  19. MODULE_LICENSE("GPL");
  20. MODULE_PARM(debug, "i");
  21. MODULE_PARM_DESC(debug, "debug");
  22. MODULE_PARM(debug_ovfl, "i");
  23. MODULE_PARM_DESC(debug_ovfl, "debug ovfl");
  24. #define DEFAULT_DEBUG 1
  25. #ifdef DEFAULT_DEBUG
  26. #define DPRINT(a) \
  27. do { \
  28. if (unlikely(debug >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \
  29. } while (0)
  30. #define DPRINT_ovfl(a) \
  31. do { \
  32. if (unlikely(debug_ovfl >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \
  33. } while (0)
  34. #else
  35. #define DPRINT(a)
  36. #define DPRINT_ovfl(a)
  37. #endif
  38. static int debug, debug_ovfl;
  39. static int
  40. default_validate(struct task_struct *task, unsigned int flags, int cpu, void *data)
  41. {
  42. pfm_default_smpl_arg_t *arg = (pfm_default_smpl_arg_t*)data;
  43. int ret = 0;
  44. if (data == NULL) {
  45. DPRINT(("[%d] no argument passed\n", task->pid));
  46. return -EINVAL;
  47. }
  48. DPRINT(("[%d] validate flags=0x%x CPU%d\n", task->pid, flags, cpu));
  49. /*
  50. * must hold at least the buffer header + one minimally sized entry
  51. */
  52. if (arg->buf_size < PFM_DEFAULT_SMPL_MIN_BUF_SIZE) return -EINVAL;
  53. DPRINT(("buf_size=%lu\n", arg->buf_size));
  54. return ret;
  55. }
  56. static int
  57. default_get_size(struct task_struct *task, unsigned int flags, int cpu, void *data, unsigned long *size)
  58. {
  59. pfm_default_smpl_arg_t *arg = (pfm_default_smpl_arg_t *)data;
  60. /*
  61. * size has been validated in default_validate
  62. */
  63. *size = arg->buf_size;
  64. return 0;
  65. }
  66. static int
  67. default_init(struct task_struct *task, void *buf, unsigned int flags, int cpu, void *data)
  68. {
  69. pfm_default_smpl_hdr_t *hdr;
  70. pfm_default_smpl_arg_t *arg = (pfm_default_smpl_arg_t *)data;
  71. hdr = (pfm_default_smpl_hdr_t *)buf;
  72. hdr->hdr_version = PFM_DEFAULT_SMPL_VERSION;
  73. hdr->hdr_buf_size = arg->buf_size;
  74. hdr->hdr_cur_offs = sizeof(*hdr);
  75. hdr->hdr_overflows = 0UL;
  76. hdr->hdr_count = 0UL;
  77. DPRINT(("[%d] buffer=%p buf_size=%lu hdr_size=%lu hdr_version=%u cur_offs=%lu\n",
  78. task->pid,
  79. buf,
  80. hdr->hdr_buf_size,
  81. sizeof(*hdr),
  82. hdr->hdr_version,
  83. hdr->hdr_cur_offs));
  84. return 0;
  85. }
  86. static int
  87. default_handler(struct task_struct *task, void *buf, pfm_ovfl_arg_t *arg, struct pt_regs *regs, unsigned long stamp)
  88. {
  89. pfm_default_smpl_hdr_t *hdr;
  90. pfm_default_smpl_entry_t *ent;
  91. void *cur, *last;
  92. unsigned long *e, entry_size;
  93. unsigned int npmds, i;
  94. unsigned char ovfl_pmd;
  95. unsigned char ovfl_notify;
  96. if (unlikely(buf == NULL || arg == NULL|| regs == NULL || task == NULL)) {
  97. DPRINT(("[%d] invalid arguments buf=%p arg=%p\n", task->pid, buf, arg));
  98. return -EINVAL;
  99. }
  100. hdr = (pfm_default_smpl_hdr_t *)buf;
  101. cur = buf+hdr->hdr_cur_offs;
  102. last = buf+hdr->hdr_buf_size;
  103. ovfl_pmd = arg->ovfl_pmd;
  104. ovfl_notify = arg->ovfl_notify;
  105. /*
  106. * precheck for sanity
  107. */
  108. if ((last - cur) < PFM_DEFAULT_MAX_ENTRY_SIZE) goto full;
  109. npmds = hweight64(arg->smpl_pmds[0]);
  110. ent = (pfm_default_smpl_entry_t *)cur;
  111. prefetch(arg->smpl_pmds_values);
  112. entry_size = sizeof(*ent) + (npmds << 3);
  113. /* position for first pmd */
  114. e = (unsigned long *)(ent+1);
  115. hdr->hdr_count++;
  116. DPRINT_ovfl(("[%d] count=%lu cur=%p last=%p free_bytes=%lu ovfl_pmd=%d ovfl_notify=%d npmds=%u\n",
  117. task->pid,
  118. hdr->hdr_count,
  119. cur, last,
  120. last-cur,
  121. ovfl_pmd,
  122. ovfl_notify, npmds));
  123. /*
  124. * current = task running at the time of the overflow.
  125. *
  126. * per-task mode:
  127. * - this is ususally the task being monitored.
  128. * Under certain conditions, it might be a different task
  129. *
  130. * system-wide:
  131. * - this is not necessarily the task controlling the session
  132. */
  133. ent->pid = current->pid;
  134. ent->ovfl_pmd = ovfl_pmd;
  135. ent->last_reset_val = arg->pmd_last_reset; //pmd[0].reg_last_reset_val;
  136. /*
  137. * where did the fault happen (includes slot number)
  138. */
  139. ent->ip = regs->cr_iip | ((regs->cr_ipsr >> 41) & 0x3);
  140. ent->tstamp = stamp;
  141. ent->cpu = smp_processor_id();
  142. ent->set = arg->active_set;
  143. ent->tgid = current->tgid;
  144. /*
  145. * selectively store PMDs in increasing index number
  146. */
  147. if (npmds) {
  148. unsigned long *val = arg->smpl_pmds_values;
  149. for(i=0; i < npmds; i++) {
  150. *e++ = *val++;
  151. }
  152. }
  153. /*
  154. * update position for next entry
  155. */
  156. hdr->hdr_cur_offs += entry_size;
  157. cur += entry_size;
  158. /*
  159. * post check to avoid losing the last sample
  160. */
  161. if ((last - cur) < PFM_DEFAULT_MAX_ENTRY_SIZE) goto full;
  162. /*
  163. * keep same ovfl_pmds, ovfl_notify
  164. */
  165. arg->ovfl_ctrl.bits.notify_user = 0;
  166. arg->ovfl_ctrl.bits.block_task = 0;
  167. arg->ovfl_ctrl.bits.mask_monitoring = 0;
  168. arg->ovfl_ctrl.bits.reset_ovfl_pmds = 1; /* reset before returning from interrupt handler */
  169. return 0;
  170. full:
  171. DPRINT_ovfl(("sampling buffer full free=%lu, count=%lu, ovfl_notify=%d\n", last-cur, hdr->hdr_count, ovfl_notify));
  172. /*
  173. * increment number of buffer overflow.
  174. * important to detect duplicate set of samples.
  175. */
  176. hdr->hdr_overflows++;
  177. /*
  178. * if no notification requested, then we saturate the buffer
  179. */
  180. if (ovfl_notify == 0) {
  181. arg->ovfl_ctrl.bits.notify_user = 0;
  182. arg->ovfl_ctrl.bits.block_task = 0;
  183. arg->ovfl_ctrl.bits.mask_monitoring = 1;
  184. arg->ovfl_ctrl.bits.reset_ovfl_pmds = 0;
  185. } else {
  186. arg->ovfl_ctrl.bits.notify_user = 1;
  187. arg->ovfl_ctrl.bits.block_task = 1; /* ignored for non-blocking context */
  188. arg->ovfl_ctrl.bits.mask_monitoring = 1;
  189. arg->ovfl_ctrl.bits.reset_ovfl_pmds = 0; /* no reset now */
  190. }
  191. return -1; /* we are full, sorry */
  192. }
  193. static int
  194. default_restart(struct task_struct *task, pfm_ovfl_ctrl_t *ctrl, void *buf, struct pt_regs *regs)
  195. {
  196. pfm_default_smpl_hdr_t *hdr;
  197. hdr = (pfm_default_smpl_hdr_t *)buf;
  198. hdr->hdr_count = 0UL;
  199. hdr->hdr_cur_offs = sizeof(*hdr);
  200. ctrl->bits.mask_monitoring = 0;
  201. ctrl->bits.reset_ovfl_pmds = 1; /* uses long-reset values */
  202. return 0;
  203. }
  204. static int
  205. default_exit(struct task_struct *task, void *buf, struct pt_regs *regs)
  206. {
  207. DPRINT(("[%d] exit(%p)\n", task->pid, buf));
  208. return 0;
  209. }
  210. static pfm_buffer_fmt_t default_fmt={
  211. .fmt_name = "default_format",
  212. .fmt_uuid = PFM_DEFAULT_SMPL_UUID,
  213. .fmt_arg_size = sizeof(pfm_default_smpl_arg_t),
  214. .fmt_validate = default_validate,
  215. .fmt_getsize = default_get_size,
  216. .fmt_init = default_init,
  217. .fmt_handler = default_handler,
  218. .fmt_restart = default_restart,
  219. .fmt_restart_active = default_restart,
  220. .fmt_exit = default_exit,
  221. };
  222. static int __init
  223. pfm_default_smpl_init_module(void)
  224. {
  225. int ret;
  226. ret = pfm_register_buffer_fmt(&default_fmt);
  227. if (ret == 0) {
  228. printk("perfmon_default_smpl: %s v%u.%u registered\n",
  229. default_fmt.fmt_name,
  230. PFM_DEFAULT_SMPL_VERSION_MAJ,
  231. PFM_DEFAULT_SMPL_VERSION_MIN);
  232. } else {
  233. printk("perfmon_default_smpl: %s cannot register ret=%d\n",
  234. default_fmt.fmt_name,
  235. ret);
  236. }
  237. return ret;
  238. }
  239. static void __exit
  240. pfm_default_smpl_cleanup_module(void)
  241. {
  242. int ret;
  243. ret = pfm_unregister_buffer_fmt(default_fmt.fmt_uuid);
  244. printk("perfmon_default_smpl: unregister %s=%d\n", default_fmt.fmt_name, ret);
  245. }
  246. module_init(pfm_default_smpl_init_module);
  247. module_exit(pfm_default_smpl_cleanup_module);