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

nv17_fence.c (4312B)


      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 <bskeggs@redhat.com>
     23 */
     24#include "nouveau_drv.h"
     25#include "nouveau_dma.h"
     26#include "nv10_fence.h"
     27
     28#include <nvif/push006c.h>
     29
     30#include <nvif/class.h>
     31#include <nvif/cl0002.h>
     32
     33#include <nvhw/class/cl176e.h>
     34
     35int
     36nv17_fence_sync(struct nouveau_fence *fence,
     37		struct nouveau_channel *prev, struct nouveau_channel *chan)
     38{
     39	struct nouveau_cli *cli = (void *)prev->user.client;
     40	struct nv10_fence_priv *priv = chan->drm->fence;
     41	struct nv10_fence_chan *fctx = chan->fence;
     42	struct nvif_push *ppush = prev->chan.push;
     43	struct nvif_push *npush = chan->chan.push;
     44	u32 value;
     45	int ret;
     46
     47	if (!mutex_trylock(&cli->mutex))
     48		return -EBUSY;
     49
     50	spin_lock(&priv->lock);
     51	value = priv->sequence;
     52	priv->sequence += 2;
     53	spin_unlock(&priv->lock);
     54
     55	ret = PUSH_WAIT(ppush, 5);
     56	if (!ret) {
     57		PUSH_MTHD(ppush, NV176E, SET_CONTEXT_DMA_SEMAPHORE, fctx->sema.handle,
     58					 SEMAPHORE_OFFSET, 0,
     59					 SEMAPHORE_ACQUIRE, value + 0,
     60					 SEMAPHORE_RELEASE, value + 1);
     61		PUSH_KICK(ppush);
     62	}
     63
     64	if (!ret && !(ret = PUSH_WAIT(npush, 5))) {
     65		PUSH_MTHD(npush, NV176E, SET_CONTEXT_DMA_SEMAPHORE, fctx->sema.handle,
     66					 SEMAPHORE_OFFSET, 0,
     67					 SEMAPHORE_ACQUIRE, value + 1,
     68					 SEMAPHORE_RELEASE, value + 2);
     69		PUSH_KICK(npush);
     70	}
     71
     72	mutex_unlock(&cli->mutex);
     73	return 0;
     74}
     75
     76static int
     77nv17_fence_context_new(struct nouveau_channel *chan)
     78{
     79	struct nv10_fence_priv *priv = chan->drm->fence;
     80	struct ttm_resource *reg = priv->bo->bo.resource;
     81	struct nv10_fence_chan *fctx;
     82	u32 start = reg->start * PAGE_SIZE;
     83	u32 limit = start + priv->bo->bo.base.size - 1;
     84	int ret = 0;
     85
     86	fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
     87	if (!fctx)
     88		return -ENOMEM;
     89
     90	nouveau_fence_context_new(chan, &fctx->base);
     91	fctx->base.emit = nv10_fence_emit;
     92	fctx->base.read = nv10_fence_read;
     93	fctx->base.sync = nv17_fence_sync;
     94
     95	ret = nvif_object_ctor(&chan->user, "fenceCtxDma", NvSema,
     96			       NV_DMA_FROM_MEMORY,
     97			       &(struct nv_dma_v0) {
     98					.target = NV_DMA_V0_TARGET_VRAM,
     99					.access = NV_DMA_V0_ACCESS_RDWR,
    100					.start = start,
    101					.limit = limit,
    102			       }, sizeof(struct nv_dma_v0),
    103			       &fctx->sema);
    104	if (ret)
    105		nv10_fence_context_del(chan);
    106	return ret;
    107}
    108
    109void
    110nv17_fence_resume(struct nouveau_drm *drm)
    111{
    112	struct nv10_fence_priv *priv = drm->fence;
    113
    114	nouveau_bo_wr32(priv->bo, 0, priv->sequence);
    115}
    116
    117int
    118nv17_fence_create(struct nouveau_drm *drm)
    119{
    120	struct nv10_fence_priv *priv;
    121	int ret = 0;
    122
    123	priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
    124	if (!priv)
    125		return -ENOMEM;
    126
    127	priv->base.dtor = nv10_fence_destroy;
    128	priv->base.resume = nv17_fence_resume;
    129	priv->base.context_new = nv17_fence_context_new;
    130	priv->base.context_del = nv10_fence_context_del;
    131	spin_lock_init(&priv->lock);
    132
    133	ret = nouveau_bo_new(&drm->client, 4096, 0x1000,
    134			     NOUVEAU_GEM_DOMAIN_VRAM,
    135			     0, 0x0000, NULL, NULL, &priv->bo);
    136	if (!ret) {
    137		ret = nouveau_bo_pin(priv->bo, NOUVEAU_GEM_DOMAIN_VRAM, false);
    138		if (!ret) {
    139			ret = nouveau_bo_map(priv->bo);
    140			if (ret)
    141				nouveau_bo_unpin(priv->bo);
    142		}
    143		if (ret)
    144			nouveau_bo_ref(NULL, &priv->bo);
    145	}
    146
    147	if (ret) {
    148		nv10_fence_destroy(drm);
    149		return ret;
    150	}
    151
    152	nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
    153	return ret;
    154}