162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 OR MIT */ 262306a36Sopenharmony_ci/************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright 2021 VMware, Inc., Palo Alto, CA., USA 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 762306a36Sopenharmony_ci * copy of this software and associated documentation files (the 862306a36Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 962306a36Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 1062306a36Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 1162306a36Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 1262306a36Sopenharmony_ci * the following conditions: 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * The above copyright notice and this permission notice (including the 1562306a36Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 1662306a36Sopenharmony_ci * of the Software. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1962306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2062306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 2162306a36Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 2262306a36Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2362306a36Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 2462306a36Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci **************************************************************************/ 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#ifndef _VMWGFX_MKSSTAT_H_ 2962306a36Sopenharmony_ci#define _VMWGFX_MKSSTAT_H_ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include <asm/page.h> 3262306a36Sopenharmony_ci#include <linux/kconfig.h> 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* Reservation marker for mksstat pid's */ 3562306a36Sopenharmony_ci#define MKSSTAT_PID_RESERVED -1 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS) 3862306a36Sopenharmony_ci/* 3962306a36Sopenharmony_ci * Kernel-internal mksGuestStat counters. The order of this enum dictates the 4062306a36Sopenharmony_ci * order of instantiation of these counters in the mksGuestStat pages. 4162306a36Sopenharmony_ci */ 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_citypedef enum { 4462306a36Sopenharmony_ci MKSSTAT_KERN_EXECBUF, /* vmw_execbuf_ioctl */ 4562306a36Sopenharmony_ci MKSSTAT_KERN_COTABLE_RESIZE, 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci MKSSTAT_KERN_COUNT /* Reserved entry; always last */ 4862306a36Sopenharmony_ci} mksstat_kern_stats_t; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/** 5162306a36Sopenharmony_ci * vmw_mksstat_get_kern_pstat: Computes the address of the MKSGuestStatCounterTime 5262306a36Sopenharmony_ci * array from the address of the base page. 5362306a36Sopenharmony_ci * 5462306a36Sopenharmony_ci * @page_addr: Pointer to the base page. 5562306a36Sopenharmony_ci * Return: Pointer to the MKSGuestStatCounterTime array. 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic inline void *vmw_mksstat_get_kern_pstat(void *page_addr) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci return page_addr + PAGE_SIZE * 1; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/** 6462306a36Sopenharmony_ci * vmw_mksstat_get_kern_pinfo: Computes the address of the MKSGuestStatInfoEntry 6562306a36Sopenharmony_ci * array from the address of the base page. 6662306a36Sopenharmony_ci * 6762306a36Sopenharmony_ci * @page_addr: Pointer to the base page. 6862306a36Sopenharmony_ci * Return: Pointer to the MKSGuestStatInfoEntry array. 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic inline void *vmw_mksstat_get_kern_pinfo(void *page_addr) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci return page_addr + PAGE_SIZE * 2; 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/** 7762306a36Sopenharmony_ci * vmw_mksstat_get_kern_pstrs: Computes the address of the mksGuestStat strings 7862306a36Sopenharmony_ci * sequence from the address of the base page. 7962306a36Sopenharmony_ci * 8062306a36Sopenharmony_ci * @page_addr: Pointer to the base page. 8162306a36Sopenharmony_ci * Return: Pointer to the mksGuestStat strings sequence. 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic inline void *vmw_mksstat_get_kern_pstrs(void *page_addr) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci return page_addr + PAGE_SIZE * 3; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/* 9062306a36Sopenharmony_ci * MKS_STAT_TIME_DECL/PUSH/POP macros to be used in timer-counted routines. 9162306a36Sopenharmony_ci */ 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistruct mksstat_timer_t { 9462306a36Sopenharmony_ci/* mutable */ mksstat_kern_stats_t old_top; 9562306a36Sopenharmony_ci const u64 t0; 9662306a36Sopenharmony_ci const int slot; 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci#define MKS_STAT_TIME_DECL(kern_cntr) \ 10062306a36Sopenharmony_ci struct mksstat_timer_t _##kern_cntr = { \ 10162306a36Sopenharmony_ci .t0 = rdtsc(), \ 10262306a36Sopenharmony_ci .slot = vmw_mksstat_get_kern_slot(current->pid, dev_priv) \ 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci#define MKS_STAT_TIME_PUSH(kern_cntr) \ 10662306a36Sopenharmony_ci do { \ 10762306a36Sopenharmony_ci if (_##kern_cntr.slot >= 0) { \ 10862306a36Sopenharmony_ci _##kern_cntr.old_top = dev_priv->mksstat_kern_top_timer[_##kern_cntr.slot]; \ 10962306a36Sopenharmony_ci dev_priv->mksstat_kern_top_timer[_##kern_cntr.slot] = kern_cntr; \ 11062306a36Sopenharmony_ci } \ 11162306a36Sopenharmony_ci } while (0) 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#define MKS_STAT_TIME_POP(kern_cntr) \ 11462306a36Sopenharmony_ci do { \ 11562306a36Sopenharmony_ci if (_##kern_cntr.slot >= 0) { \ 11662306a36Sopenharmony_ci const pid_t pid = atomic_cmpxchg(&dev_priv->mksstat_kern_pids[_##kern_cntr.slot], current->pid, MKSSTAT_PID_RESERVED); \ 11762306a36Sopenharmony_ci dev_priv->mksstat_kern_top_timer[_##kern_cntr.slot] = _##kern_cntr.old_top; \ 11862306a36Sopenharmony_ci \ 11962306a36Sopenharmony_ci if (pid == current->pid) { \ 12062306a36Sopenharmony_ci const u64 dt = rdtsc() - _##kern_cntr.t0; \ 12162306a36Sopenharmony_ci MKSGuestStatCounterTime *pstat; \ 12262306a36Sopenharmony_ci \ 12362306a36Sopenharmony_ci BUG_ON(!dev_priv->mksstat_kern_pages[_##kern_cntr.slot]); \ 12462306a36Sopenharmony_ci \ 12562306a36Sopenharmony_ci pstat = vmw_mksstat_get_kern_pstat(page_address(dev_priv->mksstat_kern_pages[_##kern_cntr.slot])); \ 12662306a36Sopenharmony_ci \ 12762306a36Sopenharmony_ci atomic64_inc(&pstat[kern_cntr].counter.count); \ 12862306a36Sopenharmony_ci atomic64_add(dt, &pstat[kern_cntr].selfCycles); \ 12962306a36Sopenharmony_ci atomic64_add(dt, &pstat[kern_cntr].totalCycles); \ 13062306a36Sopenharmony_ci \ 13162306a36Sopenharmony_ci if (_##kern_cntr.old_top != MKSSTAT_KERN_COUNT) \ 13262306a36Sopenharmony_ci atomic64_sub(dt, &pstat[_##kern_cntr.old_top].selfCycles); \ 13362306a36Sopenharmony_ci \ 13462306a36Sopenharmony_ci atomic_set(&dev_priv->mksstat_kern_pids[_##kern_cntr.slot], current->pid); \ 13562306a36Sopenharmony_ci } \ 13662306a36Sopenharmony_ci } \ 13762306a36Sopenharmony_ci } while (0) 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci#else 14062306a36Sopenharmony_ci#define MKS_STAT_TIME_DECL(kern_cntr) 14162306a36Sopenharmony_ci#define MKS_STAT_TIME_PUSH(kern_cntr) 14262306a36Sopenharmony_ci#define MKS_STAT_TIME_POP(kern_cntr) 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci#endif /* IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS */ 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#endif 147