lkml.org 
[lkml]   [2020]   [Jul]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
Subjectarch/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]
\
 
 \ /
  Last update: 2020-07-17 11:26    [W:0.184 / U:1.084 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site