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