Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | #ifndef _rstf_h |
2 | #define _rstf_h | |
3 | ||
4 | #ident "@(#) rstf.h 1.41: 12/08/03 13:03:59 @(#)" | |
5 | ||
6 | /* | |
7 | * WARNING: The Java RST jrst package relies upon the existing comment style | |
8 | * to pick off the rtype value in each record. The Perl script | |
9 | * that "parses" this .h file is jrst/c2java.pl | |
10 | * I apologize in advance for this hackery. -R Quong 5/2002 | |
11 | * | |
12 | * File contents (you can search this file using on the terms below) | |
13 | * 0) Associated header files and #defines | |
14 | * 1) Overview of RST format | |
15 | * History | |
16 | * 2) Version info and checking | |
17 | * If you use the RST version check code, you must link with rstf/rstf.o | |
18 | * 3) struct definitions | |
19 | * 4) Useful functions | |
20 | * If you use any functions in (3), you must link with rstf/rstf.o | |
21 | */ | |
22 | ||
23 | /* | |
24 | * ================ 0) Associated header file and #defines =========== | |
25 | * Choose *ONE* of the following to include: | |
26 | * | |
27 | * rstf.h // most people should just include this file | |
28 | * rstf_bustrace.h // bustrace implementation specifics + rstf.h | |
29 | * | |
30 | * To use deprecated RSTF values, include rstf_deprecated.h *FIRST* Ex: | |
31 | * | |
32 | * #include "rstf/rstf_deprecated.h" | |
33 | * #include "rstf/rstf.h" | |
34 | * | |
35 | */ | |
36 | ||
37 | /* | |
38 | * ================ 1) Overview of RST format ================ | |
39 | * RST (trace) format or just RST for short. | |
40 | * Russell's Simplified Trace format | |
41 | * Really Simple Trace format | |
42 | * | |
43 | * RST format handles "unified architectural" trace data. | |
44 | * There are different kinds of records corresponding to | |
45 | * - instructions | |
46 | * - events (traps, interrupts) | |
47 | * - MMU state (TLB entry changes) | |
48 | * - internal processor state (register dumps) | |
49 | * - high-level evnts (process/context switch, thread switch) | |
50 | * - markers (timestamp, current CPU) | |
51 | * - state (cache/memory state) | |
52 | * | |
53 | * For simplicity of reading data, all records are the same size (24 bytes) | |
54 | * making it easy if you want to skip certain records. | |
55 | * The first byte in each record, the rtype, denotes the record type. | |
56 | * | |
57 | * +==============+ | |
58 | * | byte: header | The first record must be of type rstf_headerT | |
59 | * | maj,minor,% | Use init_rstf_header(rstf_headerT * hp) | |
60 | * | header | | |
61 | * | marker | | |
62 | * +==============+ | |
63 | * | byte: rtype | | |
64 | * | | | |
65 | * | 23 bytes of | | |
66 | * | data | | |
67 | * +==============+ | |
68 | * | byte: rtype | | |
69 | * | | | |
70 | * | 23 bytes of | | |
71 | * | data | | |
72 | * +==============+ | |
73 | * | byte: rtype | | |
74 | * | | | |
75 | * | 23 bytes of | | |
76 | * | data | | |
77 | * +==============+ | |
78 | * | |
79 | * We have different records type, so that future record types | |
80 | * can be added in the future. | |
81 | * | |
82 | * One easy way to read or write an RST trace is to define a | |
83 | * buffer of type rstf_unionT, which is a union of all known rec types. | |
84 | * You can access the record type of your choice directly w/o typecasts. | |
85 | * | |
86 | * rstf_unionT rstbuff [1024]; | |
87 | * ... read or write into rstbuff ... | |
88 | * rstf_instrT * instrPtr = & rstbuff[3].instr; // good = NO TYPE CASTING | |
89 | * rstf_instrT * instrPtr = (rstf_instrT*) &rstbuff[3]; // avoid, bad, ugly | |
90 | * int pc = instrPtr->pc_va; | |
91 | * int iContext = rstbuff[89].pavadiff.icontext; | |
92 | * rstf_tlbT * tlb = & rstbuff[234].tlb; // no type casting (!!) | |
93 | * | |
94 | * HISTORY: | |
95 | * This was format was originally known as unatrace (Version 1) in 1999. | |
96 | * | |
97 | * In 10/99, I (R Quong) developed a new definition for | |
98 | * the unatrace version 2 (now known as unawrap) format, | |
99 | * to be a general trace wrapper. | |
100 | * Rather than call the original format unatrace version 1, which | |
101 | * became way rather confusing, I renamed it as RST. | |
102 | * As of 4/2001, nothing is called unatrace. | |
103 | */ | |
104 | ||
105 | #include <stdio.h> // FILE* | |
106 | #include <sys/types.h> // uid_t | |
107 | ||
108 | #ifdef __cplusplus | |
109 | extern "C" { | |
110 | #endif | |
111 | #if 0 | |
112 | } | |
113 | #endif | |
114 | ||
115 | #if defined(RSTF_USE_DEPRECATED) | |
116 | #include "rstf/rstf_deprecated.h" | |
117 | #endif | |
118 | ||
119 | // if compiling with cc, use '-xCC' to handle C++ comments. | |
120 | ||
121 | // emacs commands for me (RQ) | |
122 | // (query-replace-regexp "int\\([0-9]+\\)" "int\\1_t" nil) | |
123 | ||
124 | #ifndef MIN | |
125 | #define MIN(a,b) (((a)>(b))?(b):(a)) | |
126 | #endif | |
127 | ||
128 | /* | |
129 | * 2) Version info and checking | |
130 | */ | |
131 | ||
132 | #define RSTF_MAGIC "RST Header" | |
133 | #define RSTF_MAJOR_VERSION 2 | |
134 | #define RSTF_MINOR_VERSION 13 | |
135 | ||
136 | #define RSTF_VERSION_STR "2.13" | |
137 | ||
138 | // Mandatory version checking info: | |
139 | // See vercheck.h for return codes: | |
140 | // 0 = version match | |
141 | // 2 = semi compatible versions | |
142 | // 4 = version mismatch | |
143 | int rstf_version_check_fn (const char* compile_time_version); | |
144 | ||
145 | // Convenience macro for version checking | |
146 | #define RSTF_CHECK_VERSION() rstf_version_check_fn(RSTF_VERSION_STR) | |
147 | ||
148 | // Do a compile-time vs run-time check on a record from a trace | |
149 | #define RSTF_CHECK_TRACEVER(rstheader_ptr) \ | |
150 | rstf_checkheader(RSTF_VERSION_STR, rstheader_ptr) | |
151 | ||
152 | static const char* rstf_version_str = "\n\ | |
153 | 2.13 07/25/2005 [VP] Added TRAPPED_INSTR_T record type\n\ | |
154 | 2.12 09/29/2004 [VP] extended cpuid fields to 10 bits; added accessor funcs\n\ | |
155 | 2.10 09/17/2003 Merged in rfs.h file, which defines record for RFS traces\n\ | |
156 | 2.09 08/28/2003 defined is_data one bit field in tsb_access record\n\ | |
157 | 2.08 06/16/2003 define tsb_access record\n\ | |
158 | 2.07 10/18/2002 define snoopT record\n\ | |
159 | 2.06 03/XX/2002 regvalT:tpc is array; clean up comments for MM (trap::pstate, trapexit::tpc, tlb::line_idx)\n\ | |
160 | 2.05 02/07/2002 augment STATUS_T w/ more analyzer-commands\n\ | |
161 | 2.05 10/19/2001 augment STATUS_T w/ analyzer-commands, e.g. for MPCachesim\n\ | |
162 | 2.05 10/04/2001 add bustrace::tdiff, renamed CONTEXT_T to PREG_T, add rstf_deprecated.h, expand hwinfo\n\ | |
163 | 2.04 8/16/2001 revisions to bus trace spec\n\ | |
164 | 2.03 8/06/2001 compile-vs-runtime version checking, openRST() supports rstzip\n\ | |
165 | 2.02 7/20/2001 revise memval64/128 recs, add bus trace record type\n\ | |
166 | 2.01 6/20/2001 add recs memval64 and memval128 records \n\ | |
167 | 2.00 6/19/2001 rev 1.10 to 2.00 (no other changes)\n\ | |
168 | 1.10 5/23/2001 cleanup openRST(), closeRST\n\ | |
169 | 1.10 4/26/2001 add cpuid to INSTR_T +TRAP_T, add TRACEINFO_T,\n\ | |
170 | deprecate ASI_T, modified REGVAL_T \n\ | |
171 | 1.9 4/20/2001 In CONTEXT_T: add cpuid, rename 'asi' to 'asiReg'\n\ | |
172 | 1.8 3/27/2001 unixcommand(), rstf_snprintf(), stdized rstf_headerT,magic\n\ | |
173 | 1.7 3/26/2001 Add RECNUM_T for rst-snapper\n\ | |
174 | 1.6 3/15/2001 Add support for MP (cpuid to PAVADIFF, cpuid/tlbnum TLB)\n\ | |
175 | 1.5 9/18/2000 Fixed Shade V6 record types (thanks Kelvin)\n\ | |
176 | 1.4 9/9/2000 Added icontext and dcontext to PAVADIFF_T rec\n\ | |
177 | 1.4 9/?/2000 Added major, minor numbers to HEADER_T rec\n\ | |
178 | 1.3 8/25/2000 Added PATCH_T type.\n\ | |
179 | 1.2 8/22/2000 Added STATUS_T type.\n\ | |
180 | "; | |
181 | ||
182 | /* The rtypes in RST */ | |
183 | enum { | |
184 | // values for the rtype field in the following traces. | |
185 | // we start at 3 not 0, to catch the common uninitialized case. | |
186 | ||
187 | // enum::rtypes Do not remove THIS comment, c2java.pl needs this | |
188 | RST_ZERO_T = 0, // should not see this | |
189 | RST_ONE_T = 1, // reserved, not used 5/2000. | |
190 | RSTHEADER_T = 2, // [REQUIRED] header type (mostly for marking) | |
191 | INSTR_T = 3, // instruction | |
192 | ||
193 | TRACEINFO_T = 4, // [REQUIRED] additional header info | |
194 | ||
195 | TLB_T = 5, // change in a TLB line | |
196 | THREAD_T = 6, // thread info | |
197 | TRAP_T = 7, // trap event | |
198 | TRAPEXIT_T = 8, // exit a trap | |
199 | REGVAL_T = 9, // short register dump (1 or 2 regs) | |
200 | TIMESTAMP_T = 11, // current cycle | |
201 | CPU_T = 11, // current CPU | |
202 | PROCESS_T = 12, // change in process, uses Unix PID ... rarely used. | |
203 | DMA_T = 13, // DMA event | |
204 | STRDESC_T = 14, // record is a N-char null-terminated (!) string (N<22) | |
205 | LEFTDELIM_T = 15, // multi-record data must be delimited by | |
206 | RIGHTDELIM_T = 16, // matching LEFTDELIM, RIGHTDELIM records | |
207 | PREG_T = 17, // priv regs (traplev, pstate, asiReg) | |
208 | PHYSADDR_T = 18, // physical addr of PC and EA; prefer PAVADIFF instead | |
209 | PAVADIFF_T = 19, // (PA-VA) values of PC and EA | |
210 | NULLREC_T = 20, // null record, which should be ignored | |
211 | // E.g. change the rtype to NULLREC_T to ignore it | |
212 | STRCONT_T = 21, // string that is *NOT* null-terminated | |
213 | // Multi-record str=>[STRCONT_T...STRCONT_T STRDESC_T] | |
214 | FILEMARKER_T = 22, // indicate where we are in a file | |
215 | RECNUM_T = 22, // set rec num counters (indicates a skip in the trace) | |
216 | STATUS_T = 23, // some sort of status (error, EOF, etc). | |
217 | PATCH_T = 24, // patch instructions (application specific) | |
218 | HWINFO_T = 25, // # cpu's, speed, memory, etc | |
219 | MEMVAL_T = 26, // value from ld/st from/to memory | |
220 | BUSTRACE_T = 27, // data from a bus trace | |
221 | SNOOP_T = 28, // a snoop event | |
222 | TSB_ACCESS_T = 29, // TSB access address during tlb fill | |
223 | RFS_SECTION_HEADER_T = 30, // The section header for RFS trace sub-type. | |
224 | RFS_CW_T = 31, // cache-warming data | |
225 | RFS_BT_T = 32, // branch-predict hardware warming | |
226 | // RFS_RST_T is only used to identify the section type in the | |
227 | // section header no actual rst records of that rtype are actually created | |
228 | RFS_RST_T = 33, | |
229 | ||
230 | TRAPPING_INSTR_T = 34, | |
231 | ||
232 | TIMESYNC_T = 35, // emitted periodically with a common sequence number | |
233 | // to align per-cpu traces | |
234 | ||
235 | DEVIDSTR_T = 36, // displays like a string record. in addition, maps device ids to names | |
236 | ||
237 | ||
238 | LAST_T = 37 | |
239 | ||
240 | }; | |
241 | ||
242 | /* | |
243 | * Multi-record types. | |
244 | * These types values are used in a LEFTDELIM_T record in the WHAT field. | |
245 | */ | |
246 | enum { | |
247 | STRING_MRT = 257, | |
248 | REGDUMP_MRT = 258, | |
249 | LAST_MRT = 300 | |
250 | }; | |
251 | ||
252 | // These are all 32 bit values representing invalid or bad addresses | |
253 | // I'll choose odd values of the form 0x3141592y where y=odd | |
254 | #define RSTF_BADADDR_BASE 0x31415900 // fictitious data EA, unknown reason | |
255 | #define RSTF_NO_EA 0x31415921 // fictitious data EA, unknown reason | |
256 | #define RSTF_NO_PC 0x31415923 // fictitious PC , unknown reason | |
257 | #define RSTF_ATRACE_NO_PC 0x31415927 // fictitious PC when no atrace I-rec | |
258 | #define RSTF_ATRACE_NO_EA 0x3141592f // fictitious data EA when no atrace D-rec | |
259 | ||
260 | // D-addr address is invalid, officially removed in 2.05 | |
261 | // #define RSTF_NOADDR 0x00314159 // (!!) Deprecated as of v 1.5 (!!) | |
262 | ||
263 | #define RSTF_IS_BADADDR(addr) \ | |
264 | ((((addr) & 01) != 0) && (((addr >> 8) == (RSTF_BADADDR_BASE >> 8)))) | |
265 | ||
266 | // | |
267 | // Here are definitions of the individual RST record types. | |
268 | // There are some convenience types at the end, to let you view | |
269 | // an RST record as an array of 8, 16, 32, or 64 bit values | |
270 | // and | |
271 | // a union type | |
272 | ||
273 | typedef struct { /* not done yet */ | |
274 | uint8_t rtype; /* value = ZERO_T */ | |
275 | uint8_t notused8; | |
276 | uint16_t notused16; | |
277 | uint32_t notused32; | |
278 | uint64_t notused64; | |
279 | uint64_t notused64a; | |
280 | } rstf_protoT; | |
281 | typedef rstf_protoT rstf_xxxT; | |
282 | ||
283 | /* | |
284 | * 3) struct definitions | |
285 | */ | |
286 | ||
287 | // view rsttrace record as an array of bytes, shorts, ints and long longs | |
288 | typedef struct { | |
289 | uint8_t arr8[ sizeof(rstf_protoT)/sizeof(uint8_t) ]; | |
290 | } rstf_uint8T; | |
291 | ||
292 | typedef struct { | |
293 | uint16_t arr16[ sizeof(rstf_protoT)/sizeof(uint16_t) ]; | |
294 | } rstf_uint16T; | |
295 | ||
296 | typedef struct { | |
297 | uint32_t arr32[ sizeof(rstf_protoT)/sizeof(uint32_t) ]; | |
298 | } rstf_uint32T; | |
299 | ||
300 | typedef struct { | |
301 | uint64_t arr64[ sizeof(rstf_protoT)/sizeof(uint64_t) ]; | |
302 | } rstf_uint64T; | |
303 | ||
304 | // All RST traces must begin with an rstf_headerT record. | |
305 | // | |
306 | // Initialize via init_rstf_header (rstf_headerT * headerp); | |
307 | typedef struct { | |
308 | uint8_t rtype; /* value = RSTHEADER_T */ | |
309 | uint8_t majorVer; /* major version Ex: 2 (binary value) */ | |
310 | uint8_t minorVer; /* minor version Ex: 23 (binary value) */ | |
311 | uint8_t percent; /* must be '%' to be compliant */ | |
312 | ||
313 | // header_str MUST start with RSTF_MAGIC | |
314 | // Expect it to look like: "RST Header v1.9" | |
315 | char header_str[ sizeof(rstf_uint8T) - sizeof( uint32_t ) ]; | |
316 | } rstf_headerT; | |
317 | ||
318 | #define MAX_INSTR_CPUID 48 | |
319 | typedef struct { | |
320 | uint8_t rtype; /* value = INSTR_T */ | |
321 | unsigned notused : 1; /* not used */ | |
322 | unsigned ea_valid : 1; /* ea_va field is valid, for ld/st only */ | |
323 | unsigned tr : 1; /* trap occured 1=yes */ | |
324 | unsigned hpriv : 1; /* hpriv: hpstate.hpriv==1. It is recommended */ | |
325 | /* that pr be set to 0 when hpriv==1 */ | |
326 | unsigned pr : 1; /* priviledged or user 1=priv */ | |
327 | unsigned bt : 1; /* br/trap taken, cond-move/st done */ | |
328 | unsigned an : 1; /* 1=annulled (instr was not executed) */ | |
329 | unsigned reservedCompress : 1; /* was used by rstzipv2 compressor */ | |
330 | ||
331 | unsigned cpuid : 6; /* do not access the cpuid field directly. Instead, use the | |
332 | set/get_cpuid functions defined below */ | |
333 | unsigned cpuid9_6 : 4; | |
334 | ||
335 | unsigned notused3 : 6; /* must be zero in this version of RST */ | |
336 | ||
337 | uint32_t instr; /* instruction word (opcode, src, dest) */ | |
338 | uint64_t pc_va; /* VA */ | |
339 | uint64_t ea_va; /* VA: Eff addr of ld/st; Eff targ of CTI */ | |
340 | } rstf_instrT; | |
341 | static void rstf_instrT_set_cpuid(rstf_instrT * tr, int cpuid) { tr->cpuid = cpuid & 0x3f; tr->cpuid9_6 = ((cpuid>>6) & 0xf); } | |
342 | static int rstf_instrT_get_cpuid(const rstf_instrT * tr) { return (tr->cpuid9_6<<6)|tr->cpuid; } | |
343 | ||
344 | typedef struct { | |
345 | uint8_t rtype; /* value = PAVADIFF_T */ | |
346 | unsigned ea_valid : 1; /* does ea_pa contain a valid address */ | |
347 | unsigned cpuid : 7; | |
348 | unsigned cpuid9_7 : 3; | |
349 | unsigned notused13: 13; /* must be zero */ | |
350 | uint16_t icontext; /* I-context used for these diffs */ | |
351 | uint16_t dcontext; /* only valid if ea_valid is true (!) */ | |
352 | uint64_t pc_pa_va; /* (PA-VA) of PC */ | |
353 | uint64_t ea_pa_va; /* (PA-VA) of EA for ld/st (not branches), if ea_valid is true */ | |
354 | } rstf_pavadiffT; | |
355 | static void rstf_pavadiffT_set_cpuid(rstf_pavadiffT * tr, int cpuid) { tr->cpuid = cpuid & 0x7f; tr->cpuid9_7 = (cpuid>>7)&0x7; } | |
356 | static int rstf_pavadiffT_get_cpuid(const rstf_pavadiffT * tr) { return (tr->cpuid9_7 << 7)|tr->cpuid; } | |
357 | ||
358 | // subtypes for records with a rtype2 field | |
359 | enum { | |
360 | RSTT2_ZERO_T = 0, RSTT2_ONE = 1, // reserved | |
361 | RSTT2_NLEVEL_T = 2, // | |
362 | RSTT2_CPUINFO_T = 3, | |
363 | RSTT2_CPUIDINFO_T = 4, | |
364 | RSTT2_LAST_T = 5 // | |
365 | }; | |
366 | ||
367 | // Trace information: | |
368 | ||
369 | // Each RST trace starts with a header record, followed by a series of tracinfo records | |
370 | ||
371 | // The first traceinfo record should indicate the trace level (incremented with each update) | |
372 | ||
373 | // The next traceinfo record specifies the number of cpus and the min/max cpuid in the trace | |
374 | ||
375 | // The following traceinfo records list the cpuids specified in the trace, up to 10 per record | |
376 | ||
377 | // This is followed by a series of string records containing more detail about the trace | |
378 | ||
379 | ||
380 | ||
381 | // Initialize these records with init_rstf_traceinfo_level(). | |
382 | // | |
383 | // Each program that generates/processes/modifies the trace is a level. | |
384 | // Level 0 = program that generated the trace | |
385 | // Level 1 = first "filter" run on the trace that modifies the trace. | |
386 | // To be compliant w/ RST v2.06, the second record in the trace | |
387 | // must be a traceinfo_levelT. | |
388 | // Thus a filter can read the second record, bump the level | |
389 | // and rewrite the modified record | |
390 | typedef struct { /* not done yet */ | |
391 | uint8_t rtype; /* value = TRACEINFO_T */ | |
392 | uint8_t rtype2; /* RSTT2_NLEVEL_T */ | |
393 | uint16_t level; /* number of levels, must be >= 1 */ | |
394 | uint32_t val32; | |
395 | uint64_t time64; /* value returned by time(2) */ | |
396 | uint64_t notused64a; | |
397 | } rstf_traceinfo_levelT; | |
398 | ||
399 | typedef struct { | |
400 | uint8_t rtype; /* value=TRACEINFO_T */ | |
401 | uint8_t rtype2; /* value = RSTT2_CPUINFO_T */ | |
402 | int16_t numcpus; /* number of cpus in trace */ | |
403 | int16_t min_cpu_id; | |
404 | int16_t max_cpu_id; | |
405 | int64_t reserved1; /* must be zero in this version */ | |
406 | int64_t reserved2; /* must be zero in this version */ | |
407 | } rstf_cpuinfoT; | |
408 | ||
409 | /* The cpuidinfo records list the cpuids that occur in the trace. | |
410 | * It is needed because cpuids are not necessarily 0..ncpus-1. | |
411 | * More than one cpuidinfo record can appear following a cpuinfo record, | |
412 | * each contains up to 10 cpuids that appear in the trace. | |
413 | * For example, there will be 3 cpuidinfo records for ncpus=24. | |
414 | * Unused cpuid's must be set to 0 | |
415 | */ | |
416 | ||
417 | typedef struct { | |
418 | uint8_t rtype; /* value=TRACEINFO_T */ | |
419 | uint8_t rtype2; /* value=RSTT2_CPUIDINFO_T */ | |
420 | uint16_t reserved1; /* must be zero in this version */ | |
421 | uint16_t cpuids[10]; /* unused fields must be zero */ | |
422 | } rstf_cpuidinfoT; | |
423 | ||
424 | // placemarker, as will split off more variants of | |
425 | typedef struct { /* not done yet */ | |
426 | uint8_t rtype; /* value = TRACEINFO_T */ | |
427 | uint8_t rtype2; /* subtype: RSTT2_NLEVEL_T */ | |
428 | uint16_t val16; | |
429 | uint32_t val32; | |
430 | uint64_t val64; | |
431 | uint64_t val64a; | |
432 | } rstf_traceinfoT; | |
433 | ||
434 | ||
435 | ||
436 | typedef struct { | |
437 | uint8_t rtype; /* value = TLB_T */ | |
438 | unsigned demap : 1; /* 0 = add/replace entry ; 1=invalidate */ | |
439 | unsigned tlb_type : 1; /* 0 = INSTR, 1 = DATA */ | |
440 | unsigned notused : 6; /* not used */ | |
441 | ||
442 | // Each TLB implementor can number the lines in the TLB arbitrarily | |
443 | // For direct-mapped TLBs, the line index is obvious | |
444 | // For a K-way TLB, we recommend having idx={0,1,..,K-1}=first set | |
445 | uint16_t tlb_index; /* TLB line index, specific to each TLB impl */ | |
446 | ||
447 | unsigned tlb_no : 2 ; /* which I or D TLB ? (eg. Ch+ has 3 D TLBS) */ | |
448 | unsigned cpuid : 6 ; /* changed in v1.6 */ | |
449 | unsigned cpuid9_6 : 4; | |
450 | unsigned unused : 4 ; /* */ | |
451 | ||
452 | uint16_t unused16; /* */ | |
453 | ||
454 | // The blaze RSTracer collects the following information | |
455 | // tte_tag[63:13] = VA[63:13] tte_tag[12:0] = context | |
456 | // (!) This format is different from that used in the US-I hardware | |
457 | uint64_t tte_tag; /* tag for a TTE */ | |
458 | ||
459 | // See the struct rstf_tte_dataT at the end of this file | |
460 | // for an example of how the tte_data might be organized. | |
461 | // rstf_tte_dataT * xp = (rst_tte_data_T *) & tlbp->tte_data; | |
462 | uint64_t tte_data; /* data for a TTE */ | |
463 | } rstf_tlbT; | |
464 | static void rstf_tlbT_set_cpuid(rstf_tlbT * tr, int cpuid) { tr->cpuid = cpuid & 0x3f; tr->cpuid9_6 = (cpuid>>6)&0xf; } | |
465 | static int rstf_tlbT_get_cpuid(const rstf_tlbT * tr) { return (tr->cpuid9_6<<6)|tr->cpuid; } | |
466 | ||
467 | typedef struct { /* not done yet */ | |
468 | uint8_t rtype; /* value = THREAD_T */ | |
469 | uint8_t notused8; | |
470 | uint16_t icontext; /* I-context */ | |
471 | uint32_t notused32; | |
472 | uint64_t tid; /* Thread ID or %g7=ptr to OS thread */ | |
473 | uint64_t notused64; | |
474 | } rstf_threadT; | |
475 | ||
476 | typedef struct { | |
477 | uint8_t rtype; /* value = PROCESS_T */ | |
478 | uint8_t notused8; | |
479 | uint16_t notused16; | |
480 | uint32_t notused32; | |
481 | ||
482 | uint32_t oldpid; /* previous process id 0=no info */ | |
483 | uint32_t newpid; /* current process id 0=no info */ | |
484 | ||
485 | uint32_t oldcontext; | |
486 | uint32_t newcontext; | |
487 | } rstf_processT; | |
488 | ||
489 | typedef struct { | |
490 | uint8_t rtype; /* value = PREG_T */ | |
491 | uint8_t asiReg; /* ASI register */ | |
492 | uint16_t unused_lastcontext; /* DEPRECATED */ | |
493 | ||
494 | uint8_t traplevel; | |
495 | uint8_t traptype; /* traptype[traplevel] register */ | |
496 | uint16_t pstate; /* pstate */ | |
497 | ||
498 | uint8_t cpuid; /* cpu 0, 1, 2, ... */ | |
499 | uint8_t cpuid9_8 : 2; | |
500 | uint8_t notused4 : 6; /* */ | |
501 | uint16_t notused16; /* */ | |
502 | uint32_t notused32; /* */ | |
503 | ||
504 | // DO NOT USE THESE FOR GETTING THE CURRENT CONTEXT | |
505 | // Use the PAVADIFF_T icontext and dcontext, instead | |
506 | // These are MMU reg values, which may or may not be used by the instr | |
507 | uint16_t primA; /* primary IMMU context, must be equal to primD */ | |
508 | uint16_t secA; /* secondary IMMU context, not used */ | |
509 | uint16_t primD; /* primary DMMU context register */ | |
510 | uint16_t secD; /* secondary DMMU context register */ | |
511 | } rstf_pregT; | |
512 | static void rstf_pregT_set_cpuid(rstf_pregT * tr, int cpuid) { tr->cpuid = cpuid & 0xff; tr->cpuid9_8 = (cpuid>>8) & 3; } | |
513 | static int rstf_pregT_get_cpuid(const rstf_pregT * tr) { return (tr->cpuid9_8<<8)|tr->cpuid; } | |
514 | ||
515 | typedef struct { | |
516 | uint8_t rtype; /* value = TRAP_T */ | |
517 | unsigned is_async : 1 ; /* asynchronous trap ? */ | |
518 | unsigned unused : 3 ; /* unused */ | |
519 | unsigned tl : 4 ; /* trap level at the time trap occurred */ | |
520 | ||
521 | unsigned cpuid : 6 ; /* cpu id */ | |
522 | unsigned ttype : 10; /* trap type for V9, only 9 bits matter */ | |
523 | ||
524 | uint16_t pstate; /* Pstate register in the trap */ | |
525 | uint16_t cpuid9_6 : 4; | |
526 | ||
527 | uint16_t syscall : 12; /* If a system call, the syscall # */ | |
528 | ||
529 | uint64_t pc; /* PC before the trap (= post-trap TPC[TL]) */ | |
530 | uint64_t npc; /* NPC before trap (= post-trap TNPC[TL]) */ | |
531 | } rstf_trapT; | |
532 | static void rstf_trapT_set_cpuid(rstf_trapT * tr, int cpuid) { tr->cpuid = cpuid & 0x3f; tr->cpuid9_6 = (cpuid>>6) & 0xf; } | |
533 | static int rstf_trapT_get_cpuid(const rstf_trapT * tr) { return (tr->cpuid9_6 << 6) | tr->cpuid; } | |
534 | ||
535 | typedef struct { | |
536 | uint8_t rtype; /* value = TRAPEXIT_T */ | |
537 | uint8_t tl; /* trap level , after done/retry */ | |
538 | unsigned cpuid : 6 ; /* 10-bit cpu id */ | |
539 | unsigned cpuid9_6 : 4; | |
540 | unsigned notused10 : 6; | |
541 | uint32_t tstate; /* bottom 32 bits of tstate */ | |
542 | ||
543 | uint64_t unused64; /* used to be pc */ | |
544 | uint64_t unused64b; /* used to be npc */ | |
545 | } rstf_trapexitT; | |
546 | static void rstf_trapexitT_set_cpuid(rstf_trapexitT * tr, int cpuid) { tr->cpuid = cpuid & 0x3f; tr->cpuid9_6 = (cpuid>>6) & 0xf; } | |
547 | static int rstf_trapexitT_get_cpuid(const rstf_trapexitT * tr) { return (tr->cpuid9_6 << 6) | tr->cpuid; } | |
548 | ||
549 | ||
550 | typedef struct { | |
551 | uint8_t rtype; /* value = CPU_T */ | |
552 | uint8_t notused8; | |
553 | uint16_t notused16; | |
554 | uint16_t notused16b; | |
555 | uint16_t cpu; /* CPU ID = 0, 1, etc */ | |
556 | uint64_t notused64; | |
557 | uint64_t timestamp; | |
558 | } rstf_cpuT; | |
559 | ||
560 | typedef struct { | |
561 | uint8_t rtype; /* value = DMA_T */ | |
562 | unsigned unused : 7; /* unused */ | |
563 | unsigned iswrite : 1; /* 1=write to memory, 0=read from memory */ | |
564 | uint16_t notused16; | |
565 | uint32_t nbytes; /* # of bytes transfered in the DMA */ | |
566 | uint64_t start_pa; /* starting address for the DMA */ | |
567 | uint32_t devid; /* id of device that performed the dma */ | |
568 | uint32_t notused32; | |
569 | } rstf_dmaT; | |
570 | ||
571 | typedef struct { | |
572 | uint8_t rtype; /* value = TSB_ACCESS_T */ | |
573 | unsigned unused : 7; | |
574 | unsigned isdata : 1; /* 1=data access, 0=instruction access */ | |
575 | uint16_t unused2 : 6; | |
576 | uint16_t cpuid : 10; /* CPU ID = 0, 1, etc */ | |
577 | uint32_t notused32; | |
578 | uint64_t pa; /* physical address of TSB access */ | |
579 | uint64_t va; /* virtual address of TSB access */ | |
580 | } rstf_tsb_accessT; | |
581 | static void rstf_tsb_accessT_set_cpuid(rstf_tsb_accessT * tr, int cpuid) { tr->cpuid = cpuid; } | |
582 | static int rstf_tsb_accessT_get_cpuid(const rstf_tsb_accessT * tr) { return tr->cpuid; } | |
583 | ||
584 | ||
585 | /* A rstf_trapping_instrT record is output before a synchronous trap record to provide | |
586 | * additional information about the cause of the trap. It is also output before an async trap | |
587 | * with information about the instruction that would have executed if the trap hadn't been taken | |
588 | * | |
589 | * The trap record will typically be followed by an rstf_instrT record with the tr flag set. | |
590 | */ | |
591 | typedef struct { | |
592 | uint8_t rtype; /* value = TRAPPING_INSTR_T */ | |
593 | ||
594 | /* values of hpstate.hpriv and pstate.priv when the trapping instr was initiated */ | |
595 | uint8_t hpriv: 1; | |
596 | uint8_t priv : 1; | |
597 | ||
598 | uint8_t iftrap : 1; // if true, only cpuid and ea_va are valid | |
599 | ||
600 | uint8_t ea_va_valid : 1; // valid only if iftrap == 0 | |
601 | uint8_t ea_pa_valid : 1; // do not translate ea_va unless true | |
602 | uint8_t unused3: 3; | |
603 | ||
604 | uint16_t cpuid: 10; | |
605 | uint16_t unused6: 6; | |
606 | ||
607 | uint32_t instr; // valid only if iftrap == 0 | |
608 | ||
609 | uint64_t pc_va; // always valid | |
610 | ||
611 | uint64_t ea_va; // only if ea_va_valid | |
612 | ||
613 | } rstf_trapping_instrT; | |
614 | static void rstf_trapping_instrT_set_cpuid(rstf_trapping_instrT * tr, int cpuid) { tr->cpuid = cpuid; } | |
615 | static int rstf_trapping_instrT_get_cpuid(const rstf_trapping_instrT * tr) { return tr->cpuid; } | |
616 | ||
617 | // | |
618 | // RST Bus trace format philosophy. | |
619 | // (i) convert a minimal set of "common" data into a standard form | |
620 | // which is sufficient for any generic-bus-trace analyzer | |
621 | // (ii) to leave the bus-trace implementation specific data bits as-is, | |
622 | // in a bus-trace specific set of 64-96 bits. | |
623 | // | |
624 | // There are major differences between different bus trace implementations | |
625 | // (system, bus, logic analyzer) even only looking at the | |
626 | // HPLA/Firetruck versus Tektronix/E10K traces. | |
627 | // In particular, the transaction types alone are different. | |
628 | // And as we collect more bus traces from different/new setups, this | |
629 | // problem will only get worse. | |
630 | // | |
631 | // See rstf_bustrace.h for bus-trace implementation specific details. | |
632 | // To access bus trace implementations specific fields use: | |
633 | // #include <rstf/rstf_bustrace.h> | |
634 | // | |
635 | // Or, if you just need common fields (e.g. a cache simulator), use | |
636 | // #include <rstf/rstf.h> | |
637 | // | |
638 | // Again, The bustrace record (here) in rstf.h only describes fields | |
639 | // common to all bus trace records. These fields are those suitable | |
640 | // for cache simulators and should be values present in all bus | |
641 | // traces. | |
642 | ||
643 | ||
644 | #ifndef _rstf_bustrace_h | |
645 | ||
646 | enum { | |
647 | // TX types must know so a cache simulator can do the right thing | |
648 | // 07/26/2001 | |
649 | ||
650 | RST_BTTX_BADVAL = 0x0, // Make common unitialized value an error | |
651 | ||
652 | // UPA | |
653 | RST_BTTX_RTS = 0x10, // Read to Share | |
654 | RST_BTTX_RTSA = 1, // Read to Share Always (I access) | |
655 | RST_BTTX_RTO = 2, // Read to Own | |
656 | RST_BTTX_RTD = 3, // Read to Discard | |
657 | RST_BTTX_CGSS = 4, // CopybackGotoSState | |
658 | RST_BTTX_NCR = 5, // NonCachedRead | |
659 | RST_BTTX_NCBR = 6, // NonCachedBlockRead | |
660 | RST_BTTX_NCBW = 7, // NonCachedBlockWrite | |
661 | RST_BTTX_WB = 8, // Writeback | |
662 | RST_BTTX_WI = 9, // WriteInvalidate | |
663 | RST_BTTX_INV = 10, // Invalidate | |
664 | RST_BTTX_CB = 11, // Copyback | |
665 | RST_BTTX_CBI = 12, // CopybackInvalidate | |
666 | RST_BTTX_CBD = 13, // CopybackToDiscard | |
667 | RST_BTTX_NCW = 14, // NonCachedWrite | |
668 | RST_BTTX_INT = 15, // Interrupt | |
669 | ||
670 | // Additional Tx types in the firetruck bus | |
671 | RST_BTTX_IDLE = 0x11, // Idle | |
672 | RST_BTTX_ADMIN = 0x12, // Admin | |
673 | RST_BTTX_RTSF = 0x13, // ReadToShareFork | |
674 | RST_BTTX_RS = 0x14, // ReadStream | |
675 | ||
676 | RST_BTTX_RSTADMIN = 0x18, // an administrative record (reserved) | |
677 | RST_BTTX_LAST = 0x18 // any value greater than this is an error | |
678 | }; | |
679 | ||
680 | // In rstf_bustrace.h, u_btimpl64_t is defined as a union of structs | |
681 | // but if we did not see rstf_bustrace.h, define it as an long long. | |
682 | // | |
683 | typedef uint64_t u_btimpl64_t; | |
684 | ||
685 | #endif /* _rstf_bustrace_h */ | |
686 | ||
687 | // The common bus trace info if the user just includes <rstf/rstf.h> | |
688 | typedef struct { | |
689 | uint8_t rtype; /* value = BUSTRACE_T */ | |
690 | ||
691 | unsigned dirtyvictim : 1; // this access create dirty victim? | |
692 | unsigned shared : 1; // FT: anybody claim share this line? E10K:N/A | |
693 | unsigned owned : 1; // FT: owned line asserted E10K: N/A | |
694 | unsigned memcancel : 1; // E10=abort bit, FT=data cancel | |
695 | unsigned bt_type : 4; /* type of bus trace, see rstf_bustrace.h */ | |
696 | ||
697 | unsigned txType : 6; // Transaction type | |
698 | unsigned agentid : 10; // cpu/board/agent/module ID | |
699 | ||
700 | unsigned tdiff : 1 ; // 1=timestamp is differental from prev rec, | |
701 | unsigned nsScale : 1 ; // 1=timestamp is in nS; 0=timestamp in 100nS | |
702 | unsigned timestamp : 20; // absolute=unsigned, time delta=signed | |
703 | ||
704 | ||
705 | u_btimpl64_t btimpl64; // specific to a given bustrace | |
706 | uint64_t addr_pa; // PA, bottom 6 bits may be unused | |
707 | } rstf_bustraceT; | |
708 | ||
709 | ||
710 | enum { | |
711 | // ================ | |
712 | // register types | |
713 | // | |
714 | RSTREG_INT_RT = 1, | |
715 | RSTREG_FLOAT_RT = 2, | |
716 | RSTREG_PRIV_RT = 3, | |
717 | RSTREG_OTHER_RT = 4, // | |
718 | RSTREG_UNUSED_RT = 5, // register value bits are unused | |
719 | ||
720 | // regtype[i]=RSTREG_CC_RT => regid[i] field holds icc+xcc values | |
721 | // regid[i] bits 0:3 hold icc regid[i] bits 4:7 hold xcc | |
722 | // XCC: n z v c ICC: n z v c | |
723 | // Bits 7 6 5 4 3 2 1 0 | |
724 | RSTREG_CC_RT = 6, | |
725 | ||
726 | // regtype[i]=RSTREG_CC_RT => regid[i] field holds icc+xcc values | |
727 | // regid[i] bits 0:3 hold icc regid[i] bits 4:7 hold xcc | |
728 | // XCC: n z v c ICC: n z v c | |
729 | // Bits 7 6 5 4 3 2 1 0 | |
730 | RSTREG_FCC_RT = 7, | |
731 | ||
732 | // regtype[i]=RSTREG_WININT_RT => regid[i] field holds winptr+regnum | |
733 | // regid[i] bits 7:5 holds window pointer (0-8), for integer regs | |
734 | // or global type (RSTREG_USER_GLOBAL thru | |
735 | // RSTREG_ALTERNATE_GLOBAL) and global level | |
736 | // for Millennium-type architectures | |
737 | // Examples: | |
738 | // %l5 of window 3 = 0x75 = 8b'011-10101 (l5 = 21 = 0x15) | |
739 | // %l3 of window 7 = 0xf3 = 8b'111-10011 (l3 = 19 = 0x13) | |
740 | // %ag3 = 0x63 = 8b'011-00011 | |
741 | // Transformation Functions: | |
742 | // regid = (wp << 5) + regnum; | |
743 | // wp = (regid >> 5); regnum = (regid & 0x1f); | |
744 | RSTREG_WININT_RT = 8, | |
745 | ||
746 | RSTREG_MMU_RT = 9, // MMU specific | |
747 | ||
748 | RSTREG_HPRIV_RT = 10, | |
749 | ||
750 | RSTREG_LAST_RT = 11, | |
751 | ||
752 | // ================ | |
753 | // register ID's | |
754 | // | |
755 | ||
756 | // int registers, %g0=0,%g7=7,%o0=8,%o7=15,%l0=16,%l7=23,%i0=24,%i7=31 | |
757 | RSTREG_iGLOBAL_R = 0, | |
758 | RSTREG_iOUT_R = 8, | |
759 | RSTREG_iLOCAL_R = 16, | |
760 | RSTREG_iIN_R = 24, | |
761 | RSTREG_iTHREAD_R = RSTREG_iGLOBAL_R+7, // %g7 = & kernel thread struct | |
762 | RSTREG_iSP_R = RSTREG_iOUT_R+6, | |
763 | RSTREG_iFP_R = RSTREG_iIN_R+6, | |
764 | ||
765 | // float registers, SingleP=0..31, DoubleP=32..63, QuadP=64..95 | |
766 | // - A quad float occupies regval[0..1] and must be regtype[0]. | |
767 | // And, regtype[1] must be RSTREG_CC_RT or RSTREG_UNUSED_RT. | |
768 | ||
769 | // priv registers (same encoding as in the RDPR instr) | |
770 | // used when regtype=RSTREG_PRIV_RT | |
771 | RSTREG_TPC_R = 0, | |
772 | RSTREG_TNPC_R = 1, | |
773 | RSTREG_TSTATE_R = 2, | |
774 | RSTREG_TT_R = 3, | |
775 | RSTREG_TICK_R = 4, | |
776 | RSTREG_TBA_R = 5, | |
777 | RSTREG_PSTATE_R = 6, | |
778 | RSTREG_TL_R = 7, | |
779 | RSTREG_PIL_R = 8, | |
780 | RSTREG_CWP_R = 9, | |
781 | RSTREG_CANSAVE_R = 10, | |
782 | RSTREG_CANRESTORE_R = 11, | |
783 | RSTREG_CLEANWIN_R = 12, | |
784 | RSTREG_OTHERWIN_R = 13, | |
785 | RSTREG_WSTATE_R = 14, | |
786 | RSTREG_FQ_R = 15, | |
787 | RSTREG_VERSION_R = 31, | |
788 | ||
789 | // There is an instance of the following registers for each trap level | |
790 | // We allocate enough space for 8 trap levels (as of 2001, MAXTL=4) | |
791 | // Thus for TPC[ TL=3 ], use regid=RSTREG_TPC_RBASE+3 | |
792 | RSTREG_TPC_RBASE = 64, | |
793 | RSTREG_TNPC_RBASE = 72, | |
794 | RSTREG_TSTATE_RBASE = 80, | |
795 | RSTREG_TT_RBASE = 88, | |
796 | ||
797 | // other registers (same encoding as in the RDSTATE instr) | |
798 | // used when regtype=RSTREG_OTHER_RT | |
799 | RSTREG_Y_R = 0, | |
800 | RSTREG_CC_R = 2, | |
801 | RSTREG_ASI_R = 3, | |
802 | // RSTREG_TICK_R = 4, (duplicated from above) | |
803 | RSTREG_PC_R = 5, | |
804 | RSTREG_FPRS_R = 6, | |
805 | RSTREG_ASR_R = 7, // not used | |
806 | RSTREG_OLDFSR_R = 8, // not used | |
807 | RSTREG_ASR_PCR_R = 16, | |
808 | RSTREG_ASR_PIC_R = 17, | |
809 | RSTREG_ASR_IEU_CTRL_R = 18, | |
810 | RSTREG_ASR_GSR_R = 19, | |
811 | RSTREG_ASR_INTR_SET_R = 20, | |
812 | RSTREG_ASR_INTR_CLR_R = 21, | |
813 | RSTREG_ASR_INTR_WRITE_R = 22, | |
814 | RSTREG_ASR_TICK_CMPR_R = 23, | |
815 | RSTREG_ASR_STICK_REG_R = 24, | |
816 | RSTREG_ASR_STICK_CMPR_R = 25, | |
817 | RSTREG_ASR_STICK_THR_STR_R = 26, | |
818 | RSTREG_ASR_NPC_R = 32, | |
819 | RSTREG_ASR_FSR_R = 33, | |
820 | ||
821 | // register id's for regtype RSTREG_HPRIV_RT. | |
822 | // Values correspond to rd/wr hpr instruction operand encodings | |
823 | RSTREG_HPR_HPSTATE = 0x0, | |
824 | RSTREG_HPR_HTSTATE = 0x1, | |
825 | RSTREG_HPR_HINTP = 0x3, | |
826 | RSTREG_HPR_HTBA = 0x5, | |
827 | RSTREG_HPR_HVER = 0x6, | |
828 | RSTREG_HPR_HSTICK_CMPR = 0x1f, | |
829 | ||
830 | // global types (used for global registers in regtype=RSTREG_WININT_RT) | |
831 | RSTREG_USER_GLOBAL = 0, // %g0-g7 | |
832 | RSTREG_INTERRUPT_GLOBAL = 1, // %ig0-ig7 | |
833 | RSTREG_MMU_GLOBAL = 2, // %mg0-mg7 | |
834 | RSTREG_ALTERNATE_GLOBAL = 3, // %ag0-ag7 | |
835 | ||
836 | // mmu reg types. use encodings from ASI 0x58 | |
837 | RSTREG_MMU_PCONTEXT=0x8, | |
838 | RSTREG_MMU_SCONTEXT=0x10, | |
839 | ||
840 | RSTREG_LAST_MARKER = 15 | |
841 | }; | |
842 | ||
843 | /* | |
844 | * This structure contains one or two register values | |
845 | */ | |
846 | typedef struct { | |
847 | uint8_t rtype; /* value = REGVAL_T */ | |
848 | unsigned postInstr : 1; /* 0=values before instr, 1=values AFTER */ | |
849 | unsigned cpuid : 7; /* CPU */ | |
850 | ||
851 | uint8_t regtype[2]; /* type: Ex: regtype[0]=RSTREG_INT_RT */ | |
852 | uint8_t regid[2]; /* register Ex regid[0]=14 (%o6=%sp) */ | |
853 | ||
854 | uint16_t cpuid9_7 : 3; | |
855 | uint16_t notused13 : 13; | |
856 | ||
857 | uint64_t reg64[2]; /* reg64[i] described by regtype[i]/regid[i]*/ | |
858 | } rstf_regvalT; | |
859 | static void rstf_regvalT_set_cpuid(rstf_regvalT * tr, int cpuid) { tr->cpuid = cpuid & 0x7f; tr->cpuid9_7 = (cpuid>>7) & 0x7; } | |
860 | static int rstf_regvalT_get_cpuid(const rstf_regvalT * tr) { return (tr->cpuid9_7 << 7) | tr->cpuid; } | |
861 | ||
862 | ||
863 | // Memory values | |
864 | // An RST trace is associated with a direct-mapped memory cache | |
865 | // of geometry 128Bytes x 32K lines. Every ifetch/load/store/prefetch | |
866 | // with a valid memory PA accesses the cache. Memory value records are | |
867 | // emitted for each miss | |
868 | ||
869 | #define RSTF_MEMVAL_CACHE_BLOCKSIZE 128 | |
870 | #define RSTF_MEMVAL_CACHE_LINES 32768 | |
871 | ||
872 | ||
873 | // A memory value record can be either a memval128T or memval64T | |
874 | // memval128T = 128 bits of aligned data. | |
875 | // Only give bits 4:43 of address. Must sign extend to get full addr | |
876 | // if isContRec==1, ignore addr bits and use address from previous rec | |
877 | // This is done because the record only has enough space for 43 bits | |
878 | // of address, so a 64 bit memval that precedes the 128 bit memval | |
879 | // provides the address. | |
880 | // | |
881 | typedef struct { | |
882 | uint8_t rtype; /* value = MEMVAL_T */ | |
883 | unsigned ismemval128 : 1; // type of memval? 1=memval128T 0=memval64T | |
884 | unsigned addrisVA : 1; // What type of addr? 1=VA 0=PA | |
885 | unsigned isContRec : 1; // continuation? applies only to memval128T | |
886 | unsigned zero3: 3; // should be zero | |
887 | unsigned cpuid9_8 : 2; | |
888 | unsigned cpuid : 8 ; // cpu id | |
889 | ||
890 | // contain 40 bits <04:43> which must be sign extended to get the full addr | |
891 | uint8_t addr36_43; // shift this value 36 bits to the right | |
892 | uint32_t addr04_35; // addr = (long long) (addr04_35 << 4); | |
893 | uint64_t val[2]; // must be ALIGNED 128 bits=16 bytes data | |
894 | } rstf_memval128T; | |
895 | static void rstf_memval128T_set_cpuid(rstf_memval128T * tr, int cpuid) { tr->cpuid = cpuid & 0xff; tr->cpuid9_8 = (cpuid>>8) & 3; } | |
896 | static int rstf_memval128T_get_cpuid(const rstf_memval128T * tr) { return (tr->cpuid9_8<<8)|tr->cpuid; } | |
897 | ||
898 | static void rstf_memval128T_set_addr(rstf_memval128T * tr, uint64_t addr) {tr->addr36_43 = (addr>>36)&0xff; tr->addr04_35 = (addr>>4) & ~0u;} | |
899 | static uint64_t rstf_memval128T_get_addr(rstf_memval128T * tr) { return (((uint64_t)tr->addr36_43) << 36) | (((uint64_t)tr->addr04_35) << 4); } | |
900 | ||
901 | typedef struct { | |
902 | uint8_t rtype; /* value = MEMVAL_T */ | |
903 | unsigned ismemval128 : 1; // type of memval? 1=memval128T 0=memval64T | |
904 | unsigned addrisVA : 1; // What type of addr? 1=VA 0=PA | |
905 | unsigned isContRec : 1; // this bit does not apply to rstf_memval64T | |
906 | unsigned zero3: 3; // should be zero | |
907 | unsigned cpuid9_8 : 2; | |
908 | unsigned cpuid : 8 ; // cpu id | |
909 | unsigned unused4 : 4 ; // | |
910 | unsigned size : 4 ; // # of valid bytes in val (1-8) | |
911 | ||
912 | uint32_t notused32; // | |
913 | uint64_t addr; // 64 bit address | |
914 | uint64_t val; // 64 bits = 8 bytes of data | |
915 | } rstf_memval64T; | |
916 | // cpuid accessor fns same as memval128 | |
917 | static void rstf_memval64T_set_cpuid(rstf_memval64T * tr, int cpuid) { tr->cpuid = cpuid & 0xff; tr->cpuid9_8 = (cpuid>>8) & 3; } | |
918 | static int rstf_memval64T_get_cpuid(const rstf_memval64T * tr) { return (tr->cpuid9_8<<8)|tr->cpuid; } | |
919 | ||
920 | typedef struct { | |
921 | uint8_t rtype; /* value = LEFTDELIM_T, RIGHTDELIM_T */ | |
922 | uint8_t id; /* left and right delims must match */ | |
923 | uint16_t what; /* type of data */ | |
924 | uint32_t length; /* length of data (bytes) in following recs */ | |
925 | uint64_t notused64; | |
926 | uint64_t notused64a; | |
927 | } rstf_delimT; | |
928 | ||
929 | // PHYSADDR_T: this record type is rarely used as of 7/2001 | |
930 | typedef struct { | |
931 | uint8_t rtype; /* value = PHYSADDR_T */ | |
932 | unsigned ea_valid : 1; /* does ea_pa contain a valid address */ | |
933 | unsigned cpuid : 7; | |
934 | uint16_t cpuid9_7 : 3; | |
935 | uint16_t notused13 : 13; | |
936 | uint32_t notused32; | |
937 | uint64_t pc_pa; | |
938 | uint64_t ea_pa; | |
939 | } rstf_physaddrT; | |
940 | static void rstf_physaddrT_set_cpuid(rstf_physaddrT * tr, int cpuid) { tr->cpuid = cpuid & 0x7f; tr->cpuid9_7 = (cpuid>>7) & 0x7; } | |
941 | static int rstf_physaddrT_get_cpuid(const rstf_physaddrT * tr) { return (tr->cpuid9_7 << 7) | tr->cpuid; } | |
942 | ||
943 | /* tell record #, before/after processing level LEV */ | |
944 | typedef struct { | |
945 | uint8_t rtype; /* value = FILEMARKER_T == RECNUM_T */ | |
946 | unsigned recNum : 1 ; /* 0 = filemark, 1 = recnum */ | |
947 | unsigned level : 7 ; /* LEV=level of the processing, 0=orig data */ | |
948 | uint8_t recType; /* rec type (e.g. INSTR_T) to set on count */ | |
949 | uint8_t cpuID; /* 0 = first CPU */ | |
950 | uint32_t cpuid9_8 : 2; | |
951 | uint32_t notused30 : 30; | |
952 | uint64_t incount; /* input record # */ | |
953 | uint64_t outcount; /* output record # (not used in recnum_T) */ | |
954 | } rstf_filemarkerT; | |
955 | static void rstf_filemarkerT_set_cpuid(rstf_filemarkerT * tr, int cpuid) { tr->cpuID = cpuid & 0xff; tr->cpuid9_8 = (cpuid>>8) & 3; } | |
956 | static int rstf_filemarkerT_get_cpuid(const rstf_filemarkerT * tr) { return (tr->cpuid9_8<<8)|tr->cpuID; } | |
957 | ||
958 | ||
959 | // reset record number counter. | |
960 | typedef struct { | |
961 | uint8_t rtype; /* value = FILEMARKER_T == RECNUM_T */ | |
962 | unsigned recNum : 1 ; /* 0 = filemark, 1 = recnum */ | |
963 | unsigned level : 7 ; /* not used */ | |
964 | uint8_t recType; /* type of record (e.g. INSTR_T) to set on count) */ | |
965 | uint8_t cpuID; /* 0 = first CPU */ | |
966 | uint32_t cpuid9_8 : 2; | |
967 | uint32_t notused30 : 30; | |
968 | uint64_t incount; /* new record # */ | |
969 | uint64_t notused64; /* not used */ | |
970 | } rstf_recnumT; | |
971 | // accessor funcs same as filemarkerT | |
972 | ||
973 | typedef struct { | |
974 | uint8_t rtype; /* value = STRDESC_T, STRCONT_T */ | |
975 | char string[23]; /* null terminated if STRDESC, no if STRCONT */ | |
976 | } rstf_stringT; | |
977 | ||
978 | // values in a STATUS_T record | |
979 | enum { | |
980 | // values for the status field a STATUS_T record | |
981 | // we start at 2 not 0, to catch the common uninitialized case. | |
982 | RST_EOF = 2, | |
983 | RST_ERROR = 3, | |
984 | RST_ANALYZER_CMD = 4, | |
985 | // let me know what else you want... | |
986 | ||
987 | // analyzer specs | |
988 | // Any/all analyzers are free to ignore these records | |
989 | RST_AN_ALL_ANALYZERS = 3, /* request for all analyzers */ | |
990 | RST_AN_CACHESIM = 4, /* all cache simulators */ | |
991 | RST_AN_MPCACHESIM = 5, | |
992 | RST_AN_CYCLESIM = 8, | |
993 | RST_AN_SIM_HONEY = 9, | |
994 | RST_AN_SIM_BB = 10, | |
995 | RST_AN_AZTECS = 11, | |
996 | RST_AN_MAYAS = 12, | |
997 | ||
998 | // command | |
999 | RST_ACMD_RESET_COUNTERS = 3, | |
1000 | RST_ACMD_DUMP_COUNTERS = 4, | |
1001 | ||
1002 | RST_STATUS_END = 255 | |
1003 | }; | |
1004 | ||
1005 | typedef struct { | |
1006 | uint8_t rtype; /* value = STATUS_T */ | |
1007 | uint8_t status; /* enumerated value (e.g. RST_EOF) */ | |
1008 | uint8_t analzyer; /* analyzer for ANALYZER_CMD */ | |
1009 | uint8_t command; /* command for ANALYZER_CMD */ | |
1010 | uint32_t notused32; | |
1011 | uint64_t notused64; | |
1012 | uint64_t notused64a; | |
1013 | } rstf_statusT; | |
1014 | ||
1015 | typedef struct { | |
1016 | uint8_t rtype; /* value = PATCH_T */ | |
1017 | ||
1018 | unsigned unused : 7; /* */ | |
1019 | unsigned isBegin : 1; /* 1=begin of patch, 0=end of patch */ | |
1020 | ||
1021 | uint8_t rewindrecs; /* # recs to rewind before applying patch */ | |
1022 | uint8_t id; /* id should match begin/end pairs */ | |
1023 | ||
1024 | uint16_t length; /* # recs in patch, ignore beg/end patchT */ | |
1025 | /* we count those beg/end of nested patches */ | |
1026 | ||
1027 | uint16_t notused32; | |
1028 | ||
1029 | char descr[16]; /* may not be null-terminated */ | |
1030 | } rstf_patchT; | |
1031 | ||
1032 | // Categories and infotypes for HWINFO_T | |
1033 | // If there are multiple values (e.g. sizes of caches) | |
1034 | // use the INDEX field to differentiate. | |
1035 | // NUMENT indicates how many vals there | |
1036 | enum { | |
1037 | HWCAT_TRSRC = 2, // trace source | |
1038 | HWINFO_RSTBLAZE = 2, // | |
1039 | HWINFO_ATRACE = 3, // | |
1040 | HWINFO_SHADE5 = 5, // | |
1041 | HWINFO_SHADE6 = 6, // | |
1042 | HWINFO_SIMICS = 7, // | |
1043 | ||
1044 | HWCAT_SIMHW = 6, // a simulated hardware value | |
1045 | HWCAT_HOSTHW = 7, // real machine hardware value | |
1046 | ||
1047 | HWINFO_CPUTYPE = 2, // 1 = US-1, 3=US-3, etc | |
1048 | HWINFO_NUMPROC = 3, // | |
1049 | HWINFO_MEMSIZE = 4, // bytes | |
1050 | HWINFO_CPUFREQ = 5, // Hertz [0]=cpufreq [1]=stick freq | |
1051 | HWINFO_TLBSIZE = 8, // size of index-th TLB, val2=assoc | |
1052 | HWINFO_CACHESPEC = 9, // size | |
1053 | HWINFO_NUMNIC = 10, // number of NICS | |
1054 | HWINFO_IPADDR = 11, // IP address | |
1055 | HWINFO_DISKSIZE = 12, // bytes | |
1056 | HWINFO_DISKDELAY = 14, // cpufreq cycles [0]=read delay [1]=write delay | |
1057 | HWINFO_NREGWIN = 15, // Number of register windows | |
1058 | ||
1059 | HWCAT_DUMMY = -1 | |
1060 | }; | |
1061 | ||
1062 | enum { | |
1063 | SNOOP_RTO = 1, | |
1064 | SNOOP_RTS = 2 | |
1065 | }; | |
1066 | ||
1067 | enum { | |
1068 | DEVICE_CPU = 1 | |
1069 | }; | |
1070 | ||
1071 | ||
1072 | typedef struct { | |
1073 | uint8_t rtype; /* value = SNOOP_T */ | |
1074 | uint8_t snoopreq; /* type of snoop request, values */ | |
1075 | uint16_t device_id; /* agent ID initiating the request */ | |
1076 | uint32_t size; /* size in bytes of snoop */ | |
1077 | uint64_t addr_pa; | |
1078 | uint16_t device_type; /* What type of device */ | |
1079 | uint16_t notused16; /* reserved */ | |
1080 | uint32_t notused32; /* reserved */ | |
1081 | } rstf_snoopT; | |
1082 | ||
1083 | typedef struct { | |
1084 | uint8_t rtype; /* value = HWINFO_T */ | |
1085 | unsigned sim : 1; | |
1086 | unsigned unused : 7; | |
1087 | uint8_t category; /* category of info Ex: sim HW value */ | |
1088 | uint8_t infotype; /* type of value Ex: CPU freq or mem size */ | |
1089 | uint16_t entindex; /* if multiple entries (e.g. cache sizes) */ | |
1090 | uint16_t nument; /* total number of entries 0=> only 1 entry */ | |
1091 | uint64_t val; /* value */ | |
1092 | uint64_t val2; | |
1093 | } rstf_hwinfoT; | |
1094 | ||
1095 | ||
1096 | enum rstf_timesyncT_subtype_e { | |
1097 | rstf_timesyncT_nil=0, | |
1098 | rstf_timesyncT_local=1, | |
1099 | rstf_timesyncT_global=2 | |
1100 | // 3..255: available for other events (eg serial sync) | |
1101 | }; | |
1102 | ||
1103 | typedef struct { | |
1104 | uint8_t rtype; // equal to TIMESYNC_T | |
1105 | uint8_t subtype; // valid values in enum rstf_timesyncT_subtype_e; | |
1106 | uint16_t zero1; // reserved1 | |
1107 | ||
1108 | uint16_t zero2; // reserved2 | |
1109 | uint16_t cpuid; | |
1110 | ||
1111 | uint64_t data; // not used for barrier sync | |
1112 | uint64_t sequence_number; // use for ordering events across traces | |
1113 | } rstf_timesyncT; | |
1114 | static void rstf_timesyncT_set_cpuid(rstf_timesyncT * tr, int cpuid) { tr->cpuid = cpuid; } | |
1115 | static int rstf_timesyncT_get_cpuid(const rstf_timesyncT * tr) { return tr->cpuid; } | |
1116 | ||
1117 | ||
1118 | static const uint32_t rstf_devidstr_continuation_id = ~0u; | |
1119 | typedef struct { | |
1120 | uint8_t rtype; // equal to DEVIDSTR_T | |
1121 | ||
1122 | /* Trailing characters must all be zero. If str[18] is not zero, | |
1123 | * this record is followed by more devidstrT record(s) that | |
1124 | * continue the string, until a zero character is found. These | |
1125 | * continuation records have an id of <rstf_devidstr_continuation_id> | |
1126 | */ | |
1127 | char str[19]; | |
1128 | ||
1129 | uint32_t id; | |
1130 | } rstf_devidstrT; | |
1131 | ||
1132 | ||
1133 | /************************ RFS SUB-TRACE STUFF ***************************/ | |
1134 | ||
1135 | /* Structure of an RST-Format Snap: | |
1136 | * | |
1137 | * ======== | |
1138 | * Header: | |
1139 | * ======== | |
1140 | * Descr: rstf_stringT record identifying the trace as rfs format | |
1141 | * The string should be the RFS descriptor 23-char string: | |
1142 | * "RFS vX.YY RST-FMT SNAP\0" | |
1143 | * X is rfs_major_version, YY is rfs_minor_version (version of the | |
1144 | * RFS format SPECIFICATION) | |
1145 | * ======== | |
1146 | * One or more RFS sections | |
1147 | * ======== | |
1148 | * | |
1149 | * An RFS section consists of an RFS section header and section data | |
1150 | * The section header is of type rstf_rfs_section_headerT (defined below) | |
1151 | * The various section data types are also defined below; these may be extended | |
1152 | * if necessary | |
1153 | ||
1154 | * | |
1155 | * IMPORTANT: Since it is possible for the record-count for | |
1156 | * the RST section to be unknown, | |
1157 | * there can be only one RST section in a snap, and it MUST be the last section | |
1158 | * FIXME: this constraint can be relaxed at the cost of slowing down | |
1159 | * the compressor/analyzers etc | |
1160 | */ | |
1161 | ||
1162 | static const int rfs_major_version = 1; | |
1163 | static const int rfs_minor_version = 0; | |
1164 | ||
1165 | // all "reserved" fields in rfs structures should be initialized | |
1166 | // to 0 for consistency. | |
1167 | ||
1168 | ||
1169 | // a ridiculously large positive 64-bit number | |
1170 | static const int64_t rfs_unknown_nrecords = ((~0ull)>>1); | |
1171 | ||
1172 | ||
1173 | typedef struct { | |
1174 | unsigned rtype : 8; // RFS_SECTION_HEADER_T | |
1175 | unsigned section_type : 8; // same as the data rtype (eg RFS_CW_T | |
1176 | // or RFS_BP_T or RFS_RST_T) | |
1177 | unsigned reserved1 : 16; | |
1178 | ||
1179 | uint32_t reserved2; | |
1180 | ||
1181 | // n_records == rfs_unknown_nrecords indicates unknown record count: | |
1182 | // reader must determine count from the input stream | |
1183 | // This feature is ONLY supported for an RST section, | |
1184 | // of which there can be only one | |
1185 | int64_t n_records; // NOT including section header record. | |
1186 | ||
1187 | uint64_t reserved3; | |
1188 | ||
1189 | // the reserved fields may be used for a checksum (eg md5sum) in the future | |
1190 | } rstf_rfs_section_headerT; | |
1191 | ||
1192 | ||
1193 | ||
1194 | typedef struct { | |
1195 | uint8_t rtype; // value = RFS_BT_T | |
1196 | unsigned cpuid : 10; | |
1197 | unsigned taken : 1; | |
1198 | unsigned reserved: 13; | |
1199 | unsigned instr; // instr word | |
1200 | uint64_t pc_va; // branch pc | |
1201 | uint64_t npc_va; // fall-through addr if branch not taken | |
1202 | } rstf_bpwarmingT; | |
1203 | static void rstf_bpwarmingT_set_cpuid(rstf_bpwarmingT * tr, int cpuid) { tr->cpuid = cpuid; } | |
1204 | static int rstf_bpwarmingT_get_cpuid(const rstf_bpwarmingT * tr) { return tr->cpuid; } | |
1205 | ||
1206 | enum cw_reftype_e { | |
1207 | cw_reftype_NIL = 0, | |
1208 | cw_reftype_I = 1, | |
1209 | cw_reftype_R = 2, | |
1210 | cw_reftype_W = 3, | |
1211 | cw_reftype_PF_D = 4, | |
1212 | cw_reftype_PF_I = 5, | |
1213 | cw_reftype_DMA_R = 6, | |
1214 | cw_reftype_DMA_W = 7, | |
1215 | ||
1216 | cw_reftype_MAX | |
1217 | }; | |
1218 | ||
1219 | ||
1220 | typedef struct { | |
1221 | uint8_t rtype; // value = RFS_CW_T | |
1222 | ||
1223 | unsigned cpuid : 10; // must be ZERO for DMA_R and DMA_W reftypes | |
1224 | unsigned reftype : 6; | |
1225 | ||
1226 | unsigned reserved1: 8; | |
1227 | ||
1228 | union refinfo_u { | |
1229 | uint32_t dma_size; | |
1230 | ||
1231 | struct refinfo_s { | |
1232 | unsigned asi : 8; // must be defined for ALL reference types | |
1233 | // except DMA. For DMA, the dma_size field | |
1234 | // overlaps with this struct | |
1235 | unsigned va_valid: 1; | |
1236 | unsigned fcn : 5; // for prefetch refs only. For others, | |
1237 | // consider this as "reserved" | |
1238 | unsigned reserved: 18; | |
1239 | } s; | |
1240 | ||
1241 | uint32_t l; // this is just to represent refinfo_s as a 32-bit | |
1242 | // quantity that can be passed to functions | |
1243 | ||
1244 | } refinfo; | |
1245 | ||
1246 | // va must be ZERO for DMA_R or DMA_W. and if the refinfo.s.va_valid | |
1247 | // bit is clear | |
1248 | uint64_t va; | |
1249 | ||
1250 | uint64_t pa; | |
1251 | } rstf_cachewarmingT; | |
1252 | static void rstf_cachewarmingT_set_cpuid(rstf_cachewarmingT * tr, int cpuid) { tr->cpuid = cpuid; } | |
1253 | static int rstf_cachewarmingT_get_cpuid(const rstf_cachewarmingT * tr) { return tr->cpuid; } | |
1254 | ||
1255 | /******************END OF RFS SUB-TRACE STUFF ***************************/ | |
1256 | ||
1257 | ||
1258 | // my template for use in emacs. Ignore. | |
1259 | typedef struct { /* not done yet */ | |
1260 | uint8_t rtype; /* value = PROTO_T */ | |
1261 | uint8_t notused8; | |
1262 | uint16_t notused16; | |
1263 | uint32_t notused32; | |
1264 | uint64_t notused64; | |
1265 | uint64_t notused64a; | |
1266 | } rstf_whatT; | |
1267 | ||
1268 | typedef union { | |
1269 | rstf_headerT header; | |
1270 | rstf_instrT instr; | |
1271 | rstf_traceinfo_levelT tlevel; | |
1272 | rstf_cpuinfoT cpuinfo; | |
1273 | rstf_cpuidinfoT cpuidinfo; | |
1274 | rstf_tlbT tlb; | |
1275 | rstf_threadT thread; | |
1276 | rstf_pregT preg; | |
1277 | rstf_trapT trap; | |
1278 | rstf_trapexitT trapexit; | |
1279 | rstf_trapping_instrT trapping_instr; | |
1280 | rstf_cpuT cpu; | |
1281 | rstf_dmaT dma; | |
1282 | rstf_delimT delim; | |
1283 | rstf_physaddrT physaddr; | |
1284 | rstf_pavadiffT pavadiff; | |
1285 | rstf_filemarkerT fmarker; | |
1286 | rstf_hwinfoT hwinfo; | |
1287 | rstf_recnumT recnum; | |
1288 | rstf_stringT string; | |
1289 | rstf_statusT status; | |
1290 | rstf_patchT patch; | |
1291 | rstf_regvalT regval; | |
1292 | rstf_memval64T memval64; | |
1293 | rstf_memval128T memval128; | |
1294 | rstf_bustraceT bustrace; | |
1295 | rstf_snoopT snoop; | |
1296 | rstf_tsb_accessT tsb_access; | |
1297 | rstf_rfs_section_headerT rfs_section_header; | |
1298 | rstf_bpwarmingT bpwarming; | |
1299 | rstf_cachewarmingT cachewarming; | |
1300 | ||
1301 | // types for fields in the rst record | |
1302 | rstf_protoT proto; | |
1303 | rstf_uint8T arr8; | |
1304 | rstf_uint16T arr16; | |
1305 | rstf_uint32T arr32; | |
1306 | rstf_uint64T arr64; | |
1307 | ||
1308 | #if defined(RSTF_USE_DEPRECATED) | |
1309 | rstf_contextT context; | |
1310 | #endif | |
1311 | ||
1312 | } rstf_unionT; | |
1313 | ||
1314 | #define SIZEOF_RSTF (sizeof(rstf_unionT)) | |
1315 | ||
1316 | // ================ 4) Useful functions ================ | |
1317 | // | |
1318 | // Some macros and functions for dealing with rstf | |
1319 | // | |
1320 | ||
1321 | // Do a compile-time vs run-time check on a record from a trace | |
1322 | int rstf_checkheader (const char* compile_time_ver, rstf_headerT *rec); | |
1323 | ||
1324 | // Open a RST file for reading. | |
1325 | // If the file is compressed (rstzip/rstzip2), automatically decompress | |
1326 | // We use popen() internally, if filename is a compressed file | |
1327 | // Returns | |
1328 | // null on error and sets errno | |
1329 | // | |
1330 | FILE* openRST (const char* filename); | |
1331 | void closeRST (FILE* f); // pclose(f); if compressed | |
1332 | int isPipeRST (FILE* f); // 1 if f is a pipe, as in from popen(). | |
1333 | ||
1334 | // initialize a header record with the current RST major/minor number. | |
1335 | // The string | |
1336 | int init_rstf_header (rstf_headerT * headerp); | |
1337 | ||
1338 | // initialize a header record with the current RST major/minor number. | |
1339 | int init_rstf_traceinfo_level (rstf_traceinfo_levelT * ti, int level); | |
1340 | ||
1341 | // Initialize a single STR_DESC RST record STRP with the string STR | |
1342 | // takes the last 22 chars if STR will not fully fit. | |
1343 | int init_rstf_string (rstf_stringT * strp, const char *str); | |
1344 | ||
1345 | // Note: In most cases, rstf_snprintf() is easier to use. | |
1346 | // Initialize upto MAXREC records with the string STR, using | |
1347 | // STRDESC_T and STRCONT_T records. Handles strings of any length. | |
1348 | // Returns the number of RST records used. | |
1349 | // You must allocate the space to which STRP points. | |
1350 | // | |
1351 | // Ex: | |
1352 | // rstf_unionT buff[128]; | |
1353 | // int currIdx = 37 ; | |
1354 | // char charbuff [8192]; | |
1355 | // sprintf(charbuff, "A long bunch of data %s %d ...", ... ); | |
1356 | // rstf_sprintf( &buff[currIdx] , charbuff, 128-37-1 ); | |
1357 | // | |
1358 | int init_rstf_strbuff (rstf_stringT * strp, const char *str, int maxrec); | |
1359 | ||
1360 | // Convenience fns: | |
1361 | // rstf_sprintf(): | |
1362 | // initialize a RST record STRP with the sprintf output | |
1363 | // if the resulting string is too long, the last 22 chars are used. | |
1364 | // | |
1365 | // rstf_snprintf() | |
1366 | // initialize upto MAXREC RST records STRP with the sprintf output | |
1367 | // if the resulting string is too long, the last characters are dropped. | |
1368 | // Also, we use an 8K buffer, all chars beyond which are silently dropped. | |
1369 | // Returns the number of RST records actually used. | |
1370 | // | |
1371 | // Ex: | |
1372 | // rstf_unionT buff[...]; | |
1373 | // rstf_unionT * currRec = ... ; | |
1374 | // struct passwd * pp = getpwuid( getuid() ); | |
1375 | // nr = rstf_sprintf( currRec, "Collected by user %s", pp->pw_name); | |
1376 | // nr = rstf_snprintf( currRec+1, 4, "Some big long string %s", stringval); | |
1377 | // | |
1378 | int rstf_sprintf (rstf_stringT * strp, const char* fmt, ...); | |
1379 | int rstf_snprintf (rstf_stringT * strp, int maxrec, const char* fmt, ...); | |
1380 | ||
1381 | // Given a multi-record string, read it. | |
1382 | // STRP points to the first of NREC consecutive (in an array) RST records. | |
1383 | // These need not all be string, but must know how many recs we can read. | |
1384 | // Returns the string in a static buffer. | |
1385 | // If NRREAD != NULL, we return the number of RST records we skipped over. | |
1386 | // Internally we use a 2048 char buffer. | |
1387 | const char* get_rstf_longstr (const rstf_stringT * strp, int nrec, int *nrread); | |
1388 | ||
1389 | // 1) Return the result of running command COMMAND | |
1390 | // The result is returned in a static buffer of size at least 4K. | |
1391 | // | |
1392 | // 2) Store the exit status at *EXIT_STATUS, if this addr is non-NULL | |
1393 | // 3) Get at most MAXLINE lines of output from the COMMAND. | |
1394 | // | |
1395 | char* unixcommand (const char * command, int MAXLINE, int* exit_status); | |
1396 | ||
1397 | // returns a pointer to a statically allocated buffer | |
1398 | // Ex: rstf_btTxtype2str (RST_BTTX_RTSA) ==> "RTSA" | |
1399 | const char* rstf_btTxtype2str (int txType); | |
1400 | ||
1401 | ||
1402 | // the set cpuid function must be called *after* initializing the rtype field | |
1403 | // the get cpuid function returns 0xffff if the cpuid field is not present in | |
1404 | // the record type being queried. | |
1405 | static void rstf_set_cpuid(rstf_unionT * rec, int cpuid) { | |
1406 | switch(rec->proto.rtype) { | |
1407 | case INSTR_T: | |
1408 | rstf_instrT_set_cpuid(&rec->instr, cpuid); | |
1409 | break; | |
1410 | case PAVADIFF_T: | |
1411 | rstf_pavadiffT_set_cpuid(&rec->pavadiff, cpuid); | |
1412 | break; | |
1413 | case TLB_T: | |
1414 | rstf_tlbT_set_cpuid(&rec->tlb, cpuid); | |
1415 | break; | |
1416 | case PREG_T: | |
1417 | rstf_pregT_set_cpuid(&rec->preg, cpuid); | |
1418 | break; | |
1419 | case TRAP_T: | |
1420 | rstf_trapT_set_cpuid(&rec->trap, cpuid); | |
1421 | break; | |
1422 | case TRAPEXIT_T: | |
1423 | rstf_trapexitT_set_cpuid(&rec->trapexit, cpuid); | |
1424 | break; | |
1425 | case TSB_ACCESS_T: | |
1426 | rstf_tsb_accessT_set_cpuid(&rec->tsb_access, cpuid); | |
1427 | break; | |
1428 | case TRAPPING_INSTR_T: | |
1429 | rstf_trapping_instrT_set_cpuid(&rec->trapping_instr, cpuid); | |
1430 | break; | |
1431 | case REGVAL_T: | |
1432 | rstf_regvalT_set_cpuid(&rec->regval, cpuid); | |
1433 | break; | |
1434 | case MEMVAL_T: | |
1435 | rstf_memval128T_set_cpuid(&rec->memval128, cpuid); | |
1436 | break; | |
1437 | case PHYSADDR_T: | |
1438 | rstf_physaddrT_set_cpuid(&rec->physaddr, cpuid); | |
1439 | break; | |
1440 | case FILEMARKER_T: | |
1441 | rstf_filemarkerT_set_cpuid(&rec->fmarker, cpuid); | |
1442 | break; | |
1443 | case RFS_BT_T: | |
1444 | rstf_bpwarmingT_set_cpuid(&rec->bpwarming, cpuid); | |
1445 | break; | |
1446 | case RFS_CW_T: | |
1447 | rstf_cachewarmingT_set_cpuid(&rec->cachewarming, cpuid); | |
1448 | break; | |
1449 | default: | |
1450 | break; | |
1451 | // fprintf(stderr, "rstf.h: warning: set_cpuid meaningless for rtype=%d\n", rec->proto.rtype); | |
1452 | } // swithc(rtype) | |
1453 | } | |
1454 | ||
1455 | static int16_t rstf_get_cpuid(const rstf_unionT * rec) | |
1456 | { | |
1457 | switch(rec->proto.rtype) { | |
1458 | case INSTR_T: | |
1459 | return rstf_instrT_get_cpuid(&rec->instr); | |
1460 | break; | |
1461 | case PAVADIFF_T: | |
1462 | return rstf_pavadiffT_get_cpuid(&rec->pavadiff); | |
1463 | break; | |
1464 | case TLB_T: | |
1465 | return rstf_tlbT_get_cpuid(&rec->tlb); | |
1466 | break; | |
1467 | case PREG_T: | |
1468 | return rstf_pregT_get_cpuid(&rec->preg); | |
1469 | break; | |
1470 | case TRAP_T: | |
1471 | return rstf_trapT_get_cpuid(&rec->trap); | |
1472 | break; | |
1473 | case TRAPEXIT_T: | |
1474 | return rstf_trapexitT_get_cpuid(&rec->trapexit); | |
1475 | break; | |
1476 | case TSB_ACCESS_T: | |
1477 | return rstf_tsb_accessT_get_cpuid(&rec->tsb_access); | |
1478 | case TRAPPING_INSTR_T: | |
1479 | return rstf_trapping_instrT_get_cpuid(&rec->trapping_instr); | |
1480 | case REGVAL_T: | |
1481 | return rstf_regvalT_get_cpuid(&rec->regval); | |
1482 | break; | |
1483 | case MEMVAL_T: | |
1484 | return rstf_memval128T_get_cpuid(&rec->memval128); | |
1485 | break; | |
1486 | case PHYSADDR_T: | |
1487 | return rstf_physaddrT_get_cpuid(&rec->physaddr); | |
1488 | break; | |
1489 | case FILEMARKER_T: | |
1490 | return rstf_filemarkerT_get_cpuid(&rec->fmarker); | |
1491 | break; | |
1492 | case RFS_BT_T: | |
1493 | return rstf_bpwarmingT_get_cpuid(&rec->bpwarming); | |
1494 | break; | |
1495 | case RFS_CW_T: | |
1496 | return rstf_cachewarmingT_get_cpuid(&rec->cachewarming); | |
1497 | break; | |
1498 | default: | |
1499 | // fprintf(stderr, "rstf.h: warning: get_cpuid meaningless for rtype=%d\n", rec->proto.rtype); | |
1500 | return -1; | |
1501 | } // swithc(rtype) | |
1502 | } // static int16_T rstf_get_cpuid() | |
1503 | ||
1504 | ||
1505 | ||
1506 | // Initialize the RST record pointed ty by RST_PTR, with the rtype RTYPE_VAL | |
1507 | // Fill the rest of the record with zero data. | |
1508 | // This macro code is as efficient as I (RQ) could make it. | |
1509 | // Ex: | |
1510 | // rstf_unionT array[256]; | |
1511 | // ... | |
1512 | // INIT_RST_REC( &array[k], INSTR_T); | |
1513 | // rstf_instrT * p = & ( array[k].instr ); | |
1514 | // | |
1515 | #define INIT_RST_REC(rstf_x_ptr,rtype_val) \ | |
1516 | do { \ | |
1517 | rstf_uint64T * p_x_rst = (rstf_uint64T*) (rstf_x_ptr); \ | |
1518 | p_x_rst->arr64[0] = (rtype_val); \ | |
1519 | p_x_rst->arr64[0] <<= (64-8); \ | |
1520 | p_x_rst->arr64[1] = 0; \ | |
1521 | p_x_rst->arr64[2] = 0; \ | |
1522 | } while (0==1) | |
1523 | ||
1524 | #define ZERO_RST_REC(rstf_x_ptr) \ | |
1525 | do { \ | |
1526 | rstf_uint64T * p_x_rst = (rstf_uint64T*) (rstf_x_ptr); \ | |
1527 | p_x_rst->arr64[0] = 0; \ | |
1528 | p_x_rst->arr64[1] = 0; \ | |
1529 | p_x_rst->arr64[2] = 0; \ | |
1530 | } while (0==1) | |
1531 | ||
1532 | // The tte_data that blaze v2.40-v3.60 uses to mimic the US-III. | |
1533 | // This type is now an official type in rstf.h | |
1534 | // | |
1535 | struct rstf_tte_dataT { | |
1536 | unsigned valid : 1; /* valid bit */ | |
1537 | unsigned size : 2; /* page size */ | |
1538 | unsigned nfo : 1; /* no-fault only */ | |
1539 | unsigned ie : 1; /* invert endianness */ | |
1540 | unsigned soft2 : 9; /* forced to zero */ | |
1541 | unsigned subpg : 2; | |
1542 | unsigned sn : 1; /* snoop bit */ | |
1543 | unsigned diag_reserved : 2; | |
1544 | unsigned diag_used : 1; | |
1545 | unsigned io : 1; | |
1546 | unsigned pa_tag_hi : 11; /* PA bits <42:32> hi+lo give 43 bit PA */ | |
1547 | unsigned pa_tag_lo : 19; /* PA bits <31:13> (use for 32-bit addr) */ | |
1548 | unsigned soft : 6; /* forced to zero */ | |
1549 | unsigned lock : 1; /* lock bit */ | |
1550 | unsigned cp : 1; /* cacheable physical */ | |
1551 | unsigned cv : 1; /* cacheable virtual */ | |
1552 | unsigned e : 1; /* side-effect */ | |
1553 | unsigned priv : 1; /* priviledged */ | |
1554 | unsigned writable : 1; /* writeable */ | |
1555 | unsigned global : 1; /* global (same as tag.g) */ | |
1556 | }; | |
1557 | ||
1558 | #ifdef __cplusplus | |
1559 | } | |
1560 | #endif | |
1561 | ||
1562 | #endif /* _rstf_h */ |