>-----Original Message-----
>From: Eric Auger <[email protected]>
>Subject: Re: [PATCH v3 10/20] intel_iommu: Handle PASID entry removing and
>updating
...
>> +static bool vtd_pasid_entry_compare(VTDPASIDEntry *p1, VTDPASIDEntry
>*p2)
>> +{
>> + return !memcmp(p1, p2, sizeof(*p1));
>> +}
>> +
>> +/*
>> + * This function is used to update or clear cached pasid entry in vtd_as.
>> + * vtd_as is released when corresponding cached pasid entry is cleared,
>> + * except for PCI_NO_PASID which vtd_as is owen by PCI sub-system.
>I would document when it is supposed to return true (indicates that the
>cached pasid entry needs to be removed).
Will do.
>> + */
>> +static gboolean vtd_flush_pasid_locked(gpointer key, gpointer value,
>> + gpointer user_data)
>> +{
>> + VTDPASIDCacheInfo *pc_info = user_data;
>> + VTDAddressSpace *vtd_as = value;
>> + VTDPASIDCacheEntry *pc_entry = &vtd_as->pasid_cache_entry;
>> + VTDPASIDEntry pe;
>> + uint16_t did;
>> + uint32_t pasid;
>> + int ret;
>> +
>> + if (!pc_entry->valid) {
>> + return false;
>> + }
>> + did = VTD_SM_PASID_ENTRY_DID(&pc_entry->pasid_entry);
>> +
>> + if (vtd_as_to_iommu_pasid_locked(vtd_as, &pasid)) {
>> + goto remove;
>> + }
>> +
>> + switch (pc_info->type) {
>> + case VTD_PASID_CACHE_PASIDSI:
>> + if (pc_info->pasid != pasid) {
>> + return false;
>> + }
>> + /* fall through */
>> + case VTD_PASID_CACHE_DOMSI:
>> + if (pc_info->did != did) {
>> + return false;
>> + }
>> + /* fall through */
>> + case VTD_PASID_CACHE_GLOBAL_INV:
>> + break;
>> + default:
>> + error_setg(&error_fatal, "invalid pc_info->type for flush");
>> + }
>> +
>> + /*
>> + * pasid cache invalidation may indicate a present pasid
>> + * entry to present pasid entry modification. To cover such
>> + * case, vIOMMU emulator needs to fetch latest guest pasid
>> + * entry and compares with cached pasid entry, then update
>> + * pasid cache.
>> + */
>> + ret = vtd_dev_get_pe_from_pasid(vtd_as, pasid, &pe);
>> + if (ret) {
>> + /*
>> + * No valid pasid entry in guest memory. e.g. pasid entry
>> + * was modified to be either all-zero or non-present. Either
>> + * case means existing pasid cache should be removed.
>> + */
>> + goto remove;
>> + }
>> +
>> + /* No need to update if cached pasid entry is latest */
>that comment sounds really weird to me. In case the cache entry does not
>match the one in guest mem, you update it below - at least that's what I
>understand ;-) - However you want to return false because you don't want
>g_hash_table_foreach_remove() to remove the entry.
You understand totally right😊, will rephase to:
/* Update cached pasid entry if it's stale compared to what's in guest memory */
>> + if (!vtd_pasid_entry_compare(&pe, &pc_entry->pasid_entry)) {
>> + pc_entry->pasid_entry = pe;
>> + }
>> + return false;
>> +
>> +remove:
>> + pc_entry->valid = false;
>> +
>> + /*
>> + * Don't remove address space of PCI_NO_PASID which is created for
>PCI
>> + * sub-system.
>> + */
>> + if (vtd_as->pasid == PCI_NO_PASID) {
>> + return false;
>> + }
>> + return true;
>> +}
>> +
>> +/* Update the pasid cache in vIOMMU */
>> +static void vtd_pasid_cache_sync(IntelIOMMUState *s,
>VTDPASIDCacheInfo *pc_info)
>> +{
>> + if (!s->flts || !s->root_scalable || !s->dmar_enabled) {
>> + return;
>> + }
>> +
>> + /*
>> + * Regards to a pasid cache invalidation, e.g. a PSI.
>Regarded PASID cache invalidation?
>> + * It could be either cases of below:
>> + * a) a present pasid entry moved to non-present
>a present cache pasid entry needs to be removed
>> + * b) a present pasid entry to be a present entry
>above sounds a bit weird. A present cached pasid entry needs to be updated
>> + * c) a non-present pasid entry moved to present
>a present cached pasid entry needs to be created. As this is not handled
>in this patch I would move this to next one.
>Besides since there is another comment below I am not even sure this is
>requested or at least I would put this in a doc comment for the function
>and not within the code.
Will do.
>> --- a/hw/i386/intel_iommu_internal.h
>> +++ b/hw/i386/intel_iommu_internal.h
>> @@ -315,6 +315,7 @@ typedef enum VTDFaultReason {
>> * request while disabled */
>> VTD_FR_IR_SID_ERR = 0x26, /* Invalid Source-ID */
>>
>> + VTD_FR_RTADDR_INV_TTM = 0x31, /* Invalid TTM in RTADDR */
>> /* PASID directory entry access failure */
>> VTD_FR_PASID_DIR_ACCESS_ERR = 0x50,
>> /* The Present(P) field of pasid directory entry is 0 */
>> @@ -492,6 +493,15 @@ typedef union VTDInvDesc VTDInvDesc;
>> #define VTD_INV_DESC_PIOTLB_RSVD_VAL0
>0xfff000000000f1c0ULL
>> #define VTD_INV_DESC_PIOTLB_RSVD_VAL1 0xf80ULL
>>
>> +/* PASID-cache Invalidate Descriptor (pc_inv_dsc) fields */
>> +#define VTD_INV_DESC_PASIDC_G(x) extract64((x)->val[0], 4, 2)
>> +#define VTD_INV_DESC_PASIDC_G_DSI 0
>> +#define VTD_INV_DESC_PASIDC_G_PASID_SI 1
>> +#define VTD_INV_DESC_PASIDC_G_GLOBAL 3
>> +#define VTD_INV_DESC_PASIDC_DID(x) extract64((x)->val[0], 16,
>16)
>> +#define VTD_INV_DESC_PASIDC_PASID(x) extract64((x)->val[0], 32,
>20)
>thanks for converting to extract64 ;-)
>> +#define VTD_INV_DESC_PASIDC_RSVD_VAL0 0xfff000000000f1c0ULL
>nit: I find such mask definition error prone and difficult to review.
>combined MAKE_64BIT_MASK() would make it clearer I think
Yes, so we need to be careful to ensure its correctness when coding.
But I think a single 0xfff000000000f1c0ULL is cleaner than many
MAKE_64BIT_MASK() combined.
Thanks
Zhenzhong