static ulong ramoops_pmsg_size = MIN_MEM_SIZE;
module_param_named(pmsg_size, ramoops_pmsg_size, ulong, 0400);
MODULE_PARM_DESC(pmsg_size, "size of user space message log");
staticunsignedlonglong mem_address;
module_param_hw(mem_address, ullong, other, 0400);
MODULE_PARM_DESC(mem_address, "start of reserved RAM used to store oops/panic logs");
staticchar *mem_name;
module_param_named(mem_name, mem_name, charp, 0400);
MODULE_PARM_DESC(mem_name, "name of kernel param that holds addr");
static ulong mem_size;
module_param(mem_size, ulong, 0400);
MODULE_PARM_DESC(mem_size, "size of reserved RAM used to store oops/panic logs");
staticint ramoops_max_reason = -1;
module_param_named(max_reason, ramoops_max_reason, int, 0400);
MODULE_PARM_DESC(max_reason, "maximum reason for kmsg dump (default 2: Oops and Panic) ");
staticint ramoops_ecc;
module_param_named(ecc, ramoops_ecc, int, 0400);
MODULE_PARM_DESC(ramoops_ecc, "if non-zero, the option enables ECC support and specifies " "ECC buffer size in bytes (1 is a special value, means 16 " "bytes ECC)");
staticint ramoops_dump_oops = -1;
module_param_named(dump_oops, ramoops_dump_oops, int, 0400);
MODULE_PARM_DESC(dump_oops, "(deprecated: use max_reason instead) set to 1 to dump oopses & panics, 0 to only dump panics");
/* * Ramoops headers provide time stamps for PSTORE_TYPE_DMESG, but * PSTORE_TYPE_CONSOLE and PSTORE_TYPE_FTRACE don't currently have * valid time stamps, so it is initialized to zero.
*/
record->time.tv_sec = 0;
record->time.tv_nsec = 0;
record->compressed = false;
/* Find the next valid persistent_ram_zone for DMESG */ while (cxt->dump_read_cnt < cxt->max_dump_cnt && !prz) {
prz = ramoops_get_next_prz(cxt->dprzs, cxt->dump_read_cnt++,
record); if (!prz_ok(prz)) continue;
header_length = ramoops_read_kmsg_hdr(persistent_ram_old(prz),
&record->time,
&record->compressed); /* Clear and skip this DMESG record if it has no valid header */ if (!header_length) {
persistent_ram_free_old(prz);
persistent_ram_zap(prz);
prz = NULL;
}
}
if (!prz_ok(prz) && !cxt->console_read_cnt++)
prz = ramoops_get_next_prz(&cxt->cprz, 0 /* single */, record);
if (!prz_ok(prz) && !cxt->pmsg_read_cnt++)
prz = ramoops_get_next_prz(&cxt->mprz, 0 /* single */, record);
/* ftrace is last since it may want to dynamically allocate memory. */ if (!prz_ok(prz)) { if (!(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU) &&
!cxt->ftrace_read_cnt++) {
prz = ramoops_get_next_prz(cxt->fprzs, 0 /* single */,
record);
} else { /* * Build a new dummy record which combines all the * per-cpu records including metadata and ecc info.
*/ struct persistent_ram_zone *tmp_prz, *prz_next;
if (record->type == PSTORE_TYPE_CONSOLE) { if (!cxt->cprz) return -ENOMEM;
persistent_ram_write(cxt->cprz, record->buf, record->size); return 0;
} elseif (record->type == PSTORE_TYPE_FTRACE) { int zonenum;
if (!cxt->fprzs) return -ENOMEM; /* * Choose zone by if we're using per-cpu buffers.
*/ if (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
zonenum = smp_processor_id(); else
zonenum = 0;
if (record->type != PSTORE_TYPE_DMESG) return -EINVAL;
/* * We could filter on record->reason here if we wanted to (which * would duplicate what happened before the "max_reason" setting * was added), but that would defeat the purpose of a system * changing printk.always_kmsg_dump, so instead log everything that * the kmsg dumper sends us, since it should be doing the filtering * based on the combination of printk.always_kmsg_dump and our * requested "max_reason".
*/
/* * Explicitly only take the first part of any new crash. * If our buffer is larger than kmsg_bytes, this can never happen, * and if our buffer is smaller than kmsg_bytes, we don't want the * report split across multiple records.
*/ if (record->part != 1) return -ENOSPC;
if (!cxt->dprzs) return -ENOSPC;
prz = cxt->dprzs[cxt->dump_write_cnt];
/* * Since this is a new crash dump, we need to reset the buffer in * case it still has an old dump present. Without this, the new dump * will get appended, which would seriously confuse anything trying * to check dump file contents. Specifically, ramoops_read_kmsg_hdr() * expects to find a dump header in the beginning of buffer data, so * we must to reset the buffer values, in order to ensure that the * header will be written to the beginning of the buffer.
*/
persistent_ram_zap(prz);
/* Build header and append record contents. */
hlen = ramoops_write_kmsg_hdr(prz, record); if (!hlen) return -ENOMEM;
/* Allocate nothing for 0 mem_sz or 0 record_size. */ if (mem_sz == 0 || record_size == 0) {
*cnt = 0; return 0;
}
/* * If we have a negative record size, calculate it based on * mem_sz / *cnt. If we have a positive record size, calculate * cnt from mem_sz / record_size.
*/ if (record_size < 0) { if (*cnt == 0) return 0;
record_size = mem_sz / *cnt; if (record_size == 0) {
dev_err(dev, "%s record size == 0 (%zu / %u)\n",
name, mem_sz, *cnt); goto fail;
}
} else {
*cnt = mem_sz / record_size; if (*cnt == 0) {
dev_err(dev, "%s record count == 0 (%zu / %zu)\n",
name, mem_sz, record_size); goto fail;
}
}
if (*paddr + mem_sz - cxt->phys_addr > cxt->size) {
dev_err(dev, "no room for %s mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n",
name,
mem_sz, (unsignedlonglong)*paddr,
cxt->size, (unsignedlonglong)cxt->phys_addr); goto fail;
}
if (*paddr + sz - cxt->phys_addr > cxt->size) {
dev_err(dev, "no room for %s mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n",
name, sz, (unsignedlonglong)*paddr,
cxt->size, (unsignedlonglong)cxt->phys_addr); return -ENOMEM;
}
/* Read a u32 from a dt property and make sure it's safe for an int. */ staticint ramoops_parse_dt_u32(struct platform_device *pdev, constchar *propname,
u32 default_value, u32 *value)
{
u32 val32 = 0; int ret;
ret = of_property_read_u32(pdev->dev.of_node, propname, &val32); if (ret == -EINVAL) { /* field is missing, use default value. */
val32 = default_value;
} elseif (ret < 0) {
dev_err(&pdev->dev, "failed to parse property %s: %d\n",
propname, ret); return ret;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) {
dev_err(&pdev->dev, "failed to locate DT /reserved-memory resource\n"); return -EINVAL;
}
pdata->mem_size = resource_size(res);
pdata->mem_address = res->start; /* * Setting "unbuffered" is deprecated and will be ignored if * "mem_type" is also specified.
*/
pdata->mem_type = of_property_read_bool(of_node, "unbuffered"); /* * Setting "no-dump-oops" is deprecated and will be ignored if * "max_reason" is also specified.
*/ if (of_property_read_bool(of_node, "no-dump-oops"))
pdata->max_reason = KMSG_DUMP_PANIC; else
pdata->max_reason = KMSG_DUMP_OOPS;
#define parse_u32(name, field, default_value) { \
ret = ramoops_parse_dt_u32(pdev, name, default_value, \
&value); \ if (ret < 0) \ return ret; \
field = value; \
}
/* * Some old Chromebooks relied on the kernel setting the * console_size and pmsg_size to the record size since that's * what the downstream kernel did. These same Chromebooks had * "ramoops" straight under the root node which isn't * according to the current upstream bindings (though it was * arguably acceptable under a prior version of the bindings). * Let's make those old Chromebooks work by detecting that * we're not a child of "reserved-memory" and mimicking the * expected behavior.
*/
parent_node = of_get_parent(of_node); if (!of_node_name_eq(parent_node, "reserved-memory") &&
!pdata->console_size && !pdata->ftrace_size &&
!pdata->pmsg_size && !pdata->ecc_info.ecc_size) {
pdata->console_size = pdata->record_size;
pdata->pmsg_size = pdata->record_size;
}
of_node_put(parent_node);
/* * Only a single ramoops area allowed at a time, so fail extra * probes.
*/ if (cxt->max_dump_cnt) {
pr_err("already initialized\n"); goto fail_out;
}
cxt->pstore.data = cxt; /* * Prepare frontend flags based on which areas are initialized. * For ramoops_init_przs() cases, the "max count" variable tells * if there are regions present. For ramoops_init_prz() cases, * the single region size is how to check.
*/
cxt->pstore.flags = 0; if (cxt->max_dump_cnt) {
cxt->pstore.flags |= PSTORE_FLAGS_DMESG;
cxt->pstore.max_reason = pdata->max_reason;
} if (cxt->console_size)
cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE; if (cxt->max_ftrace_cnt)
cxt->pstore.flags |= PSTORE_FLAGS_FTRACE; if (cxt->pmsg_size)
cxt->pstore.flags |= PSTORE_FLAGS_PMSG;
/* * Since bufsize is only used for dmesg crash dumps, it * must match the size of the dprz record (after PRZ header * and ECC bytes have been accounted for).
*/ if (cxt->pstore.flags & PSTORE_FLAGS_DMESG) {
cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size;
cxt->pstore.buf = kvzalloc(cxt->pstore.bufsize, GFP_KERNEL); if (!cxt->pstore.buf) {
pr_err("cannot allocate pstore crash dump buffer\n");
err = -ENOMEM; goto fail_clear;
}
}
err = pstore_register(&cxt->pstore); if (err) {
pr_err("registering with pstore failed\n"); goto fail_buf;
}
/* * Update the module parameter variables as well so they are visible * through /sys/module/ramoops/parameters/
*/
mem_size = pdata->mem_size;
mem_address = pdata->mem_address;
record_size = pdata->record_size;
ramoops_max_reason = pdata->max_reason;
ramoops_console_size = pdata->console_size;
ramoops_pmsg_size = pdata->pmsg_size;
ramoops_ftrace_size = pdata->ftrace_size;
/* * Prepare a dummy platform data structure to carry the module * parameters. If mem_size isn't set, then there are no module * parameters, and we can skip this.
*/ if (!mem_size) return;
pr_info("using module parameters\n");
memset(&pdata, 0, sizeof(pdata));
pdata.mem_size = mem_size;
pdata.mem_address = mem_address;
pdata.mem_type = mem_type;
pdata.record_size = record_size;
pdata.console_size = ramoops_console_size;
pdata.ftrace_size = ramoops_ftrace_size;
pdata.pmsg_size = ramoops_pmsg_size; /* If "max_reason" is set, its value has priority over "dump_oops". */ if (ramoops_max_reason >= 0)
pdata.max_reason = ramoops_max_reason; /* Otherwise, if "dump_oops" is set, parse it into "max_reason". */ elseif (ramoops_dump_oops != -1)
pdata.max_reason = ramoops_dump_oops ? KMSG_DUMP_OOPS
: KMSG_DUMP_PANIC; /* And if neither are explicitly set, use the default. */ else
pdata.max_reason = KMSG_DUMP_OOPS;
pdata.flags = RAMOOPS_FLAG_FTRACE_PER_CPU;
/* * For backwards compatibility ramoops.ecc=1 means 16 bytes ECC * (using 1 byte for ECC isn't much of use anyway).
*/
pdata.ecc_info.ecc_size = ramoops_ecc == 1 ? 16 : ramoops_ecc;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.