Your message dated Tue, 09 Jul 2013 21:33:30 +0000
with message-id <[email protected]>
and subject line Bug#584119: fixed in crash 7.0.1-1
has caused the Debian Bug report #584119,
regarding crash: [patch] SPU inspection support for powerpc
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
584119: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=584119
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: crash
Version: 5.0.4-1
Severity: wishlist
Tags: patch
User: [email protected]
Usertags: origin-ubuntu maverick ubuntu-patch

Hello,

In Ubuntu, we've applied the attached patch to achieve the following:

debian/patches/01_spu_commands.patch
  + Provides SPU extension support
debian/rules:
 + Enable SPU on PPC

We thought you might be interested in doing the same. 

Cheers,
 Michael

-- System Information:
Debian Release: squeeze/sid
  APT prefers maverick-updates
  APT policy: (500, 'maverick-updates'), (500, 'maverick-proposed'), (500, 
'maverick')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.34-4-generic (SMP w/2 CPU cores)
Locale: LANG=en_DK.utf8, LC_CTYPE=en_DK.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff -u crash-5.0.4/debian/rules crash-5.0.4/debian/rules
--- crash-5.0.4/debian/rules
+++ crash-5.0.4/debian/rules
@@ -3,10 +3,15 @@
 # Uncomment this to turn on verbose mode.
 export DH_VERBOSE=1
 
-
 %:
 	dh --with quilt $@
 
+override_dh_auto_build:
+	dh_auto_build
+ifneq (,$(filter $(DEB_BUILD_ARCH), powerpc ppc64))
+	$(MAKE) extensions
+endif
+
 override_dh_auto_clean:
 	cp $(CURDIR)/Makefile $(CURDIR)/debian/Makefile.ori
 	dh_auto_clean
@@ -23,5 +28,8 @@
 	dh_auto_install
 	cp $(CURDIR)/debian/Makefile.ori $(CURDIR)/Makefile
-
+ifneq (,$(filter $(DEB_BUILD_ARCH), powerpc ppc64))
+	mkdir -p debian/crash/usr/lib/crash/extensions
+	cp -p extensions/spu.so debian/crash/usr/lib/crash/extensions/
+endif
 override_dh_auto_test:
 	# Crash does not provide a testsuite
