>>>> @@ -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