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