diff -u crash-5.0.4/debian/changelog crash-5.0.4/debian/changelog
diff -u crash-5.0.4/debian/patches/series crash-5.0.4/debian/patches/series
--- crash-5.0.4/debian/patches/series
+++ crash-5.0.4/debian/patches/series
@@ -1,0 +2 @@
+01_spu_commands.patch
only in patch2:
unchanged:
--- crash-5.0.4.orig/debian/patches/01_spu_commands.patch
+++ crash-5.0.4/debian/patches/01_spu_commands.patch
@@ -0,0 +1,1042 @@
+## 01_spu_commands.dpatch by Mathias Klose
+
+
+diff -urNad crash-4.0-4.9-1ubuntu1~/Makefile crash-4.0-4.9-1ubuntu1/Makefile
+--- crash-4.0-4.9-1ubuntu1~/Makefile	2007-11-20 18:53:17.000000000 -0600
++++ crash-4.0-4.9-1ubuntu1/Makefile	2007-11-20 19:06:57.000000000 -0600
+@@ -136,7 +136,8 @@
+         ${EXTENSIONS}/libsial/sial_var.c \
+         ${EXTENSIONS}/libsial/sial.y \
+         ${EXTENSIONS}/sial.c \
+-        ${EXTENSIONS}/sial.mk
++        ${EXTENSIONS}/sial.mk \
++        ${EXTENSIONS}/spu.c
+ 
+ DAEMON_OBJECT_FILES=remote_daemon.o va_server.o va_server_v1.o \
+ 	lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \
+diff -urNad crash-4.0-4.9-1ubuntu1~/extensions/Makefile crash-4.0-4.9-1ubuntu1/extensions/Makefile
+--- crash-4.0-4.9-1ubuntu1~/extensions/Makefile	2007-11-20 18:53:17.000000000 -0600
++++ crash-4.0-4.9-1ubuntu1/extensions/Makefile	2007-11-20 19:02:42.000000000 -0600
+@@ -45,3 +45,7 @@
+ 	@for MAKEFILE in `grep -sl "^clean:" *.mk`; \
+ 	  do make --no-print-directory -f $$MAKEFILE clean; \
+ 	done
++
++spu.so: ../defs.h spu.c
++	gcc -nostartfiles -shared -rdynamic -o spu.so spu.c -fPIC \
++				 		-D$(TARGET) $(TARGET_CFLAGS)
+diff -urNad crash-4.0-4.9-1ubuntu1~/extensions/spu.c crash-4.0-4.9-1ubuntu1/extensions/spu.c
+--- crash-4.0-4.9-1ubuntu1~/extensions/spu.c	1969-12-31 18:00:00.000000000 -0600
++++ crash-4.0-4.9-1ubuntu1/extensions/spu.c	2007-11-20 19:11:43.000000000 -0600
+@@ -0,0 +1,1011 @@
++/* spu.c - commands for viewing Cell/B.E. SPUs data
++ *
++ * (C) Copyright 2007 IBM Corp.
++ *
++ * Author: Lucio Correia <[email protected]>
++ *
++ * 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_PROPERTY_NAME	 (64)
++#define STR_SPU_INVALID		(0x0)
++#define STR_SPU_ID		(0x1)
++#define STR_SPU_PID		(0x2)
++#define STR_SPU_CTX_ADDR	(0x8)
++
++#define SPUCTX_CMD_NAME "spuctx"
++#define SPUS_CMD_NAME "spus"
++#define SPURQ_CMD_NAME "spurq"
++
++struct cbe_size_table;
++struct cbe_offset_table;
++void init_cbe_size_table(void);
++void init_cbe_offset_table(void);
++ulong get_spu_addr(ulong spu_info);
++
++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
++};
++
++struct cbe_size_table {
++	long crash_spu_info;
++	long spu;
++	long spu_context;
++	long spu_prio_array;
++	long list_head;
++} cbe_size_table;
++
++struct cbe_offset_table {
++	long crash_spu_info_spu;
++	long crash_spu_info_saved_mfc_sr1_RW;
++	long crash_spu_info_saved_mfc_dar;
++	long crash_spu_info_saved_mfc_dsisr;
++	long crash_spu_info_saved_spu_runcntl_RW;
++	long crash_spu_info_saved_spu_status_R;
++	long crash_spu_info_saved_spu_npc_RW;
++
++	long spu_node;
++	long spu_number;
++	long spu_ctx;
++	long spu_pid;
++	long spu_name;
++	long spu_slb_replace;
++	long spu_mm;
++	long spu_timestamp;
++	long spu_class_0_pending;
++	long spu_problem;
++	long spu_priv2;
++	long spu_flags;
++
++	long spu_context_spu;
++	long spu_context_state;
++	long spu_context_prio;
++	long spu_context_local_store;
++	long spu_context_rq;
++
++	long spu_prio_array_runq;
++} cbe_offset_table;
++
++#define CBE_SIZE(X)			(cbe_size_table.X)
++#define CBE_OFFSET(X, Y)		(cbe_offset_table.X##_##Y)
++
++#define CBE_SIZE_INIT(X, Y) 						\
++do {									\
++	cbe_size_table.X = STRUCT_SIZE(Y);				\
++	if (cbe_size_table.X == -1)					\
++		error(FATAL, "Couldn't get %s size.\n", Y);		\
++} while(0)
++
++#define CBE_OFFSET_INIT(X, Y, Z)					\
++do {									\
++	cbe_offset_table.X = MEMBER_OFFSET(Y, Z);			\
++	if (cbe_offset_table.X == -1)					\
++		error(FATAL, "Couldn't get %s.%s offset.\n", Y, Z);	\
++} while(0)
++
++ulong spu[NR_SPUS];
++
++/*****************************************************************************
++ * INIT FUNCTIONS
++ */
++
++/*
++ * Read kernel virtual addresses of crash_spu_info data stored by kdump
++ */
++
++void init_cbe_size_table(void)
++{
++	CBE_SIZE_INIT(crash_spu_info, "crash_spu_info");
++	CBE_SIZE_INIT(spu, "spu");
++	CBE_SIZE_INIT(spu_context, "spu_context");
++	CBE_SIZE_INIT(spu_prio_array, "spu_prio_array");
++	CBE_SIZE_INIT(list_head, "list_head");
++}
++
++void init_cbe_offset_table(void)
++{
++	CBE_OFFSET_INIT(crash_spu_info_spu, "crash_spu_info", "spu");
++	CBE_OFFSET_INIT(crash_spu_info_saved_mfc_sr1_RW, "crash_spu_info",
++							"saved_mfc_sr1_RW");
++	CBE_OFFSET_INIT(crash_spu_info_saved_mfc_dar, "crash_spu_info",
++							"saved_mfc_dar");
++	CBE_OFFSET_INIT(crash_spu_info_saved_mfc_dsisr, "crash_spu_info",
++							"saved_mfc_dsisr");
++	CBE_OFFSET_INIT(crash_spu_info_saved_spu_runcntl_RW, "crash_spu_info",
++							"saved_spu_runcntl_RW");
++	CBE_OFFSET_INIT(crash_spu_info_saved_spu_status_R, "crash_spu_info",
++							"saved_spu_status_R");
++	CBE_OFFSET_INIT(crash_spu_info_saved_spu_npc_RW, "crash_spu_info",
++							"saved_spu_npc_RW");
++
++	CBE_OFFSET_INIT(spu_node, "spu", "node");
++	CBE_OFFSET_INIT(spu_number, "spu", "number");
++	CBE_OFFSET_INIT(spu_ctx, "spu", "ctx");
++	CBE_OFFSET_INIT(spu_pid, "spu", "pid");
++	CBE_OFFSET_INIT(spu_name, "spu", "name");
++	CBE_OFFSET_INIT(spu_slb_replace, "spu", "slb_replace");
++	CBE_OFFSET_INIT(spu_mm, "spu", "mm");
++	CBE_OFFSET_INIT(spu_timestamp, "spu", "timestamp");
++	CBE_OFFSET_INIT(spu_class_0_pending, "spu", "class_0_pending");
++	CBE_OFFSET_INIT(spu_problem, "spu", "problem");
++	CBE_OFFSET_INIT(spu_priv2, "spu", "priv2");
++	CBE_OFFSET_INIT(spu_flags, "spu", "flags");
++
++	CBE_OFFSET_INIT(spu_context_spu, "spu_context", "spu");
++	CBE_OFFSET_INIT(spu_context_state, "spu_context", "state");
++	CBE_OFFSET_INIT(spu_context_prio, "spu_context", "prio");
++	CBE_OFFSET_INIT(spu_context_local_store, "spu_context", "local_store");
++	CBE_OFFSET_INIT(spu_context_rq, "spu_context", "rq");
++
++	CBE_OFFSET_INIT(spu_prio_array_runq, "spu_prio_array", "runq");
++}
++
++void get_crash_spu_info(void)
++{
++	int i;
++	ulong addr;
++	long struct_size;
++
++	addr = symbol_value("crash_spu_info");
++	struct_size = CBE_SIZE(crash_spu_info);
++
++	for (i = 0; i < NR_SPUS; i++)
++		spu[i] = addr + (i * struct_size);
++}
++
++_init()
++{
++	int i, n_registered;
++	struct command_table_entry *cte;
++
++	init_cbe_size_table();
++	init_cbe_offset_table();
++
++	for (i = 0; i < NR_SPUS; i++)
++		spu[i] = 0;
++
++	register_extension(command_table);
++
++	get_crash_spu_info();
++}
++
++
++_fini() { }
++
++
++
++/*****************************************************************************
++ * BASIC FUNCTIONS
++ */
++
++
++/*
++ * Returns a pointer to the requested SPU field 
++ */
++ulong get_spu_addr(ulong spu_info)
++{
++	ulong spu_addr;
++
++	readmem(spu_info + CBE_OFFSET(crash_spu_info, spu), KVADDR, &spu_addr, 
++			sizeof(spu_addr), "get_spu_addr", FAULT_ON_ERROR);
++
++	return spu_addr;
++}
++
++
++/*****************************************************************************
++ * SPUCTX COMMAND
++ */
++
++#define DUMP_WIDTH	23
++#define DUMP_SPU_NAME							\
++do {									\
++	fprintf(fp, "  %-*s = %s\n", DUMP_WIDTH, "name", name_str);	\
++} while(0)
++
++#define DUMP_SPU_FIELD(format, field, cast)				\
++do {									\
++	offset = CBE_OFFSET(spu, field);				\
++	fprintf(fp, "  %-*s = "format"\n", DUMP_WIDTH, #field,		\
++					cast(spu_data + offset));	\
++} while(0)
++
++#define DUMP_CTX_FIELD(format, field, cast)				\
++do {									\
++	offset = CBE_OFFSET(spu_context, field);			\
++	fprintf(fp, "  %-*s = "format"\n", DUMP_WIDTH, #field,		\
++					cast(ctx_data + offset));	\
++} while(0)
++
++#define DUMP_DBG_FIELD(format, field, cast)				\
++do {									\
++	offset = CBE_OFFSET(crash_spu_info, field);			\
++	fprintf(fp, "  %-*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 crash_spu_info.
++ */
++void print_ctx_info(char *ctx_data, char *spu_data, int info)
++{
++	long offset, size;
++	char *name_str, *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) {
++		offset = CBE_OFFSET(spu, name);
++		size = MAX_PROPERTY_NAME * sizeof(char);
++		name_str = (char *)GETBUF(size);
++		readmem(*(ulong *)(spu_data + offset), KVADDR, name_str, size,
++						"name_str", FAULT_ON_ERROR);
++		DUMP_SPU_NAME;
++		FREEBUF(name_str);
++
++		DUMP_SPU_FIELD("%d", node, *(int *));
++		DUMP_SPU_FIELD("%d", number, *(int *));
++		DUMP_SPU_FIELD("%d", pid, *(int *));
++		DUMP_SPU_FIELD("0x%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("0x%lx", flags, *(ulong *));
++
++		size = CBE_SIZE(crash_spu_info);
++		debug_data = (char *)GETBUF(size);
++		readmem(spu[info], KVADDR, debug_data, size, "debug_data",
++								FAULT_ON_ERROR);
++
++		DUMP_DBG_FIELD("0x%lx", saved_mfc_sr1_RW, *(ulong *));
++		DUMP_DBG_FIELD("0x%lx", saved_mfc_dar, *(ulong *));
++		DUMP_DBG_FIELD("0x%lx", saved_mfc_dsisr, *(ulong *));
++		DUMP_DBG_FIELD("0x%x", saved_spu_runcntl_RW, *(uint *));
++		DUMP_DBG_FIELD("0x%x", saved_spu_status_R, *(uint *));
++		DUMP_DBG_FIELD("0x%x", 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 = CBE_SIZE(spu_context);
++	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);
++
++	spu_addr = *(ulong *)(ctx_data + CBE_OFFSET(spu_context, spu));
++
++	if (spu_addr) {
++		size = CBE_SIZE(spu);
++		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;
++		}
++	}
++
++	fprintf(fp,"\nDumping 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 show_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 = get_spu_addr(spu[i]) + CBE_OFFSET(spu, 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 = CBE_SIZE(list_head);
++	prio_runq_off =  CBE_OFFSET(spu_prio_array, runq);
++	ctx_rq_off =  CBE_OFFSET(spu_context, rq);
++	prio_size = CBE_SIZE(spu_prio_array);
++
++	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;
++
++		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);
++			error(FATAL, "Couldn't walk the list.\n");
++		}
++
++		ctxs_size = cnt * sizeof(ulong);
++		ctxs = (ulong *)GETBUF(ctxs_size);
++
++		BZERO(ctxs, ctxs_size);
++		cnt = retrieve_list(ctxs, cnt);
++		hq_close();
++
++		for (j = 0; j < cnt; j++)
++			show_ctx_info(ctxs[j]);
++
++		FREEBUF(ctxs);
++	}
++
++	FREEBUF(u_spu_prio);
++}
++
++/*
++ * 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, 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_addr(spu[dvalue]) + CBE_OFFSET(spu, 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_addr(spu[i]) + 
++							CBE_OFFSET(spu, pid);
++				readmem(addr, KVADDR, &pid, sizeof(pid), 
++					"str_to_spuctx PID", FAULT_ON_ERROR);
++
++				if (dvalue == pid) {
++					addr = get_spu_addr(spu[i]) +
++							CBE_OFFSET(spu, 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_addr(spu[i]) + CBE_OFFSET(spu, 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 = CBE_SIZE(list_head);
++		prio_runq_off = CBE_OFFSET(spu_prio_array, runq);
++		ctx_rq_off = CBE_OFFSET(spu_context, rq);
++		prio_size = CBE_SIZE(spu_prio_array);
++
++		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;
++
++			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);
++				error(FATAL, "Couldn't walk the list.\n");
++			}
++
++			ctxs_size = cnt * sizeof(ulong);
++			ctxs = (ulong *)GETBUF(ctxs_size);
++			
++			BZERO(ctxs, ctxs_size);
++			cnt = retrieve_list(ctxs, cnt);
++			hq_close();
++
++			for (j = 0; j < cnt; j++)
++				if (hvalue == ctxs[j]) {
++					type = STR_SPU_CTX_ADDR;
++					*value = hvalue;
++					*spu_ctx = ctxs[j];
++					FREEBUF(u_spu_prio);
++					FREEBUF(ctxs);
++					return type;
++				}
++
++			FREEBUF(ctxs);
++		}
++
++		FREEBUF(u_spu_prio);
++	}
++
++	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_ID:
++			case STR_SPU_PID:
++			case STR_SPU_CTX_ADDR:
++				ctxlist[cnt++] = ctx;
++				break;
++
++			case STR_SPU_INVALID:
++				error(INFO, "Invalid SPU reference: %s\n",
++								args[optind]);
++				break;
++			}
++		}
++		else
++			error(INFO, "Invalid SPU reference: %s\n", 
++								args[optind]);
++		optind++;
++	}
++
++	if (cnt == 0)
++		error(INFO, "No valid ID, PID or context address.\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, state;
++	uint status;
++	ulong ctx_addr, spu_addr;
++	char *spu_data;
++	const char *state_str;
++
++	if (spu_info) {
++		readmem(spu_info + CBE_OFFSET(crash_spu_info, 
++			saved_spu_status_R), KVADDR, &status, sizeof(status),
++			"print_spu_header: get status", FAULT_ON_ERROR);
++
++		size = CBE_SIZE(spu);
++		spu_data = GETBUF(size);
++		spu_addr = get_spu_addr(spu_info);
++		readmem(spu_addr, KVADDR, spu_data, size, "SPU struct", 
++								FAULT_ON_ERROR);
++
++		id = *(int *)(spu_data + CBE_OFFSET(spu, number));
++		ctx_addr = *(ulong *)(spu_data + CBE_OFFSET(spu, ctx));
++		pid = *(int *)(spu_data + CBE_OFFSET(spu, pid));
++
++		readmem(ctx_addr + CBE_OFFSET(spu_context, state), KVADDR,
++			&state, sizeof(state), "print_spu_header get ctxstate",
++			FAULT_ON_ERROR);
++
++		switch (state) {
++			case 0: /* SPU_STATE_RUNNABLE */
++				state_str = "RUNNABLE";
++				break;
++
++			case 1: /* SPU_STATE_SAVED */
++				state_str = " SAVED  ";
++				break;
++
++			default:
++				state_str = "UNKNOWN ";
++		}
++
++		fprintf(fp, "%2d   %16lx   %s   %16lx   %s   %5d\n", id, 
++		    spu_addr, 
++		    status % 2 ? "RUNNING" : (ctx_addr ? "STOPPED" : "  IDLE "),
++		    ctx_addr, state_str, pid);
++
++		FREEBUF(spu_data);
++	}
++}
++
++void print_node_header(int node)
++{
++	fprintf(fp, "\n");
++	fprintf(fp, "NODE %i:\n", node);
++	fprintf(fp, "ID        SPUADDR      SPUSTATUS       CTXADDR       \
++CTXSTATE    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 = spu[j] + CBE_OFFSET(crash_spu_info, spu);
++			readmem(addr, KVADDR, &spu_addr, sizeof(spu_addr),
++					"show_spus spu_addr", FAULT_ON_ERROR);
++
++			offset = CBE_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 = CBE_OFFSET(spu_prio_array, runq);
++	jump = CBE_SIZE(list_head);
++	ctx_rq_off = CBE_OFFSET(spu_context, rq);
++	prio_size = CBE_SIZE(spu_prio_array);
++
++	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);
++		hq_close();
++
++		if (cnt == -1) {
++			FREEBUF(u_spu_prio);
++			error(FATAL, "Couldn't walk runqueue[%i].\n", i);
++		}
++	}
++
++	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",
++	"[ID | PID | CTXADDR] ...",
++ 
++	"  This command shows the fields of spu and spu_context structs for a ",
++	"SPU context, including debug info specially saved by kdump after a ",
++	"crash.",
++	"  By default, it shows info about all the contexts created by the ",
++	"system, including ones in the runqueue. To specify the contexts of ",
++	"interest, the PID of the controller task, ID of the SPU which the ",
++	"context is bound to or the address of spu_context struct can be used ",
++	"as parameters.",
++	"\nEXAMPLES",
++	"\n  Show info about contexts bound to SPUs 0 and 7, and the one ",
++	"controlled by thread whose PID is 1524:",
++	"\n    crash> spuctx 0 7 1524",
++	"\n    Dumping context fields for spu_context c00000003dcbdd80:",
++	"      state                   = 0",
++	"      prio                    = 120",
++	"      local_store             = 0xc000000039055840",
++	"      rq                      = 0xc00000003dcbe720",
++	"      node                    = 0",
++	"      number                  = 0",
++	"      pid                     = 1524",
++	"      name                    = spe",
++	"      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",
++	"\n    Dumping context fields for spu_context c00000003dec4e80:",
++	"      state                   = 0",
++	"      prio                    = 120",
++	"      local_store             = 0xc00000003b1cea40",
++	"      rq                      = 0xc00000003dec5820",
++	"      node                    = 0",
++	"      number                  = 7",
++	"      pid                     = 1538",
++	"      name                    = spe",
++	"      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",
++	"\n    Dumping context fields for spu_context c00000003dcbdd80:",
++	"      state                   = 0",
++	"      prio                    = 120",
++	"      local_store             = 0xc000000039055840",
++	"      rq                      = 0xc00000003dcbe720",
++	"      node                    = 0",
++	"      number                  = 0",
++	"      pid                     = 1524",
++	"      name                    = spe",
++	"      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",
++
++	"\n  Show info about the context whose struct spu_context address is ", 
++	"0xc00000003dcbed80:\n",
++	"crash> spuctx 0x00000003dcbed80",
++	"    ...",
++	NULL
++};
++
++
++char *help_spus[] = {
++	SPUS_CMD_NAME,
++	"shows how contexts are scheduled in the SPUs",
++	" ",
++	"  This command shows how the contexts are scheduled in the SPUs of ",
++	"each node. It provides info about the spu address, SPU status, the ",
++	"spu_context address, context state and spu_context addresses and the ",
++	"PID of controller thread for each SPU.",
++	"\nEXAMPLE",
++	"  Show SPU contexts:",
++	"\n    crash> spus",
++	"    NODE 0:",
++	"    ID        SPUADDR      SPUSTATUS       CTXADDR       CTXSTATE    PID ",
++	"     0   c000000001fac880   RUNNING   c00000003dcbdd80   RUNNABLE    1524",
++	"     1   c000000001faca80   RUNNING   c00000003bf34e00   RUNNABLE    1528",
++	"     2   c000000001facc80   RUNNING   c00000003bf30e00   RUNNABLE    1525",
++	"     3   c000000001face80   RUNNING   c000000039421d00   RUNNABLE    1533",
++	"     4   c00000003ee29080   RUNNING   c00000003dec3e80   RUNNABLE    1534",
++	"     5   c00000003ee28e80   RUNNING   c00000003bf32e00   RUNNABLE    1526",
++	"     6   c00000003ee28c80   STOPPED   c000000039e5e700    SAVED      1522",
++	"     7   c00000003ee2e080   RUNNING   c00000003dec4e80   RUNNABLE    1538",
++	"\n    NODE 1:",
++	"    ID        SPUADDR      SPUSTATUS       CTXADDR       CTXSTATE    PID ",
++	"     8   c00000003ee2de80   RUNNING   c00000003dcbed80   RUNNABLE    1529",
++	"     9   c00000003ee2dc80   RUNNING   c00000003bf39e00   RUNNABLE    1535",
++	"    10   c00000003ee2da80   RUNNING   c00000003bf3be00   RUNNABLE    1521",
++	"    11   c000000001fad080   RUNNING   c000000039420d00   RUNNABLE    1532",
++	"    12   c000000001fad280   RUNNING   c00000003bf3ee00   RUNNABLE    1536",
++	"    13   c000000001fad480   RUNNING   c00000003dec2e80   RUNNABLE    1539",
++	"    14   c000000001fad680   RUNNING   c00000003bf3ce00   RUNNABLE    1537",
++	"    15   c000000001fad880   RUNNING   c00000003dec6e80   RUNNABLE    1540",
++	NULL
++};
++
++
++char *help_spurq[] = {
++	SPURQ_CMD_NAME,
++	"shows contexts on the SPU runqueue",
++	" ",
++	"  This command shows info about all contexts waiting for execution ", 
++	"in the SPU runqueue. No parameter is needed.",
++	"\nEXAMPLE",
++	"  Show SPU runqueue:",
++	"\n    crash> spurq",
++	"    PRIO[120]:",
++	"    c000000000fd7380",
++	"    c00000003bf31e00",
++	"    PRIO[125]:",
++	"    c000000039422d00",
++	"    c00000000181eb80",
++	NULL
++};
++
only in patch2:
unchanged:
--- crash-5.0.4.orig/debian/patches/00list
+++ crash-5.0.4/debian/patches/00list
@@ -0,0 +1 @@
+01_spu_commands.dpatch

