aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
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}