aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
authorAruna Balakrishnaiah <aruna@linux.vnet.ibm.com>2013-06-05 14:51:05 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-06-20 03:04:43 -0400
commitb1f70e1f72179f7afe02f4131ed15da406f93e0d (patch)
tree06339aae00a13200d679ef59fd90d38d35676138 /arch/powerpc/platforms/pseries
parent1bf247f8df2e37b53d0415015e56910677626108 (diff)
powerpc/pseries: Add version and timestamp to oops header
Introduce version and timestamp information in the oops header. oops_log_info (oops header) holds version (to distinguish between old and new format oops header), length of the oops text (compressed or uncompressed) and timestamp. The version field will sit in the same place as the length in old headers. version is assigned 5000 (greater than oops partition size) so that existing tools will refuse to dump new style partitions as the length is too large. The updated tools will work with both old and new format headers. Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com> Reviewed-by: Jim Keniston <jkenisto@us.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r--arch/powerpc/platforms/pseries/nvram.c57
1 files changed, 38 insertions, 19 deletions
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index e54a8b7f5c64..742735acd8b6 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -29,6 +29,13 @@
29/* Max bytes to read/write in one go */ 29/* Max bytes to read/write in one go */
30#define NVRW_CNT 0x20 30#define NVRW_CNT 0x20
31 31
32/*
33 * Set oops header version to distingush between old and new format header.
34 * lnx,oops-log partition max size is 4000, header version > 4000 will
35 * help in identifying new header.
36 */
37#define OOPS_HDR_VERSION 5000
38
32static unsigned int nvram_size; 39static unsigned int nvram_size;
33static int nvram_fetch, nvram_store; 40static int nvram_fetch, nvram_store;
34static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ 41static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */
@@ -67,6 +74,12 @@ static const char *pseries_nvram_os_partitions[] = {
67 NULL 74 NULL
68}; 75};
69 76
77struct oops_log_info {
78 u16 version;
79 u16 report_length;
80 u64 timestamp;
81} __attribute__((packed));
82
70static void oops_to_nvram(struct kmsg_dumper *dumper, 83static void oops_to_nvram(struct kmsg_dumper *dumper,
71 enum kmsg_dump_reason reason); 84 enum kmsg_dump_reason reason);
72 85
@@ -83,28 +96,28 @@ static unsigned long last_unread_rtas_event; /* timestamp */
83 96
84 * big_oops_buf[] holds the uncompressed text we're capturing. 97 * big_oops_buf[] holds the uncompressed text we're capturing.
85 * 98 *
86 * oops_buf[] holds the compressed text, preceded by a prefix. 99 * oops_buf[] holds the compressed text, preceded by a oops header.
87 * The prefix is just a u16 holding the length of the compressed* text. 100 * oops header has u16 holding the version of oops header (to differentiate
88 * (*Or uncompressed, if compression fails.) oops_buf[] gets written 101 * between old and new format header) followed by u16 holding the length of
89 * to NVRAM. 102 * the compressed* text (*Or uncompressed, if compression fails.) and u64
103 * holding the timestamp. oops_buf[] gets written to NVRAM.
90 * 104 *
91 * oops_len points to the prefix. oops_data points to the compressed text. 105 * oops_log_info points to the header. oops_data points to the compressed text.
92 * 106 *
93 * +- oops_buf 107 * +- oops_buf
94 * | +- oops_data 108 * | +- oops_data
95 * v v 109 * v v
96 * +------------+-----------------------------------------------+ 110 * +-----------+-----------+-----------+------------------------+
97 * | length | text | 111 * | version | length | timestamp | text |
98 * | (2 bytes) | (oops_data_sz bytes) | 112 * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes) |
99 * +------------+-----------------------------------------------+ 113 * +-----------+-----------+-----------+------------------------+
100 * ^ 114 * ^
101 * +- oops_len 115 * +- oops_log_info
102 * 116 *
103 * We preallocate these buffers during init to avoid kmalloc during oops/panic. 117 * We preallocate these buffers during init to avoid kmalloc during oops/panic.
104 */ 118 */
105static size_t big_oops_buf_sz; 119static size_t big_oops_buf_sz;
106static char *big_oops_buf, *oops_buf; 120static char *big_oops_buf, *oops_buf;
107static u16 *oops_len;
108static char *oops_data; 121static char *oops_data;
109static size_t oops_data_sz; 122static size_t oops_data_sz;
110 123
@@ -425,9 +438,8 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
425 oops_log_partition.name); 438 oops_log_partition.name);
426 return; 439 return;
427 } 440 }
428 oops_len = (u16*) oops_buf; 441 oops_data = oops_buf + sizeof(struct oops_log_info);
429 oops_data = oops_buf + sizeof(u16); 442 oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
430 oops_data_sz = oops_log_partition.size - sizeof(u16);
431 443
432 /* 444 /*
433 * Figure compression (preceded by elimination of each line's <n> 445 * Figure compression (preceded by elimination of each line's <n>
@@ -555,6 +567,7 @@ error:
555/* Compress the text from big_oops_buf into oops_buf. */ 567/* Compress the text from big_oops_buf into oops_buf. */
556static int zip_oops(size_t text_len) 568static int zip_oops(size_t text_len)
557{ 569{
570 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
558 int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len, 571 int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
559 oops_data_sz); 572 oops_data_sz);
560 if (zipped_len < 0) { 573 if (zipped_len < 0) {
@@ -562,7 +575,9 @@ static int zip_oops(size_t text_len)
562 pr_err("nvram: logging uncompressed oops/panic report\n"); 575 pr_err("nvram: logging uncompressed oops/panic report\n");
563 return -1; 576 return -1;
564 } 577 }
565 *oops_len = (u16) zipped_len; 578 oops_hdr->version = OOPS_HDR_VERSION;
579 oops_hdr->report_length = (u16) zipped_len;
580 oops_hdr->timestamp = get_seconds();
566 return 0; 581 return 0;
567} 582}
568 583
@@ -576,6 +591,7 @@ static int zip_oops(size_t text_len)
576static void oops_to_nvram(struct kmsg_dumper *dumper, 591static void oops_to_nvram(struct kmsg_dumper *dumper,
577 enum kmsg_dump_reason reason) 592 enum kmsg_dump_reason reason)
578{ 593{
594 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
579 static unsigned int oops_count = 0; 595 static unsigned int oops_count = 0;
580 static bool panicking = false; 596 static bool panicking = false;
581 static DEFINE_SPINLOCK(lock); 597 static DEFINE_SPINLOCK(lock);
@@ -622,11 +638,14 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
622 kmsg_dump_get_buffer(dumper, false, 638 kmsg_dump_get_buffer(dumper, false,
623 oops_data, oops_data_sz, &text_len); 639 oops_data, oops_data_sz, &text_len);
624 err_type = ERR_TYPE_KERNEL_PANIC; 640 err_type = ERR_TYPE_KERNEL_PANIC;
625 *oops_len = (u16) text_len; 641 oops_hdr->version = OOPS_HDR_VERSION;
642 oops_hdr->report_length = (u16) text_len;
643 oops_hdr->timestamp = get_seconds();
626 } 644 }
627 645
628 (void) nvram_write_os_partition(&oops_log_partition, oops_buf, 646 (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
629 (int) (sizeof(*oops_len) + *oops_len), err_type, ++oops_count); 647 (int) (sizeof(*oops_hdr) + oops_hdr->report_length), err_type,
648 ++oops_count);
630 649
631 spin_unlock_irqrestore(&lock, flags); 650 spin_unlock_irqrestore(&lock, flags);
632} 651}