vms-329: VAX runtime reads SYS over the executive ACP (the real flip) — sysboot+image-activation green, install-menu reached - #706
Merged
Conversation
…(faithful flip) Retire the vmsfs.ko + POSIX SYS$DISK bypass on VAX. The VAX runtime now reads and writes SYS$DISK over the executive ACP (IO$_ACCESS/READVBLK/WRITEVBLK/$MOUNT via /dev/vms) -- the same executive path Linux uses. Option A (conductor-approved): rename __linux__ -> OVMX_HAVE_ACP so RMS/boot call vms_kif_acp_* with zero platform knowledge; the POSIX arm is kept only for the kernel-less unit build. Shared kernel-core vmsfs_acp.c is BYTE-UNCHANGED -- only added to the module SRCS. Kernel (NetBSD vms.kmod): - vms_blockdev_netbsd.c (NEW): the exec_blockdev_read/write_block seam + the single-unit device-native disk resolve (vms_devtab_disk_backing). Transliterates the proven vmsfs.kmod path -- vn_bdev_openpath-cached devvp + bread / getblk+bwrite, vn_close(FREAD|FWRITE). Quarantined TU (avoids the exec_rbtree/sys/rbtree collision). - vms_netbsd.c: 9 IOCTL_ACP_* dispatch cases + the readvb/writevb bounce seam (the ACP's separate user-buffer pointer needs a manual bounce like vms_mbx_bigio; the shared handler and exec_copyout contract stay unchanged) + vms_acp_init/cleanup + per-proc vms_acp_release_all. - exec_kbackend_netbsd.h: real exec_blockdev_* under OVMX_ODS2_KERNEL. - Makefile + build-vms-module-vax.sh + build-devvms-vax.sh: add vmsfs_acp.c + ods2_reader.c + ods2_edit.c + vms_blockdev_netbsd.c, -DOVMX_ODS2_KERNEL. Userspace: rms_core/io/search.c + rms_internal.h __linux__ -> OVMX_HAVE_ACP; OVMX_HAVE_ACP build define on vmsrms (non-standalone) + ovmx_init; ovmx_boot_netbsd.c ACP $MOUNT flip (mirrors ovmx_boot_linux.c). Verified: elf32-vax kernel cross-compile ILP32-clean; loadable vms.kmod links with all OVMX/codec symbols resolved (modload-ready); userspace ovmx-images cross-build green with the flip. SIMH sysboot-over-ACP runtime proof (INV-6 hash-diff) in flight. DKA0:->DUA0: MSCP device-native rename tracked as vms-47d (resolve accepts both). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ot-over-ACP GREEN run-boot.sh's hand-rolled vmsfs_master compile predates the flip's move of tools/vmsfs_master.c to the genuine ODS-2 codec (vms-5eb R6-build): it passed only -I src/kernel/vmsfs and no codec sources, so "vmsfs/ods2.h" was not found and the sysboot SYSTEM-volume mastering died before the boot ever ran. Baseline dd452f5 fails identically -- this is a flip-era harness regression, NOT an ACP issue. Mirror tools/CMakeLists.txt's vmsfs_master target: add -I src/vmsfs/include + the six ods2 codec sources (reader/writer/edit/bdev/path/block_posix). With this, the SIMH sysboot-over-ACP proof PASSES end-to-end on real NetBSD/vax: ovmx_init boots as PID 1, mounts SYS$DISK over the EXECUTIVE ACP (the vmsfs mount is #else, not compiled), PROVISION.EXE demand-pages off the ODS-2 volume and RUNS (SYSTEM [1,4] identity), stamps UIC file ownership, and reaches Username:. The INV-6 hash-diff confirms the on-disk bytes REALLY changed -- proof the ACP read AND write paths (exec_blockdev_read/write_block + the readvb/writevb bounce) ran, with no false-pass path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…MX$INSTALL.COM) stage_sysvol.sh gains a --distribution --kit <OVMX-OS-VAX.KIT> mode, the netbsd-vax mirror of the x86_64 install-media flow (design-vms-faithful-install.md §3.3): the distribution disk differs from an installed system disk ONLY in its payload — (a) the OS kit at SYS$UPDATE:OVMX-OS-VAX.KIT, and (b) a distribution SYSTARTUP_VMS.COM (the VAX Decision-A variant + one $ @sys$MANAGER:OVMX$INSTALL.COM block) so the mastered volume boots into the install menu. Default (non-distribution) mode is byte-identical. OVMX$INSTALL.COM reused byte-for-byte. Verified: real OVMX-OS-VAX.KIT packed + staged + mastered, kit present at SYS$UPDATE:, SYSTARTUP invokes the menu. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…IZE formats the real target) INITIALIZE.EXE resolves a VMS disk unit to its real backing block device via vms_kif_disk_resolve; the flip wired the 9 ACP ioctls but not DISK_RESOLVE, so on VAX INITIALIZE of a blank target could not format it. Backfill (shared kernel-core BYTE-UNCHANGED): the Linux handler uses the full devtab (not ported to VAX), so a VAX-side vms_ioctl_disk_resolve reuses the existing single-unit resolve. - vms_acp_nb.h: struct vms_diskresolve_args twin (48B) + VMS_IOCTL_DISK_RESOLVE _IOWR(0x57) with a compile-time assert == 0xC0305657u (ABI-identical to Linux). - vms_blockdev_netbsd.c: unit map + install target (DKA100:/DUA100: -> ra2c); transient vms_devtab_disk_resolve (open->v_rdev->close, no cache, fail-honest SS$_NOSUCHDEV); the handler (plain memcpy, quarantined TU). - vms_netbsd.c: VMS_IOCTL_DISK_RESOLVE dispatch case (ACP _IOWR group). Verified: both elf32-vax cross-builds green (ILP32 + modload-ready), symbols defined. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… proof in flight drive_install_vax.py (new): forks do_sysboot's SIMH/KA655 skeleton, reuses the console helpers verbatim (expect_wake/_console_text/_hard_kill + the HARNESS_ERROR/ PROOF_FAILED contract), attaches the distribution volume (rq1->ra1->DKA0:) + a BLANK ODS-2 target (rq2->ra2->DKA100:, both writable), boots straight into OVMX$INSTALL.COM (no login), and drives its real PRESERVE path (1/PRESERVE/DKA100:/WORK/YES -> %MOUNT-I-MOUNTED -> %PCSI-I-DONE -> SYSTEM password -> %UAF-I-SAVED -> SCSNODE/SCSID -> SYSGEN -> %DISMOUNT -> "installation is complete"). Mirrors the x86_64 assertions: %PCSI-I-DONE with no %PCSI-[EF]-, rooted DKA100:[SYS0.SYSCOMMON.SYSEXE]DCL.EXE present, flat [SYSEXE]DCL.EXE ABSENT (%RMS-E-DNF), and the anti-LARP run-an-installed-image- FROM-the-target (RUNX :== $DKA100:...DCL.EXE + -c "SHOW TIME", no crash). run-boot.sh: new `install` mode — cross-builds the REAL utility images (PRODUCT/AUTHORIZE/INITIALIZE/SYSGEN.EXE via ovmx-images), packs OVMX-OS-VAX.KIT, masters the distribution volume (stage_sysvol.sh --distribution), formats a blank ODS-2 target, attaches both, and sha256s the target before/after (INV-6 write-proof). drive_boot_vax.py: assembly now `MAKEDEV ra1 ra2` so /dev/ra2c (DKA100:) exists. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…f4b4) Brings the SIMH e2e proof harness onto the branch: tests/lab-vax/run-boot.sh 'install' mode + tests/lab-vax/drive_install_vax.py + the two-disk distribution staging (stage_sysvol.sh), plus vms-f60's VMS_IOCTL_DISK_RESOLVE and the DKA100:/DUA100: -> /dev/ra2c unit-map entry the installer needs. Conflict resolution: - src/kernel-netbsd/{vms_blockdev_netbsd.c,vms_internal.h,vms_netbsd.c}: took the install branch (strict superset -- main lacked vms-f60's DISK_RESOLVE). - src/ovmx_init/ovmx_boot_netbsd.c: took main (keeps piece A's ovmx_boot_prepare_stage_dir, which the install branch predates).
Turns the shipped netbsd-vax runtime onto the executive Files-11 ACP, all at once -- NetBSD's spec_vnops allows exactly ONE open of /dev/ra1c, so the ACP $MOUNT and the vmsfs.ko VFS mount of SYS$DISK cannot coexist and no transitional half-state exists (rd vms-049's finding). * tools/cross-vax/build-ovmx-init-vax.sh (the SHIPPED PID 1): define OVMX_HAVE_ACP + OVMX_BOOT_ACP_BRIDGE, link ovmx_boot_acp_read.c + ovmx_boot_sysgen_acp.c + src/imgact/imgact_acp.c, drop _POSIX_C_SOURCE so the recipe matches the CMake target and the standing ILP32 audit. New weak-seam anchor: STARTUP.EXE must resolve ovmx_sysgen_acp_read STRONG, and ovmx_boot_netbsd.o must reference vms_kif_acp_mount (teeth for the macro). * src/ovmx_init/CMakeLists.txt: bridge TUs on EVERY substrate; OVMX_HAVE_ACP + OVMX_BOOT_ACP_BRIDGE unconditional (reconciles vms-8e8f's flagged split). * ovmx_boot_netbsd.c / ovmx_boot_linux.c / ovmx_boot.h: RETIRE ovmx_boot_mount_system_disk() -- the VFS mount seam op is gone, not merely unused; mount_system_disk_native() is ACP-only with no fallback arm. * ovmx_init.c: conversational SYSBOOT path is ACP on every substrate (the netbsd VFS #else branch deleted); IMGACT.EXE staging is Linux-only (vax activates through ld.elf_so, Decision A -- no IMGACT.EXE on the volume). * src/vmsrms/CMakeLists.txt: OVMX_HAVE_ACP for the standalone netbsd-vax cross too -- that configuration is not a unit build, it is the libvmsrms.a linked into the shipped VAX DCL/LOGINOUT/PROVISION/JOB_CONTROL. * ovmx_provision.c: re-key the ACP provisioning arms from __linux__ to OVMX_HAVE_ACP (+ define it in the CMake target and the vax recipe, with teeth). With /vms gone the POSIX lchown arm would swallow every ENOENT and provision nothing while reporting success. Not yet SIMH-proven -- pushed before the long cross build (host reaper).
…l + open_executive/system_disk ops)
… block trace)
First traced cutover boot: the executive ACP opened /dev/ra1c and bread() LBN 1
with NO VFS mount in the picture -- and the bytes came back 53 46 4d 56 ("SFMV"),
the OVMX VMFS superblock. vmsfs_acp.c's acp_validate_ods2() therefore refused
the mount (SS$_DEVNOTMOUNT -> %OVMX-F-SYSINIT), correctly: tests/lab-vax
mastered every volume with vmsfs_master's DEFAULT format, which is the bespoke
VMFS, not Files-11 ODS-2. Fix the media, never the validation:
* run-boot.sh: --ods2 on the system volume, the distribution volume, the blank
install target, and their content-gating list passes.
* new master_sysneg_volume(): the sysboot negative control gets its OWN
genuine-ODS-2 volume with an EMPTY tree, so it still MOUNTS and then fails
the installed-system gate on the missing SYS$SYSTEM:DCL.EXE. Reusing the
VMFS ODS2_IMG would have halted one step earlier and silently gutted the
control; ODS2_IMG stays VMFS for the sibling vmsfs VFS-module drivers.
TEMPORARY (reverted before this branch is handed over): the OVMXTRACE printf in
vms_blockdev_netbsd.c that produced the evidence above.
…DASSGN Second traced cutover boot: the ACP $MOUNT of DKA0: SUCCEEDED on the VAX (%OVMX-I-MOUNTED, with the trace showing real bread()s of the genuine ODS-2 home block at LBN 1, the INDEXF header and the SCB, with NO VFS mount) -- and then require_installed_system() said DCL.EXE was absent, with ZERO further block reads. No reads means imgact_acp_open() failed before it ever touched the disk: src/kernel-netbsd/vms_netbsd.c answers neither VMS_IOCTL_REGISTER nor VMS_IOCTL_DASSGN, so acp_register() got ENOTTY -> SS$_NOSUCHDEV and EVERY ACP file open on this substrate failed. The ops were never missed before because nothing in-kernel needs them (every NetBSD ioctl path find-or-creates the PCB via vms_proc_get) and no VAX image had ever opened an ACP file. * vms_proctab_nb.h: struct vms_register_args / vms_dassgn_args + the request numbers, encodings _Static_assert-pinned to the Linux build's command words (0xC0085640 / 0xC0085641 / 0xC0085651). * vms_netbsd.c: REGISTER/_CONTINUE returns the PCB vms_proc_get builds anyway (the Linux twin's adopt-or-create); DASSGN mirrors the Linux fallback chain minus the device table this substrate does not carry -- mailbox, then file-class, else SS$_IVCHAN. No fabricated success (INV-6). Substrate dispatch only; src/kernel-core is untouched.
…nt on a read-only NetBSD root
Third traced cutover boot (after the REGISTER/DASSGN fix): the executive ACP
mounted DKA0:, and the ACP file walk now REALLY RUNS on the VAX -- the trace
shows genuine directory-block bread()s (LBN 108/109/128, "SY"/"SY"/"BU" name
bytes) and require_installed_system() FOUND SYS$SYSTEM:DCL.EXE over IO$_ACCESS.
The boot then halted one step later:
%OVMX-F-SYSINIT, cannot create the boot-image staging directory
%OVMX-I-SYSINIT, Read-only file system
ovmx_boot_prepare_stage_dir() mkdir(2)s /run and /run/ovmx-boot before mounting
the staging tmpfs. mount(2) does not write to the underlying filesystem, but
mkdir(2) does, and this boot runs on a READ-ONLY root (the assembly session ends
with `mount -u -r /'), so both mkdirs return EROFS.
* drive_boot_vax.py: create /run/ovmx-boot alongside /vms /proc /dev/pts
/dev/shm when the bootable disk is assembled -- the same class of thing (a
mount point a shipped OVMX/NetBSD root carries), the same read-only-root
reason.
* ovmx_boot_netbsd.c: document that contract where the mkdirs live. They stay,
and EROFS on a root without the directory still halts honestly (INV-6) rather
than staging into nowhere.
…VE_ACP
Third traced cutover boot got PID 1 all the way through the ACP file walk --
installed-system gate PASSED over IO$_ACCESS, ~20 first-hop/utility/shareable
images STAGED off the ODS-2 volume through the ACP, PROVISION.EXE demand-paged
and RAN (%STDRV-I-STARTUP, 'system identity SYSTEM') -- and then:
%OVMX-I-STARTUP, handing SYS$MANAGER:STARTUP.COM to DCL for ACP resolution
%DCL-E-OPENIN, error opening SYS$MANAGER:STARTUP.COM as input
Three ACP arms were still gated on __linux__ from when the netbsd-vax runtime
VFS-mounted SYS$DISK and so still had a /vms POSIX tree to fall back to. The
coupled cutover retired that mount: on the VAX those fallbacks now reach
nothing at all. The code behind each gate is already substrate-neutral -- this
is a definition, not a port. (It also removes three __linux__ source forks,
which build-boot-images-vax.sh's INV-DRIFT note forbids in this image set.)
* vmsdcl/dcl_script.c -- @-procedure open over RMS/ACP (the blocker).
* vmsdcl/dcl_cmd_process.c -- activatable-image resolution through the ACP;
without it DCL cannot find ANY image on the VAX post-cutover.
* libvms/rtl/rms_textfile.c -- SYSUAF / RIGHTSLIST / $GETUAI / OPERATOR.LOG.
A SYSUAF that reads as EMPTY is worse than one that fails: it looks like 'no
such account'.
* src/vmsdcl/CMakeLists.txt + src/libvms/CMakeLists.txt: define OVMX_HAVE_ACP
on the target, including the netbsd-vax STANDALONE archive (that archive is
not a unit build -- it is the libvmsdcl.a/libvms.a that become the shipped
VAX DCL.EXE/LOGINOUT.EXE/PROVISION.EXE/JOB_CONTROL.EXE), exactly as
src/vmsrms/CMakeLists.txt already reasons.
* src/vmslink/mk_dcl.sh + mk_libvms_shr.sh: the NATIVE-LINK recipes compile
these TUs themselves and satisfied __linux__ for free. Without an explicit
-DOVMX_HAVE_ACP the x86_64 native-link DCL.EXE/LIBVMS$SHR would SILENTLY
lose arms the CMake build keeps -- a regression no compile gate can catch.
Byte-for-byte a no-op on x86_64; the VAX is where the arms are new.
OBSERVED, NOT CHANGED: mk_vmsrms_shr.sh defines no OVMX_HAVE_ACP either, so the
native-link LIBVMSRMS$SHR is built with RMS's ACP arms compiled OUT. That
predates this item and is not on the VAX path (the VAX links the CMake
libvmsrms.a, which does define it); turning it on would change the native-link
symbol vector, so it is left for its own item rather than smuggled in here.
…ry ACP block trace
Fourth traced cutover boot: DCL opened SYS$MANAGER:STARTUP.COM OVER THE ACP and
EXECUTED it -- SYSTARTUP_VMS.COM ran ('The OVMX system is now executing the
site-specific startup commands') and $RUN created a real process
(%RUN-S-PROC_ID 00000067). One failure left, and it is a MEDIA gap the cutover
EXPOSED rather than caused:
%OVMX-W-OWNER, home directory SYS$SYSDEVICE:[USERS.DEFAULT] did not resolve
over the ACP (parent missing?) (x4: DEFAULT/GUEST/USER1/USER2)
The vax system volume has no [USERS]. distro/Dockerfile.bootable creates
/system-stage/vms/{USERS,SYSTMP} before mastering the x86_64 image and gates on
']USERS.DIR;' appearing in the listing -- git cannot carry an empty directory,
so every mastering step must create them itself, and stage_sysvol.sh never did.
Pre-cutover this was INVISIBLE: PROVISION's home pass lchown()ed a /vms
passthrough path, a missing parent came back ENOENT, and it was silently
swallowed -- four home directories 'provisioned' that never existed. The ACP arm
resolves the parent DID for real and says so. Fixing the media, not the report.
* stage_sysvol.sh: mkdir [USERS] + [SYSTMP] in the staged tree (the vax twin of
the Dockerfile.bootable step), so PROVISION CREATEs each account home under
[USERS] over IO$_CREATE with the account's UIC.
* run-boot.sh: content-gate the mastered system volume on ']USERS.DIR' -- the
vax twin of the Dockerfile.bootable gate, so a staging regression fails at
mastering instead of three minutes into a SIMH boot.
* vms_blockdev_netbsd.c: REVERT the temporary OVMXTRACE printfs from f03666d.
They did their job -- they are what proved the executive ACP opens /dev/ra1c
and bread()s the genuine ODS-2 home block / INDEXF header / SCB / directory
blocks with NO VFS mount anywhere in the picture, and the four boot logs
holding that evidence are the receipt. No debug output ships.
…ed script banner
The vms-329 ACP flip retired the ovmx_boot_mount_system_disk() boot op (the
vmsfs.ko VFS mount of SYS$DISK), dropping the NetBSD boot backend from 9 to 8
ovmx_boot.h ops. build-ovmx-images-vax-cmake.sh was updated to remove that
symbol from its per-op nm check and reword its banner to the count-neutral
"OK: every ovmx_boot.h op is defined by the NetBSD backend", but the
vax-cmake-images job's post-build grep in ci.yml still asserted the stale
"OK: all 9 ovmx_boot.h ops defined by the NetBSD backend" banner. The docker
build + 10/10 parity check passed; only the migrated-teeth grep failed
("FAIL: the NetBSD boot-backend ops check did not run"), reddening the whole
job. Align the grep to the script's actual banner. No script/CMake/link change
-- the aggregate build and parity closure were already green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
baron-3dl
force-pushed
the
merge/vms-c45-w2
branch
from
August 22, 2026 15:11
db03bf7 to
4341a01
Compare
This was referenced Aug 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
vmsdcl/libvms/vmsrms+mk_dcl.sh/mk_libvms_shr.sh.[USERS]+[SYSTMP]on the VAX volume; reverts the temporary ACP block trace.tests/lab-vax/drive_install_vax.pydriver + updatedstage_sysvol.sh/run-boot.sh.Schema/contract change (has_schema_change: true) — this rides the 3-way convergence gate (x86_64 CI + VAX ILP32 + Alpha LP64). DO NOT MERGE on this PR's CI alone — merge is held for explicit go-ahead once the conductor confirms all three legs.
Test plan
🤖 Generated with Claude Code