Thanks, Ard. It is a good open that if we really need both SetAttribute and SetMappingAttribute.
Looking at code again, I prefer to remove SetAttribute(). I do not suggest we define MapInfo, because I want to make it DMA engine implementation choice. All we want is just to set an access attribute for this mapping, there is no need to input base/length. Because Map() should always be called by a device driver, no matter it is PCI DMA, ISA DMA, or low power controller DMA, I think SetMappingAttribute is good enough. I will plan to remove SetAttribute() in V5. Thank you Yao Jiewen From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Ard Biesheuvel Sent: Tuesday, May 2, 2017 5:56 PM To: Yao, Jiewen <jiewen....@intel.com> Cc: Ni, Ruiyu <ruiyu...@intel.com>; edk2-devel@lists.01.org; Leo Duran <leo.du...@amd.com> Subject: Re: [edk2] [PATCH 1/3] MdeModulePkg/Include: Add IOMMU protocol definition. Hello Jiewen, On 29 April 2017 at 14:48, Jiewen Yao <jiewen....@intel.com<mailto:jiewen....@intel.com>> wrote: > This protocol is to abstract DMA access from IOMMU. > 1) Intel "DMAR" ACPI table. > 2) AMD "IVRS" ACPI table > 3) ARM "IORT" ACPI table. > > There might be multiple IOMMU engines on one platform. > For example, one for graphic and one for rest PCI devices > (such as ATA/USB). > All IOMMU engines are reported by one ACPI table. > > All IOMMU protocol provider should be based upon ACPI table. > This single IOMMU protocol can handle multiple IOMMU engines on one system. > > This IOMMU protocol provider can use UEFI device path to distinguish > if the device is graphic or ATA/USB, and find out corresponding > IOMMU engine. > > The IOMMU protocol provides 2 capabilities: > A) Set DMA access attribute - such as write/read control. > B) Remap DMA memory - such as remap above 4GiB system memory address > to below 4GiB device address. > It provides AllocateBuffer/FreeBuffer/Map/Unmap for DMA memory. > The remapping can be static (fixed at build time) or dynamic (allocate > at runtime). > > 4) AMD "SEV" feature. > We can have an AMD SEV specific IOMMU driver to produce IOMMU protocol, > and manage SEV bit. > > Cc: Ruiyu Ni <ruiyu...@intel.com<mailto:ruiyu...@intel.com>> > Cc: Leo Duran <leo.du...@amd.com<mailto:leo.du...@amd.com>> > Cc: Brijesh Singh <brijesh.si...@amd.com<mailto:brijesh.si...@amd.com>> > Cc: Ard Biesheuvel > <ard.biesheu...@linaro.org<mailto:ard.biesheu...@linaro.org>> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Jiewen Yao <jiewen....@intel.com<mailto:jiewen....@intel.com>> > --- > MdeModulePkg/Include/Protocol/IoMmu.h | 310 ++++++++++++++++++++ > MdeModulePkg/MdeModulePkg.dec | 3 + > 2 files changed, 313 insertions(+) > > diff --git a/MdeModulePkg/Include/Protocol/IoMmu.h > b/MdeModulePkg/Include/Protocol/IoMmu.h > new file mode 100644 > index 0000000..3f62f46 > --- /dev/null > +++ b/MdeModulePkg/Include/Protocol/IoMmu.h > @@ -0,0 +1,310 @@ > +/** @file > + EFI IOMMU Protocol. > + > +Copyright (c) 2017, Intel Corporation. All rights reserved.<BR> > +This program and the accompanying materials are licensed and made available > under > +the terms and conditions of the BSD License that accompanies this > distribution. > +The full text of the license may be found at > +http://opensource.org/licenses/bsd-license.php. > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > +**/ > + > + > +#ifndef __IOMMU_H__ > +#define __IOMMU_H__ > + > +// > +// IOMMU Protocol GUID value > +// > +#define EDKII_IOMMU_PROTOCOL_GUID \ > + { \ > + 0x4e939de9, 0xd948, 0x4b0f, { 0x88, 0xed, 0xe6, 0xe1, 0xce, 0x51, > 0x7c, 0x1e } \ > + } > + > +// > +// Forward reference for pure ANSI compatability > +// > +typedef struct _EDKII_IOMMU_PROTOCOL EDKII_IOMMU_PROTOCOL; > + > +// > +// Revision The revision to which the IOMMU interface adheres. > +// All future revisions must be backwards compatible. > +// If a future version is not back wards compatible it is not the > same GUID. > +// > +#define EDKII_IOMMU_PROTOCOL_REVISION 0x00010000 > + > +// > +// IOMMU Access for SetAttribute > +// > +// These types can be "ORed" together as needed. > +// Any undefined bits are reserved and must be zero. > +// > +#define EDKII_IOMMU_ACCESS_READ 0x1 > +#define EDKII_IOMMU_ACCESS_WRITE 0x2 > + > +// > +// IOMMU Operation for Map > +// > +typedef enum { > + /// > + /// A read operation from system memory by a bus master that is not > capable of producing > + /// PCI dual address cycles. > + /// > + EdkiiIoMmuOperationBusMasterRead, > + /// > + /// A write operation from system memory by a bus master that is not > capable of producing > + /// PCI dual address cycles. > + /// > + EdkiiIoMmuOperationBusMasterWrite, > + /// > + /// Provides both read and write access to system memory by both the > processor and a bus > + /// master that is not capable of producing PCI dual address cycles. > + /// > + EdkiiIoMmuOperationBusMasterCommonBuffer, > + /// > + /// A read operation from system memory by a bus master that is capable of > producing PCI > + /// dual address cycles. > + /// > + EdkiiIoMmuOperationBusMasterRead64, > + /// > + /// A write operation to system memory by a bus master that is capable of > producing PCI > + /// dual address cycles. > + /// > + EdkiiIoMmuOperationBusMasterWrite64, > + /// > + /// Provides both read and write access to system memory by both the > processor and a bus > + /// master that is capable of producing PCI dual address cycles. > + /// > + EdkiiIoMmuOperationBusMasterCommonBuffer64, > + EdkiiIoMmuOperationMaximum > +} EDKII_IOMMU_OPERATION; > + > +// > +// IOMMU attribute for AllocateBuffer > +// Any undefined bits are reserved and must be zero. > +// > +#define EDKII_IOMMU_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 > +#define EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED 0x0800 > +#define EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 > + > +#define EDKII_IOMMU_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER > (EDKII_IOMMU_ATTRIBUTE_MEMORY_WRITE_COMBINE | > EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED | > EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) > + > +#define EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER > (~EDKII_IOMMU_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER) > + > +/** > + 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] DeviceAddress The base of device memory address to be used > as the DMA memory. > + @param[in] Length The length of device memory address to be > used as the DMA memory. > + @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 DeviceAddress is not IoMmu Page size > aligned. > + @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned. > + @retval EFI_INVALID_PARAMETER Length is 0. > + @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 DeviceAddress and Length. > + @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. > + > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_IOMMU_SET_ATTRIBUTE)( > + IN EDKII_IOMMU_PROTOCOL *This, > + IN EFI_HANDLE DeviceHandle, > + IN EFI_PHYSICAL_ADDRESS DeviceAddress, > + IN UINT64 Length, > + IN UINT64 IoMmuAccess > + ); > + It is a bit unfortunate that we need both SetAttribute and SetMappingAttribute. Could we instead make the MAPPING_INFO struct (or at least, some part of it) part of the protocol? This would allow the PCI bus driver to call SetAttribute() directly, taking the values from the struct. > +/** > + Provides the controller-specific addresses required to access system > memory from a > + DMA bus master. > + > + @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. > + > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_IOMMU_MAP)( > + 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 > + ); > + > +/** > + 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. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_IOMMU_UNMAP)( > + IN EDKII_IOMMU_PROTOCOL *This, > + IN VOID *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. > + > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_IOMMU_ALLOCATE_BUFFER)( > + 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 > + ); > + > +/** > + 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(). > + > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_IOMMU_FREE_BUFFER)( > + IN EDKII_IOMMU_PROTOCOL *This, > + IN UINTN Pages, > + IN VOID *HostAddress > + ); > + > +/** > + 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. > + > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EDKII_IOMMU_SET_MAPPING_ATTRIBUTE)( > + IN EDKII_IOMMU_PROTOCOL *This, > + IN EFI_HANDLE DeviceHandle, > + IN VOID *Mapping, > + IN UINT64 IoMmuAccess > + ); > + > +/// > +/// IOMMU Protocol structure. > +/// > +struct _EDKII_IOMMU_PROTOCOL { > + UINT64 Revision; > + EDKII_IOMMU_SET_ATTRIBUTE SetAttribute; > + EDKII_IOMMU_MAP Map; > + EDKII_IOMMU_UNMAP Unmap; > + EDKII_IOMMU_ALLOCATE_BUFFER AllocateBuffer; > + EDKII_IOMMU_FREE_BUFFER FreeBuffer; > + EDKII_IOMMU_SET_MAPPING_ATTRIBUTE SetMappingAttribute; > +}; > + > +/// > +/// IOMMU Protocol GUID variable. > +/// > +extern EFI_GUID gEdkiiIoMmuProtocolGuid; > + > +#endif > diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec > index 356b3e1..db596b6 100644 > --- a/MdeModulePkg/MdeModulePkg.dec > +++ b/MdeModulePkg/MdeModulePkg.dec > @@ -540,6 +540,9 @@ > ## Include/Protocol/NonDiscoverableDevice.h > gEdkiiNonDiscoverableDeviceProtocolGuid = { 0x0d51905b, 0xb77e, 0x452a, > {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } } > > + ## Include/Protocol/IoMmu.h > + gEdkiiIoMmuProtocolGuid = { 0x4e939de9, 0xd948, 0x4b0f, { 0x88, 0xed, > 0xe6, 0xe1, 0xce, 0x51, 0x7c, 0x1e } } > + > # > # [Error.gEfiMdeModulePkgTokenSpaceGuid] > # 0x80000001 | Invalid value provided. > -- > 2.7.4.windows.1 > _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org> https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel