Hi, I've developed this crash extension to analyze SPU specific data for Cell/B.E. processor. This extension makes use of some important data saved by this kernel patch (that is not mainline yet) http://ozlabs.org/pipermail/cbe-oss-dev/2007-May/001848.html during the crash dump. I would like to check if there is any issue with the code. Thanks in advance, -- Lucio Correia Software Engineer IBM LTC Brazil
/* spu.c - commands for viewing Cell/B.E. SPUs data * * (C) Copyright 2007 IBM Corp. * * Author: Lucio Correia <luciojhc@xxxxxxxxxx> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "defs.h" #define NR_SPUS (16) /* Enough for current hardware */ #define MAX_PRIO (140) #define MAX_CTXS (50) #define STR_SPU_INVALID (0x0) #define STR_SPU_ID (0x1) #define STR_SPU_PID (0x2) #define STR_SPU_ADDR (0x4) #define STR_SPU_CTX_ADDR (0x8) #define SPUCTX_CMD_NAME "spuctx" #define SPUS_CMD_NAME "spus" #define SPURQ_CMD_NAME "spurq" ulong get_debug_field(ulong spu, char *field); ulong get_spu_field(ulong spu, char *field); void cmd_spus(void); void cmd_spurq(void); void cmd_spuctx(void); char *help_spus[]; char *help_spurq[]; void show_spu_state(ulong spu); void dump_spu_runq(ulong k_prio_array); char *help_spuctx[]; void show_ctx_info(ulong ctx_addr); void print_ctx_info(char *ctx_data, char *spu_data, int info); void show_ctx_info_all(void); static struct command_table_entry command_table[] = { SPUCTX_CMD_NAME, cmd_spuctx, help_spuctx, 0, SPUS_CMD_NAME, cmd_spus, help_spus, 0, SPURQ_CMD_NAME, cmd_spurq, help_spurq, 0, NULL }; ulong spu[NR_SPUS]; /***************************************************************************** * INIT FUNCTIONS */ /* * Read kernel virtual addresses of debug_spu_info data stored by kdump */ int get_debug_spu_info(void) { int i; ulong addr; long offset; if (symbol_exists("debug_spu_info")) { addr = symbol_value("debug_spu_info"); offset = STRUCT_SIZE("debug_spu_info"); if (offset == -1) error(FATAL, "Couldn't get debug_spu_info size.\n"); } else return FALSE; for (i = 0; i < NR_SPUS; i++) spu[i] = addr + (i * offset); return TRUE; } _init() { int i, n_registered; struct command_table_entry *cte; for (i = 0; i < NR_SPUS; i++) spu[i] = 0; register_extension(command_table); if (!get_debug_spu_info()) error(FATAL, "Couldn't get spu_debug_info data.\n"); } _fini() { } /***************************************************************************** * BASIC FUNCTIONS */ /* * Returns a pointer to the requested debug field */ ulong get_debug_field(ulong spu_info, char *field) { ulong offset; offset = MEMBER_OFFSET("debug_spu_info", field); if (offset == -1) error(FATAL, "Couldn't get debug_spu_info.%s offset.\n", field); return spu_info + offset; } /* * Returns a pointer to the requested SPU field */ ulong get_spu_field(ulong spu_info, char* field) { ulong offset, spu_addr; offset = MEMBER_OFFSET("debug_spu_info", "spu"); if (offset == -1) error(FATAL, "Couldn't get debug_spu_info.spu offset.\n"); readmem(spu_info + offset, KVADDR, &spu_addr, sizeof(spu_addr), "get_spu_field", FAULT_ON_ERROR); offset = field ? MEMBER_OFFSET("spu", field) : 0; if (offset == -1) error(FATAL, "Couldn't get spu.%s offset.\n", field); return spu_addr + offset; } /***************************************************************************** * SPUCTX COMMAND */ #define DUMP_WIDTH 23 #define DUMP_SPU_FIELD(format, field, cast) \ do { \ offset = MEMBER_OFFSET("spu", field); \ if (offset == -1) \ error(FATAL, "Couldn't get offset for %s.\n", field); \ \ printf(" %-*s = "format"\n", DUMP_WIDTH, field, \ cast(spu_data + offset)); \ } while(0) #define DUMP_CTX_FIELD(format, field, cast) \ do { \ offset = MEMBER_OFFSET("spu_context", field); \ if (offset == -1) \ error(FATAL, "Couldn't get offset for %s.\n", field); \ \ printf(" %-*s = "format"\n", DUMP_WIDTH, field, \ cast(ctx_data + offset)); \ } while(0) #define DUMP_DBG_FIELD(format, field, cast) \ do { \ offset = MEMBER_OFFSET("debug_spu_info", field); \ if (offset == -1) \ error(FATAL, "Couldn't get offset for %s.\n", field); \ \ printf(" %-*s = "format"\n", DUMP_WIDTH, field, \ cast(debug_data + offset)); \ } while(0) /* * Print the spu and spu_context structs fields. Some SPU memory-mapped IO * registers are taken directly from debug_spu_info. */ void print_ctx_info(char *ctx_data, char *spu_data, int info) { long offset, size; char *debug_data; DUMP_CTX_FIELD("%d", "state", *(int *)); DUMP_CTX_FIELD("%d", "prio", *(int *)); DUMP_CTX_FIELD("%p", "local_store", *(ulong *)); DUMP_CTX_FIELD("%p", "rq", *(ulong *)); if (spu_data) { DUMP_SPU_FIELD("%d", "node", *(int *)); DUMP_SPU_FIELD("%d", "number", *(int *)); DUMP_SPU_FIELD("%d", "pid", *(int *)); DUMP_SPU_FIELD("%s", "name", (char *)); DUMP_SPU_FIELD("%x", "slb_replace", *(unsigned int *)); DUMP_SPU_FIELD("%p", "mm", *(ulong *)); DUMP_SPU_FIELD("%p", "timestamp", *(long long *)); DUMP_SPU_FIELD("%d", "class_0_pending", *(int *)); DUMP_SPU_FIELD("%p", "problem", *(ulong *)); DUMP_SPU_FIELD("%p", "priv2", *(ulong *)); DUMP_SPU_FIELD("%lu", "flags", *(ulong *)); size = STRUCT_SIZE("debug_spu_info"); if (size == -1) error(FATAL, "Couldn't get debug_spu_info size.\n"); debug_data = (char *)GETBUF(size); readmem(spu[info], KVADDR, debug_data, size, "debug_data", FAULT_ON_ERROR); DUMP_DBG_FIELD("%lu", "saved_mfc_sr1_RW", *(ulong *)); DUMP_DBG_FIELD("%lu", "saved_mfc_dar", *(ulong *)); DUMP_DBG_FIELD("%lu", "saved_mfc_dsisr", *(ulong *)); DUMP_DBG_FIELD("%u", "saved_spu_runcntl_RW", *(uint *)); DUMP_DBG_FIELD("%u", "saved_spu_status_R", *(uint *)); DUMP_DBG_FIELD("%u", "saved_spu_npc_RW", *(uint *)); FREEBUF(debug_data); } } /* * Pass ctx and respective spu data to print_ctx_info for the contexts in * ctx_addr list (chosen contexts). */ void show_ctx_info(ulong ctx_addr) { int number, info, i; char *ctx_data, *spu_data; long size, offset; ulong spu_addr, addr; spu_data = NULL; info = 0; size = STRUCT_SIZE("spu_context"); if (size == -1) error(FATAL, "Couldn't get spu_context size.\n"); ctx_data = GETBUF(size); if (!ctx_data) error(FATAL, "Couldn't allocate memory for ctx.\n"); readmem(ctx_addr, KVADDR, ctx_data, size, "show_ctx_info ctx", FAULT_ON_ERROR); offset = MEMBER_OFFSET("spu_context", "spu"); if (offset == -1) error(FATAL, "Couldn't get spu_context_spu offset.\n"); spu_addr = *(ulong *)(ctx_data + offset); if (spu_addr) { size = STRUCT_SIZE("spu"); if (size == -1) error(FATAL, "Couldn't get spu size.\n"); spu_data = GETBUF(size); if (!spu_data) error(FATAL, "Couldn't allocate memory for spu.\n"); readmem(spu_addr, KVADDR, spu_data, size, "show_ctx_info spu", FAULT_ON_ERROR); for (i = 0; i < NR_SPUS; i++) { readmem(spu[i], KVADDR, &addr, sizeof(addr), "spu addr", FAULT_ON_ERROR); if (addr == spu_addr) info = i; } } printf("Dumping context fields for spu_context %lx:\n", ctx_addr); print_ctx_info(ctx_data, spu_data, info); FREEBUF(ctx_data); if (spu_addr) FREEBUF(spu_data); } /* * Pass ctx and respective spu data to print_ctx_info for all the contexts * running and on the runqueue. */ void show_ctx_info_all(void) { int i, j, cnt; long prio_size, prio_runq_off, ctx_rq_off, jump, offset, ctxs_size; char *u_spu_prio; ulong spu_prio_addr, k_spu_prio, kvaddr, uvaddr, addr, ctx; ulong *ctxs; ulong list_head[2]; struct list_data list_data, *ld; /* Walking SPUs */ for (i = 0; i < NR_SPUS; i++) { addr = (ulong)get_spu_field(spu[i], "ctx"); readmem(addr, KVADDR, &ctx, sizeof(ctx), "show_ctx_info_all", FAULT_ON_ERROR); show_ctx_info(ctx); } /* Walking SPU runqueue */ if (symbol_exists("spu_prio")) { spu_prio_addr = symbol_value("spu_prio"); readmem(spu_prio_addr, KVADDR, &k_spu_prio, sizeof(k_spu_prio), "runq_array", FAULT_ON_ERROR); } else error(FATAL, "Could not get SPU run queue data.\n"); jump = STRUCT_SIZE("list_head"); if (jump == -1) error(FATAL, "Couldn't get list_head size.\n"); prio_runq_off = MEMBER_OFFSET("spu_prio_array", "runq"); if (prio_runq_off == -1) error(FATAL, "Couldn't get runq offset.\n"); ctx_rq_off = MEMBER_OFFSET("spu_context", "rq"); if (ctx_rq_off == -1) error(FATAL, "Couldn't get rq offset.\n"); prio_size = STRUCT_SIZE("spu_prio_array"); if (prio_size == -1) error(FATAL, "Couldn't get list_head size.\n"); u_spu_prio = (char *)GETBUF(prio_size); readmem(k_spu_prio, KVADDR, u_spu_prio, prio_size, "get_runq_ctxs", FAULT_ON_ERROR); ctxs_size = MAX_CTXS * sizeof(ulong); ctxs = (ulong *)GETBUF(ctxs_size); for (i = 0; i < MAX_PRIO; i++) { offset = prio_runq_off + i * jump; kvaddr = k_spu_prio + offset; uvaddr = (ulong)u_spu_prio + offset; BCOPY((char *)uvaddr, (char *)&list_head[0], sizeof(ulong)*2); if ((list_head[0] == kvaddr) && (list_head[1] == kvaddr)) continue; ld = &list_data; BZERO(ld, sizeof(struct list_data)); ld->start = list_head[0]; ld->list_head_offset = ctx_rq_off; ld->flags |= RETURN_ON_LIST_ERROR; ld->end = kvaddr; hq_open(); cnt = do_list(ld); if (cnt == -1) { hq_close(); FREEBUF(u_spu_prio); FREEBUF(ctxs); error(FATAL, "Couldn't walk the list.\n"); } BZERO(ctxs, ctxs_size); cnt = retrieve_list(ctxs, cnt); hq_close(); for (j = 0; j < cnt; j++) if (j < MAX_CTXS) show_ctx_info(ctxs[j]); } FREEBUF(u_spu_prio); FREEBUF(ctxs); } /* * Tries to discover the meaning of string and to find the referred context */ int str_to_spuctx(char *string, ulong *value, ulong *spu_ctx) { char *s, *u_spu_prio; ulong dvalue, hvalue, addr, spu_addr, ctx; ulong k_spu_prio, spu_prio_addr, kvaddr, uvaddr; int type, pid, i, j, cnt; long prio_size, prio_runq_off, ctx_rq_off, jump, offset, ctxs_size; ulong *ctxs; ulong list_head[2]; struct list_data list_data, *ld; if (string == NULL) { error(INFO, "%s: received NULL string.\n", __FUNCTION__); return STR_SPU_INVALID; } s = string; dvalue = hvalue = BADADDR; if (decimal(s, 0)) dvalue = dtol(s, RETURN_ON_ERROR, NULL); if (hexadecimal(s, 0)) { if (STRNEQ(s, "0x") || STRNEQ(s, "0X")) s += 2; if (strlen(s) <= MAX_HEXADDR_STRLEN) hvalue = htol(s, RETURN_ON_ERROR, NULL); } type = STR_SPU_INVALID; if (dvalue != BADADDR) { /* Testing for SPU ID */ if ((dvalue >= 0) && (dvalue < NR_SPUS)) { addr = get_spu_field(spu[dvalue], "ctx"); readmem(addr, KVADDR, &ctx, sizeof(ctx), "str_to_spuctx ID", FAULT_ON_ERROR); type = STR_SPU_ID; *value = dvalue; *spu_ctx = ctx; return type; } else { /* Testing for PID */ for (i = 0; i < NR_SPUS; i++) { addr = get_spu_field(spu[i], "pid"); readmem(addr, KVADDR, &pid, sizeof(pid), "str_to_spuctx PID", FAULT_ON_ERROR); if (dvalue == pid) { addr = get_spu_field(spu[i], "ctx"); readmem(addr, KVADDR, &ctx, sizeof(ctx), "str_to_spuctx PID ctx", FAULT_ON_ERROR); type = STR_SPU_PID; *value = dvalue; *spu_ctx = ctx; return type; } } } } if (hvalue != BADADDR) { /* Testing for spuctx address on SPUs */ for (i = 0; i < NR_SPUS; i++) { addr = get_spu_field(spu[i], "ctx"); readmem(addr, KVADDR, &ctx, sizeof(ctx), "str_to_spuctx CTX", FAULT_ON_ERROR); if (hvalue == ctx) { type = STR_SPU_CTX_ADDR; *value = hvalue; *spu_ctx = ctx; return type; } } /* Testing for spuctx address on SPU runqueue */ if (symbol_exists("spu_prio")) { spu_prio_addr = symbol_value("spu_prio"); readmem(spu_prio_addr, KVADDR, &k_spu_prio, sizeof(k_spu_prio), "runq_array", FAULT_ON_ERROR); } else error(FATAL, "Could not get SPU run queue data.\n"); jump = STRUCT_SIZE("list_head"); if (jump == -1) error(FATAL, "Couldn't get list_head size.\n"); prio_runq_off = MEMBER_OFFSET("spu_prio_array", "runq"); if (prio_runq_off == -1) error(FATAL, "Couldn't get runq offset.\n"); ctx_rq_off = MEMBER_OFFSET("spu_context", "rq"); if (ctx_rq_off == -1) error(FATAL, "Couldn't get rq offset.\n"); prio_size = STRUCT_SIZE("spu_prio_array"); if (prio_size == -1) error(FATAL, "Couldn't get list_head size.\n"); u_spu_prio = (char *)GETBUF(prio_size); readmem(k_spu_prio, KVADDR, u_spu_prio, prio_size, "get_runq_ctxs", FAULT_ON_ERROR); ctxs_size = MAX_CTXS * sizeof(ulong); ctxs = (ulong *)GETBUF(ctxs_size); for (i = 0; i < MAX_PRIO; i++) { offset = prio_runq_off + i * jump; kvaddr = k_spu_prio + offset; uvaddr = (ulong)u_spu_prio + offset; BCOPY((char *)uvaddr, (char *)&list_head[0], sizeof(ulong)*2); if ((list_head[0] == kvaddr) && (list_head[1] == kvaddr)) continue; ld = &list_data; BZERO(ld, sizeof(struct list_data)); ld->start = list_head[0]; ld->list_head_offset = ctx_rq_off; ld->flags |= RETURN_ON_LIST_ERROR; ld->end = kvaddr; hq_open(); cnt = do_list(ld); if (cnt == -1) { hq_close(); FREEBUF(u_spu_prio); FREEBUF(ctxs); error(FATAL, "Couldn't walk the list.\n"); } BZERO(ctxs, ctxs_size); cnt = retrieve_list(ctxs, cnt); hq_close(); for (j = 0; j < cnt; j++) if ((j < MAX_CTXS) && (hvalue == ctxs[j])) { type = STR_SPU_CTX_ADDR; *value = hvalue; *spu_ctx = ctxs[j]; FREEBUF(u_spu_prio); FREEBUF(ctxs); return type; } } FREEBUF(u_spu_prio); FREEBUF(ctxs); /* Testing for spu address */ for (i = 0; i < NR_SPUS; i++) { addr = get_debug_field(spu[i], "spu"); readmem(addr, KVADDR, &spu_addr, sizeof(spu_addr), "str_to_spuctx SPU", FAULT_ON_ERROR); if (hvalue == spu_addr) { addr = get_spu_field(spu[i], "ctx"); readmem(addr, KVADDR, &ctx, sizeof(ctx), "str_to_spuctx SPU ctx", FAULT_ON_ERROR); type = STR_SPU_ADDR; *value = hvalue; *spu_ctx = ctx; return type; } } } return type; } /* * spuctx command stands for "spu context" and shows the context fields * for the spu or respective struct address passed as an argument */ void cmd_spuctx() { int i, c, cnt; ulong value, ctx; ulong *ctxlist; while ((c = getopt(argcnt, args, "")) != EOF) { switch(c) { default: argerrs++; break; } } if (argerrs) cmd_usage(pc->curcmd, SYNOPSIS); if (!args[optind]) { show_ctx_info_all(); return; } cnt = 0; ctxlist = (ulong *)GETBUF((MAXARGS+NR_CPUS)*sizeof(ctx)); while (args[optind]) { if (IS_A_NUMBER(args[optind])) { switch (str_to_spuctx(args[optind], &value, &ctx)) { case STR_SPU_ADDR: case STR_SPU_CTX_ADDR: case STR_SPU_ID: case STR_SPU_PID: ctxlist[cnt++] = ctx; break; case STR_SPU_INVALID: error(INFO, "Invalid SPU context or PID: %s\n", args[optind]); break; } } else error(INFO, "Invalid SPU context or PID: %s\n", args[optind]); optind++; } if (cnt == 0) error(INFO, "No valid ID, PID or address for a SPU.\n"); else for (i = 0; i < cnt; i++) show_ctx_info(ctxlist[i]); FREEBUF(ctxlist); } /***************************************************************************** * SPUS COMMAND */ void print_spu_header(ulong spu_info) { int id, pid, size; ulong ctx_addr, spu_addr; char *spu_data; if (spu_info) { size = STRUCT_SIZE("spu"); spu_data = GETBUF(size); spu_addr = get_spu_field(spu_info, NULL); readmem(spu_addr, KVADDR, spu_data, size, "SPU struct", FAULT_ON_ERROR); id = *(int *)(spu_data + MEMBER_OFFSET("spu", "number")); ctx_addr = *(ulong *)(spu_data + MEMBER_OFFSET("spu", "ctx")); pid = *(int *)(spu_data + MEMBER_OFFSET("spu", "pid")); fprintf(fp, "%2d\t%16lx\t%16lx\t%s\t%5d\n", id, spu_addr, ctx_addr, ctx_addr ? "LOADED" : " IDLE ", pid); FREEBUF(spu_data); } } void print_node_header(int node) { fprintf(fp, "\n"); fprintf(fp, "NODE %i:\n", node); fprintf(fp, "ID\t SPUADDR \t CTXADDR \t STATE\t PID\n"); } void show_spus() { int i, j, nr_cpus, show_header, node; ulong spu_addr, addr; long offset; nr_cpus = kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS; for (i = 0; i < nr_cpus; i++) { show_header = TRUE; for (j = 0; j < NR_SPUS; j++) { addr = get_debug_field(spu[j], "spu"); readmem(addr, KVADDR, &spu_addr, sizeof(spu_addr), "show_spus spu_addr", FAULT_ON_ERROR); offset = MEMBER_OFFSET("spu", "node"); if (offset == -1) error(FATAL, "Couldn't get spu.node offset.\n"); spu_addr += offset; readmem(spu_addr, KVADDR, &node, sizeof(node), "show_spus node", FAULT_ON_ERROR); if (node == i) { if (show_header) { print_node_header(node); show_header = FALSE; } print_spu_header(spu[j]); } } } } /* * spus stands for "spu state" and shows what contexts are running in what * SPU. */ void cmd_spus() { int c; while ((c = getopt(argcnt, args, "")) != EOF) { switch(c) { default: argerrs++; break; } } if (argerrs || args[optind]) cmd_usage(pc->curcmd, SYNOPSIS); else show_spus(); } /***************************************************************************** * SPURQ COMMAND */ /* * Prints the addresses of SPU contexts on the SPU runqueue. */ void dump_spu_runq(ulong k_spu_prio) { int i, cnt; long prio_size, prio_runq_off, ctx_rq_off, jump, offset; char *u_spu_prio; ulong kvaddr, uvaddr; ulong list_head[2]; struct list_data list_data, *ld; prio_runq_off = MEMBER_OFFSET("spu_prio_array", "runq"); if (prio_runq_off == -1) error(FATAL, "Couldn't get runq offset.\n"); jump = STRUCT_SIZE("list_head"); if (jump == -1) error(FATAL, "Couldn't get list_head size.\n"); ctx_rq_off = MEMBER_OFFSET("spu_context", "rq"); if (ctx_rq_off == -1) error(FATAL, "Couldn't get rq offset.\n"); prio_size = STRUCT_SIZE("spu_prio_array"); if (prio_size == -1) error(FATAL, "Couldn't get list_head size.\n"); u_spu_prio = (char *)GETBUF(prio_size); readmem(k_spu_prio, KVADDR, u_spu_prio, prio_size, "get_runq_ctxs", FAULT_ON_ERROR); for (i = 0; i < MAX_PRIO; i++) { offset = prio_runq_off + (i * jump); kvaddr = k_spu_prio + offset; uvaddr = (ulong)u_spu_prio + offset; BCOPY((char *)uvaddr, (char *)&list_head[0], sizeof(ulong)*2); if ((list_head[0] == kvaddr) && (list_head[1] == kvaddr)) continue; fprintf(fp, "PRIO[%i]:\n", i); ld = &list_data; BZERO(ld, sizeof(struct list_data)); ld->start = list_head[0]; ld->list_head_offset = ctx_rq_off; ld->flags |= VERBOSE; ld->end = kvaddr; hq_open(); cnt = do_list(ld); if (cnt == -1) { hq_close(); FREEBUF(u_spu_prio); error(FATAL, "Couldn't walk runqueue[%i].\n", i); } hq_close(); } FREEBUF(u_spu_prio); } /* * spurq stands for "spu run queue" and shows info about the contexts * that are on the SPU run queue */ void cmd_spurq() { int c; ulong spu_prio_addr, spu_prio; long size; while ((c = getopt(argcnt, args, "")) != EOF) { switch(c) { default: argerrs++; break; } } if (argerrs || args[optind]) cmd_usage(pc->curcmd, SYNOPSIS); else { if (symbol_exists("spu_prio")) { spu_prio_addr = symbol_value("spu_prio"); readmem(spu_prio_addr, KVADDR, &spu_prio, sizeof(spu_prio), "runq_array", FAULT_ON_ERROR); dump_spu_runq(spu_prio); } else error(FATAL, "Could not get SPU run queue data.\n"); } } /********************************************************************************** * HELP TEXTS */ char *help_spuctx[] = { SPUCTX_CMD_NAME, "shows complete info about a SPU context and its run control state", "[args]", " This command shows complete info regarding the run control state of \ a SPU context, including debug info specially saved by kdump during a crash \ event. The parameters can be the PID of the controller task, number of SPU \ bound to the context, address of struct spu of this SPU or address of \ the proper SPU context.", "\nEXAMPLES", " Show info about contexts bound to SPUs 0 and 7, and the one \ controlled by PID 1524:\n", " crash> spuctx 0 7 1524", " Dumping context fields for spu_context c00000003dcbdd80:", " state = 0", " prio = 120", " local_store = 0xc000000039055840", " rq = 0xc00000003dcbe720", " node = 0", " number = 0", " pid = 1524", " name = ", " slb_replace = 0", " mm = 0xc0000000005dd700", " timestamp = 0x10000566f", " class_0_pending = 0", " problem = 0xd000080080210000", " priv2 = 0xd000080080230000", " flags = 0", " saved_mfc_sr1_RW = 59", " saved_mfc_dar = 14987979559889612800", " saved_mfc_dsisr = 0", " saved_spu_runcntl_RW = 1", " saved_spu_status_R = 1", " saved_spu_npc_RW = 0", " Dumping context fields for spu_context c00000003dec4e80:", " state = 0", " prio = 120", " local_store = 0xc00000003b1cea40", " rq = 0xc00000003dec5820", " node = 0", " number = 7", " pid = 1538", " name = ", " slb_replace = 0", " mm = 0xc0000000005d2b80", " timestamp = 0x10000566f", " class_0_pending = 0", " problem = 0xd000080080600000", " priv2 = 0xd000080080620000", " flags = 0", " saved_mfc_sr1_RW = 59", " saved_mfc_dar = 14987979559896297472", " saved_mfc_dsisr = 0", " saved_spu_runcntl_RW = 1", " saved_spu_status_R = 1", " saved_spu_npc_RW = 0", " Dumping context fields for spu_context c00000003dcbdd80:", " state = 0", " prio = 120", " local_store = 0xc000000039055840", " rq = 0xc00000003dcbe720", " node = 0", " number = 0", " pid = 1524", " name = ", " slb_replace = 0", " mm = 0xc0000000005dd700", " timestamp = 0x10000566f", " class_0_pending = 0", " problem = 0xd000080080210000", " priv2 = 0xd000080080230000", " flags = 0", " saved_mfc_sr1_RW = 59", " saved_mfc_dar = 14987979559889612800", " saved_mfc_dsisr = 0", " saved_spu_runcntl_RW = 1", " saved_spu_status_R = 1", " saved_spu_npc_RW = 0", " "",", " Show info about context whose struct spu_context address is \ 0xc00000003dcbed80 and the one bound to SPU whose struct spu address is \ 0xc000000001faca80:\n", " crash> spuctx 0x 0xc000000001faca80", " ...", NULL }; char *help_spus[] = { SPUS_CMD_NAME, "shows SPU contexts running on each SPE", " ", " This command shows info about all the SPU contexts bound to a SPU. \ No parameter is needed.", "\nEXAMPLE", " Show SPU contexts:\n", " crash> spus", " NODE 0:", " ID SPUADDR CTXADDR STATE PID", " 0 c000000001fac880 c00000003dcbdd80 LOADED 1524", " 1 c000000001faca80 c00000003bf34e00 LOADED 1528", " 2 c000000001facc80 c00000003bf30e00 LOADED 1525", " 3 c000000001face80 c000000039421d00 LOADED 1533", " 4 c00000003ee29080 c00000003dec3e80 LOADED 1534", " 5 c00000003ee28e80 c00000003bf32e00 LOADED 1526", " 6 c00000003ee28c80 c000000039e5e700 LOADED 1522", " 7 c00000003ee2e080 c00000003dec4e80 LOADED 1538", "", " NODE 1:", " ID SPUADDR CTXADDR STATE PID", " 8 c00000003ee2de80 c00000003dcbed80 LOADED 1529", " 9 c00000003ee2dc80 c00000003bf39e00 LOADED 1535", " 10 c00000003ee2da80 c00000003bf3be00 LOADED 1521", " 11 c000000001fad080 c000000039420d00 LOADED 1532", " 12 c000000001fad280 c00000003bf3ee00 LOADED 1536", " 13 c000000001fad480 c00000003dec2e80 LOADED 1539", " 14 c000000001fad680 c00000003bf3ce00 LOADED 1537", " 15 c000000001fad880 c00000003dec6e80 LOADED 1540", NULL }; char *help_spurq[] = { SPURQ_CMD_NAME, "shows SPU contexts on the runqueue", " ", " This command shows info about all the SPU contexts waiting for \ execution in the processor. No parameter is needed.", "\nEXAMPLE", " Show SPU runqueue:\n", " crash> spurq", " PRIO[120]:", " c000000000fd7380", " c00000003bf31e00", " PRIO[125]:", " c000000039422d00", " c00000000181eb80", NULL };
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility