Skip to content

Commit 2100319

Browse files
Sai Prakash Ranjanarndb
authored andcommitted
asm-generic/io: Add logging support for MMIO accessors
Add logging support for MMIO high level accessors such as read{b,w,l,q} and their relaxed versions to aid in debugging unexpected crashes/hangs caused by the corresponding MMIO operation. Signed-off-by: Sai Prakash Ranjan <[email protected]> Signed-off-by: Arnd Bergmann <[email protected]>
1 parent 451f2f1 commit 2100319

File tree

1 file changed

+87
-4
lines changed
  • include/asm-generic

1 file changed

+87
-4
lines changed

include/asm-generic/io.h

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <asm/page.h> /* I/O is all done through memory accesses */
1111
#include <linux/string.h> /* for memset() and memcpy() */
1212
#include <linux/types.h>
13+
#include <linux/instruction_pointer.h>
1314

1415
#ifdef CONFIG_GENERIC_IOMAP
1516
#include <asm-generic/iomap.h>
@@ -61,6 +62,44 @@
6162
#define __io_par(v) __io_ar(v)
6263
#endif
6364

65+
/*
66+
* "__DISABLE_TRACE_MMIO__" flag can be used to disable MMIO tracing for
67+
* specific kernel drivers in case of excessive/unwanted logging.
68+
*
69+
* Usage: Add a #define flag at the beginning of the driver file.
70+
* Ex: #define __DISABLE_TRACE_MMIO__
71+
* #include <...>
72+
* ...
73+
*/
74+
#if IS_ENABLED(CONFIG_TRACE_MMIO_ACCESS) && !(defined(__DISABLE_TRACE_MMIO__))
75+
#include <linux/tracepoint-defs.h>
76+
77+
DECLARE_TRACEPOINT(rwmmio_write);
78+
DECLARE_TRACEPOINT(rwmmio_post_write);
79+
DECLARE_TRACEPOINT(rwmmio_read);
80+
DECLARE_TRACEPOINT(rwmmio_post_read);
81+
82+
void log_write_mmio(u64 val, u8 width, volatile void __iomem *addr,
83+
unsigned long caller_addr);
84+
void log_post_write_mmio(u64 val, u8 width, volatile void __iomem *addr,
85+
unsigned long caller_addr);
86+
void log_read_mmio(u8 width, const volatile void __iomem *addr,
87+
unsigned long caller_addr);
88+
void log_post_read_mmio(u64 val, u8 width, const volatile void __iomem *addr,
89+
unsigned long caller_addr);
90+
91+
#else
92+
93+
static inline void log_write_mmio(u64 val, u8 width, volatile void __iomem *addr,
94+
unsigned long caller_addr) {}
95+
static inline void log_post_write_mmio(u64 val, u8 width, volatile void __iomem *addr,
96+
unsigned long caller_addr) {}
97+
static inline void log_read_mmio(u8 width, const volatile void __iomem *addr,
98+
unsigned long caller_addr) {}
99+
static inline void log_post_read_mmio(u64 val, u8 width, const volatile void __iomem *addr,
100+
unsigned long caller_addr) {}
101+
102+
#endif /* CONFIG_TRACE_MMIO_ACCESS */
64103

65104
/*
66105
* __raw_{read,write}{b,w,l,q}() access memory in native endianness.
@@ -149,9 +188,11 @@ static inline u8 readb(const volatile void __iomem *addr)
149188
{
150189
u8 val;
151190

191+
log_read_mmio(8, addr, _THIS_IP_);
152192
__io_br();
153193
val = __raw_readb(addr);
154194
__io_ar(val);
195+
log_post_read_mmio(val, 8, addr, _THIS_IP_);
155196
return val;
156197
}
157198
#endif
@@ -162,9 +203,11 @@ static inline u16 readw(const volatile void __iomem *addr)
162203
{
163204
u16 val;
164205

206+
log_read_mmio(16, addr, _THIS_IP_);
165207
__io_br();
166208
val = __le16_to_cpu((__le16 __force)__raw_readw(addr));
167209
__io_ar(val);
210+
log_post_read_mmio(val, 16, addr, _THIS_IP_);
168211
return val;
169212
}
170213
#endif
@@ -175,9 +218,11 @@ static inline u32 readl(const volatile void __iomem *addr)
175218
{
176219
u32 val;
177220

221+
log_read_mmio(32, addr, _THIS_IP_);
178222
__io_br();
179223
val = __le32_to_cpu((__le32 __force)__raw_readl(addr));
180224
__io_ar(val);
225+
log_post_read_mmio(val, 32, addr, _THIS_IP_);
181226
return val;
182227
}
183228
#endif
@@ -189,9 +234,11 @@ static inline u64 readq(const volatile void __iomem *addr)
189234
{
190235
u64 val;
191236

237+
log_read_mmio(64, addr, _THIS_IP_);
192238
__io_br();
193239
val = __le64_to_cpu(__raw_readq(addr));
194240
__io_ar(val);
241+
log_post_read_mmio(val, 64, addr, _THIS_IP_);
195242
return val;
196243
}
197244
#endif
@@ -201,29 +248,35 @@ static inline u64 readq(const volatile void __iomem *addr)
201248
#define writeb writeb
202249
static inline void writeb(u8 value, volatile void __iomem *addr)
203250
{
251+
log_write_mmio(value, 8, addr, _THIS_IP_);
204252
__io_bw();
205253
__raw_writeb(value, addr);
206254
__io_aw();
255+
log_post_write_mmio(value, 8, addr, _THIS_IP_);
207256
}
208257
#endif
209258

210259
#ifndef writew
211260
#define writew writew
212261
static inline void writew(u16 value, volatile void __iomem *addr)
213262
{
263+
log_write_mmio(value, 16, addr, _THIS_IP_);
214264
__io_bw();
215265
__raw_writew((u16 __force)cpu_to_le16(value), addr);
216266
__io_aw();
267+
log_post_write_mmio(value, 16, addr, _THIS_IP_);
217268
}
218269
#endif
219270

220271
#ifndef writel
221272
#define writel writel
222273
static inline void writel(u32 value, volatile void __iomem *addr)
223274
{
275+
log_write_mmio(value, 32, addr, _THIS_IP_);
224276
__io_bw();
225277
__raw_writel((u32 __force)__cpu_to_le32(value), addr);
226278
__io_aw();
279+
log_post_write_mmio(value, 32, addr, _THIS_IP_);
227280
}
228281
#endif
229282

@@ -232,9 +285,11 @@ static inline void writel(u32 value, volatile void __iomem *addr)
232285
#define writeq writeq
233286
static inline void writeq(u64 value, volatile void __iomem *addr)
234287
{
288+
log_write_mmio(value, 64, addr, _THIS_IP_);
235289
__io_bw();
236290
__raw_writeq(__cpu_to_le64(value), addr);
237291
__io_aw();
292+
log_post_write_mmio(value, 64, addr, _THIS_IP_);
238293
}
239294
#endif
240295
#endif /* CONFIG_64BIT */
@@ -248,63 +303,91 @@ static inline void writeq(u64 value, volatile void __iomem *addr)
248303
#define readb_relaxed readb_relaxed
249304
static inline u8 readb_relaxed(const volatile void __iomem *addr)
250305
{
251-
return __raw_readb(addr);
306+
u8 val;
307+
308+
log_read_mmio(8, addr, _THIS_IP_);
309+
val = __raw_readb(addr);
310+
log_post_read_mmio(val, 8, addr, _THIS_IP_);
311+
return val;
252312
}
253313
#endif
254314