--- End Message ---
--- Begin Message ---
Source: crash
Source-Version: 7.0.1-1

We believe that the bug you reported is fixed in the latest version of
crash, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Troy Heber <[email protected]> (supplier of updated crash package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Format: 1.8
Date: Tue, 18 Jun 2013 13:38:49 -0600
Source: crash
Binary: crash
Architecture: source amd64
Version: 7.0.1-1
Distribution: unstable
Urgency: low
Maintainer: Troy Heber <[email protected]>
Changed-By: Troy Heber <[email protected]>
Description: 
 crash      - kernel debugging utility, allowing gdb like syntax
Closes: 504522 584119 656132 702513 710675
Changes: 
 crash (7.0.1-1) unstable; urgency=low
 .
   * Enable armel (closes: #656132)
   * Enable s390x (closes: #710675)
   * Include the crash/defs.h header (closes: #702513)
   * Sync with the Ubuntu crash package, build crash extensions, SPU has been
     dropped (closes: #584119), lpia has been dropped (closes: #504522).
   * Fix the -I include path sequence in the extensions/eppic.mk file to
     prevent a series of "redefined" and "redeclaration" warnings when
     compiling the EPPIC extension module.
   * Address two compile-time warnings generated as a result of the
     gdb*7.6.patch.  Without the patch, there are "warning: no previous
     prototype" warnings for gdb_main_entry() and replace_ui_file_FILE().
   * Implemented a new "mod -t" option that walks through the installed modules
     and checks for non*zero values in each module's "taints" bitmask, and
     translates the bits into symbolic letters if possible, or shows the
     hexadecimal value of the bitmask if not.  In older kernels, the
     "license_gplok" field is checked, and if non*zero, its value is displayed
     in hexadecimal.  Lastly, if the "gpgsig_ok" member exists and is zero, a
     "(U)" notation will also be displayed.
    * Fixed compiler warnings generated by extensions/trace.c when compiled
      with *DFORTIFY_SOURCE=2.  Without the patch, the messages "warning:
      ignoring return value of 'mktemp', declared with attribute
      warn_unused_result", "warning: ignoring return value of 'fwrite',
      declared with attribute warn_unused_result", and "warning: 'trace_dat'
      may be used uninitialized in this function" are generated.
   * Laid down the basic infrastructure for the ARM64 backtrace facility using
     the kernel's arm64 unwind facility as a basis.  Compile*tested only.
   * Implemented the ARM64 virtual-to-physical kernel and user address
     translation functions, supporting both 2*level page tables with 64K pages,
     and 3*level page tables with 4K pages.  Also added the associated PTE
     translator function.  Compile*tested only.
   * Implemented the capability of building crash as an x86_64 binary for
     analyzing ARM64 dumpfiles on an x86_64 host, which can be done by entering
     "make target=ARM64".  After the initial build is complete, subsequent
     builds can be done by entering "make" alone.
   * Added "aarch64" to the ExclusiveArch: line in the crash.spec file.
   * Fix for the S390X "bt" command for Linux 3.10 and later kernels.  Without
     the patch, the starting stack location of the per*cpu async and panic
     stacks of active tasks would be incorrectly determined.
Checksums-Sha1: 
 45dc610e6197287876d7f00320abc93de250e578 1101 crash_7.0.1-1.dsc
 3b9233cba7b92c9df611b9827d32e93390b26717 32013795 crash_7.0.1.orig.tar.gz
 413b07bd59a802c7185fe1874dc842381326dfa1 61707 crash_7.0.1-1.diff.gz
 fe9bfcda8aa806f09bf72d745901720d7745073f 3062848 crash_7.0.1-1_amd64.deb
Checksums-Sha256: 
 55da24841cb8ec52c1948b917fc68f2b2dc0c381ab2103b775fa827986cb8aad 1101 
crash_7.0.1-1.dsc
 131c11e48d70ebaad3e2f1a019be479ca0c892a163561007becc4f3d75619deb 32013795 
crash_7.0.1.orig.tar.gz
 8ecbde6fbafa62164e6a4aff59c1c3aa91e757482b90eddbd3382fa0d48b598a 61707 
crash_7.0.1-1.diff.gz
 0a1e101ae057c56a707bb53a59e9e35fe6bf1c1464c57bc1d6bc5b4ad2193635 3062848 
crash_7.0.1-1_amd64.deb
Files: 
 010e1e317c404ca77dbf6bb383e1c520 1101 utils optional crash_7.0.1-1.dsc
 b59076aebaced87e9073328cb0a4f50a 32013795 utils optional 
crash_7.0.1.orig.tar.gz
 eefea1bdbbc2488294c7ab9dab2f2faa 61707 utils optional crash_7.0.1-1.diff.gz
 651ccd55d6f448775d7be14e88e94ffd 3062848 utils optional crash_7.0.1-1_amd64.deb

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iD8DBQFR3Hl3QOr9C+GfGI4RApumAJ0UbwnpYkoApj64Mt1hoAUhCoNDfwCfQFIR
mpkHZ/Vdpg2rT1ag+gCd018=
=d6e5
-----END PGP SIGNATURE-----

--- End Message ---

Reply via email to