Messages in this thread | | | Date | Fri, 17 Jul 2020 16:58:37 +0800 | From | kernel test robot <> | Subject | arch/powerpc/platforms/powernv/pci-ioda-tce.c:77:34: sparse: sparse: cast from restricted __be64 |
| |
tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master head: 07a56bb875afbe39dabbf6ba7b83783d166863db commit: 56090a3902c80c296e822d11acdb6a101b322c52 powerpc/powernv/ioda: Fix race in TCE level allocation date: 11 months ago config: powerpc64-randconfig-s031-20200717 (attached as .config) compiler: powerpc64-linux-gcc (GCC) 9.3.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # apt-get install sparse # sparse version: v0.6.2-49-g707c5017-dirty git checkout 56090a3902c80c296e822d11acdb6a101b322c52 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=powerpc64
If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
arch/powerpc/platforms/powernv/pci-ioda-tce.c:196:45: sparse: sparse: cast to restricted __be64 >> arch/powerpc/platforms/powernv/pci-ioda-tce.c:77:34: sparse: sparse: cast from restricted __be64 >> arch/powerpc/platforms/powernv/pci-ioda-tce.c:77:34: sparse: sparse: cast from restricted __be64 arch/powerpc/platforms/powernv/pci-ioda-tce.c:77:34: sparse: sparse: cast to restricted __be64
vim +77 arch/powerpc/platforms/powernv/pci-ioda-tce.c
50 51 static void pnv_pci_ioda2_table_do_free_pages(__be64 *addr, 52 unsigned long size, unsigned int levels); 53 54 static __be64 *pnv_tce(struct iommu_table *tbl, bool user, long idx, bool alloc) 55 { 56 __be64 *tmp = user ? tbl->it_userspace : (__be64 *) tbl->it_base; 57 int level = tbl->it_indirect_levels; 58 const long shift = ilog2(tbl->it_level_size); 59 unsigned long mask = (tbl->it_level_size - 1) << (level * shift); 60 61 while (level) { 62 int n = (idx & mask) >> (level * shift); 63 unsigned long oldtce, tce = be64_to_cpu(READ_ONCE(tmp[n])); 64 65 if (!tce) { 66 __be64 *tmp2; 67 68 if (!alloc) 69 return NULL; 70 71 tmp2 = pnv_alloc_tce_level(tbl->it_nid, 72 ilog2(tbl->it_level_size) + 3); 73 if (!tmp2) 74 return NULL; 75 76 tce = __pa(tmp2) | TCE_PCI_READ | TCE_PCI_WRITE; > 77 oldtce = be64_to_cpu(cmpxchg(&tmp[n], 0, 78 cpu_to_be64(tce))); 79 if (oldtce) { 80 pnv_pci_ioda2_table_do_free_pages(tmp2, 81 ilog2(tbl->it_level_size) + 3, 1); 82 tce = oldtce; 83 } 84 } 85 86 tmp = __va(tce & ~(TCE_PCI_READ | TCE_PCI_WRITE)); 87 idx &= ~mask; 88 mask >>= shift; 89 --level; 90 } 91 92 return tmp + idx; 93 } 94 95 int pnv_tce_build(struct iommu_table *tbl, long index, long npages, 96 unsigned long uaddr, enum dma_data_direction direction, 97 unsigned long attrs) 98 { 99 u64 proto_tce = iommu_direction_to_tce_perm(direction); 100 u64 rpn = __pa(uaddr) >> tbl->it_page_shift; 101 long i; 102 103 if (proto_tce & TCE_PCI_WRITE) 104 proto_tce |= TCE_PCI_READ; 105 106 for (i = 0; i < npages; i++) { 107 unsigned long newtce = proto_tce | 108 ((rpn + i) << tbl->it_page_shift); 109 unsigned long idx = index - tbl->it_offset + i; 110 111 *(pnv_tce(tbl, false, idx, true)) = cpu_to_be64(newtce); 112 } 113 114 return 0; 115 } 116 117 #ifdef CONFIG_IOMMU_API 118 int pnv_tce_xchg(struct iommu_table *tbl, long index, 119 unsigned long *hpa, enum dma_data_direction *direction, 120 bool alloc) 121 { 122 u64 proto_tce = iommu_direction_to_tce_perm(*direction); 123 unsigned long newtce = *hpa | proto_tce, oldtce; 124 unsigned long idx = index - tbl->it_offset; 125 __be64 *ptce = NULL; 126 127 BUG_ON(*hpa & ~IOMMU_PAGE_MASK(tbl)); 128 129 if (*direction == DMA_NONE) { 130 ptce = pnv_tce(tbl, false, idx, false); 131 if (!ptce) { 132 *hpa = 0; 133 return 0; 134 } 135 } 136 137 if (!ptce) { 138 ptce = pnv_tce(tbl, false, idx, alloc); 139 if (!ptce) 140 return alloc ? H_HARDWARE : H_TOO_HARD; 141 } 142 143 if (newtce & TCE_PCI_WRITE) 144 newtce |= TCE_PCI_READ; 145 146 oldtce = be64_to_cpu(xchg(ptce, cpu_to_be64(newtce))); 147 *hpa = oldtce & ~(TCE_PCI_READ | TCE_PCI_WRITE); 148 *direction = iommu_tce_direction(oldtce); 149 150 return 0; 151 } 152 153 __be64 *pnv_tce_useraddrptr(struct iommu_table *tbl, long index, bool alloc) 154 { 155 if (WARN_ON_ONCE(!tbl->it_userspace)) 156 return NULL; 157 158 return pnv_tce(tbl, true, index - tbl->it_offset, alloc); 159 } 160 #endif 161 162 void pnv_tce_free(struct iommu_table *tbl, long index, long npages) 163 { 164 long i; 165 166 for (i = 0; i < npages; i++) { 167 unsigned long idx = index - tbl->it_offset + i; 168 __be64 *ptce = pnv_tce(tbl, false, idx, false); 169 170 if (ptce) 171 *ptce = cpu_to_be64(0); 172 } 173 } 174 175 unsigned long pnv_tce_get(struct iommu_table *tbl, long index) 176 { 177 __be64 *ptce = pnv_tce(tbl, false, index - tbl->it_offset, false); 178 179 if (!ptce) 180 return 0; 181 182 return be64_to_cpu(*ptce); 183 } 184 185 static void pnv_pci_ioda2_table_do_free_pages(__be64 *addr, 186 unsigned long size, unsigned int levels) 187 { 188 const unsigned long addr_ul = (unsigned long) addr & 189 ~(TCE_PCI_READ | TCE_PCI_WRITE); 190 191 if (levels) { 192 long i; 193 u64 *tmp = (u64 *) addr_ul; 194 195 for (i = 0; i < size; ++i) { > 196 unsigned long hpa = be64_to_cpu(tmp[i]); 197 198 if (!(hpa & (TCE_PCI_READ | TCE_PCI_WRITE))) 199 continue; 200 201 pnv_pci_ioda2_table_do_free_pages(__va(hpa), size, 202 levels - 1); 203 } 204 } 205 206 free_pages(addr_ul, get_order(size << 3)); 207 } 208
--- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org [unhandled content-type:application/gzip] | |