Skip to contentSkip to conversation

PM4 packet streaming support (v2)

PATCH New Tom St Denis 1 participant 1 message May 20, 2018

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 PM4 packet streaming support (v2)

This adds the initial bits of PM4 stream decoding that can be used to achieve other debugging purposes. The first being tying ring data loosely to shader data when printing waves. Now the --waves command can print out information about the shader along with dumping the WAVE_STATUS registers.

(v2): Add ability to specify ring name and documentation

---
 doc/sphinx/source/libpm4_stream.rst | 102 +++++++++++++++
 doc/sphinx/source/libumr_api.rst    |   1 +
 doc/umr.1                           |   6 +-
 src/app/main.c                      |  12 +-
 src/app/print_waves.c               |  36 +++++-
 src/lib/CMakeLists.txt              |   1 +
 src/lib/umr_read_pm4_stream.c       | 244 ++++++++++++++++++++++++++++++++++++
 src/umr.h                           |  22 +++-
 8 files changed, 417 insertions(+), 7 deletions(-)
 create mode 100644 doc/sphinx/source/libpm4_stream.rst
 create mode 100644 src/lib/umr_read_pm4_stream.c
doc/sphinx/source/libpm4_stream.rst new file +102 -0
new file mode 100644
index 000000000000..790cb9ca831f
@@ -0,0 +1,102 @@
+===================
+PM4 Stream Decoding
+===================
+
+The UMR library has the ability to read rings into a linked list
+of PM4 packets with pointers to indirect buffers (IBs) and shaders.
+
+-----------------
+PM4 Decode a Ring
+-----------------
+
+To decode a ring into a stream the following function can be used:
+
+::
+
+	struct umr_pm4_stream *umr_pm4_decode_ring(struct umr_asic *asic, char *ringname);
+
+Which will decode the ring named by ringname and return a pointer to
+the following structure if successful:
+
+::
+
+	/* IB/ring decoding/dumping/etc */
+	struct umr_pm4_stream {
+		uint32_t
+			pkttype,	// packet type (0==simple write, 3 == packet)
+			pkt0off,	// base address for PKT0 writes
+			opcode,
+			n_words,	// number of words ignoring header
+			*words;		// words following header word
+
+		struct umr_pm4_stream
+				*next,	// adjacent PM4 packet if any
+				*ib;	// IB this packet might point to
+
+		struct umr_shaders_pgm *shader; // shader program if any
+	};
+
+Adjacent PM4 packets are pointed to by 'next' (NULL terminated) and
+any IBs or shaders that are found are pointed to by 'ib' and 'shader'
+respectively.
+
+-------------------
+PM4 Decode a Buffer
+-------------------
+
+To decode a PM4 stream inside a user buffer the following function
+can be used:
+
+::
+
+	struct umr_pm4_stream *umr_pm4_decode_stream(struct umr_asic *asic, int vmid, uint32_t *stream, uint32_t nwords);
+
+This will return a structure pointer if successful.
+
+--------------------
+Freeing a PM4 Stream
+--------------------
+
+A PM4 stream can be freed with the following function:
+
+::
+
+	void umr_free_pm4_stream(struct umr_pm4_stream *stream);
+
+------------------------------
+Finding Shaders in PM4 Streams
+------------------------------
+
+The WAVE_STATUS registers can indicate active waves and where in
+shaders they are but not information about the shaders themselves.
+The following functions can find shaders in PM4 streams:
+
+::
+
+	struct umr_shaders_pgm *umr_find_shader_in_stream(struct umr_pm4_stream *stream, unsigned vmid, uint64_t addr);
+	struct umr_shaders_pgm *umr_find_shader_in_ring(struct umr_asic *asic, char *ringname, unsigned vmid, uint64_t addr, int no_halt);
+
+If found they return a pointer to a shader structure which then
+indicates the base address, VMID, and size of the shader.  This
+function returns a copy of the shader structure from the PM4 stream
+structure which must be freed independently.  Calling umr_free_pm4_stream()
+will not free these copies.
+
+::
+
+	struct umr_shaders_pgm {
+		// VMID and length in bytes
+		uint32_t
+			vmid,
+			size;
+
+		// address in VM space for this shader
+		uint64_t addr;
+
+		struct umr_shaders_pgm *next;
+
+		struct {
+			uint64_t ib_base, ib_offset;
+		} src;
+	};
+
doc/sphinx/source/libumr_api.rst +1 -0
index 66877f87a3f9..f2a569f3042c 100644
@@ -13,3 +13,4 @@ libumrcore.a: API Documentation
    libvm_access
    libhalt_waves
    libwave_status
