intel_iommu: Add support for PASID-based device IOTLB invalidation

Signed-off-by: Clément Mathieu--Drif <clement.mathieu--drif@eviden.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Message-Id: <20241212083757.605022-14-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:
Clément Mathieu--Drif 2024-12-12 16:37:50 +08:00 committed by Michael S. Tsirkin
parent 1075645d43
commit dd8200503e
2 changed files with 61 additions and 0 deletions

View file

@ -3075,6 +3075,49 @@ static void do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as,
memory_region_notify_iommu(&vtd_dev_as->iommu, 0, event);
}
static bool vtd_process_device_piotlb_desc(IntelIOMMUState *s,
VTDInvDesc *inv_desc)
{
uint16_t sid;
VTDAddressSpace *vtd_dev_as;
bool size;
bool global;
hwaddr addr;
uint32_t pasid;
uint64_t mask[4] = {VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_VAL0,
VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_VAL1,
VTD_INV_DESC_ALL_ONE, VTD_INV_DESC_ALL_ONE};
if (!vtd_inv_desc_reserved_check(s, inv_desc, mask, true,
__func__, "device piotlb inv")) {
return false;
}
global = VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(inv_desc->hi);
size = VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(inv_desc->hi);
addr = VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(inv_desc->hi);
sid = VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(inv_desc->lo);
if (global) {
QLIST_FOREACH(vtd_dev_as, &s->vtd_as_with_notifiers, next) {
if ((vtd_dev_as->pasid != PCI_NO_PASID) &&
(PCI_BUILD_BDF(pci_bus_num(vtd_dev_as->bus),
vtd_dev_as->devfn) == sid)) {
do_invalidate_device_tlb(vtd_dev_as, size, addr);
}
}
} else {
pasid = VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(inv_desc->lo);
vtd_dev_as = vtd_get_as_by_sid_and_pasid(s, sid, pasid);
if (!vtd_dev_as) {
return true;
}
do_invalidate_device_tlb(vtd_dev_as, size, addr);
}
return true;
}
static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s,
VTDInvDesc *inv_desc)
{
@ -3161,6 +3204,13 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
}
break;
case VTD_INV_DESC_DEV_PIOTLB:
trace_vtd_inv_desc("device-piotlb", inv_desc.hi, inv_desc.lo);
if (!vtd_process_device_piotlb_desc(s, &inv_desc)) {
return false;
}
break;
case VTD_INV_DESC_DEVICE:
trace_vtd_inv_desc("device", inv_desc.hi, inv_desc.lo);
if (!vtd_process_device_iotlb_desc(s, &inv_desc)) {

View file

@ -385,6 +385,7 @@ typedef union VTDInvDesc VTDInvDesc;
#define VTD_INV_DESC_WAIT 0x5 /* Invalidation Wait Descriptor */
#define VTD_INV_DESC_PIOTLB 0x6 /* PASID-IOTLB Invalidate Desc */
#define VTD_INV_DESC_PC 0x7 /* PASID-cache Invalidate Desc */
#define VTD_INV_DESC_DEV_PIOTLB 0x8 /* PASID-based-DIOTLB inv_desc*/
#define VTD_INV_DESC_NONE 0 /* Not an Invalidate Descriptor */
/* Masks for Invalidation Wait Descriptor*/
@ -426,6 +427,16 @@ typedef union VTDInvDesc VTDInvDesc;
/* Masks for Interrupt Entry Invalidate Descriptor */
#define VTD_INV_DESC_IEC_RSVD 0xffff000007fff1e0ULL
/* Masks for PASID based Device IOTLB Invalidate Descriptor */
#define VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(val) ((val) & \
0xfffffffffffff000ULL)
#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(val) ((val >> 11) & 0x1)
#define VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(val) ((val) & 0x1)
#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(val) (((val) >> 16) & 0xffffULL)
#define VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(val) ((val >> 32) & 0xfffffULL)
#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_VAL0 0xfff000000000f000ULL
#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_VAL1 0x7feULL
/* Rsvd field masks for spte */
#define VTD_SPTE_SNP 0x800ULL