How to allocate contiguous memory in DriverKit?

We want to allocate a block of contiguous memory (≤1M) for audio ring DMA usage, but we haven't found any explicit method in the DriverKit documentation for allocating contiguous memory.

I'm aware that IOBufferMemoryDescriptor::Create can be used in DriverKit to allocate memory and share it with user space. However, is the allocated memory physically contiguous? Can it guarantee that when I subsequently call PrepareForDMA in IODMACommand, there will be only one segment?

Could you please help review this? Thank you!

Answered by DTS Engineer in 862837022

I'm aware that IOBufferMemoryDescriptor::Create can be used in DriverKit to allocate memory and share it with user space. However, is the allocated memory physically contiguous?

True physical continuity is largely irrelevant on our platforms. At this point, all of our platforms include an IOMMU which manages mapping 64-bit memory ranges into the "physical" addresses visible to devices on the PCI bus. You can read more about how this actually works in "Background Info on PCI Address Translation".

Can it guarantee that when I subsequently call PrepareForDMA in IODMACommand, there will be only one segment?

Yes. Many of our DEXTs actually check that "segmentsCount==1" and assert (crash) on any value other than "1". Having the descriptor segment would imply that the machine was so far out of the expected behavior range that they'd prefer to crash instead of trying to "sort it out". I'm actually not sure a DEXT could get IODMACommand to segment. Inside the kernel, this is typically caused by IOMultiMemoryDescriptor, but that doesn't exist in DriverKit. Maybe there is an IODMACommandSpecification configuration that would cause segmentation, but I'm not sure what that would be.

Also, anticipating your question:

We want to allocate a block of contiguous memory (≤1M) for audio ring DMA usage...

Obviously, there is an upper limit to this sort of thing, but that limit is FAR above the 1M range (think 1+ GB). I believe IOBufferMemoryDescriptor will actually fail to create when you hit that limit.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

I'm aware that IOBufferMemoryDescriptor::Create can be used in DriverKit to allocate memory and share it with user space. However, is the allocated memory physically contiguous?

True physical continuity is largely irrelevant on our platforms. At this point, all of our platforms include an IOMMU which manages mapping 64-bit memory ranges into the "physical" addresses visible to devices on the PCI bus. You can read more about how this actually works in "Background Info on PCI Address Translation".

Can it guarantee that when I subsequently call PrepareForDMA in IODMACommand, there will be only one segment?

Yes. Many of our DEXTs actually check that "segmentsCount==1" and assert (crash) on any value other than "1". Having the descriptor segment would imply that the machine was so far out of the expected behavior range that they'd prefer to crash instead of trying to "sort it out". I'm actually not sure a DEXT could get IODMACommand to segment. Inside the kernel, this is typically caused by IOMultiMemoryDescriptor, but that doesn't exist in DriverKit. Maybe there is an IODMACommandSpecification configuration that would cause segmentation, but I'm not sure what that would be.

Also, anticipating your question:

We want to allocate a block of contiguous memory (≤1M) for audio ring DMA usage...

Obviously, there is an upper limit to this sort of thing, but that limit is FAR above the 1M range (think 1+ GB). I believe IOBufferMemoryDescriptor will actually fail to create when you hit that limit.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

How to allocate contiguous memory in DriverKit?
 
 
Q