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

etnaviv_gem_prime.c (3412B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2014-2018 Etnaviv Project
      4 */
      5
      6#include <drm/drm_prime.h>
      7#include <linux/dma-buf.h>
      8#include <linux/module.h>
      9
     10#include "etnaviv_drv.h"
     11#include "etnaviv_gem.h"
     12
     13MODULE_IMPORT_NS(DMA_BUF);
     14
     15static struct lock_class_key etnaviv_prime_lock_class;
     16
     17struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj)
     18{
     19	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
     20	int npages = obj->size >> PAGE_SHIFT;
     21
     22	if (WARN_ON(!etnaviv_obj->pages))  /* should have already pinned! */
     23		return ERR_PTR(-EINVAL);
     24
     25	return drm_prime_pages_to_sg(obj->dev, etnaviv_obj->pages, npages);
     26}
     27
     28int etnaviv_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
     29{
     30	void *vaddr;
     31
     32	vaddr = etnaviv_gem_vmap(obj);
     33	if (!vaddr)
     34		return -ENOMEM;
     35	iosys_map_set_vaddr(map, vaddr);
     36
     37	return 0;
     38}
     39
     40int etnaviv_gem_prime_pin(struct drm_gem_object *obj)
     41{
     42	if (!obj->import_attach) {
     43		struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
     44
     45		mutex_lock(&etnaviv_obj->lock);
     46		etnaviv_gem_get_pages(etnaviv_obj);
     47		mutex_unlock(&etnaviv_obj->lock);
     48	}
     49	return 0;
     50}
     51
     52void etnaviv_gem_prime_unpin(struct drm_gem_object *obj)
     53{
     54	if (!obj->import_attach) {
     55		struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
     56
     57		mutex_lock(&etnaviv_obj->lock);
     58		etnaviv_gem_put_pages(to_etnaviv_bo(obj));
     59		mutex_unlock(&etnaviv_obj->lock);
     60	}
     61}
     62
     63static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj)
     64{
     65	struct iosys_map map = IOSYS_MAP_INIT_VADDR(etnaviv_obj->vaddr);
     66
     67	if (etnaviv_obj->vaddr)
     68		dma_buf_vunmap(etnaviv_obj->base.import_attach->dmabuf, &map);
     69
     70	/* Don't drop the pages for imported dmabuf, as they are not
     71	 * ours, just free the array we allocated:
     72	 */
     73	kvfree(etnaviv_obj->pages);
     74
     75	drm_prime_gem_destroy(&etnaviv_obj->base, etnaviv_obj->sgt);
     76}
     77
     78static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj)
     79{
     80	struct iosys_map map;
     81	int ret;
     82
     83	lockdep_assert_held(&etnaviv_obj->lock);
     84
     85	ret = dma_buf_vmap(etnaviv_obj->base.import_attach->dmabuf, &map);
     86	if (ret)
     87		return NULL;
     88	return map.vaddr;
     89}
     90
     91static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
     92		struct vm_area_struct *vma)
     93{
     94	return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
     95}
     96
     97static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
     98	/* .get_pages should never be called */
     99	.release = etnaviv_gem_prime_release,
    100	.vmap = etnaviv_gem_prime_vmap_impl,
    101	.mmap = etnaviv_gem_prime_mmap_obj,
    102};
    103
    104struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
    105	struct dma_buf_attachment *attach, struct sg_table *sgt)
    106{
    107	struct etnaviv_gem_object *etnaviv_obj;
    108	size_t size = PAGE_ALIGN(attach->dmabuf->size);
    109	int ret, npages;
    110
    111	ret = etnaviv_gem_new_private(dev, size, ETNA_BO_WC,
    112				      &etnaviv_gem_prime_ops, &etnaviv_obj);
    113	if (ret < 0)
    114		return ERR_PTR(ret);
    115
    116	lockdep_set_class(&etnaviv_obj->lock, &etnaviv_prime_lock_class);
    117
    118	npages = size / PAGE_SIZE;
    119
    120	etnaviv_obj->sgt = sgt;
    121	etnaviv_obj->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
    122	if (!etnaviv_obj->pages) {
    123		ret = -ENOMEM;
    124		goto fail;
    125	}
    126
    127	ret = drm_prime_sg_to_page_array(sgt, etnaviv_obj->pages, npages);
    128	if (ret)
    129		goto fail;
    130
    131	etnaviv_gem_obj_add(dev, &etnaviv_obj->base);
    132
    133	return &etnaviv_obj->base;
    134
    135fail:
    136	drm_gem_object_put(&etnaviv_obj->base);
    137
    138	return ERR_PTR(ret);
    139}