Skip to content

wb7, wb8: pstore/ramoops panic-log persistence (shuttle kernel side)#359

Draft
evgeny-boger wants to merge 8 commits into
feature/v6.18from
feature/wb-pstore-shuttle-v6.18
Draft

wb7, wb8: pstore/ramoops panic-log persistence (shuttle kernel side)#359
evgeny-boger wants to merge 8 commits into
feature/v6.18from
feature/wb-pstore-shuttle-v6.18

Conversation

@evgeny-boger

Copy link
Copy Markdown
Member

Kernel side of the WB pstore shuttle, targeting feature/v6.18 (most recent kernel line) per project decision — replaces the earlier dev/v6.8 draft (#358, closed). Covers both WB7 (sun8i-r40) and WB8 (sun50i-h616).

What

  1. Config (wb8.config + wirenboard7_defconfig): CONFIG_PSTORE=y, PSTORE_RAM=y, PSTORE_CONSOLE=y. The backing ramoops reserved-memory node is injected at boot by the WB U-Boot DT fixup; without it these are inert.
  2. soc/sunxi/wb-ramoops-panic-reset.c: a panic notifier that arms the idle SoC watchdog (~6 s) so a panicked board takes a DRAM-preserving warm reset; U-Boot then parks the ramoops records on eMMC and does the full recovery power cycle. Two WDT variants resolved from DT (sun6i-a31-wdt for H616, sun4i-a10-wdt for R40) — register layouts/interval mirror drivers/watchdog/sunxi_wdt.c; 6 s has an exact encoding. Gated at runtime on an actual ramoops node → a kernel-only update is a strict no-op (no-lockstep).
  3. mfd/wbec.c: poweron-reason strings for the newer EC firmware (8 warm-watchdog, 9 full-cycle), table converted to designated initializers with a source-of-truth pointer to the EC repo's append-only ABI list.

No-lockstep / degradation

  • Old U-Boot (no DT node): notifier never registers, pstore configs inert → zero behavior change.
  • Old EC: reason 9 shows numeric / "Unknown" on unpatched driver; this patch adds the strings.
  • 6 s interval lets kmsg_dump + serial backtrace complete before the fuse; an operator panic_timeout < 6 s intentionally wins.

Verification

  • wb8: full deb build (linux-image-wb8_6.18.22-wb6+shuttle618) OK; config has all 4 options; wb_ramoops_panic_reset present as a late_initcall. Hardware E2E on WB 8.5: the equivalent module (0.5 s predecessor) + these configs drove panic → warm reset → shuttle save → EC full cycle → restore → systemd-pstore harvest, on both stock EC 2.3.0 (reboot-bit path) and EC 2.4.0 (full_cycle, reason 9). The 6 s DT-resolved version supersedes it; a bench smoke of this exact build is pending.
  • wb7: config-check + standalone wb-ramoops-panic-reset.o compile clean (32-bit ARM via LLVM; the hard-float gcc toolchain wasn't available locally — full wb7 link/deb is a CI item). No WB7 hardware smoke yet; also depends on WB7 U-Boot gaining the ramoops fixup (separate work).

Companion PRs

u-boot-private#85 (shuttle + ramoops fixup, 2025.04), wb-embedded-controller#91 (EC full_cycle bit).

🤖 Generated with Claude Code

https://claude.ai/code/session_01EVPkc2g2yir6SGyrED6uNT

evgeny-boger and others added 5 commits July 5, 2026 22:34
Enable CONFIG_PSTORE_RAM and CONFIG_PSTORE_CONSOLE for the wb8 and wb7
flavours. The backing reserved-memory node (compatible = "ramoops",
last 1 MiB of DRAM, record-size 128K, console-size 256K, ecc 32) is
injected at boot by the Wiren Board U-Boot DT fixup, so kernels running
under an older U-Boot simply see no node and nothing changes. With the
node present, panic and console logs survive warm resets and are
harvested by the already-enabled systemd-pstore.service.

Part of the Wiren Board panic-log persistence (pstore shuttle) work:
U-Boot saves/restores this region across full power cycles via the swap
partition.

Targets feature/v6.18 (most recent kernel line) per project branch
policy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVPkc2g2yir6SGyrED6uNT
…sent

A panicked Wiren Board 7 or 8 otherwise parks until the EC watchdog
acts: on pre-2.4.0 EC firmware that is a full power cycle, destroying
DRAM and the just-written ramoops records; 2.4.0+ warm-resets first.
This panic notifier arms the idle SoC watchdog (~6 s, a few MMIO
writes, safe in panic context) so the board takes a DRAM-preserving
warm reset immediately and firmware-independently; U-Boot then parks
the records on eMMC and performs the full recovery power cycle (pstore
shuttle).

The watchdog is resolved from the device tree by compatible and armed
by mirroring the sunxi_wdt.c restart handler for both register layouts
(sun6i-a31-wdt on H616/T507, sun4i-a10-wdt on R40/A40i), but with a
6 s interval (exact hardware encoding) instead of 0.5 s so kmsg_dump
and the serial console can finish before the reset; a configured
panic_timeout below 6 s intentionally wins.

Gated at runtime on an actual ramoops node (injected by the Wiren
Board U-Boot DT fixup): with an older U-Boot there is no node, the
notifier never registers, and panic behaviour is unchanged - a
kernel-only update is a strict no-op.

Targets feature/v6.18 (most recent kernel line) per project branch
policy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVPkc2g2yir6SGyrED6uNT
EC firmware 2.4.x reports two reasons the driver's string table
predates: 8 = watchdog warm reset (warm-watchdog-reset EC series) and
9 = full power cycle request (used by the U-Boot pstore shuttle after
parking panic logs). Add them, plus the firmware's own placeholder 7
(Unknown) so the indices line up, and convert the table to designated
initializers with a source-of-truth note (mirrors LINUX_POWERON_REASON
in wb-embedded-controller src/wbec.c; append-only ABI). Out-of-range
values still print Unknown, so older kernels against even newer
firmware stay harmless.

Targets feature/v6.18 (most recent kernel line) per project branch
policy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVPkc2g2yir6SGyrED6uNT
Add a reserved-memory ramoops node at the fixed address 0x46000000
(1 MiB, record 128K, console 256K, ecc 32, no-map) to the Wiren Board 7
(sun8i-r40) and Wiren Board 8 (sun50i-h616) family device trees. The
address matches U-Boot WB_RAMOOPS_BASE exactly.

Carrying the node in the kernel DTB (rather than relying only on the
U-Boot DT fixup) is what makes a kernel-only update useful: under an old
U-Boot with no shuttle, the node is still present, the region survives a
warm reset, and the same kernel harvests the panic log on the next boot.
A new U-Boot's fixup yields to this node (it already takes precedence),
and its shuttle adds full-power-cycle survival on top.

Placed in the WB family base dtsis (84x/85x for WB8, 72x/74x for WB7;
73x inherits via 72x) so every shipped board gets it exactly once. The
fixed low address is bench-verified to retain across a warm reset on all
DRAM densities.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVPkc2g2yir6SGyrED6uNT
…stamp

A kernel that panics every boot would warm-reset forever. There is no
hardware reset-cause latch on these SoCs (the watchdog status register
is interrupt-mode only and clears on reset), so use the RTC general-
purpose register documented "for storing power-off information": it
survives a warm reset and is wiped by the EC's hard 5V cycle - exactly
the reset-reason signal needed.

The panic handler stamps RTC GP reg 3 (0x0700010c) before arming the
watchdog. A boot that comes up still stamped knows it just warm-reset
from a panic and declines to re-arm, letting the EC watchdog escalate
to a hard power cycle (which wipes the stamp and breaks the loop). A
60 s healthy-uptime delayed work clears the stamp so ordinary panics
always warm-reset. H616 only for now (the R40 RTC's wipe-on-hard-cycle
behaviour is not yet verified; R40 keeps arming unconditionally).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVPkc2g2yir6SGyrED6uNT
@evgeny-boger

Copy link
Copy Markdown
Member Author

Added FIXED-address ramoops DT node + panic-loop-breaker

Two changes on top of the earlier commits:

  1. Fixed reserved-memory ramoops node at 0x46000000 in the WB7 (sun8i-r40) and WB8 (sun50i-h616) family DTs (84x/85x, 72x/74x; 73x inherits via 72x). Matches U-Boot WB_RAMOOPS_BASE. This is what gives a kernel-only update value: the node is present regardless of U-Boot, so panic logs survive a warm reset and the kernel harvests them with no shuttle. Hardware-proven: on a 4 GiB WB8 with stock no-fixup U-Boot, ramoops probes at 0x46000000 from the DTB alone, and a panic → warm reset → kernel self-harvest captured 40 KB dmesg + console.

  2. Panic-loop-breaker in the notifier. There's no hardware reset-cause latch on these SoCs (watchdog status is interrupt-mode, clears on reset), so I use the RTC general-purpose register documented "for storing power-off information" (GP reg 3, 0x0700010c): it survives a warm reset and is wiped by the EC's hard 5V cycle — exactly the reset-reason signal needed. The panic handler stamps it before arming; a boot that comes up still stamped declines to re-arm (letting the EC watchdog hard-cycle to break the loop); a 60 s healthy-uptime delayed-work clears it so ordinary panics always warm-reset. Bench-confirmed: came back from a panic warm reset; holding off re-armhealthy, panic warm-reset re-armed at +60 s. H616 only for now (R40 RTC wipe-on-hard-cycle unverified; R40 keeps arming unconditionally).

Also validated: the full 6.18 kernel boots on a real WB8.4.3 (6.8→6.18 jump), ramoops at 0x46000000, and the full shuttle chain (with new U-Boot) reaches poweron_reason=9 + harvest.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EVPkc2g2yir6SGyrED6uNT

evgeny-boger and others added 3 commits July 6, 2026 02:20
…ld off

Review follow-up: the module header still said the ramoops region is at
the top of DRAM and omitted the loop brake; update it for the fixed
0x46000000 placement and mention the decline-to-re-arm behaviour. Also
gate the 'healthy, panic warm-reset re-armed' message on wb_reset_from_panic
so it only prints when a hold-off was actually lifted, not on every boot.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVPkc2g2yir6SGyrED6uNT
…n buffer)

Match the U-Boot change: move the reserved-memory ramoops node from
0x46000000 to 0x43800000 across the WB7/WB8 family DTs, and update the
address in the panic-reset module header. 0x46000000 sat only 32 MiB
above the arm64 kernel decompression buffer at 0x44000000; a kernel
larger than 32 MiB uncompressed would clobber it. 0x43800000 sits in the
gap below the decompression buffer, immune to kernel growth, and is
bench-verified to retain across a warm reset on all densities. Must stay
in sync with U-Boot WB_RAMOOPS_BASE.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVPkc2g2yir6SGyrED6uNT
…7 untested)

The fixed ramoops address was chosen for the arm64/H616 boot map and
reused on 32-bit R40. Document in the R40 dtsi that it clears the used
loads and sits ~4 MiB above the stock (unused) RAMDISK_ADDR_R, that there
is no build-time guard on the R40 side, and that retention on real WB7
hardware is still pending validation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVPkc2g2yir6SGyrED6uNT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant