Skip to content

Commit

Permalink
iommu: Add IOMMU index concept to IOMMU API
Browse files Browse the repository at this point in the history
If an IOMMU supports mappings that care about the memory
transaction attributes, then it no longer has a unique
address -> output mapping, but more than one. We can
represent these using an IOMMU index, analogous to TCG's
mmu indexes.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 20180604152941.20374-2-peter.maydell@linaro.org
  • Loading branch information
pm215 committed Jun 15, 2018
1 parent 2151b04 commit 21f4020
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
55 changes: 55 additions & 0 deletions include/exec/memory.h
Expand Up @@ -206,6 +206,20 @@ enum IOMMUMemoryRegionAttr {
* to report whenever mappings are changed, by calling
* memory_region_notify_iommu() (or, if necessary, by calling
* memory_region_notify_one() for each registered notifier).
*
* Conceptually an IOMMU provides a mapping from input address
* to an output TLB entry. If the IOMMU is aware of memory transaction
* attributes and the output TLB entry depends on the transaction
* attributes, we represent this using IOMMU indexes. Each index
* selects a particular translation table that the IOMMU has:
* @attrs_to_index returns the IOMMU index for a set of transaction attributes
* @translate takes an input address and an IOMMU index
* and the mapping returned can only depend on the input address and the
* IOMMU index.
*
* Most IOMMUs don't care about the transaction attributes and support
* only a single IOMMU index. A more complex IOMMU might have one index
* for secure transactions and one for non-secure transactions.
*/
typedef struct IOMMUMemoryRegionClass {
/* private */
Expand Down Expand Up @@ -290,6 +304,29 @@ typedef struct IOMMUMemoryRegionClass {
*/
int (*get_attr)(IOMMUMemoryRegion *iommu, enum IOMMUMemoryRegionAttr attr,
void *data);

/* Return the IOMMU index to use for a given set of transaction attributes.
*
* Optional method: if an IOMMU only supports a single IOMMU index then
* the default implementation of memory_region_iommu_attrs_to_index()
* will return 0.
*
* The indexes supported by an IOMMU must be contiguous, starting at 0.
*
* @iommu: the IOMMUMemoryRegion
* @attrs: memory transaction attributes
*/
int (*attrs_to_index)(IOMMUMemoryRegion *iommu, MemTxAttrs attrs);

/* Return the number of IOMMU indexes this IOMMU supports.
*
* Optional method: if this method is not provided, then
* memory_region_iommu_num_indexes() will return 1, indicating that
* only a single IOMMU index is supported.
*
* @iommu: the IOMMUMemoryRegion
*/
int (*num_indexes)(IOMMUMemoryRegion *iommu);
} IOMMUMemoryRegionClass;

typedef struct CoalescedMemoryRange CoalescedMemoryRange;
Expand Down Expand Up @@ -1054,6 +1091,24 @@ int memory_region_iommu_get_attr(IOMMUMemoryRegion *iommu_mr,
enum IOMMUMemoryRegionAttr attr,
void *data);

/**
* memory_region_iommu_attrs_to_index: return the IOMMU index to
* use for translations with the given memory transaction attributes.
*
* @iommu_mr: the memory region
* @attrs: the memory transaction attributes
*/
int memory_region_iommu_attrs_to_index(IOMMUMemoryRegion *iommu_mr,
MemTxAttrs attrs);

/**
* memory_region_iommu_num_indexes: return the total number of IOMMU
* indexes that this IOMMU supports.
*
* @iommu_mr: the memory region
*/
int memory_region_iommu_num_indexes(IOMMUMemoryRegion *iommu_mr);

/**
* memory_region_name: get a memory region's name
*
Expand Down
23 changes: 23 additions & 0 deletions memory.c
Expand Up @@ -1915,6 +1915,29 @@ int memory_region_iommu_get_attr(IOMMUMemoryRegion *iommu_mr,
return imrc->get_attr(iommu_mr, attr, data);
}

int memory_region_iommu_attrs_to_index(IOMMUMemoryRegion *iommu_mr,
MemTxAttrs attrs)
{
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);

if (!imrc->attrs_to_index) {
return 0;
}

return imrc->attrs_to_index(iommu_mr, attrs);
}

int memory_region_iommu_num_indexes(IOMMUMemoryRegion *iommu_mr)
{
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);

if (!imrc->num_indexes) {
return 1;
}

return imrc->num_indexes(iommu_mr);
}

void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
{
uint8_t mask = 1 << client;
Expand Down

0 comments on commit 21f4020

Please sign in to comment.