>>>> @@ -64,6 +65,13 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s,
>>> VTDHostIOMMUDevice *vtd_hiod,
>>>>            return false;
>>>>        }
>>>>
>>>> +    /* Only do the check when host device support PASIDs */
>>>> +    if (caps->max_pasid_log2 && s->pasid > hpasid) {
>>>
>>> the second comparison looks strange. hpasid is derived from ecap_reg,
>>> while ecap_reg is from s->pasid... is there any place that changes
>>> the pss filed of ecap_reg afterward? I think this check should be
>>> against caps->max_pasid_log2 as this is the value from hardware. right?
>>
>> ecap_reg is from ioctl(IOMMU_GET_HW_INFO), it's not ecap register in
>vIOMMU.
>
>I see. I misunderstood that the hpasid is got from the vIOMMU ecap
>register.
>
>> My understanding is that guest kernel will pick the 
>> min(caps->max_pasid_log2, s-
>>pasid), so checking the two doesn't make sense?
>
>I think the caps->max_pasid_log2 should be the same with hpasid since
>both are from host. Also, I didn't see the logic to pick the
>min(caps->max_pasid_log2, s->pasid). This is not expected just like the
>aw bits.
>We fail if aw-bits > host aw-bits.

It's a bit different, see below:

static u32 dev_iommu_get_max_pasids(struct device *dev)
{
        u32 max_pasids = 0, bits = 0;
        int ret;

        if (dev_is_pci(dev)) {
                ret = pci_max_pasids(to_pci_dev(dev));
                if (ret > 0)
                        max_pasids = ret;
        } else {
                ret = device_property_read_u32(dev, "pasid-num-bits", &bits);
                if (!ret)
                        max_pasids = 1UL << bits;
        }

        return min_t(u32, max_pasids, dev->iommu->iommu_dev->max_pasids);
}

dev->iommu->max_pasids = dev_iommu_get_max_pasids(dev);

caps->max_pasid_log2 = ilog2(idev->dev->iommu->max_pasids);

caps->max_pasid_log2 is then exposed to guest as pasid bit value in virtual PCI 
capability.
Then guest kernel does the same min() calculation.

Zhenzhong

Reply via email to