Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/nvram: Move generic code for nvram and pstore

With minor checks, we can move most of the code for nvram
under pseries to a common place to be re-used by other
powerpc platforms like powernv. This patch moves such
common code to arch/powerpc/kernel/nvram_64.c file.

Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
[mpe: Move select of ZLIB_DEFLATE to PPC64 to fix the build]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Hari Bathini and committed by
Michael Ellerman
78989f0a 3af229f2

+715 -663
+49 -1
arch/powerpc/include/asm/nvram.h
··· 9 9 #ifndef _ASM_POWERPC_NVRAM_H 10 10 #define _ASM_POWERPC_NVRAM_H 11 11 12 - 12 + #include <linux/types.h> 13 13 #include <linux/errno.h> 14 14 #include <linux/list.h> 15 15 #include <uapi/asm/nvram.h> 16 16 17 + /* 18 + * Set oops header version to distinguish between old and new format header. 19 + * lnx,oops-log partition max size is 4000, header version > 4000 will 20 + * help in identifying new header. 21 + */ 22 + #define OOPS_HDR_VERSION 5000 23 + 24 + struct err_log_info { 25 + __be32 error_type; 26 + __be32 seq_num; 27 + }; 28 + 29 + struct nvram_os_partition { 30 + const char *name; 31 + int req_size; /* desired size, in bytes */ 32 + int min_size; /* minimum acceptable size (0 means req_size) */ 33 + long size; /* size of data portion (excluding err_log_info) */ 34 + long index; /* offset of data portion of partition */ 35 + bool os_partition; /* partition initialized by OS, not FW */ 36 + }; 37 + 38 + struct oops_log_info { 39 + __be16 version; 40 + __be16 report_length; 41 + __be64 timestamp; 42 + } __attribute__((packed)); 43 + 44 + extern struct nvram_os_partition oops_log_partition; 45 + 17 46 #ifdef CONFIG_PPC_PSERIES 47 + extern struct nvram_os_partition rtas_log_partition; 48 + 18 49 extern int nvram_write_error_log(char * buff, int length, 19 50 unsigned int err_type, unsigned int err_seq); 20 51 extern int nvram_read_error_log(char * buff, int length, ··· 80 49 81 50 /* Synchronize NVRAM */ 82 51 extern void nvram_sync(void); 52 + 53 + /* Initialize NVRAM OS partition */ 54 + extern int __init nvram_init_os_partition(struct nvram_os_partition *part); 55 + 56 + /* Initialize NVRAM oops partition */ 57 + extern void __init nvram_init_oops_partition(int rtas_partition_exists); 58 + 59 + /* Read a NVRAM partition */ 60 + extern int nvram_read_partition(struct nvram_os_partition *part, char *buff, 61 + int length, unsigned int *err_type, 62 + unsigned int *error_log_cnt); 63 + 64 + /* Write to NVRAM OS partition */ 65 + extern int nvram_write_os_partition(struct nvram_os_partition *part, 66 + char *buff, int length, 67 + unsigned int err_type, 68 + unsigned int error_log_cnt); 83 69 84 70 /* Determine NVRAM size */ 85 71 extern ssize_t nvram_get_size(void);
+4
arch/powerpc/include/asm/rtas.h
··· 343 343 extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal); 344 344 345 345 #ifdef CONFIG_PPC_PSERIES 346 + extern unsigned long last_rtas_event; 347 + extern int clobbering_unread_rtas_event(void); 346 348 extern int pseries_devicetree_update(s32 scope); 347 349 extern void post_mobility_fixup(void); 350 + #else 351 + static inline int clobbering_unread_rtas_event(void) { return 0; } 348 352 #endif 349 353 350 354 #ifdef CONFIG_PPC_RTAS_DAEMON
+656
arch/powerpc/kernel/nvram_64.c
··· 26 26 #include <linux/init.h> 27 27 #include <linux/slab.h> 28 28 #include <linux/spinlock.h> 29 + #include <linux/kmsg_dump.h> 30 + #include <linux/pstore.h> 31 + #include <linux/zlib.h> 29 32 #include <asm/uaccess.h> 30 33 #include <asm/nvram.h> 31 34 #include <asm/rtas.h> ··· 56 53 }; 57 54 58 55 static LIST_HEAD(nvram_partitions); 56 + 57 + #ifdef CONFIG_PPC_PSERIES 58 + struct nvram_os_partition rtas_log_partition = { 59 + .name = "ibm,rtas-log", 60 + .req_size = 2079, 61 + .min_size = 1055, 62 + .index = -1, 63 + .os_partition = true 64 + }; 65 + #endif 66 + 67 + struct nvram_os_partition oops_log_partition = { 68 + .name = "lnx,oops-log", 69 + .req_size = 4000, 70 + .min_size = 2000, 71 + .index = -1, 72 + .os_partition = true 73 + }; 74 + 75 + static const char *nvram_os_partitions[] = { 76 + #ifdef CONFIG_PPC_PSERIES 77 + "ibm,rtas-log", 78 + #endif 79 + "lnx,oops-log", 80 + NULL 81 + }; 82 + 83 + static void oops_to_nvram(struct kmsg_dumper *dumper, 84 + enum kmsg_dump_reason reason); 85 + 86 + static struct kmsg_dumper nvram_kmsg_dumper = { 87 + .dump = oops_to_nvram 88 + }; 89 + 90 + /* 91 + * For capturing and compressing an oops or panic report... 92 + 93 + * big_oops_buf[] holds the uncompressed text we're capturing. 94 + * 95 + * oops_buf[] holds the compressed text, preceded by a oops header. 96 + * oops header has u16 holding the version of oops header (to differentiate 97 + * between old and new format header) followed by u16 holding the length of 98 + * the compressed* text (*Or uncompressed, if compression fails.) and u64 99 + * holding the timestamp. oops_buf[] gets written to NVRAM. 100 + * 101 + * oops_log_info points to the header. oops_data points to the compressed text. 102 + * 103 + * +- oops_buf 104 + * | +- oops_data 105 + * v v 106 + * +-----------+-----------+-----------+------------------------+ 107 + * | version | length | timestamp | text | 108 + * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes) | 109 + * +-----------+-----------+-----------+------------------------+ 110 + * ^ 111 + * +- oops_log_info 112 + * 113 + * We preallocate these buffers during init to avoid kmalloc during oops/panic. 114 + */ 115 + static size_t big_oops_buf_sz; 116 + static char *big_oops_buf, *oops_buf; 117 + static char *oops_data; 118 + static size_t oops_data_sz; 119 + 120 + /* Compression parameters */ 121 + #define COMPR_LEVEL 6 122 + #define WINDOW_BITS 12 123 + #define MEM_LEVEL 4 124 + static struct z_stream_s stream; 125 + 126 + #ifdef CONFIG_PSTORE 127 + #ifdef CONFIG_PPC_PSERIES 128 + static struct nvram_os_partition of_config_partition = { 129 + .name = "of-config", 130 + .index = -1, 131 + .os_partition = false 132 + }; 133 + #endif 134 + 135 + static struct nvram_os_partition common_partition = { 136 + .name = "common", 137 + .index = -1, 138 + .os_partition = false 139 + }; 140 + 141 + static enum pstore_type_id nvram_type_ids[] = { 142 + PSTORE_TYPE_DMESG, 143 + PSTORE_TYPE_PPC_COMMON, 144 + -1, 145 + -1, 146 + -1 147 + }; 148 + static int read_type; 149 + #endif 150 + 151 + /* nvram_write_os_partition 152 + * 153 + * We need to buffer the error logs into nvram to ensure that we have 154 + * the failure information to decode. If we have a severe error there 155 + * is no way to guarantee that the OS or the machine is in a state to 156 + * get back to user land and write the error to disk. For example if 157 + * the SCSI device driver causes a Machine Check by writing to a bad 158 + * IO address, there is no way of guaranteeing that the device driver 159 + * is in any state that is would also be able to write the error data 160 + * captured to disk, thus we buffer it in NVRAM for analysis on the 161 + * next boot. 162 + * 163 + * In NVRAM the partition containing the error log buffer will looks like: 164 + * Header (in bytes): 165 + * +-----------+----------+--------+------------+------------------+ 166 + * | signature | checksum | length | name | data | 167 + * |0 |1 |2 3|4 15|16 length-1| 168 + * +-----------+----------+--------+------------+------------------+ 169 + * 170 + * The 'data' section would look like (in bytes): 171 + * +--------------+------------+-----------------------------------+ 172 + * | event_logged | sequence # | error log | 173 + * |0 3|4 7|8 error_log_size-1| 174 + * +--------------+------------+-----------------------------------+ 175 + * 176 + * event_logged: 0 if event has not been logged to syslog, 1 if it has 177 + * sequence #: The unique sequence # for each event. (until it wraps) 178 + * error log: The error log from event_scan 179 + */ 180 + int nvram_write_os_partition(struct nvram_os_partition *part, 181 + char *buff, int length, 182 + unsigned int err_type, 183 + unsigned int error_log_cnt) 184 + { 185 + int rc; 186 + loff_t tmp_index; 187 + struct err_log_info info; 188 + 189 + if (part->index == -1) 190 + return -ESPIPE; 191 + 192 + if (length > part->size) 193 + length = part->size; 194 + 195 + info.error_type = cpu_to_be32(err_type); 196 + info.seq_num = cpu_to_be32(error_log_cnt); 197 + 198 + tmp_index = part->index; 199 + 200 + rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), 201 + &tmp_index); 202 + if (rc <= 0) { 203 + pr_err("%s: Failed nvram_write (%d)\n", __func__, rc); 204 + return rc; 205 + } 206 + 207 + rc = ppc_md.nvram_write(buff, length, &tmp_index); 208 + if (rc <= 0) { 209 + pr_err("%s: Failed nvram_write (%d)\n", __func__, rc); 210 + return rc; 211 + } 212 + 213 + return 0; 214 + } 215 + 216 + /* nvram_read_partition 217 + * 218 + * Reads nvram partition for at most 'length' 219 + */ 220 + int nvram_read_partition(struct nvram_os_partition *part, char *buff, 221 + int length, unsigned int *err_type, 222 + unsigned int *error_log_cnt) 223 + { 224 + int rc; 225 + loff_t tmp_index; 226 + struct err_log_info info; 227 + 228 + if (part->index == -1) 229 + return -1; 230 + 231 + if (length > part->size) 232 + length = part->size; 233 + 234 + tmp_index = part->index; 235 + 236 + if (part->os_partition) { 237 + rc = ppc_md.nvram_read((char *)&info, 238 + sizeof(struct err_log_info), 239 + &tmp_index); 240 + if (rc <= 0) { 241 + pr_err("%s: Failed nvram_read (%d)\n", __func__, rc); 242 + return rc; 243 + } 244 + } 245 + 246 + rc = ppc_md.nvram_read(buff, length, &tmp_index); 247 + if (rc <= 0) { 248 + pr_err("%s: Failed nvram_read (%d)\n", __func__, rc); 249 + return rc; 250 + } 251 + 252 + if (part->os_partition) { 253 + *error_log_cnt = be32_to_cpu(info.seq_num); 254 + *err_type = be32_to_cpu(info.error_type); 255 + } 256 + 257 + return 0; 258 + } 259 + 260 + /* nvram_init_os_partition 261 + * 262 + * This sets up a partition with an "OS" signature. 263 + * 264 + * The general strategy is the following: 265 + * 1.) If a partition with the indicated name already exists... 266 + * - If it's large enough, use it. 267 + * - Otherwise, recycle it and keep going. 268 + * 2.) Search for a free partition that is large enough. 269 + * 3.) If there's not a free partition large enough, recycle any obsolete 270 + * OS partitions and try again. 271 + * 4.) Will first try getting a chunk that will satisfy the requested size. 272 + * 5.) If a chunk of the requested size cannot be allocated, then try finding 273 + * a chunk that will satisfy the minum needed. 274 + * 275 + * Returns 0 on success, else -1. 276 + */ 277 + int __init nvram_init_os_partition(struct nvram_os_partition *part) 278 + { 279 + loff_t p; 280 + int size; 281 + 282 + /* Look for ours */ 283 + p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size); 284 + 285 + /* Found one but too small, remove it */ 286 + if (p && size < part->min_size) { 287 + pr_info("nvram: Found too small %s partition," 288 + " removing it...\n", part->name); 289 + nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL); 290 + p = 0; 291 + } 292 + 293 + /* Create one if we didn't find */ 294 + if (!p) { 295 + p = nvram_create_partition(part->name, NVRAM_SIG_OS, 296 + part->req_size, part->min_size); 297 + if (p == -ENOSPC) { 298 + pr_info("nvram: No room to create %s partition, " 299 + "deleting any obsolete OS partitions...\n", 300 + part->name); 301 + nvram_remove_partition(NULL, NVRAM_SIG_OS, 302 + nvram_os_partitions); 303 + p = nvram_create_partition(part->name, NVRAM_SIG_OS, 304 + part->req_size, part->min_size); 305 + } 306 + } 307 + 308 + if (p <= 0) { 309 + pr_err("nvram: Failed to find or create %s" 310 + " partition, err %d\n", part->name, (int)p); 311 + return -1; 312 + } 313 + 314 + part->index = p; 315 + part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info); 316 + 317 + return 0; 318 + } 319 + 320 + /* Derived from logfs_compress() */ 321 + static int nvram_compress(const void *in, void *out, size_t inlen, 322 + size_t outlen) 323 + { 324 + int err, ret; 325 + 326 + ret = -EIO; 327 + err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS, 328 + MEM_LEVEL, Z_DEFAULT_STRATEGY); 329 + if (err != Z_OK) 330 + goto error; 331 + 332 + stream.next_in = in; 333 + stream.avail_in = inlen; 334 + stream.total_in = 0; 335 + stream.next_out = out; 336 + stream.avail_out = outlen; 337 + stream.total_out = 0; 338 + 339 + err = zlib_deflate(&stream, Z_FINISH); 340 + if (err != Z_STREAM_END) 341 + goto error; 342 + 343 + err = zlib_deflateEnd(&stream); 344 + if (err != Z_OK) 345 + goto error; 346 + 347 + if (stream.total_out >= stream.total_in) 348 + goto error; 349 + 350 + ret = stream.total_out; 351 + error: 352 + return ret; 353 + } 354 + 355 + /* Compress the text from big_oops_buf into oops_buf. */ 356 + static int zip_oops(size_t text_len) 357 + { 358 + struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; 359 + int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len, 360 + oops_data_sz); 361 + if (zipped_len < 0) { 362 + pr_err("nvram: compression failed; returned %d\n", zipped_len); 363 + pr_err("nvram: logging uncompressed oops/panic report\n"); 364 + return -1; 365 + } 366 + oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); 367 + oops_hdr->report_length = cpu_to_be16(zipped_len); 368 + oops_hdr->timestamp = cpu_to_be64(get_seconds()); 369 + return 0; 370 + } 371 + 372 + #ifdef CONFIG_PSTORE 373 + static int nvram_pstore_open(struct pstore_info *psi) 374 + { 375 + /* Reset the iterator to start reading partitions again */ 376 + read_type = -1; 377 + return 0; 378 + } 379 + 380 + /** 381 + * nvram_pstore_write - pstore write callback for nvram 382 + * @type: Type of message logged 383 + * @reason: reason behind dump (oops/panic) 384 + * @id: identifier to indicate the write performed 385 + * @part: pstore writes data to registered buffer in parts, 386 + * part number will indicate the same. 387 + * @count: Indicates oops count 388 + * @compressed: Flag to indicate the log is compressed 389 + * @size: number of bytes written to the registered buffer 390 + * @psi: registered pstore_info structure 391 + * 392 + * Called by pstore_dump() when an oops or panic report is logged in the 393 + * printk buffer. 394 + * Returns 0 on successful write. 395 + */ 396 + static int nvram_pstore_write(enum pstore_type_id type, 397 + enum kmsg_dump_reason reason, 398 + u64 *id, unsigned int part, int count, 399 + bool compressed, size_t size, 400 + struct pstore_info *psi) 401 + { 402 + int rc; 403 + unsigned int err_type = ERR_TYPE_KERNEL_PANIC; 404 + struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf; 405 + 406 + /* part 1 has the recent messages from printk buffer */ 407 + if (part > 1 || (type != PSTORE_TYPE_DMESG)) 408 + return -1; 409 + 410 + if (clobbering_unread_rtas_event()) 411 + return -1; 412 + 413 + oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); 414 + oops_hdr->report_length = cpu_to_be16(size); 415 + oops_hdr->timestamp = cpu_to_be64(get_seconds()); 416 + 417 + if (compressed) 418 + err_type = ERR_TYPE_KERNEL_PANIC_GZ; 419 + 420 + rc = nvram_write_os_partition(&oops_log_partition, oops_buf, 421 + (int) (sizeof(*oops_hdr) + size), err_type, count); 422 + 423 + if (rc != 0) 424 + return rc; 425 + 426 + *id = part; 427 + return 0; 428 + } 429 + 430 + /* 431 + * Reads the oops/panic report, rtas, of-config and common partition. 432 + * Returns the length of the data we read from each partition. 433 + * Returns 0 if we've been called before. 434 + */ 435 + static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, 436 + int *count, struct timespec *time, char **buf, 437 + bool *compressed, struct pstore_info *psi) 438 + { 439 + struct oops_log_info *oops_hdr; 440 + unsigned int err_type, id_no, size = 0; 441 + struct nvram_os_partition *part = NULL; 442 + char *buff = NULL; 443 + int sig = 0; 444 + loff_t p; 445 + 446 + read_type++; 447 + 448 + switch (nvram_type_ids[read_type]) { 449 + case PSTORE_TYPE_DMESG: 450 + part = &oops_log_partition; 451 + *type = PSTORE_TYPE_DMESG; 452 + break; 453 + case PSTORE_TYPE_PPC_COMMON: 454 + sig = NVRAM_SIG_SYS; 455 + part = &common_partition; 456 + *type = PSTORE_TYPE_PPC_COMMON; 457 + *id = PSTORE_TYPE_PPC_COMMON; 458 + time->tv_sec = 0; 459 + time->tv_nsec = 0; 460 + break; 461 + #ifdef CONFIG_PPC_PSERIES 462 + case PSTORE_TYPE_PPC_RTAS: 463 + part = &rtas_log_partition; 464 + *type = PSTORE_TYPE_PPC_RTAS; 465 + time->tv_sec = last_rtas_event; 466 + time->tv_nsec = 0; 467 + break; 468 + case PSTORE_TYPE_PPC_OF: 469 + sig = NVRAM_SIG_OF; 470 + part = &of_config_partition; 471 + *type = PSTORE_TYPE_PPC_OF; 472 + *id = PSTORE_TYPE_PPC_OF; 473 + time->tv_sec = 0; 474 + time->tv_nsec = 0; 475 + break; 476 + #endif 477 + default: 478 + return 0; 479 + } 480 + 481 + if (!part->os_partition) { 482 + p = nvram_find_partition(part->name, sig, &size); 483 + if (p <= 0) { 484 + pr_err("nvram: Failed to find partition %s, " 485 + "err %d\n", part->name, (int)p); 486 + return 0; 487 + } 488 + part->index = p; 489 + part->size = size; 490 + } 491 + 492 + buff = kmalloc(part->size, GFP_KERNEL); 493 + 494 + if (!buff) 495 + return -ENOMEM; 496 + 497 + if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) { 498 + kfree(buff); 499 + return 0; 500 + } 501 + 502 + *count = 0; 503 + 504 + if (part->os_partition) 505 + *id = id_no; 506 + 507 + if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { 508 + size_t length, hdr_size; 509 + 510 + oops_hdr = (struct oops_log_info *)buff; 511 + if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) { 512 + /* Old format oops header had 2-byte record size */ 513 + hdr_size = sizeof(u16); 514 + length = be16_to_cpu(oops_hdr->version); 515 + time->tv_sec = 0; 516 + time->tv_nsec = 0; 517 + } else { 518 + hdr_size = sizeof(*oops_hdr); 519 + length = be16_to_cpu(oops_hdr->report_length); 520 + time->tv_sec = be64_to_cpu(oops_hdr->timestamp); 521 + time->tv_nsec = 0; 522 + } 523 + *buf = kmalloc(length, GFP_KERNEL); 524 + if (*buf == NULL) 525 + return -ENOMEM; 526 + memcpy(*buf, buff + hdr_size, length); 527 + kfree(buff); 528 + 529 + if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) 530 + *compressed = true; 531 + else 532 + *compressed = false; 533 + return length; 534 + } 535 + 536 + *buf = buff; 537 + return part->size; 538 + } 539 + 540 + static struct pstore_info nvram_pstore_info = { 541 + .owner = THIS_MODULE, 542 + .name = "nvram", 543 + .open = nvram_pstore_open, 544 + .read = nvram_pstore_read, 545 + .write = nvram_pstore_write, 546 + }; 547 + 548 + static int nvram_pstore_init(void) 549 + { 550 + int rc = 0; 551 + 552 + nvram_type_ids[2] = PSTORE_TYPE_PPC_RTAS; 553 + nvram_type_ids[3] = PSTORE_TYPE_PPC_OF; 554 + 555 + nvram_pstore_info.buf = oops_data; 556 + nvram_pstore_info.bufsize = oops_data_sz; 557 + 558 + spin_lock_init(&nvram_pstore_info.buf_lock); 559 + 560 + rc = pstore_register(&nvram_pstore_info); 561 + if (rc != 0) 562 + pr_err("nvram: pstore_register() failed, defaults to " 563 + "kmsg_dump; returned %d\n", rc); 564 + 565 + return rc; 566 + } 567 + #else 568 + static int nvram_pstore_init(void) 569 + { 570 + return -1; 571 + } 572 + #endif 573 + 574 + void __init nvram_init_oops_partition(int rtas_partition_exists) 575 + { 576 + int rc; 577 + 578 + rc = nvram_init_os_partition(&oops_log_partition); 579 + if (rc != 0) { 580 + #ifdef CONFIG_PPC_PSERIES 581 + if (!rtas_partition_exists) { 582 + pr_err("nvram: Failed to initialize oops partition!"); 583 + return; 584 + } 585 + pr_notice("nvram: Using %s partition to log both" 586 + " RTAS errors and oops/panic reports\n", 587 + rtas_log_partition.name); 588 + memcpy(&oops_log_partition, &rtas_log_partition, 589 + sizeof(rtas_log_partition)); 590 + #else 591 + pr_err("nvram: Failed to initialize oops partition!"); 592 + return; 593 + #endif 594 + } 595 + oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL); 596 + if (!oops_buf) { 597 + pr_err("nvram: No memory for %s partition\n", 598 + oops_log_partition.name); 599 + return; 600 + } 601 + oops_data = oops_buf + sizeof(struct oops_log_info); 602 + oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info); 603 + 604 + rc = nvram_pstore_init(); 605 + 606 + if (!rc) 607 + return; 608 + 609 + /* 610 + * Figure compression (preceded by elimination of each line's <n> 611 + * severity prefix) will reduce the oops/panic report to at most 612 + * 45% of its original size. 613 + */ 614 + big_oops_buf_sz = (oops_data_sz * 100) / 45; 615 + big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); 616 + if (big_oops_buf) { 617 + stream.workspace = kmalloc(zlib_deflate_workspacesize( 618 + WINDOW_BITS, MEM_LEVEL), GFP_KERNEL); 619 + if (!stream.workspace) { 620 + pr_err("nvram: No memory for compression workspace; " 621 + "skipping compression of %s partition data\n", 622 + oops_log_partition.name); 623 + kfree(big_oops_buf); 624 + big_oops_buf = NULL; 625 + } 626 + } else { 627 + pr_err("No memory for uncompressed %s data; " 628 + "skipping compression\n", oops_log_partition.name); 629 + stream.workspace = NULL; 630 + } 631 + 632 + rc = kmsg_dump_register(&nvram_kmsg_dumper); 633 + if (rc != 0) { 634 + pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc); 635 + kfree(oops_buf); 636 + kfree(big_oops_buf); 637 + kfree(stream.workspace); 638 + } 639 + } 640 + 641 + /* 642 + * This is our kmsg_dump callback, called after an oops or panic report 643 + * has been written to the printk buffer. We want to capture as much 644 + * of the printk buffer as possible. First, capture as much as we can 645 + * that we think will compress sufficiently to fit in the lnx,oops-log 646 + * partition. If that's too much, go back and capture uncompressed text. 647 + */ 648 + static void oops_to_nvram(struct kmsg_dumper *dumper, 649 + enum kmsg_dump_reason reason) 650 + { 651 + struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; 652 + static unsigned int oops_count = 0; 653 + static bool panicking = false; 654 + static DEFINE_SPINLOCK(lock); 655 + unsigned long flags; 656 + size_t text_len; 657 + unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ; 658 + int rc = -1; 659 + 660 + switch (reason) { 661 + case KMSG_DUMP_RESTART: 662 + case KMSG_DUMP_HALT: 663 + case KMSG_DUMP_POWEROFF: 664 + /* These are almost always orderly shutdowns. */ 665 + return; 666 + case KMSG_DUMP_OOPS: 667 + break; 668 + case KMSG_DUMP_PANIC: 669 + panicking = true; 670 + break; 671 + case KMSG_DUMP_EMERG: 672 + if (panicking) 673 + /* Panic report already captured. */ 674 + return; 675 + break; 676 + default: 677 + pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n", 678 + __func__, (int) reason); 679 + return; 680 + } 681 + 682 + if (clobbering_unread_rtas_event()) 683 + return; 684 + 685 + if (!spin_trylock_irqsave(&lock, flags)) 686 + return; 687 + 688 + if (big_oops_buf) { 689 + kmsg_dump_get_buffer(dumper, false, 690 + big_oops_buf, big_oops_buf_sz, &text_len); 691 + rc = zip_oops(text_len); 692 + } 693 + if (rc != 0) { 694 + kmsg_dump_rewind(dumper); 695 + kmsg_dump_get_buffer(dumper, false, 696 + oops_data, oops_data_sz, &text_len); 697 + err_type = ERR_TYPE_KERNEL_PANIC; 698 + oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); 699 + oops_hdr->report_length = cpu_to_be16(text_len); 700 + oops_hdr->timestamp = cpu_to_be64(get_seconds()); 701 + } 702 + 703 + (void) nvram_write_os_partition(&oops_log_partition, oops_buf, 704 + (int) (sizeof(*oops_hdr) + text_len), err_type, 705 + ++oops_count); 706 + 707 + spin_unlock_irqrestore(&lock, flags); 708 + } 59 709 60 710 static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) 61 711 {
+1
arch/powerpc/platforms/Kconfig.cputype
··· 2 2 bool "64-bit kernel" 3 3 default n 4 4 select HAVE_VIRT_CPU_ACCOUNTING 5 + select ZLIB_DEFLATE 5 6 help 6 7 This option selects whether a 32-bit or a 64-bit kernel 7 8 will be built.
-1
arch/powerpc/platforms/pseries/Kconfig
··· 16 16 select PPC_UDBG_16550 17 17 select PPC_NATIVE 18 18 select PPC_PCI_CHOICE if EXPERT 19 - select ZLIB_DEFLATE 20 19 select PPC_DOORBELL 21 20 select HAVE_CONTEXT_TRACKING 22 21 select HOTPLUG_CPU if SMP
+5 -661
arch/powerpc/platforms/pseries/nvram.c
··· 20 20 #include <linux/kmsg_dump.h> 21 21 #include <linux/pstore.h> 22 22 #include <linux/ctype.h> 23 - #include <linux/zlib.h> 24 23 #include <asm/uaccess.h> 25 24 #include <asm/nvram.h> 26 25 #include <asm/rtas.h> ··· 29 30 /* Max bytes to read/write in one go */ 30 31 #define NVRW_CNT 0x20 31 32 32 - /* 33 - * Set oops header version to distinguish 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 - 39 33 static unsigned int nvram_size; 40 34 static int nvram_fetch, nvram_store; 41 35 static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ 42 36 static DEFINE_SPINLOCK(nvram_lock); 43 37 44 - struct err_log_info { 45 - __be32 error_type; 46 - __be32 seq_num; 47 - }; 48 - 49 - struct nvram_os_partition { 50 - const char *name; 51 - int req_size; /* desired size, in bytes */ 52 - int min_size; /* minimum acceptable size (0 means req_size) */ 53 - long size; /* size of data portion (excluding err_log_info) */ 54 - long index; /* offset of data portion of partition */ 55 - bool os_partition; /* partition initialized by OS, not FW */ 56 - }; 57 - 58 - static struct nvram_os_partition rtas_log_partition = { 59 - .name = "ibm,rtas-log", 60 - .req_size = 2079, 61 - .min_size = 1055, 62 - .index = -1, 63 - .os_partition = true 64 - }; 65 - 66 - static struct nvram_os_partition oops_log_partition = { 67 - .name = "lnx,oops-log", 68 - .req_size = 4000, 69 - .min_size = 2000, 70 - .index = -1, 71 - .os_partition = true 72 - }; 73 - 74 - static const char *pseries_nvram_os_partitions[] = { 75 - "ibm,rtas-log", 76 - "lnx,oops-log", 77 - NULL 78 - }; 79 - 80 - struct oops_log_info { 81 - __be16 version; 82 - __be16 report_length; 83 - __be64 timestamp; 84 - } __attribute__((packed)); 85 - 86 - static void oops_to_nvram(struct kmsg_dumper *dumper, 87 - enum kmsg_dump_reason reason); 88 - 89 - static struct kmsg_dumper nvram_kmsg_dumper = { 90 - .dump = oops_to_nvram 91 - }; 92 - 93 38 /* See clobbering_unread_rtas_event() */ 94 39 #define NVRAM_RTAS_READ_TIMEOUT 5 /* seconds */ 95 40 static unsigned long last_unread_rtas_event; /* timestamp */ 96 41 97 - /* 98 - * For capturing and compressing an oops or panic report... 99 - 100 - * big_oops_buf[] holds the uncompressed text we're capturing. 101 - * 102 - * oops_buf[] holds the compressed text, preceded by a oops header. 103 - * oops header has u16 holding the version of oops header (to differentiate 104 - * between old and new format header) followed by u16 holding the length of 105 - * the compressed* text (*Or uncompressed, if compression fails.) and u64 106 - * holding the timestamp. oops_buf[] gets written to NVRAM. 107 - * 108 - * oops_log_info points to the header. oops_data points to the compressed text. 109 - * 110 - * +- oops_buf 111 - * | +- oops_data 112 - * v v 113 - * +-----------+-----------+-----------+------------------------+ 114 - * | version | length | timestamp | text | 115 - * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes) | 116 - * +-----------+-----------+-----------+------------------------+ 117 - * ^ 118 - * +- oops_log_info 119 - * 120 - * We preallocate these buffers during init to avoid kmalloc during oops/panic. 121 - */ 122 - static size_t big_oops_buf_sz; 123 - static char *big_oops_buf, *oops_buf; 124 - static char *oops_data; 125 - static size_t oops_data_sz; 126 - 127 - /* Compression parameters */ 128 - #define COMPR_LEVEL 6 129 - #define WINDOW_BITS 12 130 - #define MEM_LEVEL 4 131 - static struct z_stream_s stream; 132 - 133 42 #ifdef CONFIG_PSTORE 134 - static struct nvram_os_partition of_config_partition = { 135 - .name = "of-config", 136 - .index = -1, 137 - .os_partition = false 138 - }; 139 - 140 - static struct nvram_os_partition common_partition = { 141 - .name = "common", 142 - .index = -1, 143 - .os_partition = false 144 - }; 145 - 146 - static enum pstore_type_id nvram_type_ids[] = { 147 - PSTORE_TYPE_DMESG, 148 - PSTORE_TYPE_PPC_RTAS, 149 - PSTORE_TYPE_PPC_OF, 150 - PSTORE_TYPE_PPC_COMMON, 151 - -1 152 - }; 153 - static int read_type; 154 - static unsigned long last_rtas_event; 43 + unsigned long last_rtas_event; 155 44 #endif 156 45 157 46 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) ··· 133 246 return nvram_size ? nvram_size : -ENODEV; 134 247 } 135 248 136 - 137 - /* nvram_write_os_partition, nvram_write_error_log 249 + /* nvram_write_error_log 138 250 * 139 251 * We need to buffer the error logs into nvram to ensure that we have 140 - * the failure information to decode. If we have a severe error there 141 - * is no way to guarantee that the OS or the machine is in a state to 142 - * get back to user land and write the error to disk. For example if 143 - * the SCSI device driver causes a Machine Check by writing to a bad 144 - * IO address, there is no way of guaranteeing that the device driver 145 - * is in any state that is would also be able to write the error data 146 - * captured to disk, thus we buffer it in NVRAM for analysis on the 147 - * next boot. 148 - * 149 - * In NVRAM the partition containing the error log buffer will looks like: 150 - * Header (in bytes): 151 - * +-----------+----------+--------+------------+------------------+ 152 - * | signature | checksum | length | name | data | 153 - * |0 |1 |2 3|4 15|16 length-1| 154 - * +-----------+----------+--------+------------+------------------+ 155 - * 156 - * The 'data' section would look like (in bytes): 157 - * +--------------+------------+-----------------------------------+ 158 - * | event_logged | sequence # | error log | 159 - * |0 3|4 7|8 error_log_size-1| 160 - * +--------------+------------+-----------------------------------+ 161 - * 162 - * event_logged: 0 if event has not been logged to syslog, 1 if it has 163 - * sequence #: The unique sequence # for each event. (until it wraps) 164 - * error log: The error log from event_scan 252 + * the failure information to decode. 165 253 */ 166 - static int nvram_write_os_partition(struct nvram_os_partition *part, 167 - char *buff, int length, 168 - unsigned int err_type, 169 - unsigned int error_log_cnt) 170 - { 171 - int rc; 172 - loff_t tmp_index; 173 - struct err_log_info info; 174 - 175 - if (part->index == -1) { 176 - return -ESPIPE; 177 - } 178 - 179 - if (length > part->size) { 180 - length = part->size; 181 - } 182 - 183 - info.error_type = cpu_to_be32(err_type); 184 - info.seq_num = cpu_to_be32(error_log_cnt); 185 - 186 - tmp_index = part->index; 187 - 188 - rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index); 189 - if (rc <= 0) { 190 - pr_err("%s: Failed nvram_write (%d)\n", __func__, rc); 191 - return rc; 192 - } 193 - 194 - rc = ppc_md.nvram_write(buff, length, &tmp_index); 195 - if (rc <= 0) { 196 - pr_err("%s: Failed nvram_write (%d)\n", __func__, rc); 197 - return rc; 198 - } 199 - 200 - return 0; 201 - } 202 - 203 254 int nvram_write_error_log(char * buff, int length, 204 255 unsigned int err_type, unsigned int error_log_cnt) 205 256 { ··· 151 326 } 152 327 153 328 return rc; 154 - } 155 - 156 - /* nvram_read_partition 157 - * 158 - * Reads nvram partition for at most 'length' 159 - */ 160 - static int nvram_read_partition(struct nvram_os_partition *part, char *buff, 161 - int length, unsigned int *err_type, 162 - unsigned int *error_log_cnt) 163 - { 164 - int rc; 165 - loff_t tmp_index; 166 - struct err_log_info info; 167 - 168 - if (part->index == -1) 169 - return -1; 170 - 171 - if (length > part->size) 172 - length = part->size; 173 - 174 - tmp_index = part->index; 175 - 176 - if (part->os_partition) { 177 - rc = ppc_md.nvram_read((char *)&info, 178 - sizeof(struct err_log_info), 179 - &tmp_index); 180 - if (rc <= 0) { 181 - pr_err("%s: Failed nvram_read (%d)\n", __func__, rc); 182 - return rc; 183 - } 184 - } 185 - 186 - rc = ppc_md.nvram_read(buff, length, &tmp_index); 187 - if (rc <= 0) { 188 - pr_err("%s: Failed nvram_read (%d)\n", __func__, rc); 189 - return rc; 190 - } 191 - 192 - if (part->os_partition) { 193 - *error_log_cnt = be32_to_cpu(info.seq_num); 194 - *err_type = be32_to_cpu(info.error_type); 195 - } 196 - 197 - return 0; 198 329 } 199 330 200 331 /* nvram_read_error_log ··· 188 407 return 0; 189 408 } 190 409 191 - /* pseries_nvram_init_os_partition 192 - * 193 - * This sets up a partition with an "OS" signature. 194 - * 195 - * The general strategy is the following: 196 - * 1.) If a partition with the indicated name already exists... 197 - * - If it's large enough, use it. 198 - * - Otherwise, recycle it and keep going. 199 - * 2.) Search for a free partition that is large enough. 200 - * 3.) If there's not a free partition large enough, recycle any obsolete 201 - * OS partitions and try again. 202 - * 4.) Will first try getting a chunk that will satisfy the requested size. 203 - * 5.) If a chunk of the requested size cannot be allocated, then try finding 204 - * a chunk that will satisfy the minum needed. 205 - * 206 - * Returns 0 on success, else -1. 207 - */ 208 - static int __init pseries_nvram_init_os_partition(struct nvram_os_partition 209 - *part) 210 - { 211 - loff_t p; 212 - int size; 213 - 214 - /* Look for ours */ 215 - p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size); 216 - 217 - /* Found one but too small, remove it */ 218 - if (p && size < part->min_size) { 219 - pr_info("nvram: Found too small %s partition," 220 - " removing it...\n", part->name); 221 - nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL); 222 - p = 0; 223 - } 224 - 225 - /* Create one if we didn't find */ 226 - if (!p) { 227 - p = nvram_create_partition(part->name, NVRAM_SIG_OS, 228 - part->req_size, part->min_size); 229 - if (p == -ENOSPC) { 230 - pr_info("nvram: No room to create %s partition, " 231 - "deleting any obsolete OS partitions...\n", 232 - part->name); 233 - nvram_remove_partition(NULL, NVRAM_SIG_OS, 234 - pseries_nvram_os_partitions); 235 - p = nvram_create_partition(part->name, NVRAM_SIG_OS, 236 - part->req_size, part->min_size); 237 - } 238 - } 239 - 240 - if (p <= 0) { 241 - pr_err("nvram: Failed to find or create %s" 242 - " partition, err %d\n", part->name, (int)p); 243 - return -1; 244 - } 245 - 246 - part->index = p; 247 - part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info); 248 - 249 - return 0; 250 - } 251 - 252 410 /* 253 411 * Are we using the ibm,rtas-log for oops/panic reports? And if so, 254 412 * would logging this oops/panic overwrite an RTAS event that rtas_errd ··· 196 476 * We assume that if rtas_errd hasn't read the RTAS event in 197 477 * NVRAM_RTAS_READ_TIMEOUT seconds, it's probably not going to. 198 478 */ 199 - static int clobbering_unread_rtas_event(void) 479 + int clobbering_unread_rtas_event(void) 200 480 { 201 481 return (oops_log_partition.index == rtas_log_partition.index 202 482 && last_unread_rtas_event 203 483 && get_seconds() - last_unread_rtas_event <= 204 484 NVRAM_RTAS_READ_TIMEOUT); 205 - } 206 - 207 - /* Derived from logfs_compress() */ 208 - static int nvram_compress(const void *in, void *out, size_t inlen, 209 - size_t outlen) 210 - { 211 - int err, ret; 212 - 213 - ret = -EIO; 214 - err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS, 215 - MEM_LEVEL, Z_DEFAULT_STRATEGY); 216 - if (err != Z_OK) 217 - goto error; 218 - 219 - stream.next_in = in; 220 - stream.avail_in = inlen; 221 - stream.total_in = 0; 222 - stream.next_out = out; 223 - stream.avail_out = outlen; 224 - stream.total_out = 0; 225 - 226 - err = zlib_deflate(&stream, Z_FINISH); 227 - if (err != Z_STREAM_END) 228 - goto error; 229 - 230 - err = zlib_deflateEnd(&stream); 231 - if (err != Z_OK) 232 - goto error; 233 - 234 - if (stream.total_out >= stream.total_in) 235 - goto error; 236 - 237 - ret = stream.total_out; 238 - error: 239 - return ret; 240 - } 241 - 242 - /* Compress the text from big_oops_buf into oops_buf. */ 243 - static int zip_oops(size_t text_len) 244 - { 245 - struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; 246 - int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len, 247 - oops_data_sz); 248 - if (zipped_len < 0) { 249 - pr_err("nvram: compression failed; returned %d\n", zipped_len); 250 - pr_err("nvram: logging uncompressed oops/panic report\n"); 251 - return -1; 252 - } 253 - oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); 254 - oops_hdr->report_length = cpu_to_be16(zipped_len); 255 - oops_hdr->timestamp = cpu_to_be64(get_seconds()); 256 - return 0; 257 - } 258 - 259 - #ifdef CONFIG_PSTORE 260 - static int nvram_pstore_open(struct pstore_info *psi) 261 - { 262 - /* Reset the iterator to start reading partitions again */ 263 - read_type = -1; 264 - return 0; 265 - } 266 - 267 - /** 268 - * nvram_pstore_write - pstore write callback for nvram 269 - * @type: Type of message logged 270 - * @reason: reason behind dump (oops/panic) 271 - * @id: identifier to indicate the write performed 272 - * @part: pstore writes data to registered buffer in parts, 273 - * part number will indicate the same. 274 - * @count: Indicates oops count 275 - * @compressed: Flag to indicate the log is compressed 276 - * @size: number of bytes written to the registered buffer 277 - * @psi: registered pstore_info structure 278 - * 279 - * Called by pstore_dump() when an oops or panic report is logged in the 280 - * printk buffer. 281 - * Returns 0 on successful write. 282 - */ 283 - static int nvram_pstore_write(enum pstore_type_id type, 284 - enum kmsg_dump_reason reason, 285 - u64 *id, unsigned int part, int count, 286 - bool compressed, size_t size, 287 - struct pstore_info *psi) 288 - { 289 - int rc; 290 - unsigned int err_type = ERR_TYPE_KERNEL_PANIC; 291 - struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf; 292 - 293 - /* part 1 has the recent messages from printk buffer */ 294 - if (part > 1 || type != PSTORE_TYPE_DMESG || 295 - clobbering_unread_rtas_event()) 296 - return -1; 297 - 298 - oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); 299 - oops_hdr->report_length = cpu_to_be16(size); 300 - oops_hdr->timestamp = cpu_to_be64(get_seconds()); 301 - 302 - if (compressed) 303 - err_type = ERR_TYPE_KERNEL_PANIC_GZ; 304 - 305 - rc = nvram_write_os_partition(&oops_log_partition, oops_buf, 306 - (int) (sizeof(*oops_hdr) + size), err_type, count); 307 - 308 - if (rc != 0) 309 - return rc; 310 - 311 - *id = part; 312 - return 0; 313 - } 314 - 315 - /* 316 - * Reads the oops/panic report, rtas, of-config and common partition. 317 - * Returns the length of the data we read from each partition. 318 - * Returns 0 if we've been called before. 319 - */ 320 - static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, 321 - int *count, struct timespec *time, char **buf, 322 - bool *compressed, struct pstore_info *psi) 323 - { 324 - struct oops_log_info *oops_hdr; 325 - unsigned int err_type, id_no, size = 0; 326 - struct nvram_os_partition *part = NULL; 327 - char *buff = NULL; 328 - int sig = 0; 329 - loff_t p; 330 - 331 - read_type++; 332 - 333 - switch (nvram_type_ids[read_type]) { 334 - case PSTORE_TYPE_DMESG: 335 - part = &oops_log_partition; 336 - *type = PSTORE_TYPE_DMESG; 337 - break; 338 - case PSTORE_TYPE_PPC_RTAS: 339 - part = &rtas_log_partition; 340 - *type = PSTORE_TYPE_PPC_RTAS; 341 - time->tv_sec = last_rtas_event; 342 - time->tv_nsec = 0; 343 - break; 344 - case PSTORE_TYPE_PPC_OF: 345 - sig = NVRAM_SIG_OF; 346 - part = &of_config_partition; 347 - *type = PSTORE_TYPE_PPC_OF; 348 - *id = PSTORE_TYPE_PPC_OF; 349 - time->tv_sec = 0; 350 - time->tv_nsec = 0; 351 - break; 352 - case PSTORE_TYPE_PPC_COMMON: 353 - sig = NVRAM_SIG_SYS; 354 - part = &common_partition; 355 - *type = PSTORE_TYPE_PPC_COMMON; 356 - *id = PSTORE_TYPE_PPC_COMMON; 357 - time->tv_sec = 0; 358 - time->tv_nsec = 0; 359 - break; 360 - default: 361 - return 0; 362 - } 363 - 364 - if (!part->os_partition) { 365 - p = nvram_find_partition(part->name, sig, &size); 366 - if (p <= 0) { 367 - pr_err("nvram: Failed to find partition %s, " 368 - "err %d\n", part->name, (int)p); 369 - return 0; 370 - } 371 - part->index = p; 372 - part->size = size; 373 - } 374 - 375 - buff = kmalloc(part->size, GFP_KERNEL); 376 - 377 - if (!buff) 378 - return -ENOMEM; 379 - 380 - if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) { 381 - kfree(buff); 382 - return 0; 383 - } 384 - 385 - *count = 0; 386 - 387 - if (part->os_partition) 388 - *id = id_no; 389 - 390 - if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { 391 - size_t length, hdr_size; 392 - 393 - oops_hdr = (struct oops_log_info *)buff; 394 - if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) { 395 - /* Old format oops header had 2-byte record size */ 396 - hdr_size = sizeof(u16); 397 - length = be16_to_cpu(oops_hdr->version); 398 - time->tv_sec = 0; 399 - time->tv_nsec = 0; 400 - } else { 401 - hdr_size = sizeof(*oops_hdr); 402 - length = be16_to_cpu(oops_hdr->report_length); 403 - time->tv_sec = be64_to_cpu(oops_hdr->timestamp); 404 - time->tv_nsec = 0; 405 - } 406 - *buf = kmalloc(length, GFP_KERNEL); 407 - if (*buf == NULL) 408 - return -ENOMEM; 409 - memcpy(*buf, buff + hdr_size, length); 410 - kfree(buff); 411 - 412 - if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) 413 - *compressed = true; 414 - else 415 - *compressed = false; 416 - return length; 417 - } 418 - 419 - *buf = buff; 420 - return part->size; 421 - } 422 - 423 - static struct pstore_info nvram_pstore_info = { 424 - .owner = THIS_MODULE, 425 - .name = "nvram", 426 - .open = nvram_pstore_open, 427 - .read = nvram_pstore_read, 428 - .write = nvram_pstore_write, 429 - }; 430 - 431 - static int nvram_pstore_init(void) 432 - { 433 - int rc = 0; 434 - 435 - nvram_pstore_info.buf = oops_data; 436 - nvram_pstore_info.bufsize = oops_data_sz; 437 - 438 - spin_lock_init(&nvram_pstore_info.buf_lock); 439 - 440 - rc = pstore_register(&nvram_pstore_info); 441 - if (rc != 0) 442 - pr_err("nvram: pstore_register() failed, defaults to " 443 - "kmsg_dump; returned %d\n", rc); 444 - 445 - return rc; 446 - } 447 - #else 448 - static int nvram_pstore_init(void) 449 - { 450 - return -1; 451 - } 452 - #endif 453 - 454 - static void __init nvram_init_oops_partition(int rtas_partition_exists) 455 - { 456 - int rc; 457 - 458 - rc = pseries_nvram_init_os_partition(&oops_log_partition); 459 - if (rc != 0) { 460 - if (!rtas_partition_exists) 461 - return; 462 - pr_notice("nvram: Using %s partition to log both" 463 - " RTAS errors and oops/panic reports\n", 464 - rtas_log_partition.name); 465 - memcpy(&oops_log_partition, &rtas_log_partition, 466 - sizeof(rtas_log_partition)); 467 - } 468 - oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL); 469 - if (!oops_buf) { 470 - pr_err("nvram: No memory for %s partition\n", 471 - oops_log_partition.name); 472 - return; 473 - } 474 - oops_data = oops_buf + sizeof(struct oops_log_info); 475 - oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info); 476 - 477 - rc = nvram_pstore_init(); 478 - 479 - if (!rc) 480 - return; 481 - 482 - /* 483 - * Figure compression (preceded by elimination of each line's <n> 484 - * severity prefix) will reduce the oops/panic report to at most 485 - * 45% of its original size. 486 - */ 487 - big_oops_buf_sz = (oops_data_sz * 100) / 45; 488 - big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); 489 - if (big_oops_buf) { 490 - stream.workspace = kmalloc(zlib_deflate_workspacesize( 491 - WINDOW_BITS, MEM_LEVEL), GFP_KERNEL); 492 - if (!stream.workspace) { 493 - pr_err("nvram: No memory for compression workspace; " 494 - "skipping compression of %s partition data\n", 495 - oops_log_partition.name); 496 - kfree(big_oops_buf); 497 - big_oops_buf = NULL; 498 - } 499 - } else { 500 - pr_err("No memory for uncompressed %s data; " 501 - "skipping compression\n", oops_log_partition.name); 502 - stream.workspace = NULL; 503 - } 504 - 505 - rc = kmsg_dump_register(&nvram_kmsg_dumper); 506 - if (rc != 0) { 507 - pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc); 508 - kfree(oops_buf); 509 - kfree(big_oops_buf); 510 - kfree(stream.workspace); 511 - } 512 485 } 513 486 514 487 static int __init pseries_nvram_init_log_partitions(void) ··· 211 798 /* Scan nvram for partitions */ 212 799 nvram_scan_partitions(); 213 800 214 - rc = pseries_nvram_init_os_partition(&rtas_log_partition); 801 + rc = nvram_init_os_partition(&rtas_log_partition); 215 802 nvram_init_oops_partition(rc == 0); 216 803 return 0; 217 804 } ··· 247 834 return 0; 248 835 } 249 836 250 - 251 - /* 252 - * This is our kmsg_dump callback, called after an oops or panic report 253 - * has been written to the printk buffer. We want to capture as much 254 - * of the printk buffer as possible. First, capture as much as we can 255 - * that we think will compress sufficiently to fit in the lnx,oops-log 256 - * partition. If that's too much, go back and capture uncompressed text. 257 - */ 258 - static void oops_to_nvram(struct kmsg_dumper *dumper, 259 - enum kmsg_dump_reason reason) 260 - { 261 - struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; 262 - static unsigned int oops_count = 0; 263 - static bool panicking = false; 264 - static DEFINE_SPINLOCK(lock); 265 - unsigned long flags; 266 - size_t text_len; 267 - unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ; 268 - int rc = -1; 269 - 270 - switch (reason) { 271 - case KMSG_DUMP_RESTART: 272 - case KMSG_DUMP_HALT: 273 - case KMSG_DUMP_POWEROFF: 274 - /* These are almost always orderly shutdowns. */ 275 - return; 276 - case KMSG_DUMP_OOPS: 277 - break; 278 - case KMSG_DUMP_PANIC: 279 - panicking = true; 280 - break; 281 - case KMSG_DUMP_EMERG: 282 - if (panicking) 283 - /* Panic report already captured. */ 284 - return; 285 - break; 286 - default: 287 - pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n", 288 - __func__, (int) reason); 289 - return; 290 - } 291 - 292 - if (clobbering_unread_rtas_event()) 293 - return; 294 - 295 - if (!spin_trylock_irqsave(&lock, flags)) 296 - return; 297 - 298 - if (big_oops_buf) { 299 - kmsg_dump_get_buffer(dumper, false, 300 - big_oops_buf, big_oops_buf_sz, &text_len); 301 - rc = zip_oops(text_len); 302 - } 303 - if (rc != 0) { 304 - kmsg_dump_rewind(dumper); 305 - kmsg_dump_get_buffer(dumper, false, 306 - oops_data, oops_data_sz, &text_len); 307 - err_type = ERR_TYPE_KERNEL_PANIC; 308 - oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); 309 - oops_hdr->report_length = cpu_to_be16(text_len); 310 - oops_hdr->timestamp = cpu_to_be64(get_seconds()); 311 - } 312 - 313 - (void) nvram_write_os_partition(&oops_log_partition, oops_buf, 314 - (int) (sizeof(*oops_hdr) + text_len), err_type, 315 - ++oops_count); 316 - 317 - spin_unlock_irqrestore(&lock, flags); 318 - }