xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2 /*
3  *
4  * (C) COPYRIGHT 2011-2022 ARM Limited. All rights reserved.
5  *
6  * This program is free software and is provided to you under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation, and any use by you of this program is subject to the terms
9  * of such GNU license.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you can access it online at
18  * http://www.gnu.org/licenses/gpl-2.0.html.
19  *
20  */
21 
22 #include "mali_kbase_vinstr.h"
23 #include "hwcnt/mali_kbase_hwcnt_virtualizer.h"
24 #include "hwcnt/mali_kbase_hwcnt_types.h"
25 #include <uapi/gpu/arm/bifrost/mali_kbase_hwcnt_reader.h>
26 #include "hwcnt/mali_kbase_hwcnt_gpu.h"
27 #include "hwcnt/mali_kbase_hwcnt_gpu_narrow.h"
28 #include <uapi/gpu/arm/bifrost/mali_kbase_ioctl.h>
29 #include "mali_malisw.h"
30 #include "mali_kbase_debug.h"
31 
32 #include <linux/anon_inodes.h>
33 #include <linux/fcntl.h>
34 #include <linux/fs.h>
35 #include <linux/hrtimer.h>
36 #include <linux/log2.h>
37 #include <linux/mm.h>
38 #include <linux/mutex.h>
39 #include <linux/poll.h>
40 #include <linux/slab.h>
41 #include <linux/version_compat_defs.h>
42 #include <linux/workqueue.h>
43 
44 /* Explicitly include epoll header for old kernels. Not required from 4.16. */
45 #if KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE
46 #include <uapi/linux/eventpoll.h>
47 #endif
48 
49 /* Hwcnt reader API version */
50 #define HWCNT_READER_API 1
51 
52 /* The minimum allowed interval between dumps (equivalent to 10KHz) */
53 #define DUMP_INTERVAL_MIN_NS (100 * NSEC_PER_USEC)
54 
55 /* The maximum allowed buffers per client */
56 #define MAX_BUFFER_COUNT 32
57 
58 /**
59  * struct kbase_vinstr_context - IOCTL interface for userspace hardware
60  *                               counters.
61  * @hvirt:         Hardware counter virtualizer used by vinstr.
62  * @metadata:      Hardware counter metadata provided by virtualizer.
63  * @metadata_user: API compatible hardware counter metadata provided by vinstr.
64  *                 For compatibility with the user driver interface, this
65  *                 contains a narrowed version of the HWCNT metadata limited
66  *                 to 64 entries per block of 32 bits each.
67  * @lock:          Lock protecting all vinstr state.
68  * @suspend_count: Suspend reference count. If non-zero, timer and worker are
69  *                 prevented from being re-scheduled.
70  * @client_count:  Number of vinstr clients.
71  * @clients:       List of vinstr clients.
72  * @dump_timer:    Timer that enqueues dump_work to a workqueue.
73  * @dump_work:     Worker for performing periodic counter dumps.
74  */
75 struct kbase_vinstr_context {
76 	struct kbase_hwcnt_virtualizer *hvirt;
77 	const struct kbase_hwcnt_metadata *metadata;
78 	const struct kbase_hwcnt_metadata_narrow *metadata_user;
79 	struct mutex lock;
80 	size_t suspend_count;
81 	size_t client_count;
82 	struct list_head clients;
83 	struct hrtimer dump_timer;
84 	struct work_struct dump_work;
85 };
86 
87 /**
88  * struct kbase_vinstr_client - A vinstr client attached to a vinstr context.
89  * @vctx:              Vinstr context client is attached to.
90  * @hvcli:             Hardware counter virtualizer client.
91  * @node:              Node used to attach this client to list in vinstr
92  *                     context.
93  * @dump_interval_ns:  Interval between periodic dumps. If 0, not a periodic
94  *                     client.
95  * @next_dump_time_ns: Time in ns when this client's next periodic dump must
96  *                     occur. If 0, not a periodic client.
97  * @enable_map:        Counters enable map.
98  * @tmp_buf:           Temporary buffer to use before handing dump to client.
99  * @dump_bufs:         Array of narrow dump buffers allocated by this client.
100  * @dump_bufs_meta:    Metadata of hwcnt reader client buffers.
101  * @meta_idx:          Index of metadata being accessed by userspace.
102  * @read_idx:          Index of buffer read by userspace.
103  * @write_idx:         Index of buffer being written by dump worker.
104  * @waitq:             Client's notification queue.
105  */
106 struct kbase_vinstr_client {
107 	struct kbase_vinstr_context *vctx;
108 	struct kbase_hwcnt_virtualizer_client *hvcli;
109 	struct list_head node;
110 	u64 next_dump_time_ns;
111 	u32 dump_interval_ns;
112 	struct kbase_hwcnt_enable_map enable_map;
113 	struct kbase_hwcnt_dump_buffer tmp_buf;
114 	struct kbase_hwcnt_dump_buffer_narrow_array dump_bufs;
115 	struct kbase_hwcnt_reader_metadata *dump_bufs_meta;
116 	atomic_t meta_idx;
117 	atomic_t read_idx;
118 	atomic_t write_idx;
119 	wait_queue_head_t waitq;
120 };
121 
122 static __poll_t kbasep_vinstr_hwcnt_reader_poll(struct file *filp, poll_table *wait);
123 
124 static long kbasep_vinstr_hwcnt_reader_ioctl(
125 	struct file *filp,
126 	unsigned int cmd,
127 	unsigned long arg);
128 
129 static int kbasep_vinstr_hwcnt_reader_mmap(
130 	struct file *filp,
131 	struct vm_area_struct *vma);
132 
133 static int kbasep_vinstr_hwcnt_reader_release(
134 	struct inode *inode,
135 	struct file *filp);
136 
137 /* Vinstr client file operations */
138 static const struct file_operations vinstr_client_fops = {
139 	.owner = THIS_MODULE,
140 	.poll           = kbasep_vinstr_hwcnt_reader_poll,
141 	.unlocked_ioctl = kbasep_vinstr_hwcnt_reader_ioctl,
142 	.compat_ioctl   = kbasep_vinstr_hwcnt_reader_ioctl,
143 	.mmap           = kbasep_vinstr_hwcnt_reader_mmap,
144 	.release        = kbasep_vinstr_hwcnt_reader_release,
145 };
146 
147 /**
148  * kbasep_vinstr_timestamp_ns() - Get the current time in nanoseconds.
149  *
150  * Return: Current time in nanoseconds.
151  */
kbasep_vinstr_timestamp_ns(void)152 static u64 kbasep_vinstr_timestamp_ns(void)
153 {
154 	return ktime_get_raw_ns();
155 }
156 
157 /**
158  * kbasep_vinstr_next_dump_time_ns() - Calculate the next periodic dump time.
159  * @cur_ts_ns: Current time in nanoseconds.
160  * @interval:  Interval between dumps in nanoseconds.
161  *
162  * Return: 0 if interval is 0 (i.e. a non-periodic client), or the next dump
163  *         time that occurs after cur_ts_ns.
164  */
kbasep_vinstr_next_dump_time_ns(u64 cur_ts_ns,u32 interval)165 static u64 kbasep_vinstr_next_dump_time_ns(u64 cur_ts_ns, u32 interval)
166 {
167 	/* Non-periodic client */
168 	if (interval == 0)
169 		return 0;
170 
171 	/*
172 	 * Return the next interval after the current time relative to t=0.
173 	 * This means multiple clients with the same period will synchronise,
174 	 * regardless of when they were started, allowing the worker to be
175 	 * scheduled less frequently.
176 	 */
177 	do_div(cur_ts_ns, interval);
178 	return (cur_ts_ns + 1) * interval;
179 }
180 
181 /**
182  * kbasep_vinstr_client_dump() - Perform a dump for a client.
183  * @vcli:     Non-NULL pointer to a vinstr client.
184  * @event_id: Event type that triggered the dump.
185  *
186  * Return: 0 on success, else error code.
187  */
kbasep_vinstr_client_dump(struct kbase_vinstr_client * vcli,enum base_hwcnt_reader_event event_id)188 static int kbasep_vinstr_client_dump(
189 	struct kbase_vinstr_client *vcli,
190 	enum base_hwcnt_reader_event event_id)
191 {
192 	int errcode;
193 	u64 ts_start_ns;
194 	u64 ts_end_ns;
195 	unsigned int write_idx;
196 	unsigned int read_idx;
197 	struct kbase_hwcnt_dump_buffer *tmp_buf;
198 	struct kbase_hwcnt_dump_buffer_narrow *dump_buf;
199 	struct kbase_hwcnt_reader_metadata *meta;
200 	u8 clk_cnt;
201 
202 	WARN_ON(!vcli);
203 	lockdep_assert_held(&vcli->vctx->lock);
204 
205 	write_idx = atomic_read(&vcli->write_idx);
206 	read_idx = atomic_read(&vcli->read_idx);
207 
208 	/* Check if there is a place to copy HWC block into. */
209 	if (write_idx - read_idx == vcli->dump_bufs.buf_cnt)
210 		return -EBUSY;
211 	write_idx %= vcli->dump_bufs.buf_cnt;
212 
213 	dump_buf = &vcli->dump_bufs.bufs[write_idx];
214 	meta = &vcli->dump_bufs_meta[write_idx];
215 	tmp_buf = &vcli->tmp_buf;
216 
217 	errcode = kbase_hwcnt_virtualizer_client_dump(
218 		vcli->hvcli, &ts_start_ns, &ts_end_ns, tmp_buf);
219 	if (errcode)
220 		return errcode;
221 
222 	/* Patch the dump buf headers, to hide the counters that other hwcnt
223 	 * clients are using.
224 	 */
225 	kbase_hwcnt_gpu_patch_dump_headers(tmp_buf, &vcli->enable_map);
226 
227 	/* Copy the temp buffer to the userspace visible buffer. The strict
228 	 * variant will explicitly zero any non-enabled counters to ensure
229 	 * nothing except exactly what the user asked for is made visible.
230 	 *
231 	 * A narrow copy is required since virtualizer has a bigger buffer
232 	 * but user only needs part of it.
233 	 */
234 	kbase_hwcnt_dump_buffer_copy_strict_narrow(dump_buf, tmp_buf,
235 						   &vcli->enable_map);
236 
237 	clk_cnt = vcli->vctx->metadata->clk_cnt;
238 
239 	meta->timestamp = ts_end_ns;
240 	meta->event_id = event_id;
241 	meta->buffer_idx = write_idx;
242 	meta->cycles.top = (clk_cnt > 0) ? dump_buf->clk_cnt_buf[0] : 0;
243 	meta->cycles.shader_cores =
244 	    (clk_cnt > 1) ? dump_buf->clk_cnt_buf[1] : 0;
245 
246 	/* Notify client. Make sure all changes to memory are visible. */
247 	wmb();
248 	atomic_inc(&vcli->write_idx);
249 	wake_up_interruptible(&vcli->waitq);
250 	return 0;
251 }
252 
253 /**
254  * kbasep_vinstr_client_clear() - Reset all the client's counters to zero.
255  * @vcli: Non-NULL pointer to a vinstr client.
256  *
257  * Return: 0 on success, else error code.
258  */
kbasep_vinstr_client_clear(struct kbase_vinstr_client * vcli)259 static int kbasep_vinstr_client_clear(struct kbase_vinstr_client *vcli)
260 {
261 	u64 ts_start_ns;
262 	u64 ts_end_ns;
263 
264 	WARN_ON(!vcli);
265 	lockdep_assert_held(&vcli->vctx->lock);
266 
267 	/* A virtualizer dump with a NULL buffer will just clear the virtualizer
268 	 * client's buffer.
269 	 */
270 	return kbase_hwcnt_virtualizer_client_dump(
271 		vcli->hvcli, &ts_start_ns, &ts_end_ns, NULL);
272 }
273 
274 /**
275  * kbasep_vinstr_reschedule_worker() - Update next dump times for all periodic
276  *                                     vinstr clients, then reschedule the dump
277  *                                     worker appropriately.
278  * @vctx: Non-NULL pointer to the vinstr context.
279  *
280  * If there are no periodic clients, then the dump worker will not be
281  * rescheduled. Else, the dump worker will be rescheduled for the next periodic
282  * client dump.
283  */
kbasep_vinstr_reschedule_worker(struct kbase_vinstr_context * vctx)284 static void kbasep_vinstr_reschedule_worker(struct kbase_vinstr_context *vctx)
285 {
286 	u64 cur_ts_ns;
287 	u64 earliest_next_ns = U64_MAX;
288 	struct kbase_vinstr_client *pos;
289 
290 	WARN_ON(!vctx);
291 	lockdep_assert_held(&vctx->lock);
292 
293 	cur_ts_ns = kbasep_vinstr_timestamp_ns();
294 
295 	/*
296 	 * Update each client's next dump time, and find the earliest next
297 	 * dump time if any of the clients have a non-zero interval.
298 	 */
299 	list_for_each_entry(pos, &vctx->clients, node) {
300 		const u64 cli_next_ns =
301 			kbasep_vinstr_next_dump_time_ns(
302 				cur_ts_ns, pos->dump_interval_ns);
303 
304 		/* Non-zero next dump time implies a periodic client */
305 		if ((cli_next_ns != 0) && (cli_next_ns < earliest_next_ns))
306 			earliest_next_ns = cli_next_ns;
307 
308 		pos->next_dump_time_ns = cli_next_ns;
309 	}
310 
311 	/* Cancel the timer if it is already pending */
312 	hrtimer_cancel(&vctx->dump_timer);
313 
314 	/* Start the timer if there are periodic clients and vinstr is not
315 	 * suspended.
316 	 */
317 	if ((earliest_next_ns != U64_MAX) &&
318 	    (vctx->suspend_count == 0) &&
319 	    !WARN_ON(earliest_next_ns < cur_ts_ns))
320 		hrtimer_start(
321 			&vctx->dump_timer,
322 			ns_to_ktime(earliest_next_ns - cur_ts_ns),
323 			HRTIMER_MODE_REL);
324 }
325 
326 /**
327  * kbasep_vinstr_dump_worker()- Dump worker, that dumps all periodic clients
328  *                              that need to be dumped, then reschedules itself.
329  * @work: Work structure.
330  */
kbasep_vinstr_dump_worker(struct work_struct * work)331 static void kbasep_vinstr_dump_worker(struct work_struct *work)
332 {
333 	struct kbase_vinstr_context *vctx =
334 		container_of(work, struct kbase_vinstr_context, dump_work);
335 	struct kbase_vinstr_client *pos;
336 	u64 cur_time_ns;
337 
338 	mutex_lock(&vctx->lock);
339 
340 	cur_time_ns = kbasep_vinstr_timestamp_ns();
341 
342 	/* Dump all periodic clients whose next dump time is before the current
343 	 * time.
344 	 */
345 	list_for_each_entry(pos, &vctx->clients, node) {
346 		if ((pos->next_dump_time_ns != 0) &&
347 			(pos->next_dump_time_ns < cur_time_ns))
348 			kbasep_vinstr_client_dump(
349 				pos, BASE_HWCNT_READER_EVENT_PERIODIC);
350 	}
351 
352 	/* Update the next dump times of all periodic clients, then reschedule
353 	 * this worker at the earliest next dump time.
354 	 */
355 	kbasep_vinstr_reschedule_worker(vctx);
356 
357 	mutex_unlock(&vctx->lock);
358 }
359 
360 /**
361  * kbasep_vinstr_dump_timer() - Dump timer that schedules the dump worker for
362  *                              execution as soon as possible.
363  * @timer: Timer structure.
364  *
365  * Return: HRTIMER_NORESTART always.
366  */
kbasep_vinstr_dump_timer(struct hrtimer * timer)367 static enum hrtimer_restart kbasep_vinstr_dump_timer(struct hrtimer *timer)
368 {
369 	struct kbase_vinstr_context *vctx =
370 		container_of(timer, struct kbase_vinstr_context, dump_timer);
371 
372 	/* We don't need to check vctx->suspend_count here, as the suspend
373 	 * function will ensure that any worker enqueued here is immediately
374 	 * cancelled, and the worker itself won't reschedule this timer if
375 	 * suspend_count != 0.
376 	 */
377 	kbase_hwcnt_virtualizer_queue_work(vctx->hvirt, &vctx->dump_work);
378 	return HRTIMER_NORESTART;
379 }
380 
381 /**
382  * kbasep_vinstr_client_destroy() - Destroy a vinstr client.
383  * @vcli: vinstr client. Must not be attached to a vinstr context.
384  */
kbasep_vinstr_client_destroy(struct kbase_vinstr_client * vcli)385 static void kbasep_vinstr_client_destroy(struct kbase_vinstr_client *vcli)
386 {
387 	if (!vcli)
388 		return;
389 
390 	kbase_hwcnt_virtualizer_client_destroy(vcli->hvcli);
391 	kfree(vcli->dump_bufs_meta);
392 	kbase_hwcnt_dump_buffer_narrow_array_free(&vcli->dump_bufs);
393 	kbase_hwcnt_dump_buffer_free(&vcli->tmp_buf);
394 	kbase_hwcnt_enable_map_free(&vcli->enable_map);
395 	kfree(vcli);
396 }
397 
398 /**
399  * kbasep_vinstr_client_create() - Create a vinstr client. Does not attach to
400  *                                 the vinstr context.
401  * @vctx:     Non-NULL pointer to vinstr context.
402  * @setup:    Non-NULL pointer to hardware counter ioctl setup structure.
403  *            setup->buffer_count must not be 0 and must be a power of 2.
404  * @out_vcli: Non-NULL pointer to where created client will be stored on
405  *            success.
406  *
407  * Return: 0 on success, else error code.
408  */
kbasep_vinstr_client_create(struct kbase_vinstr_context * vctx,struct kbase_ioctl_hwcnt_reader_setup * setup,struct kbase_vinstr_client ** out_vcli)409 static int kbasep_vinstr_client_create(
410 	struct kbase_vinstr_context *vctx,
411 	struct kbase_ioctl_hwcnt_reader_setup *setup,
412 	struct kbase_vinstr_client **out_vcli)
413 {
414 	int errcode;
415 	struct kbase_vinstr_client *vcli;
416 	struct kbase_hwcnt_physical_enable_map phys_em;
417 
418 	WARN_ON(!vctx);
419 	WARN_ON(!setup);
420 	WARN_ON(setup->buffer_count == 0);
421 	WARN_ON(!is_power_of_2(setup->buffer_count));
422 
423 	vcli = kzalloc(sizeof(*vcli), GFP_KERNEL);
424 	if (!vcli)
425 		return -ENOMEM;
426 
427 	vcli->vctx = vctx;
428 
429 	errcode = kbase_hwcnt_enable_map_alloc(
430 		vctx->metadata, &vcli->enable_map);
431 	if (errcode)
432 		goto error;
433 
434 	phys_em.fe_bm = setup->fe_bm;
435 	phys_em.shader_bm = setup->shader_bm;
436 	phys_em.tiler_bm = setup->tiler_bm;
437 	phys_em.mmu_l2_bm = setup->mmu_l2_bm;
438 	kbase_hwcnt_gpu_enable_map_from_physical(&vcli->enable_map, &phys_em);
439 
440 	/* Use virtualizer's metadata to alloc tmp buffer which interacts with
441 	 * the HWC virtualizer.
442 	 */
443 	errcode = kbase_hwcnt_dump_buffer_alloc(vctx->metadata, &vcli->tmp_buf);
444 	if (errcode)
445 		goto error;
446 
447 	/* Enable all the available clk_enable_map. */
448 	vcli->enable_map.clk_enable_map = (1ull << vctx->metadata->clk_cnt) - 1;
449 
450 	/* Use vinstr's narrowed metadata to alloc narrow dump buffers which
451 	 * interact with clients.
452 	 */
453 	errcode = kbase_hwcnt_dump_buffer_narrow_array_alloc(
454 		vctx->metadata_user, setup->buffer_count, &vcli->dump_bufs);
455 	if (errcode)
456 		goto error;
457 
458 	errcode = -ENOMEM;
459 	vcli->dump_bufs_meta = kmalloc_array(
460 		setup->buffer_count, sizeof(*vcli->dump_bufs_meta), GFP_KERNEL);
461 	if (!vcli->dump_bufs_meta)
462 		goto error;
463 
464 	errcode = kbase_hwcnt_virtualizer_client_create(
465 		vctx->hvirt, &vcli->enable_map, &vcli->hvcli);
466 	if (errcode)
467 		goto error;
468 
469 	init_waitqueue_head(&vcli->waitq);
470 
471 	*out_vcli = vcli;
472 	return 0;
473 error:
474 	kbasep_vinstr_client_destroy(vcli);
475 	return errcode;
476 }
477 
kbase_vinstr_init(struct kbase_hwcnt_virtualizer * hvirt,struct kbase_vinstr_context ** out_vctx)478 int kbase_vinstr_init(
479 	struct kbase_hwcnt_virtualizer *hvirt,
480 	struct kbase_vinstr_context **out_vctx)
481 {
482 	int errcode;
483 	struct kbase_vinstr_context *vctx;
484 	const struct kbase_hwcnt_metadata *metadata;
485 
486 	if (!hvirt || !out_vctx)
487 		return -EINVAL;
488 
489 	metadata = kbase_hwcnt_virtualizer_metadata(hvirt);
490 	if (!metadata)
491 		return -EINVAL;
492 
493 	vctx = kzalloc(sizeof(*vctx), GFP_KERNEL);
494 	if (!vctx)
495 		return -ENOMEM;
496 
497 	vctx->hvirt = hvirt;
498 	vctx->metadata = metadata;
499 	errcode = kbase_hwcnt_gpu_metadata_narrow_create(&vctx->metadata_user,
500 							 metadata);
501 	if (errcode)
502 		goto err_metadata_create;
503 
504 	mutex_init(&vctx->lock);
505 	INIT_LIST_HEAD(&vctx->clients);
506 	hrtimer_init(&vctx->dump_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
507 	vctx->dump_timer.function = kbasep_vinstr_dump_timer;
508 	INIT_WORK(&vctx->dump_work, kbasep_vinstr_dump_worker);
509 
510 	*out_vctx = vctx;
511 	return 0;
512 
513 err_metadata_create:
514 	kfree(vctx);
515 
516 	return errcode;
517 }
518 
kbase_vinstr_term(struct kbase_vinstr_context * vctx)519 void kbase_vinstr_term(struct kbase_vinstr_context *vctx)
520 {
521 	if (!vctx)
522 		return;
523 
524 	/* Non-zero client count implies client leak */
525 	if (WARN_ON(vctx->client_count != 0)) {
526 		struct kbase_vinstr_client *pos, *n;
527 
528 		list_for_each_entry_safe(pos, n, &vctx->clients, node) {
529 			list_del(&pos->node);
530 			vctx->client_count--;
531 			kbasep_vinstr_client_destroy(pos);
532 		}
533 	}
534 
535 	cancel_work_sync(&vctx->dump_work);
536 	kbase_hwcnt_gpu_metadata_narrow_destroy(vctx->metadata_user);
537 
538 	WARN_ON(vctx->client_count != 0);
539 	kfree(vctx);
540 }
541 
kbase_vinstr_suspend(struct kbase_vinstr_context * vctx)542 void kbase_vinstr_suspend(struct kbase_vinstr_context *vctx)
543 {
544 	if (WARN_ON(!vctx))
545 		return;
546 
547 	mutex_lock(&vctx->lock);
548 
549 	if (!WARN_ON(vctx->suspend_count == SIZE_MAX))
550 		vctx->suspend_count++;
551 
552 	mutex_unlock(&vctx->lock);
553 
554 	/* Always sync cancel the timer and then the worker, regardless of the
555 	 * new suspend count.
556 	 *
557 	 * This ensures concurrent calls to kbase_vinstr_suspend() always block
558 	 * until vinstr is fully suspended.
559 	 *
560 	 * The timer is cancelled before the worker, as the timer
561 	 * unconditionally re-enqueues the worker, but the worker checks the
562 	 * suspend_count that we just incremented before rescheduling the timer.
563 	 *
564 	 * Therefore if we cancel the worker first, the timer might re-enqueue
565 	 * the worker before we cancel the timer, but the opposite is not
566 	 * possible.
567 	 */
568 	hrtimer_cancel(&vctx->dump_timer);
569 	cancel_work_sync(&vctx->dump_work);
570 }
571 
kbase_vinstr_resume(struct kbase_vinstr_context * vctx)572 void kbase_vinstr_resume(struct kbase_vinstr_context *vctx)
573 {
574 	if (WARN_ON(!vctx))
575 		return;
576 
577 	mutex_lock(&vctx->lock);
578 
579 	if (!WARN_ON(vctx->suspend_count == 0)) {
580 		vctx->suspend_count--;
581 
582 		/* Last resume, so re-enqueue the worker if we have any periodic
583 		 * clients.
584 		 */
585 		if (vctx->suspend_count == 0) {
586 			struct kbase_vinstr_client *pos;
587 			bool has_periodic_clients = false;
588 
589 			list_for_each_entry(pos, &vctx->clients, node) {
590 				if (pos->dump_interval_ns != 0) {
591 					has_periodic_clients = true;
592 					break;
593 				}
594 			}
595 
596 			if (has_periodic_clients)
597 				kbase_hwcnt_virtualizer_queue_work(
598 					vctx->hvirt, &vctx->dump_work);
599 		}
600 	}
601 
602 	mutex_unlock(&vctx->lock);
603 }
604 
kbase_vinstr_hwcnt_reader_setup(struct kbase_vinstr_context * vctx,struct kbase_ioctl_hwcnt_reader_setup * setup)605 int kbase_vinstr_hwcnt_reader_setup(
606 	struct kbase_vinstr_context *vctx,
607 	struct kbase_ioctl_hwcnt_reader_setup *setup)
608 {
609 	int errcode;
610 	int fd;
611 	struct kbase_vinstr_client *vcli = NULL;
612 
613 	if (!vctx || !setup ||
614 	    (setup->buffer_count == 0) ||
615 	    (setup->buffer_count > MAX_BUFFER_COUNT) ||
616 	    !is_power_of_2(setup->buffer_count))
617 		return -EINVAL;
618 
619 	errcode = kbasep_vinstr_client_create(vctx, setup, &vcli);
620 	if (errcode)
621 		goto error;
622 
623 	/* Add the new client. No need to reschedule worker, as not periodic */
624 	mutex_lock(&vctx->lock);
625 
626 	vctx->client_count++;
627 	list_add(&vcli->node, &vctx->clients);
628 
629 	mutex_unlock(&vctx->lock);
630 
631 	/* Expose to user-space only once the client is fully initialized */
632 	errcode = anon_inode_getfd(
633 		"[mali_vinstr_desc]",
634 		&vinstr_client_fops,
635 		vcli,
636 		O_RDONLY | O_CLOEXEC);
637 	if (errcode < 0)
638 		goto client_installed_error;
639 
640 	fd = errcode;
641 
642 	return fd;
643 
644 client_installed_error:
645 	mutex_lock(&vctx->lock);
646 
647 	vctx->client_count--;
648 	list_del(&vcli->node);
649 
650 	mutex_unlock(&vctx->lock);
651 error:
652 	kbasep_vinstr_client_destroy(vcli);
653 	return errcode;
654 }
655 
656 /**
657  * kbasep_vinstr_hwcnt_reader_buffer_ready() - Check if client has ready
658  *                                             buffers.
659  * @cli: Non-NULL pointer to vinstr client.
660  *
661  * Return: Non-zero if client has at least one dumping buffer filled that was
662  *         not notified to user yet.
663  */
kbasep_vinstr_hwcnt_reader_buffer_ready(struct kbase_vinstr_client * cli)664 static int kbasep_vinstr_hwcnt_reader_buffer_ready(
665 	struct kbase_vinstr_client *cli)
666 {
667 	WARN_ON(!cli);
668 	return atomic_read(&cli->write_idx) != atomic_read(&cli->meta_idx);
669 }
670 
671 /**
672  * kbasep_vinstr_hwcnt_reader_ioctl_dump() - Dump ioctl command.
673  * @cli: Non-NULL pointer to vinstr client.
674  *
675  * Return: 0 on success, else error code.
676  */
kbasep_vinstr_hwcnt_reader_ioctl_dump(struct kbase_vinstr_client * cli)677 static long kbasep_vinstr_hwcnt_reader_ioctl_dump(
678 	struct kbase_vinstr_client *cli)
679 {
680 	int errcode;
681 
682 	mutex_lock(&cli->vctx->lock);
683 
684 	errcode = kbasep_vinstr_client_dump(
685 		cli, BASE_HWCNT_READER_EVENT_MANUAL);
686 
687 	mutex_unlock(&cli->vctx->lock);
688 	return errcode;
689 }
690 
691 /**
692  * kbasep_vinstr_hwcnt_reader_ioctl_clear() - Clear ioctl command.
693  * @cli: Non-NULL pointer to vinstr client.
694  *
695  * Return: 0 on success, else error code.
696  */
kbasep_vinstr_hwcnt_reader_ioctl_clear(struct kbase_vinstr_client * cli)697 static long kbasep_vinstr_hwcnt_reader_ioctl_clear(
698 	struct kbase_vinstr_client *cli)
699 {
700 	int errcode;
701 
702 	mutex_lock(&cli->vctx->lock);
703 
704 	errcode = kbasep_vinstr_client_clear(cli);
705 
706 	mutex_unlock(&cli->vctx->lock);
707 	return errcode;
708 }
709 
710 /**
711  * kbasep_vinstr_hwcnt_reader_ioctl_get_buffer() - Get buffer ioctl command.
712  * @cli:    Non-NULL pointer to vinstr client.
713  * @buffer: Non-NULL pointer to userspace buffer.
714  * @size:   Size of buffer.
715  *
716  * Return: 0 on success, else error code.
717  */
kbasep_vinstr_hwcnt_reader_ioctl_get_buffer(struct kbase_vinstr_client * cli,void __user * buffer,size_t size)718 static long kbasep_vinstr_hwcnt_reader_ioctl_get_buffer(
719 	struct kbase_vinstr_client *cli,
720 	void __user *buffer,
721 	size_t size)
722 {
723 	unsigned int meta_idx = atomic_read(&cli->meta_idx);
724 	unsigned int idx = meta_idx % cli->dump_bufs.buf_cnt;
725 
726 	struct kbase_hwcnt_reader_metadata *meta = &cli->dump_bufs_meta[idx];
727 	const size_t meta_size = sizeof(struct kbase_hwcnt_reader_metadata);
728 	const size_t min_size = min(size, meta_size);
729 
730 	/* Metadata sanity check. */
731 	WARN_ON(idx != meta->buffer_idx);
732 
733 	/* Check if there is any buffer available. */
734 	if (unlikely(atomic_read(&cli->write_idx) == meta_idx))
735 		return -EAGAIN;
736 
737 	/* Check if previously taken buffer was put back. */
738 	if (unlikely(atomic_read(&cli->read_idx) != meta_idx))
739 		return -EBUSY;
740 
741 	/* Clear user buffer to zero. */
742 	if (unlikely(meta_size < size && clear_user(buffer, size)))
743 		return -EFAULT;
744 
745 	/* Copy next available buffer's metadata to user. */
746 	if (unlikely(copy_to_user(buffer, meta, min_size)))
747 		return -EFAULT;
748 
749 	/* Compare exchange meta idx to protect against concurrent getters */
750 	if (meta_idx != atomic_cmpxchg(&cli->meta_idx, meta_idx, meta_idx + 1))
751 		return -EBUSY;
752 
753 	return 0;
754 }
755 
756 /**
757  * kbasep_vinstr_hwcnt_reader_ioctl_put_buffer() - Put buffer ioctl command.
758  * @cli:    Non-NULL pointer to vinstr client.
759  * @buffer: Non-NULL pointer to userspace buffer.
760  * @size:   Size of buffer.
761  *
762  * Return: 0 on success, else error code.
763  */
kbasep_vinstr_hwcnt_reader_ioctl_put_buffer(struct kbase_vinstr_client * cli,void __user * buffer,size_t size)764 static long kbasep_vinstr_hwcnt_reader_ioctl_put_buffer(
765 	struct kbase_vinstr_client *cli,
766 	void __user *buffer,
767 	size_t size)
768 {
769 	unsigned int read_idx = atomic_read(&cli->read_idx);
770 	unsigned int idx = read_idx % cli->dump_bufs.buf_cnt;
771 
772 	struct kbase_hwcnt_reader_metadata *meta;
773 	const size_t meta_size = sizeof(struct kbase_hwcnt_reader_metadata);
774 	const size_t max_size = max(size, meta_size);
775 	int ret = 0;
776 	u8 stack_kbuf[64];
777 	u8 *kbuf = NULL;
778 	size_t i;
779 
780 	/* Check if any buffer was taken. */
781 	if (unlikely(atomic_read(&cli->meta_idx) == read_idx))
782 		return -EPERM;
783 
784 	if (likely(max_size <= sizeof(stack_kbuf))) {
785 		/* Use stack buffer when the size is small enough. */
786 		if (unlikely(meta_size > size))
787 			memset(stack_kbuf, 0, sizeof(stack_kbuf));
788 		kbuf = stack_kbuf;
789 	} else {
790 		kbuf = kzalloc(max_size, GFP_KERNEL);
791 		if (unlikely(!kbuf))
792 			return -ENOMEM;
793 	}
794 
795 	/*
796 	 * Copy user buffer to zero cleared kernel buffer which has enough
797 	 * space for both user buffer and kernel metadata.
798 	 */
799 	if (unlikely(copy_from_user(kbuf, buffer, size))) {
800 		ret = -EFAULT;
801 		goto out;
802 	}
803 
804 	/*
805 	 * Make sure any "extra" data passed from userspace is zero.
806 	 * It's meaningful only in case meta_size < size.
807 	 */
808 	for (i = meta_size; i < size; i++) {
809 		/* Check if user data beyond meta size is zero. */
810 		if (unlikely(kbuf[i] != 0)) {
811 			ret = -EINVAL;
812 			goto out;
813 		}
814 	}
815 
816 	/* Check if correct buffer is put back. */
817 	meta = (struct kbase_hwcnt_reader_metadata *)kbuf;
818 	if (unlikely(idx != meta->buffer_idx)) {
819 		ret = -EINVAL;
820 		goto out;
821 	}
822 
823 	/* Compare exchange read idx to protect against concurrent putters */
824 	if (read_idx !=
825 	    atomic_cmpxchg(&cli->read_idx, read_idx, read_idx + 1)) {
826 		ret = -EPERM;
827 		goto out;
828 	}
829 
830 out:
831 	if (unlikely(kbuf != stack_kbuf))
832 		kfree(kbuf);
833 	return ret;
834 }
835 
836 /**
837  * kbasep_vinstr_hwcnt_reader_ioctl_set_interval() - Set interval ioctl command.
838  * @cli:      Non-NULL pointer to vinstr client.
839  * @interval: Periodic dumping interval (disable periodic dumping if 0).
840  *
841  * Return: 0 always.
842  */
kbasep_vinstr_hwcnt_reader_ioctl_set_interval(struct kbase_vinstr_client * cli,u32 interval)843 static long kbasep_vinstr_hwcnt_reader_ioctl_set_interval(
844 	struct kbase_vinstr_client *cli,
845 	u32 interval)
846 {
847 	mutex_lock(&cli->vctx->lock);
848 
849 	if ((interval != 0) && (interval < DUMP_INTERVAL_MIN_NS))
850 		interval = DUMP_INTERVAL_MIN_NS;
851 	/* Update the interval, and put in a dummy next dump time */
852 	cli->dump_interval_ns = interval;
853 	cli->next_dump_time_ns = 0;
854 
855 	/*
856 	 * If it's a periodic client, kick off the worker early to do a proper
857 	 * timer reschedule. Return value is ignored, as we don't care if the
858 	 * worker is already queued.
859 	 */
860 	if ((interval != 0) && (cli->vctx->suspend_count == 0))
861 		kbase_hwcnt_virtualizer_queue_work(cli->vctx->hvirt,
862 						   &cli->vctx->dump_work);
863 
864 	mutex_unlock(&cli->vctx->lock);
865 
866 	return 0;
867 }
868 
869 /**
870  * kbasep_vinstr_hwcnt_reader_ioctl_enable_event() - Enable event ioctl command.
871  * @cli:      Non-NULL pointer to vinstr client.
872  * @event_id: ID of event to enable.
873  *
874  * Return: 0 always.
875  */
kbasep_vinstr_hwcnt_reader_ioctl_enable_event(struct kbase_vinstr_client * cli,enum base_hwcnt_reader_event event_id)876 static long kbasep_vinstr_hwcnt_reader_ioctl_enable_event(
877 		struct kbase_vinstr_client *cli,
878 		enum base_hwcnt_reader_event event_id)
879 {
880 	/* No-op, as events aren't supported */
881 	return 0;
882 }
883 
884 /**
885  * kbasep_vinstr_hwcnt_reader_ioctl_disable_event() - Disable event ioctl
886  *                                                    command.
887  * @cli:      Non-NULL pointer to vinstr client.
888  * @event_id: ID of event to disable.
889  *
890  * Return: 0 always.
891  */
kbasep_vinstr_hwcnt_reader_ioctl_disable_event(struct kbase_vinstr_client * cli,enum base_hwcnt_reader_event event_id)892 static long kbasep_vinstr_hwcnt_reader_ioctl_disable_event(
893 	struct kbase_vinstr_client *cli,
894 	enum base_hwcnt_reader_event event_id)
895 {
896 	/* No-op, as events aren't supported */
897 	return 0;
898 }
899 
900 /**
901  * kbasep_vinstr_hwcnt_reader_ioctl_get_hwver() - Get HW version ioctl command.
902  * @cli:   Non-NULL pointer to vinstr client.
903  * @hwver: Non-NULL pointer to user buffer where HW version will be stored.
904  *
905  * Return: 0 on success, else error code.
906  */
kbasep_vinstr_hwcnt_reader_ioctl_get_hwver(struct kbase_vinstr_client * cli,u32 __user * hwver)907 static long kbasep_vinstr_hwcnt_reader_ioctl_get_hwver(
908 	struct kbase_vinstr_client *cli,
909 	u32 __user *hwver)
910 {
911 	u32 ver = 5;
912 	const enum kbase_hwcnt_gpu_group_type type =
913 		kbase_hwcnt_metadata_group_type(cli->vctx->metadata, 0);
914 
915 	if (WARN_ON(type != KBASE_HWCNT_GPU_GROUP_TYPE_V5))
916 		return -EINVAL;
917 
918 	return put_user(ver, hwver);
919 }
920 
921 /**
922  * kbasep_vinstr_hwcnt_reader_ioctl_get_api_version() - get API version ioctl
923  *                                                      command.
924  * @cli:    The non-NULL pointer to the client
925  * @arg:    Command's argument.
926  * @size:   Size of arg.
927  *
928  * Return: 0 on success, else error code.
929  */
kbasep_vinstr_hwcnt_reader_ioctl_get_api_version(struct kbase_vinstr_client * cli,unsigned long arg,size_t size)930 static long kbasep_vinstr_hwcnt_reader_ioctl_get_api_version(
931 	struct kbase_vinstr_client *cli, unsigned long arg, size_t size)
932 {
933 	long ret = -EINVAL;
934 
935 	if (size == sizeof(u32)) {
936 		ret = put_user(HWCNT_READER_API, (u32 __user *)arg);
937 	} else if (size == sizeof(struct kbase_hwcnt_reader_api_version)) {
938 		u8 clk_cnt = cli->vctx->metadata->clk_cnt;
939 		unsigned long bytes = 0;
940 		struct kbase_hwcnt_reader_api_version api_version = {
941 			.version = HWCNT_READER_API,
942 			.features = KBASE_HWCNT_READER_API_VERSION_NO_FEATURE,
943 		};
944 
945 		if (clk_cnt > 0)
946 			api_version.features |=
947 			    KBASE_HWCNT_READER_API_VERSION_FEATURE_CYCLES_TOP;
948 		if (clk_cnt > 1)
949 			api_version.features |=
950 			    KBASE_HWCNT_READER_API_VERSION_FEATURE_CYCLES_SHADER_CORES;
951 
952 		bytes = copy_to_user(
953 			(void __user *)arg, &api_version, sizeof(api_version));
954 
955 		/* copy_to_user returns zero in case of success.
956 		 * If it fails, it returns the number of bytes that could NOT be copied
957 		 */
958 		if (bytes == 0)
959 			ret = 0;
960 		else
961 			ret = -EFAULT;
962 	}
963 	return ret;
964 }
965 
966 /**
967  * kbasep_vinstr_hwcnt_reader_ioctl() - hwcnt reader's ioctl.
968  * @filp:   Non-NULL pointer to file structure.
969  * @cmd:    User command.
970  * @arg:    Command's argument.
971  *
972  * Return: 0 on success, else error code.
973  */
kbasep_vinstr_hwcnt_reader_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)974 static long kbasep_vinstr_hwcnt_reader_ioctl(
975 	struct file *filp,
976 	unsigned int cmd,
977 	unsigned long arg)
978 {
979 	long rcode;
980 	struct kbase_vinstr_client *cli;
981 
982 	if (!filp || (_IOC_TYPE(cmd) != KBASE_HWCNT_READER))
983 		return -EINVAL;
984 
985 	cli = filp->private_data;
986 	if (!cli)
987 		return -EINVAL;
988 
989 	switch (_IOC_NR(cmd)) {
990 	case _IOC_NR(KBASE_HWCNT_READER_GET_API_VERSION):
991 		rcode = kbasep_vinstr_hwcnt_reader_ioctl_get_api_version(
992 				cli, arg, _IOC_SIZE(cmd));
993 		break;
994 	case _IOC_NR(KBASE_HWCNT_READER_GET_HWVER):
995 		rcode = kbasep_vinstr_hwcnt_reader_ioctl_get_hwver(
996 			cli, (u32 __user *)arg);
997 		break;
998 	case _IOC_NR(KBASE_HWCNT_READER_GET_BUFFER_SIZE):
999 		rcode = put_user((u32)cli->vctx->metadata_user->dump_buf_bytes,
1000 				 (u32 __user *)arg);
1001 		break;
1002 	case _IOC_NR(KBASE_HWCNT_READER_DUMP):
1003 		rcode = kbasep_vinstr_hwcnt_reader_ioctl_dump(cli);
1004 		break;
1005 	case _IOC_NR(KBASE_HWCNT_READER_CLEAR):
1006 		rcode = kbasep_vinstr_hwcnt_reader_ioctl_clear(cli);
1007 		break;
1008 	case _IOC_NR(KBASE_HWCNT_READER_GET_BUFFER):
1009 		rcode = kbasep_vinstr_hwcnt_reader_ioctl_get_buffer(
1010 			cli, (void __user *)arg, _IOC_SIZE(cmd));
1011 		break;
1012 	case _IOC_NR(KBASE_HWCNT_READER_PUT_BUFFER):
1013 		rcode = kbasep_vinstr_hwcnt_reader_ioctl_put_buffer(
1014 			cli, (void __user *)arg, _IOC_SIZE(cmd));
1015 		break;
1016 	case _IOC_NR(KBASE_HWCNT_READER_SET_INTERVAL):
1017 		rcode = kbasep_vinstr_hwcnt_reader_ioctl_set_interval(
1018 			cli, (u32)arg);
1019 		break;
1020 	case _IOC_NR(KBASE_HWCNT_READER_ENABLE_EVENT):
1021 		rcode = kbasep_vinstr_hwcnt_reader_ioctl_enable_event(
1022 			cli, (enum base_hwcnt_reader_event)arg);
1023 		break;
1024 	case _IOC_NR(KBASE_HWCNT_READER_DISABLE_EVENT):
1025 		rcode = kbasep_vinstr_hwcnt_reader_ioctl_disable_event(
1026 			cli, (enum base_hwcnt_reader_event)arg);
1027 		break;
1028 	default:
1029 		pr_warn("Unknown HWCNT ioctl 0x%x nr:%d", cmd, _IOC_NR(cmd));
1030 		rcode = -EINVAL;
1031 		break;
1032 	}
1033 
1034 	return rcode;
1035 }
1036 
1037 /**
1038  * kbasep_vinstr_hwcnt_reader_poll() - hwcnt reader's poll.
1039  * @filp: Non-NULL pointer to file structure.
1040  * @wait: Non-NULL pointer to poll table.
1041  *
1042  * Return: EPOLLIN | EPOLLRDNORM if data can be read without blocking, 0 if
1043  *         data can not be read without blocking, else EPOLLHUP | EPOLLERR.
1044  */
kbasep_vinstr_hwcnt_reader_poll(struct file * filp,poll_table * wait)1045 static __poll_t kbasep_vinstr_hwcnt_reader_poll(struct file *filp, poll_table *wait)
1046 {
1047 	struct kbase_vinstr_client *cli;
1048 
1049 	if (!filp || !wait)
1050 		return EPOLLHUP | EPOLLERR;
1051 
1052 	cli = filp->private_data;
1053 	if (!cli)
1054 		return EPOLLHUP | EPOLLERR;
1055 
1056 	poll_wait(filp, &cli->waitq, wait);
1057 	if (kbasep_vinstr_hwcnt_reader_buffer_ready(cli))
1058 		return EPOLLIN | EPOLLRDNORM;
1059 
1060 	return (__poll_t)0;
1061 }
1062 
1063 /**
1064  * kbasep_vinstr_hwcnt_reader_mmap() - hwcnt reader's mmap.
1065  * @filp: Non-NULL pointer to file structure.
1066  * @vma:  Non-NULL pointer to vma structure.
1067  *
1068  * Return: 0 on success, else error code.
1069  */
kbasep_vinstr_hwcnt_reader_mmap(struct file * filp,struct vm_area_struct * vma)1070 static int kbasep_vinstr_hwcnt_reader_mmap(
1071 	struct file *filp,
1072 	struct vm_area_struct *vma)
1073 {
1074 	struct kbase_vinstr_client *cli;
1075 	unsigned long vm_size, size, addr, pfn, offset;
1076 
1077 	if (!filp || !vma)
1078 		return -EINVAL;
1079 
1080 	cli = filp->private_data;
1081 	if (!cli)
1082 		return -EINVAL;
1083 
1084 	vm_size = vma->vm_end - vma->vm_start;
1085 
1086 	/* The mapping is allowed to span the entirety of the page allocation,
1087 	 * not just the chunk where the dump buffers are allocated.
1088 	 * This accommodates the corner case where the combined size of the
1089 	 * dump buffers is smaller than a single page.
1090 	 * This does not pose a security risk as the pages are zeroed on
1091 	 * allocation, and anything out of bounds of the dump buffers is never
1092 	 * written to.
1093 	 */
1094 	size = (1ull << cli->dump_bufs.page_order) * PAGE_SIZE;
1095 
1096 	if (vma->vm_pgoff > (size >> PAGE_SHIFT))
1097 		return -EINVAL;
1098 
1099 	offset = vma->vm_pgoff << PAGE_SHIFT;
1100 	if (vm_size > size - offset)
1101 		return -EINVAL;
1102 
1103 	addr = __pa(cli->dump_bufs.page_addr + offset);
1104 	pfn = addr >> PAGE_SHIFT;
1105 
1106 	return remap_pfn_range(
1107 		vma, vma->vm_start, pfn, vm_size, vma->vm_page_prot);
1108 }
1109 
1110 /**
1111  * kbasep_vinstr_hwcnt_reader_release() - hwcnt reader's release.
1112  * @inode: Non-NULL pointer to inode structure.
1113  * @filp:  Non-NULL pointer to file structure.
1114  *
1115  * Return: 0 always.
1116  */
kbasep_vinstr_hwcnt_reader_release(struct inode * inode,struct file * filp)1117 static int kbasep_vinstr_hwcnt_reader_release(struct inode *inode,
1118 	struct file *filp)
1119 {
1120 	struct kbase_vinstr_client *vcli = filp->private_data;
1121 
1122 	mutex_lock(&vcli->vctx->lock);
1123 
1124 	vcli->vctx->client_count--;
1125 	list_del(&vcli->node);
1126 
1127 	mutex_unlock(&vcli->vctx->lock);
1128 
1129 	kbasep_vinstr_client_destroy(vcli);
1130 
1131 	return 0;
1132 }
1133