ARM: Fix build after memfd_create syscall
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / drivers / iommu / exynos-iommu-log.h
1 /*
2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
4 *
5 * Data structure definition for Exynos IOMMU driver
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12 #ifndef _EXYNOS_IOMMU_LOG_H_
13 #define _EXYNOS_IOMMU_LOG_H_
14
15 #include <linux/mm.h>
16 #include <linux/mm_types.h>
17 #include <linux/ktime.h>
18 #include <linux/hrtimer.h>
19 #include <linux/gfp.h>
20 #include <linux/vmalloc.h>
21 #include <linux/device.h>
22
23 enum sysmmu_event_log_event {
24 EVENT_SYSMMU_NONE, /* initialized value */
25 EVENT_SYSMMU_ENABLE,
26 EVENT_SYSMMU_DISABLE,
27 EVENT_SYSMMU_TLB_INV_RANGE,
28 EVENT_SYSMMU_TLB_INV_VPN,
29 EVENT_SYSMMU_TLB_INV_ALL,
30 EVENT_SYSMMU_FLPD_FLUSH,
31 EVENT_SYSMMU_DF,
32 EVENT_SYSMMU_DF_UNLOCK,
33 EVENT_SYSMMU_DF_UNLOCK_ALL,
34 EVENT_SYSMMU_PBLMM,
35 EVENT_SYSMMU_PBSET,
36 EVENT_SYSMMU_BLOCK, /* TODO: consider later */
37 EVENT_SYSMMU_UNBLOCK, /* TODO: consider later */
38 #ifdef CONFIG_PM_RUNTIME
39 EVENT_SYSMMU_POWERON,
40 EVENT_SYSMMU_POWEROFF,
41 #endif
42 EVENT_SYSMMU_IOMMU_ATTACH,
43 EVENT_SYSMMU_IOMMU_DETACH,
44 EVENT_SYSMMU_IOMMU_MAP,
45 EVENT_SYSMMU_IOMMU_UNMAP,
46 EVENT_SYSMMU_IOMMU_ALLOCSLPD,
47 EVENT_SYSMMU_IOMMU_FREESLPD,
48 EVENT_SYSMMU_IOVMM_MAP,
49 EVENT_SYSMMU_IOVMM_UNMAP
50 };
51
52 struct sysmmu_event_range {
53 u32 start;
54 u32 end;
55 };
56
57 struct sysmmu_event_PBLMM {
58 u32 lmm;
59 u32 buf_num;
60 };
61 struct sysmmu_event_PBSET {
62 u32 config;
63 u32 start;
64 u32 end;
65 };
66
67 struct sysmmu_event_IOMMU_MAP {
68 u32 start;
69 u32 end;
70 unsigned int pfn;
71 };
72
73 struct sysmmu_event_IOVMM_MAP {
74 u32 start;
75 u32 end;
76 unsigned int dummy;
77 };
78
79 /**
80 * event must be updated before eventdata because of eventdata.dev
81 * sysmmu_event_log is not protected by any locks. That means it permits
82 * some data inconsistency by race condition between updating and reading.
83 * However the problem arises when event is either IOMMU_ATTACH or
84 * IOMMU_DETACH because they stores a pointer to device descriptor to
85 * eventdata.dev and reading the sysmmu_event_log of those events refers
86 * to values pointed by eventdata.dev.
87 * Therefore, eventdata must be updated before event not to access invalid
88 * pointer by reading debugfs entries.
89 */
90 struct sysmmu_event_log {
91 ktime_t timestamp;
92 union {
93 struct sysmmu_event_range range;
94 struct sysmmu_event_PBLMM pblmm;
95 struct sysmmu_event_PBSET pbset;
96 struct sysmmu_event_IOMMU_MAP iommu;
97 struct sysmmu_event_IOVMM_MAP iovmm;
98 u32 addr;
99 struct device *dev;
100 } eventdata;
101 enum sysmmu_event_log_event event;
102 };
103
104 struct exynos_iommu_event_log {
105 atomic_t index;
106 unsigned int log_len;
107 struct page *page_log;
108 struct sysmmu_event_log *log;
109 struct dentry *debugfs_root;
110 };
111
112 /* sizeof(struct sysmmu_event_log) = 8 + 4 * 3 + 4 = 24 bytes */
113 #define SYSMMU_LOG_LEN 1024
114 #define IOMMU_LOG_LEN 4096
115 #define IOVMM_LOG_LEN 512
116
117 #ifdef CONFIG_EXYNOS_IOMMU_EVENT_LOG
118
119 #define SYSMMU_DRVDATA_TO_LOG(data) (&(data)->log)
120 #define IOMMU_PRIV_TO_LOG(data) (&(data)->log)
121 #define IOMMU_TO_LOG(data) (&((struct exynos_iommu_domain *)(data)->priv)->log)
122 #define IOVMM_TO_LOG(data) (&(data)->log)
123
124 static inline struct sysmmu_event_log *sysmmu_event_log_get(
125 struct exynos_iommu_event_log *plog)
126 {
127 struct sysmmu_event_log *log;
128 unsigned int index =
129 (unsigned int)atomic_inc_return(&plog->index) - 1;
130 log = &plog->log[index % plog->log_len];
131 log->timestamp = ktime_get();
132 return log;
133 }
134
135 #define DEFINE_SYSMMU_EVENT_LOG(evt) \
136 static inline void SYSMMU_EVENT_LOG_##evt(struct exynos_iommu_event_log *plog) \
137 { \
138 struct sysmmu_event_log *log = sysmmu_event_log_get(plog); \
139 log->event = EVENT_SYSMMU_##evt; \
140 }
141
142 #define DEFINE_SYSMMU_EVENT_LOG_1ADDR(evt) \
143 static inline void SYSMMU_EVENT_LOG_##evt( \
144 struct exynos_iommu_event_log *plog, u32 addr) \
145 { \
146 struct sysmmu_event_log *log = sysmmu_event_log_get(plog); \
147 log->eventdata.addr = addr; \
148 log->event = EVENT_SYSMMU_##evt; \
149 }
150
151 #define DEFINE_SYSMMU_EVENT_LOG_2ADDR(evt) \
152 static inline void SYSMMU_EVENT_LOG_##evt(struct exynos_iommu_event_log *plog, \
153 u32 start, u32 end) \
154 { \
155 struct sysmmu_event_log *log = sysmmu_event_log_get(plog); \
156 log->eventdata.range.start = start; \
157 log->eventdata.range.end = end; \
158 log->event = EVENT_SYSMMU_##evt; \
159 }
160
161 /* MMU_CFG is stored at pblmm.lmm for System MMU 3.1 and 3.2 */
162 static inline void SYSMMU_EVENT_LOG_PBLMM(struct exynos_iommu_event_log *plog,
163 u32 lmm, u32 buf_num)
164 {
165 struct sysmmu_event_log *log = sysmmu_event_log_get(plog);
166 log->eventdata.pblmm.lmm = lmm;
167 log->eventdata.pblmm.buf_num = buf_num;
168 log->event = EVENT_SYSMMU_PBLMM;
169 }
170
171 /* PB index is stored at pbset.config for System MMU 3.1 and 3.2 */
172 static inline void SYSMMU_EVENT_LOG_PBSET(struct exynos_iommu_event_log *plog,
173 u32 config, u32 start, u32 end)
174 {
175 struct sysmmu_event_log *log = sysmmu_event_log_get(plog);
176 log->eventdata.pbset.config = config;
177 log->eventdata.pbset.start = start;
178 log->eventdata.pbset.end = end;
179 log->event = EVENT_SYSMMU_PBSET;
180 }
181
182 static inline void SYSMMU_EVENT_LOG_IOVMM_MAP(
183 struct exynos_iommu_event_log *plog,
184 u32 start, u32 end, unsigned int dummy)
185 {
186 struct sysmmu_event_log *log = sysmmu_event_log_get(plog);
187 log->eventdata.iovmm.start = start;
188 log->eventdata.iovmm.end = end;
189 log->eventdata.iovmm.dummy = dummy;
190 log->event = EVENT_SYSMMU_IOVMM_MAP;
191 }
192
193 static inline void SYSMMU_EVENT_LOG_IOMMU_ATTACH(
194 struct exynos_iommu_event_log *plog, struct device *dev)
195 {
196 struct sysmmu_event_log *log = sysmmu_event_log_get(plog);
197 log->eventdata.dev = dev;
198 log->event = EVENT_SYSMMU_IOMMU_ATTACH;
199 }
200
201 static inline void SYSMMU_EVENT_LOG_IOMMU_DETACH(
202 struct exynos_iommu_event_log *plog, struct device *dev)
203 {
204 struct sysmmu_event_log *log = sysmmu_event_log_get(plog);
205 log->eventdata.dev = dev;
206 log->event = EVENT_SYSMMU_IOMMU_DETACH;
207 }
208
209 static inline void SYSMMU_EVENT_LOG_IOMMU_MAP(
210 struct exynos_iommu_event_log *plog,
211 u32 start, u32 end, unsigned int pfn)
212 {
213 struct sysmmu_event_log *log = sysmmu_event_log_get(plog);
214 log->event = EVENT_SYSMMU_IOMMU_MAP;
215 log->eventdata.iommu.start = start;
216 log->eventdata.iommu.end = end;
217 log->eventdata.iommu.pfn = pfn;
218 }
219
220 int exynos_iommu_init_event_log(struct exynos_iommu_event_log *log,
221 unsigned int log_len);
222
223 static inline void exynos_iommu_free_event_log(
224 struct exynos_iommu_event_log *plog, unsigned int log_len)
225 {
226 vunmap(plog->log);
227 __free_pages(plog->page_log, get_order(sizeof(*(plog->log)) * log_len));
228 }
229
230 void sysmmu_add_log_to_debugfs(struct dentry *debugfs_root,
231 struct exynos_iommu_event_log *log, const char *name);
232
233 void iommu_add_log_to_debugfs(struct dentry *debugfs_root,
234 struct exynos_iommu_event_log *log, const char *name);
235
236 #if defined(CONFIG_EXYNOS_IOVMM) || defined(CONFIG_EXYNOS_IOVMM_V6)
237 void iovmm_add_log_to_debugfs(struct dentry *debugfs_root,
238 struct exynos_iommu_event_log *log, const char *name);
239 #else
240 #define iovmm_add_log_to_debugfs(debugfs_root, log, name) do { } while (0)
241 #endif
242
243 #else /* !CONFIG_EXYNOS_IOMMU_EVENT_LOG */
244
245 #define SYSMMU_DRVDATA_TO_LOG(data) NULL
246 #define IOMMU_PRIV_TO_LOG(data) NULL
247 #define IOMMU_TO_LOG(data) NULL
248 #define IOVMM_TO_LOG(data) NULL
249
250 static inline int exynos_iommu_init_event_log(
251 struct exynos_iommu_event_log *log, unsigned int log_len)
252 {
253 return 0;
254 }
255
256 #define exynos_iommu_free_event_log(plog, log_len) do { } while (0)
257
258 #define iovmm_add_log_to_debugfs(debugfs_root, log, name) do { } while (0)
259
260 #define DEFINE_SYSMMU_EVENT_LOG(event) \
261 static inline void SYSMMU_EVENT_LOG_##event( \
262 struct exynos_iommu_event_log *plog) \
263 { \
264 }
265
266 #define DEFINE_SYSMMU_EVENT_LOG_1ADDR(event) \
267 static inline void SYSMMU_EVENT_LOG_##event( \
268 struct exynos_iommu_event_log *plog, u32 start) \
269 { \
270 }
271
272 #define DEFINE_SYSMMU_EVENT_LOG_2ADDR(event) \
273 static inline void SYSMMU_EVENT_LOG_##event( \
274 struct exynos_iommu_event_log *plog, u32 start, u32 end) \
275 { \
276 }
277
278 static inline void SYSMMU_EVENT_LOG_PBLMM(struct exynos_iommu_event_log *plog,
279 u32 lmm, u32 buf_num)
280 {
281 }
282
283 static inline void SYSMMU_EVENT_LOG_PBSET(struct exynos_iommu_event_log *plog,
284 u32 config, u32 start, u32 end)
285 {
286 }
287
288 static inline void SYSMMU_EVENT_LOG_IOMMU_MAP(
289 struct exynos_iommu_event_log *plog,
290 u32 start, u32 end, unsigned int pfn)
291 {
292 }
293
294 static inline void SYSMMU_EVENT_LOG_IOVMM_MAP(
295 struct exynos_iommu_event_log *plog,
296 u32 start, u32 end, size_t dummy)
297 {
298 }
299
300 static inline void SYSMMU_EVENT_LOG_IOMMU_ATTACH(
301 struct exynos_iommu_event_log *plog, struct device *dev)
302 {
303 }
304
305 static inline void SYSMMU_EVENT_LOG_IOMMU_DETACH(
306 struct exynos_iommu_event_log *plog, struct device *dev)
307 {
308 }
309
310 #define sysmmu_add_log_to_debugfs(debugfs_root, log, name) do { } while (0)
311 #define iommu_add_log_to_debugfs(debugfs_root, log, name) do { } while (0)
312 #define iovmm_add_log_to_debugfs(debugfs_root, log, name) do { } while (0)
313
314 #endif /* CONFIG_EXYNOS_IOMMU_EVENT_LOG */
315
316 DEFINE_SYSMMU_EVENT_LOG(ENABLE)
317 DEFINE_SYSMMU_EVENT_LOG(DISABLE)
318 DEFINE_SYSMMU_EVENT_LOG(TLB_INV_ALL)
319 DEFINE_SYSMMU_EVENT_LOG(DF_UNLOCK_ALL)
320 DEFINE_SYSMMU_EVENT_LOG(BLOCK)
321 DEFINE_SYSMMU_EVENT_LOG(UNBLOCK)
322 #ifdef CONFIG_PM_RUNTIME
323 DEFINE_SYSMMU_EVENT_LOG(POWERON)
324 DEFINE_SYSMMU_EVENT_LOG(POWEROFF)
325 #endif
326
327 DEFINE_SYSMMU_EVENT_LOG_1ADDR(TLB_INV_VPN)
328 DEFINE_SYSMMU_EVENT_LOG_1ADDR(FLPD_FLUSH)
329 DEFINE_SYSMMU_EVENT_LOG_1ADDR(DF)
330 DEFINE_SYSMMU_EVENT_LOG_1ADDR(DF_UNLOCK)
331 DEFINE_SYSMMU_EVENT_LOG_1ADDR(IOMMU_ALLOCSLPD)
332 DEFINE_SYSMMU_EVENT_LOG_1ADDR(IOMMU_FREESLPD)
333
334 DEFINE_SYSMMU_EVENT_LOG_2ADDR(TLB_INV_RANGE)
335 DEFINE_SYSMMU_EVENT_LOG_2ADDR(IOMMU_UNMAP)
336 DEFINE_SYSMMU_EVENT_LOG_2ADDR(IOVMM_UNMAP)
337
338 #endif /*_EXYNOS_IOMMU_LOG_H_*/