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