Skip to content

The third laptop batch: a fuller report, Wi-Fi country rules, root's PATH - #641

Draft
DevomB wants to merge 32 commits into
zbook-batch-2from
zbook-batch-3
Draft

DevomB wants to merge 32 commits into
zbook-batch-2from
zbook-batch-3

Conversation

@DevomB

@DevomB DevomB commented Oct 23, 2026

Copy link
Copy Markdown
Owner

The third laptop batch, on #637's head (zbook-batch-2 01d5dab). It lands after #637:

Still to fold before its proof:

Each folded PR was read by someone other than its author. Testing on physical hardware is planned for October 2026.

Draft: it is proven after #637 lands, and lands on main by fast-forward once its Distro run is green.

DevomB added 30 commits October 23, 2026 01:23
dwl 0.8 drops touch devices, so a laptop's touchscreen did nothing. dwl now
attaches one to its cursor and turns the first finger into the pointer:
down moves it there and presses the left button, moving drags, lifting
releases. The press goes through dwl's own buttonpress, so a tap picks a
window as a click does, under the same focus rules and the lock's. Zones
are offered no touch, only those pointer events, so the proxy and its
policy are unchanged. A touchscreen covers the built-in panel (eDP, LVDS
or DSI) when there is one, and every screen otherwise.

The desktop suite proves it on QEMU's virtio-multitouch: run-ovmf.sh's
--touch adds one, bound to the GPU's first head; vm-drive.py's touch: step
taps it through QMP; and gui-check's touch-picks-window has a tap give an
unasked zone window the keyboard. vm-drive's fixture checks the step's
events.
…r run

Three things a first boot on a laptop needs and the report did not say:

- Why a sleep was short. The laptop section now gives the interrupt that
  ended the last sleep, where the kernel keeps it (/sys/power/
  pm_wakeup_irq, under PM_SLEEP_DEBUG), and the five wakeup sources that
  fired most. Where there is an IVRS table it also says whether the
  firmware gives Pluton's device (MSFT0201) and has pre-boot DMA
  protection on (IVinfo bit 1). AMD's family 1Ah processors need both to
  sleep with the IOMMU on, which amd-debug-tools checks, and a firmware
  setting can take either away.
- Which TPM came up. The firmware line names the TPM's driver and the
  hardware random number generator the kernel reads, as some firmware
  TPMs register none.
- How the clock is set. A cpufreq line gives the driver, the governor,
  the energy hint and amd-pstate's mode: power.sh's hints act only in a
  driver's active mode, and a firmware without CPPC leaves amd-pstate out.

The fixture test checks each line, an empty wakeup interrupt, no AMD line
without an IVRS table, and both IVRS answers.
… firmware settings stay on

Nothing in Kryptik sets a regulatory country, so a radio keeps the world's
rules (country 00 in wireless-regdb 2026.09.03) until it joins a network
that names its country, and goes back to them at every disconnect: no
6 GHz at all, and 5 GHz listen-only. The Wi-Fi section now says so and how
to set the country until the next boot (`iw reg set XX` as root at the
administration login), and that a Wi-Fi 7 network offering only SAE-EXT-KEY
is not joined, as the saved networks offer WPA-PSK, PSK-SHA256 and SAE.

The AMD paragraph now asks for the firmware's IOMMU, its DMA protection
and Pluton to stay on: without the IOMMU every device reaches all of
memory, and the Ryzen AI 300 parts sleep with the IOMMU on only where the
firmware keeps Pluton's device and pre-boot DMA protection.
…bug-tools asks for

From 93's read:

- A wakeup source's wakeup_count grows only while events_check_enabled is
  set (drivers/base/power/wakeup.c), which only a write to
  /sys/power/wakeup_count turns on, and kryptikd sleeps by writing "mem"
  to /sys/power/state alone. So every count stayed 0 and the lines never
  printed. The five that fired most now come by event_count, as the
  comment said they did, and the fixture's wakeup_count is the 0 a
  Kryptik machine shows.
