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

nv40.c (3693B)


      1/*
      2 * Copyright 2013 Red Hat Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 * Authors: Ben Skeggs
     23 */
     24#include "nv40.h"
     25
     26static void
     27nv40_perfctr_init(struct nvkm_pm *pm, struct nvkm_perfdom *dom,
     28		  struct nvkm_perfctr *ctr)
     29{
     30	struct nvkm_device *device = pm->engine.subdev.device;
     31	u32 log = ctr->logic_op;
     32	u32 src = 0x00000000;
     33	int i;
     34
     35	for (i = 0; i < 4; i++)
     36		src |= ctr->signal[i] << (i * 8);
     37
     38	nvkm_wr32(device, 0x00a7c0 + dom->addr, 0x00000001 | (dom->mode << 4));
     39	nvkm_wr32(device, 0x00a400 + dom->addr + (ctr->slot * 0x40), src);
     40	nvkm_wr32(device, 0x00a420 + dom->addr + (ctr->slot * 0x40), log);
     41}
     42
     43static void
     44nv40_perfctr_read(struct nvkm_pm *pm, struct nvkm_perfdom *dom,
     45		  struct nvkm_perfctr *ctr)
     46{
     47	struct nvkm_device *device = pm->engine.subdev.device;
     48
     49	switch (ctr->slot) {
     50	case 0: ctr->ctr = nvkm_rd32(device, 0x00a700 + dom->addr); break;
     51	case 1: ctr->ctr = nvkm_rd32(device, 0x00a6c0 + dom->addr); break;
     52	case 2: ctr->ctr = nvkm_rd32(device, 0x00a680 + dom->addr); break;
     53	case 3: ctr->ctr = nvkm_rd32(device, 0x00a740 + dom->addr); break;
     54	}
     55	dom->clk = nvkm_rd32(device, 0x00a600 + dom->addr);
     56}
     57
     58static void
     59nv40_perfctr_next(struct nvkm_pm *pm, struct nvkm_perfdom *dom)
     60{
     61	struct nvkm_device *device = pm->engine.subdev.device;
     62	struct nv40_pm *nv40pm = container_of(pm, struct nv40_pm, base);
     63
     64	if (nv40pm->sequence != pm->sequence) {
     65		nvkm_wr32(device, 0x400084, 0x00000020);
     66		nv40pm->sequence = pm->sequence;
     67	}
     68}
     69
     70const struct nvkm_funcdom
     71nv40_perfctr_func = {
     72	.init = nv40_perfctr_init,
     73	.read = nv40_perfctr_read,
     74	.next = nv40_perfctr_next,
     75};
     76
     77static const struct nvkm_pm_func
     78nv40_pm_ = {
     79};
     80
     81int
     82nv40_pm_new_(const struct nvkm_specdom *doms, struct nvkm_device *device,
     83	     enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm)
     84{
     85	struct nv40_pm *pm;
     86	int ret;
     87
     88	if (!(pm = kzalloc(sizeof(*pm), GFP_KERNEL)))
     89		return -ENOMEM;
     90	*ppm = &pm->base;
     91
     92	ret = nvkm_pm_ctor(&nv40_pm_, device, type, inst, &pm->base);
     93	if (ret)
     94		return ret;
     95
     96	return nvkm_perfdom_new(&pm->base, "pc", 0, 0, 0, 4, doms);
     97}
     98
     99static const struct nvkm_specdom
    100nv40_pm[] = {
    101	{ 0x20, (const struct nvkm_specsig[]) {
    102			{}
    103		}, &nv40_perfctr_func },
    104	{ 0x20, (const struct nvkm_specsig[]) {
    105			{}
    106		}, &nv40_perfctr_func },
    107	{ 0x20, (const struct nvkm_specsig[]) {
    108			{}
    109		}, &nv40_perfctr_func },
    110	{ 0x20, (const struct nvkm_specsig[]) {
    111			{}
    112		}, &nv40_perfctr_func },
    113	{ 0x20, (const struct nvkm_specsig[]) {
    114			{}
    115		}, &nv40_perfctr_func },
    116	{}
    117};
    118
    119int
    120nv40_pm_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm)
    121{
    122	return nv40_pm_new_(nv40_pm, device, type, inst, ppm);
    123}