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

chang84.c (7678B)


      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 "channv50.h"
     25
     26#include <core/client.h>
     27#include <core/ramht.h>
     28#include <subdev/mmu.h>
     29#include <subdev/timer.h>
     30
     31#include <nvif/cl826e.h>
     32
     33static int
     34g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type,
     35		   struct nvkm_event **pevent)
     36{
     37	switch (type) {
     38	case NV826E_V0_NTFY_NON_STALL_INTERRUPT:
     39		*pevent = &chan->fifo->uevent;
     40		return 0;
     41	default:
     42		break;
     43	}
     44	return -EINVAL;
     45}
     46
     47static int
     48g84_fifo_chan_engine_addr(struct nvkm_engine *engine)
     49{
     50	switch (engine->subdev.type) {
     51	case NVKM_ENGINE_DMAOBJ:
     52	case NVKM_ENGINE_SW    : return -1;
     53	case NVKM_ENGINE_GR    : return 0x0020;
     54	case NVKM_ENGINE_VP    :
     55	case NVKM_ENGINE_MSPDEC: return 0x0040;
     56	case NVKM_ENGINE_MPEG  :
     57	case NVKM_ENGINE_MSPPP : return 0x0060;
     58	case NVKM_ENGINE_BSP   :
     59	case NVKM_ENGINE_MSVLD : return 0x0080;
     60	case NVKM_ENGINE_CIPHER:
     61	case NVKM_ENGINE_SEC   : return 0x00a0;
     62	case NVKM_ENGINE_CE    : return 0x00c0;
     63	default:
     64		WARN_ON(1);
     65		return -1;
     66	}
     67}
     68
     69static int
     70g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
     71			  struct nvkm_engine *engine, bool suspend)
     72{
     73	struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
     74	struct nv50_fifo *fifo = chan->fifo;
     75	struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
     76	struct nvkm_device *device = subdev->device;
     77	u32 engn, save;
     78	int offset;
     79	bool done;
     80
     81	offset = g84_fifo_chan_engine_addr(engine);
     82	if (offset < 0)
     83		return 0;
     84
     85	engn = fifo->base.func->engine_id(&fifo->base, engine) - 1;
     86	save = nvkm_mask(device, 0x002520, 0x0000003f, 1 << engn);
     87	nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12);
     88	done = nvkm_msec(device, 2000,
     89		if (nvkm_rd32(device, 0x0032fc) != 0xffffffff)
     90			break;
     91	) >= 0;
     92	nvkm_wr32(device, 0x002520, save);
     93	if (!done) {
     94		nvkm_error(subdev, "channel %d [%s] unload timeout\n",
     95			   chan->base.chid, chan->base.object.client->name);
     96		if (suspend)
     97			return -EBUSY;
     98	}
     99
    100	nvkm_kmap(chan->eng);
    101	nvkm_wo32(chan->eng, offset + 0x00, 0x00000000);
    102	nvkm_wo32(chan->eng, offset + 0x04, 0x00000000);
    103	nvkm_wo32(chan->eng, offset + 0x08, 0x00000000);
    104	nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000);
    105	nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
    106	nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
    107	nvkm_done(chan->eng);
    108	return 0;
    109}
    110
    111
    112static int
    113g84_fifo_chan_engine_init(struct nvkm_fifo_chan *base,
    114			  struct nvkm_engine *engine)
    115{
    116	struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
    117	struct nvkm_gpuobj *engn = *nv50_fifo_chan_engine(chan, engine);
    118	u64 limit, start;
    119	int offset;
    120
    121	offset = g84_fifo_chan_engine_addr(engine);
    122	if (offset < 0)
    123		return 0;
    124	limit = engn->addr + engn->size - 1;
    125	start = engn->addr;
    126
    127	nvkm_kmap(chan->eng);
    128	nvkm_wo32(chan->eng, offset + 0x00, 0x00190000);
    129	nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit));
    130	nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start));
    131	nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 |
    132					    upper_32_bits(start));
    133	nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
    134	nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
    135	nvkm_done(chan->eng);
    136	return 0;
    137}
    138
    139static int
    140g84_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base,
    141			  struct nvkm_engine *engine,
    142			  struct nvkm_object *object)
    143{
    144	struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
    145
    146	if (g84_fifo_chan_engine_addr(engine) < 0)
    147		return 0;
    148
    149	return nvkm_object_bind(object, NULL, 0, nv50_fifo_chan_engine(chan, engine));
    150}
    151
    152static int
    153g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base,
    154			  struct nvkm_object *object)
    155{
    156	struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
    157	u32 handle = object->handle;
    158	u32 context;
    159
    160	switch (object->engine->subdev.type) {
    161	case NVKM_ENGINE_DMAOBJ:
    162	case NVKM_ENGINE_SW    : context = 0x00000000; break;
    163	case NVKM_ENGINE_GR    : context = 0x00100000; break;
    164	case NVKM_ENGINE_MPEG  :
    165	case NVKM_ENGINE_MSPPP : context = 0x00200000; break;
    166	case NVKM_ENGINE_ME    :
    167	case NVKM_ENGINE_CE    : context = 0x00300000; break;
    168	case NVKM_ENGINE_VP    :
    169	case NVKM_ENGINE_MSPDEC: context = 0x00400000; break;
    170	case NVKM_ENGINE_CIPHER:
    171	case NVKM_ENGINE_SEC   :
    172	case NVKM_ENGINE_VIC   : context = 0x00500000; break;
    173	case NVKM_ENGINE_BSP   :
    174	case NVKM_ENGINE_MSVLD : context = 0x00600000; break;
    175	default:
    176		WARN_ON(1);
    177		return -EINVAL;
    178	}
    179
    180	return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context);
    181}
    182
    183static void
    184g84_fifo_chan_init(struct nvkm_fifo_chan *base)
    185{
    186	struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
    187	struct nv50_fifo *fifo = chan->fifo;
    188	struct nvkm_device *device = fifo->base.engine.subdev.device;
    189	u64 addr = chan->ramfc->addr >> 8;
    190	u32 chid = chan->base.chid;
    191
    192	nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr);
    193	nv50_fifo_runlist_update(fifo);
    194}
    195
    196static const struct nvkm_fifo_chan_func
    197g84_fifo_chan_func = {
    198	.dtor = nv50_fifo_chan_dtor,
    199	.init = g84_fifo_chan_init,
    200	.fini = nv50_fifo_chan_fini,
    201	.ntfy = g84_fifo_chan_ntfy,
    202	.engine_ctor = g84_fifo_chan_engine_ctor,
    203	.engine_dtor = nv50_fifo_chan_engine_dtor,
    204	.engine_init = g84_fifo_chan_engine_init,
    205	.engine_fini = g84_fifo_chan_engine_fini,
    206	.object_ctor = g84_fifo_chan_object_ctor,
    207	.object_dtor = nv50_fifo_chan_object_dtor,
    208};
    209
    210int
    211g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push,
    212		   const struct nvkm_oclass *oclass,
    213		   struct nv50_fifo_chan *chan)
    214{
    215	struct nvkm_device *device = fifo->base.engine.subdev.device;
    216	int ret;
    217
    218	if (!vmm)
    219		return -EINVAL;
    220
    221	ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base,
    222				  0x10000, 0x1000, false, vmm, push,
    223				  BIT(G84_FIFO_ENGN_SW) |
    224				  BIT(G84_FIFO_ENGN_GR) |
    225				  BIT(G84_FIFO_ENGN_MPEG) |
    226				  BIT(G84_FIFO_ENGN_MSPPP) |
    227				  BIT(G84_FIFO_ENGN_ME) |
    228				  BIT(G84_FIFO_ENGN_CE0) |
    229				  BIT(G84_FIFO_ENGN_VP) |
    230				  BIT(G84_FIFO_ENGN_MSPDEC) |
    231				  BIT(G84_FIFO_ENGN_CIPHER) |
    232				  BIT(G84_FIFO_ENGN_SEC) |
    233				  BIT(G84_FIFO_ENGN_VIC) |
    234				  BIT(G84_FIFO_ENGN_BSP) |
    235				  BIT(G84_FIFO_ENGN_MSVLD) |
    236				  BIT(G84_FIFO_ENGN_DMA),
    237				  0, 0xc00000, 0x2000, oclass, &chan->base);
    238	chan->fifo = fifo;
    239	if (ret)
    240		return ret;
    241
    242	ret = nvkm_gpuobj_new(device, 0x0200, 0, true, chan->base.inst,
    243			      &chan->eng);
    244	if (ret)
    245		return ret;
    246
    247	ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst,
    248			      &chan->pgd);
    249	if (ret)
    250		return ret;
    251
    252	ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, chan->base.inst,
    253			      &chan->cache);
    254	if (ret)
    255		return ret;
    256
    257	ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, chan->base.inst,
    258			      &chan->ramfc);
    259	if (ret)
    260		return ret;
    261
    262	return nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht);
    263}