diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-11 12:12:39 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-11 12:12:39 -0700 |
commit | 77f63b4da4b69f65c17c45e797ddb3013b889df9 (patch) | |
tree | a3156a3bb0dc464bbed41fa289991aa8a38103e9 /arch/powerpc/platforms/pseries/nvram.c | |
parent | 30b229bdd88445c550efbeb076ffaa251eb05364 (diff) | |
parent | 28e61cc466d8daace4b0f04ba2b83e0bd68f5832 (diff) |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc fixes from Ben Herrenschmidt:
"This includes small series from Michael Neuling to fix a couple of
nasty remaining problems with the new Power8 support, also targeted at
stable 3.10, without which some new userspace accessible registers
aren't properly context switched, and in some case, can be clobbered
by the user of transactional memory.
Along with that, a few slightly more minor things, such as a missing
Kconfig option to enable handling of denorm exceptions when not
running under a hypervisor (or userspace will randomly crash when
hitting denorms with the vector unit), some nasty bugs in the new
pstore oops code, and other simple bug fixes worth having in now.
Note: I picked up the two powerpc KVM fixes as Alex Graf asked me to
handle KVM bits while he is on vacation. However I'll let him decide
whether they should go to -stable or not when he is back"
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
powerpc/tm: Fix context switching TAR, PPR and DSCR SPRs
powerpc: Save the TAR register earlier
powerpc: Fix context switch DSCR on POWER8
powerpc: Rework setting up H/FSCR bit definitions
powerpc: Fix hypervisor facility unavaliable vector number
powerpc/kvm/book3s_pr: Return appropriate error when allocation fails
powerpc/kvm: Add signed type cast for comparation
powerpc/eeh: Add missing procfs entry for PowerNV
powerpc/pseries: Add backward compatibilty to read old kernel oops-log
powerpc/pseries: Fix buffer overflow when reading from pstore
powerpc: On POWERNV enable PPC_DENORMALISATION by default
Diffstat (limited to 'arch/powerpc/platforms/pseries/nvram.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/nvram.c | 80 |
1 files changed, 34 insertions, 46 deletions
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 9f8671a44551..6a5f2b1f32ca 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -569,35 +569,6 @@ error: return ret; } -static int unzip_oops(char *oops_buf, char *big_buf) -{ - struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; - u64 timestamp = oops_hdr->timestamp; - char *big_oops_data = NULL; - char *oops_data_buf = NULL; - size_t big_oops_data_sz; - int unzipped_len; - - big_oops_data = big_buf + sizeof(struct oops_log_info); - big_oops_data_sz = big_oops_buf_sz - sizeof(struct oops_log_info); - oops_data_buf = oops_buf + sizeof(struct oops_log_info); - - unzipped_len = nvram_decompress(oops_data_buf, big_oops_data, - oops_hdr->report_length, - big_oops_data_sz); - - if (unzipped_len < 0) { - pr_err("nvram: decompression failed; returned %d\n", - unzipped_len); - return -1; - } - oops_hdr = (struct oops_log_info *)big_buf; - oops_hdr->version = OOPS_HDR_VERSION; - oops_hdr->report_length = (u16) unzipped_len; - oops_hdr->timestamp = timestamp; - return 0; -} - static int nvram_pstore_open(struct pstore_info *psi) { /* Reset the iterator to start reading partitions again */ @@ -685,10 +656,9 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, unsigned int err_type, id_no, size = 0; struct nvram_os_partition *part = NULL; char *buff = NULL, *big_buff = NULL; - int rc, sig = 0; + int sig = 0; loff_t p; -read_partition: read_type++; switch (nvram_type_ids[read_type]) { @@ -749,30 +719,46 @@ read_partition: *id = id_no; if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { + int length, unzipped_len; + size_t hdr_size; + oops_hdr = (struct oops_log_info *)buff; - *buf = buff + sizeof(*oops_hdr); + if (oops_hdr->version < OOPS_HDR_VERSION) { + /* Old format oops header had 2-byte record size */ + hdr_size = sizeof(u16); + length = oops_hdr->version; + time->tv_sec = 0; + time->tv_nsec = 0; + } else { + hdr_size = sizeof(*oops_hdr); + length = oops_hdr->report_length; + time->tv_sec = oops_hdr->timestamp; + time->tv_nsec = 0; + } + *buf = kmalloc(length, GFP_KERNEL); + if (*buf == NULL) + return -ENOMEM; + memcpy(*buf, buff + hdr_size, length); + kfree(buff); if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) { big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL); if (!big_buff) return -ENOMEM; - rc = unzip_oops(buff, big_buff); + unzipped_len = nvram_decompress(*buf, big_buff, + length, big_oops_buf_sz); - if (rc != 0) { - kfree(buff); + if (unzipped_len < 0) { + pr_err("nvram: decompression failed, returned " + "rc %d\n", unzipped_len); kfree(big_buff); - goto read_partition; + } else { + *buf = big_buff; + length = unzipped_len; } - - oops_hdr = (struct oops_log_info *)big_buff; - *buf = big_buff + sizeof(*oops_hdr); - kfree(buff); } - - time->tv_sec = oops_hdr->timestamp; - time->tv_nsec = 0; - return oops_hdr->report_length; + return length; } *buf = buff; @@ -816,6 +802,7 @@ static int nvram_pstore_init(void) static void __init nvram_init_oops_partition(int rtas_partition_exists) { int rc; + size_t size; rc = pseries_nvram_init_os_partition(&oops_log_partition); if (rc != 0) { @@ -844,8 +831,9 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists) 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); + size = max(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL), + zlib_inflate_workspacesize()); + stream.workspace = kmalloc(size, GFP_KERNEL); if (!stream.workspace) { pr_err("nvram: No memory for compression workspace; " "skipping compression of %s partition data\n", |