xref: /openbmc/linux/drivers/gpu/drm/vmwgfx/vmwgfx_mksstat.h (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
17a7a933eSMartin Krastev /* SPDX-License-Identifier: GPL-2.0 OR MIT */
27a7a933eSMartin Krastev /**************************************************************************
37a7a933eSMartin Krastev  *
47a7a933eSMartin Krastev  * Copyright 2021 VMware, Inc., Palo Alto, CA., USA
57a7a933eSMartin Krastev  *
67a7a933eSMartin Krastev  * Permission is hereby granted, free of charge, to any person obtaining a
77a7a933eSMartin Krastev  * copy of this software and associated documentation files (the
87a7a933eSMartin Krastev  * "Software"), to deal in the Software without restriction, including
97a7a933eSMartin Krastev  * without limitation the rights to use, copy, modify, merge, publish,
107a7a933eSMartin Krastev  * distribute, sub license, and/or sell copies of the Software, and to
117a7a933eSMartin Krastev  * permit persons to whom the Software is furnished to do so, subject to
127a7a933eSMartin Krastev  * the following conditions:
137a7a933eSMartin Krastev  *
147a7a933eSMartin Krastev  * The above copyright notice and this permission notice (including the
157a7a933eSMartin Krastev  * next paragraph) shall be included in all copies or substantial portions
167a7a933eSMartin Krastev  * of the Software.
177a7a933eSMartin Krastev  *
187a7a933eSMartin Krastev  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
197a7a933eSMartin Krastev  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
207a7a933eSMartin Krastev  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
217a7a933eSMartin Krastev  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
227a7a933eSMartin Krastev  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
237a7a933eSMartin Krastev  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
247a7a933eSMartin Krastev  * USE OR OTHER DEALINGS IN THE SOFTWARE.
257a7a933eSMartin Krastev  *
267a7a933eSMartin Krastev  **************************************************************************/
277a7a933eSMartin Krastev 
287a7a933eSMartin Krastev #ifndef _VMWGFX_MKSSTAT_H_
297a7a933eSMartin Krastev #define _VMWGFX_MKSSTAT_H_
307a7a933eSMartin Krastev 
317a7a933eSMartin Krastev #include <asm/page.h>
32*4bb50606SZack Rusin #include <linux/kconfig.h>
337a7a933eSMartin Krastev 
347a7a933eSMartin Krastev /* Reservation marker for mksstat pid's */
357a7a933eSMartin Krastev #define MKSSTAT_PID_RESERVED -1
367a7a933eSMartin Krastev 
377a7a933eSMartin Krastev #if IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS)
387a7a933eSMartin Krastev /*
397a7a933eSMartin Krastev  * Kernel-internal mksGuestStat counters. The order of this enum dictates the
407a7a933eSMartin Krastev  * order of instantiation of these counters in the mksGuestStat pages.
417a7a933eSMartin Krastev  */
427a7a933eSMartin Krastev 
437a7a933eSMartin Krastev typedef enum {
447a7a933eSMartin Krastev 	MKSSTAT_KERN_EXECBUF, /* vmw_execbuf_ioctl */
45*4bb50606SZack Rusin 	MKSSTAT_KERN_COTABLE_RESIZE,
467a7a933eSMartin Krastev 
477a7a933eSMartin Krastev 	MKSSTAT_KERN_COUNT /* Reserved entry; always last */
487a7a933eSMartin Krastev } mksstat_kern_stats_t;
497a7a933eSMartin Krastev 
507a7a933eSMartin Krastev /**
517a7a933eSMartin Krastev  * vmw_mksstat_get_kern_pstat: Computes the address of the MKSGuestStatCounterTime
527a7a933eSMartin Krastev  * array from the address of the base page.
537a7a933eSMartin Krastev  *
547a7a933eSMartin Krastev  * @page_addr: Pointer to the base page.
557a7a933eSMartin Krastev  * Return: Pointer to the MKSGuestStatCounterTime array.
567a7a933eSMartin Krastev  */
577a7a933eSMartin Krastev 
vmw_mksstat_get_kern_pstat(void * page_addr)587a7a933eSMartin Krastev static inline void *vmw_mksstat_get_kern_pstat(void *page_addr)
597a7a933eSMartin Krastev {
607a7a933eSMartin Krastev 	return page_addr + PAGE_SIZE * 1;
617a7a933eSMartin Krastev }
627a7a933eSMartin Krastev 
637a7a933eSMartin Krastev /**
647a7a933eSMartin Krastev  * vmw_mksstat_get_kern_pinfo: Computes the address of the MKSGuestStatInfoEntry
657a7a933eSMartin Krastev  * array from the address of the base page.
667a7a933eSMartin Krastev  *
677a7a933eSMartin Krastev  * @page_addr: Pointer to the base page.
687a7a933eSMartin Krastev  * Return: Pointer to the MKSGuestStatInfoEntry array.
697a7a933eSMartin Krastev  */
707a7a933eSMartin Krastev 
vmw_mksstat_get_kern_pinfo(void * page_addr)717a7a933eSMartin Krastev static inline void *vmw_mksstat_get_kern_pinfo(void *page_addr)
727a7a933eSMartin Krastev {
737a7a933eSMartin Krastev 	return page_addr + PAGE_SIZE * 2;
747a7a933eSMartin Krastev }
757a7a933eSMartin Krastev 
767a7a933eSMartin Krastev /**
777a7a933eSMartin Krastev  * vmw_mksstat_get_kern_pstrs: Computes the address of the mksGuestStat strings
787a7a933eSMartin Krastev  * sequence from the address of the base page.
797a7a933eSMartin Krastev  *
807a7a933eSMartin Krastev  * @page_addr: Pointer to the base page.
817a7a933eSMartin Krastev  * Return: Pointer to the mksGuestStat strings sequence.
827a7a933eSMartin Krastev  */
837a7a933eSMartin Krastev 
vmw_mksstat_get_kern_pstrs(void * page_addr)847a7a933eSMartin Krastev static inline void *vmw_mksstat_get_kern_pstrs(void *page_addr)
857a7a933eSMartin Krastev {
867a7a933eSMartin Krastev 	return page_addr + PAGE_SIZE * 3;
877a7a933eSMartin Krastev }
887a7a933eSMartin Krastev 
897a7a933eSMartin Krastev /*
907a7a933eSMartin Krastev  * MKS_STAT_TIME_DECL/PUSH/POP macros to be used in timer-counted routines.
917a7a933eSMartin Krastev  */
927a7a933eSMartin Krastev 
937a7a933eSMartin Krastev struct mksstat_timer_t {
947a7a933eSMartin Krastev /* mutable */ mksstat_kern_stats_t old_top;
957a7a933eSMartin Krastev 	const u64 t0;
967a7a933eSMartin Krastev 	const int slot;
977a7a933eSMartin Krastev };
987a7a933eSMartin Krastev 
997a7a933eSMartin Krastev #define MKS_STAT_TIME_DECL(kern_cntr)                                     \
1007a7a933eSMartin Krastev 	struct mksstat_timer_t _##kern_cntr = {                           \
1017a7a933eSMartin Krastev 		.t0 = rdtsc(),                                            \
1027a7a933eSMartin Krastev 		.slot = vmw_mksstat_get_kern_slot(current->pid, dev_priv) \
1037a7a933eSMartin Krastev 	}
1047a7a933eSMartin Krastev 
1057a7a933eSMartin Krastev #define MKS_STAT_TIME_PUSH(kern_cntr)                                                               \
1067a7a933eSMartin Krastev 	do {                                                                                        \
1077a7a933eSMartin Krastev 		if (_##kern_cntr.slot >= 0) {                                                       \
1087a7a933eSMartin Krastev 			_##kern_cntr.old_top = dev_priv->mksstat_kern_top_timer[_##kern_cntr.slot]; \
1097a7a933eSMartin Krastev 			dev_priv->mksstat_kern_top_timer[_##kern_cntr.slot] = kern_cntr;            \
1107a7a933eSMartin Krastev 		}                                                                                   \
1117a7a933eSMartin Krastev 	} while (0)
1127a7a933eSMartin Krastev 
1137a7a933eSMartin Krastev #define MKS_STAT_TIME_POP(kern_cntr)                                                                                                           \
1147a7a933eSMartin Krastev 	do {                                                                                                                                   \
1157a7a933eSMartin Krastev 		if (_##kern_cntr.slot >= 0) {                                                                                                  \
1167a7a933eSMartin Krastev 			const pid_t pid = atomic_cmpxchg(&dev_priv->mksstat_kern_pids[_##kern_cntr.slot], current->pid, MKSSTAT_PID_RESERVED); \
1177a7a933eSMartin Krastev 			dev_priv->mksstat_kern_top_timer[_##kern_cntr.slot] = _##kern_cntr.old_top;                                            \
1187a7a933eSMartin Krastev 			                                                                                                                       \
1197a7a933eSMartin Krastev 			if (pid == current->pid) {                                                                                             \
1207a7a933eSMartin Krastev 				const u64 dt = rdtsc() - _##kern_cntr.t0;                                                                      \
1217a7a933eSMartin Krastev 				MKSGuestStatCounterTime *pstat;                                                                                \
1227a7a933eSMartin Krastev 				                                                                                                               \
1237a7a933eSMartin Krastev 				BUG_ON(!dev_priv->mksstat_kern_pages[_##kern_cntr.slot]);                                                      \
1247a7a933eSMartin Krastev 				                                                                                                               \
1257a7a933eSMartin Krastev 				pstat = vmw_mksstat_get_kern_pstat(page_address(dev_priv->mksstat_kern_pages[_##kern_cntr.slot]));             \
1267a7a933eSMartin Krastev 				                                                                                                               \
1277a7a933eSMartin Krastev 				atomic64_inc(&pstat[kern_cntr].counter.count);                                                                 \
1287a7a933eSMartin Krastev 				atomic64_add(dt, &pstat[kern_cntr].selfCycles);                                                                \
1297a7a933eSMartin Krastev 				atomic64_add(dt, &pstat[kern_cntr].totalCycles);                                                               \
1307a7a933eSMartin Krastev 				                                                                                                               \
1317a7a933eSMartin Krastev 				if (_##kern_cntr.old_top != MKSSTAT_KERN_COUNT)                                                                \
1327a7a933eSMartin Krastev 					atomic64_sub(dt, &pstat[_##kern_cntr.old_top].selfCycles);                                             \
1337a7a933eSMartin Krastev 					                                                                                                       \
1347a7a933eSMartin Krastev 				atomic_set(&dev_priv->mksstat_kern_pids[_##kern_cntr.slot], current->pid);                                     \
1357a7a933eSMartin Krastev 			}                                                                                                                      \
1367a7a933eSMartin Krastev 		}                                                                                                                              \
1377a7a933eSMartin Krastev 	} while (0)
1387a7a933eSMartin Krastev 
1397a7a933eSMartin Krastev #else
1407a7a933eSMartin Krastev #define MKS_STAT_TIME_DECL(kern_cntr)
1417a7a933eSMartin Krastev #define MKS_STAT_TIME_PUSH(kern_cntr)
1427a7a933eSMartin Krastev #define MKS_STAT_TIME_POP(kern_cntr)
1437a7a933eSMartin Krastev 
1447a7a933eSMartin Krastev #endif /* IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS */
1457a7a933eSMartin Krastev 
1467a7a933eSMartin Krastev #endif
147