1 /*========================== begin_copyright_notice ============================ 2 3 Copyright (C) 2018-2021 Intel Corporation 4 5 SPDX-License-Identifier: MIT 6 7 ============================= end_copyright_notice ===========================*/ 8 9 #ifndef IGA_KV_H 10 #define IGA_KV_H 11 12 #include "iga.h" 13 #include "iga_types_swsb.hpp" 14 15 /************************************************************************* 16 * * 17 * The KernelView C interface * 18 * * 19 *************************************************************************/ 20 21 #ifdef __cplusplus 22 extern "C" { 23 #endif 24 25 /* 26 * This symbols defines the maximum number of PC targets that an instruction 27 * may have. It is typically used to statically allocate an array of target 28 * PCs with the kv_get_inst_targets function. 29 * E.g. 30 * uint32_t targetPCs[KV_MAX_TARGETS_PER_INSTRUCTION]; 31 * uint32_t num = kv_get_inst_targets(kv, atPc, &targets[0]); 32 * for (int i = 0; i < num; i++) { 33 * processTarget(targetPCs[i]); 34 * } 35 */ 36 #define KV_MAX_TARGETS_PER_INSTRUCTION 3 37 /* 38 * This symbol represents an invalid PC. 0 is a valid PC (the beginnning 39 * of the kernel). 40 */ 41 #define KV_INVALID_PC_VALUE ((int32_t)0xFFFFFFFF) 42 43 /* incomplete type for a kernel view handle */ 44 struct kv_t; 45 46 /* Kernel viewer statuses */ 47 typedef enum { 48 KV_SUCCESS = 0, 49 KV_ERROR = 1, /* general error */ 50 KV_DECODE_ERROR = 2, /* 51 * error during initial decode of the kernel 52 * always check KernelView::decodeSucceeded. 53 */ 54 KV_INVALID_PC = 3, /* invalid instruction PC */ 55 56 KV_INVALID_ARGUMENT = 10, /* an invalid argument passed in */ 57 58 KV_NON_SEND_INSTRUCTION = 20, /* underlying inst isn't a send */ 59 KV_DESCRIPTOR_INDIRECT = 21, /* a send message with a reg desc */ 60 KV_DESCRIPTOR_INVALID = 22, /* an unrecognized send descriptor */ 61 KV_NO_SUBFUNCTION = 23, /* underlying inst has no sub-function */ 62 63 KV_INCAPABLE_PLATFORM = 30 /* the called-api is incapable on the platform*/ 64 } kv_status_t; 65 66 /* 67 * Creates a kernel view. 68 * 'plat' - the platform 69 * 'bytes' - the kernel binary 70 * 'bytes_len' - the length of 'bytes' 71 * 'status' - the IGA status code 72 * 'errbuf' - an optional buffer to emit errors or warnings (can pass nullptr) 73 * 'errbuf_cap' - the capacity of errbuf. 74 * RETURNS: a kernel view object for use in other kv_* functions. 75 * Deallocate it with kv_delete. If there is a decode error (or other errors), this 76 * function returns an instance of Kernel Views and ERROR status. If user proceeds 77 * to use the returned Kernel View we do not guarantee that all bits are correct 78 */ 79 IGA_API kv_t *kv_create( 80 iga_gen_t plat, 81 const void *bytes, 82 size_t bytes_len, 83 iga_status_t *status, 84 char *errbuf, 85 size_t errbuf_cap, 86 // if not specified, the swsb encoding mode will be derived from platfrom 87 // by SWSB::getEncodeMode 88 iga::SWSB_ENCODE_MODE swsb_enc_mode 89 = iga::SWSB_ENCODE_MODE::SWSBInvalidMode 90 ); 91 92 /* destroys a kernel view */ 93 IGA_API void kv_delete(kv_t *); 94 95 96 /* 97 * Returns the size of the instruction at 'pc'; returns 0 if the program 98 * address is out of bounds. This allows one to iterate a kernel using this 99 * API. For example: 100 * 101 * uint32_t iLen; 102 * for (uint32_t pc = 0; 103 * (iLen = kv_get_inst_size(kv, pc)) != 0; 104 * pc += iLen) 105 * { 106 * ... process instruction 107 * } 108 */ 109 IGA_API int32_t kv_get_inst_size(const kv_t *kv, int32_t pc); 110 111 /* 112 * Returns true if the instruction has the opt 113 */ 114 IGA_API bool kv_has_inst_opt(const kv_t *kv, int32_t pc, uint32_t opt); 115 116 /* 117 * This function returns the absolute PC targets of this instruction. 118 * For branching instructions, it populates 'pcs' with the jump targets 119 * of this instruction. The number of PC's will always be less than or 120 * equal to MAX_KV_TARGETS_COUNT. The function returns the number of 121 * target PCs populated in the 'pcs' argument. 122 * 123 * For non-branching instructions this returns 0 and does not touch 'pcs'. 124 * 125 * If 'pcs' is NULL, it is ignored. The number of targets is still returned. 126 */ 127 IGA_API uint32_t kv_get_inst_targets( 128 const kv_t *kv, 129 int32_t pc, 130 int32_t *pcs); 131 132 133 /* 134 * This function returns the syntax for a given instruction. 135 * The user passes the buffer 'sbuf' (along with its capacity) to hold 136 * the output. The output may be truncated if the passed buffer is too 137 * small, but it will always be suffixed with a NUL byte. 138 * 139 * The formatting options 'fmt_opts' are the same as those in 140 * iga_disassemble_options_t::formatting_opts. 141 * 142 * The optional 'get_label_name' callback may be called to converts 143 * a PC into a label. The caller can provide NULL and internal label names 144 * will be used. The 'env' context parameter is passed to 'get_label_name'. 145 * Memory returned by the callback is only read by IGA. 146 * 147 * This function returns the number of characters written to sbuf 148 * (including NUL byte). If the PC is out of bounds or 'kv' NULL or 149 * something else is wrong, then 0 is returned. 150 */ 151 IGA_API size_t kv_get_inst_syntax( 152 const kv_t *kv, 153 int32_t pc, 154 char *sbuf, 155 size_t sbuf_cap, 156 uint32_t fmt_opts, 157 const char *(*get_label_name)(int32_t, void *), 158 void *env); 159 160 /* 161 * This function returns the default label name if custom labeler is not used. 162 */ 163 IGA_API size_t kv_get_default_label_name( 164 int32_t pc, 165 char *sbuf, 166 size_t sbuf_cap); 167 168 /* 169 * Returns non-zero iff this instruction is a branch target. 170 * The caller can use this function to determine if it should emit a label 171 * first. 172 */ 173 IGA_API uint32_t kv_is_inst_target(const kv_t *kv, int32_t pc); 174 175 176 /* 177 * This enumeration allows one to determine if a given PC is for structured 178 * control flow. This is for tools that want to render an indentation for 179 * readability. 180 */ 181 typedef enum { 182 KV_OPGROUP_INVALID, /* not a valid op (e.g. out of bounds, middle of instruction) */ 183 KV_OPGROUP_OTHER, /* some other instruction */ 184 KV_OPGROUP_IF, /* an 'if' op */ 185 KV_OPGROUP_ELSE, /* an 'else' op */ 186 KV_OPGROUP_ENDIF, /* an 'endif' op */ 187 KV_OPGROUP_WHILE, /* a 'while' op */ 188 KV_OPGROUP_SEND_EOT, /* a send message with the EOT bit set */ 189 } kv_opgroup_t; 190 191 192 /* 193 * This function returns the opcode group. The result may be compared 194 * to the integral value of the various kv_opcode_group enumerates. 195 * (See enum kv_get_opgroup_t.) 196 */ 197 IGA_API int32_t kv_get_opgroup(const kv_t *kv, int32_t pc); 198 199 200 /* 201 * Returns the send function descriptors. The count of descriptors is 202 * returned; hence, if the instruction is invalid or not a send or 203 * send using two index registers, 0 is returned. 204 * If one of the descriptors is not immediate, then 1 is returned 205 * and that descriptor is set to KV_INVALID_SEND_DESC. 206 * 207 * Also returns 0 if any parameter is NULL (and parameters are untouched). 208 */ 209 IGA_API uint32_t kv_get_send_descs( 210 const kv_t *kv, 211 int32_t pc, 212 uint32_t *ex_desc, 213 uint32_t *desc); 214 215 216 /* 217 * Returns the indirect descriptor registers for a send message. 218 * The function fails silently if the PC is invalid or a nullptr is passed. 219 * Registers are assigned KV_INVALID_REG on other failures otherwise they 220 * hold the index register and subregister (e.g. a0.2) would have 0 and 2. 221 */ 222 IGA_API void kv_get_send_indirect_descs( 223 const kv_t *kv, 224 int32_t pc, 225 uint8_t *ex_desc_reg, 226 uint8_t *ex_desc_subreg, 227 uint8_t *desc_reg, 228 uint8_t *desc_subreg); 229 230 /* 231 * Determines if the given send instruction is on ExBSO mode. 232 * exbso = 1 if true, 0 if fales. 233 * exbso = -1 if not success. 234 * exbso mode is introduces since XeHP. 235 * 236 * RETURNS: 237 * KV_SUCCESS on success 238 * KV_NON_SEND_INSTRUCTION if called on a non-send instruction 239 * KV_INVALID_PC if passed an invalid PC 240 * KV_INVALID_ARGUMENT if given a null parameter 241 * KV_INCAPABLE_PLATFORM if it's not XeHP+ platform 242 */ 243 IGA_API kv_status_t kv_get_send_exbso( 244 const kv_t *kv, 245 int32_t pc, 246 int32_t *exbso); 247 248 /* 249 * A symbol to indicate an invalid send descriptor value. 250 */ 251 #define KV_INVALID_SEND_DESC ((uint32_t)0xFFFFFFFFF) 252 253 /* TODO: review necessity of this macro. 254 * A symbol to indicate an invalid message length value. 255 */ 256 #define KV_INVALID_LEN ((uint32_t)0xFFFFFFFFF) 257 258 /* 259 * Indicates invalid register 260 */ 261 #define KV_INVALID_REG 0xff 262 263 /* 264 * Determines the message type for the given send instruction. 265 * The result is returned via the pointer 'message_type_enum' - an 266 * iga::SFMessageType value. 267 * 268 * RETURNS: 269 * KV_SUCCESS on success 270 * KV_NON_SEND_INSTRUCTION if called on a non-send instruction 271 * KV_DESCRIPTOR_INDIRECT if called on a send with reg descriptors 272 * KV_DESCRIPTOR_INVALID if unable to map the descriptor value 273 * (not all messages are mapped via this API) 274 * KV_INVALID_PC if passed an invalid PC 275 * KV_INVALID_ARGUMENT if given a null parameter 276 */ 277 IGA_API kv_status_t kv_get_message_type( 278 const kv_t *kv, int32_t pc, int32_t *message_type_enum); 279 280 /* 281 * Determines the message type for the given send instruction. 282 * desc and sfid are passed in explicitly when indirect desc prevents 283 * use of kv_get_message_type. 284 * The result is returned via the pointer 'message_type_enum' - an 285 * iga::SFMessageType value. 286 * 287 * RETURNS: 288 * KV_SUCCESS on success 289 * KV_NON_SEND_INSTRUCTION if called on a non-send instruction 290 * KV_DESCRIPTOR_INDIRECT if called on a send with reg descriptors 291 * KV_DESCRIPTOR_INVALID if unable to map the descriptor value 292 * (not all messages are mapped via this API) 293 * KV_INVALID_PC if passed an invalid PC 294 * KV_INVALID_ARGUMENT if given a null parameter 295 */ 296 IGA_API kv_status_t kv_get_message_type_ext( 297 const kv_t *kv, int32_t pc, uint32_t desc, int32_t sfid, int32_t *message_type_enum); 298 299 /* 300 * Determines the message sfid for the given send instruction. 301 * The result is returned via the pointer 'sfid_enum' - an iga::SFID 302 * 303 * RETURNS: 304 * KV_SUCCESS on success 305 * KV_NON_SEND_INSTRUCTION if called on a non-send instruction 306 * KV_DESCRIPTOR_INDIRECT if called on a send with reg descriptors 307 * KV_DESCRIPTOR_INVALID if unable to map the descriptor value 308 * KV_INVALID_PC if passed an invalid PC 309 * KV_INVALID_ARGUMENT if given a null parameter 310 */ 311 IGA_API kv_status_t kv_get_message_sfid( 312 const kv_t *kv, int32_t pc, int32_t *sfid_enum); 313 314 /* 315 * Gets message length, extended message length, and response length in 316 * units of registers. The count of lengths successfully set is returned. 317 * If any of the parameters is NULL, it returns 0. Invalid lengths are set 318 * to KV_INVALID_LEN. 319 */ 320 IGA_API uint32_t kv_get_message_len( 321 const kv_t *kv, int32_t pc, uint32_t* mLen, uint32_t* emLen, uint32_t* rLen); 322 323 /* 324 * Alternative version of kv_get_message_len when desc or exDesc are 325 * indirect. If any of the parameters is NULL, it returns 0. Invalid lengths 326 * are set to KV_INVALID_LEN. 327 */ 328 IGA_API uint32_t kv_get_message_len_ext( 329 const kv_t *kv, int32_t pc, uint32_t desc, uint32_t exDesc, 330 uint32_t* mLen, uint32_t* emLen, uint32_t* rLen); 331 332 /* 333 * Returns the ExecSize of the instruction (SIMD width) 334 * 0 - INVALID 335 * 1 - EXEC_SIZE_1 336 * 2 - EXEC_SIZE_2 337 * 3 - EXEC_SIZE_4 338 * 4 - EXEC_SIZE_8 339 * 5 - EXEC_SIZE_16 340 * 6 - EXEC_SIZE_32 341 */ 342 IGA_API uint32_t kv_get_execution_size(const kv_t *kv, int32_t pc); 343 344 /* 345 * Returns Software scoreboarding information. 346 */ 347 IGA_API bool kv_get_swsb_info( 348 const kv_t *kv, int32_t pc, iga::SWSB_ENCODE_MODE encdoe_mode, 349 iga::SWSB& swsb); 350 351 /* 352 * Returns number of sources this instruction has. 353 */ 354 IGA_API int32_t kv_get_number_sources(const kv_t *kv, int32_t pc); 355 356 /* 357 * This function returns OPcode integer. The value corresponds to 358 * binary encoding value of the opcode. 359 */ 360 IGA_API uint32_t kv_get_opcode(const kv_t *kv, int32_t pc); 361 362 /* 363 * This function returns OPcode integer. The value corresponds to 364 * binary encoding value of the opcode. 365 */ 366 IGA_API kv_status_t kv_get_subfunction(const kv_t *kv, int32_t pc, uint32_t* subfunc); 367 368 /* 369 * This function returns if intruction has destination. 370 */ 371 IGA_API int32_t kv_get_has_destination(const kv_t *kv, int32_t pc); 372 373 /* 374 * This function returns destination Register row 375 */ 376 IGA_API int32_t kv_get_destination_register(const kv_t *kv, int32_t pc); 377 378 /* 379 * This function returns destination subRegister 380 */ 381 IGA_API int32_t kv_get_destination_sub_register(const kv_t *kv, int32_t pc); 382 383 /* 384 * This function returns destination data type 385 * i.e. F, HF, INT, etc 386 */ 387 IGA_API uint32_t kv_get_destination_data_type(const kv_t *kv, int32_t pc); 388 389 /* 390 * This function returns destination register type 391 * i.e. GRF, various ARF registers 392 */ 393 IGA_API uint32_t kv_get_destination_register_type(const kv_t *kv, int32_t pc); 394 395 /* 396 * This function returns destination register KIND 397 * DIRECT, INDIRECT, IMM, INDIR etc 398 */ 399 IGA_API uint32_t kv_get_destination_register_kind(const kv_t *kv, int32_t pc); 400 401 /* 402 * This function returns source register line number for a given source. 403 */ 404 IGA_API int32_t kv_get_source_register(const kv_t *kv, int32_t pc, uint32_t sourceNumber); 405 406 /* 407 * This function returns source subRegister for a given source. 408 */ 409 IGA_API int32_t kv_get_source_sub_register(const kv_t *kv, int32_t pc, uint32_t sourceNumber); 410 411 /* 412 * This function returns source data type for a given source 413 * i.e. F, HF, INT, etc 414 */ 415 IGA_API uint32_t kv_get_source_data_type(const kv_t *kv, int32_t pc, uint32_t sourceNumber); 416 417 /* 418 * This function returns source register type for a given source. 419 * i.e. GRF, various ARF registers 420 */ 421 IGA_API uint32_t kv_get_source_register_type(const kv_t *kv, int32_t pc, uint32_t sourceNumber); 422 423 /* 424 * This function returns source register KIND for a given source 425 * DIRECT, INDIRECT, IMM, INDIR etc 426 */ 427 IGA_API uint32_t kv_get_source_register_kind(const kv_t *kv, int32_t pc, uint32_t sourceNumber); 428 429 /* 430 * This function returns whether source is a vector. 431 */ 432 IGA_API int32_t kv_is_source_vector(const kv_t *kv, int32_t pc, uint32_t sourceNumber); 433 434 /* 435 * This function returns mask offset 436 */ 437 IGA_API uint32_t kv_get_channel_offset(const kv_t *kv, int32_t pc); 438 439 /* 440 * This function returns mask control 441 */ 442 IGA_API uint32_t kv_get_mask_control(const kv_t *kv, int32_t pc); 443 444 /* 445 * This function exposes destination region. 446 */ 447 IGA_API int32_t kv_get_destination_region( 448 const kv_t *kv, int32_t pc, uint32_t *hz); 449 450 /* 451 * This function exposes source operand region. 452 */ 453 IGA_API int32_t kv_get_source_region( 454 const kv_t *kv, int32_t pc, uint32_t src_op, 455 uint32_t *vt, uint32_t *wi, uint32_t *hz); 456 457 /* 458 * This function exposes source operand immediate value. 459 */ 460 IGA_API int32_t kv_get_source_immediate( 461 const kv_t *kv, int32_t pc, uint32_t src_op, uint64_t *imm); 462 463 /* 464 * This function exposes indirect source's immediate offset. 465 Return -1 if given source is not indirect srouce 466 */ 467 IGA_API int32_t kv_get_source_indirect_imm_off( 468 const kv_t *kv, int32_t pc, uint32_t src_op, int16_t *immoff); 469 470 /* 471 * This function exposes indirect destination's immediate offset. 472 Return -1 if given destination is not indirect srouce 473 */ 474 IGA_API int32_t kv_get_destination_indirect_imm_off( 475 const kv_t *kv, int32_t pc, int16_t *mme); 476 477 /* 478 * This function exposes source's MathMacroExt number for 479 math macro instructions. 480 mme is the mme numbar, set to 8 if it's nomme. 481 Return 0 if the given instruction is math macro instruction. 482 Return -1 if given instruction is not math macro instruction. 483 */ 484 IGA_API int32_t kv_get_source_mme_number( 485 const kv_t *kv, int32_t pc, uint32_t src_op, int16_t *mme); 486 487 /* 488 * This function exposes destination's MathMacroExt number for 489 math macro instructions. 490 mme is the mme numbar, set to 8 if it's nomme. 491 Return 0 if the given instruction is math macro instruction. 492 Return -1 if given instruction is not math macro instruction. 493 */ 494 IGA_API int32_t kv_get_destination_mme_number( 495 const kv_t *kv, int32_t pc, int16_t *immoff); 496 497 /* 498 * This function return flag modifier (FlagModifier) 499 */ 500 IGA_API uint32_t kv_get_flag_modifier(const kv_t *kv, int32_t pc); 501 502 /* 503 * This function return source modifier 504 * This returns a SrcModifier 505 */ 506 IGA_API uint32_t kv_get_source_modifier( 507 const kv_t *kv, int32_t pc, uint32_t src_op); 508 509 /* 510 * This function return destination modifier 511 * This returns a DstModifier 512 */ 513 IGA_API uint32_t kv_get_destination_modifier(const kv_t *kv, int32_t pc); 514 515 /* 516 * This function return the flag register 517 */ 518 IGA_API int32_t kv_get_flag_register(const kv_t *kv, int32_t pc); 519 520 /* 521 * This function return the flag sub register 522 */ 523 IGA_API int32_t kv_get_flag_sub_register(const kv_t *kv, int32_t pc); 524 525 /* 526 * This function return the flag predicate function (a PredCtrl) 527 */ 528 IGA_API uint32_t kv_get_predicate(const kv_t *kv, int32_t pc); 529 530 /* 531 * This function returns the logical sign on the predicate (inverted or not) 532 */ 533 IGA_API uint32_t kv_get_is_inverse_predicate(const kv_t *kv, int32_t pc); 534 535 536 537 #ifdef __cplusplus 538 } 539 #endif 540 #endif 541