mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-31 14:23:53 -06:00
intel_iommu: Flush stage-2 cache in PASID-selective PASID-based iotlb invalidation
Per VT-d spec 4.1, 6.5.2.4, "Table 21. PASID-based-IOTLB Invalidation", PADID-selective PASID-based iotlb invalidation will flush stage-2 iotlb entries with matching domain id and pasid. With stage-1 translation introduced, guest could send PASID-selective PASID-based iotlb invalidation to flush either stage-1 or stage-2 entries. By this chance, remove old IOTLB related definitions which were unused. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> Reviewed-by: Clément Mathieu--Drif<clement.mathieu--drif@eviden.com> Acked-by: Jason Wang <jasowang@redhat.com> Message-Id: <20241212083757.605022-5-zhenzhong.duan@intel.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
791346f93d
commit
ad0a7f1e1e
2 changed files with 93 additions and 6 deletions
|
@ -2692,6 +2692,83 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
|
|||
return true;
|
||||
}
|
||||
|
||||
static gboolean vtd_hash_remove_by_pasid(gpointer key, gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
VTDIOTLBEntry *entry = (VTDIOTLBEntry *)value;
|
||||
VTDIOTLBPageInvInfo *info = (VTDIOTLBPageInvInfo *)user_data;
|
||||
|
||||
return ((entry->domain_id == info->domain_id) &&
|
||||
(entry->pasid == info->pasid));
|
||||
}
|
||||
|
||||
static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
|
||||
uint16_t domain_id, uint32_t pasid)
|
||||
{
|
||||
VTDIOTLBPageInvInfo info;
|
||||
VTDAddressSpace *vtd_as;
|
||||
VTDContextEntry ce;
|
||||
|
||||
info.domain_id = domain_id;
|
||||
info.pasid = pasid;
|
||||
|
||||
vtd_iommu_lock(s);
|
||||
g_hash_table_foreach_remove(s->iotlb, vtd_hash_remove_by_pasid,
|
||||
&info);
|
||||
vtd_iommu_unlock(s);
|
||||
|
||||
QLIST_FOREACH(vtd_as, &s->vtd_as_with_notifiers, next) {
|
||||
if (!vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus),
|
||||
vtd_as->devfn, &ce) &&
|
||||
domain_id == vtd_get_domain_id(s, &ce, vtd_as->pasid)) {
|
||||
uint32_t rid2pasid = VTD_CE_GET_RID2PASID(&ce);
|
||||
|
||||
if ((vtd_as->pasid != PCI_NO_PASID || pasid != rid2pasid) &&
|
||||
vtd_as->pasid != pasid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!s->flts) {
|
||||
vtd_address_space_sync(vtd_as);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool vtd_process_piotlb_desc(IntelIOMMUState *s,
|
||||
VTDInvDesc *inv_desc)
|
||||
{
|
||||
uint16_t domain_id;
|
||||
uint32_t pasid;
|
||||
uint64_t mask[4] = {VTD_INV_DESC_PIOTLB_RSVD_VAL0,
|
||||
VTD_INV_DESC_PIOTLB_RSVD_VAL1,
|
||||
VTD_INV_DESC_ALL_ONE, VTD_INV_DESC_ALL_ONE};
|
||||
|
||||
if (!vtd_inv_desc_reserved_check(s, inv_desc, mask, true,
|
||||
__func__, "piotlb inv")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
domain_id = VTD_INV_DESC_PIOTLB_DID(inv_desc->val[0]);
|
||||
pasid = VTD_INV_DESC_PIOTLB_PASID(inv_desc->val[0]);
|
||||
switch (inv_desc->val[0] & VTD_INV_DESC_PIOTLB_G) {
|
||||
case VTD_INV_DESC_PIOTLB_ALL_IN_PASID:
|
||||
vtd_piotlb_pasid_invalidate(s, domain_id, pasid);
|
||||
break;
|
||||
|
||||
case VTD_INV_DESC_PIOTLB_PSI_IN_PASID:
|
||||
break;
|
||||
|
||||
default:
|
||||
error_report_once("%s: invalid piotlb inv desc: hi=0x%"PRIx64
|
||||
", lo=0x%"PRIx64" (type mismatch: 0x%llx)",
|
||||
__func__, inv_desc->val[1], inv_desc->val[0],
|
||||
inv_desc->val[0] & VTD_INV_DESC_IOTLB_G);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool vtd_process_inv_iec_desc(IntelIOMMUState *s,
|
||||
VTDInvDesc *inv_desc)
|
||||
{
|
||||
|
@ -2810,6 +2887,13 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
|
|||
}
|
||||
break;
|
||||
|
||||
case VTD_INV_DESC_PIOTLB:
|
||||
trace_vtd_inv_desc("p-iotlb", inv_desc.val[1], inv_desc.val[0]);
|
||||
if (!vtd_process_piotlb_desc(s, &inv_desc)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case VTD_INV_DESC_WAIT:
|
||||
trace_vtd_inv_desc("wait", inv_desc.hi, inv_desc.lo);
|
||||
if (!vtd_process_wait_desc(s, &inv_desc)) {
|
||||
|
@ -2837,7 +2921,6 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
|
|||
* iommu driver) work, just return true is enough so far.
|
||||
*/
|
||||
case VTD_INV_DESC_PC:
|
||||
case VTD_INV_DESC_PIOTLB:
|
||||
if (s->scalable_mode) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -404,11 +404,6 @@ typedef union VTDInvDesc VTDInvDesc;
|
|||
#define VTD_INV_DESC_IOTLB_AM(val) ((val) & 0x3fULL)
|
||||
#define VTD_INV_DESC_IOTLB_RSVD_LO 0xffffffff0000f100ULL
|
||||
#define VTD_INV_DESC_IOTLB_RSVD_HI 0xf80ULL
|
||||
#define VTD_INV_DESC_IOTLB_PASID_PASID (2ULL << 4)
|
||||
#define VTD_INV_DESC_IOTLB_PASID_PAGE (3ULL << 4)
|
||||
#define VTD_INV_DESC_IOTLB_PASID(val) (((val) >> 32) & VTD_PASID_ID_MASK)
|
||||
#define VTD_INV_DESC_IOTLB_PASID_RSVD_LO 0xfff00000000001c0ULL
|
||||
#define VTD_INV_DESC_IOTLB_PASID_RSVD_HI 0xf80ULL
|
||||
|
||||
/* Mask for Device IOTLB Invalidate Descriptor */
|
||||
#define VTD_INV_DESC_DEVICE_IOTLB_ADDR(val) ((val) & 0xfffffffffffff000ULL)
|
||||
|
@ -443,6 +438,15 @@ typedef union VTDInvDesc VTDInvDesc;
|
|||
(0x3ffff800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM | VTD_SL_TM)) : \
|
||||
(0x3ffff800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM))
|
||||
|
||||
/* Masks for PIOTLB Invalidate Descriptor */
|
||||
#define VTD_INV_DESC_PIOTLB_G (3ULL << 4)
|
||||
#define VTD_INV_DESC_PIOTLB_ALL_IN_PASID (2ULL << 4)
|
||||
#define VTD_INV_DESC_PIOTLB_PSI_IN_PASID (3ULL << 4)
|
||||
#define VTD_INV_DESC_PIOTLB_DID(val) (((val) >> 16) & VTD_DOMAIN_ID_MASK)
|
||||
#define VTD_INV_DESC_PIOTLB_PASID(val) (((val) >> 32) & 0xfffffULL)
|
||||
#define VTD_INV_DESC_PIOTLB_RSVD_VAL0 0xfff000000000f1c0ULL
|
||||
#define VTD_INV_DESC_PIOTLB_RSVD_VAL1 0xf80ULL
|
||||
|
||||
/* Information about page-selective IOTLB invalidate */
|
||||
struct VTDIOTLBPageInvInfo {
|
||||
uint16_t domain_id;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue