diff --git a/iommu_ref_model/libiommu/src/iommu_ats.c b/iommu_ref_model/libiommu/src/iommu_ats.c index 5669bf3b..2e20c4ef 100644 --- a/iommu_ref_model/libiommu/src/iommu_ats.c +++ b/iommu_ref_model/libiommu/src/iommu_ats.c @@ -102,27 +102,43 @@ handle_page_request( page_rec_t prec; uint8_t L; uint16_t PRGI; - uint32_t device_id, cause, status, response_code; + uint32_t device_id, cause, status, response_code, PRPR; uint64_t prec_addr; uint64_t pqb; uint32_t pqh; uint32_t pqt; + PRPR = 0; + device_id = ( pr->DSV == 1 ) ? (pr->RID | (pr->DSEG << 16)) : pr->RID; + if ( g_reg_file.ddtp.iommu_mode == Off ) { + cause = 256; // "All inbound transactions disallowed" + report_fault(cause, PAGE_REQ_MSG_CODE, 0, PCIE_MESSAGE_REQUEST, 0, + device_id, pr->PV, pr->PID, pr->PRIV); + response_code = RESPONSE_FAILURE; + goto send_prgr; + } + if ( g_reg_file.ddtp.iommu_mode == DDT_Bare ) { + cause = 260; // "Transaction type disallowed" + report_fault(cause, PAGE_REQ_MSG_CODE, 0, PCIE_MESSAGE_REQUEST, 0, + device_id, pr->PV, pr->PID, pr->PRIV); + response_code = INVALID_REQUEST; + goto send_prgr; + } // To process a "Page Request" or "Stop Marker" message, the IOMMU first // locates the device-context to determine if ATS and PRI are enabled for // the requestor. - device_id = ( pr->DSV == 1 ) ? (pr->RID | (pr->DSEG << 16)) : pr->RID; if ( locate_device_context(&DC, device_id, pr->PV, pr->PID, &cause) ) { report_fault(cause, PAGE_REQ_MSG_CODE, 0, PCIE_MESSAGE_REQUEST, 0, device_id, pr->PV, pr->PID, pr->PRIV); response_code = RESPONSE_FAILURE; goto send_prgr; } + PRPR = DC.tc.PRPR; if ( DC.tc.EN_PRI == 0 ) { // 7. if any of the following conditions hold then stop and report // "Transaction type disallowed" (cause = 260). // * Transaction type is a PCIe "Page Request" Message and `DC.tc.EN_PRI` is 0. - report_fault(260, PAGE_REQ_MSG_CODE, 0, PCIE_MESSAGE_REQUEST, 0, + report_fault(260, PAGE_REQ_MSG_CODE, 0, PCIE_MESSAGE_REQUEST, DC.tc.DTF, device_id, pr->PV, pr->PID, pr->PRIV); response_code = INVALID_REQUEST; goto send_prgr; @@ -286,17 +302,12 @@ handle_page_request( // the associated "Page Request" had a PASID. For IOMMU generated "Page Request // Group Response" with response code set to Response Failure, if the "Page Request" // had a PASID then response is generated with a PASID. - if ( response_code == INVALID_REQUEST || response_code == SUCCESS ) { - if ( DC.tc.PRPR == 1 ) { - prgr.PV = pr->PV; - prgr.PID = pr->PID; - } else { - prgr.PV = 0; - prgr.PID = 0; - } - } else { + if ( PRPR == 1 ) { prgr.PV = pr->PV; prgr.PID = pr->PID; + } else { + prgr.PV = 0; + prgr.PID = 0; } // PAYLOAD encoding of PRGR is as follows // +0 | +1 | +2 | +3 | diff --git a/iommu_ref_model/test/test_app.c b/iommu_ref_model/test/test_app.c index a1bc9a57..860e4876 100644 --- a/iommu_ref_model/test/test_app.c +++ b/iommu_ref_model/test/test_app.c @@ -112,6 +112,29 @@ main(void) { fail_if( ( check_rsp_and_faults(&req, &rsp, UNSUPPORTED_REQUEST, 256, 0) < 0 ) ); } }); + pr.MSGCODE = PAGE_REQ_MSG_CODE; + pr.TAG = 0; + pr.RID = 0x1234; + pr.PV = 1; + pr.PID = 0xbabec; + pr.PRIV = 1; + pr.EXEC_REQ = 0; + pr.DSV = 1; + pr.DSEG = 0x43; + pr.PAYLOAD = 0xdeadbeef00000007; // Set last, PRG index = 0 + exp_msg.MSGCODE = PRGR_MSG_CODE; + exp_msg.TAG = 0; + exp_msg.RID = 0x1234; + exp_msg.PV = 0; + exp_msg.PID = 0; + exp_msg.PRIV = 0; + exp_msg.EXEC_REQ = 0; + exp_msg.DSV = 1; + exp_msg.DSEG = 0x43; + exp_msg.PAYLOAD = (0x1234UL << 48UL) | (RESPONSE_FAILURE << 44UL); + handle_page_request(&pr); + fail_if( ( exp_msg_received == 0 ) ); + fail_if( ( check_msg_faults(256, pr.PV, pr.PID, pr.PRIV, 0x431234, PAGE_REQ_MSG_CODE) < 0 ) ); END_TEST(); START_TEST("Bare mode tests"); @@ -130,6 +153,29 @@ main(void) { fail_if( ( check_rsp_and_faults(&req, &rsp, SUCCESS, 0, 0) < 0 ) ); } }); + pr.MSGCODE = PAGE_REQ_MSG_CODE; + pr.TAG = 0; + pr.RID = 0x1234; + pr.PV = 0; + pr.PID = 0; + pr.PRIV = 0; + pr.EXEC_REQ = 0; + pr.DSV = 1; + pr.DSEG = 0x43; + pr.PAYLOAD = 0xdeadbeef00000007; // Set last, PRG index = 0 + exp_msg.MSGCODE = PRGR_MSG_CODE; + exp_msg.TAG = 0; + exp_msg.RID = 0x1234; + exp_msg.PV = 0; + exp_msg.PID = 0; + exp_msg.PRIV = 0; + exp_msg.EXEC_REQ = 0; + exp_msg.DSV = 1; + exp_msg.DSEG = 0x43; + exp_msg.PAYLOAD = (0x1234UL << 48UL) | (INVALID_REQUEST << 44UL); + handle_page_request(&pr); + fail_if( ( exp_msg_received == 0 ) ); + fail_if( ( check_msg_faults(260, pr.PV, pr.PID, pr.PRIV, 0x431234, PAGE_REQ_MSG_CODE) < 0 ) ); // Turn it off fail_if( ( enable_iommu(Off) < 0 ) ); END_TEST(); @@ -2847,8 +2893,8 @@ main(void) { exp_msg.MSGCODE = PRGR_MSG_CODE; exp_msg.TAG = 0; exp_msg.RID = 0x1234; - exp_msg.PV = 1; - exp_msg.PID = 0xbabec; + exp_msg.PV = 0; + exp_msg.PID = 0; exp_msg.PRIV = 0; exp_msg.EXEC_REQ = 0; exp_msg.DSV = 1; @@ -2895,6 +2941,7 @@ main(void) { fail_if( ( enable_disable_pq(4, 0) < 0 ) ); DC.tc.EN_ATS = 1; DC.tc.EN_PRI = 1; + DC.tc.PRPR = 1; write_memory((char *)&DC, DC_addr, 64); iodir(INVAL_DDT, 1, 0x112233, 0); exp_msg.RID = 0x2233; @@ -2927,6 +2974,7 @@ main(void) { pr.DSEG = 0x11; DC.tc.EN_ATS = 1; DC.tc.EN_PRI = 1; + DC.tc.PRPR = 0; write_memory((char *)&DC, DC_addr, 64); iodir(INVAL_DDT, 1, 0x112233, 0); message_received = 0;