lkcd_v2_v3.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /* lkcd_v2_v3.c - core analysis suite
  2. *
  3. * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
  4. * Copyright (C) 2002, 2003, 2004, 2005 David Anderson
  5. * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc. All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. */
  17. #define LKCD_COMMON
  18. #include "defs.h"
  19. #define CONFIG_VMDUMP
  20. #include "lkcd_vmdump_v2_v3.h"
  21. static dump_header_t dump_header_v2_v3 = { 0 };
  22. static dump_page_t dump_page = { 0 };
  23. static dump_header_asm_t dump_header_asm = { 0 };
  24. static void mclx_cache_page_headers_v3(void);
  25. /*
  26. * Verify and initialize the LKCD environment, storing the common data
  27. * in the global lkcd_environment structure.
  28. */
  29. int
  30. lkcd_dump_init_v2_v3(FILE *fp, int fd)
  31. {
  32. int i;
  33. int eof;
  34. uint32_t pgcnt;
  35. dump_header_t *dh;
  36. dump_header_asm_t *dha;
  37. dump_page_t *dp;
  38. lkcd->fd = fd;
  39. lkcd->fp = fp;
  40. lseek(lkcd->fd, 0, SEEK_SET);
  41. dh = &dump_header_v2_v3;
  42. dha = &dump_header_asm;
  43. dp = &dump_page;
  44. if (read(lkcd->fd, dh, sizeof(dump_header_t)) !=
  45. sizeof(dump_header_t))
  46. return FALSE;
  47. if (dh->dh_version & LKCD_DUMP_MCLX_V1)
  48. lseek(lkcd->fd, MCLX_V1_PAGE_HEADER_CACHE, SEEK_CUR);
  49. if (read(lkcd->fd, dha, sizeof(dump_header_asm_t)) !=
  50. sizeof(dump_header_asm_t))
  51. return FALSE;
  52. lkcd->dump_page = dp;
  53. lkcd->dump_header = dh;
  54. lkcd->dump_header_asm = dha;
  55. if (lkcd->debug)
  56. dump_lkcd_environment(LKCD_DUMP_HEADER_ONLY);
  57. /*
  58. * Allocate and clear the benchmark offsets, one per megabyte.
  59. */
  60. lkcd->page_size = dh->dh_page_size;
  61. lkcd->page_shift = ffs(lkcd->page_size) - 1;
  62. lkcd->bits = sizeof(long) * 8;
  63. lkcd->benchmark_pages = (dh->dh_num_pages/LKCD_PAGES_PER_MEGABYTE())+1;
  64. lkcd->total_pages = dh->dh_num_pages;
  65. lkcd->zone_shift = ffs(ZONE_SIZE) - 1;
  66. lkcd->zone_mask = ~(ZONE_SIZE - 1);
  67. lkcd->num_zones = 0;
  68. lkcd->max_zones = 0;
  69. lkcd->zoned_offsets = 0;
  70. lkcd->get_dp_flags = get_dp_flags_v2_v3;
  71. lkcd->get_dp_address = get_dp_address_v2_v3;
  72. lkcd->get_dp_size = get_dp_size_v2_v3;
  73. lkcd->compression = LKCD_DUMP_COMPRESS_RLE;
  74. lkcd->page_header_size = sizeof(dump_page_t);
  75. lseek(lkcd->fd, LKCD_OFFSET_TO_FIRST_PAGE, SEEK_SET);
  76. for (pgcnt = 0, eof = FALSE; !eof; pgcnt++) {
  77. switch (lkcd_load_dump_page_header(dp, pgcnt))
  78. {
  79. case LKCD_DUMPFILE_OK:
  80. case LKCD_DUMPFILE_END:
  81. break;
  82. case LKCD_DUMPFILE_EOF:
  83. lkcd_print("reached EOF\n");
  84. eof = TRUE;
  85. continue;
  86. }
  87. if (dp->dp_flags &
  88. ~(DUMP_COMPRESSED|DUMP_RAW|DUMP_END|LKCD_DUMP_MCLX_V0)) {
  89. lkcd_print("unknown page flag in dump: %lx\n",
  90. dp->dp_flags);
  91. }
  92. if (dp->dp_flags & (LKCD_DUMP_MCLX_V0|LKCD_DUMP_MCLX_V1))
  93. lkcd->flags |= LKCD_MCLX;
  94. if (dp->dp_size > 4096) {
  95. lkcd_print("dp_size > 4096: %d\n", dp->dp_size);
  96. dump_lkcd_environment(LKCD_DUMP_PAGE_ONLY);
  97. }
  98. if (dp->dp_flags & DUMP_END) {
  99. lkcd_print("found DUMP_END\n");
  100. break;
  101. }
  102. lseek(lkcd->fd, dp->dp_size, SEEK_CUR);
  103. if (!LKCD_DEBUG(2))
  104. break;
  105. }
  106. /*
  107. * Allocate space for LKCD_CACHED_PAGES data pages plus one to
  108. * contain a copy of the compressed data of the current page.
  109. */
  110. if ((lkcd->page_cache_buf = (char *)malloc
  111. (dh->dh_page_size * (LKCD_CACHED_PAGES))) == NULL)
  112. return FALSE;
  113. /*
  114. * Clear the page data areas.
  115. */
  116. lkcd_free_memory();
  117. for (i = 0; i < LKCD_CACHED_PAGES; i++) {
  118. lkcd->page_cache_hdr[i].pg_bufptr =
  119. &lkcd->page_cache_buf[i * dh->dh_page_size];
  120. }
  121. if ((lkcd->compressed_page = (char *)malloc(dh->dh_page_size)) == NULL)
  122. return FALSE;
  123. if ((lkcd->page_hash = (struct page_hash_entry *)calloc
  124. (LKCD_PAGE_HASH, sizeof(struct page_hash_entry))) == NULL)
  125. return FALSE;
  126. lkcd->total_pages = eof || (pgcnt > dh->dh_num_pages) ?
  127. pgcnt : dh->dh_num_pages;
  128. lkcd->panic_task = (ulong)dh->dh_current_task;
  129. lkcd->panic_string = (char *)&dh->dh_panic_string[0];
  130. if (dh->dh_version & LKCD_DUMP_MCLX_V1)
  131. mclx_cache_page_headers_v3();
  132. if (!fp)
  133. lkcd->flags |= LKCD_REMOTE;
  134. lkcd->flags |= LKCD_VALID;
  135. return TRUE;
  136. }
  137. /*
  138. * Return the current page's dp_size.
  139. */
  140. uint32_t
  141. get_dp_size_v2_v3(void)
  142. {
  143. dump_page_t *dp;
  144. dp = (dump_page_t *)lkcd->dump_page;
  145. return(dp->dp_size);
  146. }
  147. /*
  148. * Return the current page's dp_flags.
  149. */
  150. uint32_t
  151. get_dp_flags_v2_v3(void)
  152. {
  153. dump_page_t *dp;
  154. dp = (dump_page_t *)lkcd->dump_page;
  155. return(dp->dp_flags);
  156. }
  157. /*
  158. * Return the current page's dp_address.
  159. */
  160. uint64_t
  161. get_dp_address_v2_v3(void)
  162. {
  163. dump_page_t *dp;
  164. dp = (dump_page_t *)lkcd->dump_page;
  165. return(dp->dp_address);
  166. }
  167. void
  168. dump_dump_page_v2_v3(char *s, void *dpp)
  169. {
  170. dump_page_t *dp;
  171. uint32_t flags;
  172. int others;
  173. console(s);
  174. dp = (dump_page_t *)dpp;
  175. others = 0;
  176. console(BITS32() ? "dp_address: %llx " : "dp_address: %lx ",
  177. dp->dp_address);
  178. console("dp_size: %ld ", dp->dp_size);
  179. console("dp_flags: %lx (", flags = dp->dp_flags);
  180. if (flags & DUMP_COMPRESSED)
  181. console("DUMP_COMPRESSED", others++);
  182. if (flags & DUMP_RAW)
  183. console("%sDUMP_RAW", others++ ? "|" : "");
  184. if (flags & DUMP_END)
  185. console("%sDUMP_END", others++ ? "|" : "");
  186. if (flags & LKCD_DUMP_MCLX_V0)
  187. console("%sLKCD_DUMP_MCLX_V0", others++ ? "|" : "");
  188. console(")\n");
  189. }
  190. /*
  191. * help -S output, or as specified by arg.
  192. */
  193. void
  194. dump_lkcd_environment_v2_v3(ulong arg)
  195. {
  196. int others;
  197. dump_header_t *dh;
  198. dump_header_asm_t *dha;
  199. dump_page_t *dp;
  200. dh = (dump_header_t *)lkcd->dump_header;
  201. dha = (dump_header_asm_t *)lkcd->dump_header_asm;
  202. dp = (dump_page_t *)lkcd->dump_page;
  203. if (arg == LKCD_DUMP_HEADER_ONLY)
  204. goto dump_header_only;
  205. if (arg == LKCD_DUMP_PAGE_ONLY)
  206. goto dump_page_only;
  207. dump_header_only:
  208. lkcd_print(" dump_header:\n");
  209. lkcd_print(" dh_magic_number: ");
  210. lkcd_print(BITS32() ? "%llx " : "%lx ", dh->dh_magic_number);
  211. if (dh->dh_magic_number == DUMP_MAGIC_NUMBER)
  212. lkcd_print("(DUMP_MAGIC_NUMBER)\n");
  213. else
  214. lkcd_print("(?)\n");
  215. others = 0;
  216. lkcd_print(" dh_version: ");
  217. lkcd_print(BITS32() ? "%lx (" : "%x (", dh->dh_version);
  218. switch (dh->dh_version & LKCD_DUMP_VERSION_NUMBER_MASK)
  219. {
  220. case LKCD_DUMP_V1:
  221. lkcd_print("%sLKCD_DUMP_V1", others++ ? "|" : "");
  222. break;
  223. case LKCD_DUMP_V2:
  224. lkcd_print("%sLKCD_DUMP_V2", others++ ? "|" : "");
  225. break;
  226. case LKCD_DUMP_V3:
  227. lkcd_print("%sLKCD_DUMP_V3", others++ ? "|" : "");
  228. break;
  229. }
  230. if (dh->dh_version & LKCD_DUMP_MCLX_V0)
  231. lkcd_print("%sLKCD_DUMP_MCLX_V0", others++ ? "|" : "");
  232. if (dh->dh_version & LKCD_DUMP_MCLX_V1)
  233. lkcd_print("%sLKCD_DUMP_MCLX_V1", others++ ? "|" : "");
  234. lkcd_print(")\n");
  235. lkcd_print(" dh_header_size: ");
  236. lkcd_print(BITS32() ? "%ld\n" : "%d\n", dh->dh_header_size);
  237. lkcd_print(" dh_dump_level: ");
  238. lkcd_print(BITS32() ? "%lx (" : "%x (", dh->dh_dump_level);
  239. others = 0;
  240. if (dh->dh_dump_level & DUMP_HEADER)
  241. lkcd_print("%sDUMP_HEADER", others++ ? "|" : "");
  242. if (dh->dh_dump_level & DUMP_KERN)
  243. lkcd_print("%sDUMP_KERN", others++ ? "|" : "");
  244. if (dh->dh_dump_level & DUMP_USED)
  245. lkcd_print("%sDUMP_USED", others++ ? "|" : "");
  246. if (dh->dh_dump_level & DUMP_ALL)
  247. lkcd_print("%sDUMP_ALL", others++ ? "|" : "");
  248. lkcd_print(")\n");
  249. lkcd_print(" dh_page_size: ");
  250. lkcd_print(BITS32() ? "%ld\n" : "%d\n", dh->dh_page_size);
  251. lkcd_print(" dh_memory_size: ");
  252. lkcd_print(BITS32() ? "%lld\n" : "%ld\n", dh->dh_memory_size);
  253. lkcd_print(" dh_memory_start: ");
  254. lkcd_print(BITS32() ? "%llx\n" : "%lx\n", dh->dh_memory_start);
  255. lkcd_print(" dh_memory_end: ");
  256. lkcd_print(BITS32() ? "%llx\n" : "%lx\n", dh->dh_memory_end);
  257. lkcd_print(" dh_num_pages: ");
  258. lkcd_print(BITS32() ? "%ld\n" : "%d\n", dh->dh_num_pages);
  259. lkcd_print(" dh_panic_string: %s%s", dh->dh_panic_string,
  260. dh && dh->dh_panic_string &&
  261. strstr(dh->dh_panic_string, "\n") ? "" : "\n");
  262. lkcd_print(" dh_time: %s\n",
  263. strip_linefeeds(ctime(&(dh->dh_time.tv_sec))));
  264. lkcd_print(" dh_utsname:\n");
  265. lkcd_print(" sysname: %s\n", dh->dh_utsname.sysname);
  266. lkcd_print(" nodename: %s\n", dh->dh_utsname.nodename);
  267. lkcd_print(" release: %s\n", dh->dh_utsname.release);
  268. lkcd_print(" version: %s\n", dh->dh_utsname.version);
  269. lkcd_print(" machine: %s\n", dh->dh_utsname.machine);
  270. lkcd_print(" domainname: %s\n", dh->dh_utsname.domainname);
  271. lkcd_print(" dh_current_task: %lx\n", dh->dh_current_task);
  272. lkcd_print("dha_magic_number: ");
  273. lkcd_print(BITS32() ? "%llx " : "%lx ", dha->dha_magic_number);
  274. if (dha->dha_magic_number == DUMP_ASM_MAGIC_NUMBER)
  275. lkcd_print("(DUMP_ASM_MAGIC_NUMBER)\n");
  276. else
  277. lkcd_print("(?)\n");
  278. lkcd_print(" dha_version: ");
  279. lkcd_print(BITS32() ? "%ld\n" : "%d\n", dha->dha_version);
  280. lkcd_print(" dha_header_size: ");
  281. lkcd_print(BITS32() ? "%ld\n" : "%d\n", dha->dha_header_size);
  282. #ifdef X86
  283. lkcd_print(" dha_esp: %lx\n", dha->dha_esp);
  284. lkcd_print(" dha_eip: %lx\n", dha->dha_eip);
  285. #endif
  286. #if defined PPC || ALPHA || IA64
  287. /* TBD */
  288. #endif
  289. lkcd_print(" dha_regs:\n");
  290. #ifdef PPC
  291. lkcd_print(" (PowerPC register display TBD)\n");
  292. #endif
  293. #ifdef IA64
  294. lkcd_print(" (IA64 register display TBD)\n");
  295. #endif
  296. #ifdef X86
  297. lkcd_print(" ebx: %lx\n", dha->dha_regs.ebx);
  298. lkcd_print(" ecx: %lx\n", dha->dha_regs.ecx);
  299. lkcd_print(" edx: %lx\n", dha->dha_regs.edx);
  300. lkcd_print(" esi: %lx\n", dha->dha_regs.esi);
  301. lkcd_print(" edi: %lx\n", dha->dha_regs.edi);
  302. lkcd_print(" eax: %lx\n", dha->dha_regs.eax);
  303. lkcd_print(" xds: %x\n", dha->dha_regs.xds);
  304. lkcd_print(" xes: %x\n", dha->dha_regs.xes);
  305. lkcd_print(" orig_eax: %lx\n", dha->dha_regs.orig_eax);
  306. lkcd_print(" eip: %lx\n", dha->dha_regs.eip);
  307. lkcd_print(" xcs: %x\n", dha->dha_regs.xcs);
  308. lkcd_print(" eflags: %lx\n", dha->dha_regs.eflags);
  309. lkcd_print(" esp: %lx\n", dha->dha_regs.esp);
  310. lkcd_print(" xss: %x\n", dha->dha_regs.xss);
  311. #endif
  312. #ifdef ALPHA
  313. lkcd_print(" r0: %lx\n", dha->dha_regs.r0);
  314. lkcd_print(" r1: %lx\n", dha->dha_regs.r1);
  315. lkcd_print(" r2: %lx\n", dha->dha_regs.r2);
  316. lkcd_print(" r3: %lx\n", dha->dha_regs.r3);
  317. lkcd_print(" r4: %lx\n", dha->dha_regs.r4);
  318. lkcd_print(" r5: %lx\n", dha->dha_regs.r5);
  319. lkcd_print(" r6: %lx\n", dha->dha_regs.r6);
  320. lkcd_print(" r7: %lx\n", dha->dha_regs.r7);
  321. lkcd_print(" r8: %lx\n", dha->dha_regs.r8);
  322. lkcd_print(" r19: %lx\n", dha->dha_regs.r19);
  323. lkcd_print(" r20: %lx\n", dha->dha_regs.r20);
  324. lkcd_print(" r21: %lx\n", dha->dha_regs.r21);
  325. lkcd_print(" r22: %lx\n", dha->dha_regs.r22);
  326. lkcd_print(" r23: %lx\n", dha->dha_regs.r23);
  327. lkcd_print(" r24: %lx\n", dha->dha_regs.r24);
  328. lkcd_print(" r25: %lx\n", dha->dha_regs.r25);
  329. lkcd_print(" r26: %lx\n", dha->dha_regs.r26);
  330. lkcd_print(" r27: %lx\n", dha->dha_regs.r27);
  331. lkcd_print(" r28: %lx\n", dha->dha_regs.r28);
  332. lkcd_print(" hae: %lx\n", dha->dha_regs.hae);
  333. lkcd_print(" trap_a0: %lx\n", dha->dha_regs.trap_a0);
  334. lkcd_print(" trap_a1: %lx\n", dha->dha_regs.trap_a1);
  335. lkcd_print(" trap_a2: %lx\n", dha->dha_regs.trap_a2);
  336. lkcd_print(" ps: %lx\n", dha->dha_regs.ps);
  337. lkcd_print(" pc: %lx\n", dha->dha_regs.pc);
  338. lkcd_print(" gp: %lx\n", dha->dha_regs.gp);
  339. lkcd_print(" r16: %lx\n", dha->dha_regs.r16);
  340. lkcd_print(" r17: %lx\n", dha->dha_regs.r17);
  341. lkcd_print(" r18: %lx\n", dha->dha_regs.r18);
  342. #endif
  343. if (arg == LKCD_DUMP_HEADER_ONLY)
  344. return;
  345. dump_page_only:
  346. lkcd_print(" dump_page:\n");
  347. lkcd_print(" dp_address: ");
  348. lkcd_print(BITS32() ? "%llx\n" : "%lx\n", dp->dp_address);
  349. lkcd_print(" dp_size: ");
  350. lkcd_print(BITS32() ? "%ld\n" : "%d\n", dp->dp_size);
  351. lkcd_print(" dp_flags: ");
  352. lkcd_print(BITS32() ? "%lx (" : "%x (", dp->dp_flags);
  353. others = 0;
  354. if (dp->dp_flags & DUMP_COMPRESSED)
  355. lkcd_print("DUMP_COMPRESSED", others++);
  356. if (dp->dp_flags & DUMP_RAW)
  357. lkcd_print("%sDUMP_RAW", others++ ? "|" : "");
  358. if (dp->dp_flags & DUMP_END)
  359. lkcd_print("%sDUMP_END", others++ ? "|" : "");
  360. if (dp->dp_flags & LKCD_DUMP_MCLX_V0)
  361. lkcd_print("%sLKCD_DUMP_MCLX_V0", others++ ? "|" : "");
  362. lkcd_print(")\n");
  363. }
  364. /*
  365. * Read the MCLX-enhanced page header cache. Verify the first one, which
  366. * is a pointer to the page header for address 1MB, and take the rest at
  367. * blind faith. Note that the page headers do not include the 64K dump
  368. * header offset, which must be added to the values found.
  369. */
  370. static void
  371. mclx_cache_page_headers_v3(void)
  372. {
  373. int i;
  374. uint64_t physaddr1, physaddr2, page_headers[MCLX_PAGE_HEADERS];
  375. dump_page_t dump_page, *dp;
  376. ulong granularity;
  377. if (LKCD_DEBUG(2)) /* dump headers have all been read */
  378. return;
  379. if (lkcd->total_pages > MEGABYTES(1))/* greater than 4G not supported */
  380. return;
  381. if (lseek(lkcd->fd, sizeof(dump_header_t), SEEK_SET) == -1)
  382. return;
  383. if (read(lkcd->fd, page_headers, MCLX_V1_PAGE_HEADER_CACHE) !=
  384. MCLX_V1_PAGE_HEADER_CACHE)
  385. return;
  386. dp = &dump_page;
  387. /*
  388. * Determine the granularity between offsets.
  389. */
  390. if (lseek(lkcd->fd, page_headers[0] + LKCD_OFFSET_TO_FIRST_PAGE,
  391. SEEK_SET) == -1)
  392. return;
  393. if (read(lkcd->fd, dp, lkcd->page_header_size) !=
  394. lkcd->page_header_size)
  395. return;
  396. physaddr1 = (dp->dp_address - lkcd->kvbase) << lkcd->page_shift;
  397. if (lseek(lkcd->fd, page_headers[1] + LKCD_OFFSET_TO_FIRST_PAGE,
  398. SEEK_SET) == -1)
  399. return;
  400. if (read(lkcd->fd, dp, lkcd->page_header_size) !=
  401. lkcd->page_header_size)
  402. return;
  403. physaddr2 = (dp->dp_address - lkcd->kvbase) << lkcd->page_shift;
  404. if ((physaddr1 % MEGABYTES(1)) || (physaddr2 % MEGABYTES(1)) ||
  405. (physaddr2 < physaddr1))
  406. return;
  407. granularity = physaddr2 - physaddr1;
  408. for (i = 0; i < (MCLX_PAGE_HEADERS-1); i++) {
  409. if (!page_headers[i])
  410. break;
  411. lkcd->curhdroffs = page_headers[i] + LKCD_OFFSET_TO_FIRST_PAGE;
  412. set_mb_benchmark((granularity * (i+1))/lkcd->page_size);
  413. }
  414. }