Repository navigation
Merge aurora-wip (carries #131) with review fixes - #136
Merged
Merged
Conversation
Add a default-off T8140 external-controller experiment. Require the inherited START, STOPPED and IDLE state before the standard start/wake path and pin its DMA lifetime before any startup write. Complete this optional preparation during platform probe so failed or deferred controllers do not become prerequisites for the internal DRM master. Only successfully bound, prepared controllers are included. Preserve started-session mappings on failure and quiesce retained external work during shutdown. Internal H17P lifecycle remains unchanged. Hardware qualification and validated external resource mappings remain required before this experiment can be used as a supported display path. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Describe the external display controller and four display apertures plus its fifth clock aperture from bounded read-only ADT observations. Select the first observed DCP mapper and the observed PIODMA stream. Add the reciprocal rear Type-C graph while retaining disabled controller and route status. Register names follow existing public bindings. Mailbox, firmware handoff, routing and bandwidth integration remain qualification requirements. This resource description is not a display readiness claim. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Use the generic DCP fallback required by the published T8140 external binding and explicitly classify that specific compatible as an external pipeline. Otherwise the display master never discovers a successfully prepared external node. The device and route remain disabled by default. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Keep the external CPU supply on after the loader validates and publishes its power-domain chain. The supply remains disabled in the static tree, so a refused handoff does not register or power it. This preserves firmware ownership while allowing mailbox consumers to bind. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Separate the number of display windows from the shared firmware clock aperture. Preserve the internal five-window profile and validate the external four-window profile against its existing final clock resource. Require explicit read-only experimental bandwidth offsets for the external profile, with alignment, distinctness and aperture bounds checks before startup. Keep both offsets unset by default and reject missing external clock rates rather than guessing them. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Report which bounded startup wait failed so endpoint discovery, host readiness and IOP acknowledgment failures can be distinguished without logging message payloads. Successful handshakes remain unchanged. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The external H17P trial completes endpoint setup but its normal RTKit wake sequence times out. Use the existing early-AP wake helper for this experimental profile, which announces host readiness before waiting for IOP readiness. Keep the normal wake sequence for other profiles. This ordering is a hardware qualification candidate. The previous trial retained the internal panel but did not expose an external connector. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The external H17P startup requests a shared buffer at a firmware-provided IOVA. Its setup callback maps that buffer, but the standard RTKit ops do not acknowledge mapped buffers. Select the existing co-processor-owned buffer protocol for this experimental profile so RTKit acknowledges the request and starts the crashlog endpoint before its endpoint-map reply. Keep other display profiles on their existing ops. Restore the normal wake ordering after the earlier AP-readiness trial also timed out, while retaining diagnostics for subsequent qualification. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The external H17P firmware announces dispext-service on the existing IBOOT endpoint. Match that measured service name for the experimental external profile, keeping the normal disp0-service table unchanged. Propagate endpoint allocation and startup failures to the caller. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Report external-profile control-message types and ring readiness when startup times out. Exclude normal receive notifications and rate-limit control diagnostics; no payload contents or addresses are logged. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
External H17P reaches AFK transport readiness but does not announce the DPTX port service. Its existing allocator endpoint is currently started only later with IOMFB. Make that known endpoint available before external service discovery, and skip its duplicate start during IOMFB startup. Keep normal H17P ordering unchanged. This external-only ordering change requires hardware validation; no new endpoint or message is introduced. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Limit external AFK control diagnostics to DPTX so unrelated endpoint startup cannot consume their rate limit. Distinguish a ready transport with no announced port service from a transport-start timeout. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The public m1n1 display startup initializes the DPTX controller endpoint before the port endpoint. Add that existing AFK controller interface to the experimental external H17P path, wait for its service announcement, and then continue port discovery. Send no controller service commands. Use a dedicated endpoint pointer and route its incoming messages through the existing AFK worker. Cover both retained-session quiescing and normal teardown, and never publish an allocation error as an endpoint pointer. Normal display profiles retain their existing startup sequence. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The external H17P test reaches transport readiness on the legacy DPTX endpoint without receiving a port announcement. The public version-two firmware implementation uses endpoint 0x2c, which this firmware advertises. Use that endpoint for an isolated service-discovery test. Keep a separate endpoint object with an initialization-only service table, RX routing and lifecycle handling. This does not enable operational port callbacks or transmit service commands; the discovered identity and framing must be validated before extending the command path. Normal profiles retain the legacy DPTX endpoint. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The external T8140 controller announces its port on endpoint 0x2c using version-two frames. Select that transport per endpoint, open announced interfaces and map the single physical DCP unit to logical port zero. Encode bounded command descriptors and validate replies against pending owned buffers before completing them. Preserve callback tokens and limit peer-buffer access to active allocations of the same service. Keep the legacy transport for other display profiles. Add host selftests for frame encoding, malformed records, response correlation, command identifiers and the production owned-copy helper. These pass 905 codec assertions and owned-copy cases with sanitizers; hardware qualification of the operational transport remains pending. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Document the three bounded calibration lists used for T8140 DisplayPort setup. Describe their register regions and ordering, and reject these properties on other PHY variants. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The T8140 variant currently returns from AUX setup without configuring it. The bootloader supplies three ordered DisplayPort setup lists, but the PHY driver does not read or apply them. Validate every list against its mapped register resource and apply the complete bundle at AUX setup. Reject DP selection if the bundle is missing or invalid, while keeping ordinary USB operation independent. Other PHY generations keep their existing setup paths. Drive-level training programming remains unchanged. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The experimental external profile uses AFKV2 for its DPTX port, but the companion controller endpoint still uses the legacy path. Its interfaces are discovered without receiving the version-two OPEN handshake. Select AFKV2 for the controller before starting it, so controller publication performs the same OPEN-before-ready sequence as the port. Add a one-time PHY setup message to distinguish successful calibration application from controller activation during hardware qualification. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
J700 reaches DisplayPort mode with its setup-list values present, but readback shows AUX still clamped and both supply overrides unset. The calibration lists do not perform the AUX power transition. Request the small and large supplies in order, release the clamp, then release analog shutdown. Check each masked state with a bounded poll. Track incomplete startup so a later shutdown can unwind it, and refuse to stop the domain if AUX cleanup fails. Leave ordinary USB operation and other PHY generations on their existing paths. Add host tests of the production transition helpers with register mocks, covering phase ordering, unrelated bits and failure at every stage. These pass with AddressSanitizer and UBSan; hardware qualification is pending. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The selected DP lane still reports the active power-control nibble after its protocol changes, with both receive overrides clear. The J700 path requires this lane to reach its quiescent state before link training. Assert only the selected lane's receive overrides, then sequence its power-control field into idle with bounded readback checks. Preserve the USB lane and unrelated bits. Return failures to the mux caller instead of publishing a completed mode transition. Host tests of the production helpers cover both lanes, invalid indices, unrelated-bit preservation and a failed write at every phase, under AddressSanitizer and UBSan. Hardware qualification remains pending. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Document the firmware-provided fallback and per-rate drive tables. Each has sixteen entries indexed by voltage swing and pre-emphasis; other PHYs do not accept these properties. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
After correcting the crossbar route, J700 reaches SET_LINK_RATE but the legacy PHY path waits for the wrong command-ready register. Add an isolated T8140 main-link sequence, firmware drive presets, and cleanup ownership that survives failed setup or shutdown. Preserve the other PMA used for USB. Handle the version-two group-one drive command with complete bounds and range checks before changing the PHY. Cache training values only after a successful PHY operation and retain the legacy endpoint behavior. Validation: 29 PHY state scenarios, 112 callback boundary cases, 100 group routing cases, 905 AFK assertions and production owned-buffer/AUX tests under ASan/UBSan; schema validation and strict checkpatch. Hardware qualification remains pending. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
A drive-settings read has a short request and a larger response. Validate both owned-buffer lengths before dispatch, allocate the response capacity, and report its body length without extending the input read. Keep the full response range ownership check before any callback side effect. The 917 codec assertions now include unequal request/response lengths, undersized buffers, limits, and invalid output pointers. Production owned copy tests and all J700 PHY/training/group tests pass under sanitizers. Strict checkpatch is clean. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Use the T8140 routing masks for USB3/DP and four-lane DP. The generic sequence changes the miscellaneous lane-swap control and clears routing state that this generation preserves. Update the low protocol fields in order and idle only the PMAs assigned to DisplayPort. Add opt-in callback and PHY completion diagnostics to distinguish firmware waiting from a blocked PHY operation. No calibration values are logged. Host checks pass: 33 PHY routing/state cases, 112 training bounds, 100 group routing cases, 917 codec assertions, owned-copy and AUX transition tests. Strict checkpatch passes. External-display qualification remains pending. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Keep the newer T602x DP IN clock controls for existing users, but exclude them from the J700 physical DP output. That output uses the original T602x gate sequence and read-clock reset location. The previous generic path wrote the additional source/output gate registers on J700 too. Validate the actual production mux function for every source on all three outputs, both with and without the J700 condition: 54 select/disconnect scenarios pass under ASan/UBSan. Existing PHY, training and AFK checks pass. Strict checkpatch passes; external hardware qualification remains pending. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Firmware resets the active lane count to zero before setting its link rate. Comparing the following two-lane request against that cached zero rejected a valid activation with EINVAL and prevented link completion. Query the PHY capacity for each request instead. Validate impossible counts before changing state, and propagate validation failures. Cover the zero-to-two reset sequence, unsupported counts and missing PHY. Validation: J700 PHY/training tests, 917 AFK assertions and owned-buffer checks pass under sanitizers; strict checkpatch is clean. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The V2 request has already passed the physical-capacity check. Restrict the older cached-count warning to the legacy path so a valid zero-to-two transition does not emit an incorrect error. No state transition changes. Validation: J700 host regression tests and strict checkpatch. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Keep the separate supply request/override writes and program the link-rate field before the final transmitter output controls. Combining those writes and moving the rate field after output setup did not preserve the hardware sequence. The host test now checks the actual production register transaction order, including supply writes. It rejects the previous implementation and passes the corrected sequence for both PMAs and every supported rate/SSC pair. Strict checkpatch passes. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The external firmware asks whether the connection is a virtual display. Return a bounded, zero-initialized physical-device answer instead of unsupported, matching the public m1n1 V2 DPTX protocol. Keep other unknown commands rejected and retain the callback group restrictions. Validation: query size/group checks, J700 training tests, 54 crossbar scenarios, 917 codec assertions and owned-buffer tests; checkpatch passes. Hardware qualification remains pending. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Move the firmware DP calibration bundle into the tunable-application phase, before the common supply/clamp sequence. Applying it later from AUX enable preserved the final register values but not the required initialization order. Full DP uses its own common bundle; shared USB/DP keeps the USB lane calibration and then applies the DP bundle. Existing tunable operations are reused. Actual production-dispatch tests cover full/shared/reversed DP, the legacy path and fixed USB2. Existing PHY, codec and crossbar tests pass. Strict checkpatch passes. Hardware qualification remains pending. Generated-by: LLM Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
msg_zerocopy_realloc() now allocates a fresh completion record for a stream socket whose tail skb carries another kind of ubuf_info, instead of returning NULL. This is needed when a retained-subpage splice owner sits on the skb, but it also changed kernels without ARM64_USER4K_EXPERIMENTAL: a MSG_ZEROCOPY send on a TCP socket whose last skb belongs to another zerocopy user, such as io_uring send zerocopy, used to fail with ENOBUFS and now succeeds on a new segment. Only take the new path with CONFIG_MM_SUBPAGE, which is the only configuration that creates subpage splice owners. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The four PR_AURORA_{GET,SET}_{EXEC,DEFAULT}_PAGE_SIZE prctl cases were
compiled into every kernel. On a kernel without
CONFIG_ARCH_HAS_USER_PAGE_SIZE they returned -EINVAL directly, which
skipped the unknown-option path that every other unsupported prctl
takes, so the task_prctl_unknown tracepoint no longer fired for those
option numbers.
Compile the cases and their helpers only when the architecture
supports selecting the user page size. Kernels without it handle the
option numbers exactly as before: the default case emits the
tracepoint and returns -EINVAL. Kernels with the feature are
unchanged.
Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ocfs2_truncate_file() was switched to truncate_pagecache() so that the mixed-granule tail invalidation runs for small userspace leaves. truncate_pagecache() also repeats unmap_mapping_range() after the pagecache truncation, so kernels built without ARM64_USER4K_EXPERIMENTAL got an extra unmap pass that the .19 kernel and upstream ocfs2 do not perform. Use truncate_pagecache() only when CONFIG_MM_SUBPAGE is enabled and keep the original unmap_mapping_range() + truncate_inode_pages() sequence otherwise, so ocfs2 truncation is unchanged in production builds. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bio_map_user_iov() now sizes its bio with bio_iov_vecs_to_alloc(), which returns 0 for bvec-backed iterators and only differs from iov_iter_npages() so that user4k can count user fragments. Kernels built without ARM64_USER4K_EXPERIMENTAL therefore allocated passthrough bios differently from .19 for bvec iterators (for example io_uring fixed buffers on NVMe passthrough). Use bio_iov_vecs_to_alloc() only with CONFIG_MM_SUBPAGE and keep iov_iter_npages() otherwise. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
headpage_already_acct() was changed to skip registered buffers whose release callback is not io_release_ubuf(), so that fragment-backed buffers with their own charge lifetime are not matched. Without ARM64_USER4K_EXPERIMENTAL this also skipped kernel-registered bvec buffers, changing how a compound head page already present in such a buffer affects locked-memory accounting compared with .19. Apply the skip only when CONFIG_MM_SUBPAGE is enabled. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The mixed-granule work changed the shmem GEM helper in two places that also run on kernels built without ARM64_USER4K_EXPERIMENTAL: - single-page faults go through vmf_insert_pfn_prot_mkwrite_offset() with a run-time computed sub-page offset instead of vmf_insert_pfn_mkwrite(); - drm_gem_shmem_mmap() gained an extra byte-range check that can return -EINVAL for callers whose vm_pgoff does not carry the GEM fake offset. These are the CPU mapping paths of every shmem-backed GPU buffer. Build both only with CONFIG_MM_SUBPAGE and keep the .19 code otherwise, so the production fault and mmap paths are unchanged. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
UFFDIO_COPY now validates the source range against current->mm instead of the registered mm, which matters only when the pager and target can use different user granules. On kernels built without ARM64_USER4K_EXPERIMENTAL it changed which task size bounds the source range when the uffd is driven from another process (for example a compat monitor). Validate the source against current->mm only with CONFIG_MM_SUBPAGE and keep the original validate_unaligned_range(ctx->mm, ...) otherwise. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tomoyo_dump_page() was rewritten to copy exec arguments through access_remote_vm() with a byte-position cache, so that small user leaves are read correctly. Kernels built without ARM64_USER4K_EXPERIMENTAL do not need this and got a different lookup, locking and caching path from .19. Keep the rewritten helper and its position-based cache under CONFIG_MM_SUBPAGE and restore the page-reference implementation otherwise. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PAGEMAP_SCAN keeps the target mm's leaf size in pagemap_scan_private so mixed-granule address spaces are walked correctly. Without ARM64_USER4K_EXPERIMENTAL that field always holds PAGE_SIZE, but it is loaded at run time, so the walk uses divides and multiplies instead of shifts and the private structure grows. Keep the field only with CONFIG_MM_SUBPAGE and read it through a helper that returns PAGE_SIZE otherwise. No functional change; production builds compile the scan paths as before. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The mixed-granule work added branches on vfio_dma::fragments to the unpin, unmap, map, replay, re-account, owner-change and dma_rw paths. Without CONFIG_MM_SUBPAGE no fragment provider is ever installed, so those branches are dead at run time but are still compiled into every kernel. Test them through vfio_dma_has_fragments(), which folds to false when MM_SUBPAGE is off, so a native-only build carries only the previous code paths. No functional change. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The external pin/unpin rewrite for retained fragments also changed kernels without mixed user granules: - vfio_iommu_type1_pin_pages() and _unpin_pages() round the start IOVA down to a page instead of using the caller's IOVA; - pinning a page that is already pinned now sets its dirty bit again; - dirty bits are set as length >> pgshift, which is zero when the smallest IOMMU page is larger than PAGE_SIZE, so pinned pages can be missing from the dirty bitmap, both at pin time and when the bitmap is repopulated. Build the fragment-aware pin_pages()/unpin_pages() and their helpers only with CONFIG_MM_SUBPAGE and keep the previous native implementations otherwise. Repopulate the dirty bitmap with one bit per pinned page as before. Drop the vfio_fragments_external() stub, which no longer has a caller without MM_SUBPAGE. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vfio_change_dma_owner() now calls capable(CAP_IPC_LOCK) for VFIO_DMA_MAP_FLAG_VADDR updates of native-page mappings, including updates issued by the process that already owns the mapping. capable() has side effects: it marks the task as having used a privilege and can emit LSM audit records. The previous code returned before the check when the mm did not change. Return early in that case again. The result is unchanged: moving the charge of an unchanged owner onto itself was already a no-op. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The map and unmap paths warned when the smallest IOMMU page size is larger than PAGE_SIZE, a layout that the native pinning and dirty tracking code does not handle. The mixed-granule work removed both warnings for every kernel. Keep them when CONFIG_MM_SUBPAGE is off. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The mixed-granule work changed locked_vm accounting for every kernel: refunds take the owner's mmap_lock without allowing a fatal signal to interrupt them, refunds are applied to an mm whose users have all exited, a zero-page charge no longer takes the lock, and a DMA owner change refunds the old mm even after it has exited and undoes the new charge if that refund fails. These keep vfio_dma::locked_vm consistent with the pins that were actually released, which retained fragments rely on, but they also change kernels without mixed user granules. Keep the previous rules when CONFIG_MM_SUBPAGE is off, and build the accounting KUnit suite, which checks the new rules, only with MM_SUBPAGE. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The experimental exec page-size preference is set by an unprivileged prctl and survives exec: PR_AURORA_SET_EXEC_PAGE_SIZE selects the granule for the next exec and PR_AURORA_SET_DEFAULT_PAGE_SIZE for all later ones. Nothing cleared it for a set-user-ID or set-group-ID binary, so an unprivileged user could start a privileged program with a 4K user address space and code paths it was never tested with, and the preference was also inherited by everything that program executed. Treat the preference like the personality flags in PER_CLEAR_ON_SETID. arm64_bprm_prepare_mm() now also records the granule the image gets without a preference (native for AArch64, 4K for AArch32 when available). Once begin_new_exec() has computed the new credentials, an exec that gains privilege (set-user-ID, set-group-ID, file capabilities or an LSM secure-exec transition) is restaged at that granule before the point of no return, and both the one-shot and the default preference are cleared for the new image and its children. Add KUnit cases that stage arguments in a 4K mm and check that a privileged exec is restaged at the native granule with its arguments intact, that an unprivileged one keeps 4K, and that the arch hook records the preference-free granule for AArch64 and AArch32. Only affects kernels built with ARM64_USER4K_EXPERIMENTAL. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HugeTLB mappings are built with the native page table geometry, and PMD tables can be shared between processes mapping the same file (huge_pmd_share() and pt_share_count). An mm with 4K user tables on a 16K kernel uses different table formats, and its table descriptors reuse the same ptdesc word for fragment counts, but nothing stopped a 4K-mode process from mapping hugetlbfs, MAP_HUGETLB, SHM_HUGETLB or MFD_HUGETLB memory. Refuse such mappings with -EINVAL in do_mmap() when the mm's user granule is not the native page size. Every HugeTLB VMA is created through do_mmap(), and fork and exec cannot hand one to such an mm, so this covers all entry points. Applications that probe for huge pages fall back as they do when none are configured. Add a KUnit case that maps a hugetlbfs file and MAP_HUGETLB memory into a 4K mm (refused) and the same file into a native mm (accepted). Only affects kernels built with ARM64_USER4K_EXPERIMENTAL. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The mixed-granule rework split vmf_insert_pfn_prot_mkwrite() into a static __vmf_insert_pfn_prot_mkwrite() helper and a thin exported wrapper, but left the kernel-doc comment on the helper. kernel-doc now warns that the comment describes the wrong prototype and that the helper's offset parameter is undocumented, and the exported function lost its documentation. Move the comment back onto vmf_insert_pfn_prot_mkwrite(). No code change: the prod-config mm/memory.o is identical before and after. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the mmap path was converted to byte offsets for mixed user granules, the AUX page lookup moved from perf_mmap_to_page() into map_range(), and the array_index_nospec() clamp on the AUX page index was dropped. The index is still steered by userspace: map_range() walks every page of the AUX mapping, whose length the caller chooses, and only a conditional branch keeps pagenum below rb->aux_nr_pages before rb->aux_pages[] is read. Perf events are built into every kernel, so this weakened the Spectre-v1 hardening on all configurations. Clamp the index with array_index_nospec() again, as perf_mmap_to_page() did before. The architectural behaviour is unchanged; map_range() again contains the cmp/ngc/csdb/and mask sequence that the .19 kernel had in perf_mmap_to_page(). Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Several ARM64_USER4K_KUNIT_TEST cases create shmem files with shmem_file_setup() and fill them with kernel_write(): the shared cache-file fixture used by many file-mapping cases, the 64K-granule shmem fault allocation-failure case and the 4K shmem partial-hole case. Without CONFIG_TMPFS shmem files have no write_iter, so those writes fail and the cases fail at run time. Nothing in Kconfig asked for TMPFS, so a kunitconfig that enables the tests but not TMPFS builds a kernel whose tests fail. Make ARM64_USER4K_KUNIT_TEST depend on TMPFS, as was done for the VFIO type1 harness options. The in-tree arm64_user4k kunitconfigs already set TMPFS=y and configure as before; without TMPFS, kunit.py now reports the test option as unsatisfiable. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Turn ARM64_USER4K_EXPERIMENTAL on by default, so release kernels configured with olddefconfig include it. A process that doesn't use the PR_AURORA_SET_EXEC_PAGE_SIZE prctl keeps the native granule. The mixed-granule paths in core mm, net, vfio, block and io_uring are then built in, though, and every process runs through them. So far it has run on the J700 (MacBook Neo) with j700.config, and in the arm64_user4k KUnit configurations under QEMU. It has not been run on an M1, M2 or M3 machine. Replace the help text's advice to say N, which no longer matches the default. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The previous commit made ARM64_USER4K_EXPERIMENTAL default to y, so the configuration section no longer matches when it says the option defaults off. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With ARM64_USER4K_EXPERIMENTAL, arch_pick_mmap_layout() takes the mmap randomisation and the mmap_base alignment from current->mm, not from the mm it was given. Exec only calls it once the new mm is installed, so the two are the same there. KUnit's kunit_vm_mmap() also calls it, from a kernel thread with no mm, and every usercopy test then oopses on a NULL pointer dereference in arch_pick_mmap_layout(). Pass the mm through to the randomisation and mmap_base helpers. arch_mmap_rnd() keeps using current->mm for its other callers. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ARM64_USER4K_EXPERIMENTAL is now built into the release kernel by
default. With it, any local user can ask for 4K pages through the
private PR_AURORA_SET_{EXEC,DEFAULT}_PAGE_SIZE prctls on every CPU
that supports the 4K translation granule, M1-M3 included. The
feature's hardware testing so far is DJ's J700 (MacBook Neo) only; it
has never run on an M1, M2 or M3.
Make it an experimental opt-in. The code stays compiled in, but 4K
userspace is now off unless the kernel is booted with user4k=on
(parsed with kstrtobool, so 1/0/y/n work too). user4k_enabled()
reports the choice from a __ro_after_init bool set by an early
parameter, so it is fixed before CPU capabilities are detected.
While it is off:
- arch_exec_page_size_shift(), the validator behind both SET prctls,
refuses every non-native size with EINVAL. A native or zero size
still succeeds, and the GET prctls report the native default.
- arm64_bprm_prepare_mm() ignores any exec preference and no longer
gives AArch32 images 4K, so every ELF exec, and its fallback when
the exec gains privilege, gets the native granule.
- arch_mm_init_exec() never builds an alternative-granule mm, so no
other exec path can create one either.
- The 4K and 16K user granule capabilities are not detected, so
nothing reports 4K support and the boot log has no "4K userspace
translation granule" line.
Fork copies the mm and both preferences, and neither can be set while
off, so nothing non-native is inherited. The shared MM paths that
every process runs stay compiled in and do not change.
Add an arm64-user4k-policy KUnit suite that runs with or without the
parameter. It checks the request policy for both states, and that the
real prctls, exec preparation and exec mm allocation follow the boot
switch. The other user4k suites now need user4k=on. Document the
parameter in kernel-parameters.txt, the Kconfig help and user4k.rst.
Tested under QEMU KUnit: the policy suite passes 3/3 without the
parameter and 3/3 with it, and with user4k=on the arm64_user4k config
gives the same per-test results as before (103 pass, 94 skip) plus
the new cases.
Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MM_SUBPAGE registers a per-page 4K ownership record in page_ext whose need() callback always returned true. A kernel with user4k built in therefore reserved 32 bytes for every native page at boot (2 MiB per GiB of RAM with 16K pages, about 0.2%), although 4K userspace is now off unless the kernel is booted with user4k=on and no 4K mm can exist without it. The feature's hardware testing so far is DJ's J700 only. Add arch_mm_alt_granule_enabled(), which arm64 maps to user4k_enabled(), and return it from need(). Early parameters are parsed in setup_arch(), before mm_core_init() and page_alloc_init_late() size page_ext, so the answer is known in time. Without the record, page_ext can still be allocated for another user such as page_owner or page_table_check, and mm_subpage_ext_ops then has no offset of its own: reading it would alias that user's data. Route every lookup in user-subpage.c through helpers that return no record while user4k is off. Callers that run for all memory already treat a missing record as "no 4K owner", which is the right answer then. The shmem userfaultfd mask helpers report no missing 4K units and ignore updates, and the smaps/pagemap mapcount helper returns zero counts without warning. Add a KUnit case for the lookups on a native page in both states. Verified under QEMU KUnit (1 GiB guest): the arm64_user4k config allocates 4 MiB of page_ext with user4k=on and 2 MiB (page_table_check only) without it; the mm-core config allocates 2 MiB with it and none without it, and passes 39/39 both ways. With user4k=on the user4k configs match the earlier per-test results plus the new cases: arm64_user4k 107 pass/94 skip, mm_kasan 154/47, data_kasan 16/8, VFIO 12/12. Without it the policy suite passes 4/4. A production W=1 build (Image, modules, dtbs) has no new warnings. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4K userspace is now off unless the kernel is booted with user4k=on, and without it the kernel refuses a 4K request with EINVAL. The launcher then only printed "Invalid argument", which does not say what is missing. Say in the README that the kernel must be booted with user4k=on, and print a hint when a smaller-than-native size is refused with EINVAL. errno is saved before the first message is printed. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 17, 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.
Supersedes #131. This carries @DjDeveloperr's rebase of aurora-wip onto integration/aurora, with fixes from review on top. Authors are kept on every carried commit, and it merges with a merge commit.
The carried series
568 of #131's 569 commits, including the merge of aurora-silicon/linux#328. Compared with #131's head:
oe-fabricregister. Probe then fails and Thunderbolt PCIe disappears. It also overrides thepcie_apple.tunnel_kernel_initswitch from PCI: apple: bring up T600x/T602x PCIe-C tunnels without an m1n1 handoff chriskearney/aurora-linux#10, which integration already uses to cold-initialize these ports. The four M2 Pro/Max DTBs are byte-identical to integration again.Most carried commits get new hashes, so aurora-wip needs a rebase onto integration/aurora after this merges.
user4k: built in, off unless booted with
user4k=onARM64_USER4K_EXPERIMENTALnow defaults to y, so the release kernel includes the mixed-granule code. The feature is experimental and stays off at runtime until a user boots withuser4k=on.Without the flag:
PR_AURORA_SET_*_PAGE_SIZEprctls refuse any non-native size;With the flag:
What changes with or without the flag: the shared code is compiled in, so every process on every Mac runs DJ's restructured paths for:
Compared with integration, that brings these visible changes:
locked_vmis counted in 4K units andmaxrssin kB; only BPF and debugging tools that read the kernel fields directly see this.vm_map_pages()on a PFNMAP VMA returns EINVAL, and a misalignedvm_insert_pages()returns EFAULT./proc/PID/mem: reads of PFNMAP mappings go one page-table leaf at a time, and return EINVAL outside the VMA.user4k has run on hardware in @DjDeveloperr's own tree on the J700 (MacBook Neo), with j700.config. This branch has only had short lab boots on an M1 MacBook Air and an M3 Pro MacBook Pro, with and without the flag (see Testing). It needs soak testing on M1, M2 and M3 before a release, both with and without the flag.
Fixes on top (64 commits)
Build
--no-layout-tests, so the stock bindgen the release uses builds again.BINDGEN_LAYOUT_TESTS=1keeps the layout check as an opt-in.TYPEC_TPS6598X_DEBUG_COMMANDS(default n).Neo
mesa-neo-envaccepts both the old and new GPU and display driver names, and still applies only on T8140.t6000fallback is dropped from the binding and the J700 tree, so a .19 kernel booted with the new tree can't misread the report.SEP
Display and USB-C
GPU
Wi-Fi (brcmfmac)
awdl=0as an off-switch. It's refused on interface_create v1 and v2. Only BCM4387 has been tested.Core kernel and user4k
ARM64_USER4K_EXPERIMENTAL=ngives integration's behaviour, apart from the btrfs, net, vfio, mlock and__delayitems below. The release config has the option on, so these gates don't apply there.arch_pick_mmap_layout()uses the mm it's given instead ofcurrent->mm. With the option built in, it oopsed when called from a kernel thread, as KUnit does, with or without the flag. Exec wasn't affected.array_index_nospecback.user4k=boot switch, and skip the page_ext record while it's off.user4k.rst,user_page_size.rst, kernel-parameters and the userpages README.What else changes on M1–M3
These run on M1–M3 with the production config, on top of the shared user4k paths above.
Display and USB-C
appledrmmodule serves every Mac, and it now needsdrm_dma_helper.koin the initramfs.regsdebugfs file.GPU
Touch ID
Wi-Fi (brcmfmac)
awdl_traceoption.Other drivers and core
compress=zstd.skb_splice_from_iterCHECKSUM_NONE offset now matches upstream.mlock_fixupcounts pages in a long.__delayreads MIDR, an M5 workaround that adds one register read per delay on M1–M3.appledrm.hdmi_audio=1, which is off by default on M1–M3.Testing
Build of 7638540: production config (user4k compiled in), W=1, LLVM=1, stock bindgen 0.73.1.
drm_dma_helper.ko.KUnit (QEMU arm64): no failures, and no KASAN or lockdep reports.
user4k=onuser4k=onuser4k=onuser4k=onarch_pick_mmap_layout()oops above; it passes 39/39 with the fix.arm64.user4k_test=1opt-in.DTBs: 112 of 115 are byte-identical to integration. Only t8140-j700, t8142-j813 and t8152-j873g differ.
Lab boots of 7638540 (lab package build, LLVM=1, W=1, bindgen 0.73.2). These were short smoke runs, not soaks.
user4k=on.PR_AURORA_SET_EXEC_PAGE_SIZEsees 4096-byte pages. A process started with the default set to 4K writes and hashes 256 MiB, forks 8 children and execs programs.Still needed before the next release:
user4k=onanduserpages 4k. Nothing has run on an M2 or an M1 Pro/Max yet.Release notes for Neo
appledrm_neo.*orasahi_neo.*parameters becomeappledrm.*orasahi.*.DRM_APPLE=mplusdrm_dma_helper, which the initramfs should pick up through autodetect.FYI:
🤖 Generated with Claude Code