diff --git a/iommu_ref_model/README.md b/iommu_ref_model/README.md index 6d00bcdb..73af1e9c 100644 --- a/iommu_ref_model/README.md +++ b/iommu_ref_model/README.md @@ -142,6 +142,10 @@ This function when invoked causes the IOMMU to process a command from the comman function acts like a "clock" and in each invocation processes one command. If multiple command processing is required then the function should be invoked for each command. +9. **`void get_attribs_from_req(hb_to_iommu_req_t *req, uint8_t *read, uint8_t *write, uint8_t *exec, uint8_t *priv)`** + +This function is used to extract the read, write, execute, and privilege +attributes from the the request. # Libtables functions The following functions are provided by the libtables to build memory resident data structures. diff --git a/iommu_ref_model/libiommu/include/iommu_ref_api.h b/iommu_ref_model/libiommu/include/iommu_ref_api.h index 480e6642..ea5db15d 100644 --- a/iommu_ref_model/libiommu/include/iommu_ref_api.h +++ b/iommu_ref_model/libiommu/include/iommu_ref_api.h @@ -28,5 +28,7 @@ extern void process_commands(void); extern void iommu_to_hb_do_global_observability_sync(uint8_t PR, uint8_t PW); extern void send_msg_iommu_to_hb(ats_msg_t *prgr); +extern void get_attribs_from_req(hb_to_iommu_req_t *req, uint8_t *read, + uint8_t *write, uint8_t *exec, uint8_t *priv); #endif // __IOMMU_REF_API_H__ diff --git a/iommu_ref_model/libiommu/src/iommu_translate.c b/iommu_ref_model/libiommu/src/iommu_translate.c index 00163f44..6074a85d 100644 --- a/iommu_ref_model/libiommu/src/iommu_translate.c +++ b/iommu_ref_model/libiommu/src/iommu_translate.c @@ -68,32 +68,8 @@ iommu_translate_iova( // Has to be one of the valid ttypes - this only for debug - not architectural if ( TTYP == TTYPE_NONE ) *((char *)0) = 0; - is_read = ( req->tr.read_writeAMO == READ ) ? 1 : 0; - is_write = ( req->tr.read_writeAMO == WRITE ) ? 1 : 0; - - // The No Write flag, when Set, indicates that the Function is requesting read-only - // access for this translation. - // The TA (IOMMU) may ignore the No Write Flag, however, if the TA responds with a - // translation marked as read-only then the Function must not issue Memory Write - // transactions using that translation. In this case, the Function may issue another - // translation request with the No Write flag Clear, which may result in a new - // translation completion with or without the W (Write) bit Set. - // Upon receiving a Translation Request with the NW flag Clear, TAs are permitted to - // mark the associated pages dirty. Functions MUST not issue such Requests - // unless they have been given explicit write permission. - // Note ATS Translation requests are read - so read_writeAMO is READ for these requests - is_write = ( (req->tr.at == ADDR_TYPE_PCIE_ATS_TRANSLATION_REQUEST) && - (req->no_write == 0) ) ? 1 : is_write; - - // If a Translation Request has a PASID, the Untranslated Address Field is an address - // within the process address space indicated by the PASID field. - // If a Translation Request has a PASID with either the Privileged Mode Requested - // or Execute Requested bit Set, these may be used in constructing the Translation - // Completion Data Entry. The PASID Extended Capability indicates whether a Function - // supports and is enabled to send and receive TLPs with the PASID. - is_exec = ( (is_read && req->exec_req && - (req->tr.at == ADDR_TYPE_UNTRANSLATED || req->pid_valid)) ) ? 1 : 0; - priv = ( req->pid_valid && req->priv_req ) ? S_MODE : U_MODE; + // Extract read/write/exec/priv attributes from request + get_attribs_from_req(req, &is_read, &is_write, &is_exec, &priv); // The process to translate an `IOVA` is as follows: // 1. If `ddtp.iommu_mode == Off` then stop and report "All inbound transactions diff --git a/iommu_ref_model/test/tbapi.c b/iommu_ref_model/test/tbapi.c index 38182a2c..721627d4 100644 --- a/iommu_ref_model/test/tbapi.c +++ b/iommu_ref_model/test/tbapi.c @@ -62,3 +62,36 @@ send_msg_iommu_to_hb( memcpy(&rcvd_msg, msg, sizeof(ats_msg_t)); return; } + +void +get_attribs_from_req( + hb_to_iommu_req_t *req, uint8_t *read, uint8_t *write, uint8_t *exec, uint8_t *priv) { + + *read = ( req->tr.read_writeAMO == READ ) ? 1 : 0; + *write = ( req->tr.read_writeAMO == WRITE ) ? 1 : 0; + + // The No Write flag, when Set, indicates that the Function is requesting read-only + // access for this translation. + // The TA (IOMMU) may ignore the No Write Flag, however, if the TA responds with a + // translation marked as read-only then the Function must not issue Memory Write + // transactions using that translation. In this case, the Function may issue another + // translation request with the No Write flag Clear, which may result in a new + // translation completion with or without the W (Write) bit Set. + // Upon receiving a Translation Request with the NW flag Clear, TAs are permitted to + // mark the associated pages dirty. Functions MUST not issue such Requests + // unless they have been given explicit write permission. + // Note ATS Translation requests are read - so read_writeAMO is READ for these requests + *write = ( (req->tr.at == ADDR_TYPE_PCIE_ATS_TRANSLATION_REQUEST) && + (req->no_write == 0) ) ? 1 : *write; + + // If a Translation Request has a PASID, the Untranslated Address Field is an address + // within the process address space indicated by the PASID field. + // If a Translation Request has a PASID with either the Privileged Mode Requested + // or Execute Requested bit Set, these may be used in constructing the Translation + // Completion Data Entry. The PASID Extended Capability indicates whether a Function + // supports and is enabled to send and receive TLPs with the PASID. + *exec = ( (*read && req->exec_req && + (req->tr.at == ADDR_TYPE_UNTRANSLATED || req->pid_valid)) ) ? 1 : 0; + *priv = ( req->pid_valid && req->priv_req ) ? S_MODE : U_MODE; + return; +}