Conversation
Signed-off-by: Koichi <koichi.imai.2@tier4.jp>
Signed-off-by: Koichi <koichi.imai.2@tier4.jp>
Signed-off-by: Koichi <koichi.imai.2@tier4.jp>
Signed-off-by: Koichi <koichi.imai.2@tier4.jp>
Signed-off-by: Koichi <koichi.imai.2@tier4.jp>
veqcc
approved these changes
Aug 29, 2025
Closed
ytakano
approved these changes
Sep 12, 2025
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.
Description
Summary
This PR introduces a new DMA mapping API (
dma_map.rs) that provides a robust abstraction for managing DMA transfers between devices and memory. In short, DmaMap layer transforms memory buffers into appropriate segment lists that conform to device-specific constraints.Key Features
DmaConstraintsstructure (boundary, segment size/count limits, alignment)Core Components:
DmaConstraints: Defines device-specific DMA constraints (max segment size, count, boundary, alignment)DmaMap: Manages the mapping between virtual and physical addresses for DMADmaSegment: Represents a physically contiguous memory segmentDesign Decisions
Transfer size validation without splitting
Similar to OpenBSD's approach, we expect transfers to be limited before reaching the DMAMap layer.
Dynamic bounce buffer as fallback (not recommended)
The dynamic bounce buffer allocation using
DMAPool::new()is implemented as a safety net to prevent failures, but it's not the intended path. The warning log alerts developers that their device driver should pre-allocate DMA memory to avoid unpredictable runtime overhead.Simplified segment tracking
OpenBSD tracks per-segment virtual addresses (
_ds_vaand_ds_bounce_va) to enable fine-grained copying between original and bounce buffers. AWKernel stores virtual addresses only at the map level (orig_vaddr,owned_memory) because we always allocate bounce buffers as single contiguous segments.Segment coalescing optimization
The DMA mapping layer includes segment coalescing logic that merges physically contiguous pages into single segments when possible. While this optimization rarely benefits NVMe controllers (which typically set
maxsegsize = PAGESIZE, preventing coalescing), it's implemented to support other device types.Related links
The implementation is not exactly what OpenBSD does in bus_dma but somewhat similar.
bus_dmamap_load
https://github.com/openbsd/src/blob/95647c95e86787fd3d10394754ce3752dc75799c/sys/arch/amd64/amd64/bus_dma.c#L254
bus_dmamap_unload
https://github.com/openbsd/src/blob/95647c95e86787fd3d10394754ce3752dc75799c/sys/arch/amd64/amd64/bus_dma.c#L499
struct bus_dma_segment
https://github.com/openbsd/src/blob/0f23fd2bd67855dcb0ac92c75619a560be0a8fa1/sys/arch/amd64/include/bus.h#L552
struct bus_dmamap
https://github.com/openbsd/src/blob/0f23fd2bd67855dcb0ac92c75619a560be0a8fa1/sys/arch/amd64/include/bus.h#L649
How was this PR tested?
Notes for reviewers
A bit more details about Design Decisions (Note for myself)
Transfer size validation without splitting
OpenBSD uses physio() with minphys() to enforce these limits. AWKernel hasn't implemented an equivalent physio layer yet, so this responsibility temporarily falls on upper layers. When a transfer exceeds
DmaConstraints::maxsize, we returnDmaError::SizeTooLargerather than attempting to split it. This matches the philosophy that the DMA layer should map what it's given, not make policy decisions about transfer sizes.Dynamic bounce buffer as fallback
USB drivers with large segment requirements should use
DmaMap::from_dma_pool()with pre-allocated buffers rather than relying on dynamic allocation. This design ensures the system won't fail while making it clear that proper DMA memory management requires upfront allocation. The dynamic path exists primarily for unexpected fragmentation scenarios that shouldn't occur with well-designed drivers.