Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: trapcount.cc | |
4 | // Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
5 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
6 | // | |
7 | // The above named program is free software; you can redistribute it and/or | |
8 | // modify it under the terms of the GNU General Public | |
9 | // License version 2 as published by the Free Software Foundation. | |
10 | // | |
11 | // The above named program is distributed in the hope that it will be | |
12 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | // General Public License for more details. | |
15 | // | |
16 | // You should have received a copy of the GNU General Public | |
17 | // License along with this work; if not, write to the Free Software | |
18 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
19 | // | |
20 | // ========== Copyright Header End ============================================ | |
21 | /* icq: TRACER INSTR TRAP TLB | |
22 | * | |
23 | * trapcount.cc | |
24 | * | |
25 | * | |
26 | * the Good: | |
27 | * the Bad: | |
28 | * and the Ugly: | |
29 | * numcpus = g_nvcpu_max; system.h, non-transferable to trace reader :-(. | |
30 | * UI_(un)register... ui.h, non-transferable to trace reader :-(. | |
31 | */ | |
32 | ||
33 | // standard C includes ------------------------------- | |
34 | #include <stdio.h> | |
35 | ||
36 | // standard C++/STL includes ------------------------------- | |
37 | ||
38 | // project includes ------------------------------- | |
39 | #include "system.h" // need g_nvcpus <--- NG. | |
40 | #include "ui.h" // need UI_register and UI_unregister <--- NG. | |
41 | ||
42 | ||
43 | ||
44 | // program includes ------------------------------- | |
45 | #include "../../system/util/include/atomic.h" // Argh!!!... | |
46 | #include "my_sparc.h" | |
47 | #include "sc_strings.h" | |
48 | #include "tt_strings.h" | |
49 | #include "trapcount.h" | |
50 | ||
51 | // boilerplate ------------------------------- | |
52 | ||
53 | ||
54 | // local definitions ------------------------------- | |
55 | #define BAD14 1 /* can't count 0x04e traps as interval timer any more */ | |
56 | ||
57 | ||
58 | // global variables ------------------------------- | |
59 | ||
60 | // global state | |
61 | static int CountingOn = 1; | |
62 | ||
63 | // feature options | |
64 | ||
65 | ||
66 | // debug options | |
67 | static int DEBUG = 0; | |
68 | static int VERBOSE = 0; | |
69 | ||
70 | ||
71 | // global functions ------------------------------- | |
72 | ||
73 | ||
74 | #if 0 /* we want more flexibility that Safari/Serengeti constraints allow */ | |
75 | // from Serengeti Specification (an implementation of Safari Bus) | |
76 | // lower 5-bits are AgentId | |
77 | #define ISCPUID(x) (((x) & 0x1f) < 24) // AgentIDs 0..23 = cpus | |
78 | #define ISSCHIZOID(x) (((x) & 0x1f) >= 24) // AgentIDs 24..31 = schizos | |
79 | // and upper 4-bits are NodeId. | |
80 | #else | |
81 | // x = SystemId = NodeId<<5+AgentId | |
82 | #define ISCPUID(x) (get_vcpu(x) != NULL) | |
83 | #define ISSCHIZOID(x) (get_vcpu(x) == NULL) | |
84 | #endif | |
85 | ||
86 | ||
87 | ||
88 | ||
89 | #define UNPACKINOAID(i) (((i >> 4) & 0x1e0) | 0x18 | ((i >> 6) & 0x7)) | |
90 | ||
91 | ||
92 | ||
93 | // ===================================================================== MODULE | |
94 | ||
95 | ||
96 | static const char * mode_names[10]; | |
97 | ||
98 | static trapcount * the_trapcount = NULL; | |
99 | ||
100 | extern "C" void * vtracer_init (const char * instname) // --------- module init | |
101 | { | |
102 | if (the_trapcount == NULL) { | |
103 | the_trapcount = new trapcount (instname); | |
104 | UI_register_cmd_2 ("trapcount", "", trapcount::trapcount_ui_cmds, NULL); | |
105 | } else | |
106 | fprintf(stderr, "Error: trapcount already module_init'ed\n"); | |
107 | return (void*) the_trapcount; | |
108 | } | |
109 | ||
110 | extern "C" void vtracer_fini () // -------------------------------- module fini | |
111 | { | |
112 | if (the_trapcount != NULL) { | |
113 | UI_invalidate_cmd ("trapcount"); /* aka: UI_unregister_cmd */ | |
114 | delete the_trapcount; | |
115 | the_trapcount = NULL; | |
116 | } else | |
117 | fprintf(stderr, "Error: trapcount already module_fini'ed\n"); | |
118 | } | |
119 | ||
120 | ||
121 | ||
122 | ||
123 | Counters::Counters () // -------------------------------------------- ctor | |
124 | { | |
125 | Reset (); | |
126 | } | |
127 | ||
128 | ||
129 | void Counters::Reset () | |
130 | { | |
131 | instrcount = 0LL; | |
132 | hypercount = 0LL; | |
133 | kernelcount = 0LL; | |
134 | usercount = 0LL; | |
135 | for (int i=0; i<MAX_TRAPTYPES; i++) traptypecount[i] = 0LL; | |
136 | for (int i=0; i<MAX_SYSCALLS; i++) syscallscount[i] = 0LL; | |
137 | for (int i=0; i<MAX_NCPUS; i++) mondoxcalcount[i] = 0LL; | |
138 | // for (int i=0; i<MAX_INOS; i++) mondoinocount[i] = 0LL; | |
139 | for (inoiter ip=mondoinocount.begin(); | |
140 | ip!=mondoinocount.end(); | |
141 | ip++) | |
142 | ip->second = 0LL; | |
143 | // alternatively... | |
144 | // mondoinocount.erase (mondoinocount.begin(), mondoinocount.end()); | |
145 | } | |
146 | ||
147 | ||
148 | ||
149 | ||
150 | ||
151 | ||
152 | ||
153 | trapcount::trapcount (const char * tmp_modname) // ======================= CTOR | |
154 | { | |
155 | printf("trapcount::ctor (modname=>\"%s\"), numcpus=%d \n", | |
156 | tmp_modname, g_nvcpu); | |
157 | ||
158 | mode_names[MODE_NONE] = "none"; | |
159 | mode_names[MODE_AGGREGATE] = "aggregate"; | |
160 | mode_names[MODE_BY_CPU] = "cpu"; | |
161 | mode_names[MODE_BY_MMUCNTX] = "mmucntx"; | |
162 | mode_names[MODE_BY_THREAD] = "thread"; | |
163 | ||
164 | intervalsCounter = 0; | |
165 | ||
166 | mode = MODE_NONE; | |
167 | configure_for_mode (MODE_BY_CPU); // <--- default mode <--- | |
168 | ||
169 | numcpus = g_nvcpu; /* system.h - cpu_interface.h (argh!) */ | |
170 | // numschizos = ???; /* need to know all Agent IDs ??? ... */ | |
171 | } | |
172 | ||
173 | trapcount::~trapcount () // ============================================== DTOR | |
174 | { | |
175 | } | |
176 | ||
177 | /*static*/ | |
178 | int trapcount::trapcount_ui_cmds (void*notused, int argc, char *argv[]) | |
179 | { | |
180 | if (strcmp (argv[0], "trapcount") != 0) return 0; | |
181 | ||
182 | if (argc == 1) { // status | |
183 | printf ("trapcount: counting = %s, mode = %s.\n", | |
184 | (CountingOn ? "on" : "off"), | |
185 | mode_names[the_trapcount->mode]); | |
186 | return 1; | |
187 | } | |
188 | ||
189 | if (argc >= 2 && strcmp (argv[1], "mode") == 0) { // mode | |
190 | if (argc >= 3) { | |
191 | if (strcmp (argv[2], "aggregate") == 0) | |
192 | the_trapcount->configure_for_mode (MODE_AGGREGATE); | |
193 | else if (strcmp (argv[2], "cpu") == 0) | |
194 | the_trapcount->configure_for_mode (MODE_BY_CPU); | |
195 | else if (strcmp (argv[2], "mmucntx") == 0) | |
196 | the_trapcount->configure_for_mode (MODE_BY_MMUCNTX); | |
197 | else if (strcmp (argv[2], "thread") == 0) | |
198 | the_trapcount->configure_for_mode (MODE_BY_THREAD); | |
199 | else | |
200 | printf (" * unrecognized mode arg\n"); | |
201 | } | |
202 | fprintf (stderr, "trapcount mode is %s\n", | |
203 | mode_names[ the_trapcount->mode ]); | |
204 | return 1; | |
205 | } | |
206 | ||
207 | if (argc >= 2 && strcmp (argv[1], "peek") == 0) { // peek | |
208 | the_trapcount->printCounts (0/*dont reset*/); | |
209 | return 1; | |
210 | } | |
211 | ||
212 | if (argc >= 2 && (strcmp (argv[1], "print") == 0 // print | |
213 | || strcmp (argv[1], "stats") == 0)) { // stats | |
214 | the_trapcount->printCounts (1/*do reset*/); | |
215 | return 1; | |
216 | } | |
217 | ||
218 | if (argc >= 2 && strcmp (argv[1], "debug") == 0) { // debug | |
219 | if (argc == 3) { DEBUG = (int) strtol (argv[2], NULL, 0); } | |
220 | fprintf (stderr, "trapcount debug level is %d\n", DEBUG); | |
221 | return 1; | |
222 | } | |
223 | ||
224 | if (strcmp (argv[1], "on") == 0) { // On/Off | |
225 | CountingOn = 1; | |
226 | return 1; | |
227 | } | |
228 | if (strcmp (argv[1], "off") == 0) { | |
229 | CountingOn = 0; | |
230 | return 1; | |
231 | } | |
232 | ||
233 | ||
234 | ||
235 | ||
236 | return 0; | |
237 | } | |
238 | ||
239 | ||
240 | ||
241 | int trapcount::attach (VTracer_SAM_intf * sam_intf) | |
242 | { | |
243 | return 0; // do nothing... | |
244 | } | |
245 | ||
246 | ||
247 | ||
248 | // -------- friendly reminder -------- | |
249 | //class Counters { | |
250 | //public: | |
251 | // int64 instrcount, | |
252 | // kernelcount, | |
253 | // usercount; | |
254 | // int64 traptypecount[ MAX_TRAPTYPES ]; | |
255 | // int64 syscallscount[ MAX_SYSCALLS ]; | |
256 | // int64 mondoxcalcount[ MAX_NCPUS ]; | |
257 | // //int64 mondoinocount[ MAX_INOS ]; | |
258 | // inoarray64_t mondoinocount; | |
259 | // | |
260 | // Counters (); | |
261 | //}; | |
262 | ||
263 | ||
264 | void trapcount::printCounts (int reset) // ======================= print counts | |
265 | { | |
266 | switch (mode) { | |
267 | ||
268 | case MODE_AGGREGATE: { | |
269 | ||
270 | printf (" aggregate: %12lld-instrs %12lld-kernel %12lld-user \n", | |
271 | aggregate->instrcount, | |
272 | aggregate->kernelcount, | |
273 | aggregate->usercount); | |
274 | ||
275 | for (int i=0; i<MAX_TRAPTYPES; i++) | |
276 | if (aggregate->traptypecount[ i ]) | |
277 | printf (" tt-0x%03x %12lld %s\n", | |
278 | i, | |
279 | aggregate->traptypecount[ i ], | |
280 | tt_names[ i ]); | |
281 | ||
282 | for (int i=0; i<MAX_SYSCALLS; i++) | |
283 | if (aggregate->syscallscount[ i ]) | |
284 | printf (" sc-0x%03x %12lld %s\n", | |
285 | i, | |
286 | aggregate->syscallscount[ i ], | |
287 | sc_names[ i ]); | |
288 | ||
289 | for (inoiter ip=aggregate->mondoinocount.begin(); | |
290 | ip!=aggregate->mondoinocount.end(); | |
291 | ip++) | |
292 | if (ip->second != 0) /*aggregate->mondoinocount[i] != 0)*/ | |
293 | printf (" zm-0x%03x %12lld (%02x,%02x) \n", | |
294 | ip->first, /*i,*/ | |
295 | ip->second, /*aggregate->mondoinocount[ i ],*/ | |
296 | ip->first >> 6, /*i >> 6,*/ // NodeID and AgentID | |
297 | ip->first & 0x3f); /*i & 0x3f);*/ // DeviceNo | |
298 | ||
299 | for (int i=0; i<MAX_NCPUS; i++) | |
300 | if (aggregate->mondoxcalcount[ i ]) | |
301 | printf (" xm-0x%03x %12lld \n", | |
302 | i, | |
303 | aggregate->mondoxcalcount[ i ]); | |
304 | ||
305 | if (reset) aggregate->Reset (); | |
306 | printf ("\n"); | |
307 | ||
308 | } break; | |
309 | ||
310 | case MODE_BY_CPU: { | |
311 | // someday: put each cpu in a column... | |
312 | ||
313 | for (int j=0; j<numcpus; j++) { | |
314 | ||
315 | printf (" cpu[%d]::: %12lld-instrs %12lld-kernel %12lld-user \n", | |
316 | j, | |
317 | cpus[j].instrcount, | |
318 | cpus[j].kernelcount, | |
319 | cpus[j].usercount); | |
320 | ||
321 | for (int i=0; i<MAX_TRAPTYPES; i++) | |
322 | if (cpus[j].traptypecount[ i ]) | |
323 | printf (" tt-0x%03x %12lld %s\n", | |
324 | i, | |
325 | cpus[j].traptypecount[ i ], | |
326 | tt_names[ i ]); | |
327 | ||
328 | for (int i=0; i<MAX_SYSCALLS; i++) | |
329 | if (cpus[j].syscallscount[ i ]) | |
330 | printf (" sc-0x%03x %12lld %s\n", | |
331 | i, | |
332 | cpus[j].syscallscount[ i ], | |
333 | sc_names[ i ]); | |
334 | ||
335 | for (inoiter ip=cpus[j].mondoinocount.begin(); | |
336 | ip!=cpus[j].mondoinocount.end(); | |
337 | ip++) | |
338 | if (ip->second != 0) /*cpus[j].mondoinocount[i] != 0)*/ | |
339 | printf (" md-0x%03x %12lld (%02x,%02x) \n", | |
340 | ip->first, /*i,*/ | |
341 | ip->second, /*cpus[j]->mondoinocount[ i ],*/ | |
342 | ip->first >> 6, /*i >> 6,*/ // NodeID and AgentID | |
343 | ip->first & 0x3f); /*i & 0x3f);*/ // DeviceNo | |
344 | ||
345 | for (int i=0; i<MAX_NCPUS; i++) | |
346 | if (cpus[j].mondoxcalcount[ i ]) | |
347 | printf (" md-0x%03x %12lld \n", | |
348 | i, | |
349 | cpus[j].mondoxcalcount[ i ]); | |
350 | ||
351 | ||
352 | if (reset) cpus[j].Reset (); | |
353 | printf ("\n"); | |
354 | ||
355 | }/*end-for-cpu*/ | |
356 | ||
357 | } break; | |
358 | ||
359 | default: | |
360 | printf ("printing mode %s not currently supported\n", mode_names[mode]); | |
361 | } | |
362 | } | |
363 | ||
364 | ||
365 | ||
366 | void trapcount::configure_for_mode (modes newmode) // ======= configure mode | |
367 | { | |
368 | if (newmode == mode) | |
369 | return; // we're already there... | |
370 | ||
371 | // allocate new counters | |
372 | // | |
373 | switch (newmode) { | |
374 | case MODE_NONE: | |
375 | break; | |
376 | case MODE_AGGREGATE: | |
377 | aggregate = new Counters; | |
378 | break; | |
379 | case MODE_BY_CPU: | |
380 | cpus = new Counters[MAX_NCPUS]; // array, be careful at delete! | |
381 | break; | |
382 | case MODE_BY_MMUCNTX: | |
383 | mmucntxs = new MmucntxCounters; | |
384 | break; | |
385 | case MODE_BY_THREAD: | |
386 | threads = new ThreadCounters; | |
387 | break; | |
388 | default: | |
389 | mode = MODE_NONE; | |
390 | fprintf(stderr, "Trapcount error: unimplemented mode\n"); | |
391 | } | |
392 | ||
393 | // warning: deleting the old counters creates a race condition... | |
394 | // which is worse (fatal!) than the alternative, a memory leak... | |
395 | #if 0 | |
396 | // deallocate previous counters | |
397 | // | |
398 | switch (mode) { | |
399 | case MODE_NONE: | |
400 | break; | |
401 | case MODE_AGGREGATE: | |
402 | delete aggregate; | |
403 | aggregate = NULL; | |
404 | break; | |
405 | case MODE_BY_CPU: | |
406 | delete [] cpus; | |
407 | cpus = NULL; | |
408 | break; | |
409 | case MODE_BY_MMUCNTX: | |
410 | delete mmucntxs; | |
411 | mmucntxs = NULL; | |
412 | break; | |
413 | case MODE_BY_THREAD: | |
414 | delete threads; | |
415 | threads = NULL; | |
416 | break; | |
417 | default: | |
418 | fprintf(stderr, "Trapcount error: unimplemented mode\n"); | |
419 | } | |
420 | #endif | |
421 | ||
422 | // finally, update mode | |
423 | // | |
424 | mode = newmode; | |
425 | } | |
426 | ||
427 | ||
428 | ||
429 | // ================================= TRACER ================================= | |
430 | ||
431 | ||
432 | ||
433 | int trapcount::instr (VCPU_Instruction * vi) // ======================== INSTR | |
434 | { | |
435 | if (!CountingOn) return 0; | |
436 | ||
437 | if (vi->ifetch_trap) { // fake instruction in case analyzer needs pc | |
438 | return 0; | |
439 | } | |
440 | ||
441 | if (vi->annul) { // annulled (non-executed) delay slot instr | |
442 | return 0; | |
443 | } | |
444 | ||
445 | // being consistent with HW-perf-counters and cpustat, which do not count | |
446 | // annulled, mispredicted, or trapped instructions - only retired ones. | |
447 | // | |
448 | if (vi->dmmu_trap | |
449 | || vi->exception) { | |
450 | return 0; | |
451 | } | |
452 | ||
453 | ||
454 | #if 0 | |
455 | spix_sparc_inst_t spixter; spixter.inst = rsp->instr.instr; | |
456 | spix_sparc_iop_t iop = | |
457 | spix_sparc_iop(SPIX_SPARC_V9, &((rsp->instr).instr)); | |
458 | if (iop == SPIX_SPARC_IOP_WRASR) { | |
459 | ||
460 | switch (spixter.memarithr.rd) { | |
461 | case ASR_SSI: /*0x14*/ | |
462 | fprintf (stderr, "SET_SOFTINT = 0x08x\n", ???); | |
463 | case ASR_CSI: /*0x15*/ | |
464 | fprintf (stderr, "CLR_SOFTINT = 0x08x\n", ???); | |
465 | case ASR_SFTINT: /*0x16*/ | |
466 | fprintf (stderr, "WR_SOFTINT = 0x08x\n", ???); | |
467 | } | |
468 | } | |
469 | #endif | |
470 | ||
471 | ||
472 | if (mode == MODE_AGGREGATE) { | |
473 | ++ aggregate->instrcount; | |
474 | ||
475 | if (vi->hpstate & HPSTATE_PRIV) { | |
476 | ++ aggregate->hypercount; | |
477 | } else if (vi->pstate & PSTATE_PRIV) { | |
478 | ++ aggregate->kernelcount; | |
479 | } else { | |
480 | ++ aggregate->usercount; | |
481 | } | |
482 | } else if (mode == MODE_BY_CPU) { | |
483 | ++ cpus[ vi->cpuid ].instrcount; | |
484 | ||
485 | if (vi->hpstate & HPSTATE_PRIV) { | |
486 | ++ aggregate->hypercount; | |
487 | } else if (vi->pstate & PSTATE_PRIV) { | |
488 | ++ cpus[ vi->cpuid ].kernelcount; | |
489 | } else { | |
490 | ++ cpus[ vi->cpuid ].usercount; | |
491 | } | |
492 | #if 0 | |
493 | } else if (mode == MODE_BY_MMUCNTX) { | |
494 | ++ mmucntxs[ ??? ]->instrcount; | |
495 | ||
496 | if (vi->pstate & PSTATE_PRIV) { | |
497 | } else if (vi->hpstate & HPSTATE_PRIV) { | |
498 | ++ aggregate->hypercount; | |
499 | ++ mmucntxs[ ??? ]->kernelcount; | |
500 | } else { | |
501 | ++ mmucntxs[ ??? ]->usercount; | |
502 | } | |
503 | } else if (mode == MODE_BY_THREAD) { | |
504 | #endif | |
505 | } else { | |
506 | } | |
507 | return 0; | |
508 | ||
509 | }/*instr*/ | |
510 | ||
511 | ||
512 | ||
513 | int trapcount::trap (VCPU_Trap * vt) // ================================ TRAP | |
514 | { | |
515 | if (!CountingOn) return 0; | |
516 | ||
517 | if (DEBUG) { | |
518 | ||
519 | if (!VERBOSE) { /* these are too obnoxious to display normally... */ | |
520 | if (vt->tno >= 0x080 && vt->tno <= 0x0ff) /* window-miss */ | |
521 | return 0; | |
522 | if (vt->tno >= 0x024 && vt->tno <= 0x027) /* clean-win */ | |
523 | return 0; | |
524 | if (vt->tno >= 0x064 && vt->tno <= 0x06f) /* tlb-miss */ | |
525 | return 0; | |
526 | } | |
527 | ||
528 | fprintf(stderr, "[cpu-%d] Trap 0x%03x %s ", | |
529 | vt->cpuid, vt->tno, tt_names[vt->tno]); | |
530 | ||
531 | if (vt->tno == 0x108 || vt->tno == 0x140) { | |
532 | fprintf(stderr, " %d %s", | |
533 | vt->syscallno, sc_names[ vt->syscallno ]); | |
534 | } | |
535 | ||
536 | if (vt->tno == 0x060) { | |
537 | if (ISCPUID(vt->intrsid)) | |
538 | fprintf(stderr, " xcl SID = %d", vt->intrsid); | |
539 | else | |
540 | // @@@ | |
541 | fprintf(stderr, " dev INO = 0x%03x (%02x,%02x)", | |
542 | vt->intrino, (vt->intrino >> 6), (vt->intrino & 0x3f)); | |
543 | } | |
544 | ||
545 | #if !BAD14 /* Solaris uses level-14 for pci_pbm_dma_sync signalling, Yeuch! */ | |
546 | if (vt->tno == 0x04e && vt->cpuid == 0) { | |
547 | fprintf(stderr," interval-timer count = %lld", | |
548 | intervalsCounter+1); | |
549 | } | |
550 | #endif | |
551 | ||
552 | fprintf(stderr, "\n"); | |
553 | ||
554 | return 0; | |
555 | }/*debug*/ | |
556 | ||
557 | ||
558 | if (mode == MODE_AGGREGATE) { | |
559 | ||
560 | atomic_add_64 (&aggregate->traptypecount[ vt->tno ], +1); | |
561 | ||
562 | if (vt->tno == 0x108/*syscall32*/ || vt->tno == 0x140/*syscall64*/) { | |
563 | ||
564 | atomic_add_64 (&aggregate->syscallscount[ vt->syscallno ], +1); | |
565 | ||
566 | } else if (vt->tno == 0x060/*mondo*/) { | |
567 | ||
568 | if (ISCPUID(vt->intrsid)) | |
569 | atomic_add_64 (&aggregate->mondoxcalcount[ vt->intrsid ], +1); | |
570 | else | |
571 | // @@@ | |
572 | atomic_add_64 (&aggregate->mondoinocount[ vt->intrino ], +1); | |
573 | ||
574 | } | |
575 | ||
576 | } else if (mode == MODE_BY_CPU) { | |
577 | ||
578 | atomic_add_64 (&cpus[ vt->cpuid ].traptypecount[ vt->tno ], +1); | |
579 | ||
580 | if (vt->tno == 0x108/*syscall32*/ || vt->tno == 0x140/*syscall64*/) { | |
581 | ||
582 | atomic_add_64 (&cpus[ vt->cpuid ].syscallscount[ vt->syscallno ], +1); | |
583 | ||
584 | } else if (vt->tno == 0x060/*mondo*/) { | |
585 | ||
586 | if (ISCPUID(vt->intrsid)) | |
587 | atomic_add_64 (&cpus[ vt->cpuid ].mondoxcalcount[ vt->intrsid ], +1); | |
588 | else | |
589 | // @@@ | |
590 | atomic_add_64 (&cpus[ vt->cpuid ].mondoinocount[ vt->intrino ], +1); | |
591 | ||
592 | } | |
593 | #if 0 | |
594 | } else if (mode == MODE_BY_MMUCNTX) { | |
595 | ||
596 | atomic_add_64 (&mmucntxs[ vt->??? ]->traptypecount[ vt->tno ], +1); | |
597 | ||
598 | if (vt->tno == 0x108/*syscall32*/ || vt->tno == 0x140/*syscall64*/) { | |
599 | ||
600 | atomic_add_64 (&mmucntxs[ vt->??? ]->syscallscount[ vt->syscallno ], +1); | |
601 | ||
602 | } else if (vt->tno == 0x060/*mondo*/) { | |
603 | ||
604 | if (ISCPUID(vt->intrsid)) | |
605 | atomic_add_64 (&mmucntxs[ vt->??? ]->mondoxcalcount[ vt->intrsid ], +1); | |
606 | else | |
607 | // @@@ | |
608 | atomic_add_64 (&mmucntxs[ vt->??? ]->mondoinocount[ vt->intrino ], +1); | |
609 | ||
610 | } | |
611 | ||
612 | } else if (mode == MODE_BY_THREAD) { | |
613 | ||
614 | atomic_add_64 (&threads[ vt->??? ]->traptypecount[ vt->tno ], +1); | |
615 | ||
616 | if (vt->tno == 0x108/*syscall32*/ || vt->tno == 0x140/*syscall64*/) { | |
617 | ||
618 | atomic_add_64 (&threads[ vt->??? ]->syscallscount[ vt->syscallno ], +1); | |
619 | ||
620 | } else if (vt->tno == 0x060/*mondo*/) { | |
621 | ||
622 | if (ISCPUID(vt->intrsid)) | |
623 | atomic_add_64 (&threads[ vt->??? ]->mondoxcalcount[ vt->intrsid ], +1); | |
624 | else | |
625 | // @@@ | |
626 | atomic_add_64 (&threads[ vt->??? ]->mondoinocount[ vt->intrino ], +1); | |
627 | ||
628 | } | |
629 | ||
630 | } else if (mode == MODE_SEL_CPU) { | |
631 | ||
632 | } else if (mode == MODE_SEL_MMUCNTX) { | |
633 | ||
634 | } else if (mode == MODE_SEL_THREAD) { | |
635 | #endif | |
636 | } | |
637 | ||
638 | #if !BAD14 | |
639 | if (vt->tno == 0x04e && vt->cpuid == 0) { | |
640 | ++ intervalsCounter; | |
641 | if ((intervalsCounter % 100) == 0) { | |
642 | fprintf(stderr, "trapcount info: Solaris Seconds = %lld\n", | |
643 | intervalsCounter/100); | |
644 | // | |
645 | // later this is where we'll format output | |
646 | // according to the current `mode'. | |
647 | // | |
648 | } | |
649 | } | |
650 | #endif | |
651 | ||
652 | return 0; | |
653 | } | |
654 | ||
655 | ||
656 | ||
657 | // when a tlb entry is updated automatically by a hw-table-walk... | |
658 | // | |
659 | int trapcount::tlb (VCPU_TLB * ti) // ================================== TLB | |
660 | { | |
661 | if (!CountingOn) return 0; | |
662 | ||
663 | return 0; | |
664 | } | |
665 | ||
666 | ||
667 | ||
668 | // these are dma and string records generated (asynchronously) | |
669 | // by device simulators | |
670 | // | |
671 | int trapcount::async (VCPU_AsyncData * di) // ========================== ASYNC | |
672 | { | |
673 | if (!CountingOn) return 0; | |
674 | ||
675 | return 0; | |
676 | } | |
677 | ||
678 | ||
679 | ||
680 | // local- and global- time-sync records | |
681 | // | |
682 | int trapcount::sync (VCPU_Sync * si) // ================================ SYNC | |
683 | { | |
684 | if (!CountingOn) return 0; | |
685 | ||
686 | return 0; | |
687 | } | |
688 | ||
689 | ||
690 | ||
691 | ||
692 | ||
693 | ||
694 | ||
695 | // ----- out-of-place and/or misnamed functions ... ? ----- | |
696 | // | |
697 | ||
698 | int trapcount::process_ui_cmd (int argc, char *argv[]) | |
699 | { | |
700 | return 1; | |
701 | } | |
702 | ||
703 | int trapcount::parse_args_v4(int argc, const char * tmp_argv[]) | |
704 | { | |
705 | return 1; | |
706 | } | |
707 | ||
708 | int trapcount::parse_args_v5(int argc, const char * tmp_argv[]) | |
709 | { | |
710 | return 1; | |
711 | } | |
712 | ||
713 | void trapcount::trace_on() | |
714 | { | |
715 | } | |
716 | ||
717 | void trapcount::print_status() | |
718 | { | |
719 | } | |
720 | ||
721 | void trapcount::trace_off() | |
722 | { | |
723 | } | |
724 | ||
725 | ||
726 | ||
727 | ||
728 | #if 0 // ---------------- implementation notes ---------------- // | |
729 | /* | |
730 | * Mondo-Interrupts: | |
731 | * | |
732 | * Cross-cpu interrupts are Mondo (0x060) traps with | |
733 | * IRSR (Interrupt Receive Status Register) | |
734 | * contains the source [NodeId, x, AgentId] | |
735 | * IRDR0 (Interrupt Receive Data Register #0) | |
736 | * contains the entry point address of | |
737 | * the requested service function !!! | |
738 | * | |
739 | * External interrupts are also Mondo (0x060) traps with | |
740 | * IRSR (Interrupt Receive Status Register) | |
741 | * contains the source [NodeId, x, AgentId] | |
742 | * IRDR0 (Interrupt Receive Data Register #0) | |
743 | * contains the (Solaris assigned) INO | |
744 | * of the device, where: | |
745 | * INO = NodeID << 11 | AgentID << 6 | DeviceNo | |
746 | * | |
747 | * the IRSR contains a "busy-bit" in between the NodeID and AgentID | |
748 | * so the combined SystemID is not in contiguous bits :-(((. | |
749 | * the INO does not, its SystemID are contiguous bits :-)! | |
750 | * | |
751 | * | |
752 | * | |
753 | * Not to be confused with SoftInts which are traps 0x041...0x04f | |
754 | * | |
755 | * Note that SoftInt 0x04e is (oxymoronically) hardware generated, | |
756 | * and is the stick interval timer. | |
757 | * Except...., in S10 the INO-DeviceID 0x035 interrupts come from Schizo | |
758 | * for the pci_pbm_dma_sync() calls in the drivers, and they also set | |
759 | * SoftInt 0x04e :-(((((!~ Yeuch!!! | |
760 | * | |
761 | * | |
762 | */ | |
763 | #endif |