cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

etnaviv_perfmon.c (13331B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2017 Etnaviv Project
      4 * Copyright (C) 2017 Zodiac Inflight Innovations
      5 */
      6
      7#include "common.xml.h"
      8#include "etnaviv_gpu.h"
      9#include "etnaviv_perfmon.h"
     10#include "state_hi.xml.h"
     11
     12struct etnaviv_pm_domain;
     13
     14struct etnaviv_pm_signal {
     15	char name[64];
     16	u32 data;
     17
     18	u32 (*sample)(struct etnaviv_gpu *gpu,
     19		      const struct etnaviv_pm_domain *domain,
     20		      const struct etnaviv_pm_signal *signal);
     21};
     22
     23struct etnaviv_pm_domain {
     24	char name[64];
     25
     26	/* profile register */
     27	u32 profile_read;
     28	u32 profile_config;
     29
     30	u8 nr_signals;
     31	const struct etnaviv_pm_signal *signal;
     32};
     33
     34struct etnaviv_pm_domain_meta {
     35	unsigned int feature;
     36	const struct etnaviv_pm_domain *domains;
     37	u32 nr_domains;
     38};
     39
     40static u32 perf_reg_read(struct etnaviv_gpu *gpu,
     41	const struct etnaviv_pm_domain *domain,
     42	const struct etnaviv_pm_signal *signal)
     43{
     44	gpu_write(gpu, domain->profile_config, signal->data);
     45
     46	return gpu_read(gpu, domain->profile_read);
     47}
     48
     49static inline void pipe_select(struct etnaviv_gpu *gpu, u32 clock, unsigned pipe)
     50{
     51	clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);
     52	clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(pipe);
     53
     54	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
     55}
     56
     57static u32 pipe_perf_reg_read(struct etnaviv_gpu *gpu,
     58	const struct etnaviv_pm_domain *domain,
     59	const struct etnaviv_pm_signal *signal)
     60{
     61	u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
     62	u32 value = 0;
     63	unsigned i;
     64
     65	for (i = 0; i < gpu->identity.pixel_pipes; i++) {
     66		pipe_select(gpu, clock, i);
     67		value += perf_reg_read(gpu, domain, signal);
     68	}
     69
     70	/* switch back to pixel pipe 0 to prevent GPU hang */
     71	pipe_select(gpu, clock, 0);
     72
     73	return value;
     74}
     75
     76static u32 pipe_reg_read(struct etnaviv_gpu *gpu,
     77	const struct etnaviv_pm_domain *domain,
     78	const struct etnaviv_pm_signal *signal)
     79{
     80	u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
     81	u32 value = 0;
     82	unsigned i;
     83
     84	for (i = 0; i < gpu->identity.pixel_pipes; i++) {
     85		pipe_select(gpu, clock, i);
     86		value += gpu_read(gpu, signal->data);
     87	}
     88
     89	/* switch back to pixel pipe 0 to prevent GPU hang */
     90	pipe_select(gpu, clock, 0);
     91
     92	return value;
     93}
     94
     95static u32 hi_total_cycle_read(struct etnaviv_gpu *gpu,
     96	const struct etnaviv_pm_domain *domain,
     97	const struct etnaviv_pm_signal *signal)
     98{
     99	u32 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
    100
    101	if (gpu->identity.model == chipModel_GC880 ||
    102		gpu->identity.model == chipModel_GC2000 ||
    103		gpu->identity.model == chipModel_GC2100)
    104		reg = VIVS_MC_PROFILE_CYCLE_COUNTER;
    105
    106	return gpu_read(gpu, reg);
    107}
    108
    109static u32 hi_total_idle_cycle_read(struct etnaviv_gpu *gpu,
    110	const struct etnaviv_pm_domain *domain,
    111	const struct etnaviv_pm_signal *signal)
    112{
    113	u32 reg = VIVS_HI_PROFILE_IDLE_CYCLES;
    114
    115	if (gpu->identity.model == chipModel_GC880 ||
    116		gpu->identity.model == chipModel_GC2000 ||
    117		gpu->identity.model == chipModel_GC2100)
    118		reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
    119
    120	return gpu_read(gpu, reg);
    121}
    122
    123static const struct etnaviv_pm_domain doms_3d[] = {
    124	{
    125		.name = "HI",
    126		.profile_read = VIVS_MC_PROFILE_HI_READ,
    127		.profile_config = VIVS_MC_PROFILE_CONFIG2,
    128		.nr_signals = 7,
    129		.signal = (const struct etnaviv_pm_signal[]) {
    130			{
    131				"TOTAL_READ_BYTES8",
    132				VIVS_HI_PROFILE_READ_BYTES8,
    133				&pipe_reg_read,
    134			},
    135			{
    136				"TOTAL_WRITE_BYTES8",
    137				VIVS_HI_PROFILE_WRITE_BYTES8,
    138				&pipe_reg_read,
    139			},
    140			{
    141				"TOTAL_CYCLES",
    142				0,
    143				&hi_total_cycle_read
    144			},
    145			{
    146				"IDLE_CYCLES",
    147				0,
    148				&hi_total_idle_cycle_read
    149			},
    150			{
    151				"AXI_CYCLES_READ_REQUEST_STALLED",
    152				VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED,
    153				&perf_reg_read
    154			},
    155			{
    156				"AXI_CYCLES_WRITE_REQUEST_STALLED",
    157				VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED,
    158				&perf_reg_read
    159			},
    160			{
    161				"AXI_CYCLES_WRITE_DATA_STALLED",
    162				VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED,
    163				&perf_reg_read
    164			}
    165		}
    166	},
    167	{
    168		.name = "PE",
    169		.profile_read = VIVS_MC_PROFILE_PE_READ,
    170		.profile_config = VIVS_MC_PROFILE_CONFIG0,
    171		.nr_signals = 4,
    172		.signal = (const struct etnaviv_pm_signal[]) {
    173			{
    174				"PIXEL_COUNT_KILLED_BY_COLOR_PIPE",
    175				VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE,
    176				&pipe_perf_reg_read
    177			},
    178			{
    179				"PIXEL_COUNT_KILLED_BY_DEPTH_PIPE",
    180				VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE,
    181				&pipe_perf_reg_read
    182			},
    183			{
    184				"PIXEL_COUNT_DRAWN_BY_COLOR_PIPE",
    185				VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE,
    186				&pipe_perf_reg_read
    187			},
    188			{
    189				"PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE",
    190				VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE,
    191				&pipe_perf_reg_read
    192			}
    193		}
    194	},
    195	{
    196		.name = "SH",
    197		.profile_read = VIVS_MC_PROFILE_SH_READ,
    198		.profile_config = VIVS_MC_PROFILE_CONFIG0,
    199		.nr_signals = 9,
    200		.signal = (const struct etnaviv_pm_signal[]) {
    201			{
    202				"SHADER_CYCLES",
    203				VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES,
    204				&perf_reg_read
    205			},
    206			{
    207				"PS_INST_COUNTER",
    208				VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER,
    209				&perf_reg_read
    210			},
    211			{
    212				"RENDERED_PIXEL_COUNTER",
    213				VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER,
    214				&perf_reg_read
    215			},
    216			{
    217				"VS_INST_COUNTER",
    218				VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER,
    219				&pipe_perf_reg_read
    220			},
    221			{
    222				"RENDERED_VERTICE_COUNTER",
    223				VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER,
    224				&pipe_perf_reg_read
    225			},
    226			{
    227				"VTX_BRANCH_INST_COUNTER",
    228				VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER,
    229				&pipe_perf_reg_read
    230			},
    231			{
    232				"VTX_TEXLD_INST_COUNTER",
    233				VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER,
    234				&pipe_perf_reg_read
    235			},
    236			{
    237				"PXL_BRANCH_INST_COUNTER",
    238				VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER,
    239				&pipe_perf_reg_read
    240			},
    241			{
    242				"PXL_TEXLD_INST_COUNTER",
    243				VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER,
    244				&pipe_perf_reg_read
    245			}
    246		}
    247	},
    248	{
    249		.name = "PA",
    250		.profile_read = VIVS_MC_PROFILE_PA_READ,
    251		.profile_config = VIVS_MC_PROFILE_CONFIG1,
    252		.nr_signals = 6,
    253		.signal = (const struct etnaviv_pm_signal[]) {
    254			{
    255				"INPUT_VTX_COUNTER",
    256				VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER,
    257				&perf_reg_read
    258			},
    259			{
    260				"INPUT_PRIM_COUNTER",
    261				VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER,
    262				&perf_reg_read
    263			},
    264			{
    265				"OUTPUT_PRIM_COUNTER",
    266				VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER,
    267				&perf_reg_read
    268			},
    269			{
    270				"DEPTH_CLIPPED_COUNTER",
    271				VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER,
    272				&pipe_perf_reg_read
    273			},
    274			{
    275				"TRIVIAL_REJECTED_COUNTER",
    276				VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER,
    277				&pipe_perf_reg_read
    278			},
    279			{
    280				"CULLED_COUNTER",
    281				VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER,
    282				&pipe_perf_reg_read
    283			}
    284		}
    285	},
    286	{
    287		.name = "SE",
    288		.profile_read = VIVS_MC_PROFILE_SE_READ,
    289		.profile_config = VIVS_MC_PROFILE_CONFIG1,
    290		.nr_signals = 2,
    291		.signal = (const struct etnaviv_pm_signal[]) {
    292			{
    293				"CULLED_TRIANGLE_COUNT",
    294				VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT,
    295				&perf_reg_read
    296			},
    297			{
    298				"CULLED_LINES_COUNT",
    299				VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT,
    300				&perf_reg_read
    301			}
    302		}
    303	},
    304	{
    305		.name = "RA",
    306		.profile_read = VIVS_MC_PROFILE_RA_READ,
    307		.profile_config = VIVS_MC_PROFILE_CONFIG1,
    308		.nr_signals = 7,
    309		.signal = (const struct etnaviv_pm_signal[]) {
    310			{
    311				"VALID_PIXEL_COUNT",
    312				VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT,
    313				&perf_reg_read
    314			},
    315			{
    316				"TOTAL_QUAD_COUNT",
    317				VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT,
    318				&perf_reg_read
    319			},
    320			{
    321				"VALID_QUAD_COUNT_AFTER_EARLY_Z",
    322				VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z,
    323				&perf_reg_read
    324			},
    325			{
    326				"TOTAL_PRIMITIVE_COUNT",
    327				VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT,
    328				&perf_reg_read
    329			},
    330			{
    331				"PIPE_CACHE_MISS_COUNTER",
    332				VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER,
    333				&perf_reg_read
    334			},
    335			{
    336				"PREFETCH_CACHE_MISS_COUNTER",
    337				VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER,
    338				&perf_reg_read
    339			},
    340			{
    341				"CULLED_QUAD_COUNT",
    342				VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT,
    343				&perf_reg_read
    344			}
    345		}
    346	},
    347	{
    348		.name = "TX",
    349		.profile_read = VIVS_MC_PROFILE_TX_READ,
    350		.profile_config = VIVS_MC_PROFILE_CONFIG1,
    351		.nr_signals = 9,
    352		.signal = (const struct etnaviv_pm_signal[]) {
    353			{
    354				"TOTAL_BILINEAR_REQUESTS",
    355				VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS,
    356				&perf_reg_read
    357			},
    358			{
    359				"TOTAL_TRILINEAR_REQUESTS",
    360				VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS,
    361				&perf_reg_read
    362			},
    363			{
    364				"TOTAL_DISCARDED_TEXTURE_REQUESTS",
    365				VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS,
    366				&perf_reg_read
    367			},
    368			{
    369				"TOTAL_TEXTURE_REQUESTS",
    370				VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS,
    371				&perf_reg_read
    372			},
    373			{
    374				"MEM_READ_COUNT",
    375				VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT,
    376				&perf_reg_read
    377			},
    378			{
    379				"MEM_READ_IN_8B_COUNT",
    380				VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT,
    381				&perf_reg_read
    382			},
    383			{
    384				"CACHE_MISS_COUNT",
    385				VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT,
    386				&perf_reg_read
    387			},
    388			{
    389				"CACHE_HIT_TEXEL_COUNT",
    390				VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT,
    391				&perf_reg_read
    392			},
    393			{
    394				"CACHE_MISS_TEXEL_COUNT",
    395				VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT,
    396				&perf_reg_read
    397			}
    398		}
    399	},
    400	{
    401		.name = "MC",
    402		.profile_read = VIVS_MC_PROFILE_MC_READ,
    403		.profile_config = VIVS_MC_PROFILE_CONFIG2,
    404		.nr_signals = 3,
    405		.signal = (const struct etnaviv_pm_signal[]) {
    406			{
    407				"TOTAL_READ_REQ_8B_FROM_PIPELINE",
    408				VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE,
    409				&perf_reg_read
    410			},
    411			{
    412				"TOTAL_READ_REQ_8B_FROM_IP",
    413				VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP,
    414				&perf_reg_read
    415			},
    416			{
    417				"TOTAL_WRITE_REQ_8B_FROM_PIPELINE",
    418				VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE,
    419				&perf_reg_read
    420			}
    421		}
    422	}
    423};
    424
    425static const struct etnaviv_pm_domain doms_2d[] = {
    426	{
    427		.name = "PE",
    428		.profile_read = VIVS_MC_PROFILE_PE_READ,
    429		.profile_config = VIVS_MC_PROFILE_CONFIG0,
    430		.nr_signals = 1,
    431		.signal = (const struct etnaviv_pm_signal[]) {
    432			{
    433				"PIXELS_RENDERED_2D",
    434				VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D,
    435				&pipe_perf_reg_read
    436			}
    437		}
    438	}
    439};
    440
    441static const struct etnaviv_pm_domain doms_vg[] = {
    442};
    443
    444static const struct etnaviv_pm_domain_meta doms_meta[] = {
    445	{
    446		.feature = chipFeatures_PIPE_3D,
    447		.nr_domains = ARRAY_SIZE(doms_3d),
    448		.domains = &doms_3d[0]
    449	},
    450	{
    451		.feature = chipFeatures_PIPE_2D,
    452		.nr_domains = ARRAY_SIZE(doms_2d),
    453		.domains = &doms_2d[0]
    454	},
    455	{
    456		.feature = chipFeatures_PIPE_VG,
    457		.nr_domains = ARRAY_SIZE(doms_vg),
    458		.domains = &doms_vg[0]
    459	}
    460};
    461
    462static unsigned int num_pm_domains(const struct etnaviv_gpu *gpu)
    463{
    464	unsigned int num = 0, i;
    465
    466	for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
    467		const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
    468
    469		if (gpu->identity.features & meta->feature)
    470			num += meta->nr_domains;
    471	}
    472
    473	return num;
    474}
    475
    476static const struct etnaviv_pm_domain *pm_domain(const struct etnaviv_gpu *gpu,
    477	unsigned int index)
    478{
    479	const struct etnaviv_pm_domain *domain = NULL;
    480	unsigned int offset = 0, i;
    481
    482	for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
    483		const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
    484
    485		if (!(gpu->identity.features & meta->feature))
    486			continue;
    487
    488		if (index - offset >= meta->nr_domains) {
    489			offset += meta->nr_domains;
    490			continue;
    491		}
    492
    493		domain = meta->domains + (index - offset);
    494	}
    495
    496	return domain;
    497}
    498
    499int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
    500	struct drm_etnaviv_pm_domain *domain)
    501{
    502	const unsigned int nr_domains = num_pm_domains(gpu);
    503	const struct etnaviv_pm_domain *dom;
    504
    505	if (domain->iter >= nr_domains)
    506		return -EINVAL;
    507
    508	dom = pm_domain(gpu, domain->iter);
    509	if (!dom)
    510		return -EINVAL;
    511
    512	domain->id = domain->iter;
    513	domain->nr_signals = dom->nr_signals;
    514	strncpy(domain->name, dom->name, sizeof(domain->name));
    515
    516	domain->iter++;
    517	if (domain->iter == nr_domains)
    518		domain->iter = 0xff;
    519
    520	return 0;
    521}
    522
    523int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,
    524	struct drm_etnaviv_pm_signal *signal)
    525{
    526	const unsigned int nr_domains = num_pm_domains(gpu);
    527	const struct etnaviv_pm_domain *dom;
    528	const struct etnaviv_pm_signal *sig;
    529
    530	if (signal->domain >= nr_domains)
    531		return -EINVAL;
    532
    533	dom = pm_domain(gpu, signal->domain);
    534	if (!dom)
    535		return -EINVAL;
    536
    537	if (signal->iter >= dom->nr_signals)
    538		return -EINVAL;
    539
    540	sig = &dom->signal[signal->iter];
    541
    542	signal->id = signal->iter;
    543	strncpy(signal->name, sig->name, sizeof(signal->name));
    544
    545	signal->iter++;
    546	if (signal->iter == dom->nr_signals)
    547		signal->iter = 0xffff;
    548
    549	return 0;
    550}
    551
    552int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r,
    553	u32 exec_state)
    554{
    555	const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
    556	const struct etnaviv_pm_domain *dom;
    557
    558	if (r->domain >= meta->nr_domains)
    559		return -EINVAL;
    560
    561	dom = meta->domains + r->domain;
    562
    563	if (r->signal >= dom->nr_signals)
    564		return -EINVAL;
    565
    566	return 0;
    567}
    568
    569void etnaviv_perfmon_process(struct etnaviv_gpu *gpu,
    570	const struct etnaviv_perfmon_request *pmr, u32 exec_state)
    571{
    572	const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
    573	const struct etnaviv_pm_domain *dom;
    574	const struct etnaviv_pm_signal *sig;
    575	u32 *bo = pmr->bo_vma;
    576	u32 val;
    577
    578	dom = meta->domains + pmr->domain;
    579	sig = &dom->signal[pmr->signal];
    580	val = sig->sample(gpu, dom, sig);
    581
    582	*(bo + pmr->offset) = val;
    583}