Hello Alex Williamson,

The patch edad96db58d2: "iommu/vt-d: Fix unmap_pages support" from
Nov 22, 2021, leads to the following Smatch static checker warning:

        drivers/iommu/intel/iommu.c:1369 dma_pte_clear_level()
        error: uninitialized symbol 'level_pfn'.

drivers/iommu/intel/iommu.c
    1330 static struct page *dma_pte_clear_level(struct dmar_domain *domain, 
int level,
    1331                                         struct dma_pte *pte, unsigned 
long pfn,
    1332                                         unsigned long start_pfn,
    1333                                         unsigned long last_pfn,
    1334                                         struct page *freelist)
    1335 {
    1336         struct dma_pte *first_pte = NULL, *last_pte = NULL;
    1337 
    1338         pfn = max(start_pfn, pfn);
    1339         pte = &pte[pfn_level_offset(pfn, level)];
    1340 
    1341         do {
    1342                 unsigned long level_pfn;
    1343 
    1344                 if (!dma_pte_present(pte))
    1345                         goto next;
                                 ^^^^^^^^^^

If we ever hit this goto then there is going to be a bug.

    1346 
    1347                 level_pfn = pfn & level_mask(level);
    1348 
    1349                 /* If range covers entire pagetable, free it */
    1350                 if (start_pfn <= level_pfn &&
    1351                     last_pfn >= level_pfn + level_size(level) - 1) {
    1352                         /* These suborbinate page tables are going 
away entirely. Don't
    1353                            bother to clear them; we're just going to 
*free* them. */
    1354                         if (level > 1 && !dma_pte_superpage(pte))
    1355                                 freelist = 
dma_pte_list_pagetables(domain, level - 1, pte, freelist);
    1356 
    1357                         dma_clear_pte(pte);
    1358                         if (!first_pte)
    1359                                 first_pte = pte;
    1360                         last_pte = pte;
    1361                 } else if (level > 1) {
    1362                         /* Recurse down into a level that isn't 
*entirely* obsolete */
    1363                         freelist = dma_pte_clear_level(domain, level - 
1,
    1364                                                        
phys_to_virt(dma_pte_addr(pte)),
    1365                                                        level_pfn, 
start_pfn, last_pfn,
    1366                                                        freelist);
    1367                 }
    1368 next:
--> 1369                 pfn = level_pfn + level_size(level);
                               ^^^^^^^^^

    1370         } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
    1371 
    1372         if (first_pte)
    1373                 domain_flush_cache(domain, first_pte,
    1374                                    (void *)++last_pte - (void 
*)first_pte);
    1375 
    1376         return freelist;
    1377 }

regards,
dan carpenter
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to