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

g84.c (5355B)


      1/*
      2 * Copyright 2012 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 "nv50.h"
     25
     26#include <subdev/timer.h>
     27
     28#include <nvif/class.h>
     29
     30static const struct nvkm_bitfield nv50_gr_status[] = {
     31	{ 0x00000001, "BUSY" }, /* set when any bit is set */
     32	{ 0x00000002, "DISPATCH" },
     33	{ 0x00000004, "UNK2" },
     34	{ 0x00000008, "UNK3" },
     35	{ 0x00000010, "UNK4" },
     36	{ 0x00000020, "UNK5" },
     37	{ 0x00000040, "M2MF" },
     38	{ 0x00000080, "UNK7" },
     39	{ 0x00000100, "CTXPROG" },
     40	{ 0x00000200, "VFETCH" },
     41	{ 0x00000400, "CCACHE_PREGEOM" },
     42	{ 0x00000800, "STRMOUT_VATTR_POSTGEOM" },
     43	{ 0x00001000, "VCLIP" },
     44	{ 0x00002000, "RATTR_APLANE" },
     45	{ 0x00004000, "TRAST" },
     46	{ 0x00008000, "CLIPID" },
     47	{ 0x00010000, "ZCULL" },
     48	{ 0x00020000, "ENG2D" },
     49	{ 0x00040000, "RMASK" },
     50	{ 0x00080000, "TPC_RAST" },
     51	{ 0x00100000, "TPC_PROP" },
     52	{ 0x00200000, "TPC_TEX" },
     53	{ 0x00400000, "TPC_GEOM" },
     54	{ 0x00800000, "TPC_MP" },
     55	{ 0x01000000, "ROP" },
     56	{}
     57};
     58
     59static const struct nvkm_bitfield
     60nv50_gr_vstatus_0[] = {
     61	{ 0x01, "VFETCH" },
     62	{ 0x02, "CCACHE" },
     63	{ 0x04, "PREGEOM" },
     64	{ 0x08, "POSTGEOM" },
     65	{ 0x10, "VATTR" },
     66	{ 0x20, "STRMOUT" },
     67	{ 0x40, "VCLIP" },
     68	{}
     69};
     70
     71static const struct nvkm_bitfield
     72nv50_gr_vstatus_1[] = {
     73	{ 0x01, "TPC_RAST" },
     74	{ 0x02, "TPC_PROP" },
     75	{ 0x04, "TPC_TEX" },
     76	{ 0x08, "TPC_GEOM" },
     77	{ 0x10, "TPC_MP" },
     78	{}
     79};
     80
     81static const struct nvkm_bitfield
     82nv50_gr_vstatus_2[] = {
     83	{ 0x01, "RATTR" },
     84	{ 0x02, "APLANE" },
     85	{ 0x04, "TRAST" },
     86	{ 0x08, "CLIPID" },
     87	{ 0x10, "ZCULL" },
     88	{ 0x20, "ENG2D" },
     89	{ 0x40, "RMASK" },
     90	{ 0x80, "ROP" },
     91	{}
     92};
     93
     94static void
     95nvkm_gr_vstatus_print(struct nv50_gr *gr, int r,
     96		      const struct nvkm_bitfield *units, u32 status)
     97{
     98	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
     99	u32 stat = status;
    100	u8  mask = 0x00;
    101	char msg[64];
    102	int i;
    103
    104	for (i = 0; units[i].name && status; i++) {
    105		if ((status & 7) == 1)
    106			mask |= (1 << i);
    107		status >>= 3;
    108	}
    109
    110	nvkm_snprintbf(msg, sizeof(msg), units, mask);
    111	nvkm_error(subdev, "PGRAPH_VSTATUS%d: %08x [%s]\n", r, stat, msg);
    112}
    113
    114int
    115g84_gr_tlb_flush(struct nvkm_gr *base)
    116{
    117	struct nv50_gr *gr = nv50_gr(base);
    118	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
    119	struct nvkm_device *device = subdev->device;
    120	struct nvkm_timer *tmr = device->timer;
    121	bool idle, timeout = false;
    122	unsigned long flags;
    123	char status[128];
    124	u64 start;
    125	u32 tmp;
    126
    127	spin_lock_irqsave(&gr->lock, flags);
    128	nvkm_mask(device, 0x400500, 0x00000001, 0x00000000);
    129
    130	start = nvkm_timer_read(tmr);
    131	do {
    132		idle = true;
    133
    134		for (tmp = nvkm_rd32(device, 0x400380); tmp && idle; tmp >>= 3) {
    135			if ((tmp & 7) == 1)
    136				idle = false;
    137		}
    138
    139		for (tmp = nvkm_rd32(device, 0x400384); tmp && idle; tmp >>= 3) {
    140			if ((tmp & 7) == 1)
    141				idle = false;
    142		}
    143
    144		for (tmp = nvkm_rd32(device, 0x400388); tmp && idle; tmp >>= 3) {
    145			if ((tmp & 7) == 1)
    146				idle = false;
    147		}
    148	} while (!idle &&
    149		 !(timeout = nvkm_timer_read(tmr) - start > 2000000000));
    150
    151	if (timeout) {
    152		nvkm_error(subdev, "PGRAPH TLB flush idle timeout fail\n");
    153
    154		tmp = nvkm_rd32(device, 0x400700);
    155		nvkm_snprintbf(status, sizeof(status), nv50_gr_status, tmp);
    156		nvkm_error(subdev, "PGRAPH_STATUS %08x [%s]\n", tmp, status);
    157
    158		nvkm_gr_vstatus_print(gr, 0, nv50_gr_vstatus_0,
    159				       nvkm_rd32(device, 0x400380));
    160		nvkm_gr_vstatus_print(gr, 1, nv50_gr_vstatus_1,
    161				       nvkm_rd32(device, 0x400384));
    162		nvkm_gr_vstatus_print(gr, 2, nv50_gr_vstatus_2,
    163				       nvkm_rd32(device, 0x400388));
    164	}
    165
    166
    167	nvkm_wr32(device, 0x100c80, 0x00000001);
    168	nvkm_msec(device, 2000,
    169		if (!(nvkm_rd32(device, 0x100c80) & 0x00000001))
    170			break;
    171	);
    172	nvkm_mask(device, 0x400500, 0x00000001, 0x00000001);
    173	spin_unlock_irqrestore(&gr->lock, flags);
    174	return timeout ? -EBUSY : 0;
    175}
    176
    177static const struct nvkm_gr_func
    178g84_gr = {
    179	.init = nv50_gr_init,
    180	.intr = nv50_gr_intr,
    181	.chan_new = nv50_gr_chan_new,
    182	.tlb_flush = g84_gr_tlb_flush,
    183	.units = nv50_gr_units,
    184	.sclass = {
    185		{ -1, -1, NV_NULL_CLASS, &nv50_gr_object },
    186		{ -1, -1, NV50_TWOD, &nv50_gr_object },
    187		{ -1, -1, NV50_MEMORY_TO_MEMORY_FORMAT, &nv50_gr_object },
    188		{ -1, -1, NV50_COMPUTE, &nv50_gr_object },
    189		{ -1, -1, G82_TESLA, &nv50_gr_object },
    190		{}
    191	}
    192};
    193
    194int
    195g84_gr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr)
    196{
    197	return nv50_gr_new_(&g84_gr, device, type, inst, pgr);
    198}