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

ramht.c (4102B)


      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#include <core/ramht.h>
     23#include <core/engine.h>
     24#include <core/object.h>
     25
     26static u32
     27nvkm_ramht_hash(struct nvkm_ramht *ramht, int chid, u32 handle)
     28{
     29	u32 hash = 0;
     30
     31	while (handle) {
     32		hash ^= (handle & ((1 << ramht->bits) - 1));
     33		handle >>= ramht->bits;
     34	}
     35
     36	hash ^= chid << (ramht->bits - 4);
     37	return hash;
     38}
     39
     40struct nvkm_gpuobj *
     41nvkm_ramht_search(struct nvkm_ramht *ramht, int chid, u32 handle)
     42{
     43	u32 co, ho;
     44
     45	co = ho = nvkm_ramht_hash(ramht, chid, handle);
     46	do {
     47		if (ramht->data[co].chid == chid) {
     48			if (ramht->data[co].handle == handle)
     49				return ramht->data[co].inst;
     50		}
     51
     52		if (++co >= ramht->size)
     53			co = 0;
     54	} while (co != ho);
     55
     56	return NULL;
     57}
     58
     59static int
     60nvkm_ramht_update(struct nvkm_ramht *ramht, int co, struct nvkm_object *object,
     61		  int chid, int addr, u32 handle, u32 context)
     62{
     63	struct nvkm_ramht_data *data = &ramht->data[co];
     64	u64 inst = 0x00000040; /* just non-zero for <=g8x fifo ramht */
     65	int ret;
     66
     67	nvkm_gpuobj_del(&data->inst);
     68	data->chid = chid;
     69	data->handle = handle;
     70
     71	if (object) {
     72		ret = nvkm_object_bind(object, ramht->parent, 16, &data->inst);
     73		if (ret) {
     74			if (ret != -ENODEV) {
     75				data->chid = -1;
     76				return ret;
     77			}
     78			data->inst = NULL;
     79		}
     80
     81		if (data->inst) {
     82			if (ramht->device->card_type >= NV_50)
     83				inst = data->inst->node->offset;
     84			else
     85				inst = data->inst->addr;
     86		}
     87
     88		if (addr < 0) context |= inst << -addr;
     89		else          context |= inst >>  addr;
     90	}
     91
     92	nvkm_kmap(ramht->gpuobj);
     93	nvkm_wo32(ramht->gpuobj, (co << 3) + 0, handle);
     94	nvkm_wo32(ramht->gpuobj, (co << 3) + 4, context);
     95	nvkm_done(ramht->gpuobj);
     96	return co + 1;
     97}
     98
     99void
    100nvkm_ramht_remove(struct nvkm_ramht *ramht, int cookie)
    101{
    102	if (--cookie >= 0)
    103		nvkm_ramht_update(ramht, cookie, NULL, -1, 0, 0, 0);
    104}
    105
    106int
    107nvkm_ramht_insert(struct nvkm_ramht *ramht, struct nvkm_object *object,
    108		  int chid, int addr, u32 handle, u32 context)
    109{
    110	u32 co, ho;
    111
    112	if (nvkm_ramht_search(ramht, chid, handle))
    113		return -EEXIST;
    114
    115	co = ho = nvkm_ramht_hash(ramht, chid, handle);
    116	do {
    117		if (ramht->data[co].chid < 0) {
    118			return nvkm_ramht_update(ramht, co, object, chid,
    119						 addr, handle, context);
    120		}
    121
    122		if (++co >= ramht->size)
    123			co = 0;
    124	} while (co != ho);
    125
    126	return -ENOSPC;
    127}
    128
    129void
    130nvkm_ramht_del(struct nvkm_ramht **pramht)
    131{
    132	struct nvkm_ramht *ramht = *pramht;
    133	if (ramht) {
    134		nvkm_gpuobj_del(&ramht->gpuobj);
    135		vfree(*pramht);
    136		*pramht = NULL;
    137	}
    138}
    139
    140int
    141nvkm_ramht_new(struct nvkm_device *device, u32 size, u32 align,
    142	       struct nvkm_gpuobj *parent, struct nvkm_ramht **pramht)
    143{
    144	struct nvkm_ramht *ramht;
    145	int ret, i;
    146
    147	if (!(ramht = *pramht = vzalloc(struct_size(ramht, data, (size >> 3)))))
    148		return -ENOMEM;
    149
    150	ramht->device = device;
    151	ramht->parent = parent;
    152	ramht->size = size >> 3;
    153	ramht->bits = order_base_2(ramht->size);
    154	for (i = 0; i < ramht->size; i++)
    155		ramht->data[i].chid = -1;
    156
    157	ret = nvkm_gpuobj_new(ramht->device, size, align, true,
    158			      ramht->parent, &ramht->gpuobj);
    159	if (ret)
    160		nvkm_ramht_del(pramht);
    161	return ret;
    162}