qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PULL 11/26] vfio/spapr: Allow backing bigger guest IOMMU pages with


From: Alexey Kardashevskiy
Subject: Re: [PULL 11/26] vfio/spapr: Allow backing bigger guest IOMMU pages with smaller physical pages
Date: Tue, 24 Mar 2020 15:08:22 +1100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0


On 23/03/2020 21:55, Peter Maydell wrote:
> On Tue, 21 Aug 2018 at 05:33, David Gibson <address@hidden> wrote:
>>
>> From: Alexey Kardashevskiy <address@hidden>
>>
>> At the moment the PPC64/pseries guest only supports 4K/64K/16M IOMMU
>> pages and POWER8 CPU supports the exact same set of page size so
>> so far things worked fine.
>>
>> However POWER9 supports different set of sizes - 4K/64K/2M/1G and
>> the last two - 2M and 1G - are not even allowed in the paravirt interface
>> (RTAS DDW) so we always end up using 64K IOMMU pages, although we could
>> back guest's 16MB IOMMU pages with 2MB pages on the host.
>>
>> This stores the supported host IOMMU page sizes in VFIOContainer and uses
>> this later when creating a new DMA window. This uses the system page size
>> (64k normally, 2M/16M/1G if hugepages used) as the upper limit of
>> the IOMMU pagesize.
>>
>> This changes the type of @pagesize to uint64_t as this is what
>> memory_region_iommu_get_min_page_size() returns and clz64() takes.
>>
>> There should be no behavioral changes on platforms other than pseries.
>> The guest will keep using the IOMMU page size selected by the PHB pagesize
>> property as this only changes the underlying hardware TCE table
>> granularity.
> 
> Hi; Coverity has raised an issue (CID 1421903) on this code and
> I'm not sure if it's correct or not.
> 
> 
>> @@ -144,9 +145,27 @@ int vfio_spapr_create_window(VFIOContainer *container,
>>  {
>>      int ret;
>>      IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
>> -    unsigned pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
>> +    uint64_t pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
>>      unsigned entries, pages;
>>      struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };
>> +    long systempagesize = qemu_getrampagesize();
>> +
>> +    /*
>> +     * The host might not support the guest supported IOMMU page size,
>> +     * so we will use smaller physical IOMMU pages to back them.
>> +     */
>> +    if (pagesize > systempagesize) {
>> +        pagesize = systempagesize;
>> +    }

pagesize cannot be zero here (I checked possible code paths)...



>> +    pagesize = 1ULL << (63 - clz64(container->pgsizes &
>> +                                   (pagesize | (pagesize - 1))));
>> If the argument to clz64() is zero then it will return 64, and
> then we will try to do a shift by -1, which is undefined
> behaviour.

... but the clz64() argument can if lets say container->pgsizes=1<<30
(comes from VFIO) and pagesize=1<<16 (decided by QEMU or guest).


I'll sent a patch to handle clz64()=>64. Thanks,


> Can the expression ever be zero? It's not immediately obvious to me
> that it can't be, so my suggestion would be that if it is
> impossible then an assert() of that would be helpful, and if it
> is possible then the code needs to avoid the illegal shift.

>> +    if (!pagesize) {
>> +        error_report("Host doesn't support page size 0x%"PRIx64
>> +                     ", the supported mask is 0x%lx",
>> +                     memory_region_iommu_get_min_page_size(iommu_mr),
>> +                     container->pgsizes);
>> +        return -EINVAL;
>> +    }
> 
> thanks
> -- PMM
> 

-- 
Alexey



reply via email to

[Prev in Thread] Current Thread [Next in Thread]