Commit b1f70e1f authored by Aruna Balakrishnaiah's avatar Aruna Balakrishnaiah Committed by Benjamin Herrenschmidt

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: default avatarAruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
Reviewed-by: default avatarJim Keniston <jkenisto@us.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 1bf247f8
...@@ -29,6 +29,13 @@ ...@@ -29,6 +29,13 @@
/* Max bytes to read/write in one go */ /* Max bytes to read/write in one go */
#define NVRW_CNT 0x20 #define NVRW_CNT 0x20
/*
* Set oops header version to distingush between old and new format header.
* lnx,oops-log partition max size is 4000, header version > 4000 will
* help in identifying new header.
*/
#define OOPS_HDR_VERSION 5000
static unsigned int nvram_size; static unsigned int nvram_size;
static int nvram_fetch, nvram_store; static int nvram_fetch, nvram_store;
static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */
...@@ -67,6 +74,12 @@ static const char *pseries_nvram_os_partitions[] = { ...@@ -67,6 +74,12 @@ static const char *pseries_nvram_os_partitions[] = {
NULL NULL
}; };
struct oops_log_info {
u16 version;
u16 report_length;
u64 timestamp;
} __attribute__((packed));
static void oops_to_nvram(struct kmsg_dumper *dumper, static void oops_to_nvram(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason); enum kmsg_dump_reason reason);
...@@ -83,28 +96,28 @@ static unsigned long last_unread_rtas_event; /* timestamp */ ...@@ -83,28 +96,28 @@ static unsigned long last_unread_rtas_event; /* timestamp */
* big_oops_buf[] holds the uncompressed text we're capturing. * big_oops_buf[] holds the uncompressed text we're capturing.
* *
* oops_buf[] holds the compressed text, preceded by a prefix. * oops_buf[] holds the compressed text, preceded by a oops header.
* The prefix is just a u16 holding the length of the compressed* text. * oops header has u16 holding the version of oops header (to differentiate
* (*Or uncompressed, if compression fails.) oops_buf[] gets written * between old and new format header) followed by u16 holding the length of
* to NVRAM. * the compressed* text (*Or uncompressed, if compression fails.) and u64
* holding the timestamp. oops_buf[] gets written to NVRAM.
* *
* oops_len points to the prefix. oops_data points to the compressed text. * oops_log_info points to the header. oops_data points to the compressed text.
* *
* +- oops_buf * +- oops_buf
* | +- oops_data * | +- oops_data
* v v * v v
* +------------+-----------------------------------------------+ * +-----------+-----------+-----------+------------------------+
* | length | text | * | version | length | timestamp | text |
* | (2 bytes) | (oops_data_sz bytes) | * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes) |
* +------------+-----------------------------------------------+ * +-----------+-----------+-----------+------------------------+
* ^ * ^
* +- oops_len * +- oops_log_info
* *
* We preallocate these buffers during init to avoid kmalloc during oops/panic. * We preallocate these buffers during init to avoid kmalloc during oops/panic.
*/ */
static size_t big_oops_buf_sz; static size_t big_oops_buf_sz;
static char *big_oops_buf, *oops_buf; static char *big_oops_buf, *oops_buf;
static u16 *oops_len;
static char *oops_data; static char *oops_data;
static size_t oops_data_sz; static size_t oops_data_sz;
...@@ -425,9 +438,8 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists) ...@@ -425,9 +438,8 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
oops_log_partition.name); oops_log_partition.name);
return; return;
} }
oops_len = (u16*) oops_buf; oops_data = oops_buf + sizeof(struct oops_log_info);
oops_data = oops_buf + sizeof(u16); oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
oops_data_sz = oops_log_partition.size - sizeof(u16);
/* /*
* Figure compression (preceded by elimination of each line's <n> * Figure compression (preceded by elimination of each line's <n>
...@@ -555,6 +567,7 @@ static int nvram_compress(const void *in, void *out, size_t inlen, ...@@ -555,6 +567,7 @@ static int nvram_compress(const void *in, void *out, size_t inlen,
/* Compress the text from big_oops_buf into oops_buf. */ /* Compress the text from big_oops_buf into oops_buf. */
static int zip_oops(size_t text_len) static int zip_oops(size_t text_len)
{ {
struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len, int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
oops_data_sz); oops_data_sz);
if (zipped_len < 0) { if (zipped_len < 0) {
...@@ -562,7 +575,9 @@ static int zip_oops(size_t text_len) ...@@ -562,7 +575,9 @@ static int zip_oops(size_t text_len)
pr_err("nvram: logging uncompressed oops/panic report\n"); pr_err("nvram: logging uncompressed oops/panic report\n");
return -1; return -1;
} }
*oops_len = (u16) zipped_len; oops_hdr->version = OOPS_HDR_VERSION;
oops_hdr->report_length = (u16) zipped_len;
oops_hdr->timestamp = get_seconds();
return 0; return 0;
} }
...@@ -576,6 +591,7 @@ static int zip_oops(size_t text_len) ...@@ -576,6 +591,7 @@ static int zip_oops(size_t text_len)
static void oops_to_nvram(struct kmsg_dumper *dumper, static void oops_to_nvram(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason) enum kmsg_dump_reason reason)
{ {
struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
static unsigned int oops_count = 0; static unsigned int oops_count = 0;
static bool panicking = false; static bool panicking = false;
static DEFINE_SPINLOCK(lock); static DEFINE_SPINLOCK(lock);
...@@ -622,11 +638,14 @@ static void oops_to_nvram(struct kmsg_dumper *dumper, ...@@ -622,11 +638,14 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
kmsg_dump_get_buffer(dumper, false, kmsg_dump_get_buffer(dumper, false,
oops_data, oops_data_sz, &text_len); oops_data, oops_data_sz, &text_len);
err_type = ERR_TYPE_KERNEL_PANIC; err_type = ERR_TYPE_KERNEL_PANIC;
*oops_len = (u16) text_len; oops_hdr->version = OOPS_HDR_VERSION;
oops_hdr->report_length = (u16) text_len;
oops_hdr->timestamp = get_seconds();
} }
(void) nvram_write_os_partition(&oops_log_partition, oops_buf, (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
(int) (sizeof(*oops_len) + *oops_len), err_type, ++oops_count); (int) (sizeof(*oops_hdr) + oops_hdr->report_length), err_type,
++oops_count);
spin_unlock_irqrestore(&lock, flags); spin_unlock_irqrestore(&lock, flags);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment