Skip to content

Integrate reviewed v2.1 changes into main - #61

Merged
dormancygrace merged 152 commits into
mainfrom
codex/v2.1-b1-base
Oct 6, 2026
Merged

dormancygrace merged 152 commits into
mainfrom
codex/v2.1-b1-base

Conversation

@dormancygrace

@dormancygrace dormancygrace commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

Consolidate the existing v2.1 release branch and the reviewed changes from #52, #53, #55, #56 and the #57–#59 stack into main, retaining the dependency updates already merged into main.

The combined change includes the out-of-place/burst-4 CryptoDMA fix, watchdog lifecycle fixes, RustDesk framing buffer reuse, C906 vector-context and aligned LZ4 changes, and the video/4K memory and compact boot-payload work.

Integration fixes:

  • Apply one final EDID for a batch of monitor changes.
  • Detect the loaded CryptoDMA capability before using hardware SRTP; fall back to software while an old module remains loaded.
  • Compose the initial SD boot image from the compact kernel package.
  • Preserve ZRAM Auto on enable/recompression changes.
  • Exercise the SD boot fixture in CI and verify boot.sd read back from FAT.
  • Reject RustDesk runtime video dimensions outside the 16-bit frame-header range; cover missing, malformed, negative and overflowing values.
  • Resolve the documentation conflict by keeping both private-path removal and the component-upgrade documentation.

Validation of the final combined tree:

  • All server Go tests and build with -tags teststub passed.
  • Web UI production build, lint and all 147 tests passed.
  • RustDesk: 59 tests passed, 3 intentionally ignored.
  • Platform configuration/build checks, OpenRC dependencies, 8 kernel-activation tests and the SD/FAT fixture passed.
  • CryptoDMA module with the new read-only capability marker cross-compiled against the existing 7.2.9-nanokvm-os-r1 build.
  • PR 3840x2160 at up to 30 fps with a video overclock #57 completed CI after combining the release fixes. This PR runs CI on the final main integration as well.

No full production firmware rebuild, device installation or new hardware soak test is claimed by this integration. Obsolete remote branches are removed after consolidation; v3 remains a separate development branch. No archival tags are retained, as requested.

dgrace added 30 commits October 3, 2026 04:17
dormancygrace and others added 23 commits October 6, 2026 18:12
The video settings had grown into about fifteen interdependent controls,
partly repeated in the toolbar, with hidden constraints (H.265 not over
WebRTC, the tallest portrait profile only as H.265 Direct, H.264 not at
2304 lines, frame-rate caps per size) discovered only through errors or
silent clamping, and the limits kept in three places.

- lib/video-model.ts (pure, unit-tested): the capabilities the server
  reports, the draft being edited, the delivered frame rate, the monitor
  refresh that follows it, validation with reasons, presets, and what
  applying changes (EDID rewrite, player reload).
- Profiles: Recommended, Sharpest, Smooth, Lowest latency, Compatible,
  Low traffic. Each adapts to the device and browser, keeps a portrait
  monitor and Cube/Lite receivers as they are, and states why it cannot
  apply. Settings that match none are Custom.
- Settings > Video: input, stream and monitor summary (sizes, rates,
  codec, transport); profiles; Manual settings with the monitor (portrait
  profiles in the same list), the stream (transport, codec, resolution,
  FPS with the delivered rate, bitrate) and Advanced. Unavailable choices
  stay visible and disabled with the reason. Before applying, the page
  says when the monitor will switch (and to what) and when it reloads.
- Shared settings are applied with one validated request
  (POST /api/vm/video); users still choose only the transport and the
  Direct playback of their own browser.
- The toolbar menu shows what is streamed and switches profiles; its
  resolution/FPS/quality submenus and the unused codec, mode and
  frame-detection menus are removed.
- H.265 over WebRTC: the browser decoder decides again
  (RTCRtpReceiver.getCapabilities), as before ad5750a.
- docs/VIDEO.md describes profiles, refresh following the frame rate,
  the limits and the API.

Measured on the device (2560x1440@50 source): Low traffic wrote
NanoKVM-monitor-1080-30.bin, the source switched to 1920x1080 at 30 Hz
and the encoder delivered 30 fps; restoring the previous settings brought
the source back to QHD50.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Landscape rates: 720p 120/60/30, 1080p 100/75/60/30, 1440p
  60/50/40/30, 2160p 30. 1080p100 and 1440p60 use CVT reduced blanking
  (235.5 and 241.5 MHz, within the 250 MHz range limit).
