123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- /** @file
- Copyright (c) 2019, Linaro, Ltd. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <PiDxe.h>
- #include <Library/BaseLib.h>
- #include <Library/DebugLib.h>
- #include <Library/DmaLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Protocol/IoMmu.h>
- /**
- Set IOMMU attribute for a system memory.
- If the IOMMU protocol exists, the system memory cannot be used
- for DMA by default.
- When a device requests a DMA access for a system memory,
- the device driver need use SetAttribute() to update the IOMMU
- attribute to request DMA access (read and/or write).
- The DeviceHandle is used to identify which device submits the request.
- The IOMMU implementation need translate the device path to an IOMMU device
- ID, and set IOMMU hardware register accordingly.
- 1) DeviceHandle can be a standard PCI device.
- The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.
- The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.
- The memory for BusMasterCommonBuffer need set
- EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE.
- After the memory is used, the memory need set 0 to keep it being
- protected.
- 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).
- The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or
- EDKII_IOMMU_ACCESS_WRITE.
- @param[in] This The protocol instance pointer.
- @param[in] DeviceHandle The device who initiates the DMA access
- request.
- @param[in] Mapping The mapping value returned from Map().
- @param[in] IoMmuAccess The IOMMU access.
- @retval EFI_SUCCESS The IoMmuAccess is set for the memory range
- specified by DeviceAddress and Length.
- @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.
- @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
- Map().
- @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination
- of access.
- @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.
- @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported
- by the IOMMU.
- @retval EFI_UNSUPPORTED The IOMMU does not support the memory range
- specified by Mapping.
- @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
- modify the IOMMU access.
- @retval EFI_DEVICE_ERROR The IOMMU device reported an error while
- attempting the operation.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- NonCoherentIoMmuSetAttribute (
- IN EDKII_IOMMU_PROTOCOL *This,
- IN EFI_HANDLE DeviceHandle,
- IN VOID *Mapping,
- IN UINT64 IoMmuAccess
- )
- {
- return EFI_UNSUPPORTED;
- }
- /**
- Provides the controller-specific addresses required to access system memory
- from a DMA bus master. On SEV guest, the DMA operations must be performed on
- shared buffer hence we allocate a bounce buffer to map the HostAddress to a
- DeviceAddress. The Encryption attribute is removed from the DeviceAddress
- buffer.
- @param This The protocol instance pointer.
- @param Operation Indicates if the bus master is going to read or
- write to system memory.
- @param HostAddress The system memory address to map to the PCI
- controller.
- @param NumberOfBytes On input the number of bytes to map. On output
- the number of bytes that were mapped.
- @param DeviceAddress The resulting map address for the bus master
- PCI controller to use to access the hosts
- HostAddress.
- @param Mapping A resulting value to pass to Unmap().
- @retval EFI_SUCCESS The range was mapped for the returned
- NumberOfBytes.
- @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common
- buffer.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
- lack of resources.
- @retval EFI_DEVICE_ERROR The system hardware could not map the requested
- address.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- NonCoherentIoMmuMap (
- IN EDKII_IOMMU_PROTOCOL *This,
- IN EDKII_IOMMU_OPERATION Operation,
- IN VOID *HostAddress,
- IN OUT UINTN *NumberOfBytes,
- OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
- OUT VOID **Mapping
- )
- {
- DMA_MAP_OPERATION DmaOperation;
- switch (Operation) {
- case EdkiiIoMmuOperationBusMasterRead:
- case EdkiiIoMmuOperationBusMasterRead64:
- DmaOperation = MapOperationBusMasterRead;
- break;
- case EdkiiIoMmuOperationBusMasterWrite:
- case EdkiiIoMmuOperationBusMasterWrite64:
- DmaOperation = MapOperationBusMasterWrite;
- break;
- case EdkiiIoMmuOperationBusMasterCommonBuffer:
- case EdkiiIoMmuOperationBusMasterCommonBuffer64:
- DmaOperation = MapOperationBusMasterCommonBuffer;
- break;
- default:
- ASSERT (FALSE);
- return EFI_INVALID_PARAMETER;
- }
- return DmaMap (
- DmaOperation,
- HostAddress,
- NumberOfBytes,
- DeviceAddress,
- Mapping
- );
- }
- /**
- Completes the Map() operation and releases any corresponding resources.
- @param This The protocol instance pointer.
- @param Mapping The mapping value returned from Map().
- @retval EFI_SUCCESS The range was unmapped.
- @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
- Map().
- @retval EFI_DEVICE_ERROR The data was not committed to the target system
- memory.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- NonCoherentIoMmuUnmap (
- IN EDKII_IOMMU_PROTOCOL *This,
- IN VOID *Mapping
- )
- {
- return DmaUnmap (Mapping);
- }
- /**
- Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
- OperationBusMasterCommonBuffer64 mapping.
- @param This The protocol instance pointer.
- @param Type This parameter is not used and must be ignored.
- @param MemoryType The type of memory to allocate,
- EfiBootServicesData or EfiRuntimeServicesData.
- @param Pages The number of pages to allocate.
- @param HostAddress A pointer to store the base system memory
- address of the allocated range.
- @param Attributes The requested bit mask of attributes for the
- allocated range.
- @retval EFI_SUCCESS The requested memory pages were allocated.
- @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal
- attribute bits are MEMORY_WRITE_COMBINE and
- MEMORY_CACHED.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
- @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- NonCoherentIoMmuAllocateBuffer (
- IN EDKII_IOMMU_PROTOCOL *This,
- IN EFI_ALLOCATE_TYPE Type,
- IN EFI_MEMORY_TYPE MemoryType,
- IN UINTN Pages,
- IN OUT VOID **HostAddress,
- IN UINT64 Attributes
- )
- {
- return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
- }
- /**
- Frees memory that was allocated with AllocateBuffer().
- @param This The protocol instance pointer.
- @param Pages The number of pages to free.
- @param HostAddress The base system memory address of the allocated
- range.
- @retval EFI_SUCCESS The requested memory pages were freed.
- @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
- Pages was not allocated with AllocateBuffer().
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- NonCoherentIoMmuFreeBuffer (
- IN EDKII_IOMMU_PROTOCOL *This,
- IN UINTN Pages,
- IN VOID *HostAddress
- )
- {
- return DmaFreeBuffer (Pages, HostAddress);
- }
- STATIC EDKII_IOMMU_PROTOCOL mNonCoherentIoMmuOps = {
- EDKII_IOMMU_PROTOCOL_REVISION,
- NonCoherentIoMmuSetAttribute,
- NonCoherentIoMmuMap,
- NonCoherentIoMmuUnmap,
- NonCoherentIoMmuAllocateBuffer,
- NonCoherentIoMmuFreeBuffer,
- };
- EFI_STATUS
- EFIAPI
- NonCoherentIoMmuDxeEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- return gBS->InstallMultipleProtocolInterfaces (
- &ImageHandle,
- &gEdkiiIoMmuProtocolGuid,
- &mNonCoherentIoMmuOps,
- NULL
- );
- }
|