Reviewed-by: Clément Mathieu--Drif<clement.mathieu--d...@eviden.com>
On 18/07/2024 10:16, Zhenzhong Duan wrote: > Caution: External email. Do not open attachments or click links, unless this > email comes from a known sender and you know the content is safe. > > > PASID-based iotlb (piotlb) is used during walking Intel > VT-d stage-1 page table. > > This emulates the stage-1 page table iotlb invalidation requested > by a PASID-based IOTLB Invalidate Descriptor (P_IOTLB). > > Signed-off-by: Yi Liu <yi.l....@intel.com> > Signed-off-by: Zhenzhong Duan <zhenzhong.d...@intel.com> > --- > hw/i386/intel_iommu_internal.h | 3 +++ > hw/i386/intel_iommu.c | 45 ++++++++++++++++++++++++++++++++++ > 2 files changed, 48 insertions(+) > > diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h > index cf0f176e06..7dd8176e86 100644 > --- a/hw/i386/intel_iommu_internal.h > +++ b/hw/i386/intel_iommu_internal.h > @@ -470,6 +470,9 @@ typedef union VTDInvDesc VTDInvDesc; > #define VTD_INV_DESC_PIOTLB_PASID(val) (((val) >> 32) & 0xfffffULL) > #define VTD_INV_DESC_PIOTLB_DID(val) (((val) >> 16) & \ > VTD_DOMAIN_ID_MASK) > +#define VTD_INV_DESC_PIOTLB_ADDR(val) ((val) & ~0xfffULL) > +#define VTD_INV_DESC_PIOTLB_AM(val) ((val) & 0x3fULL) > +#define VTD_INV_DESC_PIOTLB_IH(val) (((val) >> 6) & 0x1) > > /* Information about page-selective IOTLB invalidate */ > struct VTDIOTLBPageInvInfo { > diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c > index 8d47e5ba78..8ebb6dbd7d 100644 > --- a/hw/i386/intel_iommu.c > +++ b/hw/i386/intel_iommu.c > @@ -322,6 +322,28 @@ static gboolean vtd_hash_remove_by_page(gpointer key, > gpointer value, > return (entry->gfn & info->mask) == gfn || entry->gfn == gfn_tlb; > } > > +static gboolean vtd_hash_remove_by_page_piotlb(gpointer key, gpointer value, > + gpointer user_data) > +{ > + VTDIOTLBEntry *entry = (VTDIOTLBEntry *)value; > + VTDIOTLBPageInvInfo *info = (VTDIOTLBPageInvInfo *)user_data; > + uint64_t gfn = (info->addr >> VTD_PAGE_SHIFT_4K) & info->mask; > + uint64_t gfn_tlb = (info->addr & entry->mask) >> VTD_PAGE_SHIFT_4K; > + > + /* > + * According to spec, PASID-based-IOTLB Invalidation in page granularity > + * doesn't invalidate IOTLB entries caching second-stage (PGTT=010b) > + * or pass-through (PGTT=100b) mappings. Nested isn't supported yet, > + * so only need to check first-stage (PGTT=001b) mappings. > + */ > + if (entry->pgtt != VTD_SM_PASID_ENTRY_FLT) { > + return false; > + } > + > + return entry->domain_id == info->domain_id && entry->pasid == > info->pasid && > + ((entry->gfn & info->mask) == gfn || entry->gfn == gfn_tlb); > +} > + > /* Reset all the gen of VTDAddressSpace to zero and set the gen of > * IntelIOMMUState to 1. Must be called with IOMMU lock held. > */ > @@ -2886,11 +2908,30 @@ static void > vtd_piotlb_pasid_invalidate(IntelIOMMUState *s, > } > } > > +static void vtd_piotlb_page_invalidate(IntelIOMMUState *s, uint16_t > domain_id, > + uint32_t pasid, hwaddr addr, uint8_t > am, > + bool ih) > +{ > + VTDIOTLBPageInvInfo info; > + > + info.domain_id = domain_id; > + info.pasid = pasid; > + info.addr = addr; > + info.mask = ~((1 << am) - 1); > + > + vtd_iommu_lock(s); > + g_hash_table_foreach_remove(s->iotlb, > + vtd_hash_remove_by_page_piotlb, &info); > + vtd_iommu_unlock(s); > +} > + > static bool vtd_process_piotlb_desc(IntelIOMMUState *s, > VTDInvDesc *inv_desc) > { > uint16_t domain_id; > uint32_t pasid; > + uint8_t am; > + hwaddr addr; > > if ((inv_desc->val[0] & VTD_INV_DESC_PIOTLB_RSVD_VAL0) || > (inv_desc->val[1] & VTD_INV_DESC_PIOTLB_RSVD_VAL1)) { > @@ -2907,6 +2948,10 @@ static bool vtd_process_piotlb_desc(IntelIOMMUState *s, > break; > > case VTD_INV_DESC_PIOTLB_PSI_IN_PASID: > + am = VTD_INV_DESC_PIOTLB_AM(inv_desc->val[1]); > + addr = (hwaddr) VTD_INV_DESC_PIOTLB_ADDR(inv_desc->val[1]); > + vtd_piotlb_page_invalidate(s, domain_id, pasid, addr, am, > + VTD_INV_DESC_PIOTLB_IH(inv_desc->val[1])); > break; > > default: > -- > 2.34.1 >