[PATCH v3 5/6] intel_iommu_accel: Accept PRQ response for passthrough device
Zhenzhong Duan <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
Propagate guest's PRQ response to host by writing to fault_fd. Create a new VTDPRQEntry to cache cookie for each fault group, this cookie is used to mark the fault group on host side. Signed-off-by: Zhenzhong Duan <[email protected]> Reviewed-by: Clement Mathieu--Drif <[email protected]> Tested-by: Xudong Hao <[email protected]> --- hw/i386/intel_iommu_accel.h | 12 +++++++ include/hw/i386/intel_iommu.h | 6 ++++ hw/i386/intel_iommu.c | 4 +++ hw/i386/intel_iommu_accel.c | 59 +++++++++++++++++++++++++++++++++++ hw/i386/trace-events | 1 + 5 files changed, 82 insertions(+) diff --git a/hw/i386/intel_iommu_accel.h b/hw/i386/intel_iommu_accel.h index e0319749a5..0cc22b2cbb 100644 --- a/hw/i386/intel_iommu_accel.h +++ b/hw/i386/intel_iommu_accel.h @@ -20,6 +20,7 @@ typedef struct VTDAccelPASIDCacheEntry { uint32_t fs_hwpt_id; uint32_t fault_id; int fault_fd; + QLIST_HEAD(, VTDPRQEntry) vtd_prq_list; QLIST_ENTRY(VTDAccelPASIDCacheEntry) next; } VTDAccelPASIDCacheEntry; @@ -31,6 +32,9 @@ void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id, uint64_t npages, bool ih); void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info); void vtd_accel_pasid_cache_reset(IntelIOMMUState *s); +bool vtd_accel_propagate_page_group_response(IntelIOMMUState *s, + uint16_t rid, uint32_t pasid, + IOMMUPRIResponse *response); void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops); #else static inline bool vtd_check_hiod_accel(IntelIOMMUState *s, @@ -69,6 +73,14 @@ static inline void vtd_accel_pasid_cache_reset(IntelIOMMUState *s) { } +static inline +bool vtd_accel_propagate_page_group_response(IntelIOMMUState *s, + uint16_t rid, uint32_t pasid, + IOMMUPRIResponse *response) +{ + return false; +} + static inline void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops) { } diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 1842ba5840..5d44eac0ed 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -100,6 +100,12 @@ typedef struct VTDPASIDCacheEntry { bool valid; } VTDPASIDCacheEntry; +typedef struct VTDPRQEntry { + uint32_t grpid; + uint32_t cookie; + QLIST_ENTRY(VTDPRQEntry) next; +} VTDPRQEntry; + struct VTDAddressSpace { PCIBus *bus; uint8_t devfn; diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index cc8c9205df..e34cbf2b10 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -3380,6 +3380,10 @@ static bool vtd_process_page_group_response_desc(IntelIOMMUState *s, response.response_code = IOMMU_PRI_RESP_FAILURE; } + if (vtd_accel_propagate_page_group_response(s, rid, pasid, &response)) { + return true; + } + if (vtd_dev_as->pri_notifier) { vtd_dev_as->pri_notifier->notify(vtd_dev_as->pri_notifier, &response); } diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c index 79bfe763fc..6ec03c1b05 100644 --- a/hw/i386/intel_iommu_accel.c +++ b/hw/i386/intel_iommu_accel.c @@ -78,6 +78,57 @@ VTDHostIOMMUDevice *vtd_find_hiod_iommufd(VTDAddressSpace *as) return NULL; } +static void vtd_prq_response_notify(VTDAccelPASIDCacheEntry *vtd_pce, + IOMMUPRIResponse *response) +{ + struct iommu_hwpt_page_response resp; + uint32_t id = vtd_pce->fault_id; + int fd = vtd_pce->fault_fd; + VTDPRQEntry *prqe, *tmp; + ssize_t bytes; + + QLIST_FOREACH_SAFE(prqe, &vtd_pce->vtd_prq_list, next, tmp) { + if (prqe->grpid != response->prgi) { + continue; + } + + resp.cookie = prqe->cookie; + resp.code = response->response_code; + bytes = write(fd, &resp, sizeof(resp)); + trace_vtd_prq_response_notify(id, fd, resp.cookie, resp.code, bytes); + if (bytes < 0) { + error_report_once("FAULTQ(id %u): write failed " + "[cookie 0x%x code 0x%x] (%m)", + id, resp.cookie, resp.code); + } + + QLIST_REMOVE(prqe, next); + g_free(prqe); + } +} + +bool vtd_accel_propagate_page_group_response(IntelIOMMUState *s, + uint16_t rid, uint32_t pasid, + IOMMUPRIResponse *response) +{ + VTDAddressSpace *vtd_as = vtd_get_as_by_sid(s, rid); + VTDAccelPASIDCacheEntry *vtd_pce; + VTDHostIOMMUDevice *vtd_hiod = vtd_find_hiod_iommufd(vtd_as); + + if (!vtd_hiod) { + return false; + } + + QLIST_FOREACH(vtd_pce, &vtd_hiod->pasid_cache_list, next) { + if (vtd_pce->pasid == pasid) { + vtd_prq_response_notify(vtd_pce, response); + return true; + } + } + + return false; +} + static void vtd_prq_report_fault(VTDAccelPASIDCacheEntry *vtd_pce, struct iommu_hwpt_pgfault *fault, int cnt) { @@ -96,6 +147,13 @@ static void vtd_prq_report_fault(VTDAccelPASIDCacheEntry *vtd_pce, fault->addr, last_page, fault->grpid, fault->perm & IOMMU_PGFAULT_PERM_READ, fault->perm & IOMMU_PGFAULT_PERM_WRITE); + if (last_page) { + VTDPRQEntry *prqe = g_malloc0(sizeof(*prqe)); + + prqe->grpid = fault->grpid; + prqe->cookie = fault->cookie; + QLIST_INSERT_HEAD(&vtd_pce->vtd_prq_list, prqe, next); + } } } @@ -425,6 +483,7 @@ static void vtd_accel_fill_pc(VTDHostIOMMUDevice *vtd_hiod, uint32_t pasid, vtd_pce->pasid = pasid; vtd_pce->pasid_entry = *pe; vtd_pce->fault_fd = -1; + QLIST_INIT(&vtd_pce->vtd_prq_list); QLIST_INSERT_HEAD(&vtd_hiod->pasid_cache_list, vtd_pce, next); if (!vtd_device_attach_iommufd(vtd_pce, &local_err)) { diff --git a/hw/i386/trace-events b/hw/i386/trace-events index dca726c9b8..d3e83292d7 100644 --- a/hw/i386/trace-events +++ b/hw/i386/trace-events @@ -78,6 +78,7 @@ vtd_device_attach_hwpt(uint32_t dev_id, uint32_t pasid, uint32_t hwpt_id, int re vtd_device_detach_hwpt(uint32_t dev_id, uint32_t pasid, int ret) "dev_id %d pasid %d ret: %d" vtd_device_reattach_def_hwpt(uint32_t dev_id, uint32_t pasid, uint32_t hwpt_id, int ret) "dev_id %d pasid %d hwpt_id %d, ret: %d" vtd_prq_read_fault(uint32_t fault_id, uint32_t fault_fd, ssize_t bytes) "fault_id %d fault_fd %d ret: %zd" +vtd_prq_response_notify(uint32_t fault_id, uint32_t fault_fd, uint32_t cookie, uint32_t code, ssize_t bytes) "fault_id %d fault_fd %d cookie %d code %d ret: %zd" # amd_iommu.c amdvi_evntlog_fail(uint64_t addr, uint32_t head) "error: fail to write at addr 0x%"PRIx64" + offset 0x%"PRIx32 -- 2.52.0