- Auto (NanoKVM-final-video-profiles.bin) is 1920x1080 at 100 Hz;
  QHD and UHD become explicit choices.
- Portrait profiles per rate, as landscape: 720x1280 120/60/30,
  1080x1920 100/75/60/30, 1296x2304 and 1440x2560 60/50/30
  (NanoKVM-portrait-<w>x<h>-<hz>.bin, CVT reduced blanking with the
  established portrait sync). The established files and timings keep
  their bytes.
- 1080p120 was tried: at 285.5 MHz (1142 Mbit/s per MIPI lane) VI
  reported receive errors until the VIP clocks were raised to the vendor
  overdrive values, and the encoder then delivered about 109 fps, so
  1080p is offered at 100 Hz (942 Mbit/s per lane, stock VIP clocks).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Frame-rate tiers (Go and capture_rate.hpp): 720p 120, 1080p 100,
  QHD 60, larger 30 fps. With the video overclock the encoder sustains
  about 250 Mpix/s (QHD60, UHD30); at 1080p a fixed per-frame cost limits
  it to about 109 fps, so 1080p is offered at 100.
- The third VPSS buffer and pipelined encoding follow the pixel rate
  (size x fps above QHD50) instead of the size; a 64 MiB pool keeps two
  buffers at QHD, where a third does not fit.
- Auto is 1920x1080 at up to 100 Hz wherever the EDID is written live;
  QHD and UHD are explicit choices. Portrait profiles follow the stream
  rate like landscape (1080x1920 up to 100, 1296x2304 and 1440x2560 up
  to 60 Hz); 1440x2560 H.265 is also offered over WebRTC.
- Bitrate for motion, for every size and rate: about 0.05 bit per pixel
  with H.265 and 1.5 times that with H.264, rounded up to an offered
  value (adds 8 and 12 Mbit/s): 1080p100 12, QHD60 12, UHD30 15 Mbit/s.
  Presets derive it (Sharpest 20, Low traffic 1 stay fixed), the manual
  settings show it as a hint, and the factory default is 100 fps,
  12 Mbit/s, matching Recommended.
- Presets: Balanced (2560x1440 at 60) replaces Smooth (1080p75, now
  covered by Recommended).
- docs/VIDEO.md updated.

Measured (overclocked kernel, H.265, Chrome): 1080p100 input 100 Hz,
encoder 100 fps, 98 delivered, stock VIP clocks, no VI errors;
2560x1440@60: 60 fps; 1080p120 (1142 Mbit/s per MIPI lane) needed the
vendor overdrive VIP clocks and still delivered about 108 fps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the 128 MiB CMA pool, 3840x2160 failed on cold boots: the encoder
could not allocate its last reference buffers (about 16 MiB) because Linux
had borrowed the free CMA pages and they could not be migrated back
(cma_alloc_fail grew, the native SendFrame failed, the copy fallback could
not create its pool, and the channel was recreated in a loop). Two of four
consecutive cold boots had no video; switching to 4K at run time worked.

- A third boot image per board, <board>-uhd.sd: the same kernel with a
  128 MiB fixed carveout. CMA stays the default; the 64 MiB fixed mode is
  unchanged. nanokvm-activate-kernel accepts "uhd".
- 3840x2160 (monitor profile, stream limit, capture) needs a pool of at
  least 128 MiB that is not reusable: SupportsUHD in the server and
  check_res in libkvm. Elsewhere it is offered as unavailable with the
  "video-memory" reason, which now names the 4K memory mode.
- The memory API lists the installed modes and reports the real pool size;
  the memory page offers CMA, Fixed 64 MiB and 4K 128 MiB.
- zram gains an "auto" size, half of the Linux memory (API sizeMiB 0). The
  4K mode leaves Linux about 105 MiB, so there it defaults to zram auto
  unless memory.conf says otherwise.

Measured (pcie, 3840x2160@30 H.265, OpenSBI 1.9): CMA cold boots 2 of 4
with video; a 128 MiB fixed carveout booted with video, 117 MiB of video
memory in use, no VB pool errors, MemTotal 104 MiB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/usr/lib/nanokvm/boot held a 9 MiB FIT for every board and video memory
mode (133 MiB with the 4K mode). They share the kernel and initramfs and
differ only in the device tree, so the package now carries one template,
the device trees (padded to 32 KiB, one layout for all) and the SHA-256 of
each image the build made: 9.5 MiB.

- build.sh still runs mkimage for every image (images/boot-fit) and
  fit-layout.py checks that substituting the device tree and its image
  hash into the template reproduces each one byte for byte.