255315
#ifndef readw_relaxed
256316
#define readw_relaxed readw_relaxed
257317
static inline u16 readw_relaxed(const volatile void __iomem *addr)
258318
{
259-
return __le16_to_cpu(__raw_readw(addr));
319+
u16 val;
320+
321+
log_read_mmio(16, addr, _THIS_IP_);
322+
val = __le16_to_cpu(__raw_readw(addr));
323+
log_post_read_mmio(val, 16, addr, _THIS_IP_);
324+
return val;
260325
}
261326
#endif
262327

263328
#ifndef readl_relaxed
264329
#define readl_relaxed readl_relaxed
265330
static inline u32 readl_relaxed(const volatile void __iomem *addr)
266331
{
267-
return __le32_to_cpu(__raw_readl(addr));
332+
u32 val;
333+
334+
log_read_mmio(32, addr, _THIS_IP_);
335+
val = __le32_to_cpu(__raw_readl(addr));
336+
log_post_read_mmio(val, 32, addr, _THIS_IP_);
337+
return val;
268338
}
269339
#endif
270340

271341
#if defined(readq) && !defined(readq_relaxed)
272342
#define readq_relaxed readq_relaxed
273343
static inline u64 readq_relaxed(const volatile void __iomem *addr)
274344
{
275-
return __le64_to_cpu(__raw_readq(addr));
345+
u64 val;
346+
347+
log_read_mmio(64, addr, _THIS_IP_);
348+
val = __le64_to_cpu(__raw_readq(addr));
349+
log_post_read_mmio(val, 64, addr, _THIS_IP_);
350+
return val;
276351
}
277352
#endif
278353

279354
#ifndef writeb_relaxed
280355
#define writeb_relaxed writeb_relaxed
281356
static inline void writeb_relaxed(u8 value, volatile void __iomem *addr)
282357
{
358+
log_write_mmio(value, 8, addr, _THIS_IP_);
283359
__raw_writeb(value, addr);
360+
log_post_write_mmio(value, 8, addr, _THIS_IP_);
284361
}
285362
#endif
286363

287364
#ifndef writew_relaxed
288365
#define writew_relaxed writew_relaxed
289366
static inline void writew_relaxed(u16 value, volatile void __iomem *addr)
290367
{
368+
log_write_mmio(value, 16, addr, _THIS_IP_);
291369
__raw_writew(cpu_to_le16(value), addr);
370+
log_post_write_mmio(value, 16, addr, _THIS_IP_);
292371
}
293372
#endif
294373

295374
#ifndef writel_relaxed
296375
#define writel_relaxed writel_relaxed
297376
static inline void writel_relaxed(u32 value, volatile void __iomem *addr)
298377
{
378+
log_write_mmio(value, 32, addr, _THIS_IP_);
299379
__raw_writel(__cpu_to_le32(value), addr);
380+
log_post_write_mmio(value, 32, addr, _THIS_IP_);
300381
}
301382
#endif
302383

303384
#if defined(writeq) && !defined(writeq_relaxed)
304385
#define writeq_relaxed writeq_relaxed
305386
static inline void writeq_relaxed(u64 value, volatile void __iomem *addr)
306387
{
388+
log_write_mmio(value, 64, addr, _THIS_IP_);
307389
__raw_writeq(__cpu_to_le64(value), addr);
390+
log_post_write_mmio(value, 64, addr, _THIS_IP_);
308391
}
309392
#endif
310393

0 commit comments

Comments
 (0)