- The IVRS line's comment said more than amd-debug-tools does: its rule
  is for family 1Ah models 0x20-0x2e, 0x60-0x6e and 0x70-0x7e, it takes
  MSFT0201 named in the IVRS in place of pre-boot DMA protection, and it
  calls MSFT0201 an ACPI device, nothing more. The comment now says that,
  and the line gains "msft0201 in ivrs yes|no", so protection off is not
  read as a laptop that cannot sleep.
softdog's timer is a CLOCK_MONOTONIC hrtimer with no PM callbacks
(softdog.c), and on a machine that sleeps to idle its clock runs whenever
the s2idle loop wakes for an event that wakes nothing. On AMD that includes
amd_pmc's msleep(2500) after every cycle that reached the deepest state
(pmc.c, upstream 9f5595d5f03f), and an LPS0 machine's EC keeps waking it for
battery, charger and thermal notices. Nothing feeds the timer during the
sleep, so a night of such events spends its 60 s and the laptop reboots in
its sleep, with everything open in its zones lost; the boot's bootstatus
then says nothing. The design said the drivers stop their timers across
suspend, which softdog's does not.

The feeder already leaves AMD's TCO timer unopened on such a machine for the
same reason; it now leaves the software watchdog so too. Intel's TCO timer,
which its driver stops for a sleep to idle, still catches a stopped machine
there; on an AMD laptop the lockup detectors alone catch a hung kernel. The
test VMs sleep in S3, where the firmware stops the timers, so the state
suite's reset by the software watchdog is unchanged.

tools/tests/watchdog-feeder.sh runs the feeder against stand-in timers: with
s2idle in force it feeds Intel's and neither of the others, and sleeping
deep it feeds all three.
shadow's su sets root's PATH from login.defs' ENV_SUPATH, with or without
"-", and s_shadow's edit of that line leaves PATH=/bin:/usr/bin. After su,
ip, iw, cryptsetup and every other program in /usr/sbin answered "command
not found". The etc step sets ENV_SUPATH to PATH=/usr/sbin:/usr/bin beside
CONSOLE and SU_WHEEL_ONLY, which it already sets there, and the build fails
if the line is missing. The etc step comes after the images cache key, so
no image is rebuilt; s_shadow's edit stays as it is until one is.

tools/tests/su-path.sh runs s_shadow's edit and etc_login_defs on shadow
4.16.0's two PATH lines and reads ENV_SUPATH back as su does.
…not handed out wrong

A program that keeps its descriptor after a grant ends (a call page whose
track died when `k` or the lock took the camera back) holds uvcvideo, and
with it the camera's streaming interface. The next grant then probed the
let-go interfaces again and found no capture node: it failed after 3 s
with "no camera: none is plugged in", or on a camera with an infrared
function handed the zone that one's node instead.

grant() now refuses while the driver is held and an earlier end left an
interface to take again (kept()), and says to turn the camera off there
first. The check comes after the zone's directory is made, so the run
directory is there, and before the driver is loaded, so the let-go list is
still there for the grant made once the program lets go.

The camera design says so; a unit test runs kept() on a stand-in /sys.
…woke a sleep, which TPM and clock driver run, and whether the IOMMU table names MSFT0201
… gets its country's Wi-Fi rules, and which firmware settings stay on
…e is checked in a guest

From 93's read: QEMU hides S3 unless run-ovmf.sh is given --s3, so every
suite guest but suspend-test's sleeps only to idle, and there the feeder
now leaves the software watchdog unfed. state-p6 resets by that watchdog
and checks it armed for 60 s, so it now starts with --s3: the guest sleeps
deep, the feeder arms the software watchdog, and the step proves its reset
as before (p6 uses no desktop, so std VGA in place of virtio-gpu is no
loss). state-p5b, which boots without --s3, now checks that the boot report
shows the software watchdog unfed: the rule seen in a guest.

The feeder's fixture test also checks that its mem_sleep read was moved
under the scratch directory, so a changed path cannot make it read the
runner's own.
…rant is refused, with the reason, not handed out wrong
…me report

Without it the check would pass on a report written before the feeder
opened anything. Intel's TCO timer is fed whichever way the machine
sleeps, so seeing it active means the feeder had made its choices.
shellcheck reads a bare done after echo, on a loop's one line, as the loop's own done (SC1010).
The quoted word writes the same bytes.
dwl's motionnotify picks the surface under the pointer before it moves the
cursor. A mouse's small steps never show it, but a touch is one jump and the
button at once: the press and release went to whatever the pointer had been
resting on, while the keyboard went to the window tapped. A tap on one
zone's window could click another's. touchpoint picks the surface again
where the touch landed, as dwl's own focus-restoring call does, before the
button goes out; a finger held down keeps its window as before.

gui-check's touch round now rests the pointer on zone 0's window first, and
holds the tap's press and release to untrusted's probe, with none for zone
0's. wlprobe's cursor mode says each pointer button it is sent.
Closed on a dock, the panel stays on, and a touch through the lid would
click, and take the keyboard, on a screen no one sees, and hold off the
idle lock. touchdown drops every touch while the lid is shut. touchpoint
drops one, too, while a built-in panel is there but off, dark or disabled,
rather than spread it over the other screens. A finger already down still
ends through touchup or touchcancel.

cleanuplisteners removes the five touch listeners with the cursor's own.
One touchscreen is taken to be the laptop's, which the comment now says.
…aves the software watchdog unfed, so a long sleep does not reboot it
…ap clicks the window under the finger, and no touch acts through a shut lid
Since the proxy passes wp_fractional_scale_v1, a zone's window is told the
exact scale, and the browser draws sharp at it. The user guide and laptop.md
still said zones hear a whole number, rounded up. havoc and the lock draw at
1 and are enlarged, so they look soft at any scale but 1, which the guide
now says beside its suggestion of 1.5. `kryptik display NAME auto` drops the
monitor's line, so a `*` line wins over the built-in rule, which also needs
1200 lines; the guide and the command's usage now say both.
…unning flat

The battery's ACPI driver wakes an s2idle machine when the charge falls to
the firmware's alarm level or goes critical (drivers/acpi/battery.c,
acpi_battery_update). The laptop then waits at the state passphrase
prompt, lid still shut, and the power service waits on the suspended
state partition, as every program started then does, so its 3% power-off
never comes and the laptop runs flat awake.

kryptikd already answers the lock while the partition is suspended, from
sysfs alone. From each sleep's end until the passphrase is given (or from
its start, for a daemon started again at the prompt) it now looks at the
battery every 30 s, by power.sh's rule: the fullest of the machine's own
batteries at or under 3% and running down. Seen twice running, it powers
off with reboot(2). The zones are not stopped first: they are frozen, the
partition and their volumes have no key, everything was written out
before the seal, and a sync would wait on the partition for good.

critical_in is held to tools/tests/power.sh's cases in a unit test, and
the twice-running count to its own.
… and the count carries across a sleep

The suspend suite's guest runs programs at the passphrase prompt, so the
power service's loop is not sure to stall there. Where it does not, its
shutdown would ask kryptikd to stop each zone and then run the system's
shutdown, which syncs, stops kryptikd and unmounts: none of that can
finish with the state partition suspended, and kryptikd's own power-off
would die with it. sealed() reads /sys/block with builtins alone, and
while it holds the service leaves the power-off to kryptikd.

From 93's read: kryptikd's count of critical looks reset at each sleep's
end, so a machine put back to sleep within 30 s of each wake would never
see two in one wake. It now resets only once the partition is back.

tools/tests/power.sh runs sealed() against stand-in device-mapper trees,
and checks that the loop's power-off waits on it.
laptop() had grown past the cognitive-complexity line with the wakeup
sources and the AMD IOMMU line (Tectonix: complex functions 69 to 70).
sleeping() and cameras() take those parts as they were, and laptop() calls
them where they stood, so the report reads the same.
…se after a wake powers the machine off, with the state sealed

This branch has not been deployed

No deployments
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