- compose-fit (shell, dd and sha256sum) rebuilds an image on the device
  and replaces the output only when it matches the build's hash.
  nanokvm-activate-kernel and the personal image builder use it.
- The FIT description no longer names the board, so all images have the
  same layout.
- The server looks for <board>[-mode].dtb to list the video memory modes.

Checked: compose-fit output equals mkimage's pcie-uhd image; activation
tests cover the composed image, a corrupted device tree and the uhd mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Out-of-place requests made the H.265 + CryptoDMA hang rarer, not
impossible: 1920x1080@100 H.265 over WebRTC with hardware SRTP still hung
after 6 to 17 minutes. A device stand (HDMI capture, VPSS and H.265 encoding
from the application, 1250 AES-CTR requests of 1216 bytes per second) varied
the DMA_CTRL burst limits:

  write burst 16 (vendor secure boot): mean time to hang about 48 s
  write burst 6 (vendor Linux driver):  about 78 s at 1080p100, 63 s at UHD
  write burst 4:                        no hang in 15 min; no hang in 13 min
                                        of 3840x2160 H.265 WebRTC

The encoder fed from memory without capture or scaling did not hang with
bursts of 6 in 10 minutes, and read-only (hash) requests never hung, so long
CryptoDMA writes into a DDR already busy with capture, scaling and encoding
are the trigger. Read bursts stay at 16. Throughput costs 2.6 %: 22371
instead of 22968 requests of 1216 bytes per second; 3840x2160 WebRTC uses
about 1500.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The kernel enables XTheadVector for user space. These patches from #46 (by
Codex) make the T-Head vector state handling correct on the C906:

- 0032: riscv_v_is_on() also checks the legacy XTheadVector status field.
- 0033: vendor extension headers usable from assembly.
- 0034: the trap entry clears the legacy vector status as well, so a
  preempted task cannot leave the vector unit enabled in the kernel.

The opt-in vector kernel backends of #46 (usercopy, checksums, ChaCha, CRC;
0036/0037) and their tools are not included: on the NanoKVM they did not
help. Loopback TCP with the vector usercopy measured 33.8 MiB/s against 34.5
without it; the kernel copies sockets, pipes and files in 4 KiB pages,
below its 16 KiB threshold. #46's own WireGuard comparisons showed no
general gain either.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0039 adds CONFIG_RISCV_C906_LZ4_DECOMPRESS: the LZ4 decompressor copies
complete wild-copy spans with aligned 64-bit loads and stores on the C906,
keeping the forward order for overlapping matches. Enabled in the NanoKVM
kernel. tools/c906-lz4 holds the qualification tools.

Same code as in #47; its Kconfig hunk is regenerated for a tree without the
#46 vector backends, which it used as context.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #59:

- The full SD image builder still required usr/lib/nanokvm/boot/detect.sd,
  which the compact kernel package no longer has. It now composes boot.sd
  with compose-fit. test-alpine-sd-image-boot.py runs the builder on a
  compact-layout fixture (stub f2fs tools) and checks the FAT boot.sd; it
  fails without this change.
- The zram switch and the recompression switch sent the computed Auto size
  (for example 52 MiB), which the API rejects, or turned Auto into a manual
  size when it matched an offered one. Both send 0 for Auto now
  (swapRequestSize, with tests).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4K video memory mode (128 MiB fixed) and a 10 MiB kernel boot payload
Video settings: profiles, capabilities, refresh following fps, H.265 WebRTC
Release line: remove private data, keep watchdog across app restarts, out-of-place CryptoDMA
perf(rustdesk): reuse framing buffers and detached XSalsa20-Poly1305 (split from #47)
c906: XTheadVector context fixes and aligned LZ4 decompression (replaces #46)
3840x2160 at up to 30 fps with a video overclock
Comment thread server/service/rustdesk/bridge.go Fixed
Comment thread server/service/rustdesk/bridge.go Fixed
Comment thread server/service/rustdesk/bridge.go Fixed
Comment thread server/service/rustdesk/bridge.go Fixed
@dormancygrace
dormancygrace merged commit fb2117e into main Oct 6, 2026
13 checks passed
@dormancygrace
dormancygrace deleted the codex/v2.1-b1-base branch October 6, 2026 23:19
dormancygrace added a commit that referenced this pull request Oct 6, 2026
Integrate reviewed v2.1 changes into main
dormancygrace added a commit that referenced this pull request Oct 6, 2026
Integrate reviewed v2.1 changes into main
dormancygrace added a commit that referenced this pull request Oct 6, 2026
Integrate reviewed v2.1 changes into main
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.

2 participants