[PATCH v1 1/2] powerpc/mmiotrace: Add MMIO Tracing tool for PowerPC
kernel test robot
lkp at intel.com
Thu Jun 27 22:31:17 AEST 2024
Hi Jialong,
kernel test robot noticed the following build errors:
[auto build test ERROR on powerpc/next]
[also build test ERROR on powerpc/fixes linus/master v6.10-rc5 next-20240626]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Jialong-Yang/powerpc-mmiotrace-bind-ioremap-and-page-fault-to-active-mmiotrace/20240624-163027
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
patch link: https://lore.kernel.org/r/2bf90acf7d29641ba6643934ff8dbba897dbd2d9.1718873074.git.jialong.yang%40shingroup.cn
patch subject: [PATCH v1 1/2] powerpc/mmiotrace: Add MMIO Tracing tool for PowerPC
config: powerpc-randconfig-r113-20240627 (https://download.01.org/0day-ci/archive/20240627/202406271946.A6jwFfaY-lkp@intel.com/config)
compiler: powerpc-linux-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20240627/202406271946.A6jwFfaY-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202406271946.A6jwFfaY-lkp@intel.com/
All error/warnings (new ones prefixed by >>):
arch/powerpc/mm/kmmio.c: In function 'pmd_mkinvalid':
>> arch/powerpc/mm/kmmio.c:140:16: error: implicit declaration of function '__pmd_raw' [-Werror=implicit-function-declaration]
140 | return __pmd_raw(pmd_raw(pmd) & ~cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID));
| ^~~~~~~~~
>> arch/powerpc/mm/kmmio.c:140:26: error: implicit declaration of function 'pmd_raw'; did you mean 'pmd_bad'? [-Werror=implicit-function-declaration]
140 | return __pmd_raw(pmd_raw(pmd) & ~cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID));
| ^~~~~~~
| pmd_bad
In file included from include/linux/byteorder/big_endian.h:5,
from arch/powerpc/include/uapi/asm/byteorder.h:14,
from include/asm-generic/bitops/le.h:6,
from arch/powerpc/include/asm/bitops.h:325,
from include/linux/bitops.h:63,
from include/linux/thread_info.h:27,
from arch/powerpc/include/asm/ptrace.h:342,
from arch/powerpc/include/asm/hw_irq.h:12,
from arch/powerpc/include/asm/irqflags.h:12,
from include/linux/irqflags.h:18,
from include/asm-generic/cmpxchg-local.h:6,
from arch/powerpc/include/asm/cmpxchg.h:755,
from arch/powerpc/include/asm/atomic.h:11,
from include/linux/atomic.h:7,
from include/linux/rcupdate.h:25,
from include/linux/rculist.h:11,
from arch/powerpc/mm/kmmio.c:10:
>> arch/powerpc/mm/kmmio.c:140:70: error: '_PAGE_INVALID' undeclared (first use in this function); did you mean 'RPM_INVALID'?
140 | return __pmd_raw(pmd_raw(pmd) & ~cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID));
| ^~~~~~~~~~~~~
include/uapi/linux/byteorder/big_endian.h:38:51: note: in definition of macro '__cpu_to_be64'
38 | #define __cpu_to_be64(x) ((__force __be64)(__u64)(x))
| ^
arch/powerpc/mm/kmmio.c:140:42: note: in expansion of macro 'cpu_to_be64'
140 | return __pmd_raw(pmd_raw(pmd) & ~cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID));
| ^~~~~~~~~~~
arch/powerpc/mm/kmmio.c:140:70: note: each undeclared identifier is reported only once for each function it appears in
140 | return __pmd_raw(pmd_raw(pmd) & ~cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID));
| ^~~~~~~~~~~~~
include/uapi/linux/byteorder/big_endian.h:38:51: note: in definition of macro '__cpu_to_be64'
38 | #define __cpu_to_be64(x) ((__force __be64)(__u64)(x))
| ^
arch/powerpc/mm/kmmio.c:140:42: note: in expansion of macro 'cpu_to_be64'
140 | return __pmd_raw(pmd_raw(pmd) & ~cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID));
| ^~~~~~~~~~~
arch/powerpc/mm/kmmio.c: In function 'kmmio_handler':
>> arch/powerpc/mm/kmmio.c:318:32: error: 'struct pt_regs' has no member named 'softe'
318 | ctx->saved_softe = regs->softe;
| ^~
arch/powerpc/mm/kmmio.c:330:13: error: 'struct pt_regs' has no member named 'softe'
330 | regs->softe = IRQS_DISABLED; // soft interrupt
| ^~
>> arch/powerpc/mm/kmmio.c:332:9: error: 'local_paca' undeclared (first use in this function); did you mean 'local_lock'?
332 | local_paca->srr_valid = 0;
| ^~~~~~~~~~
| local_lock
arch/powerpc/mm/kmmio.c: In function 'post_kmmio_handler':
arch/powerpc/mm/kmmio.c:383:13: error: 'struct pt_regs' has no member named 'softe'
383 | regs->softe = ctx->saved_softe;
| ^~
arch/powerpc/mm/kmmio.c: In function 'pmd_mkinvalid':
>> arch/powerpc/mm/kmmio.c:141:1: warning: control reaches end of non-void function [-Wreturn-type]
141 | }
| ^
cc1: some warnings being treated as errors
vim +/__pmd_raw +140 arch/powerpc/mm/kmmio.c
137
138 static inline pmd_t pmd_mkinvalid(pmd_t pmd)
139 {
> 140 return __pmd_raw(pmd_raw(pmd) & ~cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID));
> 141 }
142
143 static void clear_pmd_presence(pmd_t *pmd, bool clear, pmdval_t *old)
144 {
145 pmd_t new_pmd;
146 pmdval_t v = pmd_val(*pmd);
147
148 if (clear) {
149 *old = v;
150 new_pmd = pmd_mkinvalid(*pmd);
151 } else {
152 /* Presume this has been called with clear==true previously */
153 new_pmd = __pmd(*old);
154 }
155 *pmd = new_pmd;
156 }
157
158 static void clear_pte_presence(pte_t *pte, bool clear, pteval_t *old, unsigned long addr)
159 {
160 pteval_t v = pte_val(*pte);
161
162 if (clear) {
163 *old = v;
164 /* Nothing should care about address */
165 pte_clear(&init_mm, addr, pte);
166 } else {
167 /* Presume this has been called with clear==true previously */
168 set_pte_at(&init_mm, addr, pte, __pte(*old));
169 }
170 }
171
172 static int clear_page_presence(struct kmmio_fault_page *f, bool clear)
173 {
174 unsigned int level;
175 pte_t *pte = lookup_address(f->addr, &level);
176
177 if (!pte) {
178 pr_err("no pte for addr 0x%08lx\n", f->addr);
179 return -1;
180 }
181
182 if (level == PMD_SHIFT)
183 clear_pmd_presence((pmd_t *)pte, clear, &f->old_presence);
184 else if (level == PAGE_SHIFT)
185 clear_pte_presence(pte, clear, &f->old_presence, f->addr);
186 else {
187 pr_err("unexpected page level 0x%x.\n", level);
188 return -1;
189 }
190
191 mmap_read_lock(&init_mm);
192 struct vm_area_struct *vma = find_vma(&init_mm, f->addr);
193
194 mmap_read_unlock(&init_mm);
195
196 flush_tlb_page(vma, f->addr);
197
198 return 0;
199 }
200
201 /*
202 * Mark the given page as not present. Access to it will trigger a fault.
203 *
204 * Struct kmmio_fault_page is protected by RCU and kmmio_lock, but the
205 * protection is ignored here. RCU read lock is assumed held, so the struct
206 * will not disappear unexpectedly. Furthermore, the caller must guarantee,
207 * that double arming the same virtual address (page) cannot occur.
208 *
209 * Double disarming on the other hand is allowed, and may occur when a fault
210 * and mmiotrace shutdown happen simultaneously.
211 */
212 static int arm_kmmio_fault_page(struct kmmio_fault_page *f)
213 {
214 int ret;
215
216 WARN_ONCE(f->armed, pr_fmt("kmmio page already armed.\n"));
217 if (f->armed) {
218 pr_warn("double-arm: addr 0x%08lx, ref %d, old %d\n",
219 f->addr, f->count, !!f->old_presence);
220 }
221 ret = clear_page_presence(f, true);
222 WARN_ONCE(ret < 0, pr_fmt("arming at 0x%08lx failed.\n"),
223 f->addr);
224 f->armed = true;
225 return ret;
226 }
227
228 /** Restore the given page to saved presence state. */
229 static void disarm_kmmio_fault_page(struct kmmio_fault_page *f)
230 {
231 int ret = clear_page_presence(f, false);
232
233 WARN_ONCE(ret < 0,
234 KERN_ERR "kmmio disarming at 0x%08lx failed.\n", f->addr);
235 f->armed = false;
236 }
237
238 /*
239 * This is being called from do_page_fault().
240 *
241 * We may be in an interrupt or a critical section. Also prefecthing may
242 * trigger a page fault. We may be in the middle of process switch.
243 * We cannot take any locks, because we could be executing especially
244 * within a kmmio critical section.
245 *
246 * Local interrupts are disabled, so preemption cannot happen.
247 * Do not enable interrupts, do not sleep, and watch out for other CPUs.
248 */
249 /*
250 * Interrupts are disabled on entry as trap3 is an interrupt gate
251 * and they remain disabled throughout this function.
252 */
253 int kmmio_handler(struct pt_regs *regs, unsigned long addr)
254 {
255 struct kmmio_context *ctx;
256 struct kmmio_fault_page *faultpage;
257 int ret = 0; /* default to fault not handled */
258 unsigned long page_base = addr;
259 unsigned int l;
260 pte_t *pte = lookup_address(addr, &l);
261
262 if (!pte)
263 return -EINVAL;
264 page_base &= page_level_mask(l);
265
266 /*
267 * Hold the RCU read lock over single stepping to avoid looking
268 * up the probe and kmmio_fault_page again. The rcu_read_lock_sched()
269 * also disables preemption and prevents process switch during
270 * the single stepping. We can only handle one active kmmio trace
271 * per cpu, so ensure that we finish it before something else
272 * gets to run.
273 */
274 rcu_read_lock_sched_notrace();
275
276 faultpage = get_kmmio_fault_page(page_base);
277 if (!faultpage) {
278 /*
279 * Either this page fault is not caused by kmmio, or
280 * another CPU just pulled the kmmio probe from under
281 * our feet. The latter case should not be possible.
282 */
283 goto no_kmmio;
284 }
285
286 ctx = this_cpu_ptr(&kmmio_ctx);
287 if (ctx->active) {
288 if (page_base == ctx->addr) {
289 /*
290 * A second fault on the same page means some other
291 * condition needs handling by do_page_fault(), the
292 * page really not being present is the most common.
293 */
294 pr_debug("secondary hit for 0x%08lx CPU %d.\n",
295 addr, smp_processor_id());
296
297 if (!faultpage->old_presence)
298 pr_info("unexpected secondary hit for address 0x%08lx on CPU %d.\n",
299 addr, smp_processor_id());
300 } else {
301 /*
302 * Prevent overwriting already in-flight context.
303 * This should not happen, let's hope disarming at
304 * least prevents a panic.
305 */
306 pr_emerg("recursive probe hit on CPU %d, for address 0x%08lx. Ignoring.\n",
307 smp_processor_id(), addr);
308 pr_emerg("previous hit was at 0x%08lx.\n", ctx->addr);
309 disarm_kmmio_fault_page(faultpage);
310 }
311 goto no_kmmio;
312 }
313 ctx->active++;
314
315 ctx->fpage = faultpage;
316 ctx->probe = get_kmmio_probe(page_base);
317 ctx->saved_flags = (regs->msr & (MSR_SE | MSR_EE));
> 318 ctx->saved_softe = regs->softe;
319 ctx->addr = page_base;
320
321 if (ctx->probe && ctx->probe->pre_handler)
322 ctx->probe->pre_handler(ctx->probe, regs, addr);
323
324 /*
325 * Enable single-stepping and disable interrupts for the faulting
326 * context. Local interrupts must not get enabled during stepping.
327 */
328 regs->msr |= MSR_SE; // single step
329 regs->msr &= ~MSR_EE; // hard interrupt
330 regs->softe = IRQS_DISABLED; // soft interrupt
331
> 332 local_paca->srr_valid = 0;
333
334 /* Now we set present bit in PTE and single step. */
335 disarm_kmmio_fault_page(ctx->fpage);
336
337 /*
338 * If another cpu accesses the same page while we are stepping,
339 * the access will not be caught. It will simply succeed and the
340 * only downside is we lose the event. If this becomes a problem,
341 * the user should drop to single cpu before tracing.
342 */
343
344 return 1; /* fault handled */
345
346 no_kmmio:
347 rcu_read_unlock_sched_notrace();
348 return ret;
349 }
350
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
More information about the Linuxppc-dev
mailing list