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