>-----Original Message-----
>From: Eric Auger <eric.au...@redhat.com>
>Subject: Re: [PATCH v5 11/21] intel_iommu: Handle PASID entry removal and
>update
snip...

>> +
>> +/*
>> + * This function is a loop function which return value determines if
>whose returned value determines whether current vtd_as iterator matches
>the pasid cache entry info passed in user_data and needs to be removed
>from the pasid cache.

Will do.

>> + * vtd_as including cached pasid entry is removed.
>> + *
>> + * For PCI_NO_PASID, when corresponding cached pasid entry is cleared,
>> + * it returns false so that vtd_as is reserved as it's owned by PCI
>> + * sub-system. For other pasid, it returns true so vtd_as is removed.
>> + */
>> +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;
>> +    }
>> +
>> +    /*
>> +     * 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;
>> +}
>> +
>> +/*
>> + * For a PASID cache invalidation, this function handles below scenarios:
>> + * a) a present cached pasid entry needs to be removed
>> + * b) a present cached pasid entry needs to be updated
>> + */
>> +static void vtd_pasid_cache_sync(IntelIOMMUState *s,
>VTDPASIDCacheInfo *pc_info)
>> +{
>> +    if (!s->flts || !s->root_scalable || !s->dmar_enabled) {
>> +        return;
>> +    }
>> +
>> +    vtd_iommu_lock(s);
>> +    /*
>> +     * a,b): loop all the existing vtd_as instances for pasid cache removal
>> +       or update.
>> +     */
>> +    g_hash_table_foreach_remove(s->vtd_address_spaces,
>vtd_flush_pasid_locked,
>> +                                pc_info);
>> +    vtd_iommu_unlock(s);
>> +}
>> +
>> +static bool vtd_process_pasid_desc(IntelIOMMUState *s,
>> +                                   VTDInvDesc *inv_desc)
>> +{
>> +    uint16_t did;
>> +    uint32_t pasid;
>> +    VTDPASIDCacheInfo pc_info;
>> +    uint64_t mask[4] = {VTD_INV_DESC_PASIDC_RSVD_VAL0,
>VTD_INV_DESC_ALL_ONE,
>> +                        VTD_INV_DESC_ALL_ONE,
>VTD_INV_DESC_ALL_ONE};
>> +
>> +    if (!vtd_inv_desc_reserved_check(s, inv_desc, mask, true,
>> +                                     __func__, "pasid cache inv"))
>{
>> +        return false;
>> +    }
>> +
>> +    did = VTD_INV_DESC_PASIDC_DID(inv_desc);
>> +    pasid = VTD_INV_DESC_PASIDC_PASID(inv_desc);
>> +
>> +    switch (VTD_INV_DESC_PASIDC_G(inv_desc)) {
>> +    case VTD_INV_DESC_PASIDC_G_DSI:
>> +        trace_vtd_pasid_cache_dsi(did);
>> +        pc_info.type = VTD_PASID_CACHE_DOMSI;
>> +        pc_info.did = did;
>> +        break;
>> +
>> +    case VTD_INV_DESC_PASIDC_G_PASID_SI:
>> +        /* PASID selective implies a DID selective */
>> +        trace_vtd_pasid_cache_psi(did, pasid);
>> +        pc_info.type = VTD_PASID_CACHE_PASIDSI;
>> +        pc_info.did = did;
>> +        pc_info.pasid = pasid;
>> +        break;
>> +
>> +    case VTD_INV_DESC_PASIDC_G_GLOBAL:
>> +        trace_vtd_pasid_cache_gsi();
>> +        pc_info.type = VTD_PASID_CACHE_GLOBAL_INV;
>> +        break;
>> +
>> +    default:
>> +        error_report_once("invalid granularity field in PASID-cache
>invalidate "
>> +                          "descriptor, hi: 0x%"PRIx64" lo: 0x%"
>PRIx64,
>> +                           inv_desc->val[1], inv_desc->val[0]);
>what's the point of printing the 2nd 64b? Looking at Figure 6-2 in the
>spec (6.5.2.2. PASID-cache invalidate descriptor) it does not seem to
>contain anything?

I think it's a tradition in intel_iommu.c to print hi and low for 128bit or 
val[3-0] for 256bit inv_desc, even though hi may be reserved.

>
>Besides I read in the spec:
>Domain-ID (DID): The DID field indicates the target domain-id. Hardware
>ignores bits 31:(16+N), where N is the domain-id width reported in the
>Capability Register.
>
>How do you make sure N is same on both pIOMMU and vIOMMU?

There is no relationship between pIOMMU's and vIOMMU's DID. host and guest 
kernel manage their DID separately.

Thanks
Zhenzhong

Reply via email to