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