panwrap-syscall.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143
  1. /*
  2. * © Copyright 2017 The BiOpenly Community
  3. *
  4. * This program is free software and is provided to you under the terms of the
  5. * GNU General Public License version 2 as published by the Free Software
  6. * Foundation, and any use by you of this program is subject to the terms
  7. * of such GNU licence.
  8. *
  9. * A copy of the licence is included with the program, and can also be obtained
  10. * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  11. * Boston, MA 02110-1301, USA.
  12. *
  13. */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <stdbool.h>
  18. #include <sys/stat.h>
  19. #include <fcntl.h>
  20. #include <pthread.h>
  21. #include <linux/ioctl.h>
  22. #include <math.h>
  23. #include <sys/mman.h>
  24. #include <stdarg.h>
  25. #include <mali-ioctl.h>
  26. #include <list.h>
  27. #include "panwrap.h"
  28. static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER;
  29. #define LOCK() pthread_mutex_lock(&l)
  30. #define UNLOCK() pthread_mutex_unlock(&l)
  31. #define IOCTL_CASE(request) (_IOWR(_IOC_TYPE(request), _IOC_NR(request), \
  32. _IOC_SIZE(request)))
  33. struct ioctl_info {
  34. const char *name;
  35. };
  36. struct device_info {
  37. const char *name;
  38. const struct ioctl_info info[MALI_IOCTL_TYPE_COUNT][_IOC_NR(0xffffffff)];
  39. };
  40. struct allocated_memory {
  41. u64 gpu_va;
  42. bool same_va;
  43. struct list node;
  44. };
  45. struct mapped_memory {
  46. size_t length;
  47. void *addr;
  48. u64 gpu_va;
  49. struct list node;
  50. };
  51. typedef void* (mmap_func)(void *, size_t, int, int, int, loff_t);
  52. typedef int (open_func)(const char *, int flags, ...);
  53. #define IOCTL_TYPE(type) [type - MALI_IOCTL_TYPE_BASE] =
  54. #define IOCTL_INFO(n) [_IOC_NR(MALI_IOCTL_##n)] = { .name = #n }
  55. static struct device_info mali_info = {
  56. .name = "mali",
  57. .info = {
  58. IOCTL_TYPE(0x80) {
  59. IOCTL_INFO(GET_VERSION),
  60. },
  61. IOCTL_TYPE(0x82) {
  62. IOCTL_INFO(MEM_ALLOC),
  63. IOCTL_INFO(MEM_IMPORT),
  64. IOCTL_INFO(MEM_COMMIT),
  65. IOCTL_INFO(MEM_QUERY),
  66. IOCTL_INFO(MEM_FREE),
  67. IOCTL_INFO(MEM_FLAGS_CHANGE),
  68. IOCTL_INFO(MEM_ALIAS),
  69. IOCTL_INFO(SYNC),
  70. IOCTL_INFO(POST_TERM),
  71. IOCTL_INFO(HWCNT_SETUP),
  72. IOCTL_INFO(HWCNT_DUMP),
  73. IOCTL_INFO(HWCNT_CLEAR),
  74. IOCTL_INFO(GPU_PROPS_REG_DUMP),
  75. IOCTL_INFO(FIND_CPU_OFFSET),
  76. IOCTL_INFO(GET_VERSION_NEW),
  77. IOCTL_INFO(SET_FLAGS),
  78. IOCTL_INFO(SET_TEST_DATA),
  79. IOCTL_INFO(INJECT_ERROR),
  80. IOCTL_INFO(MODEL_CONTROL),
  81. IOCTL_INFO(KEEP_GPU_POWERED),
  82. IOCTL_INFO(FENCE_VALIDATE),
  83. IOCTL_INFO(STREAM_CREATE),
  84. IOCTL_INFO(GET_PROFILING_CONTROLS),
  85. IOCTL_INFO(SET_PROFILING_CONTROLS),
  86. IOCTL_INFO(DEBUGFS_MEM_PROFILE_ADD),
  87. IOCTL_INFO(JOB_SUBMIT),
  88. IOCTL_INFO(DISJOINT_QUERY),
  89. IOCTL_INFO(GET_CONTEXT_ID),
  90. IOCTL_INFO(TLSTREAM_ACQUIRE_V10_4),
  91. IOCTL_INFO(TLSTREAM_TEST),
  92. IOCTL_INFO(TLSTREAM_STATS),
  93. IOCTL_INFO(TLSTREAM_FLUSH),
  94. IOCTL_INFO(HWCNT_READER_SETUP),
  95. IOCTL_INFO(SET_PRFCNT_VALUES),
  96. IOCTL_INFO(SOFT_EVENT_UPDATE),
  97. IOCTL_INFO(MEM_JIT_INIT),
  98. IOCTL_INFO(TLSTREAM_ACQUIRE),
  99. },
  100. },
  101. };
  102. #undef IOCTL_INFO
  103. #undef IOCTL_TYPE
  104. static inline const struct ioctl_info *
  105. ioctl_get_info(unsigned long int request)
  106. {
  107. return &mali_info.info[_IOC_TYPE(request) - MALI_IOCTL_TYPE_BASE]
  108. [_IOC_NR(request)];
  109. }
  110. static int mali_fd = 0;
  111. static LIST_HEAD(allocations);
  112. static LIST_HEAD(mmaps);
  113. extern FILE *ioctl_fp;
  114. #define FLAG_INFO(flag) { MALI_MEM_##flag, #flag }
  115. static const struct panwrap_flag_info mem_flag_info[] = {
  116. FLAG_INFO(PROT_CPU_RD),
  117. FLAG_INFO(PROT_CPU_WR),
  118. FLAG_INFO(PROT_GPU_RD),
  119. FLAG_INFO(PROT_GPU_WR),
  120. FLAG_INFO(PROT_GPU_EX),
  121. FLAG_INFO(GROW_ON_GPF),
  122. FLAG_INFO(COHERENT_SYSTEM),
  123. FLAG_INFO(COHERENT_LOCAL),
  124. FLAG_INFO(CACHED_CPU),
  125. FLAG_INFO(SAME_VA),
  126. FLAG_INFO(NEED_MMAP),
  127. FLAG_INFO(COHERENT_SYSTEM_REQUIRED),
  128. FLAG_INFO(SECURE),
  129. FLAG_INFO(DONT_NEED),
  130. FLAG_INFO(IMPORT_SHARED),
  131. {}
  132. };
  133. #undef FLAG_INFO
  134. #define FLAG_INFO(flag) { MALI_JD_REQ_##flag, #flag }
  135. static const struct panwrap_flag_info jd_req_flag_info[] = {
  136. FLAG_INFO(FS),
  137. FLAG_INFO(CS),
  138. FLAG_INFO(T),
  139. FLAG_INFO(CF),
  140. FLAG_INFO(V),
  141. FLAG_INFO(FS_AFBC),
  142. FLAG_INFO(EVENT_COALESCE),
  143. FLAG_INFO(COHERENT_GROUP),
  144. FLAG_INFO(PERMON),
  145. FLAG_INFO(EXTERNAL_RESOURCES),
  146. FLAG_INFO(ONLY_COMPUTE),
  147. FLAG_INFO(SPECIFIC_COHERENT_GROUP),
  148. FLAG_INFO(EVENT_ONLY_ON_FAILURE),
  149. FLAG_INFO(EVENT_NEVER),
  150. FLAG_INFO(SKIP_CACHE_START),
  151. FLAG_INFO(SKIP_CACHE_END),
  152. {}
  153. };
  154. #undef FLAG_INFO
  155. #define FLAG_INFO(flag) { flag, #flag }
  156. static const struct panwrap_flag_info mmap_prot_flag_info[] = {
  157. FLAG_INFO(PROT_EXEC),
  158. FLAG_INFO(PROT_READ),
  159. FLAG_INFO(PROT_WRITE),
  160. {}
  161. };
  162. /* Fix issue building for Linux */
  163. #ifndef MAP_UNINITIALIZED
  164. #define MAP_UNINITIALIZED 0xDEADBEEF
  165. #endif
  166. static const struct panwrap_flag_info mmap_flags_flag_info[] = {
  167. FLAG_INFO(MAP_SHARED),
  168. FLAG_INFO(MAP_PRIVATE),
  169. FLAG_INFO(MAP_ANONYMOUS),
  170. FLAG_INFO(MAP_DENYWRITE),
  171. FLAG_INFO(MAP_FIXED),
  172. FLAG_INFO(MAP_GROWSDOWN),
  173. FLAG_INFO(MAP_HUGETLB),
  174. FLAG_INFO(MAP_LOCKED),
  175. FLAG_INFO(MAP_NONBLOCK),
  176. FLAG_INFO(MAP_NORESERVE),
  177. FLAG_INFO(MAP_POPULATE),
  178. FLAG_INFO(MAP_STACK),
  179. FLAG_INFO(MAP_UNINITIALIZED),
  180. {}
  181. };
  182. static const struct panwrap_flag_info external_resources_access_flag_info[] = {
  183. FLAG_INFO(MALI_EXT_RES_ACCESS_SHARED),
  184. FLAG_INFO(MALI_EXT_RES_ACCESS_EXCLUSIVE),
  185. {}
  186. };
  187. static const struct panwrap_flag_info mali_jd_dep_type_flag_info[] = {
  188. FLAG_INFO(MALI_JD_DEP_TYPE_DATA),
  189. FLAG_INFO(MALI_JD_DEP_TYPE_ORDER),
  190. {}
  191. };
  192. #undef FLAG_INFO
  193. static struct mapped_memory *find_mapped_mem(void *addr)
  194. {
  195. struct mapped_memory *pos = NULL;
  196. list_for_each_entry(pos, &mmaps, node) {
  197. if (pos->addr == addr)
  198. return pos;
  199. }
  200. return NULL;
  201. }
  202. static struct mapped_memory *find_gpu_mapped_mem(uint64_t addr)
  203. {
  204. struct mapped_memory *pos = NULL;
  205. list_for_each_entry(pos, &mmaps, node) {
  206. printf("Candidate (%llx, %llx) for %llx\n", pos->gpu_va, pos->gpu_va + pos->length, addr);
  207. if (addr >= pos->gpu_va && addr <= pos->gpu_va + pos->length)
  208. return pos;
  209. }
  210. return NULL;
  211. }
  212. void *fetch_mapped_gpu(u64 gpu_addr, size_t sz)
  213. {
  214. if (!gpu_addr) {
  215. panwrap_log("Tried to dereference GPU null!\n");
  216. return NULL;
  217. }
  218. struct mapped_memory *mem = find_gpu_mapped_mem(gpu_addr);
  219. if (!mem) {
  220. panwrap_log("Unmapped GPU mem %llx\n", gpu_addr);
  221. return NULL;
  222. }
  223. /* Sanity bounds check */
  224. if (gpu_addr - mem->gpu_va + sz > mem->length) {
  225. panwrap_log("GPU memory overflow @ %llX\n", gpu_addr);
  226. return NULL;
  227. }
  228. return mem->addr + (gpu_addr - mem->gpu_va);
  229. }
  230. static inline const char *
  231. ioctl_decode_coherency_mode(enum mali_ioctl_coherency_mode mode)
  232. {
  233. switch (mode) {
  234. case COHERENCY_ACE_LITE: return "ACE_LITE";
  235. case COHERENCY_ACE: return "ACE";
  236. case COHERENCY_NONE: return "None";
  237. default: return "???";
  238. }
  239. }
  240. static inline const char *
  241. ioctl_decode_jd_prio(mali_jd_prio prio)
  242. {
  243. switch (prio) {
  244. case MALI_JD_PRIO_LOW: return "Low";
  245. case MALI_JD_PRIO_MEDIUM: return "Medium";
  246. case MALI_JD_PRIO_HIGH: return "High";
  247. default: return "???";
  248. }
  249. }
  250. /*
  251. * Decodes the jd_core_req flags and their real meanings
  252. * See mali_kbase_jd.c
  253. */
  254. static inline const char *
  255. ioctl_get_job_type_from_jd_core_req(mali_jd_core_req req)
  256. {
  257. if (req & MALI_JD_REQ_SOFT_JOB)
  258. return "Soft job";
  259. if (req & MALI_JD_REQ_ONLY_COMPUTE)
  260. return "Compute Shader Job";
  261. switch (req & (MALI_JD_REQ_FS | MALI_JD_REQ_CS | MALI_JD_REQ_T)) {
  262. case MALI_JD_REQ_DEP:
  263. return "Dependency only job";
  264. case MALI_JD_REQ_FS:
  265. return "Fragment shader job";
  266. case MALI_JD_REQ_CS:
  267. return "Vertex/Geometry shader job";
  268. case MALI_JD_REQ_T:
  269. return "Tiler job";
  270. case (MALI_JD_REQ_FS | MALI_JD_REQ_CS):
  271. return "Fragment shader + vertex/geometry shader job";
  272. case (MALI_JD_REQ_FS | MALI_JD_REQ_T):
  273. return "Fragment shader + tiler job";
  274. case (MALI_JD_REQ_CS | MALI_JD_REQ_T):
  275. return "Vertex/geometry shader job + tiler job";
  276. case (MALI_JD_REQ_FS | MALI_JD_REQ_CS | MALI_JD_REQ_T):
  277. return "Fragment shader + vertex/geometry shader job + tiler job";
  278. }
  279. return "???";
  280. }
  281. #define SOFT_FLAG(flag) \
  282. case MALI_JD_REQ_SOFT_##flag: \
  283. panwrap_log_cont("%s)", "SOFT_" #flag); \
  284. break
  285. /* Decodes the actual jd_core_req flags, but not their meanings */
  286. static inline void
  287. ioctl_log_decoded_jd_core_req(mali_jd_core_req req)
  288. {
  289. if (req & MALI_JD_REQ_SOFT_JOB) {
  290. panwrap_log_cont("0x%010x (", req);
  291. switch (req) {
  292. SOFT_FLAG(DUMP_CPU_GPU_TIME);
  293. SOFT_FLAG(FENCE_TRIGGER);
  294. SOFT_FLAG(FENCE_WAIT);
  295. SOFT_FLAG(REPLAY);
  296. SOFT_FLAG(EVENT_WAIT);
  297. SOFT_FLAG(EVENT_SET);
  298. SOFT_FLAG(EVENT_RESET);
  299. SOFT_FLAG(DEBUG_COPY);
  300. SOFT_FLAG(JIT_ALLOC);
  301. SOFT_FLAG(JIT_FREE);
  302. SOFT_FLAG(EXT_RES_MAP);
  303. SOFT_FLAG(EXT_RES_UNMAP);
  304. default: panwrap_log_cont("???" ")"); break;
  305. }
  306. } else {
  307. panwrap_log_decoded_flags(jd_req_flag_info, req);
  308. }
  309. }
  310. #undef SOFT_FLAG
  311. static void
  312. ioctl_decode_pre_mem_alloc(unsigned long int request, void *ptr)
  313. {
  314. const struct mali_ioctl_mem_alloc *args = ptr;
  315. panwrap_log("\tva_pages = %lld\n", args->va_pages);
  316. panwrap_log("\tcommit_pages = %lld\n", args->commit_pages);
  317. panwrap_log("\textent = 0x%llx\n", args->extent);
  318. panwrap_log("\tflags = ");
  319. panwrap_log_decoded_flags(mem_flag_info, args->flags);
  320. panwrap_log_cont("\n");
  321. }
  322. static void
  323. ioctl_decode_pre_mem_import(unsigned long int request, void *ptr)
  324. {
  325. const struct mali_ioctl_mem_import *args = ptr;
  326. const char *type;
  327. switch (args->type) {
  328. case MALI_MEM_IMPORT_TYPE_UMP: type = "UMP"; break;
  329. case MALI_MEM_IMPORT_TYPE_UMM: type = "UMM"; break;
  330. case MALI_MEM_IMPORT_TYPE_USER_BUFFER: type = "User buffer"; break;
  331. default: type = "Invalid"; break;
  332. }
  333. panwrap_log("\tphandle = 0x%llx\n", args->phandle);
  334. panwrap_log("\ttype = %d (%s)\n", args->type, type);
  335. panwrap_log("\tflags = ");
  336. panwrap_log_decoded_flags(mem_flag_info, args->flags);
  337. panwrap_log_cont("\n");
  338. }
  339. static void
  340. ioctl_decode_pre_mem_commit(unsigned long int request, void *ptr)
  341. {
  342. const struct mali_ioctl_mem_commit *args = ptr;
  343. panwrap_log("\tgpu_addr = 0x%llx\n", args->gpu_addr);
  344. panwrap_log("\tpages = %lld\n", args->pages);
  345. }
  346. static void
  347. ioctl_decode_pre_mem_query(unsigned long int request, void *ptr)
  348. {
  349. const struct mali_ioctl_mem_query *args = ptr;
  350. char *query_name;
  351. switch (args->query) {
  352. case MALI_MEM_QUERY_COMMIT_SIZE: query_name = "Commit size"; break;
  353. case MALI_MEM_QUERY_VA_SIZE: query_name = "VA size"; break;
  354. case MALI_MEM_QUERY_FLAGS: query_name = "Flags"; break;
  355. default: query_name = "???"; break;
  356. }
  357. panwrap_log("\tgpu_addr = 0x%llx\n", args->gpu_addr);
  358. panwrap_log("\tquery = %d (%s)\n", args->query, query_name);
  359. }
  360. static void
  361. ioctl_decode_pre_mem_free(unsigned long int request, void *ptr)
  362. {
  363. const struct mali_ioctl_mem_free *args = ptr;
  364. panwrap_log("\tgpu_addr = 0x%llx\n", args->gpu_addr);
  365. }
  366. static void
  367. ioctl_decode_pre_mem_flags_change(unsigned long int request, void *ptr)
  368. {
  369. const struct mali_ioctl_mem_flags_change *args = ptr;
  370. panwrap_log("\tgpu_va = 0x%llx\n", args->gpu_va);
  371. panwrap_log("\tflags = ");
  372. panwrap_log_decoded_flags(mem_flag_info, args->flags);
  373. panwrap_log_cont("\n");
  374. panwrap_log("\tmask = 0x%llx\n", args->mask);
  375. }
  376. static void
  377. ioctl_decode_pre_mem_alias(unsigned long int request, void *ptr)
  378. {
  379. const struct mali_ioctl_mem_alias *args = ptr;
  380. panwrap_log("\tflags = ");
  381. panwrap_log_decoded_flags(mem_flag_info, args->flags);
  382. panwrap_log_cont("\n");
  383. panwrap_log("\tstride = %lld\n", args->stride);
  384. panwrap_log("\tnents = %lld\n", args->nents);
  385. panwrap_log("\tai = 0x%llx\n", args->ai);
  386. }
  387. static inline void
  388. ioctl_decode_pre_sync(unsigned long int request, void *ptr)
  389. {
  390. const struct mali_ioctl_sync *args = ptr;
  391. const char *type;
  392. struct mapped_memory *mem = find_mapped_mem((void*) (uintptr_t) args->handle);
  393. switch (args->type) {
  394. case MALI_SYNC_TO_DEVICE: type = "device <- CPU"; break;
  395. case MALI_SYNC_TO_CPU: type = "device -> CPU"; break;
  396. default: type = "???"; break;
  397. }
  398. if (mem) {
  399. panwrap_log("\thandle = %p (end=%p, len=%zu)\n",
  400. (void*) (uintptr_t) args->handle,
  401. (void*) (uintptr_t) args->handle + mem->length,
  402. mem->length);
  403. panwrap_log("\tuser_addr = %p - %p (offset=%llu)\n",
  404. args->user_addr, args->user_addr + args->size,
  405. (u64) (uintptr_t) args->user_addr - (u64) (uintptr_t) args->handle);
  406. } else {
  407. panwrap_log("\tERROR! Unknown handle specified\n");
  408. panwrap_log("\thandle = 0x%p\n", (void*) (uintptr_t) args->handle);
  409. panwrap_log("\tuser_addr = %p - %p\n",
  410. args->user_addr, args->user_addr + args->size);
  411. }
  412. panwrap_log("\tsize = %lld\n", args->size);
  413. panwrap_log("\ttype = %d (%s)\n", args->type, type);
  414. if (args->type == MALI_SYNC_TO_DEVICE) {
  415. panwrap_log("\tDumping memory being synced to device:\n");
  416. panwrap_log_hexdump(args->user_addr, args->size, "\t\t");
  417. }
  418. }
  419. static void
  420. ioctl_decode_pre_set_flags(unsigned long int request, void *ptr)
  421. {
  422. const struct mali_ioctl_set_flags *args = ptr;
  423. panwrap_log("\tcreate_flags = %08x\n", args->create_flags);
  424. }
  425. static inline void
  426. ioctl_decode_pre_stream_create(unsigned long int request, void *ptr)
  427. {
  428. const struct mali_ioctl_stream_create *args = ptr;
  429. panwrap_log("\tname = %s\n", args->name);
  430. }
  431. struct mapped_dump {
  432. u64 gpu_va;
  433. u64 length;
  434. /* Followed by buffer itself */
  435. };
  436. static void
  437. dump_mapped_memory() {
  438. /* Anything that is mapped? Dump it to a file.
  439. * Should be called once at the end of a frame in a single-frame
  440. * render.
  441. * Useful for replay, offline decode, etc.
  442. */
  443. FILE *fp = fopen("memory-dump.bin", "wb");
  444. struct mapped_memory *pos = NULL;
  445. list_for_each_entry(pos, &mmaps, node) {
  446. struct mapped_dump dump = {
  447. .gpu_va = pos->gpu_va,
  448. .length = pos->length
  449. };
  450. /* We don't care about endianness, LE everywhere */
  451. if (pos->addr && pos->gpu_va) {
  452. fwrite(&dump, 1, sizeof(dump), fp);
  453. if (pos->length) {
  454. fwrite(pos->addr, 1, pos->length, fp);
  455. }
  456. } else {
  457. printf("Warning, NULL mmap skipped in dump\n");
  458. }
  459. }
  460. fclose(fp);
  461. }
  462. /* TODO: Decode offline */
  463. #define __PANWRAP
  464. #include <pantrace.h>
  465. static inline void
  466. ioctl_decode_pre_job_submit(unsigned long int request, void *ptr)
  467. {
  468. const struct mali_ioctl_job_submit *args = ptr;
  469. const struct mali_jd_atom_v2 *atoms = args->addr;
  470. panwrap_log("\taddr = %p\n", args->addr);
  471. panwrap_log("\tnr_atoms = %d\n", args->nr_atoms);
  472. panwrap_log("\tstride = %d\n", args->stride);
  473. /* The stride should be equivalent to the length of the structure,
  474. * if it isn't then it's possible we're somehow tracing one of the
  475. * legacy job formats
  476. */
  477. if (args->stride != sizeof(*atoms)) {
  478. panwrap_log("\tSIZE MISMATCH (stride should be %zd, was %d)\n",
  479. sizeof(*atoms), args->stride);
  480. panwrap_log("\tCannot dump atoms :(, maybe it's a legacy job format?\n");
  481. return;
  482. }
  483. panwrap_log("\tAtoms:\n");
  484. for (unsigned int i = 0; i < args->nr_atoms; i++) {
  485. const struct mali_jd_atom_v2 *a = &atoms[i];
  486. uint64_t core_req;
  487. panwrap_log("\t\tudata = [0x%llx, 0x%llx]\n",
  488. a->udata.blob[0], a->udata.blob[1]);
  489. panwrap_log("\t\tnr_ext_res = %d\n", a->nr_ext_res);
  490. if (a->ext_res_list) {
  491. panwrap_log("\t\text_res_list.count = %lld\n",
  492. a->ext_res_list->count);
  493. panwrap_log("\t\tExternal resources:\n");
  494. for (unsigned int j = 0; j < a->nr_ext_res; j++)
  495. {
  496. panwrap_log("\t\t\t");
  497. panwrap_log_decoded_flags(
  498. external_resources_access_flag_info,
  499. a->ext_res_list[j].ext_resource[0]);
  500. panwrap_log_cont("\n");
  501. }
  502. } else {
  503. panwrap_log("\t\t<no external resources>\n");
  504. }
  505. core_req = a->core_req | a->compat_core_req;
  506. panwrap_log("\t\tcompat_core_req = 0x%x\n", a->compat_core_req);
  507. panwrap_log("\t\tcore_req = 0x%x\n", a->core_req);
  508. panwrap_log("\t\tPre-dependencies:\n");
  509. for (unsigned int j = 0; j < ARRAY_SIZE(a->pre_dep); j++) {
  510. panwrap_log("\t\t\tatom_id = %d flags == ",
  511. a->pre_dep[i].atom_id);
  512. panwrap_log_decoded_flags(
  513. mali_jd_dep_type_flag_info,
  514. a->pre_dep[i].dependency_type);
  515. panwrap_log_cont("\n");
  516. }
  517. panwrap_log("\t\tatom_number = %d\n", a->atom_number);
  518. panwrap_log("\t\tprio = %d (%s)\n",
  519. a->prio, ioctl_decode_jd_prio(a->prio));
  520. panwrap_log("\t\tdevice_nr = %d\n", a->device_nr);
  521. panwrap_log("\t\tJob type = %s\n",
  522. ioctl_get_job_type_from_jd_core_req(core_req));
  523. panwrap_log("\t\tdecoded_core_req = ");
  524. ioctl_log_decoded_jd_core_req(core_req);
  525. panwrap_log_cont("\n");
  526. dump_mapped_memory();
  527. fflush(ioctl_fp);
  528. chai_trace_atom(a);
  529. }
  530. }
  531. static void
  532. ioctl_decode_pre(unsigned long int request, void *ptr)
  533. {
  534. switch (IOCTL_CASE(request)) {
  535. case IOCTL_CASE(MALI_IOCTL_MEM_ALLOC):
  536. ioctl_decode_pre_mem_alloc(request, ptr);
  537. break;
  538. case IOCTL_CASE(MALI_IOCTL_MEM_IMPORT):
  539. ioctl_decode_pre_mem_import(request, ptr);
  540. break;
  541. case IOCTL_CASE(MALI_IOCTL_MEM_COMMIT):
  542. ioctl_decode_pre_mem_commit(request, ptr);
  543. break;
  544. case IOCTL_CASE(MALI_IOCTL_MEM_QUERY):
  545. ioctl_decode_pre_mem_query(request, ptr);
  546. break;
  547. case IOCTL_CASE(MALI_IOCTL_MEM_FREE):
  548. ioctl_decode_pre_mem_free(request, ptr);
  549. break;
  550. case IOCTL_CASE(MALI_IOCTL_MEM_FLAGS_CHANGE):
  551. ioctl_decode_pre_mem_flags_change(request, ptr);
  552. break;
  553. case IOCTL_CASE(MALI_IOCTL_MEM_ALIAS):
  554. ioctl_decode_pre_mem_alias(request, ptr);
  555. break;
  556. case IOCTL_CASE(MALI_IOCTL_SYNC):
  557. ioctl_decode_pre_sync(request, ptr);
  558. break;
  559. case IOCTL_CASE(MALI_IOCTL_SET_FLAGS):
  560. ioctl_decode_pre_set_flags(request, ptr);
  561. break;
  562. case IOCTL_CASE(MALI_IOCTL_STREAM_CREATE):
  563. ioctl_decode_pre_stream_create(request, ptr);
  564. break;
  565. case IOCTL_CASE(MALI_IOCTL_JOB_SUBMIT):
  566. ioctl_decode_pre_job_submit(request, ptr);
  567. break;
  568. default:
  569. break;
  570. }
  571. }
  572. static void
  573. ioctl_decode_post_get_version(unsigned long int request, void *ptr)
  574. {
  575. const struct mali_ioctl_get_version *args = ptr;
  576. panwrap_log("\tmajor = %3d\n", args->major);
  577. panwrap_log("\tminor = %3d\n", args->minor);
  578. }
  579. static void
  580. ioctl_decode_post_mem_alloc(unsigned long int request, void *ptr)
  581. {
  582. const struct mali_ioctl_mem_alloc *args = ptr;
  583. struct allocated_memory *new = malloc(sizeof(*new));
  584. panwrap_log("\tgpu_va = 0x%llx\n", args->gpu_va);
  585. panwrap_log("\tva_alignment = %d\n", args->va_alignment);
  586. panwrap_log("\tflags = %llx", args->flags);
  587. new->gpu_va = args->gpu_va;
  588. new->same_va = args->flags & MALI_MEM_SAME_VA;
  589. list_add(&new->node, &allocations);
  590. panwrap_log_cont("\n");
  591. }
  592. static void
  593. ioctl_decode_post_mem_import(unsigned long int request, void *ptr)
  594. {
  595. const struct mali_ioctl_mem_import *args = ptr;
  596. panwrap_log("\tgpu_va = 0x%llx\n", args->gpu_va);
  597. panwrap_log("\tva_pages = %lld\n", args->va_pages);
  598. panwrap_log("\tflags = ");
  599. panwrap_log_decoded_flags(mem_flag_info, args->flags);
  600. panwrap_log_cont("\n");
  601. }
  602. static void
  603. ioctl_decode_post_mem_commit(unsigned long int request, void *ptr)
  604. {
  605. const struct mali_ioctl_mem_commit *args = ptr;
  606. panwrap_log("\tresult_subcode = %d\n", args->result_subcode);
  607. struct allocated_memory *new = malloc(sizeof(*new));
  608. new->gpu_va = args->gpu_addr;
  609. new->same_va = false;
  610. list_add(&new->node, &allocations);
  611. }
  612. static void
  613. ioctl_decode_post_mem_query(unsigned long int request, void *ptr)
  614. {
  615. const struct mali_ioctl_mem_query *args = ptr;
  616. panwrap_log("\tvalue = 0x%llx\n", args->value);
  617. }
  618. static void
  619. ioctl_decode_post_mem_alias(unsigned long int request, void *ptr)
  620. {
  621. const struct mali_ioctl_mem_alias *args = ptr;
  622. panwrap_log("\tgpu_va = 0x%llx\n", args->gpu_va);
  623. panwrap_log("\tva_pages = %lld\n", args->va_pages);
  624. }
  625. static inline void
  626. ioctl_decode_post_sync(unsigned long int request, void *ptr)
  627. {
  628. const struct mali_ioctl_sync *args = ptr;
  629. if (args->type != MALI_SYNC_TO_CPU)
  630. return;
  631. panwrap_log("\tDumping memory from device:\n");
  632. panwrap_log_hexdump(args->user_addr, args->size, "\t\t");
  633. }
  634. static void
  635. ioctl_decode_post_gpu_props_reg_dump(unsigned long int request, void *ptr)
  636. {
  637. const struct mali_ioctl_gpu_props_reg_dump *args = ptr;
  638. const char *implementation;
  639. switch (args->thread.impl_tech) {
  640. case MALI_GPU_IMPLEMENTATION_UNKNOWN: implementation = "Unknown"; break;
  641. case MALI_GPU_IMPLEMENTATION_SILICON: implementation = "Silicon"; break;
  642. case MALI_GPU_IMPLEMENTATION_FPGA: implementation = "FPGA"; break;
  643. case MALI_GPU_IMPLEMENTATION_SW: implementation = "Software"; break;
  644. }
  645. panwrap_log("\tcore:\n");
  646. panwrap_log("\t\tProduct ID: %d\n", args->core.product_id);
  647. panwrap_log("\t\tVersion status: %d\n", args->core.version_status);
  648. panwrap_log("\t\tMinor revision: %d\n", args->core.minor_revision);
  649. panwrap_log("\t\tMajor revision: %d\n", args->core.major_revision);
  650. panwrap_log("\t\tGPU speed (?): %dMHz\n", args->core.gpu_speed_mhz);
  651. panwrap_log("\t\tGPU frequencies (?): %dKHz-%dKHz\n",
  652. args->core.gpu_freq_khz_min, args->core.gpu_freq_khz_max);
  653. panwrap_log("\t\tShader program counter size: %.lf MB\n",
  654. pow(2, args->core.log2_program_counter_size) / 1024 / 1024);
  655. panwrap_log("\t\tTexture features:\n");
  656. for (unsigned int i = 0; i < ARRAY_SIZE(args->core.texture_features); i++)
  657. panwrap_log("\t\t\t%010x\n", args->core.texture_features[i]);
  658. panwrap_log("\t\tAvailable memory: %lld bytes\n",
  659. args->core.gpu_available_memory_size);
  660. panwrap_log("\tL2 cache:\n");
  661. panwrap_log("\t\tLine size: %.lf (bytes, words?)\n",
  662. pow(2, args->l2.log2_line_size));
  663. panwrap_log("\t\tCache size: %.lf KB\n",
  664. pow(2, args->l2.log2_cache_size) / 1024);
  665. panwrap_log("\t\tL2 slice count: %d\n", args->l2.num_l2_slices);
  666. panwrap_log("\tTiler:\n");
  667. panwrap_log("\t\tBinary size: %d bytes\n",
  668. args->tiler.bin_size_bytes);
  669. panwrap_log("\t\tMax active levels: %d\n",
  670. args->tiler.max_active_levels);
  671. panwrap_log("\tThreads:\n");
  672. panwrap_log("\t\tMax threads: %d\n", args->thread.max_threads);
  673. panwrap_log("\t\tMax threads per workgroup: %d\n",
  674. args->thread.max_workgroup_size);
  675. panwrap_log("\t\tMax threads allowed for synchronizing on simple barrier: %d\n",
  676. args->thread.max_barrier_size);
  677. panwrap_log("\t\tMax registers available per-core: %d\n",
  678. args->thread.max_registers);
  679. panwrap_log("\t\tMax tasks that can be sent to a core before blocking: %d\n",
  680. args->thread.max_task_queue);
  681. panwrap_log("\t\tMax allowed thread group split value: %d\n",
  682. args->thread.max_thread_group_split);
  683. panwrap_log("\t\tImplementation type: %d (%s)\n",
  684. args->thread.impl_tech, implementation);
  685. panwrap_log("\tRaw props:\n");
  686. panwrap_log("\t\tShader present? %s\n", YES_NO(args->raw.shader_present));
  687. panwrap_log("\t\tTiler present? %s\n", YES_NO(args->raw.tiler_present));
  688. panwrap_log("\t\tL2 present? %s\n", YES_NO(args->raw.l2_present));
  689. panwrap_log("\t\tStack present? %s\n", YES_NO(args->raw.stack_present));
  690. panwrap_log("\t\tL2 features: 0x%010x\n", args->raw.l2_features);
  691. panwrap_log("\t\tSuspend size: %d\n", args->raw.suspend_size);
  692. panwrap_log("\t\tMemory features: 0x%010x\n", args->raw.mem_features);
  693. panwrap_log("\t\tMMU features: 0x%010x\n", args->raw.mmu_features);
  694. panwrap_log("\t\tAS (what is this?) present? %s\n",
  695. YES_NO(args->raw.as_present));
  696. panwrap_log("\t\tJS (what is this?) present? %s\n",
  697. YES_NO(args->raw.js_present));
  698. panwrap_log("\t\tJS features:\n");
  699. for (unsigned int i = 0; i < ARRAY_SIZE(args->raw.js_features); i++)
  700. panwrap_log("\t\t\t%010x\n", args->raw.js_features[i]);
  701. panwrap_log("\t\tTiler features: %010x\n", args->raw.tiler_features);
  702. panwrap_log("\t\tGPU ID: 0x%x\n", args->raw.gpu_id);
  703. panwrap_log("\t\tThread features: 0x%x\n", args->raw.thread_features);
  704. panwrap_log("\t\tCoherency mode: 0x%x (%s)\n",
  705. args->raw.coherency_mode,
  706. ioctl_decode_coherency_mode(args->raw.coherency_mode));
  707. panwrap_log("\tCoherency info:\n");
  708. panwrap_log("\t\tNumber of groups: %d\n", args->coherency_info.num_groups);
  709. panwrap_log("\t\tNumber of core groups (coherent or not): %d\n",
  710. args->coherency_info.num_core_groups);
  711. panwrap_log("\t\tFeatures: 0x%x\n", args->coherency_info.coherency);
  712. panwrap_log("\t\tGroups:\n");
  713. for (unsigned int i = 0; i < args->coherency_info.num_groups; i++) {
  714. panwrap_log("\t\t\t- Core mask: %010llx\n",
  715. args->coherency_info.group[i].core_mask);
  716. panwrap_log("\t\t\t Number of cores: %d\n",
  717. args->coherency_info.group[i].num_cores);
  718. }
  719. }
  720. static inline void
  721. ioctl_decode_post_stream_create(unsigned long int request, void *ptr)
  722. {
  723. const struct mali_ioctl_stream_create *args = ptr;
  724. panwrap_log("\tfd = %d\n", args->fd);
  725. }
  726. static inline void
  727. ioctl_decode_post_get_context_id(unsigned long int request, void *ptr)
  728. {
  729. const struct mali_ioctl_get_context_id *args = ptr;
  730. panwrap_log("\tid = 0x%llx\n", args->id);
  731. }
  732. static void
  733. ioctl_decode_post(unsigned long int request, void *ptr)
  734. {
  735. switch (IOCTL_CASE(request)) {
  736. case IOCTL_CASE(MALI_IOCTL_GET_VERSION):
  737. case IOCTL_CASE(MALI_IOCTL_GET_VERSION_NEW):
  738. ioctl_decode_post_get_version(request, ptr);
  739. break;
  740. case IOCTL_CASE(MALI_IOCTL_MEM_ALLOC):
  741. ioctl_decode_post_mem_alloc(request, ptr);
  742. break;
  743. case IOCTL_CASE(MALI_IOCTL_MEM_IMPORT):
  744. ioctl_decode_post_mem_import(request, ptr);
  745. break;
  746. case IOCTL_CASE(MALI_IOCTL_MEM_COMMIT):
  747. ioctl_decode_post_mem_commit(request, ptr);
  748. break;
  749. case IOCTL_CASE(MALI_IOCTL_MEM_QUERY):
  750. ioctl_decode_post_mem_query(request, ptr);
  751. break;
  752. case IOCTL_CASE(MALI_IOCTL_MEM_ALIAS):
  753. ioctl_decode_post_mem_alias(request, ptr);
  754. break;
  755. case IOCTL_CASE(MALI_IOCTL_SYNC):
  756. ioctl_decode_post_sync(request, ptr);
  757. break;
  758. case IOCTL_CASE(MALI_IOCTL_GPU_PROPS_REG_DUMP):
  759. ioctl_decode_post_gpu_props_reg_dump(request, ptr);
  760. break;
  761. case IOCTL_CASE(MALI_IOCTL_STREAM_CREATE):
  762. ioctl_decode_post_stream_create(request, ptr);
  763. break;
  764. case IOCTL_CASE(MALI_IOCTL_GET_CONTEXT_ID):
  765. ioctl_decode_post_get_context_id(request, ptr);
  766. break;
  767. default:
  768. break;
  769. }
  770. }
  771. /**
  772. * Overriden libc functions start here
  773. */
  774. int
  775. panwrap_open_wrap(open_func *orig_open, const char *path, int flags, va_list args)
  776. {
  777. mode_t mode = 0;
  778. int ret;
  779. if (flags & O_CREAT) {
  780. mode = (mode_t) va_arg(args, int);
  781. ret = orig_open(path, flags, mode);
  782. } else {
  783. ret = orig_open(path, flags);
  784. }
  785. LOCK();
  786. if (ret != -1) {
  787. if (strcmp(path, "/dev/mali0") == 0) {
  788. panwrap_log("/dev/mali0 fd == %d\n", ret);
  789. mali_fd = ret;
  790. } else if (strstr(path, "/dev/")) {
  791. panwrap_log("Unknown device %s opened at fd %d\n",
  792. path, ret);
  793. }
  794. }
  795. UNLOCK();
  796. return ret;
  797. }
  798. int
  799. open(const char *path, int flags, ...)
  800. {
  801. PROLOG(open);
  802. va_list args;
  803. va_start(args, flags);
  804. int o = panwrap_open_wrap(orig_open, path, flags, args);
  805. va_end(args);
  806. return o;
  807. }
  808. int
  809. open64(const char *path, int flags, ...)
  810. {
  811. PROLOG(open64);
  812. va_list args;
  813. va_start(args, flags);
  814. int o = panwrap_open_wrap(orig_open64, path, flags, args);
  815. va_end(args);
  816. return o;
  817. }
  818. int
  819. close(int fd)
  820. {
  821. PROLOG(close);
  822. LOCK();
  823. if (fd > 0 && fd == mali_fd) {
  824. panwrap_log("/dev/mali0 closed\n");
  825. mali_fd = 0;
  826. }
  827. UNLOCK();
  828. return orig_close(fd);
  829. }
  830. /* XXX: Android has a messed up ioctl signature */
  831. int ioctl(int fd, unsigned long request, ...)
  832. {
  833. const char *name;
  834. union mali_ioctl_header *header;
  835. PROLOG(ioctl);
  836. int ioc_size = _IOC_SIZE(request);
  837. int ret;
  838. uint32_t func;
  839. void *ptr;
  840. if (ioc_size) {
  841. va_list args;
  842. va_start(args, request);
  843. ptr = va_arg(args, void *);
  844. va_end(args);
  845. } else {
  846. ptr = NULL;
  847. }
  848. if (fd && fd != mali_fd)
  849. return orig_ioctl(fd, request, ptr);
  850. LOCK();
  851. panwrap_freeze_time();
  852. header = ptr;
  853. name = ioctl_get_info(request)->name;
  854. if (!name)
  855. name = "???";
  856. if (!ptr) { /* All valid mali ioctl's should have a specified arg */
  857. panwrap_log("<%-20s> (%02lu) (%08lx), has no arguments? Cannot decode :(\n",
  858. name, _IOC_NR(request), request);
  859. panwrap_unfreeze_time();
  860. ret = orig_ioctl(fd, request, ptr);
  861. panwrap_freeze_time();
  862. panwrap_log("\t= %02d\n", ret);
  863. goto out;
  864. }
  865. /* Dump to ioctl file */
  866. fwrite(&request, 1, sizeof(request), ioctl_fp);
  867. fwrite(ptr, 1, _IOC_SIZE(request), ioctl_fp);
  868. func = header->id;
  869. panwrap_log("<%-20s> (%02lu) (%08lx) (%04lu) (%03d)\n",
  870. name, _IOC_NR(request), request, _IOC_SIZE(request), func);
  871. ioctl_decode_pre(request, ptr);
  872. panwrap_unfreeze_time();
  873. ret = orig_ioctl(fd, request, ptr);
  874. panwrap_freeze_time();
  875. panwrap_log("\t= %02d, %02d\n",
  876. ret, header->rc);
  877. ioctl_decode_post(request, ptr);
  878. out:
  879. panwrap_unfreeze_time();
  880. UNLOCK();
  881. return ret;
  882. }
  883. static inline void *panwrap_mmap_wrap(mmap_func *func,
  884. void *addr, size_t length, int prot,
  885. int flags, int fd, loff_t offset)
  886. {
  887. struct allocated_memory *pos = NULL;
  888. struct mapped_memory *new;
  889. void *ret;
  890. bool found = false;
  891. bool same_va = false;
  892. if (!mali_fd || fd != mali_fd)
  893. return func(addr, length, prot, flags, fd, offset);
  894. LOCK();
  895. ret = func(addr, length, prot, flags, fd, offset);
  896. panwrap_freeze_time();
  897. new = calloc(sizeof(*new), 1);
  898. new->length = length;
  899. new->addr = ret;
  900. list_for_each_entry(pos, &allocations, node) {
  901. /* The kernel driver uses the offset to specify which GPU VA
  902. * we're mapping */
  903. if (pos->gpu_va == (u64) offset) {
  904. found = true;
  905. same_va = pos->same_va;
  906. list_del(&pos->node);
  907. free(pos);
  908. break;
  909. }
  910. }
  911. if (found) {
  912. new->gpu_va = same_va ? (u64) (uintptr_t) ret : (u64) offset;
  913. panwrap_log("GPU memory 0x%llx mapped to %p - %p length=%zu\n",
  914. offset, ret, ret + length, length);
  915. } else {
  916. panwrap_log("Unknown memory mapping %p - %p: offset=%lld length=%zu prot = ",
  917. ret, ret + length, offset, length);
  918. panwrap_log_decoded_flags(mmap_prot_flag_info, prot);
  919. panwrap_log_cont(" flags = ");
  920. panwrap_log_decoded_flags(mmap_flags_flag_info, flags);
  921. panwrap_log_cont("\n");
  922. }
  923. list_add(&new->node, &mmaps);
  924. panwrap_unfreeze_time();
  925. UNLOCK();
  926. return ret;
  927. }
  928. void *mmap64(void *addr, size_t length, int prot, int flags, int fd,
  929. loff_t offset)
  930. {
  931. PROLOG(mmap64);
  932. return panwrap_mmap_wrap(orig_mmap64, addr, length, prot, flags, fd,
  933. offset);
  934. }
  935. void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
  936. {
  937. #ifdef __LP64__
  938. PROLOG(mmap);
  939. return panwrap_mmap_wrap(orig_mmap, addr, length, prot, flags, fd,
  940. offset);
  941. #else
  942. return mmap64(addr, length, prot, flags, fd, (loff_t) offset);
  943. #endif
  944. }
  945. int munmap(void *addr, size_t length)
  946. {
  947. int ret;
  948. struct mapped_memory *mem;
  949. PROLOG(munmap);
  950. LOCK();
  951. ret = orig_munmap(addr, length);
  952. panwrap_freeze_time();
  953. mem = find_mapped_mem(addr);
  954. if (!mem)
  955. goto out;
  956. /* Was it memory mapped from the GPU? */
  957. if (mem->gpu_va)
  958. panwrap_log("Unmapped GPU memory 0x%llx@%p\n",
  959. mem->gpu_va, mem->addr);
  960. else
  961. panwrap_log("Unmapped unknown memory %p\n",
  962. mem->addr);
  963. list_del(&mem->node);
  964. free(mem);
  965. out:
  966. panwrap_unfreeze_time();
  967. UNLOCK();
  968. return ret;
  969. }