pstore Dump Reasons: Configure Which Oops and Shutdown Events Become Records
“Save crash logs” is an incomplete requirement. A product may need panic evidence, recoverable Oops reports, emergency-restart diagnostics, or a record of orderly shutdown. Those events do not enter ramoops under identical conditions. This guide follows upstream Linux v6.12 and turns the kmsg reason filter into a reviewable event policy. It does not promise a record for every physical reset, and the proposed event matrix has not been executed on a target board.
Define the event, not just the operator’s description
Start with the path that generated the event. An Oops is not necessarily a panic; a configuration that escalates an Oops can produce a different sequence from an Oops after which execution continues. Similarly, an emergency restart is a distinct path from orderly shutdown. A technician saying “it rebooted” has described the visible outcome, not the kmsg dump reason.
For v6.12, the reason enumeration assigns 0 to UNDEF, 1 to PANIC, 2 to OOPS, 3 to EMERG, and 4 to SHUTDOWN; MAX follows as the boundary value. These values form an ordered threshold, not a set of independent flag bits. Verify them against the exact product branch before copying a numeric policy. v6.12 kmsg reason enumeration.
Distinguish an explicit threshold from the default rule
The kmsg dispatcher skips a reason above a dumper’s maximum. When the maximum is UNDEF, it substitutes OOPS unless printk.always_kmsg_dump is enabled, in which case it uses MAX. Therefore an explicit maximum of 1 or 2 is not widened just by enabling always_kmsg_dump. v6.12 kmsg dispatch implementation.
Write the policy in words before encoding it. “Panic only” corresponds to threshold 1; “panic and Oops” corresponds to 2. A value of 0 delegates the threshold decision to the global fallback rule; it does not mean “disable all dumps.” This distinction is especially important when two teams maintain the device tree and boot arguments independently.

Inspect ramoops configuration at the deployed boundary
In the v6.12 ramoops device-tree binding, max-reason defaults to 2. The module-parameter spelling is max_reason, while the device-tree property uses a hyphen. Deprecated dump_oops and no-dump-oops settings require careful interpretation; prefer the current setting in a reviewed product configuration. v6.12 ramoops binding.
# Read-only observations on the target
cat /proc/cmdline
cat /sys/module/ramoops/parameters/max_reason
cat /sys/module/printk/parameters/always_kmsg_dump
dmesg | grep -Ei 'ramoops|persistent store'
If a file is unavailable, retain that observation and inspect the saved deployment artifacts. Do not write a new value merely to discover whether it is accepted. Compare the active device tree, command line, kernel configuration, and startup messages. The driver transfers the effective maximum to the pstore backend; configuration ownership should make clear which input path is in use. v6.12 ramoops configuration handling.
Require a dump call as well as permission to pass
A threshold cannot create an event that the kernel never emits. The ordinary restart, halt, and power-off implementation contains SHUTDOWN dump calls, while the emergency restart path uses EMERG. That source-level fact identifies intended software paths; it does not prove that every board reset switch or firmware reset passes through them. v6.12 restart and shutdown implementation.
For each product event, trace the actual entry point and note any bypass. If the processor stops before the dump call, or the backend is unavailable, an eligible reason still produces no usable record. Keep those conditions out of the filter verdict: mark the event path unproven rather than changing max_reason until some file appears.
Keep console evidence separate from dmesg dumps
The pstore console frontend records kernel console messages independently of an Oops or panic trigger when enabled. A console-ramoops file therefore cannot establish that an event passed the dmesg reason filter. Conversely, its absence does not establish a threshold error. v6.12 console frontend configuration.
Define the expected record type for every test. Record a unique test marker in the controlled workload, capture an external observation of the event, and correlate the next boot’s evidence. Do not use the mere existence of a familiar filename as success: it could belong to a prior incident or another frontend.
Build a safe, discriminating event matrix
Use columns for event entry point, emitted reason, effective threshold, eligibility, expected record type, and observed result. For thresholds 1 and 2, include an Oops case because it distinguishes them. To evaluate the global fallback, compare max_reason=0 with always_kmsg_dump off and on, rather than changing both variables without a control.
Begin with source review and a configuration-only check. Execute disruptive events only on an isolated development system with an approved recovery route and disposable workload. Include an orderly reboot case separately from emergency restart. Preserve the existing evidence first, and record whether an Oops was configured to escalate. A test that accidentally becomes a panic cannot validate an Oops-only expectation.
Use negative expectations deliberately: a filtered event should not create a new dmesg record for that incident. It may still leave console evidence. Check incident identity and collection timing before declaring the negative case passed. No destructive trigger commands are supplied here because a safe entry point is platform- and laboratory-specific.
Deliver an event policy with explicit limits
- Pin the enum and dispatcher behavior to the shipped kernel.
- Document the effective threshold and the role of the global fallback.
- Map each supported event to its actual dump call.
- Distinguish console, dmesg, and unrelated retained records.
- Keep eligibility, successful capture, and later collection as separate results.
The outcome is a precise operational promise: these event paths are intended to produce these record types under these conditions. That statement is more useful than assuming every Oops, reboot, and reset should leave the same crash file.