Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / rst / rstf / rstf.h
CommitLineData
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
131extern "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
165int 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
174static 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 */
205enum {
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 */
268enum {
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
295typedef 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;
303typedef 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
310typedef struct {
311 uint8_t arr8[ sizeof(rstf_protoT)/sizeof(uint8_t) ];
312} rstf_uint8T;
313
314typedef struct {
315 uint16_t arr16[ sizeof(rstf_protoT)/sizeof(uint16_t) ];
316} rstf_uint16T;
317
318typedef struct {
319 uint32_t arr32[ sizeof(rstf_protoT)/sizeof(uint32_t) ];
320} rstf_uint32T;
321
322typedef 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);
329typedef 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
341typedef 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;
363static void rstf_instrT_set_cpuid(rstf_instrT * tr, int cpuid) { tr->cpuid = cpuid & 0x3f; tr->cpuid9_6 = ((cpuid>>6) & 0xf); }
364static int rstf_instrT_get_cpuid(const rstf_instrT * tr) { return (tr->cpuid9_6<<6)|tr->cpuid; }
365
366typedef 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;
377static void rstf_pavadiffT_set_cpuid(rstf_pavadiffT * tr, int cpuid) { tr->cpuid = cpuid & 0x7f; tr->cpuid9_7 = (cpuid>>7)&0x7; }
378static 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
381enum {
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
412typedef 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
421typedef 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
439typedef 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
447typedef 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
458typedef 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;
486static void rstf_tlbT_set_cpuid(rstf_tlbT * tr, int cpuid) { tr->cpuid = cpuid & 0x3f; tr->cpuid9_6 = (cpuid>>6)&0xf; }
487static int rstf_tlbT_get_cpuid(const rstf_tlbT * tr) { return (tr->cpuid9_6<<6)|tr->cpuid; }
488
489typedef 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
498typedef 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
511typedef 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;
534static void rstf_pregT_set_cpuid(rstf_pregT * tr, int cpuid) { tr->cpuid = cpuid & 0xff; tr->cpuid9_8 = (cpuid>>8) & 3; }
535static int rstf_pregT_get_cpuid(const rstf_pregT * tr) { return (tr->cpuid9_8<<8)|tr->cpuid; }
536
537typedef 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;
554static void rstf_trapT_set_cpuid(rstf_trapT * tr, int cpuid) { tr->cpuid = cpuid & 0x3f; tr->cpuid9_6 = (cpuid>>6) & 0xf; }
555static int rstf_trapT_get_cpuid(const rstf_trapT * tr) { return (tr->cpuid9_6 << 6) | tr->cpuid; }
556
557typedef 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;
568static void rstf_trapexitT_set_cpuid(rstf_trapexitT * tr, int cpuid) { tr->cpuid = cpuid & 0x3f; tr->cpuid9_6 = (cpuid>>6) & 0xf; }
569static int rstf_trapexitT_get_cpuid(const rstf_trapexitT * tr) { return (tr->cpuid9_6 << 6) | tr->cpuid; }
570
571
572typedef 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
582typedef 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
593typedef 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;
603static void rstf_tsb_accessT_set_cpuid(rstf_tsb_accessT * tr, int cpuid) { tr->cpuid = cpuid; }
604static 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 */
613typedef 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;
636static void rstf_trapping_instrT_set_cpuid(rstf_trapping_instrT * tr, int cpuid) { tr->cpuid = cpuid; }
637static 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
668enum {
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 //
705typedef 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>
710typedef 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
732enum {
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 */
868typedef 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;
881static void rstf_regvalT_set_cpuid(rstf_regvalT * tr, int cpuid) { tr->cpuid = cpuid & 0x7f; tr->cpuid9_7 = (cpuid>>7) & 0x7; }
882static 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//
903typedef 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;
917static void rstf_memval128T_set_cpuid(rstf_memval128T * tr, int cpuid) { tr->cpuid = cpuid & 0xff; tr->cpuid9_8 = (cpuid>>8) & 3; }
918static int rstf_memval128T_get_cpuid(const rstf_memval128T * tr) { return (tr->cpuid9_8<<8)|tr->cpuid; }
919
920static void rstf_memval128T_set_addr(rstf_memval128T * tr, uint64_t addr) {tr->addr36_43 = (addr>>36)&0xff; tr->addr04_35 = (addr>>4) & ~0u;}
921static uint64_t rstf_memval128T_get_addr(rstf_memval128T * tr) { return (((uint64_t)tr->addr36_43) << 36) | (((uint64_t)tr->addr04_35) << 4); }
922
923typedef 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
939static void rstf_memval64T_set_cpuid(rstf_memval64T * tr, int cpuid) { tr->cpuid = cpuid & 0xff; tr->cpuid9_8 = (cpuid>>8) & 3; }
940static int rstf_memval64T_get_cpuid(const rstf_memval64T * tr) { return (tr->cpuid9_8<<8)|tr->cpuid; }
941
942typedef 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
952typedef 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;
962static void rstf_physaddrT_set_cpuid(rstf_physaddrT * tr, int cpuid) { tr->cpuid = cpuid & 0x7f; tr->cpuid9_7 = (cpuid>>7) & 0x7; }
963static 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 */
966typedef 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;
977static void rstf_filemarkerT_set_cpuid(rstf_filemarkerT * tr, int cpuid) { tr->cpuID = cpuid & 0xff; tr->cpuid9_8 = (cpuid>>8) & 3; }
978static int rstf_filemarkerT_get_cpuid(const rstf_filemarkerT * tr) { return (tr->cpuid9_8<<8)|tr->cpuID; }
979
980
981// reset record number counter.
982typedef 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
995typedef 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
1001enum {
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
1027typedef 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
1037typedef 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
1058enum {
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
1084enum {
1085 SNOOP_RTO = 1,
1086 SNOOP_RTS = 2
1087};
1088
1089enum {
1090 DEVICE_CPU = 1
1091};
1092
1093
1094typedef 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
1105typedef 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
1118enum 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
1125typedef 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;
1136static void rstf_timesyncT_set_cpuid(rstf_timesyncT * tr, int cpuid) { tr->cpuid = cpuid; }
1137static int rstf_timesyncT_get_cpuid(const rstf_timesyncT * tr) { return tr->cpuid; }
1138
1139
1140static const uint32_t rstf_devidstr_continuation_id = ~0u;
1141typedef 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
1184static const int rfs_major_version = 1;
1185static 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
1192static const int64_t rfs_unknown_nrecords = ((~0ull)>>1);
1193
1194
1195typedef 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
1216typedef 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;
1225static void rstf_bpwarmingT_set_cpuid(rstf_bpwarmingT * tr, int cpuid) { tr->cpuid = cpuid; }
1226static int rstf_bpwarmingT_get_cpuid(const rstf_bpwarmingT * tr) { return tr->cpuid; }
1227
1228enum 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
1242typedef 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;
1274static void rstf_cachewarmingT_set_cpuid(rstf_cachewarmingT * tr, int cpuid) { tr->cpuid = cpuid; }
1275static 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.
1281typedef 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
1290typedef 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
1344int 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 //
1352FILE* openRST (const char* filename);
1353void closeRST (FILE* f); // pclose(f); if compressed
1354int 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
1358int init_rstf_header (rstf_headerT * headerp);
1359
1360 // initialize a header record with the current RST major/minor number.
1361int 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.
1365int 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 //
1380int 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 //
1400int rstf_sprintf (rstf_stringT * strp, const char* fmt, ...);
1401int 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.
1409const 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 //
1417char* 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"
1421const 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.
1427static 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
1477static 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 //
1557struct 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 */