summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2013-09-11 09:06:48 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2013-09-11 09:06:48 +0200
commitbf09dc9587232ac7ed69a05bf725cfaeb7eeaa34 (patch)
treea90c4b2cdf67839540223c5ffe507df0117650aa
parentf688359ba004407d918177c149cbee3d9be7b209 (diff)
utils: move utilities such as viv_gpu_top to separate directory
Split them off from fb and replay, where they don't belong. Some of these are useful beyond reverse engineering. Also add a few utilities not part of etna_viv before: - viv_registers: print contents of all (non-crashing on read) GPU registers - viv_watch: watch debug registers
-rw-r--r--native/Makefile2
-rw-r--r--native/README.md2
-rw-r--r--native/fb/Makefile2
-rw-r--r--native/replay/Makefile2
-rw-r--r--native/replay/reset.c29
-rw-r--r--native/utils/.gitignore5
-rw-r--r--native/utils/Makefile40
-rw-r--r--native/utils/viv_gpu_top.c (renamed from native/fb/viv_gpu_top.c)0
-rw-r--r--native/utils/viv_info.c (renamed from native/replay/viv_info.c)0
-rw-r--r--native/utils/viv_registers.c86
-rw-r--r--native/utils/viv_reset.c56
-rw-r--r--native/utils/viv_watch.c172
12 files changed, 364 insertions, 32 deletions
diff --git a/native/Makefile b/native/Makefile
index 2c66f0f..4bcc7b2 100644
--- a/native/Makefile
+++ b/native/Makefile
@@ -2,7 +2,7 @@ TOP=.
include $(TOP)/Makefile.inc
-DIRS=gallium etnaviv driver fb fb_rawshader replay test2d
+DIRS=gallium etnaviv driver fb fb_rawshader replay test2d utils
# only needed for reverse engineering/dumping
# this needs a current EGL+OpenGL ES2 driver
diff --git a/native/README.md b/native/README.md
index 648ddef..134400e 100644
--- a/native/README.md
+++ b/native/README.md
@@ -25,3 +25,5 @@ Directory contents
- `test2d`: 2D engine tests
+- `util`: Various utilities for developing, debugging and profiling for Vivante GPUS
+
diff --git a/native/fb/Makefile b/native/fb/Makefile
index 050c325..b3e6afa 100644
--- a/native/fb/Makefile
+++ b/native/fb/Makefile
@@ -8,7 +8,7 @@ CXXFLAGS +=
LDFLAGS +=
TARGETS = rotate_cube alpha_blend cube_companion cubemap_sphere particle_system etna_gears stencil_test displacement mip_cube viv_profile ps_sandbox \
- viv_gpu_top downsample_test
+ downsample_test
COMPANION_OBJS = ../resources/companion_array.o ../resources/companion_mesh.o ../resources/companion_texture.o
ETNA_OBJS = ../lib/fbdemos.o ../lib/etna_bswap.o ../driver/libetnadriver.a ../gallium/libminigallium.a ../etnaviv/libetnaviv.a
diff --git a/native/replay/Makefile b/native/replay/Makefile
index 317e014..d3c5f4c 100644
--- a/native/replay/Makefile
+++ b/native/replay/Makefile
@@ -5,7 +5,7 @@ include $(TOP)/Makefile.inc
COMMON_FLAGS += -I$(TOP)/resources -I$(TOP)/driver
LDFLAGS_ETNA = $(LDFLAGS) -L$(TOP)/etnaviv -letnaviv
-TARGETS = reset viv_info
+TARGETS =
TARGETS_GC800 = cube cube_companion cube_etna ps_sandbox_etna etna_test cube_etna2
TARGETS_GC2000 = cube_etna2_gc2000 empty_screen_gc2000 cube_gc2000 cube_companion_gc2000 cube_etna_gc2000
COMPANION_OBJS = ../resources/companion_array.o ../resources/companion_mesh.o ../resources/companion_texture.o
diff --git a/native/replay/reset.c b/native/replay/reset.c
deleted file mode 100644
index 3b40fff..0000000
--- a/native/replay/reset.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Reset GPU, useful in case it hangs */
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <stdarg.h>
-
-#include "viv_raw.h"
-
-int main(int argc, char **argv)
-{
- int rv;
- struct viv_conn *conn = 0;
- rv = viv_open(VIV_HW_3D, &conn);
- if(rv!=0)
- {
- fprintf(stderr, "Error opening device\n");
- exit(1);
- }
- printf("Succesfully opened device, resetting\n");
- viv_reset(conn);
- viv_close(conn);
- return 0;
-}
-
diff --git a/native/utils/.gitignore b/native/utils/.gitignore
new file mode 100644
index 0000000..9b4cc5e
--- /dev/null
+++ b/native/utils/.gitignore
@@ -0,0 +1,5 @@
+viv_gpu_top
+viv_info
+viv_registers
+viv_reset
+viv_watch
diff --git a/native/utils/Makefile b/native/utils/Makefile
new file mode 100644
index 0000000..1ac3604
--- /dev/null
+++ b/native/utils/Makefile
@@ -0,0 +1,40 @@
+TOP=..
+
+include $(TOP)/Makefile.inc
+
+COMMON_FLAGS +=
+CFLAGS +=
+CXXFLAGS +=
+LDFLAGS +=
+
+ifeq ($(ETNAVIV_PROFILER), 1)
+# Define ETNAVIV_PROFILER=1 if the kernel was built with VIVANTE_PROFILER
+# enabled
+COMMON_FLAGS += -DVIVANTE_PROFILER=1
+endif
+
+TARGETS = viv_gpu_top viv_info viv_registers viv_reset viv_watch
+
+ETNA_OBJS = ../etnaviv/libetnaviv.a
+
+all: $(TARGETS)
+
+clean:
+ rm -f *.o ../lib/*.o ../resources/*.o
+ rm -f $(TARGETS)
+
+viv_gpu_top: viv_gpu_top.o $(ETNA_OBJS)
+ $(CXX) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+viv_info: viv_info.o $(ETNA_OBJS)
+ $(CXX) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+viv_registers: viv_registers.o $(ETNA_OBJS)
+ $(CXX) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+viv_reset: viv_reset.o $(ETNA_OBJS)
+ $(CXX) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+viv_watch: viv_watch.o $(ETNA_OBJS)
+ $(CXX) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
diff --git a/native/fb/viv_gpu_top.c b/native/utils/viv_gpu_top.c
index 97ee3a6..97ee3a6 100644
--- a/native/fb/viv_gpu_top.c
+++ b/native/utils/viv_gpu_top.c
diff --git a/native/replay/viv_info.c b/native/utils/viv_info.c
index 9f1cf37..9f1cf37 100644
--- a/native/replay/viv_info.c
+++ b/native/utils/viv_info.c
diff --git a/native/utils/viv_registers.c b/native/utils/viv_registers.c
new file mode 100644
index 0000000..2e295e9
--- /dev/null
+++ b/native/utils/viv_registers.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012-2013 Etnaviv Project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+/* Dump all reachable GPU registers */
+/*
+ * Important: Needs kernel module compiled with user space register access
+ * (gcdREGISTER_ACCESS_FROM_USER=1)
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <etnaviv/viv.h>
+#include "gc_hal_base.h"
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_abi.h"
+
+int main()
+{
+ struct viv_conn *conn = 0;
+ int rv = 0;
+ rv = viv_open(VIV_HW_3D, &conn);
+ if(rv!=0)
+ {
+ fprintf(stderr, "Error opening device\n");
+ exit(1);
+ }
+
+ gcsHAL_INTERFACE id = {};
+ memset((void*)&id, 0, sizeof(id));
+
+ // 0x000..0x200 ok
+ // 0x200..0x400 crash
+ // 0x400..0x800 ok
+ // 0x800..0xa00 crash
+ // 0xa00..0xc00 crash
+ // 0xc00..0xe00 crash
+ // 0xe00..0x1000 crash
+ // everything above that I've tested: crash
+ for(int address=0x000; address<0x800; address+=4)
+ {
+ if(address >= 0x200 && address < 0x400)
+ continue; /* reading causes CPU(!) crash */
+ id.command = gcvHAL_READ_REGISTER;
+ id.u.ReadRegisterData.address = address;
+ if(viv_invoke(conn, &id) != VIV_STATUS_OK)
+ {
+ perror("Ioctl error");
+ exit(1);
+ }
+ printf("%05x %08x\n", address, id.u.ReadRegisterData.data);
+ fflush(stdout);
+ }
+
+ viv_close(conn);
+ return 0;
+}
+
diff --git a/native/utils/viv_reset.c b/native/utils/viv_reset.c
new file mode 100644
index 0000000..0d7c6a2
--- /dev/null
+++ b/native/utils/viv_reset.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012-2013 Etnaviv Project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+/* Reset GPU, useful in case it hangs.
+ */
+/*
+ * Note: this is known to be unreliable with many kernel drivers and can bring
+ * the GPU in a state that can only be recovered with a device reboot.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <stdarg.h>
+
+#include <etnaviv/viv.h>
+
+int main(int argc, char **argv)
+{
+ int rv;
+ struct viv_conn *conn = 0;
+ rv = viv_open(VIV_HW_3D, &conn);
+ if(rv!=0)
+ {
+ fprintf(stderr, "Error opening device\n");
+ exit(1);
+ }
+ printf("Succesfully opened device, resetting\n");
+ viv_reset(conn);
+ viv_close(conn);
+ return 0;
+}
+
diff --git a/native/utils/viv_watch.c b/native/utils/viv_watch.c
new file mode 100644
index 0000000..9a12d39
--- /dev/null
+++ b/native/utils/viv_watch.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2012-2013 Etnaviv Project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+/* Watch GPU debug registers */
+/* Important: Needs kernel module compiled with user space register access
+ * (gcdREGISTER_ACCESS_FROM_USER=1) */
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <etnaviv/viv.h>
+#include "gc_hal_base.h"
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_abi.h"
+
+struct viv_conn *conn = 0;
+
+static const char clear_screen[] = {0x1b, '[', 'H',
+ 0x1b, '[', 'J',
+ 0x0};
+static const char color_num_zero[] = "\x1b[1;30m";
+static const char color_num[] = "\x1b[1;33m";
+static const char color_reset[] = "\x1b[0m";
+
+static void write_register(uint32_t address, uint32_t data)
+{
+ gcsHAL_INTERFACE id;
+ id.command = gcvHAL_WRITE_REGISTER;
+ id.u.WriteRegisterData.address = address;
+ id.u.WriteRegisterData.data = data;
+ if(viv_invoke(conn, &id) != VIV_STATUS_OK)
+ {
+ perror("Ioctl error");
+ exit(1);
+ }
+}
+
+static uint32_t read_register(uint32_t address)
+{
+ gcsHAL_INTERFACE id;
+ id.command = gcvHAL_READ_REGISTER;
+ id.u.ReadRegisterData.address = address;
+ if(viv_invoke(conn, &id) != VIV_STATUS_OK)
+ {
+ perror("Ioctl error");
+ exit(1);
+ }
+ return id.u.ReadRegisterData.data;
+}
+
+struct debug_register
+{
+ const char *module;
+ uint32_t select_reg;
+ uint32_t select_shift;
+ uint32_t read_reg;
+ uint32_t count;
+ uint32_t signature;
+};
+
+/* XXX possible to select/clear four debug registers at a time? this would
+ * avoid writes.
+ */
+static struct debug_register debug_registers[] =
+{
+ { "RA", 0x474, 16, 0x448, 16, 0x12344321 },
+ { "TX", 0x474, 24, 0x44C, 16, 0x12211221 },
+ { "FE", 0x470, 0, 0x450, 16, 0xBABEF00D },
+ { "PE", 0x470, 16, 0x454, 16, 0xBABEF00D },
+ { "DE", 0x470, 8, 0x458, 16, 0xBABEF00D },
+ { "SH", 0x470, 24, 0x45C, 16, 0xDEADBEEF },
+ { "PA", 0x474, 0, 0x460, 16, 0x0000AAAA },
+ { "SE", 0x474, 8, 0x464, 16, 0x5E5E5E5E },
+ { "MC", 0x478, 0, 0x468, 16, 0x12345678 },
+ { "HI", 0x478, 8, 0x46C, 16, 0xAAAAAAAA }
+};
+#define NUM_MODULES (sizeof(debug_registers) / sizeof(struct debug_register))
+#define MAX_COUNT 16
+
+int main()
+{
+ int rv = 0;
+ rv = viv_open(VIV_HW_3D, &conn);
+ if(rv!=0)
+ {
+ fprintf(stderr, "Error opening device\n");
+ exit(1);
+ }
+
+ uint32_t counters[NUM_MODULES][MAX_COUNT] = {{}};
+ uint32_t counters_prev[NUM_MODULES][MAX_COUNT] = {{}};
+ int interval = 1000000;
+ int reset = 0; /* reset counters after read */
+
+ int has_prev = 0;
+ while(true)
+ {
+ printf("%s", clear_screen);
+ for(unsigned int rid=0; rid<NUM_MODULES; ++rid)
+ {
+ struct debug_register *rdesc = &debug_registers[rid];
+ for(unsigned int sid=0; sid<15; ++sid)
+ {
+ write_register(rdesc->select_reg, sid << rdesc->select_shift);
+ counters[rid][sid] = read_register(rdesc->read_reg);
+ }
+ if(reset)
+ {
+ write_register(rdesc->select_reg, 15 << rdesc->select_shift);
+ counters[rid][15] = read_register(rdesc->read_reg);
+ }
+ write_register(debug_registers[rid].select_reg, 0 << rdesc->select_shift);
+ }
+
+ printf(" ");
+ for(unsigned int rid=0; rid<NUM_MODULES; ++rid)
+ {
+ printf("%-8s ", debug_registers[rid].module);
+ }
+ printf("\n");
+ for(unsigned int sid=0; sid<MAX_COUNT ; ++sid)
+ {
+ printf("%01x ", sid);
+ for(unsigned int rid=0; rid<NUM_MODULES; ++rid)
+ {
+ const char *color = "";
+ if(has_prev && counters[rid][sid] != counters_prev[rid][sid])
+ color = color_num;
+ printf("%s%08x%s ", color, counters[rid][sid], color_reset);
+ }
+ printf("\n");
+ }
+ usleep(interval);
+
+ for(unsigned int rid=0; rid<NUM_MODULES; ++rid)
+ for(unsigned int sid=0; sid<MAX_COUNT; ++sid)
+ counters_prev[rid][sid] = counters[rid][sid];
+ has_prev = 1;
+ }
+
+ viv_close(conn);
+ return 0;
+}
+