+   libpm4_stream
doc/umr.1 +4 -2
index a777d9312054..c163a7bcb3f0 100644
@@ -90,13 +90,15 @@ options that apply are:
 and
 .B use_pci
 .
-.IP "--waves, -wa"
+.IP "--waves, -wa <ring_name>"
 Print out information about any active CU waves.  Note that if GFX power gating
 is enabled this command may result in a GPU hang.  It's unlikely unless you're
 invoking it very rapidly.  Unlike the wave count reading in --top this command
 will operate regardless of whether GFX PG is enabled or not.  Can use
 .B bits
-to decode the wave bitfields.
+to decode the wave bitfields.  An optional ring name can be specified
+(default: gfx) to search for pointers to active shaders to find extra debugging
+information.
 
 .IP "--vm-decode, -vm vmid@<address> <num_of_pages>"
 Decode page mappings at a specified address (in hex) from the VMID specified.
src/app/main.c +10 -2
index d6571e77b74d..1710b2cdf4a9 100644
@@ -274,6 +274,12 @@ int main(int argc, char **argv)
 		} else if (!strcmp(argv[i], "--waves") || !strcmp(argv[i], "-wa")) {
 			if (!asic)
 				asic = get_asic();
+			if (i + 1 < argc) {
+				if (argv[i+1][0] != '-') {
+					strcpy(asic->options.ring_name, argv[i+1]);
+					++i;
+				}
+			}
 			umr_print_waves(asic);
 		} else if (!strcmp(argv[i], "--scan") || !strcmp(argv[i], "-s")) {
 			if (i + 1 < argc) {
@@ -573,9 +579,11 @@ int main(int argc, char **argv)
 	"\n\t\t'-O bits,follow,empty_log' to continually dump the trace log.)\n"
 "\n\t--top, -t\n\t\tSummarize GPU utilization.  Can select a SE block with --bank.  Can use"
 	"\n\t\toptions 'use_colour' to colourize output and 'use_pci' to improve efficiency.\n"
-"\n\t--waves, -wa\n\t\tPrint out information about any active CU waves.  Can use '-O bits'"
+"\n\t--waves, -wa <ring_name>\n\t\tPrint out information about any active CU waves.  Can use '-O bits'"
 	"\n\t\tto see decoding of various wave fields.  Can use the '-O halt_waves' option"
-	"\n\t\tto halt the SQ while reading registers.\n"
+	"\n\t\tto halt the SQ while reading registers.  An optional ring name can be specified"
+	"\n\t\twhich will then search a given ring for pointers to active shaders.  It will"
+	"\n\t\tdefault to the 'gfx' ring if nothing is specified.\n"
 "\n\t--vm-decode, -vm vmid@<address> <num_of_pages>"
 	"\n\t\tDecode page mappings at a specified address (in hex) from the VMID specified."
 	"\n\t\tThe VMID can be specified in hexadecimal (with leading '0x') or in decimal."
src/app/print_waves.c +34 -2
index 6965f7f31854..3847d69a3b8d 100644
@@ -41,10 +41,19 @@ void umr_print_waves(struct umr_asic *asic)
 	uint64_t pgm_addr;
 	struct umr_wave_data *wd, *owd;
 	int first = 1, col = 0;
+	struct umr_shaders_pgm *shader = NULL;
+	struct umr_pm4_stream *stream;
 
 	if (asic->options.halt_waves)
 		umr_sq_cmd_halt_waves(asic, UMR_SQ_CMD_HALT);
 
+	// scan a ring but don't trigger the halt/resume
+	// since it would have already been done
+	x = asic->options.halt_waves;
+	asic->options.halt_waves = 0;
+	stream = umr_pm4_decode_ring(asic, asic->options.ring_name[0] ? asic->options.ring_name : "gfx");
+	asic->options.halt_waves = x;
+
 	if (asic->family <= FAMILY_CIK)
 		shift = 3;  // on SI..CIK allocations were done in 8-dword blocks
 	else
@@ -220,8 +229,28 @@ void umr_print_waves(struct umr_asic *asic)
 				}
 			}
 
-			printf("\n\nPGM_MEM:\n");
-			pgm_addr = (((uint64_t)wd->ws.pc_hi << 32) | wd->ws.pc_lo) - (NUM_OPCODE_WORDS*4)/2;
+			printf("\n\nPGM_MEM:");
+			pgm_addr = (((uint64_t)wd->ws.pc_hi << 32) | wd->ws.pc_lo);
+			if (stream)
+				shader = umr_find_shader_in_stream(stream, wd->ws.hw_id.vm_id, pgm_addr);
+			if (shader) {
+				printf(" (found shader at: %s%u%s@0x%s%llx%s of %s%u%s bytes)\n",
+					BLUE, shader->vmid, RST,
+					YELLOW, (unsigned long long)shader->addr, RST,
+					BLUE, shader->size, RST);
+
+				// start decoding a bit before PC if possible
+				if (shader->addr + ((NUM_OPCODE_WORDS*4)/2) < pgm_addr)
+					pgm_addr -= (NUM_OPCODE_WORDS*4)/2;
+				else
+					pgm_addr = shader->addr;
+
+				free(shader);
+			} else {
+				pgm_addr -= (NUM_OPCODE_WORDS*4)/2;
+				printf("\n");
+			}
+
 			umr_vm_disasm(asic, wd->ws.hw_id.vm_id, pgm_addr, (((uint64_t)wd->ws.pc_hi << 32) | wd->ws.pc_lo), NUM_OPCODE_WORDS*4, NULL);
 
 			Hv("LDS_ALLOC", wd->ws.lds_alloc.value);
@@ -253,6 +282,9 @@ void umr_print_waves(struct umr_asic *asic)
 		wd = owd;
 	}
 
+	if (stream)
+		umr_free_pm4_stream(stream);
+
 	if (asic->options.halt_waves)
 		umr_sq_cmd_halt_waves(asic, UMR_SQ_CMD_RESUME);
 }
src/lib/CMakeLists.txt +1 -0
index 7a04540b58c8..3d4e376b1495 100644
@@ -28,6 +28,7 @@ add_library(umrcore STATIC
   umr_apply_bank_address.c
   umr_llvm_disasm.c
   umr_read_ring_data.c
+  umr_read_pm4_stream.c
   update.c
   version.c
   $<TARGET_OBJECTS:asic> $<TARGET_OBJECTS:ip>
src/lib/umr_read_pm4_stream.c new file +244 -0

244 lines not on this page · raw message

src/umr.h +21 -1
index 4c9f95e1b87b..326c13af694f 100644
@@ -213,7 +213,8 @@ struct umr_options {
 	char
 		*scanblock,
 		dev_name[32],
-		hub_name[32];
+		hub_name[32],
+		ring_name[32];
 	struct {
 		int domain,
 		    bus,
@@ -621,7 +622,26 @@ int umr_grbm_select_index(struct umr_asic *asic, uint32_t se, uint32_t sh, uint3
 int umr_sq_cmd_halt_waves(struct umr_asic *asic, enum umr_sq_cmd_halt_resume mode);
 
 /* IB/ring decoding/dumping/etc */
+struct umr_pm4_stream {
+	uint32_t pkttype,				// packet type (0==simple write, 3 == packet)
+			 pkt0off,				// base address for PKT0 writes
+			 opcode,
+			 n_words,				// number of words ignoring header
+			 *words;				// words following header word
+
+	struct umr_pm4_stream *next,	// adjacent PM4 packet if any
+						  *ib;		// IB this packet might point to
+
+	struct umr_shaders_pgm *shader; // shader program if any
+};
+
 void *umr_read_ring_data(struct umr_asic *asic, char *ringname, uint32_t *ringsize);
+struct umr_pm4_stream *umr_pm4_decode_ring(struct umr_asic *asic, char *ringname);
+struct umr_pm4_stream *umr_pm4_decode_stream(struct umr_asic *asic, int vmid, uint32_t *stream, uint32_t nwords);
+void umr_free_pm4_stream(struct umr_pm4_stream *stream);
+struct umr_shaders_pgm *umr_find_shader_in_stream(struct umr_pm4_stream *stream, unsigned vmid, uint64_t addr);
+struct umr_shaders_pgm *umr_find_shader_in_ring(struct umr_asic *asic, char *ringname, unsigned vmid, uint64_t addr, int no_halt);
+
 void umr_print_decode(struct umr_asic *asic, struct umr_ring_decoder *decoder, uint32_t ib);
 void umr_dump_ib(struct umr_asic *asic, struct umr_ring_decoder *decoder);
 void umr_dump_shaders(struct umr_asic *asic, struct umr_ring_decoder *decoder, struct umr_wave_data *wd);
Signature · 6 lines
2.14.3

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx