Re: Can't boot benh/powerpc.git kernel

2010-11-11 Thread Jim Keniston
On Thu, 2010-11-11 at 09:06 +1100, Benjamin Herrenschmidt wrote:
> On Wed, 2010-11-10 at 11:54 -0800, Jim Keniston wrote:
> > I got Ben's linux/kernel/git/benh/powerpc.git source and built it
> > (.config file attached*).  It hangs on boot.  When I boot it with
> > loglevel=8, its last words are:
> 
> First, please try with Linus upstream. The "master" branch in my git
> tree is quite stale, and my next and merge branch are too at the moment
> as I'm still travelling. All our current stuff was merged during the
> last merge window so there's nothing "new" for you to pickup in my tree
> at the moment :-)
> 
> If the problem still occurs, I'll have a look next week.
> 
> Cheers,
> Ben.

I built from Linus's git tree, and that kernel doesn't boot, either.
(It doesn't hang, but rather panics during boot.  I can provide a
console log if you like.)

v2.6.36 and v2.6.37-rc1 boot fine for me.  I'll post my nvram-related
patches against v2.6.37-rc1.

Jim

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 0/4] More ppc64 nvram code cleanup

2010-11-11 Thread Jim Keniston
This series contains some fixups to Ben Herrenschmidt's Aug. 2 patch
set, "[RFC] Clean up ppc64 nvram code" --
http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-August/084601.html

These patches apply atop Ben's 11-patch series.
---

Jim Keniston (4):
  Handle partition names >= 12 chars
  Fix NVRAM partition list setup
  Fix nvram_create_partition() arg order
  Fix powerpc nvram init order


 arch/powerpc/kernel/nvram_64.c |   31 +++
 arch/powerpc/platforms/pseries/nvram.c |8 
 2 files changed, 15 insertions(+), 24 deletions(-)

--
Jim Keniston
IBM Linux Technology Center
Beaverton, OR

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/4] Fix powerpc nvram init order

2010-11-11 Thread Jim Keniston
Don't run pseries_nvram_init_log_partition() until after the partition
list has been initialized.  Fixes a boot-time crash.

Signed-off-by: Jim Keniston 
---

 arch/powerpc/platforms/pseries/nvram.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c 
b/arch/powerpc/platforms/pseries/nvram.c
index e3acb0b..e1a43d9 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -318,7 +318,7 @@ static int __init pseries_nvram_init_log_partition(void)

return 0;
 }
-machine_arch_initcall(pseries, pseries_nvram_init_log_partition);
+machine_late_initcall(pseries, pseries_nvram_init_log_partition);
 
 int __init pSeries_nvram_init(void)
 {

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 3/4] Fix NVRAM partition list setup

2010-11-11 Thread Jim Keniston
Simplify creation and use of the NVRAM partition list.

Signed-off-by: Jim Keniston 
---

 arch/powerpc/kernel/nvram_64.c |   26 --
 1 files changed, 8 insertions(+), 18 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index d467f8c..19122d4 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -51,7 +51,7 @@ struct nvram_partition {
unsigned int index;
 };
 
-static struct nvram_partition * nvram_part;
+static LIST_HEAD(nvram_partitions);
 
 static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
 {
@@ -196,13 +196,11 @@ static struct miscdevice nvram_dev = {
 #ifdef DEBUG_NVRAM
 static void __init nvram_print_partitions(char * label)
 {
-   struct list_head * p;
struct nvram_partition * tmp_part;

printk(KERN_WARNING "%s-\n", label);
printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
-   list_for_each(p, &nvram_part->partition) {
-   tmp_part = list_entry(p, struct nvram_partition, partition);
+   list_for_each_entry(tmp_part, &nvram_partitions, partition) {
printk(KERN_WARNING "%4d\t%02x\t%02x\t%d\t%s\n",
   tmp_part->index, tmp_part->header.signature,
   tmp_part->header.checksum, tmp_part->header.length,
@@ -250,7 +248,7 @@ int __init nvram_remove_partition(const char *name, int sig)
struct nvram_partition *part, *prev, *tmp;
int rc;
 
-   list_for_each_entry(part, &nvram_part->partition, partition) {
+   list_for_each_entry(part, &nvram_partitions, partition) {
if (part->header.signature != sig)
continue;
if (name && strncmp(name, part->header.name, 12))
@@ -269,7 +267,7 @@ int __init nvram_remove_partition(const char *name, int sig)
 
/* Merge contiguous ones */
prev = NULL;
-   list_for_each_entry_safe(part, tmp, &nvram_part->partition, partition) {
+   list_for_each_entry_safe(part, tmp, &nvram_partitions, partition) {
if (part->header.signature != NVRAM_SIG_FREE) {
prev = NULL;
continue;
@@ -333,7 +331,7 @@ loff_t __init nvram_create_partition(const char *name, int 
sig,
 
/* Find a free partition that will give us the maximum needed size 
   If can't find one that will give us the minimum size needed */
-   list_for_each_entry(part, &nvram_part->partition, partition) {
+   list_for_each_entry(part, &nvram_partitions, partition) {
if (part->header.signature != NVRAM_SIG_FREE)
continue;
 
@@ -412,7 +410,7 @@ int nvram_get_partition_size(loff_t data_index)
 {
struct nvram_partition *part;

-   list_for_each_entry(part, &nvram_part->partition, partition) {
+   list_for_each_entry(part, &nvram_partitions, partition) {
if (part->index + NVRAM_HEADER_LEN == data_index)
return (part->header.length - 1) * NVRAM_BLOCK_LEN;
}
@@ -430,7 +428,7 @@ loff_t nvram_find_partition(const char *name, int sig, int 
*out_size)
 {
struct nvram_partition *p;
 
-   list_for_each_entry(p, &nvram_part->partition, partition) {
+   list_for_each_entry(p, &nvram_partitions, partition) {
if (p->header.signature == sig &&
(!name || !strncmp(p->header.name, name, 12))) {
if (out_size)
@@ -499,7 +497,7 @@ static int __init nvram_scan_partitions(void)

memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN);
tmp_part->index = cur_index;
-   list_add_tail(&tmp_part->partition, &nvram_part->partition);
+   list_add_tail(&tmp_part->partition, &nvram_partitions);

cur_index += phead.length * NVRAM_BLOCK_LEN;
}
@@ -526,14 +524,6 @@ static int __init nvram_init(void)
return rc;
}

-   /* initialize our anchor for the nvram partition list */
-   nvram_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
-   if (!nvram_part) {
-   printk(KERN_ERR "nvram_init: Failed kmalloc\n");
-   return -ENOMEM;
-   }
-   INIT_LIST_HEAD(&nvram_part->partition);
-  
/* Get all the NVRAM partitions */
error = nvram_scan_partitions();
if (error) {

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 4/4] Handle partition names >= 12 chars

2010-11-11 Thread Jim Keniston
The name field in the nvram_header can be < 12 chars, null-terminated,
or 12 chars without the null.  Handle this safely.

Signed-off-by: Jim Keniston 
---

 arch/powerpc/kernel/nvram_64.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 19122d4..cda7c3f 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -42,6 +42,7 @@ struct nvram_header {
unsigned char signature;
unsigned char checksum;
unsigned short length;
+   /* Terminating null required only for names < 12 chars. */
char name[12];
 };
 
@@ -201,7 +202,7 @@ static void __init nvram_print_partitions(char * label)
printk(KERN_WARNING "%s-\n", label);
printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
list_for_each_entry(tmp_part, &nvram_partitions, partition) {
-   printk(KERN_WARNING "%4d\t%02x\t%02x\t%d\t%s\n",
+   printk(KERN_WARNING "%4d\t%02x\t%02x\t%d\t%12s\n",
   tmp_part->index, tmp_part->header.signature,
   tmp_part->header.checksum, tmp_part->header.length,
   tmp_part->header.name);
@@ -256,7 +257,7 @@ int __init nvram_remove_partition(const char *name, int sig)
 
/* Make partition a free partition */
part->header.signature = NVRAM_SIG_FREE;
-   sprintf(part->header.name, "");
+   strncpy(part->header.name, "", 12);
part->header.checksum = nvram_checksum(&part->header);
rc = nvram_write_header(part);
if (rc <= 0) {

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2/4] Fix nvram_create_partition() arg order

2010-11-11 Thread Jim Keniston
Use the correct arg order when calling nvram_create_partition().

Signed-off-by: Jim Keniston 
---

 arch/powerpc/platforms/pseries/nvram.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c 
b/arch/powerpc/platforms/pseries/nvram.c
index e1a43d9..4b705dc 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -292,7 +292,7 @@ static int __init pseries_nvram_init_log_partition(void)
/* Create one if we didn't find */
if (!p) {
p = nvram_create_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS,
-  NVRAM_MIN_REQ, NVRAM_MAX_REQ);
+  NVRAM_MAX_REQ, NVRAM_MIN_REQ);
/* No room for it, try to get rid of any OS partition
 * and try again
 */
@@ -301,8 +301,8 @@ static int __init pseries_nvram_init_log_partition(void)
" partition, deleting all OS partitions...");
nvram_remove_partition(NULL, NVRAM_SIG_OS);
p = nvram_create_partition(NVRAM_LOG_PART_NAME,
-  NVRAM_SIG_OS, NVRAM_MIN_REQ,
-  NVRAM_MAX_REQ);
+  NVRAM_SIG_OS, NVRAM_MAX_REQ,
+  NVRAM_MIN_REQ);
}
}
 

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2/6] nvram: Capture oops/panic reports in ibm, oops-log partition

2010-11-13 Thread Jim Keniston
Create the ibm,oops-log NVRAM partition, and capture the end of the printk
buffer in it when there's an oops or panic.  If we can't create the
ibm,oops-log partition, capture the oops/panic report in ibm,rtas-log.

Signed-off-by: Jim Keniston 
---

 arch/powerpc/platforms/pseries/nvram.c |   89 
 1 files changed, 88 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c 
b/arch/powerpc/platforms/pseries/nvram.c
index 43d5c52..6c88cda 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -16,6 +16,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -50,11 +52,32 @@ static struct os_partition rtas_log_partition = {
.index = -1
 };
 
+static struct os_partition oops_log_partition = {
+   .name = "ibm,oops-log",
+   .req_size = 4000,
+   .min_size = 2000,
+   .index = -1
+};
+
 static const char *valid_os_partitions[] = {
"ibm,rtas-log",
+   "ibm,oops-log",
NULL
 };
 
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+   enum kmsg_dump_reason reason,
+   const char *old_msgs, unsigned long old_len,
+   const char *new_msgs, unsigned long new_len);
+
+static struct kmsg_dumper nvram_kmsg_dumper = {
+   .dump = oops_to_nvram
+};
+
+/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
+static size_t oops_buf_sz;
+static char *oops_buf;
+
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
unsigned int i;
@@ -337,9 +360,36 @@ static int __init pseries_nvram_init_os_partition(struct 
os_partition *part)
return 0;
 }
 
+static void __init nvram_init_oops_partition(int rtas_partition_exists)
+{
+   int rc;
+
+   rc = pseries_nvram_init_os_partition(&oops_log_partition);
+   if (rc != 0) {
+   if (!rtas_partition_exists)
+   return;
+   pr_notice("nvram: Using %s partition to log both"
+   " RTAS errors and oops/panic reports\n",
+   rtas_log_partition.name);
+   memcpy(&oops_log_partition, &rtas_log_partition,
+   sizeof(rtas_log_partition));
+   }
+   oops_buf_sz = oops_log_partition.size - sizeof(struct err_log_info);
+   oops_buf = kmalloc(oops_buf_sz, GFP_KERNEL);
+   rc = kmsg_dump_register(&nvram_kmsg_dumper);
+   if (rc != 0) {
+   pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
+   kfree(oops_buf);
+   return;
+   }
+}
+
 static int __init pseries_nvram_init_log_partitions(void)
 {
-   (void) pseries_nvram_init_os_partition(&rtas_log_partition);
+   int rc;
+
+   rc = pseries_nvram_init_os_partition(&rtas_log_partition);
+   nvram_init_oops_partition(rc == 0);
return 0;
 }
 machine_late_initcall(pseries, pseries_nvram_init_log_partitions);
@@ -373,3 +423,40 @@ int __init pSeries_nvram_init(void)
 
return 0;
 }
+
+/*
+ * Try to capture the last capture_len bytes of the printk buffer.  Return
+ * the amount actually captured.
+ */
+static size_t capture_last_msgs(const char *old_msgs, size_t old_len,
+   const char *new_msgs, size_t new_len,
+   char *captured, size_t capture_len)
+{
+   if (new_len >= capture_len) {
+   memcpy(captured, new_msgs + (new_len - capture_len),
+   capture_len);
+   return capture_len;
+   } else {
+   /* Grab the end of old_msgs. */
+   size_t old_tail_len = min(old_len, capture_len - new_len);
+   memcpy(captured, old_msgs + (old_len - old_tail_len),
+   old_tail_len);
+   memcpy(captured + old_tail_len, new_msgs, new_len);
+   return old_tail_len + new_len;
+   }
+}
+
+/* our kmsg_dump callback */
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+   enum kmsg_dump_reason reason,
+   const char *old_msgs, unsigned long old_len,
+   const char *new_msgs, unsigned long new_len)
+{
+   static unsigned int oops_count = 0;
+   size_t text_len;
+
+   text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
+   oops_buf, oops_buf_sz);
+   (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
+   (int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
+}

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[RFC PATCH 0/6] nvram: Capture oops/panic reports in NVRAM

2010-11-13 Thread Jim Keniston
This patch series enables p Series systems to capture oops and panic
reports from the printk buffer into NVRAM, where they can be examined
after reboot using the nvram command.

Patches 1-2 implement the basic feature, and patch 4 adds compression,
so we can capture more of the printk buffer.  Patches 3 and 5-6 add
refinements.  Patch 5 is not powerpc-specific, and I plan to pursue that
independently on LKML.

This series applies atop the little bug-fix series I posted two days
ago --

"More ppc64 nvram code cleanup"
http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-November/087009.html

-- which in turn applies atop Ben Herrenschmidt's Aug. 2 patch set --

"[RFC] Clean up ppc64 nvram code"
http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-August/084601.html

My patches have been tested against 2.6.37-rc1.
---

Jim Keniston (6):
  Shrink our zlib_deflate workspace from 268K to 24K
  Slim down zlib_deflate workspace when possible
  Add compression to fit more printk output into NVRAM
  Always capture start of oops report to NVRAM
  Capture oops/panic reports in ibm,oops-log partition
  Generalize code for OS partitions in NVRAM


 arch/powerpc/include/asm/nvram.h   |3 
 arch/powerpc/include/asm/rtas.h|6 
 arch/powerpc/kernel/nvram_64.c |   31 ++
 arch/powerpc/platforms/pseries/nvram.c |  470 
 include/linux/zlib.h   |   14 +
 lib/zlib_deflate/deflate.c |   33 ++
 lib/zlib_deflate/deflate_syms.c|1 
 lib/zlib_deflate/defutil.h |   17 +
 8 files changed, 504 insertions(+), 71 deletions(-)

--
Jim Keniston
IBM Linux Technology Center
Beaverton, OR

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 3/6] nvram: Always capture start of oops report to NVRAM

2010-11-13 Thread Jim Keniston
If we don't have room to capture the entire oops report, capture as much
as possible, starting 150 chars before the "Oops:" line.

Signed-off-by: Jim Keniston 
---

 arch/powerpc/platforms/pseries/nvram.c |   91 
 1 files changed, 91 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c 
b/arch/powerpc/platforms/pseries/nvram.c
index 6c88cda..e1bc1a4 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -446,6 +446,87 @@ static size_t capture_last_msgs(const char *old_msgs, 
size_t old_len,
}
 }
 
+/* Find the last occurrence of needle in haystack, which is haystack_len 
long.*/
+static const char *strnrstr(const char *haystack, const char *needle,
+   size_t haystack_len)
+{
+   size_t needle_len = strlen(needle);
+   const char *haystack_end = haystack + haystack_len;
+   const char *prev, *next = NULL;
+   do {
+   prev = next;
+   next = strnstr(haystack, needle, haystack_len);
+   if (next) {
+   haystack = next + needle_len;
+   haystack_len = haystack_end - haystack;
+   }
+   } while (next);
+   return prev;
+}
+
+/* The preamble is the last bit of messages logged before the oops. */
+#define PREAMBLE_CHARS 150
+#define OOPS_TAG "Oops: "
+
+/*
+ * Find the beginning of the most recent oops report, back up PREAMBLE_CHARS
+ * characters, and copy up to captured_len characters from there to captured[].
+ * If we can't find the oops, just capture the end of the printk buffer,
+ * if we haven't already.
+ */
+static size_t capture_oops(const char *old_msgs, size_t old_len,
+   const char *new_msgs, size_t new_len,
+   char *captured, size_t capture_len,
+   size_t already_captured)
+{
+   const char *poops;  /* Points to the 'O' in "Oops: ..." */
+   const char *preamble;
+   const char *old_end = old_msgs + old_len;
+   const char *new_end = new_msgs + new_len;
+   size_t nc1, nc2;
+
+   if ((poops = strnrstr(new_msgs, OOPS_TAG, new_len)) != NULL) {
+   /* Oops starts in new_msgs -- the most common case. */
+   preamble = poops - PREAMBLE_CHARS;
+   if (preamble >= new_msgs) {
+   /* preamble is also in new_msgs. */
+   nc1 = min(capture_len, (size_t)(new_end - preamble));
+   memcpy(captured, preamble, nc1);
+   nc2 = 0;
+   } else {
+   /* Have to get some of the preamble from old_msgs */
+   nc1 = min((size_t)(new_msgs - preamble), old_len);
+   memcpy(captured, (old_end - nc1), nc1);
+   nc2 = min(new_len, capture_len - nc1);
+   memcpy(captured + nc1, new_msgs, nc2);
+   }
+   } else if ((poops = strnrstr(old_msgs, OOPS_TAG, old_len)) != NULL) {
+   /* Oops starts in old_msgs. */
+   preamble = poops - PREAMBLE_CHARS;
+   if (preamble < old_msgs)
+   preamble = old_msgs;
+   nc1 = min(capture_len, (size_t)(old_end - preamble));
+   memcpy(captured, preamble, nc1);
+   nc2 = min((size_t)(capture_len - nc1), new_len);
+   memcpy(captured + nc1, new_msgs, nc2);
+   } else {
+   /*
+* Either there was a VERY long oops report that scrolled
+* out of the printk buffer, or the "Oops" tag is split
+* across old_msgs and new_msgs, or oopses don't start with
+* "Oops" anymore.  Just capture as much of the last messages
+* as we think we can squeeze into NVRAM.
+*/
+   if (already_captured)
+   return already_captured;
+   nc1 = capture_last_msgs(old_msgs, old_len, new_msgs,
+   new_len, captured, capture_len);
+   nc2 = 0;
+   }
+
+   return nc1 + nc2;
+}
+
 /* our kmsg_dump callback */
 static void oops_to_nvram(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason,
@@ -457,6 +538,16 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
 
text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
oops_buf, oops_buf_sz);
+   if (reason == KMSG_DUMP_OOPS) {
+   /*
+* Ensure that we have the start of the oops report,
+* and the message(s) leading up to it.
+*/
+   const char *poops = strnrstr(oops_buf, O

[PATCH 1/6] nvram: Generalize code for OS partitions in NVRAM

2010-11-13 Thread Jim Keniston
Adapt the functions used to create and write to the RTAS-log partition
to work with any OS-type partition.

Signed-off-by: Jim Keniston 
---

 arch/powerpc/include/asm/nvram.h   |3 -
 arch/powerpc/kernel/nvram_64.c |   31 ++-
 arch/powerpc/platforms/pseries/nvram.c |  138 +++-
 3 files changed, 110 insertions(+), 62 deletions(-)

diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h
index 457a1a5..3cd90fd 100644
--- a/arch/powerpc/include/asm/nvram.h
+++ b/arch/powerpc/include/asm/nvram.h
@@ -50,7 +50,8 @@ static inline int mmio_nvram_init(void)
 
 extern loff_t nvram_create_partition(const char *name, int sig,
 int req_size, int min_size);
-extern int nvram_remove_partition(const char *name, int sig);
+extern int nvram_remove_partition(const char *name, int sig,
+   const char *exceptions[]);
 extern int nvram_get_partition_size(loff_t data_index);
 extern loff_t nvram_find_partition(const char *name, int sig, int *out_size);
 
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index cda7c3f..3de46cd 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -237,22 +237,45 @@ static unsigned char __init nvram_checksum(struct 
nvram_header *p)
return c_sum;
 }
 
+/*
+ * Per the criteria passed via nvram_remove_partition(), should this
+ * partition be removed?  1=remove, 0=keep
+ */
+static int nvram_condemn_partition(struct nvram_partition *part,
+   const char *name, int sig, const char *exceptions[])
+{
+   if (part->header.signature != sig)
+   return 0;
+   if (name) {
+   if (strncmp(name, part->header.name, 12))
+   return 0;
+   } else if (exceptions) {
+   const char **except;
+   for (except = exceptions; *except; except++) {
+   if (!strncmp(*except, part->header.name, 12))
+   return 0;
+   }
+   }
+   return 1;
+}
+
 /**
  * nvram_remove_partition - Remove one or more partitions in nvram
  * @name: name of the partition to remove, or NULL for a
  *signature only match
  * @sig: signature of the partition(s) to remove
+ * @exceptions: When removing all partitions with a matching signature,
+ *leave these alone.
  */
 
-int __init nvram_remove_partition(const char *name, int sig)
+int __init nvram_remove_partition(const char *name, int sig,
+   const char *exceptions[])
 {
struct nvram_partition *part, *prev, *tmp;
int rc;
 
list_for_each_entry(part, &nvram_partitions, partition) {
-   if (part->header.signature != sig)
-   continue;
-   if (name && strncmp(name, part->header.name, 12))
+   if (!nvram_condemn_partition(part, name, sig, exceptions))
continue;
 
/* Make partition a free partition */
diff --git a/arch/powerpc/platforms/pseries/nvram.c 
b/arch/powerpc/platforms/pseries/nvram.c
index 4b705dc..43d5c52 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -30,17 +30,30 @@ static int nvram_fetch, nvram_store;
 static char nvram_buf[NVRW_CNT];   /* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
-static long nvram_error_log_index = -1;
-static long nvram_error_log_size = 0;
-
 struct err_log_info {
int error_type;
unsigned int seq_num;
 };
-#define NVRAM_MAX_REQ  2079
-#define NVRAM_MIN_REQ  1055
 
-#define NVRAM_LOG_PART_NAME"ibm,rtas-log"
+struct os_partition {
+   const char *name;
+   int req_size;   /* desired size, in bytes */
+   int min_size;   /* minimum acceptable size (0 means req_size) */
+   long size;  /* size of data portion of partition */
+   long index; /* offset of data portion of partition */
+};
+
+static struct os_partition rtas_log_partition = {
+   .name = "ibm,rtas-log",
+   .req_size = 2079,
+   .min_size = 1055,
+   .index = -1
+};
+
+static const char *valid_os_partitions[] = {
+   "ibm,rtas-log",
+   NULL
+};
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -134,7 +147,7 @@ static ssize_t pSeries_nvram_get_size(void)
 }
 
 
-/* nvram_write_error_log
+/* nvram_write_os_partition, nvram_write_error_log
  *
  * We need to buffer the error logs into nvram to ensure that we have
  * the failure information to decode.  If we have a severe error there
@@ -156,48 +169,55 @@ static ssize_t pSeries_nvram_get_size(void)
  * The 'data' section would look like (in bytes):
  * +--++---+
  * | event_logged | seq

[PATCH 4/6] nvram: Add compression to fit more printk output into NVRAM

2010-11-13 Thread Jim Keniston
Capture more than twice as much text from the printk buffer, and
compress it to fit it in the ibm,oops-log NVRAM partition.

Signed-off-by: Jim Keniston 
---

 arch/powerpc/include/asm/rtas.h|6 +
 arch/powerpc/platforms/pseries/nvram.c |  195 
 2 files changed, 177 insertions(+), 24 deletions(-)

diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index 3d35f8a..6e0f4b5 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -205,10 +205,12 @@ extern void pSeries_log_error(char *buf, unsigned int 
err_type, int fatal);
 #define ERR_FLAG_ALREADY_LOGGED0x0
 #define ERR_FLAG_BOOT  0x1 /* log was pulled from NVRAM on boot */
 #define ERR_TYPE_RTAS_LOG  0x2 /* from rtas event-scan */
-#define ERR_TYPE_KERNEL_PANIC  0x4 /* from panic() */
+#define ERR_TYPE_KERNEL_PANIC  0x4 /* from die()/panic() */
+#define ERR_TYPE_KERNEL_PANIC_GZ 0x8   /* ditto, compressed */
 
 /* All the types and not flags */
-#define ERR_TYPE_MASK  (ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC)
+#define ERR_TYPE_MASK \
+   (ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC | ERR_TYPE_KERNEL_PANIC_GZ)
 
 #define RTAS_DEBUG KERN_DEBUG "RTAS: "
  
diff --git a/arch/powerpc/platforms/pseries/nvram.c 
b/arch/powerpc/platforms/pseries/nvram.c
index e1bc1a4..8e5ed74 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -17,7 +17,10 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -74,9 +77,24 @@ static struct kmsg_dumper nvram_kmsg_dumper = {
.dump = oops_to_nvram
 };
 
-/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
-static size_t oops_buf_sz;
-static char *oops_buf;
+/*
+ * big_oops_buf[] holds the uncompressed text we're capturing.  little_oops_buf
+ * holds the compressed text, plus its length.  little_oops_buf gets written
+ * to NVRAM.
+ *
+ * We preallocate these buffers during init to avoid kmalloc during oops/panic.
+ */
+static size_t big_oops_buf_sz, little_oops_buf_sz;
+static char *big_oops_buf;
+
+static struct oops_parition_data {
+#define OOPS_PTN_PREFIX_SZ sizeof(unsigned short)
+   unsigned short length;
+   char buf[0];
+} *little_oops_buf;
+
+#define COMPR_LEVEL 6
+static struct z_stream_s stream;
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -374,13 +392,42 @@ static void __init nvram_init_oops_partition(int 
rtas_partition_exists)
memcpy(&oops_log_partition, &rtas_log_partition,
sizeof(rtas_log_partition));
}
-   oops_buf_sz = oops_log_partition.size - sizeof(struct err_log_info);
-   oops_buf = kmalloc(oops_buf_sz, GFP_KERNEL);
+
+   little_oops_buf_sz = oops_log_partition.size - OOPS_PTN_PREFIX_SZ;
+   little_oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
+   if (!little_oops_buf) {
+   pr_err("nvram: No memory for %s partition\n",
+   oops_log_partition.name);
+   return;
+   }
+   /*
+* Figure compression (preceded by elimination of each line's 
+* severity prefix) will reduce the oops/panic report to at most
+* 45% of its original size.
+*/
+   big_oops_buf_sz = (little_oops_buf_sz * 100) / 45;
+   big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
+   if (big_oops_buf) {
+   stream.workspace = vmalloc(zlib_deflate_workspacesize());
+   if (!stream.workspace) {
+   pr_err("nvram: No memory for compression workspace; "
+   "skipping compression of %s partition data\n",
+   oops_log_partition.name);
+   kfree(big_oops_buf);
+   big_oops_buf = NULL;
+   }
+   } else {
+   pr_err("No memory for uncompressed %s data; "
+   "skipping compression\n", oops_log_partition.name);
+   stream.workspace = NULL;
+   }
+
rc = kmsg_dump_register(&nvram_kmsg_dumper);
if (rc != 0) {
pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
-   kfree(oops_buf);
-   return;
+   kfree(little_oops_buf);
+   kfree(big_oops_buf);
+   vfree(stream.workspace);
}
 }
 
@@ -527,7 +574,105 @@ static size_t capture_oops(const char *old_msgs, size_t 
old_len,
return nc1 + nc2;
 }
 
-/* our kmsg_dump callback */
+/*
+ * For a panic, capture the last capture_len chars of the printk buffer.
+ * For an oops, ensure that we have the start of the oops report, and the
+ * message(s) leading up to it.
+ */
+static 

[PATCH 6/6] nvram: Shrink our zlib_deflate workspace from 268K to 24K

2010-11-13 Thread Jim Keniston
Exploit zlib_deflate_workspacesize2() to create a much smaller
zlib_deflate workspace when capturing oops/panic reports to NVRAM.

Signed-off-by: Jim Keniston 
---

 arch/powerpc/platforms/pseries/nvram.c |   11 +++
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c 
b/arch/powerpc/platforms/pseries/nvram.c
index 8e5ed74..6409cb6 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -17,7 +17,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -94,6 +93,8 @@ static struct oops_parition_data {
 } *little_oops_buf;
 
 #define COMPR_LEVEL 6
+#define WINDOW_BITS 12
+#define MEM_LEVEL 4
 static struct z_stream_s stream;
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
@@ -408,7 +409,8 @@ static void __init nvram_init_oops_partition(int 
rtas_partition_exists)
big_oops_buf_sz = (little_oops_buf_sz * 100) / 45;
big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
if (big_oops_buf) {
-   stream.workspace = vmalloc(zlib_deflate_workspacesize());
+   stream.workspace = kmalloc(zlib_deflate_workspacesize2(
+   WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
if (!stream.workspace) {
pr_err("nvram: No memory for compression workspace; "
"skipping compression of %s partition data\n",
@@ -427,7 +429,7 @@ static void __init nvram_init_oops_partition(int 
rtas_partition_exists)
pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
kfree(little_oops_buf);
kfree(big_oops_buf);
-   vfree(stream.workspace);
+   kfree(stream.workspace);
}
 }
 
@@ -625,7 +627,8 @@ static int nvram_compress(const void *in, void *out, size_t 
inlen,
int err, ret;
 
ret = -EIO;
-   err = zlib_deflateInit(&stream, COMPR_LEVEL);
+   err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
+   MEM_LEVEL, Z_DEFAULT_STRATEGY);
if (err != Z_OK)
goto error;
 

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 5/6] nvram: Slim down zlib_deflate workspace when possible

2010-11-13 Thread Jim Keniston
Instead of always creating a huge (268K) deflate_workspace with the
maximum compression parameters (windowBits=15, memLevel=8), allow the
caller to obtain a smaller workspace (24K in our case) by specifying
smaller parameter values -- via zlib_deflate_workspacesize2(). In our
case, a small workspace is a win because our choices are to allocate
the workspace when we need it (i.e., during an oops or panic) or
allocate it at boot time.  (We do the latter.)

Signed-off-by: Jim Keniston 
---

 include/linux/zlib.h|   14 --
 lib/zlib_deflate/deflate.c  |   33 -
 lib/zlib_deflate/deflate_syms.c |1 +
 lib/zlib_deflate/defutil.h  |   17 +
 4 files changed, 58 insertions(+), 7 deletions(-)

diff --git a/include/linux/zlib.h b/include/linux/zlib.h
index 40c49cb..3f15036 100644
--- a/include/linux/zlib.h
+++ b/include/linux/zlib.h
@@ -179,11 +179,21 @@ typedef z_stream *z_streamp;
 
 /* basic functions */
 
+extern int zlib_deflate_workspacesize2 (int windowBits, int memLevel);
+/*
+   Returns the number of bytes that needs to be allocated for a per-
+   stream workspace with the specified parameters.  A pointer to this
+   number of bytes should be returned in stream->workspace before
+   calling zlib_deflateInit2(); and the windowBits and memLevel
+   parameters passed to zlib_deflateInit2() must not exceed those
+   passed here.
+*/
+
 extern int zlib_deflate_workspacesize (void);
 /*
Returns the number of bytes that needs to be allocated for a per-
-   stream workspace.  A pointer to this number of bytes should be
-   returned in stream->workspace before calling zlib_deflateInit().
+   stream workspace with the default (large) windowBits and memLevel
+   parameters.
 */
 
 /* 
diff --git a/lib/zlib_deflate/deflate.c b/lib/zlib_deflate/deflate.c
index 46a31e5..cdb207a 100644
--- a/lib/zlib_deflate/deflate.c
+++ b/lib/zlib_deflate/deflate.c
@@ -176,6 +176,7 @@ int zlib_deflateInit2(
 deflate_state *s;
 int noheader = 0;
 deflate_workspace *mem;
+char *next;
 
 ush *overlay;
 /* We overlay pending_buf and d_buf+l_buf. This works since the average
@@ -199,6 +200,21 @@ int zlib_deflateInit2(
strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
 return Z_STREAM_ERROR;
 }
+
+/*
+ * Direct the workspace's pointers to the chunks that were allocated
+ * along with the deflate_workspace struct.
+ */
+next = (char *) mem;
+next += sizeof(*mem);
+mem->window_memory = (Byte *) next;
+next += zlib_deflate_window_memsize(windowBits);
+mem->prev_memory = (Pos *) next;
+next += zlib_deflate_prev_memsize(windowBits);
+mem->head_memory = (Pos *) next;
+next += zlib_deflate_head_memsize(memLevel);
+mem->overlay_memory = next;
+
 s = (deflate_state *) &(mem->deflate_memory);
 strm->state = (struct internal_state *)s;
 s->strm = strm;
@@ -1249,5 +1265,20 @@ static block_state deflate_slow(
 
 int zlib_deflate_workspacesize(void)
 {
-return sizeof(deflate_workspace);
+return zlib_deflate_workspacesize2(MAX_WBITS, MAX_MEM_LEVEL);
+}
+
+int zlib_deflate_workspacesize2(int windowBits, int memLevel)
+{
+if (windowBits < 0) /* undocumented feature: suppress zlib header */
+windowBits = -windowBits;
+if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+windowBits < 9 || windowBits > 15)
+return -1;
+
+return sizeof(deflate_workspace)
++ zlib_deflate_window_memsize(windowBits)
++ zlib_deflate_prev_memsize(windowBits)
++ zlib_deflate_head_memsize(memLevel)
++ zlib_deflate_overlay_memsize(memLevel);
 }
diff --git a/lib/zlib_deflate/deflate_syms.c b/lib/zlib_deflate/deflate_syms.c
index ccfe25f..cdf1cdd 100644
--- a/lib/zlib_deflate/deflate_syms.c
+++ b/lib/zlib_deflate/deflate_syms.c
@@ -11,6 +11,7 @@
 #include 
 
 EXPORT_SYMBOL(zlib_deflate_workspacesize);
+EXPORT_SYMBOL(zlib_deflate_workspacesize2);
 EXPORT_SYMBOL(zlib_deflate);
 EXPORT_SYMBOL(zlib_deflateInit2);
 EXPORT_SYMBOL(zlib_deflateEnd);
diff --git a/lib/zlib_deflate/defutil.h b/lib/zlib_deflate/defutil.h
index 6b15a90..b640b64 100644
--- a/lib/zlib_deflate/defutil.h
+++ b/lib/zlib_deflate/defutil.h
@@ -241,12 +241,21 @@ typedef struct deflate_state {
 typedef struct deflate_workspace {
 /* State memory for the deflator */
 deflate_state deflate_memory;
-Byte window_memory[2 * (1 << MAX_WBITS)];
-Pos prev_memory[1 << MAX_WBITS];
-Pos head_memory[1 << (MAX_MEM_LEVEL + 7)];
-char overlay_memory[(1 << (MAX_MEM_LEVEL + 6)) * (sizeof(ush)+2)];
+Byte *window_memory;
+Pos *prev_memory;
+Pos *head_memory;
+char *overlay_memory;
 } deflate_workspace;
 
+#define zlib_deflate_window_memsize(windowBits) \
+   (2 * (1 << (windowBits)) * sizeof(Byte))
+#define zlib_deflate_prev_memsize(windo

Re: [RFC PATCH 0/6] nvram: Capture oops/panic reports in NVRAM

2010-11-13 Thread Jim Keniston
On Sat, 2010-11-13 at 20:15 -0800, Jim Keniston wrote:
> This patch series enables p Series systems to capture oops and panic
> reports from the printk buffer into NVRAM, where they can be examined
> after reboot using the nvram command.
> 

Here's a patch to the nvram command to add --unzip and --ascii options,
for examination of oops/panic reports captured in ibm,oops-log or
ibm,rtas-log.

The nvram command is part of powerpc-utils --
git://powerpc-utils.git.sourceforge.net/gitroot/powerpc-utils/powerpc-utils

You can build it using
cc nvram.c -ldl -lz -o nvram

BTW, as far as I can tell, the zlib_deflate code in the kernel can't
produce the header that the gunzip command wants -- hence the reliance
on libz in the nvram command.

Jim
---

 src/nvram.c |  136 +++
 1 files changed, 136 insertions(+), 0 deletions(-)

diff --git a/src/nvram.c b/src/nvram.c
index d25e073..e00ae12 100644
--- a/src/nvram.c
+++ b/src/nvram.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "nvram.h"
 
@@ -62,6 +63,8 @@ static struct option long_options[] = {
 {"print-event-scan",   no_argument,   NULL, 'E'},
 {"partitions", no_argument,   NULL, 'P'},
 {"dump",   required_argument, NULL, 'd'},
+{"ascii",  required_argument, NULL, 'a'},
+{"unzip",  required_argument, NULL, 'z'},
 {"nvram-file", required_argument, NULL, 'n'},
 {"nvram-size", required_argument, NULL, 's'},
 {"update-config",  required_argument, NULL, 'u'},
@@ -99,6 +102,10 @@ help(void)
 "  print NVRAM paritition header info\n"
 "  --dump \n"
 "  raw dump of partition (use --partitions to see names)\n"
+"  --ascii \n"
+"  print partition contents as ASCII text\n"
+"  --unzip \n"
+"  decompress and print compressed data from partition\n"
 "  --nvram-file \n"
 "  specify alternate nvram data file (default is /dev/nvram)\n"
 "  --nvram-size\n"
@@ -1189,6 +1196,121 @@ dump_raw_partition(struct nvram *nvram, char *name)
 }
 
 /**
+ * dump_ascii_partition
+ * @brief ASCII data dump of a partition, excluding header
+ *
+ * @param nvram nvram struct containing partition
+ * @param name name of partition to dump
+ * @return 0 on success, !0 otherwise
+ *
+ * Partition subheaders, if any, are dumped along with the rest of the data.
+ * We substitute periods for unprintable characters.
+ */
+int
+dump_ascii_partition(struct nvram *nvram, char *name)
+{
+struct partition_header *phead;
+char *start, *end, *c;
+
+phead = nvram_find_partition(nvram, 0, name, NULL);
+if (!phead) {
+   err_msg("there is no %s partition!\n", name);
+   return -1;
+}
+
+start = (char*) phead;
+end = start + phead->length * NVRAM_BLOCK_SIZE;
+start += sizeof(*phead);   /* Skip partition header. */
+for (c = start; c < end; c++) {
+   if (isprint(*c) || isspace(*c))
+   putchar(*c);
+   else
+   putchar('.');
+}
+/* Always end with a newline.*/
+putchar('\n');
+return 0;
+}
+
+int
+dump_zipped_text(char *zipped_text, unsigned int zipped_length)
+{
+z_stream strm;
+int result;
+char unzipped_text[4096];
+
+strm.zalloc = Z_NULL;
+strm.zfree = Z_NULL;
+strm.opaque = Z_NULL;
+strm.avail_in = zipped_length;
+strm.next_in = zipped_text;
+result = inflateInit(&strm);
+if (result != Z_OK) {
+   err_msg("can't decompress text: inflateInit() returned %d\n", result);
+   return -1;
+}
+
+do {
+   strm.avail_out = 4096;
+   strm.next_out = unzipped_text;
+   result = inflate(&strm, Z_NO_FLUSH);
+   switch (result) {
+   case Z_STREAM_ERROR:
+   case Z_NEED_DICT:
+   case Z_DATA_ERROR:
+   case Z_MEM_ERROR:
+   err_msg("can't decompress text: inflate() returned %d\n", result);
+   (void) inflateEnd(&strm);
+   return -1;
+   }
+   if (fwrite(unzipped_text, 4096 - strm.avail_out, 1, stdout) != 1) {
+   err_msg("can't decompress text: fwrite() failed\n");
+   (void) inflateEnd(&strm);
+   return -1;
+   }
+} while (strm.avail_out == 0);
+
+(void) inflateEnd(&strm);
+return 0;
+}
+
+/**
+ * unzip_partition
+ * @brief Uncompress and print compressed data from a partition.
+ *
+ * @param nvram nvram struct containing partition
+ * @param name name of partition to dump
+ * @return 0 on success, !0 ot

Re: Can't boot benh/powerpc.git kernel

2010-11-16 Thread Jim Keniston
On Tue, 2010-11-16 at 14:26 +1100, Michael Neuling wrote:
> In message <1289520464.4752.12.ca...@localhost> you wrote:
> > On Thu, 2010-11-11 at 09:06 +1100, Benjamin Herrenschmidt wrote:
> > > On Wed, 2010-11-10 at 11:54 -0800, Jim Keniston wrote:
> > > > I got Ben's linux/kernel/git/benh/powerpc.git source and built it
> > > > (.config file attached*).  It hangs on boot.  When I boot it with
> > > > loglevel=8, its last words are:
> > > 
> > > First, please try with Linus upstream. The "master" branch in my git
> > > tree is quite stale, and my next and merge branch are too at the moment
> > > as I'm still travelling. All our current stuff was merged during the
> > > last merge window so there's nothing "new" for you to pickup in my tree
> > > at the moment :-)
> > > 
> > > If the problem still occurs, I'll have a look next week.
> > > 
> > > Cheers,
> > > Ben.
> > 
> > I built from Linus's git tree, and that kernel doesn't boot, either.
> > (It doesn't hang, but rather panics during boot.  I can provide a
> > console log if you like.)
> 
> Yes please.  
> 
> Linus' tree with pseries_defconfig boots fine for me on my POWER5 box.
> 
> > v2.6.36 and v2.6.37-rc1 boot fine for me.  I'll post my nvram-related
> > patches against v2.6.37-rc1.
> 
> So it's broken between 37-rc1 and whereever you grabbed Linus tree.
> That's a fairly small window.  Can you bisect it?

I was apparently comparing apples to oranges.  Given the fatal
configuration options (DEBUG_SLAB and/or DEBUG_PAGEALLOC) 2.6.37-rc1
fails the same as a more recent snapshot of Linus's tree.  I updated my
view today, and it still fails to boot with DEBUG_SLAB and/or
DEBUG_PAGEALLOC, and boots OK without them.

It also fails to boot with SLUB and SLUB_DEBUG enabled, even with
SLUB_DEBUG_ON disabled.

Ben has access to my system, and will look at it in a few days.

Jim

> 
> Mikey
> ___
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev


___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] powerpc: fix call to subpage_protection()

2010-11-18 Thread Jim Keniston
On Thu, 2010-11-18 at 13:32 +1100, Michael Neuling wrote:
> In: 
>   powerpc/mm: Fix pgtable cache cleanup with CONFIG_PPC_SUBPAGE_PROT
>   commit d28513bc7f675d28b479db666d572e078ecf182d
>   Author: David Gibson 
> 
> subpage_protection() was changed to to take an mm rather a pgdir but it
> didn't change calling site in hashpage_preload().  The change wasn't
> noticed at compile time since hashpage_preload() used a void* as the
> parameter to subpage_protection().
> 
> This is obviously wrong and can trigger the following crash when
> CONFIG_SLAB, CONFIG_DEBUG_SLAB, CONFIG_PPC_64K_PAGES
> CONFIG_PPC_SUBPAGE_PROT are enabled.
> 
...
> 
> The following changes this subpage_protection() call.
> 
> Reported-by: Jim Keniston 
> Signed-off-by: Michael Neuling 
> Tested-by: Jim Keniston 
> cc: David Gibson 
> cc: sta...@kernel.org (only 2.6.33 and newer)
> ---
> > It boots fine with pseries_defconfig.
> > 
> > Attached is the config file that I've been using, which is probably
> > descended over many generations of kernels from some config file in my
> > machine's distant past.  (Enable DEBUG_SLAB or DEBUG_PAGEALLOC and it
> > will fail to boot.)  After I run 'make menuconfig' starting from
> > pseries_defconfig...
> > $ diff config_ok .config | wc -l
> > 2052
> 
> I narrowed this down to adding the following on pseries_defconfig:
>   +CONFIG_SLAB=y
>   +CONFIG_PPC_64K_PAGES=y
>   +CONFIG_PPC_SUBPAGE_PROT=y
>   +CONFIG_DEBUG_SLAB=y
> To reproduce the fail.

I have indeed verified that when I apply those config changes atop
pseries_defconfig, the resulting kernel fails to boot on my Power 5
system without this fix, and boots correctly with this fix.  So the
Tested-by line is correct.

Unfortunately, this fix doesn't enable my legacy configuration to boot
with CONFIG_SLAB=y.  It still fails in the same way -- console output
attached.

FWIW, this failure isn't an obstacle for me.  I'm in no way attached to
my legacy configuration; pseries_defconfig is fine for me.  On the other
hand, I can continue testing fixes, and/or make my system available to
other IBMers when I'm not using it, if you want to continue to pursue
this problem.

Thanks.
Jim

>   
> 
> diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
> index 83f534d..5e95844 100644
> --- a/arch/powerpc/mm/hash_utils_64.c
> +++ b/arch/powerpc/mm/hash_utils_64.c
> @@ -1123,7 +1123,7 @@ void hash_preload(struct mm_struct *mm, unsigned long 
> ea,
>   else
>  #endif /* CONFIG_PPC_HAS_HASH_64K */
>   rc = __hash_page_4K(ea, access, vsid, ptep, trap, local, ssize,
> - subpage_protection(pgdir, ea));
> + subpage_protection(mm, ea));
> 
>   /* Dump some info in case of hash insertion failure, they should
>* never happen so it is really useful to know if/when they do
> 
> 

This is with Michael Neuling's subpage_protection fix, using my legacy
.config DEBUG_SLAB configured.

boot: linus
Using 0084e28a bytes for initrd buffer
Please wait, loading kernel...
Allocated 00f0 bytes for kernel @ 01e0
   Elf64 kernel loaded...
Loading ramdisk...
ramdisk loaded 0084e28a @ 02d0
OF stdout device is: /vdevice/v...@3000
Preparing to boot Linux version 2.6.37-rc2-5-ppc64 (j...@elm3b90) (gcc version 
4.3.2 [gcc-4_3-branch revision 141291] (SUSE Linux) ) #9 SMP Wed Nov 17 
18:17:23 PST 2010
Max number of cores passed to firmware: 512 (NR_CPUS = 1024)
Calling ibm,client-architecture-support... not implemented
command line: 
root=/dev/disk/by-id/scsi-SIBM_ST373453LC_3HW1CQ147445Q2A4-part3 quiet 
profile=2 sysrq=1 insmod=sym53c8xx insmod=ipr crashkernel=256M-:128M loglevel=8 
memory layout at init:
  memory_limit :  (16 MB aligned)
  alloc_bottom : 0355
  alloc_top: 0800
  alloc_top_hi : 7000
  amo_top  : 0800
  ram_top  : 7000
instantiating rtas at 0x076a... done
boot cpu hw idx 0
starting cpu hw idx 2... done
copying OF device tree...
Building dt strings...
Building dt structure...
Device tree strings 0x0356 -> 0x0356129c
Device tree struct  0x0357 -> 0x0358
Calling quiesce...
returning from prom_init
Crash kernel location must be 0x200
Reserving 128MB of memory at 32MB for crashkernel (System RAM: 1792MB)
Phyp-dump not supported on this hardware
Allocated 655360 bytes for 1024 pacas at c1f3
Using pSeries machine description
Page orders: linear mapping = 24, virtual = 12, io = 12
Found initrd at 0xc2d0:0xc354e28a
bootconsole [udbg0] enabled
Partition configured for 4 cpus.
CPU maps initialized for 2 threa

Re: [PATCH] powerpc: fix call to subpage_protection()

2010-11-30 Thread Jim Keniston
On Tue, 2010-11-30 at 05:08 -0600, Milton Miller wrote:
> [fixed Michael Neuling's address]
> 
> On Fri Nov 19 about 07:06:19 EST in 2010, Benjamin Herrenschmidt wrote:
> > On Thu, 2010-11-18 at 10:23 -0800, Jim Keniston wrote:
> > > FWIW, this failure isn't an obstacle for me.  I'm in no way attached to
> > > my legacy configuration; pseries_defconfig is fine for me.  On the other
> > > hand, I can continue testing fixes, and/or make my system available to
> > > other IBMers when I'm not using it, if you want to continue to pursue
> > > this problem.
> 
> > From the look of it your "legacy" config is lacking the necessary
> > storage drivers...
> > 
> 
> Looking closer, it would appear he intended to get them from initramfs
> but unpacking it failed.  Pulling from his log in the original message:

Bingo!  Not only was I using a "legacy" .config file, I'd also copied
and pasted an older yaboot.conf entry without updating the initrd-size
clause.  The initrd-size value was apparently big enough until I enabled
the extra DEBUG code.  Mr. Miller's diagnostic message reported the
unpacking failure at just a few bytes past the specified initrd-size.
Adjusting the initrd-size to match the actual size of the file enables
the kernel to boot.

So... cockpit error.  Very sorry for the fuss, but thanks for the
detective work.

As for Mr. Miller's patch...
Tested-by: Jim Keniston 

Jim

> 
> > > 
> > > Calling ibm,client-architecture-support... not implemented
> > > command line: 
> > > root=/dev/disk/by-id/scsi-SIBM_ST373453LC_3HW1CQ147445Q2A4-part3 
> > > quiet profile=2 sysrq=1 insmod=sym53c8xx insmod=ipr 
> > > crashkernel=256M-:128M loglevel=8 
> > > 
> > > memory layout at init:
> > >   memory_limit :  (16 MB aligned)
> > >   alloc_bottom : 0355
> > >   alloc_top: 0800
> > >   alloc_top_hi : 7000
> > >   amo_top  : 0800
> > >   ram_top  : 7000
> > > instantiating rtas at 0x076a... done
> > > boot cpu hw idx 0
> > > starting cpu hw idx 2... done
> > > copying OF device tree...
> > > Building dt strings...
> > > Building dt structure...
> > > Device tree strings 0x0356 -> 0x0356129c
> > > Device tree struct  0x0357 -> 0x0358
> ..
> > > Found initrd at 0xc2d0:0xc354e28a
> ..
> > > NET: Registered protocol family 1
> > > PCI: CLS 128 bytes, default 128
> > > Unpacking initramfs...
> > > Initramfs unpacking failed: read error
> 
> "read error" occurs in lib/decompress_inflate.c if the fill routine
> returns a negative count, which would inlclude a NULL fill pointer like
> init/initramfs.c.
> 
> 
> Maybe this debugging patch (against 2.6.35, applys with small offset to 
> 2.6.37-rc4) can help isolate the corruption?
> 
> From: Milton Miller 
> initramfs: show input and output offsets on unpacking failures
> 
> When the initramfs input is corrupted, having the pointer to the buffer
> segment being decompressed, and the decompress input and output byte
> counts from the compressed stream can help isolate the source of the
> corruption.
> 
> Signed-off-by: Milton Miller 
> 
> ---
>  init/initramfs.c |5 +
>  1 file changed, 5 insertions(+)
> 
> Index: sim/init/initramfs.c
> ===
> --- sim.orig/init/initramfs.c 2009-07-13 18:44:56.0 -0500
> +++ sim/init/initramfs.c  2009-07-13 18:59:32.0 -0500
> @@ -384,6 +384,9 @@ static int __init write_buffer(char *buf
>   return len - count;
>  }
> 
> +static unsigned my_inptr;   /* index of next byte to be processed in inbuf */
> +static unsigned bytes_out;  /* count of chars processed from current archive 
> */
> +
>  static int __init flush_buffer(void *bufv, unsigned len)
>  {
>   char *buf = (char *) bufv;
> @@ -393,6 +396,7 @@ static int __init flush_buffer(void *buf
>   return -1;
>   while ((written = write_buffer(buf, len)) < len && !message) {
>   char c = buf[written];
> + bytes_out += written;
>   if (c == '0') {
>   buf += written;
>   len -= written;
> @@ -407,8 +411,6 @@ static int __init flush_buffer(void *buf
>   return origLen;
>  }
> 
> -static unsigned my_inptr;   /* index of next byte to be processed in inbuf */
> -
>  

Re: [PATCH 01/13] powerpc/nvram: Move things out of asm/nvram.h

2010-11-30 Thread Jim Keniston
On Tue, 2010-11-30 at 16:47 +1100, b...@kernel.crashing.org wrote:
> From: Benjamin Herrenschmidt 
> 
> This moves a bunch of definitions out of asm/nvram.h to the files
> that use them or just outright remove completely unused stuff.
> 
> We leave the partition signatures definitions, they will be useful
> 
> Signed-off-by: Benjamin Herrenschmidt 

I applied the whole 13-patch set, and built and booted the result.
Seems fine.

Tested-by: Jim Keniston 

Jim

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 1/6] nvram: Generalize code for OS partitions in NVRAM

2011-02-09 Thread Jim Keniston
On Mon, 2011-02-07 at 15:57 +1100, Benjamin Herrenschmidt wrote:
> On Sat, 2010-11-13 at 20:15 -0800, Jim Keniston wrote:
> > Adapt the functions used to create and write to the RTAS-log partition
> > to work with any OS-type partition.
> > 
> > Signed-off-by: Jim Keniston 
> > ---
> 
> Overall pretty good (sorry for taking that long to review, I've been
> swamped down). Just a handful of minor nits:

I've appended an updated patch, which addresses your comments and also
applies to 2.6.38-rc4, rather than to your kernel as it stood on Nov.
13.  See below for responses to comments.

> 
> > +/*
> > + * Per the criteria passed via nvram_remove_partition(), should this
> > + * partition be removed?  1=remove, 0=keep
> > + */
> > +static int nvram_condemn_partition(struct nvram_partition *part,
> > +   const char *name, int sig, const char *exceptions[])
> 
> As "fun" as this name is, it didn't help me understand what the function
> was about until I read the code for the next one :-)
> 
> What about instead something like nvram_can_remove_partition() or
> something a bit more explicit like that ?

Done.

...
>  .../...
> 
> > +static const char *valid_os_partitions[] = {
> > +   "ibm,rtas-log",
> > +   NULL
> > +};
> 
> Can you pick a name that will be less confusing in the global
> symbol table ? Something like "pseries_nvram_os_partitions"

Done.

> or whatever shorter you can come up with which doesn't suck ?
> 
> Also, should we move that "os partition" core out of pseries ?
> 
> Looks like it will be useful for a few other platforms, I'd like
> to move that to a more generically useful location in arch/powerpc
> but that's not a blocker for this series but something to do next
> maybe ?

I haven't tried to do that reorganization.

> 
> In that case "struct os_partition" should also find itself a better
> name, maybe struct nvram_os_partition ?

Done.

...
> > if (rc <= 0) {
> > -   printk(KERN_ERR "nvram_write_error_log: Failed nvram_write 
> > (%d)\n", rc);
> > +   printk(KERN_ERR "nvram_write_os_partition: Failed nvram_write 
> > (%d)\n", rc);
> > return rc;
> > }
> > 
> > return 0;
> >  }
> 
> While at it, turn these into pr_err and use __FUNCTION__ or __func__

Done.  However, I didn't convert any printks in functions that I wasn't
otherwise changing.

> 
> > +int nvram_write_error_log(char * buff, int length,
> > +  unsigned int err_type, unsigned int 
> > error_log_cnt)
> > +{
> > +   return nvram_write_os_partition(&rtas_log_partition, buff, length,
> > +   err_type, error_log_cnt);
> > +}
> 
> That's a candidate for a static inline in a .h

Maybe, but in my next patch this function adjusts a static variable, so
I figure that putting it in a header would be messy.

Here's my revised patch.
Jim
=
Generalize code for OS partitions in NVRAM

Adapt the functions used to create and write to the RTAS-log partition
to work with any OS-type partition.

Signed-off-by: Jim Keniston 
---

 arch/powerpc/include/asm/nvram.h   |3 -
 arch/powerpc/kernel/nvram_64.c |   31 ++-
 arch/powerpc/platforms/pseries/nvram.c |  143 +++-
 3 files changed, 113 insertions(+), 64 deletions(-)

diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h
index 92efe67..9d1aafe 100644
--- a/arch/powerpc/include/asm/nvram.h
+++ b/arch/powerpc/include/asm/nvram.h
@@ -51,7 +51,8 @@ static inline int mmio_nvram_init(void)
 extern int __init nvram_scan_partitions(void);
 extern loff_t nvram_create_partition(const char *name, int sig,
 int req_size, int min_size);
-extern int nvram_remove_partition(const char *name, int sig);
+extern int nvram_remove_partition(const char *name, int sig,
+   const char *exceptions[]);
 extern int nvram_get_partition_size(loff_t data_index);
 extern loff_t nvram_find_partition(const char *name, int sig, int *out_size);
 
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index bb12b32..bec1e93 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -237,22 +237,45 @@ static unsigned char __init nvram_checksum(struct 
nvram_header *p)
return c_sum;
 }
 
+/*
+ * Per the criteria passed via nvram_remove_partition(), should this
+ * partition be removed?  1=remove, 0=keep
+ */
+static int nvram_can_remove_partition(struct nvram_partition *part,
+   const char *name,

Re: [PATCH 2/6] nvram: Capture oops/panic reports in ibm, oops-log partition

2011-02-09 Thread Jim Keniston
On Mon, 2011-02-07 at 16:01 +1100, Benjamin Herrenschmidt wrote:
> On Sat, 2010-11-13 at 20:15 -0800, Jim Keniston wrote:
> > Create the ibm,oops-log NVRAM partition, and capture the end of the printk
> > buffer in it when there's an oops or panic.  If we can't create the
> > ibm,oops-log partition, capture the oops/panic report in ibm,rtas-log.

I've appended an updated patch that addresses your comments and applies
to 2.6.38-rc4.

> 
> Won't the parsing tools choke on the oops log in the RTAS log
> partition ?

I don't think that that will be a problem, because pSeries_log_error()
doesn't log errors that aren't of type ERR_TYPE_RTAS_LOG.

However, I did add code to ensure that even if ibm,rtas-log is used for
both RTAS errors and oops reports, an oops report won't overwrite a
recently captured RTAS event that hasn't yet been read into the
filesystem (e.g., by rtas_errd).

> 
> Also, maybe remove the "ibm," prefix on the nvram partition, make it
> "lnx," instead.

Done.

> 
> Then, if you move the rest of the code out of pseries, you can move that
> out too, just make pseries platform code call the init code for it, that
> way other platforms can re-use that as-is.
> 
> But that later part can wait a separate patch series,

Agreed.

> just make sure you
> change the partition name now.

Still done.

> 
> Cheers,
> Ben.

Here's my revised patch.
Jim
=
Capture oops/panic reports in lnx,oops-log partition

Create the lnx,oops-log NVRAM partition, and capture the end of the printk
buffer in it when there's an oops or panic.  If we can't create the
lnx,oops-log partition, capture the oops/panic report in ibm,rtas-log.

Signed-off-by: Jim Keniston 
---

 arch/powerpc/platforms/pseries/nvram.c |  118 +++-
 1 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c 
b/arch/powerpc/platforms/pseries/nvram.c
index befb41b..419707b 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -16,6 +16,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -39,7 +41,7 @@ struct nvram_os_partition {
const char *name;
int req_size;   /* desired size, in bytes */
int min_size;   /* minimum acceptable size (0 means req_size) */
-   long size;  /* size of data portion of partition */
+   long size;  /* size of data portion (excluding err_log_info) */
long index; /* offset of data portion of partition */
 };
 
@@ -50,11 +52,35 @@ static struct nvram_os_partition rtas_log_partition = {
.index = -1
 };
 
+static struct nvram_os_partition oops_log_partition = {
+   .name = "lnx,oops-log",
+   .req_size = 4000,
+   .min_size = 2000,
+   .index = -1
+};
+
 static const char *pseries_nvram_os_partitions[] = {
"ibm,rtas-log",
+   "lnx,oops-log",
NULL
 };
 
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+   enum kmsg_dump_reason reason,
+   const char *old_msgs, unsigned long old_len,
+   const char *new_msgs, unsigned long new_len);
+
+static struct kmsg_dumper nvram_kmsg_dumper = {
+   .dump = oops_to_nvram
+};
+
+/* See clobbering_unread_rtas_event() */
+#define NVRAM_RTAS_READ_TIMEOUT 5  /* seconds */
+static unsigned long last_unread_rtas_event;   /* timestamp */
+
+/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
+static char *oops_buf;
+
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
unsigned int i;
@@ -214,8 +240,11 @@ int nvram_write_os_partition(struct nvram_os_partition 
*part, char * buff,
 int nvram_write_error_log(char * buff, int length,
   unsigned int err_type, unsigned int error_log_cnt)
 {
-   return nvram_write_os_partition(&rtas_log_partition, buff, length,
+   int rc = nvram_write_os_partition(&rtas_log_partition, buff, length,
err_type, error_log_cnt);
+   if (!rc)
+   last_unread_rtas_event = get_seconds();
+   return rc;
 }
 
 /* nvram_read_error_log
@@ -274,6 +303,7 @@ int nvram_clear_error_log(void)
printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write 
(%d)\n", rc);
return rc;
}
+   last_unread_rtas_event = 0;
 
return 0;
 }
@@ -342,9 +372,35 @@ static int __init pseries_nvram_init_os_partition(struct 
nvram_os_partition
return 0;
 }
 
+static void __init nvram_init_oops_partition(int rtas_partition_exists)
+{
+   int rc;
+
+   rc = pseries_nvram_init_os_partition(&oops_log_partition);
+   if (rc != 0) {
+   if (!rtas_partition_exists)
+ 

[PATCH] nvram: Don't overwrite oops/panic report on normal shutdown

2011-03-25 Thread Jim Keniston
For normal halt, reboot, and poweroff events, refrain from overwriting
the lnx,oops-log partition.  Also, don't save the dmesg buffer on an
emergency-restart event if we've already saved it earlier in panic().

Signed-off-by: Jim Keniston 
---

 arch/powerpc/platforms/pseries/nvram.c |   24 
 1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c 
b/arch/powerpc/platforms/pseries/nvram.c
index 419707b..00cc3a0 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -480,8 +480,32 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
const char *new_msgs, unsigned long new_len)
 {
static unsigned int oops_count = 0;
+   static bool panicking = false;
size_t text_len;
 
+   switch (reason) {
+   case KMSG_DUMP_RESTART:
+   case KMSG_DUMP_HALT:
+   case KMSG_DUMP_POWEROFF:
+   /* These are almost always orderly shutdowns. */
+   return;
+   case KMSG_DUMP_OOPS:
+   case KMSG_DUMP_KEXEC:
+   break;
+   case KMSG_DUMP_PANIC:
+   panicking = true;
+   break;
+   case KMSG_DUMP_EMERG:
+   if (panicking)
+   /* Panic report already captured. */
+   return;
+   break;
+   default:
+   pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
+   __FUNCTION__, (int) reason);
+   return;
+   }
+
if (clobbering_unread_rtas_event())
return;
 

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 0/8 userland!] systemtap: Add initial support for ppc32

2009-12-01 Thread Jim Keniston
On Sat, 2009-11-28 at 01:32 +0300, Anton Vorontsov wrote:
> Hi all,
> 
> Here are some patches that add systemtap support for ppc32 machines.
> 
> This is all pretty straightforward, though I didn't test it much,
> only run few 'hello world' taps and decided that it's good enough. ;-)
> 
> I plan to test it more thoughtfully sometime next week, and fix missing
> things (if any). But so far I'm interested in the feedback on this
> initial support.
> 
> Thanks!
> 
> p.s. I though it would be a good idea to cc linuxppc-dev. At least
> kexec-tools guys tend to do it as well.

I think one thing that got missed was completing the support for ppc32
in tapset/powerpc/registers.stp (functions *_arg and [u_]register).  A
lot of the 32-bit code is already in place, having been copied over from
the x86_64 version, but the _reg_offsets[] array and
_stp_get_register_by_offset() work only for 64-bit contexts.  A comment
at the end of _stp_register_regs() suggests that you can get the correct
32-bit offsets by dividing the 64-bit offsets by 2; compare pt_regs
structs to verify.

I'm cc-ing Ananth, who did the original ppc64 work on this file.

The *_arg and [u_]register functions are described in the stapfuncs man
page (but not in the Language Reference doc).
testsuite/systemtap.context/num_args.tcl tests some of these functions
(or used to, at least).

Jim Keniston

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] powerpc/nvram: Add compression to fit more oops output into NVRAM

2011-07-25 Thread Jim Keniston
Capture more than twice as much text from the printk buffer, and
compress it to fit it in the lnx,oops-log NVRAM partition.  You
can view the compressed text using the new (as of July 20) --unzip
option of the nvram command in the powerpc-utils package.

Signed-off-by: Jim Keniston 
---

 arch/powerpc/include/asm/rtas.h|6 +
 arch/powerpc/platforms/pseries/nvram.c |  171 +++-
 2 files changed, 168 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index 58625d1..41f69ae 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -249,10 +249,12 @@ extern void pSeries_log_error(char *buf, unsigned int 
err_type, int fatal);
 #define ERR_FLAG_ALREADY_LOGGED0x0
 #define ERR_FLAG_BOOT  0x1 /* log was pulled from NVRAM on boot */
 #define ERR_TYPE_RTAS_LOG  0x2 /* from rtas event-scan */
-#define ERR_TYPE_KERNEL_PANIC  0x4 /* from panic() */
+#define ERR_TYPE_KERNEL_PANIC  0x4 /* from die()/panic() */
+#define ERR_TYPE_KERNEL_PANIC_GZ 0x8   /* ditto, compressed */
 
 /* All the types and not flags */
-#define ERR_TYPE_MASK  (ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC)
+#define ERR_TYPE_MASK \
+   (ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC | ERR_TYPE_KERNEL_PANIC_GZ)
 
 #define RTAS_DEBUG KERN_DEBUG "RTAS: "
  
diff --git a/arch/powerpc/platforms/pseries/nvram.c 
b/arch/powerpc/platforms/pseries/nvram.c
index 00cc3a0..a76b228 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -18,6 +18,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -78,8 +80,41 @@ static struct kmsg_dumper nvram_kmsg_dumper = {
 #define NVRAM_RTAS_READ_TIMEOUT 5  /* seconds */
 static unsigned long last_unread_rtas_event;   /* timestamp */
 
-/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
-static char *oops_buf;
+/*
+ * For capturing and compressing an oops or panic report...
+
+ * big_oops_buf[] holds the uncompressed text we're capturing.
+ *
+ * oops_buf[] holds the compressed text, preceded by a prefix.
+ * The prefix is just a u16 holding the length of the compressed* text.
+ * (*Or uncompressed, if compression fails.)  oops_buf[] gets written
+ * to NVRAM.
+ *
+ * oops_len points to the prefix.  oops_data points to the compressed text.
+ *
+ * +- oops_buf
+ * |   +- oops_data
+ * v   v
+ * ++---+
+ * | length| text  |
+ * | (2 bytes) | (oops_data_sz bytes)  |
+ * ++---+
+ * ^
+ * +- oops_len
+ *
+ * We preallocate these buffers during init to avoid kmalloc during oops/panic.
+ */
+static size_t big_oops_buf_sz;
+static char *big_oops_buf, *oops_buf;
+static u16 *oops_len;
+static char *oops_data;
+static size_t oops_data_sz;
+
+/* Compression parameters */
+#define COMPR_LEVEL 6
+#define WINDOW_BITS 12
+#define MEM_LEVEL 4
+static struct z_stream_s stream;
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -387,11 +422,44 @@ static void __init nvram_init_oops_partition(int 
rtas_partition_exists)
sizeof(rtas_log_partition));
}
oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
+   if (!oops_buf) {
+   pr_err("nvram: No memory for %s partition\n",
+   oops_log_partition.name);
+   return;
+   }
+   oops_len = (u16*) oops_buf;
+   oops_data = oops_buf + sizeof(u16);
+   oops_data_sz = oops_log_partition.size - sizeof(u16);
+
+   /*
+* Figure compression (preceded by elimination of each line's 
+* severity prefix) will reduce the oops/panic report to at most
+* 45% of its original size.
+*/
+   big_oops_buf_sz = (oops_data_sz * 100) / 45;
+   big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
+   if (big_oops_buf) {
+   stream.workspace = kmalloc(zlib_deflate_workspacesize(
+   WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
+   if (!stream.workspace) {
+   pr_err("nvram: No memory for compression workspace; "
+   "skipping compression of %s partition data\n",
+   oops_log_partition.name);
+   kfree(big_oops_buf);
+   big_oops_buf = NULL;
+   }
+   } else {
+   pr_err("No memory for uncompressed %s data; "
+   "skipping compression\n", oops_log_partition.name);
+   stream.workspace = NULL;
+   }
+
rc = kmsg_dump_regis

Re: [PATCH] powerpc/nvram: Add spinlock to oops_to_nvram to prevent oops in compression code.

2011-12-01 Thread Jim Keniston
On Thu, 2011-12-01 at 12:46 +1100, Anton Blanchard wrote:
> When issuing a system reset we almost always oops in the oops_to_nvram
> code because multiple CPUs are using the deflate work area. Add a
> spinlock to protect it.
> 
> To play it safe I'm using trylock to avoid locking up if the NVRAM
> code oopses. This means we might miss multiple CPUs oopsing at exactly
> the same time but I think it's best to play it safe for now. Once we
> are happy with the reliability we can change it to a full spinlock.
> 
> Signed-off-by: Anton Blanchard 

Acked-by: Jim Keniston 

> ---
> 
> Index: linux-build/arch/powerpc/platforms/pseries/nvram.c
> ===
> --- linux-build.orig/arch/powerpc/platforms/pseries/nvram.c   2011-12-01 
> 09:44:27.205568463 +1100
> +++ linux-build/arch/powerpc/platforms/pseries/nvram.c2011-12-01 
> 12:36:49.334478156 +1100
> @@ -634,6 +634,8 @@ static void oops_to_nvram(struct kmsg_du
>  {
>   static unsigned int oops_count = 0;
>   static bool panicking = false;
> + static DEFINE_SPINLOCK(lock);
> + unsigned long flags;
>   size_t text_len;
>   unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
>   int rc = -1;
> @@ -664,6 +666,9 @@ static void oops_to_nvram(struct kmsg_du
>   if (clobbering_unread_rtas_event())
>   return;
> 
> + if (!spin_trylock_irqsave(&lock, flags))
> + return;
> +
>   if (big_oops_buf) {
>   text_len = capture_last_msgs(old_msgs, old_len,
>   new_msgs, new_len, big_oops_buf, big_oops_buf_sz);
> @@ -679,4 +684,6 @@ static void oops_to_nvram(struct kmsg_du
> 
>   (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
>   (int) (sizeof(*oops_len) + *oops_len), err_type, ++oops_count);
> +
> + spin_unlock_irqrestore(&lock, flags);
>  }
> 


___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/2] [POWERPC] uprobes: powerpc port

2012-06-06 Thread Jim Keniston
On Wed, 2012-06-06 at 15:05 +0530, Ananth N Mavinakayanahalli wrote:
> On Wed, Jun 06, 2012 at 11:27:02AM +0200, Peter Zijlstra wrote:
> > On Wed, 2012-06-06 at 14:51 +0530, Ananth N Mavinakayanahalli wrote:
> > > One TODO in this port compared to x86 is the uprobe abort_xol() logic.
> > > x86 depends on the thread_struct.trap_nr (absent in powerpc) to determine
> > > if a signal was caused when the uprobed instruction was single-stepped/
> > > emulated, in which case, we reset the instruction pointer to the probed
> > > address and retry the probe again. 
> > 
> > Another curious difference is that x86 uses an instruction decoder and
> > contains massive tables to validate we can probe a particular
> > instruction.

Part of that difference is because the x86 instruction set is a lot more
complex.  Another part is due to the lack, back when the x86 code was
created, of robust handling by uprobes of traps by probed instructions.
So we refused to probe instructions that we knew (or strongly suspected)
would generate traps in user mode -- e.g., privileged instructions,
illegal instructions.  A couple of times we had to "legalize"
instructions or prefixes that we didn't originally expect to encounter.

> > 
> > Can we probe all possible PPC instructions?
> 
> For the kernel, the only ones that are off limits are rfi (return from
> interrupt), mtmsr (move to msr). All other instructions can be probed.
> 
> Both those instructions are supervisor level, so we won't see them in
> userspace at all; so we should be able to probe all user level
> instructions.

Presumably rfi or mtmsr could show up in the instruction stream via an
erroneous or mischievous asm statement.  It'd be good to verify that you
handle that gracefully.

> 
> I am not aware of specific caveats for vector/altivec instructions;
> maybe Paul or Ben are more suitable to comment on that.
> 
> Ananth
> 

Jim


___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev