Thanks in advance,
------------------------------------------------------------------------
/* 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