trace_osnoise.c 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * OS Noise Tracer: computes the OS Noise suffered by a running thread.
  4. * Timerlat Tracer: measures the wakeup latency of a timer triggered IRQ and thread.
  5. *
  6. * Based on "hwlat_detector" tracer by:
  7. * Copyright (C) 2008-2009 Jon Masters, Red Hat, Inc. <[email protected]>
  8. * Copyright (C) 2013-2016 Steven Rostedt, Red Hat, Inc. <[email protected]>
  9. * With feedback from Clark Williams <[email protected]>
  10. *
  11. * And also based on the rtsl tracer presented on:
  12. * DE OLIVEIRA, Daniel Bristot, et al. Demystifying the real-time linux
  13. * scheduling latency. In: 32nd Euromicro Conference on Real-Time Systems
  14. * (ECRTS 2020). Schloss Dagstuhl-Leibniz-Zentrum fur Informatik, 2020.
  15. *
  16. * Copyright (C) 2021 Daniel Bristot de Oliveira, Red Hat, Inc. <[email protected]>
  17. */
  18. #include <linux/kthread.h>
  19. #include <linux/tracefs.h>
  20. #include <linux/uaccess.h>
  21. #include <linux/cpumask.h>
  22. #include <linux/delay.h>
  23. #include <linux/sched/clock.h>
  24. #include <uapi/linux/sched/types.h>
  25. #include <linux/sched.h>
  26. #include "trace.h"
  27. #ifdef CONFIG_X86_LOCAL_APIC
  28. #include <asm/trace/irq_vectors.h>
  29. #undef TRACE_INCLUDE_PATH
  30. #undef TRACE_INCLUDE_FILE
  31. #endif /* CONFIG_X86_LOCAL_APIC */
  32. #include <trace/events/irq.h>
  33. #include <trace/events/sched.h>
  34. #define CREATE_TRACE_POINTS
  35. #include <trace/events/osnoise.h>
  36. /*
  37. * Default values.
  38. */
  39. #define BANNER "osnoise: "
  40. #define DEFAULT_SAMPLE_PERIOD 1000000 /* 1s */
  41. #define DEFAULT_SAMPLE_RUNTIME 1000000 /* 1s */
  42. #define DEFAULT_TIMERLAT_PERIOD 1000 /* 1ms */
  43. #define DEFAULT_TIMERLAT_PRIO 95 /* FIFO 95 */
  44. /*
  45. * trace_array of the enabled osnoise/timerlat instances.
  46. */
  47. struct osnoise_instance {
  48. struct list_head list;
  49. struct trace_array *tr;
  50. };
  51. static struct list_head osnoise_instances;
  52. static bool osnoise_has_registered_instances(void)
  53. {
  54. return !!list_first_or_null_rcu(&osnoise_instances,
  55. struct osnoise_instance,
  56. list);
  57. }
  58. /*
  59. * osnoise_instance_registered - check if a tr is already registered
  60. */
  61. static int osnoise_instance_registered(struct trace_array *tr)
  62. {
  63. struct osnoise_instance *inst;
  64. int found = 0;
  65. rcu_read_lock();
  66. list_for_each_entry_rcu(inst, &osnoise_instances, list) {
  67. if (inst->tr == tr)
  68. found = 1;
  69. }
  70. rcu_read_unlock();
  71. return found;
  72. }
  73. /*
  74. * osnoise_register_instance - register a new trace instance
  75. *
  76. * Register a trace_array *tr in the list of instances running
  77. * osnoise/timerlat tracers.
  78. */
  79. static int osnoise_register_instance(struct trace_array *tr)
  80. {
  81. struct osnoise_instance *inst;
  82. /*
  83. * register/unregister serialization is provided by trace's
  84. * trace_types_lock.
  85. */
  86. lockdep_assert_held(&trace_types_lock);
  87. inst = kmalloc(sizeof(*inst), GFP_KERNEL);
  88. if (!inst)
  89. return -ENOMEM;
  90. INIT_LIST_HEAD_RCU(&inst->list);
  91. inst->tr = tr;
  92. list_add_tail_rcu(&inst->list, &osnoise_instances);
  93. return 0;
  94. }
  95. /*
  96. * osnoise_unregister_instance - unregister a registered trace instance
  97. *
  98. * Remove the trace_array *tr from the list of instances running
  99. * osnoise/timerlat tracers.
  100. */
  101. static void osnoise_unregister_instance(struct trace_array *tr)
  102. {
  103. struct osnoise_instance *inst;
  104. int found = 0;
  105. /*
  106. * register/unregister serialization is provided by trace's
  107. * trace_types_lock.
  108. */
  109. list_for_each_entry_rcu(inst, &osnoise_instances, list,
  110. lockdep_is_held(&trace_types_lock)) {
  111. if (inst->tr == tr) {
  112. list_del_rcu(&inst->list);
  113. found = 1;
  114. break;
  115. }
  116. }
  117. if (!found)
  118. return;
  119. kvfree_rcu(inst);
  120. }
  121. /*
  122. * NMI runtime info.
  123. */
  124. struct osn_nmi {
  125. u64 count;
  126. u64 delta_start;
  127. };
  128. /*
  129. * IRQ runtime info.
  130. */
  131. struct osn_irq {
  132. u64 count;
  133. u64 arrival_time;
  134. u64 delta_start;
  135. };
  136. #define IRQ_CONTEXT 0
  137. #define THREAD_CONTEXT 1
  138. /*
  139. * sofirq runtime info.
  140. */
  141. struct osn_softirq {
  142. u64 count;
  143. u64 arrival_time;
  144. u64 delta_start;
  145. };
  146. /*
  147. * thread runtime info.
  148. */
  149. struct osn_thread {
  150. u64 count;
  151. u64 arrival_time;
  152. u64 delta_start;
  153. };
  154. /*
  155. * Runtime information: this structure saves the runtime information used by
  156. * one sampling thread.
  157. */
  158. struct osnoise_variables {
  159. struct task_struct *kthread;
  160. bool sampling;
  161. pid_t pid;
  162. struct osn_nmi nmi;
  163. struct osn_irq irq;
  164. struct osn_softirq softirq;
  165. struct osn_thread thread;
  166. local_t int_counter;
  167. };
  168. /*
  169. * Per-cpu runtime information.
  170. */
  171. DEFINE_PER_CPU(struct osnoise_variables, per_cpu_osnoise_var);
  172. /*
  173. * this_cpu_osn_var - Return the per-cpu osnoise_variables on its relative CPU
  174. */
  175. static inline struct osnoise_variables *this_cpu_osn_var(void)
  176. {
  177. return this_cpu_ptr(&per_cpu_osnoise_var);
  178. }
  179. #ifdef CONFIG_TIMERLAT_TRACER
  180. /*
  181. * Runtime information for the timer mode.
  182. */
  183. struct timerlat_variables {
  184. struct task_struct *kthread;
  185. struct hrtimer timer;
  186. u64 rel_period;
  187. u64 abs_period;
  188. bool tracing_thread;
  189. u64 count;
  190. };
  191. DEFINE_PER_CPU(struct timerlat_variables, per_cpu_timerlat_var);
  192. /*
  193. * this_cpu_tmr_var - Return the per-cpu timerlat_variables on its relative CPU
  194. */
  195. static inline struct timerlat_variables *this_cpu_tmr_var(void)
  196. {
  197. return this_cpu_ptr(&per_cpu_timerlat_var);
  198. }
  199. /*
  200. * tlat_var_reset - Reset the values of the given timerlat_variables
  201. */
  202. static inline void tlat_var_reset(void)
  203. {
  204. struct timerlat_variables *tlat_var;
  205. int cpu;
  206. /*
  207. * So far, all the values are initialized as 0, so
  208. * zeroing the structure is perfect.
  209. */
  210. for_each_cpu(cpu, cpu_online_mask) {
  211. tlat_var = per_cpu_ptr(&per_cpu_timerlat_var, cpu);
  212. memset(tlat_var, 0, sizeof(*tlat_var));
  213. }
  214. }
  215. #else /* CONFIG_TIMERLAT_TRACER */
  216. #define tlat_var_reset() do {} while (0)
  217. #endif /* CONFIG_TIMERLAT_TRACER */
  218. /*
  219. * osn_var_reset - Reset the values of the given osnoise_variables
  220. */
  221. static inline void osn_var_reset(void)
  222. {
  223. struct osnoise_variables *osn_var;
  224. int cpu;
  225. /*
  226. * So far, all the values are initialized as 0, so
  227. * zeroing the structure is perfect.
  228. */
  229. for_each_cpu(cpu, cpu_online_mask) {
  230. osn_var = per_cpu_ptr(&per_cpu_osnoise_var, cpu);
  231. memset(osn_var, 0, sizeof(*osn_var));
  232. }
  233. }
  234. /*
  235. * osn_var_reset_all - Reset the value of all per-cpu osnoise_variables
  236. */
  237. static inline void osn_var_reset_all(void)
  238. {
  239. osn_var_reset();
  240. tlat_var_reset();
  241. }
  242. /*
  243. * Tells NMIs to call back to the osnoise tracer to record timestamps.
  244. */
  245. bool trace_osnoise_callback_enabled;
  246. /*
  247. * osnoise sample structure definition. Used to store the statistics of a
  248. * sample run.
  249. */
  250. struct osnoise_sample {
  251. u64 runtime; /* runtime */
  252. u64 noise; /* noise */
  253. u64 max_sample; /* max single noise sample */
  254. int hw_count; /* # HW (incl. hypervisor) interference */
  255. int nmi_count; /* # NMIs during this sample */
  256. int irq_count; /* # IRQs during this sample */
  257. int softirq_count; /* # softirqs during this sample */
  258. int thread_count; /* # threads during this sample */
  259. };
  260. #ifdef CONFIG_TIMERLAT_TRACER
  261. /*
  262. * timerlat sample structure definition. Used to store the statistics of
  263. * a sample run.
  264. */
  265. struct timerlat_sample {
  266. u64 timer_latency; /* timer_latency */
  267. unsigned int seqnum; /* unique sequence */
  268. int context; /* timer context */
  269. };
  270. #endif
  271. /*
  272. * Protect the interface.
  273. */
  274. struct mutex interface_lock;
  275. /*
  276. * Tracer data.
  277. */
  278. static struct osnoise_data {
  279. u64 sample_period; /* total sampling period */
  280. u64 sample_runtime; /* active sampling portion of period */
  281. u64 stop_tracing; /* stop trace in the internal operation (loop/irq) */
  282. u64 stop_tracing_total; /* stop trace in the final operation (report/thread) */
  283. #ifdef CONFIG_TIMERLAT_TRACER
  284. u64 timerlat_period; /* timerlat period */
  285. u64 print_stack; /* print IRQ stack if total > */
  286. int timerlat_tracer; /* timerlat tracer */
  287. #endif
  288. bool tainted; /* infor users and developers about a problem */
  289. } osnoise_data = {
  290. .sample_period = DEFAULT_SAMPLE_PERIOD,
  291. .sample_runtime = DEFAULT_SAMPLE_RUNTIME,
  292. .stop_tracing = 0,
  293. .stop_tracing_total = 0,
  294. #ifdef CONFIG_TIMERLAT_TRACER
  295. .print_stack = 0,
  296. .timerlat_period = DEFAULT_TIMERLAT_PERIOD,
  297. .timerlat_tracer = 0,
  298. #endif
  299. };
  300. #ifdef CONFIG_TIMERLAT_TRACER
  301. static inline bool timerlat_enabled(void)
  302. {
  303. return osnoise_data.timerlat_tracer;
  304. }
  305. static inline int timerlat_softirq_exit(struct osnoise_variables *osn_var)
  306. {
  307. struct timerlat_variables *tlat_var = this_cpu_tmr_var();
  308. /*
  309. * If the timerlat is enabled, but the irq handler did
  310. * not run yet enabling timerlat_tracer, do not trace.
  311. */
  312. if (!tlat_var->tracing_thread) {
  313. osn_var->softirq.arrival_time = 0;
  314. osn_var->softirq.delta_start = 0;
  315. return 0;
  316. }
  317. return 1;
  318. }
  319. static inline int timerlat_thread_exit(struct osnoise_variables *osn_var)
  320. {
  321. struct timerlat_variables *tlat_var = this_cpu_tmr_var();
  322. /*
  323. * If the timerlat is enabled, but the irq handler did
  324. * not run yet enabling timerlat_tracer, do not trace.
  325. */
  326. if (!tlat_var->tracing_thread) {
  327. osn_var->thread.delta_start = 0;
  328. osn_var->thread.arrival_time = 0;
  329. return 0;
  330. }
  331. return 1;
  332. }
  333. #else /* CONFIG_TIMERLAT_TRACER */
  334. static inline bool timerlat_enabled(void)
  335. {
  336. return false;
  337. }
  338. static inline int timerlat_softirq_exit(struct osnoise_variables *osn_var)
  339. {
  340. return 1;
  341. }
  342. static inline int timerlat_thread_exit(struct osnoise_variables *osn_var)
  343. {
  344. return 1;
  345. }
  346. #endif
  347. #ifdef CONFIG_PREEMPT_RT
  348. /*
  349. * Print the osnoise header info.
  350. */
  351. static void print_osnoise_headers(struct seq_file *s)
  352. {
  353. if (osnoise_data.tainted)
  354. seq_puts(s, "# osnoise is tainted!\n");
  355. seq_puts(s, "# _-------=> irqs-off\n");
  356. seq_puts(s, "# / _------=> need-resched\n");
  357. seq_puts(s, "# | / _-----=> need-resched-lazy\n");
  358. seq_puts(s, "# || / _----=> hardirq/softirq\n");
  359. seq_puts(s, "# ||| / _---=> preempt-depth\n");
  360. seq_puts(s, "# |||| / _--=> preempt-lazy-depth\n");
  361. seq_puts(s, "# ||||| / _-=> migrate-disable\n");
  362. seq_puts(s, "# |||||| / ");
  363. seq_puts(s, " MAX\n");
  364. seq_puts(s, "# ||||| / ");
  365. seq_puts(s, " SINGLE Interference counters:\n");
  366. seq_puts(s, "# ||||||| RUNTIME ");
  367. seq_puts(s, " NOISE %% OF CPU NOISE +-----------------------------+\n");
  368. seq_puts(s, "# TASK-PID CPU# ||||||| TIMESTAMP IN US ");
  369. seq_puts(s, " IN US AVAILABLE IN US HW NMI IRQ SIRQ THREAD\n");
  370. seq_puts(s, "# | | | ||||||| | | ");
  371. seq_puts(s, " | | | | | | | |\n");
  372. }
  373. #else /* CONFIG_PREEMPT_RT */
  374. static void print_osnoise_headers(struct seq_file *s)
  375. {
  376. if (osnoise_data.tainted)
  377. seq_puts(s, "# osnoise is tainted!\n");
  378. seq_puts(s, "# _-----=> irqs-off\n");
  379. seq_puts(s, "# / _----=> need-resched\n");
  380. seq_puts(s, "# | / _---=> hardirq/softirq\n");
  381. seq_puts(s, "# || / _--=> preempt-depth\n");
  382. seq_puts(s, "# ||| / _-=> migrate-disable ");
  383. seq_puts(s, " MAX\n");
  384. seq_puts(s, "# |||| / delay ");
  385. seq_puts(s, " SINGLE Interference counters:\n");
  386. seq_puts(s, "# ||||| RUNTIME ");
  387. seq_puts(s, " NOISE %% OF CPU NOISE +-----------------------------+\n");
  388. seq_puts(s, "# TASK-PID CPU# ||||| TIMESTAMP IN US ");
  389. seq_puts(s, " IN US AVAILABLE IN US HW NMI IRQ SIRQ THREAD\n");
  390. seq_puts(s, "# | | | ||||| | | ");
  391. seq_puts(s, " | | | | | | | |\n");
  392. }
  393. #endif /* CONFIG_PREEMPT_RT */
  394. /*
  395. * osnoise_taint - report an osnoise error.
  396. */
  397. #define osnoise_taint(msg) ({ \
  398. struct osnoise_instance *inst; \
  399. struct trace_buffer *buffer; \
  400. \
  401. rcu_read_lock(); \
  402. list_for_each_entry_rcu(inst, &osnoise_instances, list) { \
  403. buffer = inst->tr->array_buffer.buffer; \
  404. trace_array_printk_buf(buffer, _THIS_IP_, msg); \
  405. } \
  406. rcu_read_unlock(); \
  407. osnoise_data.tainted = true; \
  408. })
  409. /*
  410. * Record an osnoise_sample into the tracer buffer.
  411. */
  412. static void
  413. __trace_osnoise_sample(struct osnoise_sample *sample, struct trace_buffer *buffer)
  414. {
  415. struct trace_event_call *call = &event_osnoise;
  416. struct ring_buffer_event *event;
  417. struct osnoise_entry *entry;
  418. event = trace_buffer_lock_reserve(buffer, TRACE_OSNOISE, sizeof(*entry),
  419. tracing_gen_ctx());
  420. if (!event)
  421. return;
  422. entry = ring_buffer_event_data(event);
  423. entry->runtime = sample->runtime;
  424. entry->noise = sample->noise;
  425. entry->max_sample = sample->max_sample;
  426. entry->hw_count = sample->hw_count;
  427. entry->nmi_count = sample->nmi_count;
  428. entry->irq_count = sample->irq_count;
  429. entry->softirq_count = sample->softirq_count;
  430. entry->thread_count = sample->thread_count;
  431. if (!call_filter_check_discard(call, entry, buffer, event))
  432. trace_buffer_unlock_commit_nostack(buffer, event);
  433. }
  434. /*
  435. * Record an osnoise_sample on all osnoise instances.
  436. */
  437. static void trace_osnoise_sample(struct osnoise_sample *sample)
  438. {
  439. struct osnoise_instance *inst;
  440. struct trace_buffer *buffer;
  441. rcu_read_lock();
  442. list_for_each_entry_rcu(inst, &osnoise_instances, list) {
  443. buffer = inst->tr->array_buffer.buffer;
  444. __trace_osnoise_sample(sample, buffer);
  445. }
  446. rcu_read_unlock();
  447. }
  448. #ifdef CONFIG_TIMERLAT_TRACER
  449. /*
  450. * Print the timerlat header info.
  451. */
  452. #ifdef CONFIG_PREEMPT_RT
  453. static void print_timerlat_headers(struct seq_file *s)
  454. {
  455. seq_puts(s, "# _-------=> irqs-off\n");
  456. seq_puts(s, "# / _------=> need-resched\n");
  457. seq_puts(s, "# | / _-----=> need-resched-lazy\n");
  458. seq_puts(s, "# || / _----=> hardirq/softirq\n");
  459. seq_puts(s, "# ||| / _---=> preempt-depth\n");
  460. seq_puts(s, "# |||| / _--=> preempt-lazy-depth\n");
  461. seq_puts(s, "# ||||| / _-=> migrate-disable\n");
  462. seq_puts(s, "# |||||| /\n");
  463. seq_puts(s, "# ||||||| ACTIVATION\n");
  464. seq_puts(s, "# TASK-PID CPU# ||||||| TIMESTAMP ID ");
  465. seq_puts(s, " CONTEXT LATENCY\n");
  466. seq_puts(s, "# | | | ||||||| | | ");
  467. seq_puts(s, " | |\n");
  468. }
  469. #else /* CONFIG_PREEMPT_RT */
  470. static void print_timerlat_headers(struct seq_file *s)
  471. {
  472. seq_puts(s, "# _-----=> irqs-off\n");
  473. seq_puts(s, "# / _----=> need-resched\n");
  474. seq_puts(s, "# | / _---=> hardirq/softirq\n");
  475. seq_puts(s, "# || / _--=> preempt-depth\n");
  476. seq_puts(s, "# ||| / _-=> migrate-disable\n");
  477. seq_puts(s, "# |||| / delay\n");
  478. seq_puts(s, "# ||||| ACTIVATION\n");
  479. seq_puts(s, "# TASK-PID CPU# ||||| TIMESTAMP ID ");
  480. seq_puts(s, " CONTEXT LATENCY\n");
  481. seq_puts(s, "# | | | ||||| | | ");
  482. seq_puts(s, " | |\n");
  483. }
  484. #endif /* CONFIG_PREEMPT_RT */
  485. static void
  486. __trace_timerlat_sample(struct timerlat_sample *sample, struct trace_buffer *buffer)
  487. {
  488. struct trace_event_call *call = &event_osnoise;
  489. struct ring_buffer_event *event;
  490. struct timerlat_entry *entry;
  491. event = trace_buffer_lock_reserve(buffer, TRACE_TIMERLAT, sizeof(*entry),
  492. tracing_gen_ctx());
  493. if (!event)
  494. return;
  495. entry = ring_buffer_event_data(event);
  496. entry->seqnum = sample->seqnum;
  497. entry->context = sample->context;
  498. entry->timer_latency = sample->timer_latency;
  499. if (!call_filter_check_discard(call, entry, buffer, event))
  500. trace_buffer_unlock_commit_nostack(buffer, event);
  501. }
  502. /*
  503. * Record an timerlat_sample into the tracer buffer.
  504. */
  505. static void trace_timerlat_sample(struct timerlat_sample *sample)
  506. {
  507. struct osnoise_instance *inst;
  508. struct trace_buffer *buffer;
  509. rcu_read_lock();
  510. list_for_each_entry_rcu(inst, &osnoise_instances, list) {
  511. buffer = inst->tr->array_buffer.buffer;
  512. __trace_timerlat_sample(sample, buffer);
  513. }
  514. rcu_read_unlock();
  515. }
  516. #ifdef CONFIG_STACKTRACE
  517. #define MAX_CALLS 256
  518. /*
  519. * Stack trace will take place only at IRQ level, so, no need
  520. * to control nesting here.
  521. */
  522. struct trace_stack {
  523. int stack_size;
  524. int nr_entries;
  525. unsigned long calls[MAX_CALLS];
  526. };
  527. static DEFINE_PER_CPU(struct trace_stack, trace_stack);
  528. /*
  529. * timerlat_save_stack - save a stack trace without printing
  530. *
  531. * Save the current stack trace without printing. The
  532. * stack will be printed later, after the end of the measurement.
  533. */
  534. static void timerlat_save_stack(int skip)
  535. {
  536. unsigned int size, nr_entries;
  537. struct trace_stack *fstack;
  538. fstack = this_cpu_ptr(&trace_stack);
  539. size = ARRAY_SIZE(fstack->calls);
  540. nr_entries = stack_trace_save(fstack->calls, size, skip);
  541. fstack->stack_size = nr_entries * sizeof(unsigned long);
  542. fstack->nr_entries = nr_entries;
  543. return;
  544. }
  545. static void
  546. __timerlat_dump_stack(struct trace_buffer *buffer, struct trace_stack *fstack, unsigned int size)
  547. {
  548. struct trace_event_call *call = &event_osnoise;
  549. struct ring_buffer_event *event;
  550. struct stack_entry *entry;
  551. event = trace_buffer_lock_reserve(buffer, TRACE_STACK, sizeof(*entry) + size,
  552. tracing_gen_ctx());
  553. if (!event)
  554. return;
  555. entry = ring_buffer_event_data(event);
  556. memcpy(&entry->caller, fstack->calls, size);
  557. entry->size = fstack->nr_entries;
  558. if (!call_filter_check_discard(call, entry, buffer, event))
  559. trace_buffer_unlock_commit_nostack(buffer, event);
  560. }
  561. /*
  562. * timerlat_dump_stack - dump a stack trace previously saved
  563. */
  564. static void timerlat_dump_stack(u64 latency)
  565. {
  566. struct osnoise_instance *inst;
  567. struct trace_buffer *buffer;
  568. struct trace_stack *fstack;
  569. unsigned int size;
  570. /*
  571. * trace only if latency > print_stack config, if enabled.
  572. */
  573. if (!osnoise_data.print_stack || osnoise_data.print_stack > latency)
  574. return;
  575. preempt_disable_notrace();
  576. fstack = this_cpu_ptr(&trace_stack);
  577. size = fstack->stack_size;
  578. rcu_read_lock();
  579. list_for_each_entry_rcu(inst, &osnoise_instances, list) {
  580. buffer = inst->tr->array_buffer.buffer;
  581. __timerlat_dump_stack(buffer, fstack, size);
  582. }
  583. rcu_read_unlock();
  584. preempt_enable_notrace();
  585. }
  586. #else /* CONFIG_STACKTRACE */
  587. #define timerlat_dump_stack(u64 latency) do {} while (0)
  588. #define timerlat_save_stack(a) do {} while (0)
  589. #endif /* CONFIG_STACKTRACE */
  590. #endif /* CONFIG_TIMERLAT_TRACER */
  591. /*
  592. * Macros to encapsulate the time capturing infrastructure.
  593. */
  594. #define time_get() trace_clock_local()
  595. #define time_to_us(x) div_u64(x, 1000)
  596. #define time_sub(a, b) ((a) - (b))
  597. /*
  598. * cond_move_irq_delta_start - Forward the delta_start of a running IRQ
  599. *
  600. * If an IRQ is preempted by an NMI, its delta_start is pushed forward
  601. * to discount the NMI interference.
  602. *
  603. * See get_int_safe_duration().
  604. */
  605. static inline void
  606. cond_move_irq_delta_start(struct osnoise_variables *osn_var, u64 duration)
  607. {
  608. if (osn_var->irq.delta_start)
  609. osn_var->irq.delta_start += duration;
  610. }
  611. #ifndef CONFIG_PREEMPT_RT
  612. /*
  613. * cond_move_softirq_delta_start - Forward the delta_start of a running softirq.
  614. *
  615. * If a softirq is preempted by an IRQ or NMI, its delta_start is pushed
  616. * forward to discount the interference.
  617. *
  618. * See get_int_safe_duration().
  619. */
  620. static inline void
  621. cond_move_softirq_delta_start(struct osnoise_variables *osn_var, u64 duration)
  622. {
  623. if (osn_var->softirq.delta_start)
  624. osn_var->softirq.delta_start += duration;
  625. }
  626. #else /* CONFIG_PREEMPT_RT */
  627. #define cond_move_softirq_delta_start(osn_var, duration) do {} while (0)
  628. #endif
  629. /*
  630. * cond_move_thread_delta_start - Forward the delta_start of a running thread
  631. *
  632. * If a noisy thread is preempted by an softirq, IRQ or NMI, its delta_start
  633. * is pushed forward to discount the interference.
  634. *
  635. * See get_int_safe_duration().
  636. */
  637. static inline void
  638. cond_move_thread_delta_start(struct osnoise_variables *osn_var, u64 duration)
  639. {
  640. if (osn_var->thread.delta_start)
  641. osn_var->thread.delta_start += duration;
  642. }
  643. /*
  644. * get_int_safe_duration - Get the duration of a window
  645. *
  646. * The irq, softirq and thread varaibles need to have its duration without
  647. * the interference from higher priority interrupts. Instead of keeping a
  648. * variable to discount the interrupt interference from these variables, the
  649. * starting time of these variables are pushed forward with the interrupt's
  650. * duration. In this way, a single variable is used to:
  651. *
  652. * - Know if a given window is being measured.
  653. * - Account its duration.
  654. * - Discount the interference.
  655. *
  656. * To avoid getting inconsistent values, e.g.,:
  657. *
  658. * now = time_get()
  659. * ---> interrupt!
  660. * delta_start -= int duration;
  661. * <---
  662. * duration = now - delta_start;
  663. *
  664. * result: negative duration if the variable duration before the
  665. * interrupt was smaller than the interrupt execution.
  666. *
  667. * A counter of interrupts is used. If the counter increased, try
  668. * to capture an interference safe duration.
  669. */
  670. static inline s64
  671. get_int_safe_duration(struct osnoise_variables *osn_var, u64 *delta_start)
  672. {
  673. u64 int_counter, now;
  674. s64 duration;
  675. do {
  676. int_counter = local_read(&osn_var->int_counter);
  677. /* synchronize with interrupts */
  678. barrier();
  679. now = time_get();
  680. duration = (now - *delta_start);
  681. /* synchronize with interrupts */
  682. barrier();
  683. } while (int_counter != local_read(&osn_var->int_counter));
  684. /*
  685. * This is an evidence of race conditions that cause
  686. * a value to be "discounted" too much.
  687. */
  688. if (duration < 0)
  689. osnoise_taint("Negative duration!\n");
  690. *delta_start = 0;
  691. return duration;
  692. }
  693. /*
  694. *
  695. * set_int_safe_time - Save the current time on *time, aware of interference
  696. *
  697. * Get the time, taking into consideration a possible interference from
  698. * higher priority interrupts.
  699. *
  700. * See get_int_safe_duration() for an explanation.
  701. */
  702. static u64
  703. set_int_safe_time(struct osnoise_variables *osn_var, u64 *time)
  704. {
  705. u64 int_counter;
  706. do {
  707. int_counter = local_read(&osn_var->int_counter);
  708. /* synchronize with interrupts */
  709. barrier();
  710. *time = time_get();
  711. /* synchronize with interrupts */
  712. barrier();
  713. } while (int_counter != local_read(&osn_var->int_counter));
  714. return int_counter;
  715. }
  716. #ifdef CONFIG_TIMERLAT_TRACER
  717. /*
  718. * copy_int_safe_time - Copy *src into *desc aware of interference
  719. */
  720. static u64
  721. copy_int_safe_time(struct osnoise_variables *osn_var, u64 *dst, u64 *src)
  722. {
  723. u64 int_counter;
  724. do {
  725. int_counter = local_read(&osn_var->int_counter);
  726. /* synchronize with interrupts */
  727. barrier();
  728. *dst = *src;
  729. /* synchronize with interrupts */
  730. barrier();
  731. } while (int_counter != local_read(&osn_var->int_counter));
  732. return int_counter;
  733. }
  734. #endif /* CONFIG_TIMERLAT_TRACER */
  735. /*
  736. * trace_osnoise_callback - NMI entry/exit callback
  737. *
  738. * This function is called at the entry and exit NMI code. The bool enter
  739. * distinguishes between either case. This function is used to note a NMI
  740. * occurrence, compute the noise caused by the NMI, and to remove the noise
  741. * it is potentially causing on other interference variables.
  742. */
  743. void trace_osnoise_callback(bool enter)
  744. {
  745. struct osnoise_variables *osn_var = this_cpu_osn_var();
  746. u64 duration;
  747. if (!osn_var->sampling)
  748. return;
  749. /*
  750. * Currently trace_clock_local() calls sched_clock() and the
  751. * generic version is not NMI safe.
  752. */
  753. if (!IS_ENABLED(CONFIG_GENERIC_SCHED_CLOCK)) {
  754. if (enter) {
  755. osn_var->nmi.delta_start = time_get();
  756. local_inc(&osn_var->int_counter);
  757. } else {
  758. duration = time_get() - osn_var->nmi.delta_start;
  759. trace_nmi_noise(osn_var->nmi.delta_start, duration);
  760. cond_move_irq_delta_start(osn_var, duration);
  761. cond_move_softirq_delta_start(osn_var, duration);
  762. cond_move_thread_delta_start(osn_var, duration);
  763. }
  764. }
  765. if (enter)
  766. osn_var->nmi.count++;
  767. }
  768. /*
  769. * osnoise_trace_irq_entry - Note the starting of an IRQ
  770. *
  771. * Save the starting time of an IRQ. As IRQs are non-preemptive to other IRQs,
  772. * it is safe to use a single variable (ons_var->irq) to save the statistics.
  773. * The arrival_time is used to report... the arrival time. The delta_start
  774. * is used to compute the duration at the IRQ exit handler. See
  775. * cond_move_irq_delta_start().
  776. */
  777. void osnoise_trace_irq_entry(int id)
  778. {
  779. struct osnoise_variables *osn_var = this_cpu_osn_var();
  780. if (!osn_var->sampling)
  781. return;
  782. /*
  783. * This value will be used in the report, but not to compute
  784. * the execution time, so it is safe to get it unsafe.
  785. */
  786. osn_var->irq.arrival_time = time_get();
  787. set_int_safe_time(osn_var, &osn_var->irq.delta_start);
  788. osn_var->irq.count++;
  789. local_inc(&osn_var->int_counter);
  790. }
  791. /*
  792. * osnoise_irq_exit - Note the end of an IRQ, sava data and trace
  793. *
  794. * Computes the duration of the IRQ noise, and trace it. Also discounts the
  795. * interference from other sources of noise could be currently being accounted.
  796. */
  797. void osnoise_trace_irq_exit(int id, const char *desc)
  798. {
  799. struct osnoise_variables *osn_var = this_cpu_osn_var();
  800. s64 duration;
  801. if (!osn_var->sampling)
  802. return;
  803. duration = get_int_safe_duration(osn_var, &osn_var->irq.delta_start);
  804. trace_irq_noise(id, desc, osn_var->irq.arrival_time, duration);
  805. osn_var->irq.arrival_time = 0;
  806. cond_move_softirq_delta_start(osn_var, duration);
  807. cond_move_thread_delta_start(osn_var, duration);
  808. }
  809. /*
  810. * trace_irqentry_callback - Callback to the irq:irq_entry traceevent
  811. *
  812. * Used to note the starting of an IRQ occurece.
  813. */
  814. static void trace_irqentry_callback(void *data, int irq,
  815. struct irqaction *action)
  816. {
  817. osnoise_trace_irq_entry(irq);
  818. }
  819. /*
  820. * trace_irqexit_callback - Callback to the irq:irq_exit traceevent
  821. *
  822. * Used to note the end of an IRQ occurece.
  823. */
  824. static void trace_irqexit_callback(void *data, int irq,
  825. struct irqaction *action, int ret)
  826. {
  827. osnoise_trace_irq_exit(irq, action->name);
  828. }
  829. /*
  830. * arch specific register function.
  831. */
  832. int __weak osnoise_arch_register(void)
  833. {
  834. return 0;
  835. }
  836. /*
  837. * arch specific unregister function.
  838. */
  839. void __weak osnoise_arch_unregister(void)
  840. {
  841. return;
  842. }
  843. /*
  844. * hook_irq_events - Hook IRQ handling events
  845. *
  846. * This function hooks the IRQ related callbacks to the respective trace
  847. * events.
  848. */
  849. static int hook_irq_events(void)
  850. {
  851. int ret;
  852. ret = register_trace_irq_handler_entry(trace_irqentry_callback, NULL);
  853. if (ret)
  854. goto out_err;
  855. ret = register_trace_irq_handler_exit(trace_irqexit_callback, NULL);
  856. if (ret)
  857. goto out_unregister_entry;
  858. ret = osnoise_arch_register();
  859. if (ret)
  860. goto out_irq_exit;
  861. return 0;
  862. out_irq_exit:
  863. unregister_trace_irq_handler_exit(trace_irqexit_callback, NULL);
  864. out_unregister_entry:
  865. unregister_trace_irq_handler_entry(trace_irqentry_callback, NULL);
  866. out_err:
  867. return -EINVAL;
  868. }
  869. /*
  870. * unhook_irq_events - Unhook IRQ handling events
  871. *
  872. * This function unhooks the IRQ related callbacks to the respective trace
  873. * events.
  874. */
  875. static void unhook_irq_events(void)
  876. {
  877. osnoise_arch_unregister();
  878. unregister_trace_irq_handler_exit(trace_irqexit_callback, NULL);
  879. unregister_trace_irq_handler_entry(trace_irqentry_callback, NULL);
  880. }
  881. #ifndef CONFIG_PREEMPT_RT
  882. /*
  883. * trace_softirq_entry_callback - Note the starting of a softirq
  884. *
  885. * Save the starting time of a softirq. As softirqs are non-preemptive to
  886. * other softirqs, it is safe to use a single variable (ons_var->softirq)
  887. * to save the statistics. The arrival_time is used to report... the
  888. * arrival time. The delta_start is used to compute the duration at the
  889. * softirq exit handler. See cond_move_softirq_delta_start().
  890. */
  891. static void trace_softirq_entry_callback(void *data, unsigned int vec_nr)
  892. {
  893. struct osnoise_variables *osn_var = this_cpu_osn_var();
  894. if (!osn_var->sampling)
  895. return;
  896. /*
  897. * This value will be used in the report, but not to compute
  898. * the execution time, so it is safe to get it unsafe.
  899. */
  900. osn_var->softirq.arrival_time = time_get();
  901. set_int_safe_time(osn_var, &osn_var->softirq.delta_start);
  902. osn_var->softirq.count++;
  903. local_inc(&osn_var->int_counter);
  904. }
  905. /*
  906. * trace_softirq_exit_callback - Note the end of an softirq
  907. *
  908. * Computes the duration of the softirq noise, and trace it. Also discounts the
  909. * interference from other sources of noise could be currently being accounted.
  910. */
  911. static void trace_softirq_exit_callback(void *data, unsigned int vec_nr)
  912. {
  913. struct osnoise_variables *osn_var = this_cpu_osn_var();
  914. s64 duration;
  915. if (!osn_var->sampling)
  916. return;
  917. if (unlikely(timerlat_enabled()))
  918. if (!timerlat_softirq_exit(osn_var))
  919. return;
  920. duration = get_int_safe_duration(osn_var, &osn_var->softirq.delta_start);
  921. trace_softirq_noise(vec_nr, osn_var->softirq.arrival_time, duration);
  922. cond_move_thread_delta_start(osn_var, duration);
  923. osn_var->softirq.arrival_time = 0;
  924. }
  925. /*
  926. * hook_softirq_events - Hook softirq handling events
  927. *
  928. * This function hooks the softirq related callbacks to the respective trace
  929. * events.
  930. */
  931. static int hook_softirq_events(void)
  932. {
  933. int ret;
  934. ret = register_trace_softirq_entry(trace_softirq_entry_callback, NULL);
  935. if (ret)
  936. goto out_err;
  937. ret = register_trace_softirq_exit(trace_softirq_exit_callback, NULL);
  938. if (ret)
  939. goto out_unreg_entry;
  940. return 0;
  941. out_unreg_entry:
  942. unregister_trace_softirq_entry(trace_softirq_entry_callback, NULL);
  943. out_err:
  944. return -EINVAL;
  945. }
  946. /*
  947. * unhook_softirq_events - Unhook softirq handling events
  948. *
  949. * This function hooks the softirq related callbacks to the respective trace
  950. * events.
  951. */
  952. static void unhook_softirq_events(void)
  953. {
  954. unregister_trace_softirq_entry(trace_softirq_entry_callback, NULL);
  955. unregister_trace_softirq_exit(trace_softirq_exit_callback, NULL);
  956. }
  957. #else /* CONFIG_PREEMPT_RT */
  958. /*
  959. * softirq are threads on the PREEMPT_RT mode.
  960. */
  961. static int hook_softirq_events(void)
  962. {
  963. return 0;
  964. }
  965. static void unhook_softirq_events(void)
  966. {
  967. }
  968. #endif
  969. /*
  970. * thread_entry - Record the starting of a thread noise window
  971. *
  972. * It saves the context switch time for a noisy thread, and increments
  973. * the interference counters.
  974. */
  975. static void
  976. thread_entry(struct osnoise_variables *osn_var, struct task_struct *t)
  977. {
  978. if (!osn_var->sampling)
  979. return;
  980. /*
  981. * The arrival time will be used in the report, but not to compute
  982. * the execution time, so it is safe to get it unsafe.
  983. */
  984. osn_var->thread.arrival_time = time_get();
  985. set_int_safe_time(osn_var, &osn_var->thread.delta_start);
  986. osn_var->thread.count++;
  987. local_inc(&osn_var->int_counter);
  988. }
  989. /*
  990. * thread_exit - Report the end of a thread noise window
  991. *
  992. * It computes the total noise from a thread, tracing if needed.
  993. */
  994. static void
  995. thread_exit(struct osnoise_variables *osn_var, struct task_struct *t)
  996. {
  997. s64 duration;
  998. if (!osn_var->sampling)
  999. return;
  1000. if (unlikely(timerlat_enabled()))
  1001. if (!timerlat_thread_exit(osn_var))
  1002. return;
  1003. duration = get_int_safe_duration(osn_var, &osn_var->thread.delta_start);
  1004. trace_thread_noise(t, osn_var->thread.arrival_time, duration);
  1005. osn_var->thread.arrival_time = 0;
  1006. }
  1007. /*
  1008. * trace_sched_switch - sched:sched_switch trace event handler
  1009. *
  1010. * This function is hooked to the sched:sched_switch trace event, and it is
  1011. * used to record the beginning and to report the end of a thread noise window.
  1012. */
  1013. static void
  1014. trace_sched_switch_callback(void *data, bool preempt,
  1015. struct task_struct *p,
  1016. struct task_struct *n,
  1017. unsigned int prev_state)
  1018. {
  1019. struct osnoise_variables *osn_var = this_cpu_osn_var();
  1020. if (p->pid != osn_var->pid)
  1021. thread_exit(osn_var, p);
  1022. if (n->pid != osn_var->pid)
  1023. thread_entry(osn_var, n);
  1024. }
  1025. /*
  1026. * hook_thread_events - Hook the insturmentation for thread noise
  1027. *
  1028. * Hook the osnoise tracer callbacks to handle the noise from other
  1029. * threads on the necessary kernel events.
  1030. */
  1031. static int hook_thread_events(void)
  1032. {
  1033. int ret;
  1034. ret = register_trace_sched_switch(trace_sched_switch_callback, NULL);
  1035. if (ret)
  1036. return -EINVAL;
  1037. return 0;
  1038. }
  1039. /*
  1040. * unhook_thread_events - *nhook the insturmentation for thread noise
  1041. *
  1042. * Unook the osnoise tracer callbacks to handle the noise from other
  1043. * threads on the necessary kernel events.
  1044. */
  1045. static void unhook_thread_events(void)
  1046. {
  1047. unregister_trace_sched_switch(trace_sched_switch_callback, NULL);
  1048. }
  1049. /*
  1050. * save_osn_sample_stats - Save the osnoise_sample statistics
  1051. *
  1052. * Save the osnoise_sample statistics before the sampling phase. These
  1053. * values will be used later to compute the diff betwneen the statistics
  1054. * before and after the osnoise sampling.
  1055. */
  1056. static void
  1057. save_osn_sample_stats(struct osnoise_variables *osn_var, struct osnoise_sample *s)
  1058. {
  1059. s->nmi_count = osn_var->nmi.count;
  1060. s->irq_count = osn_var->irq.count;
  1061. s->softirq_count = osn_var->softirq.count;
  1062. s->thread_count = osn_var->thread.count;
  1063. }
  1064. /*
  1065. * diff_osn_sample_stats - Compute the osnoise_sample statistics
  1066. *
  1067. * After a sample period, compute the difference on the osnoise_sample
  1068. * statistics. The struct osnoise_sample *s contains the statistics saved via
  1069. * save_osn_sample_stats() before the osnoise sampling.
  1070. */
  1071. static void
  1072. diff_osn_sample_stats(struct osnoise_variables *osn_var, struct osnoise_sample *s)
  1073. {
  1074. s->nmi_count = osn_var->nmi.count - s->nmi_count;
  1075. s->irq_count = osn_var->irq.count - s->irq_count;
  1076. s->softirq_count = osn_var->softirq.count - s->softirq_count;
  1077. s->thread_count = osn_var->thread.count - s->thread_count;
  1078. }
  1079. /*
  1080. * osnoise_stop_tracing - Stop tracing and the tracer.
  1081. */
  1082. static __always_inline void osnoise_stop_tracing(void)
  1083. {
  1084. struct osnoise_instance *inst;
  1085. struct trace_array *tr;
  1086. rcu_read_lock();
  1087. list_for_each_entry_rcu(inst, &osnoise_instances, list) {
  1088. tr = inst->tr;
  1089. trace_array_printk_buf(tr->array_buffer.buffer, _THIS_IP_,
  1090. "stop tracing hit on cpu %d\n", smp_processor_id());
  1091. tracer_tracing_off(tr);
  1092. }
  1093. rcu_read_unlock();
  1094. }
  1095. /*
  1096. * notify_new_max_latency - Notify a new max latency via fsnotify interface.
  1097. */
  1098. static void notify_new_max_latency(u64 latency)
  1099. {
  1100. struct osnoise_instance *inst;
  1101. struct trace_array *tr;
  1102. rcu_read_lock();
  1103. list_for_each_entry_rcu(inst, &osnoise_instances, list) {
  1104. tr = inst->tr;
  1105. if (tracer_tracing_is_on(tr) && tr->max_latency < latency) {
  1106. tr->max_latency = latency;
  1107. latency_fsnotify(tr);
  1108. }
  1109. }
  1110. rcu_read_unlock();
  1111. }
  1112. /*
  1113. * run_osnoise - Sample the time and look for osnoise
  1114. *
  1115. * Used to capture the time, looking for potential osnoise latency repeatedly.
  1116. * Different from hwlat_detector, it is called with preemption and interrupts
  1117. * enabled. This allows irqs, softirqs and threads to run, interfering on the
  1118. * osnoise sampling thread, as they would do with a regular thread.
  1119. */
  1120. static int run_osnoise(void)
  1121. {
  1122. struct osnoise_variables *osn_var = this_cpu_osn_var();
  1123. u64 start, sample, last_sample;
  1124. u64 last_int_count, int_count;
  1125. s64 noise = 0, max_noise = 0;
  1126. s64 total, last_total = 0;
  1127. struct osnoise_sample s;
  1128. unsigned int threshold;
  1129. u64 runtime, stop_in;
  1130. u64 sum_noise = 0;
  1131. int hw_count = 0;
  1132. int ret = -1;
  1133. /*
  1134. * Considers the current thread as the workload.
  1135. */
  1136. osn_var->pid = current->pid;
  1137. /*
  1138. * Save the current stats for the diff
  1139. */
  1140. save_osn_sample_stats(osn_var, &s);
  1141. /*
  1142. * if threshold is 0, use the default value of 5 us.
  1143. */
  1144. threshold = tracing_thresh ? : 5000;
  1145. /*
  1146. * Make sure NMIs see sampling first
  1147. */
  1148. osn_var->sampling = true;
  1149. barrier();
  1150. /*
  1151. * Transform the *_us config to nanoseconds to avoid the
  1152. * division on the main loop.
  1153. */
  1154. runtime = osnoise_data.sample_runtime * NSEC_PER_USEC;
  1155. stop_in = osnoise_data.stop_tracing * NSEC_PER_USEC;
  1156. /*
  1157. * Start timestemp
  1158. */
  1159. start = time_get();
  1160. /*
  1161. * "previous" loop.
  1162. */
  1163. last_int_count = set_int_safe_time(osn_var, &last_sample);
  1164. do {
  1165. /*
  1166. * Get sample!
  1167. */
  1168. int_count = set_int_safe_time(osn_var, &sample);
  1169. noise = time_sub(sample, last_sample);
  1170. /*
  1171. * This shouldn't happen.
  1172. */
  1173. if (noise < 0) {
  1174. osnoise_taint("negative noise!");
  1175. goto out;
  1176. }
  1177. /*
  1178. * Sample runtime.
  1179. */
  1180. total = time_sub(sample, start);
  1181. /*
  1182. * Check for possible overflows.
  1183. */
  1184. if (total < last_total) {
  1185. osnoise_taint("total overflow!");
  1186. break;
  1187. }
  1188. last_total = total;
  1189. if (noise >= threshold) {
  1190. int interference = int_count - last_int_count;
  1191. if (noise > max_noise)
  1192. max_noise = noise;
  1193. if (!interference)
  1194. hw_count++;
  1195. sum_noise += noise;
  1196. trace_sample_threshold(last_sample, noise, interference);
  1197. if (osnoise_data.stop_tracing)
  1198. if (noise > stop_in)
  1199. osnoise_stop_tracing();
  1200. }
  1201. /*
  1202. * In some cases, notably when running on a nohz_full CPU with
  1203. * a stopped tick PREEMPT_RCU has no way to account for QSs.
  1204. * This will eventually cause unwarranted noise as PREEMPT_RCU
  1205. * will force preemption as the means of ending the current
  1206. * grace period. We avoid this problem by calling
  1207. * rcu_momentary_dyntick_idle(), which performs a zero duration
  1208. * EQS allowing PREEMPT_RCU to end the current grace period.
  1209. * This call shouldn't be wrapped inside an RCU critical
  1210. * section.
  1211. *
  1212. * Note that in non PREEMPT_RCU kernels QSs are handled through
  1213. * cond_resched()
  1214. */
  1215. if (IS_ENABLED(CONFIG_PREEMPT_RCU)) {
  1216. local_irq_disable();
  1217. rcu_momentary_dyntick_idle();
  1218. local_irq_enable();
  1219. }
  1220. /*
  1221. * For the non-preemptive kernel config: let threads runs, if
  1222. * they so wish.
  1223. */
  1224. cond_resched();
  1225. last_sample = sample;
  1226. last_int_count = int_count;
  1227. } while (total < runtime && !kthread_should_stop());
  1228. /*
  1229. * Finish the above in the view for interrupts.
  1230. */
  1231. barrier();
  1232. osn_var->sampling = false;
  1233. /*
  1234. * Make sure sampling data is no longer updated.
  1235. */
  1236. barrier();
  1237. /*
  1238. * Save noise info.
  1239. */
  1240. s.noise = time_to_us(sum_noise);
  1241. s.runtime = time_to_us(total);
  1242. s.max_sample = time_to_us(max_noise);
  1243. s.hw_count = hw_count;
  1244. /* Save interference stats info */
  1245. diff_osn_sample_stats(osn_var, &s);
  1246. trace_osnoise_sample(&s);
  1247. notify_new_max_latency(max_noise);
  1248. if (osnoise_data.stop_tracing_total)
  1249. if (s.noise > osnoise_data.stop_tracing_total)
  1250. osnoise_stop_tracing();
  1251. return 0;
  1252. out:
  1253. return ret;
  1254. }
  1255. static struct cpumask osnoise_cpumask;
  1256. static struct cpumask save_cpumask;
  1257. /*
  1258. * osnoise_sleep - sleep until the next period
  1259. */
  1260. static void osnoise_sleep(void)
  1261. {
  1262. u64 interval;
  1263. ktime_t wake_time;
  1264. mutex_lock(&interface_lock);
  1265. interval = osnoise_data.sample_period - osnoise_data.sample_runtime;
  1266. mutex_unlock(&interface_lock);
  1267. /*
  1268. * differently from hwlat_detector, the osnoise tracer can run
  1269. * without a pause because preemption is on.
  1270. */
  1271. if (!interval) {
  1272. /* Let synchronize_rcu_tasks() make progress */
  1273. cond_resched_tasks_rcu_qs();
  1274. return;
  1275. }
  1276. wake_time = ktime_add_us(ktime_get(), interval);
  1277. __set_current_state(TASK_INTERRUPTIBLE);
  1278. while (schedule_hrtimeout_range(&wake_time, 0, HRTIMER_MODE_ABS)) {
  1279. if (kthread_should_stop())
  1280. break;
  1281. }
  1282. }
  1283. /*
  1284. * osnoise_main - The osnoise detection kernel thread
  1285. *
  1286. * Calls run_osnoise() function to measure the osnoise for the configured runtime,
  1287. * every period.
  1288. */
  1289. static int osnoise_main(void *data)
  1290. {
  1291. while (!kthread_should_stop()) {
  1292. run_osnoise();
  1293. osnoise_sleep();
  1294. }
  1295. return 0;
  1296. }
  1297. #ifdef CONFIG_TIMERLAT_TRACER
  1298. /*
  1299. * timerlat_irq - hrtimer handler for timerlat.
  1300. */
  1301. static enum hrtimer_restart timerlat_irq(struct hrtimer *timer)
  1302. {
  1303. struct osnoise_variables *osn_var = this_cpu_osn_var();
  1304. struct timerlat_variables *tlat;
  1305. struct timerlat_sample s;
  1306. u64 now;
  1307. u64 diff;
  1308. /*
  1309. * I am not sure if the timer was armed for this CPU. So, get
  1310. * the timerlat struct from the timer itself, not from this
  1311. * CPU.
  1312. */
  1313. tlat = container_of(timer, struct timerlat_variables, timer);
  1314. now = ktime_to_ns(hrtimer_cb_get_time(&tlat->timer));
  1315. /*
  1316. * Enable the osnoise: events for thread an softirq.
  1317. */
  1318. tlat->tracing_thread = true;
  1319. osn_var->thread.arrival_time = time_get();
  1320. /*
  1321. * A hardirq is running: the timer IRQ. It is for sure preempting
  1322. * a thread, and potentially preempting a softirq.
  1323. *
  1324. * At this point, it is not interesting to know the duration of the
  1325. * preempted thread (and maybe softirq), but how much time they will
  1326. * delay the beginning of the execution of the timer thread.
  1327. *
  1328. * To get the correct (net) delay added by the softirq, its delta_start
  1329. * is set as the IRQ one. In this way, at the return of the IRQ, the delta
  1330. * start of the sofitrq will be zeroed, accounting then only the time
  1331. * after that.
  1332. *
  1333. * The thread follows the same principle. However, if a softirq is
  1334. * running, the thread needs to receive the softirq delta_start. The
  1335. * reason being is that the softirq will be the last to be unfolded,
  1336. * resseting the thread delay to zero.
  1337. *
  1338. * The PREEMPT_RT is a special case, though. As softirqs run as threads
  1339. * on RT, moving the thread is enough.
  1340. */
  1341. if (!IS_ENABLED(CONFIG_PREEMPT_RT) && osn_var->softirq.delta_start) {
  1342. copy_int_safe_time(osn_var, &osn_var->thread.delta_start,
  1343. &osn_var->softirq.delta_start);
  1344. copy_int_safe_time(osn_var, &osn_var->softirq.delta_start,
  1345. &osn_var->irq.delta_start);
  1346. } else {
  1347. copy_int_safe_time(osn_var, &osn_var->thread.delta_start,
  1348. &osn_var->irq.delta_start);
  1349. }
  1350. /*
  1351. * Compute the current time with the expected time.
  1352. */
  1353. diff = now - tlat->abs_period;
  1354. tlat->count++;
  1355. s.seqnum = tlat->count;
  1356. s.timer_latency = diff;
  1357. s.context = IRQ_CONTEXT;
  1358. trace_timerlat_sample(&s);
  1359. if (osnoise_data.stop_tracing) {
  1360. if (time_to_us(diff) >= osnoise_data.stop_tracing) {
  1361. /*
  1362. * At this point, if stop_tracing is set and <= print_stack,
  1363. * print_stack is set and would be printed in the thread handler.
  1364. *
  1365. * Thus, print the stack trace as it is helpful to define the
  1366. * root cause of an IRQ latency.
  1367. */
  1368. if (osnoise_data.stop_tracing <= osnoise_data.print_stack) {
  1369. timerlat_save_stack(0);
  1370. timerlat_dump_stack(time_to_us(diff));
  1371. }
  1372. osnoise_stop_tracing();
  1373. notify_new_max_latency(diff);
  1374. wake_up_process(tlat->kthread);
  1375. return HRTIMER_NORESTART;
  1376. }
  1377. }
  1378. wake_up_process(tlat->kthread);
  1379. if (osnoise_data.print_stack)
  1380. timerlat_save_stack(0);
  1381. return HRTIMER_NORESTART;
  1382. }
  1383. /*
  1384. * wait_next_period - Wait for the next period for timerlat
  1385. */
  1386. static int wait_next_period(struct timerlat_variables *tlat)
  1387. {
  1388. ktime_t next_abs_period, now;
  1389. u64 rel_period = osnoise_data.timerlat_period * 1000;
  1390. now = hrtimer_cb_get_time(&tlat->timer);
  1391. next_abs_period = ns_to_ktime(tlat->abs_period + rel_period);
  1392. /*
  1393. * Save the next abs_period.
  1394. */
  1395. tlat->abs_period = (u64) ktime_to_ns(next_abs_period);
  1396. /*
  1397. * If the new abs_period is in the past, skip the activation.
  1398. */
  1399. while (ktime_compare(now, next_abs_period) > 0) {
  1400. next_abs_period = ns_to_ktime(tlat->abs_period + rel_period);
  1401. tlat->abs_period = (u64) ktime_to_ns(next_abs_period);
  1402. }
  1403. set_current_state(TASK_INTERRUPTIBLE);
  1404. hrtimer_start(&tlat->timer, next_abs_period, HRTIMER_MODE_ABS_PINNED_HARD);
  1405. schedule();
  1406. return 1;
  1407. }
  1408. /*
  1409. * timerlat_main- Timerlat main
  1410. */
  1411. static int timerlat_main(void *data)
  1412. {
  1413. struct osnoise_variables *osn_var = this_cpu_osn_var();
  1414. struct timerlat_variables *tlat = this_cpu_tmr_var();
  1415. struct timerlat_sample s;
  1416. struct sched_param sp;
  1417. u64 now, diff;
  1418. /*
  1419. * Make the thread RT, that is how cyclictest is usually used.
  1420. */
  1421. sp.sched_priority = DEFAULT_TIMERLAT_PRIO;
  1422. sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
  1423. tlat->count = 0;
  1424. tlat->tracing_thread = false;
  1425. hrtimer_init(&tlat->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD);
  1426. tlat->timer.function = timerlat_irq;
  1427. tlat->kthread = current;
  1428. osn_var->pid = current->pid;
  1429. /*
  1430. * Anotate the arrival time.
  1431. */
  1432. tlat->abs_period = hrtimer_cb_get_time(&tlat->timer);
  1433. wait_next_period(tlat);
  1434. osn_var->sampling = 1;
  1435. while (!kthread_should_stop()) {
  1436. now = ktime_to_ns(hrtimer_cb_get_time(&tlat->timer));
  1437. diff = now - tlat->abs_period;
  1438. s.seqnum = tlat->count;
  1439. s.timer_latency = diff;
  1440. s.context = THREAD_CONTEXT;
  1441. trace_timerlat_sample(&s);
  1442. notify_new_max_latency(diff);
  1443. timerlat_dump_stack(time_to_us(diff));
  1444. tlat->tracing_thread = false;
  1445. if (osnoise_data.stop_tracing_total)
  1446. if (time_to_us(diff) >= osnoise_data.stop_tracing_total)
  1447. osnoise_stop_tracing();
  1448. wait_next_period(tlat);
  1449. }
  1450. hrtimer_cancel(&tlat->timer);
  1451. return 0;
  1452. }
  1453. #else /* CONFIG_TIMERLAT_TRACER */
  1454. static int timerlat_main(void *data)
  1455. {
  1456. return 0;
  1457. }
  1458. #endif /* CONFIG_TIMERLAT_TRACER */
  1459. /*
  1460. * stop_kthread - stop a workload thread
  1461. */
  1462. static void stop_kthread(unsigned int cpu)
  1463. {
  1464. struct task_struct *kthread;
  1465. kthread = per_cpu(per_cpu_osnoise_var, cpu).kthread;
  1466. if (kthread)
  1467. kthread_stop(kthread);
  1468. per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
  1469. }
  1470. /*
  1471. * stop_per_cpu_kthread - Stop per-cpu threads
  1472. *
  1473. * Stop the osnoise sampling htread. Use this on unload and at system
  1474. * shutdown.
  1475. */
  1476. static void stop_per_cpu_kthreads(void)
  1477. {
  1478. int cpu;
  1479. cpus_read_lock();
  1480. for_each_online_cpu(cpu)
  1481. stop_kthread(cpu);
  1482. cpus_read_unlock();
  1483. }
  1484. /*
  1485. * start_kthread - Start a workload tread
  1486. */
  1487. static int start_kthread(unsigned int cpu)
  1488. {
  1489. struct task_struct *kthread;
  1490. void *main = osnoise_main;
  1491. char comm[24];
  1492. if (timerlat_enabled()) {
  1493. snprintf(comm, 24, "timerlat/%d", cpu);
  1494. main = timerlat_main;
  1495. } else {
  1496. snprintf(comm, 24, "osnoise/%d", cpu);
  1497. }
  1498. kthread = kthread_run_on_cpu(main, NULL, cpu, comm);
  1499. if (IS_ERR(kthread)) {
  1500. pr_err(BANNER "could not start sampling thread\n");
  1501. stop_per_cpu_kthreads();
  1502. return -ENOMEM;
  1503. }
  1504. per_cpu(per_cpu_osnoise_var, cpu).kthread = kthread;
  1505. return 0;
  1506. }
  1507. /*
  1508. * start_per_cpu_kthread - Kick off per-cpu osnoise sampling kthreads
  1509. *
  1510. * This starts the kernel thread that will look for osnoise on many
  1511. * cpus.
  1512. */
  1513. static int start_per_cpu_kthreads(void)
  1514. {
  1515. struct cpumask *current_mask = &save_cpumask;
  1516. int retval = 0;
  1517. int cpu;
  1518. cpus_read_lock();
  1519. /*
  1520. * Run only on online CPUs in which osnoise is allowed to run.
  1521. */
  1522. cpumask_and(current_mask, cpu_online_mask, &osnoise_cpumask);
  1523. for_each_possible_cpu(cpu)
  1524. per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
  1525. for_each_cpu(cpu, current_mask) {
  1526. retval = start_kthread(cpu);
  1527. if (retval) {
  1528. cpus_read_unlock();
  1529. stop_per_cpu_kthreads();
  1530. return retval;
  1531. }
  1532. }
  1533. cpus_read_unlock();
  1534. return retval;
  1535. }
  1536. #ifdef CONFIG_HOTPLUG_CPU
  1537. static void osnoise_hotplug_workfn(struct work_struct *dummy)
  1538. {
  1539. unsigned int cpu = smp_processor_id();
  1540. mutex_lock(&trace_types_lock);
  1541. if (!osnoise_has_registered_instances())
  1542. goto out_unlock_trace;
  1543. mutex_lock(&interface_lock);
  1544. cpus_read_lock();
  1545. if (!cpumask_test_cpu(cpu, &osnoise_cpumask))
  1546. goto out_unlock;
  1547. start_kthread(cpu);
  1548. out_unlock:
  1549. cpus_read_unlock();
  1550. mutex_unlock(&interface_lock);
  1551. out_unlock_trace:
  1552. mutex_unlock(&trace_types_lock);
  1553. }
  1554. static DECLARE_WORK(osnoise_hotplug_work, osnoise_hotplug_workfn);
  1555. /*
  1556. * osnoise_cpu_init - CPU hotplug online callback function
  1557. */
  1558. static int osnoise_cpu_init(unsigned int cpu)
  1559. {
  1560. schedule_work_on(cpu, &osnoise_hotplug_work);
  1561. return 0;
  1562. }
  1563. /*
  1564. * osnoise_cpu_die - CPU hotplug offline callback function
  1565. */
  1566. static int osnoise_cpu_die(unsigned int cpu)
  1567. {
  1568. stop_kthread(cpu);
  1569. return 0;
  1570. }
  1571. static void osnoise_init_hotplug_support(void)
  1572. {
  1573. int ret;
  1574. ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "trace/osnoise:online",
  1575. osnoise_cpu_init, osnoise_cpu_die);
  1576. if (ret < 0)
  1577. pr_warn(BANNER "Error to init cpu hotplug support\n");
  1578. return;
  1579. }
  1580. #else /* CONFIG_HOTPLUG_CPU */
  1581. static void osnoise_init_hotplug_support(void)
  1582. {
  1583. return;
  1584. }
  1585. #endif /* CONFIG_HOTPLUG_CPU */
  1586. /*
  1587. * osnoise_cpus_read - Read function for reading the "cpus" file
  1588. * @filp: The active open file structure
  1589. * @ubuf: The userspace provided buffer to read value into
  1590. * @cnt: The maximum number of bytes to read
  1591. * @ppos: The current "file" position
  1592. *
  1593. * Prints the "cpus" output into the user-provided buffer.
  1594. */
  1595. static ssize_t
  1596. osnoise_cpus_read(struct file *filp, char __user *ubuf, size_t count,
  1597. loff_t *ppos)
  1598. {
  1599. char *mask_str;
  1600. int len;
  1601. mutex_lock(&interface_lock);
  1602. len = snprintf(NULL, 0, "%*pbl\n", cpumask_pr_args(&osnoise_cpumask)) + 1;
  1603. mask_str = kmalloc(len, GFP_KERNEL);
  1604. if (!mask_str) {
  1605. count = -ENOMEM;
  1606. goto out_unlock;
  1607. }
  1608. len = snprintf(mask_str, len, "%*pbl\n", cpumask_pr_args(&osnoise_cpumask));
  1609. if (len >= count) {
  1610. count = -EINVAL;
  1611. goto out_free;
  1612. }
  1613. count = simple_read_from_buffer(ubuf, count, ppos, mask_str, len);
  1614. out_free:
  1615. kfree(mask_str);
  1616. out_unlock:
  1617. mutex_unlock(&interface_lock);
  1618. return count;
  1619. }
  1620. /*
  1621. * osnoise_cpus_write - Write function for "cpus" entry
  1622. * @filp: The active open file structure
  1623. * @ubuf: The user buffer that contains the value to write
  1624. * @cnt: The maximum number of bytes to write to "file"
  1625. * @ppos: The current position in @file
  1626. *
  1627. * This function provides a write implementation for the "cpus"
  1628. * interface to the osnoise trace. By default, it lists all CPUs,
  1629. * in this way, allowing osnoise threads to run on any online CPU
  1630. * of the system. It serves to restrict the execution of osnoise to the
  1631. * set of CPUs writing via this interface. Why not use "tracing_cpumask"?
  1632. * Because the user might be interested in tracing what is running on
  1633. * other CPUs. For instance, one might run osnoise in one HT CPU
  1634. * while observing what is running on the sibling HT CPU.
  1635. */
  1636. static ssize_t
  1637. osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,
  1638. loff_t *ppos)
  1639. {
  1640. cpumask_var_t osnoise_cpumask_new;
  1641. int running, err;
  1642. char buf[256];
  1643. if (count >= 256)
  1644. return -EINVAL;
  1645. if (copy_from_user(buf, ubuf, count))
  1646. return -EFAULT;
  1647. if (!zalloc_cpumask_var(&osnoise_cpumask_new, GFP_KERNEL))
  1648. return -ENOMEM;
  1649. err = cpulist_parse(buf, osnoise_cpumask_new);
  1650. if (err)
  1651. goto err_free;
  1652. /*
  1653. * trace_types_lock is taken to avoid concurrency on start/stop.
  1654. */
  1655. mutex_lock(&trace_types_lock);
  1656. running = osnoise_has_registered_instances();
  1657. if (running)
  1658. stop_per_cpu_kthreads();
  1659. mutex_lock(&interface_lock);
  1660. /*
  1661. * osnoise_cpumask is read by CPU hotplug operations.
  1662. */
  1663. cpus_read_lock();
  1664. cpumask_copy(&osnoise_cpumask, osnoise_cpumask_new);
  1665. cpus_read_unlock();
  1666. mutex_unlock(&interface_lock);
  1667. if (running)
  1668. start_per_cpu_kthreads();
  1669. mutex_unlock(&trace_types_lock);
  1670. free_cpumask_var(osnoise_cpumask_new);
  1671. return count;
  1672. err_free:
  1673. free_cpumask_var(osnoise_cpumask_new);
  1674. return err;
  1675. }
  1676. /*
  1677. * osnoise/runtime_us: cannot be greater than the period.
  1678. */
  1679. static struct trace_min_max_param osnoise_runtime = {
  1680. .lock = &interface_lock,
  1681. .val = &osnoise_data.sample_runtime,
  1682. .max = &osnoise_data.sample_period,
  1683. .min = NULL,
  1684. };
  1685. /*
  1686. * osnoise/period_us: cannot be smaller than the runtime.
  1687. */
  1688. static struct trace_min_max_param osnoise_period = {
  1689. .lock = &interface_lock,
  1690. .val = &osnoise_data.sample_period,
  1691. .max = NULL,
  1692. .min = &osnoise_data.sample_runtime,
  1693. };
  1694. /*
  1695. * osnoise/stop_tracing_us: no limit.
  1696. */
  1697. static struct trace_min_max_param osnoise_stop_tracing_in = {
  1698. .lock = &interface_lock,
  1699. .val = &osnoise_data.stop_tracing,
  1700. .max = NULL,
  1701. .min = NULL,
  1702. };
  1703. /*
  1704. * osnoise/stop_tracing_total_us: no limit.
  1705. */
  1706. static struct trace_min_max_param osnoise_stop_tracing_total = {
  1707. .lock = &interface_lock,
  1708. .val = &osnoise_data.stop_tracing_total,
  1709. .max = NULL,
  1710. .min = NULL,
  1711. };
  1712. #ifdef CONFIG_TIMERLAT_TRACER
  1713. /*
  1714. * osnoise/print_stack: print the stacktrace of the IRQ handler if the total
  1715. * latency is higher than val.
  1716. */
  1717. static struct trace_min_max_param osnoise_print_stack = {
  1718. .lock = &interface_lock,
  1719. .val = &osnoise_data.print_stack,
  1720. .max = NULL,
  1721. .min = NULL,
  1722. };
  1723. /*
  1724. * osnoise/timerlat_period: min 100 us, max 1 s
  1725. */
  1726. u64 timerlat_min_period = 100;
  1727. u64 timerlat_max_period = 1000000;
  1728. static struct trace_min_max_param timerlat_period = {
  1729. .lock = &interface_lock,
  1730. .val = &osnoise_data.timerlat_period,
  1731. .max = &timerlat_max_period,
  1732. .min = &timerlat_min_period,
  1733. };
  1734. #endif
  1735. static const struct file_operations cpus_fops = {
  1736. .open = tracing_open_generic,
  1737. .read = osnoise_cpus_read,
  1738. .write = osnoise_cpus_write,
  1739. .llseek = generic_file_llseek,
  1740. };
  1741. #ifdef CONFIG_TIMERLAT_TRACER
  1742. #ifdef CONFIG_STACKTRACE
  1743. static int init_timerlat_stack_tracefs(struct dentry *top_dir)
  1744. {
  1745. struct dentry *tmp;
  1746. tmp = tracefs_create_file("print_stack", TRACE_MODE_WRITE, top_dir,
  1747. &osnoise_print_stack, &trace_min_max_fops);
  1748. if (!tmp)
  1749. return -ENOMEM;
  1750. return 0;
  1751. }
  1752. #else /* CONFIG_STACKTRACE */
  1753. static int init_timerlat_stack_tracefs(struct dentry *top_dir)
  1754. {
  1755. return 0;
  1756. }
  1757. #endif /* CONFIG_STACKTRACE */
  1758. /*
  1759. * init_timerlat_tracefs - A function to initialize the timerlat interface files
  1760. */
  1761. static int init_timerlat_tracefs(struct dentry *top_dir)
  1762. {
  1763. struct dentry *tmp;
  1764. tmp = tracefs_create_file("timerlat_period_us", TRACE_MODE_WRITE, top_dir,
  1765. &timerlat_period, &trace_min_max_fops);
  1766. if (!tmp)
  1767. return -ENOMEM;
  1768. return init_timerlat_stack_tracefs(top_dir);
  1769. }
  1770. #else /* CONFIG_TIMERLAT_TRACER */
  1771. static int init_timerlat_tracefs(struct dentry *top_dir)
  1772. {
  1773. return 0;
  1774. }
  1775. #endif /* CONFIG_TIMERLAT_TRACER */
  1776. /*
  1777. * init_tracefs - A function to initialize the tracefs interface files
  1778. *
  1779. * This function creates entries in tracefs for "osnoise" and "timerlat".
  1780. * It creates these directories in the tracing directory, and within that
  1781. * directory the use can change and view the configs.
  1782. */
  1783. static int init_tracefs(void)
  1784. {
  1785. struct dentry *top_dir;
  1786. struct dentry *tmp;
  1787. int ret;
  1788. ret = tracing_init_dentry();
  1789. if (ret)
  1790. return -ENOMEM;
  1791. top_dir = tracefs_create_dir("osnoise", NULL);
  1792. if (!top_dir)
  1793. return 0;
  1794. tmp = tracefs_create_file("period_us", TRACE_MODE_WRITE, top_dir,
  1795. &osnoise_period, &trace_min_max_fops);
  1796. if (!tmp)
  1797. goto err;
  1798. tmp = tracefs_create_file("runtime_us", TRACE_MODE_WRITE, top_dir,
  1799. &osnoise_runtime, &trace_min_max_fops);
  1800. if (!tmp)
  1801. goto err;
  1802. tmp = tracefs_create_file("stop_tracing_us", TRACE_MODE_WRITE, top_dir,
  1803. &osnoise_stop_tracing_in, &trace_min_max_fops);
  1804. if (!tmp)
  1805. goto err;
  1806. tmp = tracefs_create_file("stop_tracing_total_us", TRACE_MODE_WRITE, top_dir,
  1807. &osnoise_stop_tracing_total, &trace_min_max_fops);
  1808. if (!tmp)
  1809. goto err;
  1810. tmp = trace_create_file("cpus", TRACE_MODE_WRITE, top_dir, NULL, &cpus_fops);
  1811. if (!tmp)
  1812. goto err;
  1813. ret = init_timerlat_tracefs(top_dir);
  1814. if (ret)
  1815. goto err;
  1816. return 0;
  1817. err:
  1818. tracefs_remove(top_dir);
  1819. return -ENOMEM;
  1820. }
  1821. static int osnoise_hook_events(void)
  1822. {
  1823. int retval;
  1824. /*
  1825. * Trace is already hooked, we are re-enabling from
  1826. * a stop_tracing_*.
  1827. */
  1828. if (trace_osnoise_callback_enabled)
  1829. return 0;
  1830. retval = hook_irq_events();
  1831. if (retval)
  1832. return -EINVAL;
  1833. retval = hook_softirq_events();
  1834. if (retval)
  1835. goto out_unhook_irq;
  1836. retval = hook_thread_events();
  1837. /*
  1838. * All fine!
  1839. */
  1840. if (!retval)
  1841. return 0;
  1842. unhook_softirq_events();
  1843. out_unhook_irq:
  1844. unhook_irq_events();
  1845. return -EINVAL;
  1846. }
  1847. static void osnoise_unhook_events(void)
  1848. {
  1849. unhook_thread_events();
  1850. unhook_softirq_events();
  1851. unhook_irq_events();
  1852. }
  1853. /*
  1854. * osnoise_workload_start - start the workload and hook to events
  1855. */
  1856. static int osnoise_workload_start(void)
  1857. {
  1858. int retval;
  1859. /*
  1860. * Instances need to be registered after calling workload
  1861. * start. Hence, if there is already an instance, the
  1862. * workload was already registered. Otherwise, this
  1863. * code is on the way to register the first instance,
  1864. * and the workload will start.
  1865. */
  1866. if (osnoise_has_registered_instances())
  1867. return 0;
  1868. osn_var_reset_all();
  1869. retval = osnoise_hook_events();
  1870. if (retval)
  1871. return retval;
  1872. /*
  1873. * Make sure that ftrace_nmi_enter/exit() see reset values
  1874. * before enabling trace_osnoise_callback_enabled.
  1875. */
  1876. barrier();
  1877. trace_osnoise_callback_enabled = true;
  1878. retval = start_per_cpu_kthreads();
  1879. if (retval) {
  1880. trace_osnoise_callback_enabled = false;
  1881. /*
  1882. * Make sure that ftrace_nmi_enter/exit() see
  1883. * trace_osnoise_callback_enabled as false before continuing.
  1884. */
  1885. barrier();
  1886. osnoise_unhook_events();
  1887. return retval;
  1888. }
  1889. return 0;
  1890. }
  1891. /*
  1892. * osnoise_workload_stop - stop the workload and unhook the events
  1893. */
  1894. static void osnoise_workload_stop(void)
  1895. {
  1896. /*
  1897. * Instances need to be unregistered before calling
  1898. * stop. Hence, if there is a registered instance, more
  1899. * than one instance is running, and the workload will not
  1900. * yet stop. Otherwise, this code is on the way to disable
  1901. * the last instance, and the workload can stop.
  1902. */
  1903. if (osnoise_has_registered_instances())
  1904. return;
  1905. /*
  1906. * If callbacks were already disabled in a previous stop
  1907. * call, there is no need to disable then again.
  1908. *
  1909. * For instance, this happens when tracing is stopped via:
  1910. * echo 0 > tracing_on
  1911. * echo nop > current_tracer.
  1912. */
  1913. if (!trace_osnoise_callback_enabled)
  1914. return;
  1915. trace_osnoise_callback_enabled = false;
  1916. /*
  1917. * Make sure that ftrace_nmi_enter/exit() see
  1918. * trace_osnoise_callback_enabled as false before continuing.
  1919. */
  1920. barrier();
  1921. stop_per_cpu_kthreads();
  1922. osnoise_unhook_events();
  1923. }
  1924. static void osnoise_tracer_start(struct trace_array *tr)
  1925. {
  1926. int retval;
  1927. /*
  1928. * If the instance is already registered, there is no need to
  1929. * register it again.
  1930. */
  1931. if (osnoise_instance_registered(tr))
  1932. return;
  1933. retval = osnoise_workload_start();
  1934. if (retval)
  1935. pr_err(BANNER "Error starting osnoise tracer\n");
  1936. osnoise_register_instance(tr);
  1937. }
  1938. static void osnoise_tracer_stop(struct trace_array *tr)
  1939. {
  1940. osnoise_unregister_instance(tr);
  1941. osnoise_workload_stop();
  1942. }
  1943. static int osnoise_tracer_init(struct trace_array *tr)
  1944. {
  1945. /*
  1946. * Only allow osnoise tracer if timerlat tracer is not running
  1947. * already.
  1948. */
  1949. if (timerlat_enabled())
  1950. return -EBUSY;
  1951. tr->max_latency = 0;
  1952. osnoise_tracer_start(tr);
  1953. return 0;
  1954. }
  1955. static void osnoise_tracer_reset(struct trace_array *tr)
  1956. {
  1957. osnoise_tracer_stop(tr);
  1958. }
  1959. static struct tracer osnoise_tracer __read_mostly = {
  1960. .name = "osnoise",
  1961. .init = osnoise_tracer_init,
  1962. .reset = osnoise_tracer_reset,
  1963. .start = osnoise_tracer_start,
  1964. .stop = osnoise_tracer_stop,
  1965. .print_header = print_osnoise_headers,
  1966. .allow_instances = true,
  1967. };
  1968. #ifdef CONFIG_TIMERLAT_TRACER
  1969. static void timerlat_tracer_start(struct trace_array *tr)
  1970. {
  1971. int retval;
  1972. /*
  1973. * If the instance is already registered, there is no need to
  1974. * register it again.
  1975. */
  1976. if (osnoise_instance_registered(tr))
  1977. return;
  1978. retval = osnoise_workload_start();
  1979. if (retval)
  1980. pr_err(BANNER "Error starting timerlat tracer\n");
  1981. osnoise_register_instance(tr);
  1982. return;
  1983. }
  1984. static void timerlat_tracer_stop(struct trace_array *tr)
  1985. {
  1986. int cpu;
  1987. osnoise_unregister_instance(tr);
  1988. /*
  1989. * Instruct the threads to stop only if this is the last instance.
  1990. */
  1991. if (!osnoise_has_registered_instances()) {
  1992. for_each_online_cpu(cpu)
  1993. per_cpu(per_cpu_osnoise_var, cpu).sampling = 0;
  1994. }
  1995. osnoise_workload_stop();
  1996. }
  1997. static int timerlat_tracer_init(struct trace_array *tr)
  1998. {
  1999. /*
  2000. * Only allow timerlat tracer if osnoise tracer is not running already.
  2001. */
  2002. if (osnoise_has_registered_instances() && !osnoise_data.timerlat_tracer)
  2003. return -EBUSY;
  2004. /*
  2005. * If this is the first instance, set timerlat_tracer to block
  2006. * osnoise tracer start.
  2007. */
  2008. if (!osnoise_has_registered_instances())
  2009. osnoise_data.timerlat_tracer = 1;
  2010. tr->max_latency = 0;
  2011. timerlat_tracer_start(tr);
  2012. return 0;
  2013. }
  2014. static void timerlat_tracer_reset(struct trace_array *tr)
  2015. {
  2016. timerlat_tracer_stop(tr);
  2017. /*
  2018. * If this is the last instance, reset timerlat_tracer allowing
  2019. * osnoise to be started.
  2020. */
  2021. if (!osnoise_has_registered_instances())
  2022. osnoise_data.timerlat_tracer = 0;
  2023. }
  2024. static struct tracer timerlat_tracer __read_mostly = {
  2025. .name = "timerlat",
  2026. .init = timerlat_tracer_init,
  2027. .reset = timerlat_tracer_reset,
  2028. .start = timerlat_tracer_start,
  2029. .stop = timerlat_tracer_stop,
  2030. .print_header = print_timerlat_headers,
  2031. .allow_instances = true,
  2032. };
  2033. __init static int init_timerlat_tracer(void)
  2034. {
  2035. return register_tracer(&timerlat_tracer);
  2036. }
  2037. #else /* CONFIG_TIMERLAT_TRACER */
  2038. __init static int init_timerlat_tracer(void)
  2039. {
  2040. return 0;
  2041. }
  2042. #endif /* CONFIG_TIMERLAT_TRACER */
  2043. __init static int init_osnoise_tracer(void)
  2044. {
  2045. int ret;
  2046. mutex_init(&interface_lock);
  2047. cpumask_copy(&osnoise_cpumask, cpu_all_mask);
  2048. ret = register_tracer(&osnoise_tracer);
  2049. if (ret) {
  2050. pr_err(BANNER "Error registering osnoise!\n");
  2051. return ret;
  2052. }
  2053. ret = init_timerlat_tracer();
  2054. if (ret) {
  2055. pr_err(BANNER "Error registering timerlat!\n");
  2056. return ret;
  2057. }
  2058. osnoise_init_hotplug_support();
  2059. INIT_LIST_HEAD_RCU(&osnoise_instances);
  2060. init_tracefs();
  2061. return 0;
  2062. }
  2063. late_initcall(init_osnoise_tracer);