Lines Matching +full:no +full:- +full:dump +full:- +full:oops
1 // SPDX-License-Identifier: GPL-2.0-only
3 * RAM Oops/Panic logger
34 "size of each dump done on oops/panic");
59 "start of reserved RAM used to store oops/panic logs");
64 "size of reserved RAM used to store oops/panic logs");
69 "memory type: 0=write-combined (default), 1=unbuffered, 2=cached");
71 static int ramoops_max_reason = -1;
74 "maximum reason for kmsg dump (default 2: Oops and Panic) ");
79 "if non-zero, the option enables ECC support and specifies "
83 static int ramoops_dump_oops = -1;
86 "(deprecated: use max_reason instead) set to 1 to dump oopses & panics, 0 to only dump panics");
89 struct persistent_ram_zone **dprzs; /* Oops dump zones */
120 struct ramoops_context *cxt = psi->data; in ramoops_pstore_open()
122 cxt->dump_read_cnt = 0; in ramoops_pstore_open()
123 cxt->console_read_cnt = 0; in ramoops_pstore_open()
124 cxt->ftrace_read_cnt = 0; in ramoops_pstore_open()
125 cxt->pmsg_read_cnt = 0; in ramoops_pstore_open()
126 cxt->blackbox_read_cnt = 0; in ramoops_pstore_open()
145 if (prz->type == PSTORE_TYPE_DMESG) in ramoops_get_next_prz()
151 record->type = prz->type; in ramoops_get_next_prz()
152 record->id = id; in ramoops_get_next_prz()
163 if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lld.%lu-%c\n%n", in ramoops_read_kmsg_hdr()
164 (time64_t *)&time->tv_sec, &time->tv_nsec, &data_type, in ramoops_read_kmsg_hdr()
166 time->tv_nsec *= 1000; in ramoops_read_kmsg_hdr()
172 (time64_t *)&time->tv_sec, &time->tv_nsec, in ramoops_read_kmsg_hdr()
174 time->tv_nsec *= 1000; in ramoops_read_kmsg_hdr()
177 time->tv_sec = 0; in ramoops_read_kmsg_hdr()
178 time->tv_nsec = 0; in ramoops_read_kmsg_hdr()
193 struct ramoops_context *cxt = record->psi->data; in ramoops_pstore_read()
203 record->time.tv_sec = 0; in ramoops_pstore_read()
204 record->time.tv_nsec = 0; in ramoops_pstore_read()
205 record->compressed = false; in ramoops_pstore_read()
208 while (cxt->dump_read_cnt < cxt->max_dump_cnt && !prz) { in ramoops_pstore_read()
209 prz = ramoops_get_next_prz(cxt->dprzs, cxt->dump_read_cnt++, in ramoops_pstore_read()
214 &record->time, in ramoops_pstore_read()
215 &record->compressed); in ramoops_pstore_read()
216 /* Clear and skip this DMESG record if it has no valid header */ in ramoops_pstore_read()
224 if (!prz_ok(prz) && !cxt->console_read_cnt++) in ramoops_pstore_read()
225 prz = ramoops_get_next_prz(&cxt->cprz, 0 /* single */, record); in ramoops_pstore_read()
227 if (!prz_ok(prz) && !cxt->pmsg_read_cnt++) in ramoops_pstore_read()
228 prz = ramoops_get_next_prz(&cxt->mprz, 0 /* single */, record); in ramoops_pstore_read()
230 if (!prz_ok(prz) && !cxt->blackbox_read_cnt++) in ramoops_pstore_read()
231 prz = ramoops_get_next_prz(&cxt->bprz, 0 /* single */, record); in ramoops_pstore_read()
235 if (!(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU) && in ramoops_pstore_read()
236 !cxt->ftrace_read_cnt++) { in ramoops_pstore_read()
237 prz = ramoops_get_next_prz(cxt->fprzs, 0 /* single */, in ramoops_pstore_read()
242 * per-cpu records including metadata and ecc info. in ramoops_pstore_read()
249 return -ENOMEM; in ramoops_pstore_read()
253 while (cxt->ftrace_read_cnt < cxt->max_ftrace_cnt) { in ramoops_pstore_read()
254 prz_next = ramoops_get_next_prz(cxt->fprzs, in ramoops_pstore_read()
255 cxt->ftrace_read_cnt++, record); in ramoops_pstore_read()
260 tmp_prz->ecc_info = prz_next->ecc_info; in ramoops_pstore_read()
261 tmp_prz->corrected_bytes += in ramoops_pstore_read()
262 prz_next->corrected_bytes; in ramoops_pstore_read()
263 tmp_prz->bad_blocks += prz_next->bad_blocks; in ramoops_pstore_read()
266 &tmp_prz->old_log, in ramoops_pstore_read()
267 &tmp_prz->old_log_size, in ramoops_pstore_read()
268 prz_next->old_log, in ramoops_pstore_read()
269 prz_next->old_log_size); in ramoops_pstore_read()
273 record->id = 0; in ramoops_pstore_read()
282 size = persistent_ram_old_size(prz) - header_length; in ramoops_pstore_read()
285 record->ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0); in ramoops_pstore_read()
287 record->buf = kvzalloc(size + record->ecc_notice_size + 1, GFP_KERNEL); in ramoops_pstore_read()
288 if (record->buf == NULL) { in ramoops_pstore_read()
289 size = -ENOMEM; in ramoops_pstore_read()
293 memcpy(record->buf, (char *)persistent_ram_old(prz) + header_length, in ramoops_pstore_read()
296 persistent_ram_ecc_string(prz, record->buf + size, in ramoops_pstore_read()
297 record->ecc_notice_size + 1); in ramoops_pstore_read()
301 kvfree(prz->old_log); in ramoops_pstore_read()
311 char hdr[36]; /* "===="(4), %lld(20), "."(1), %06lu(6), "-%c\n"(3) */ in ramoops_write_kmsg_hdr()
315 RAMOOPS_KERNMSG_HDR "%lld.%06lu-%c\n", in ramoops_write_kmsg_hdr()
316 (time64_t)record->time.tv_sec, in ramoops_write_kmsg_hdr()
317 record->time.tv_nsec / 1000, in ramoops_write_kmsg_hdr()
318 record->compressed ? 'C' : 'D'); in ramoops_write_kmsg_hdr()
326 struct ramoops_context *cxt = record->psi->data; in ramoops_pstore_write()
330 if (record->type == PSTORE_TYPE_CONSOLE) { in ramoops_pstore_write()
331 if (!cxt->cprz) in ramoops_pstore_write()
332 return -ENOMEM; in ramoops_pstore_write()
333 persistent_ram_write(cxt->cprz, record->buf, record->size); in ramoops_pstore_write()
335 } else if (record->type == PSTORE_TYPE_FTRACE) { in ramoops_pstore_write()
338 if (!cxt->fprzs) in ramoops_pstore_write()
339 return -ENOMEM; in ramoops_pstore_write()
341 * Choose zone by if we're using per-cpu buffers. in ramoops_pstore_write()
343 if (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU) in ramoops_pstore_write()
348 persistent_ram_write(cxt->fprzs[zonenum], record->buf, in ramoops_pstore_write()
349 record->size); in ramoops_pstore_write()
351 } else if (record->type == PSTORE_TYPE_PMSG) { in ramoops_pstore_write()
353 return -EINVAL; in ramoops_pstore_write()
354 } else if (record->type == PSTORE_TYPE_BLACKBOX) { in ramoops_pstore_write()
355 if (!cxt->bprz) in ramoops_pstore_write()
356 return -ENOMEM; in ramoops_pstore_write()
357 persistent_ram_write(cxt->bprz, record->buf, record->size); in ramoops_pstore_write()
361 if (record->type != PSTORE_TYPE_DMESG) in ramoops_pstore_write()
362 return -EINVAL; in ramoops_pstore_write()
365 * We could filter on record->reason here if we wanted to (which in ramoops_pstore_write()
380 if (record->part != 1) in ramoops_pstore_write()
381 return -ENOSPC; in ramoops_pstore_write()
383 if (!cxt->dprzs) in ramoops_pstore_write()
384 return -ENOSPC; in ramoops_pstore_write()
386 prz = cxt->dprzs[cxt->dump_write_cnt]; in ramoops_pstore_write()
389 * Since this is a new crash dump, we need to reset the buffer in in ramoops_pstore_write()
390 * case it still has an old dump present. Without this, the new dump in ramoops_pstore_write()
392 * to check dump file contents. Specifically, ramoops_read_kmsg_hdr() in ramoops_pstore_write()
393 * expects to find a dump header in the beginning of buffer data, so in ramoops_pstore_write()
402 return -ENOMEM; in ramoops_pstore_write()
404 size = record->size; in ramoops_pstore_write()
405 if (size + hlen > prz->buffer_size) in ramoops_pstore_write()
406 size = prz->buffer_size - hlen; in ramoops_pstore_write()
407 persistent_ram_write(prz, record->buf, size); in ramoops_pstore_write()
409 cxt->dump_write_cnt = (cxt->dump_write_cnt + 1) % cxt->max_dump_cnt; in ramoops_pstore_write()
417 if (record->type == PSTORE_TYPE_PMSG) { in ramoops_pstore_write_user()
418 struct ramoops_context *cxt = record->psi->data; in ramoops_pstore_write_user()
420 if (!cxt->mprz) in ramoops_pstore_write_user()
421 return -ENOMEM; in ramoops_pstore_write_user()
422 return persistent_ram_write_user(cxt->mprz, buf, record->size); in ramoops_pstore_write_user()
425 return -EINVAL; in ramoops_pstore_write_user()
430 struct ramoops_context *cxt = record->psi->data; in ramoops_pstore_erase()
433 switch (record->type) { in ramoops_pstore_erase()
435 if (record->id >= cxt->max_dump_cnt) in ramoops_pstore_erase()
436 return -EINVAL; in ramoops_pstore_erase()
437 prz = cxt->dprzs[record->id]; in ramoops_pstore_erase()
440 prz = cxt->cprz; in ramoops_pstore_erase()
443 if (record->id >= cxt->max_ftrace_cnt) in ramoops_pstore_erase()
444 return -EINVAL; in ramoops_pstore_erase()
445 prz = cxt->fprzs[record->id]; in ramoops_pstore_erase()
448 prz = cxt->mprz; in ramoops_pstore_erase()
451 prz = cxt->bprz; in ramoops_pstore_erase()
454 return -EINVAL; in ramoops_pstore_erase()
480 persistent_ram_free(&cxt->mprz); in ramoops_free_przs()
483 persistent_ram_free(&cxt->cprz); in ramoops_free_przs()
485 /* Free dump PRZs */ in ramoops_free_przs()
486 if (cxt->dprzs) { in ramoops_free_przs()
487 for (i = 0; i < cxt->max_dump_cnt; i++) in ramoops_free_przs()
488 persistent_ram_free(&cxt->dprzs[i]); in ramoops_free_przs()
490 kfree(cxt->dprzs); in ramoops_free_przs()
491 cxt->dprzs = NULL; in ramoops_free_przs()
492 cxt->max_dump_cnt = 0; in ramoops_free_przs()
496 if (cxt->fprzs) { in ramoops_free_przs()
497 for (i = 0; i < cxt->max_ftrace_cnt; i++) in ramoops_free_przs()
498 persistent_ram_free(&cxt->fprzs[i]); in ramoops_free_przs()
499 kfree(cxt->fprzs); in ramoops_free_przs()
500 cxt->fprzs = NULL; in ramoops_free_przs()
501 cxt->max_ftrace_cnt = 0; in ramoops_free_przs()
512 int err = -ENOMEM; in ramoops_init_przs()
546 if (*paddr + mem_sz - cxt->phys_addr > cxt->size) { in ramoops_init_przs()
547 dev_err(dev, "no room for %s mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n", in ramoops_init_przs()
550 cxt->size, (unsigned long long)cxt->phys_addr); in ramoops_init_przs()
572 name, i, *cnt - 1); in ramoops_init_przs()
574 &cxt->ecc_info, in ramoops_init_przs()
575 cxt->memtype, flags, label); in ramoops_init_przs()
584 i--; in ramoops_init_przs()
592 prz_ar[i]->type = pstore_name_to_type(name); in ramoops_init_przs()
613 if (*paddr + sz - cxt->phys_addr > cxt->size) { in ramoops_init_prz()
614 dev_err(dev, "no room for %s mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n", in ramoops_init_prz()
616 cxt->size, (unsigned long long)cxt->phys_addr); in ramoops_init_prz()
617 return -ENOMEM; in ramoops_init_prz()
621 *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, in ramoops_init_prz()
622 cxt->memtype, PRZ_FLAG_ZAP_OLD, label); in ramoops_init_prz()
633 (*prz)->type = pstore_name_to_type(name); in ramoops_init_prz()
646 ret = of_property_read_u32(pdev->dev.of_node, propname, &val32); in ramoops_parse_dt_u32()
647 if (ret == -EINVAL) { in ramoops_parse_dt_u32()
651 dev_err(&pdev->dev, "failed to parse property %s: %d\n", in ramoops_parse_dt_u32()
658 dev_err(&pdev->dev, "%s %u > INT_MAX\n", propname, val32); in ramoops_parse_dt_u32()
659 return -EOVERFLOW; in ramoops_parse_dt_u32()
669 struct device_node *of_node = pdev->dev.of_node; in ramoops_parse_dt()
675 dev_dbg(&pdev->dev, "using Device Tree\n"); in ramoops_parse_dt()
679 dev_err(&pdev->dev, in ramoops_parse_dt()
680 "failed to locate DT /reserved-memory resource\n"); in ramoops_parse_dt()
681 return -EINVAL; in ramoops_parse_dt()
684 pdata->mem_size = resource_size(res); in ramoops_parse_dt()
685 pdata->mem_address = res->start; in ramoops_parse_dt()
690 pdata->mem_type = of_property_read_bool(of_node, "unbuffered"); in ramoops_parse_dt()
692 * Setting "no-dump-oops" is deprecated and will be ignored if in ramoops_parse_dt()
695 if (of_property_read_bool(of_node, "no-dump-oops")) in ramoops_parse_dt()
696 pdata->max_reason = KMSG_DUMP_PANIC; in ramoops_parse_dt()
698 pdata->max_reason = KMSG_DUMP_OOPS; in ramoops_parse_dt()
708 parse_u32("mem-type", pdata->mem_type, pdata->mem_type); in ramoops_parse_dt()
709 parse_u32("record-size", pdata->record_size, 0); in ramoops_parse_dt()
710 parse_u32("console-size", pdata->console_size, 0); in ramoops_parse_dt()
711 parse_u32("ftrace-size", pdata->ftrace_size, 0); in ramoops_parse_dt()
712 parse_u32("pmsg-size", pdata->pmsg_size, 0); in ramoops_parse_dt()
713 parse_u32("blackbox-size", pdata->blackbox_size, 0); in ramoops_parse_dt()
714 parse_u32("ecc-size", pdata->ecc_info.ecc_size, 0); in ramoops_parse_dt()
715 parse_u32("flags", pdata->flags, 0); in ramoops_parse_dt()
716 parse_u32("max-reason", pdata->max_reason, pdata->max_reason); in ramoops_parse_dt()
728 * we're not a child of "reserved-memory" and mimicking the in ramoops_parse_dt()
732 if (!of_node_name_eq(parent_node, "reserved-memory") && in ramoops_parse_dt()
733 !pdata->console_size && !pdata->ftrace_size && in ramoops_parse_dt()
734 !pdata->pmsg_size && !pdata->ecc_info.ecc_size && in ramoops_parse_dt()
735 !pdata->blackbox_size) { in ramoops_parse_dt()
736 pdata->console_size = pdata->record_size; in ramoops_parse_dt()
737 pdata->pmsg_size = pdata->record_size; in ramoops_parse_dt()
738 pdata->blackbox_size = pdata->record_size; in ramoops_parse_dt()
747 struct device *dev = &pdev->dev; in ramoops_probe()
748 struct ramoops_platform_data *pdata = dev->platform_data; in ramoops_probe()
753 int err = -EINVAL; in ramoops_probe()
759 if (cxt->max_dump_cnt) { in ramoops_probe()
776 err = -EINVAL; in ramoops_probe()
780 if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size && in ramoops_probe()
781 !pdata->ftrace_size && !pdata->pmsg_size && !pdata->blackbox_size)) { in ramoops_probe()
783 "non-zero\n"); in ramoops_probe()
784 err = -EINVAL; in ramoops_probe()
788 if (pdata->record_size && !is_power_of_2(pdata->record_size)) in ramoops_probe()
789 pdata->record_size = rounddown_pow_of_two(pdata->record_size); in ramoops_probe()
790 if (pdata->console_size && !is_power_of_2(pdata->console_size)) in ramoops_probe()
791 pdata->console_size = rounddown_pow_of_two(pdata->console_size); in ramoops_probe()
792 if (pdata->ftrace_size && !is_power_of_2(pdata->ftrace_size)) in ramoops_probe()
793 pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); in ramoops_probe()
794 if (pdata->pmsg_size && !is_power_of_2(pdata->pmsg_size)) in ramoops_probe()
795 pdata->pmsg_size = rounddown_pow_of_two(pdata->pmsg_size); in ramoops_probe()
796 if (pdata->blackbox_size && !is_power_of_2(pdata->blackbox_size)) in ramoops_probe()
797 pdata->blackbox_size = rounddown_pow_of_two(pdata->blackbox_size); in ramoops_probe()
799 cxt->size = pdata->mem_size; in ramoops_probe()
800 cxt->phys_addr = pdata->mem_address; in ramoops_probe()
801 cxt->memtype = pdata->mem_type; in ramoops_probe()
802 cxt->record_size = pdata->record_size; in ramoops_probe()
803 cxt->console_size = pdata->console_size; in ramoops_probe()
804 cxt->ftrace_size = pdata->ftrace_size; in ramoops_probe()
805 cxt->pmsg_size = pdata->pmsg_size; in ramoops_probe()
806 cxt->blackbox_size = pdata->blackbox_size; in ramoops_probe()
807 cxt->flags = pdata->flags; in ramoops_probe()
808 cxt->ecc_info = pdata->ecc_info; in ramoops_probe()
810 paddr = cxt->phys_addr; in ramoops_probe()
812 dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size in ramoops_probe()
813 - cxt->pmsg_size - cxt->blackbox_size; in ramoops_probe()
814 err = ramoops_init_prz("blackbox", dev, cxt, &cxt->bprz, &paddr, in ramoops_probe()
815 cxt->blackbox_size, 0); in ramoops_probe()
822 err = ramoops_init_przs("dmesg", dev, cxt, &cxt->dprzs, &paddr, in ramoops_probe()
823 dump_mem_sz, cxt->record_size, in ramoops_probe()
824 &cxt->max_dump_cnt, 0, 0); in ramoops_probe()
828 err = ramoops_init_prz("console", dev, cxt, &cxt->cprz, &paddr, in ramoops_probe()
829 cxt->console_size, 0); in ramoops_probe()
833 err = ramoops_init_prz("pmsg", dev, cxt, &cxt->mprz, &paddr, in ramoops_probe()
834 cxt->pmsg_size, 0); in ramoops_probe()
838 cxt->max_ftrace_cnt = (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU) in ramoops_probe()
841 err = ramoops_init_przs("ftrace", dev, cxt, &cxt->fprzs, &paddr, in ramoops_probe()
842 cxt->ftrace_size, -1, in ramoops_probe()
843 &cxt->max_ftrace_cnt, LINUX_VERSION_CODE, in ramoops_probe()
844 (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU) in ramoops_probe()
849 cxt->pstore.data = cxt; in ramoops_probe()
856 cxt->pstore.flags = 0; in ramoops_probe()
857 if (cxt->max_dump_cnt) { in ramoops_probe()
858 cxt->pstore.flags |= PSTORE_FLAGS_DMESG; in ramoops_probe()
859 cxt->pstore.max_reason = pdata->max_reason; in ramoops_probe()
861 if (cxt->console_size) in ramoops_probe()
862 cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE; in ramoops_probe()
863 if (cxt->max_ftrace_cnt) in ramoops_probe()
864 cxt->pstore.flags |= PSTORE_FLAGS_FTRACE; in ramoops_probe()
865 if (cxt->pmsg_size) in ramoops_probe()
866 cxt->pstore.flags |= PSTORE_FLAGS_PMSG; in ramoops_probe()
867 if (cxt->blackbox_size) in ramoops_probe()
868 cxt->pstore.flags |= PSTORE_FLAGS_BLACKBOX; in ramoops_probe()
875 if (cxt->pstore.flags & PSTORE_FLAGS_DMESG) { in ramoops_probe()
876 cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size; in ramoops_probe()
877 cxt->pstore.buf = kvzalloc(cxt->pstore.bufsize, GFP_KERNEL); in ramoops_probe()
878 if (!cxt->pstore.buf) { in ramoops_probe()
879 pr_err("cannot allocate pstore crash dump buffer\n"); in ramoops_probe()
880 err = -ENOMEM; in ramoops_probe()
885 err = pstore_register(&cxt->pstore); in ramoops_probe()
895 mem_size = pdata->mem_size; in ramoops_probe()
896 mem_address = pdata->mem_address; in ramoops_probe()
897 record_size = pdata->record_size; in ramoops_probe()
898 ramoops_max_reason = pdata->max_reason; in ramoops_probe()
899 ramoops_console_size = pdata->console_size; in ramoops_probe()
900 ramoops_pmsg_size = pdata->pmsg_size; in ramoops_probe()
901 ramoops_ftrace_size = pdata->ftrace_size; in ramoops_probe()
902 ramoops_blackbox_size = pdata->blackbox_size; in ramoops_probe()
905 cxt->size, (unsigned long long)cxt->phys_addr, in ramoops_probe()
906 cxt->ecc_info.ecc_size); in ramoops_probe()
911 kvfree(cxt->pstore.buf); in ramoops_probe()
913 cxt->pstore.bufsize = 0; in ramoops_probe()
924 pstore_unregister(&cxt->pstore); in ramoops_remove()
926 kvfree(cxt->pstore.buf); in ramoops_remove()
927 cxt->pstore.bufsize = 0; in ramoops_remove()
958 * parameters. If mem_size isn't set, then there are no module in ramoops_register_dummy()
979 else if (ramoops_dump_oops != -1) in ramoops_register_dummy()
993 dummy = platform_device_register_data(NULL, "ramoops", -1, in ramoops_register_dummy()
1024 MODULE_DESCRIPTION("RAM Oops/Panic logger/driver");