The API is defined in the header file sysroot-*-kos/include/coresrv/io/dma.h
from the KasperskyOS SDK.
The API is designed to set up data exchange between devices and RAM in direct memory access (DMA) mode in which the processor is not used.
Information about API functions is provided in the table below.
Using the API
The standard scenario for API usage includes the following steps:
DMA buffer consists of one or more physical memory regions (blocks) that are used for DMA. A DMA buffer consisting of multiple blocks can be used if the device supports "scatter/gather DMA" mode. A DMA buffer consisting of one block can be used only if the device supports "scatter/gather DMA" or "continuous DMA" mode. The likelihood of creating a DMA buffer consisting of one large block is lower than the likelihood of creating a DMA buffer consisting of multiple small blocks. This is especially relevant when physical memory is highly fragmented.
If the device supports only "continuous DMA" mode, you must use a DMA buffer consisting of one block even if IOMMU is enabled.
To complete this step, call the KnIoDmaCreate()
or KnIoDmaCreateContinuous()
function. The KnIoDmaCreateContinuous()
function creates a DMA buffer consisting of one block. The KnIoDmaCreate()
function creates a DMA buffer consisting of one block if the 2^order value is equal to the memory page size value, or if the 2^order value is the next largest value of the memory page size in the ascending ordered set {2^(order-1);memory page size;2^order}. If the value of the memory page size is greater than the 2^order value, the KnIoDmaCreate()
function can create a DMA buffer consisting of multiple blocks.
The DMA buffer handle can be transferred to another process via IPC.
One DMA buffer can be mapped to multiple virtual memory regions of one or more processes that own the handle of this DMA buffer. Mapping allows processes to receive read-and/or-write access to the DMA buffer.
To reserve a virtual memory region and map the DMA buffer to it, call the KnIoDmaMap()
function.
A handle received when calling the KnIoDmaMap()
function cannot be transferred to another process via IPC.
KnIoDmaBegin()
function call.The KnIoDmaBegin()
function must be called to create a kernel object containing the addresses and sizes of blocks comprising the DMA buffer. A device needs this information to use the DMA buffer. A device can work with physical addresses and/or virtual addresses depending on whether IOMMU is enabled. If IOMMU is enabled, an object contains virtual addresses of blocks. Otherwise, an object contains physical addresses of blocks.
A handle received when calling the KnIoDmaBegin()
function cannot be transferred to another process via IPC.
At this step, get the addresses and sizes of blocks from the kernel object that was created by calling the KnIoDmaBegin()
function. The received addresses and sizes will need to be passed to the device by using MMIO, for example. After receiving this information, the device can write to the DMA buffer and/or read from it (if IOMMU is enabled, a device on the PCIe bus must be attached to the IOMMU domain).
To complete this step, you need to call the KnIoDmaGetInfo()
or KnIoDmaContinuousGetDmaAddr()
function. The KnIoDmaGetInfo()
function gets the memory page number (frame
) and the order
for each block. (The memory page number multiplied by the memory page size results in the block address. The 2^order value is the block size in memory pages.) The KnIoDmaContinuousGetDmaAddr()
function can be used if the DMA buffer consists of one block. This function gets the block address. (The accepted block size should be the DMA buffer size that was defined when this buffer was created.)
Closing access to the DMA buffer for a device
If you delete the kernel object that was created when the KnIoDmaBegin()
function was called and IOMMU is enabled, the device will be denied access to the DMA buffer. To delete this object, call the KnHandleClose()
function and specify the handle that was received when the KnIoDmaBegin()
function was called. (The KnHandleClose()
function is declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h
from the KasperskyOS SDK.)
Deleting a DMA buffer
To delete a DMA buffer, complete the following steps:
KnIoDmaMap()
function calls.To complete this step, use the KnHandleClose()
function and specify the handles that were received from KnIoDmaMap()
function calls. (KnHandleClose()
function is declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h
from the KasperskyOS SDK.)
This step must be completed for all processes whose memory is mapped to the DMA buffer.
KnIoDmaBegin()
function call.To complete this step, call the KnHandleClose()
function and specify the handle that was received when the KnIoDmaBegin()
function was called.
To complete this step, use the KnHandleClose()
and/or KnHandleRevoke()
functions that are declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h
from the KasperskyOS SDK.
Information about API functions
dma.h functions
Function |
Information about the function |
---|---|
|
Purpose Creates a DMA buffer. Parameters
Returned values If successful, the function returns Additional information In the
|
|
Purpose Creates a DMA buffer consisting of one block. Parameters
Returned values If successful, the function returns Additional information In the
|
|
Purpose Reserves a virtual memory region and maps the DMA buffer to it. Parameters
Returned values If successful, the function returns Additional information In the
|
|
Purpose Modifies the DMA buffer cache settings. Parameters
Returned values If successful, the function returns Additional information This function can be used if the following conditions are fulfilled:
In the
|
|
Purpose Gets information about a DMA buffer. This information includes the addresses and sizes of blocks. Parameters
Returned values If successful, the function returns |
|
Purpose Gets the block address for a DMA buffer consisting of one block. Parameters
Returned values If successful, the function returns |
|
Purpose Opens access to a DMA buffer for a device. Parameters
Returned values If successful, the function returns |