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.c (18450B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2015-2018 Etnaviv Project
      4 */
      5
      6#include <drm/drm_prime.h>
      7#include <linux/dma-mapping.h>
      8#include <linux/shmem_fs.h>
      9#include <linux/spinlock.h>
     10#include <linux/vmalloc.h>
     11
     12#include "etnaviv_drv.h"
     13#include "etnaviv_gem.h"
     14#include "etnaviv_gpu.h"
     15#include "etnaviv_mmu.h"
     16
     17static struct lock_class_key etnaviv_shm_lock_class;
     18static struct lock_class_key etnaviv_userptr_lock_class;
     19
     20static void etnaviv_gem_scatter_map(struct etnaviv_gem_object *etnaviv_obj)
     21{
     22	struct drm_device *dev = etnaviv_obj->base.dev;
     23	struct sg_table *sgt = etnaviv_obj->sgt;
     24
     25	/*
     26	 * For non-cached buffers, ensure the new pages are clean
     27	 * because display controller, GPU, etc. are not coherent.
     28	 */
     29	if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK)
     30		dma_map_sgtable(dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
     31}
     32
     33static void etnaviv_gem_scatterlist_unmap(struct etnaviv_gem_object *etnaviv_obj)
     34{
     35	struct drm_device *dev = etnaviv_obj->base.dev;
     36	struct sg_table *sgt = etnaviv_obj->sgt;
     37
     38	/*
     39	 * For non-cached buffers, ensure the new pages are clean
     40	 * because display controller, GPU, etc. are not coherent:
     41	 *
     42	 * WARNING: The DMA API does not support concurrent CPU
     43	 * and device access to the memory area.  With BIDIRECTIONAL,
     44	 * we will clean the cache lines which overlap the region,
     45	 * and invalidate all cache lines (partially) contained in
     46	 * the region.
     47	 *
     48	 * If you have dirty data in the overlapping cache lines,
     49	 * that will corrupt the GPU-written data.  If you have
     50	 * written into the remainder of the region, this can
     51	 * discard those writes.
     52	 */
     53	if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK)
     54		dma_unmap_sgtable(dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
     55}
     56
     57/* called with etnaviv_obj->lock held */
     58static int etnaviv_gem_shmem_get_pages(struct etnaviv_gem_object *etnaviv_obj)
     59{
     60	struct drm_device *dev = etnaviv_obj->base.dev;
     61	struct page **p = drm_gem_get_pages(&etnaviv_obj->base);
     62
     63	if (IS_ERR(p)) {
     64		dev_dbg(dev->dev, "could not get pages: %ld\n", PTR_ERR(p));
     65		return PTR_ERR(p);
     66	}
     67
     68	etnaviv_obj->pages = p;
     69
     70	return 0;
     71}
     72
     73static void put_pages(struct etnaviv_gem_object *etnaviv_obj)
     74{
     75	if (etnaviv_obj->sgt) {
     76		etnaviv_gem_scatterlist_unmap(etnaviv_obj);
     77		sg_free_table(etnaviv_obj->sgt);
     78		kfree(etnaviv_obj->sgt);
     79		etnaviv_obj->sgt = NULL;
     80	}
     81	if (etnaviv_obj->pages) {
     82		drm_gem_put_pages(&etnaviv_obj->base, etnaviv_obj->pages,
     83				  true, false);
     84
     85		etnaviv_obj->pages = NULL;
     86	}
     87}
     88
     89struct page **etnaviv_gem_get_pages(struct etnaviv_gem_object *etnaviv_obj)
     90{
     91	int ret;
     92
     93	lockdep_assert_held(&etnaviv_obj->lock);
     94
     95	if (!etnaviv_obj->pages) {
     96		ret = etnaviv_obj->ops->get_pages(etnaviv_obj);
     97		if (ret < 0)
     98			return ERR_PTR(ret);
     99	}
    100
    101	if (!etnaviv_obj->sgt) {
    102		struct drm_device *dev = etnaviv_obj->base.dev;
    103		int npages = etnaviv_obj->base.size >> PAGE_SHIFT;
    104		struct sg_table *sgt;
    105
    106		sgt = drm_prime_pages_to_sg(etnaviv_obj->base.dev,
    107					    etnaviv_obj->pages, npages);
    108		if (IS_ERR(sgt)) {
    109			dev_err(dev->dev, "failed to allocate sgt: %ld\n",
    110				PTR_ERR(sgt));
    111			return ERR_CAST(sgt);
    112		}
    113
    114		etnaviv_obj->sgt = sgt;
    115
    116		etnaviv_gem_scatter_map(etnaviv_obj);
    117	}
    118
    119	return etnaviv_obj->pages;
    120}
    121
    122void etnaviv_gem_put_pages(struct etnaviv_gem_object *etnaviv_obj)
    123{
    124	lockdep_assert_held(&etnaviv_obj->lock);
    125	/* when we start tracking the pin count, then do something here */
    126}
    127
    128static int etnaviv_gem_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
    129		struct vm_area_struct *vma)
    130{
    131	pgprot_t vm_page_prot;
    132
    133	vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP;
    134
    135	vm_page_prot = vm_get_page_prot(vma->vm_flags);
    136
    137	if (etnaviv_obj->flags & ETNA_BO_WC) {
    138		vma->vm_page_prot = pgprot_writecombine(vm_page_prot);
    139	} else if (etnaviv_obj->flags & ETNA_BO_UNCACHED) {
    140		vma->vm_page_prot = pgprot_noncached(vm_page_prot);
    141	} else {
    142		/*
    143		 * Shunt off cached objs to shmem file so they have their own
    144		 * address_space (so unmap_mapping_range does what we want,
    145		 * in particular in the case of mmap'd dmabufs)
    146		 */
    147		vma->vm_pgoff = 0;
    148		vma_set_file(vma, etnaviv_obj->base.filp);
    149
    150		vma->vm_page_prot = vm_page_prot;
    151	}
    152
    153	return 0;
    154}
    155
    156static int etnaviv_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
    157{
    158	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
    159
    160	return etnaviv_obj->ops->mmap(etnaviv_obj, vma);
    161}
    162
    163static vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
    164{
    165	struct vm_area_struct *vma = vmf->vma;
    166	struct drm_gem_object *obj = vma->vm_private_data;
    167	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
    168	struct page **pages, *page;
    169	pgoff_t pgoff;
    170	int err;
    171
    172	/*
    173	 * Make sure we don't parallel update on a fault, nor move or remove
    174	 * something from beneath our feet.  Note that vmf_insert_page() is
    175	 * specifically coded to take care of this, so we don't have to.
    176	 */
    177	err = mutex_lock_interruptible(&etnaviv_obj->lock);
    178	if (err)
    179		return VM_FAULT_NOPAGE;
    180	/* make sure we have pages attached now */
    181	pages = etnaviv_gem_get_pages(etnaviv_obj);
    182	mutex_unlock(&etnaviv_obj->lock);
    183
    184	if (IS_ERR(pages)) {
    185		err = PTR_ERR(pages);
    186		return vmf_error(err);
    187	}
    188
    189	/* We don't use vmf->pgoff since that has the fake offset: */
    190	pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
    191
    192	page = pages[pgoff];
    193
    194	VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
    195	     page_to_pfn(page), page_to_pfn(page) << PAGE_SHIFT);
    196
    197	return vmf_insert_page(vma, vmf->address, page);
    198}
    199
    200int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset)
    201{
    202	int ret;
    203
    204	/* Make it mmapable */
    205	ret = drm_gem_create_mmap_offset(obj);
    206	if (ret)
    207		dev_err(obj->dev->dev, "could not allocate mmap offset\n");
    208	else
    209		*offset = drm_vma_node_offset_addr(&obj->vma_node);
    210
    211	return ret;
    212}
    213
    214static struct etnaviv_vram_mapping *
    215etnaviv_gem_get_vram_mapping(struct etnaviv_gem_object *obj,
    216			     struct etnaviv_iommu_context *context)
    217{
    218	struct etnaviv_vram_mapping *mapping;
    219
    220	list_for_each_entry(mapping, &obj->vram_list, obj_node) {
    221		if (mapping->context == context)
    222			return mapping;
    223	}
    224
    225	return NULL;
    226}
    227
    228void etnaviv_gem_mapping_unreference(struct etnaviv_vram_mapping *mapping)
    229{
    230	struct etnaviv_gem_object *etnaviv_obj = mapping->object;
    231
    232	mutex_lock(&etnaviv_obj->lock);
    233	WARN_ON(mapping->use == 0);
    234	mapping->use -= 1;
    235	mutex_unlock(&etnaviv_obj->lock);
    236
    237	drm_gem_object_put(&etnaviv_obj->base);
    238}
    239
    240struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(
    241	struct drm_gem_object *obj, struct etnaviv_iommu_context *mmu_context,
    242	u64 va)
    243{
    244	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
    245	struct etnaviv_vram_mapping *mapping;
    246	struct page **pages;
    247	int ret = 0;
    248
    249	mutex_lock(&etnaviv_obj->lock);
    250	mapping = etnaviv_gem_get_vram_mapping(etnaviv_obj, mmu_context);
    251	if (mapping) {
    252		/*
    253		 * Holding the object lock prevents the use count changing
    254		 * beneath us.  If the use count is zero, the MMU might be
    255		 * reaping this object, so take the lock and re-check that
    256		 * the MMU owns this mapping to close this race.
    257		 */
    258		if (mapping->use == 0) {
    259			mutex_lock(&mmu_context->lock);
    260			if (mapping->context == mmu_context)
    261				mapping->use += 1;
    262			else
    263				mapping = NULL;
    264			mutex_unlock(&mmu_context->lock);
    265			if (mapping)
    266				goto out;
    267		} else {
    268			mapping->use += 1;
    269			goto out;
    270		}
    271	}
    272
    273	pages = etnaviv_gem_get_pages(etnaviv_obj);
    274	if (IS_ERR(pages)) {
    275		ret = PTR_ERR(pages);
    276		goto out;
    277	}
    278
    279	/*
    280	 * See if we have a reaped vram mapping we can re-use before
    281	 * allocating a fresh mapping.
    282	 */
    283	mapping = etnaviv_gem_get_vram_mapping(etnaviv_obj, NULL);
    284	if (!mapping) {
    285		mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
    286		if (!mapping) {
    287			ret = -ENOMEM;
    288			goto out;
    289		}
    290
    291		INIT_LIST_HEAD(&mapping->scan_node);
    292		mapping->object = etnaviv_obj;
    293	} else {
    294		list_del(&mapping->obj_node);
    295	}
    296
    297	mapping->use = 1;
    298
    299	ret = etnaviv_iommu_map_gem(mmu_context, etnaviv_obj,
    300				    mmu_context->global->memory_base,
    301				    mapping, va);
    302	if (ret < 0)
    303		kfree(mapping);
    304	else
    305		list_add_tail(&mapping->obj_node, &etnaviv_obj->vram_list);
    306
    307out:
    308	mutex_unlock(&etnaviv_obj->lock);
    309
    310	if (ret)
    311		return ERR_PTR(ret);
    312
    313	/* Take a reference on the object */
    314	drm_gem_object_get(obj);
    315	return mapping;
    316}
    317
    318void *etnaviv_gem_vmap(struct drm_gem_object *obj)
    319{
    320	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
    321
    322	if (etnaviv_obj->vaddr)
    323		return etnaviv_obj->vaddr;
    324
    325	mutex_lock(&etnaviv_obj->lock);
    326	/*
    327	 * Need to check again, as we might have raced with another thread
    328	 * while waiting for the mutex.
    329	 */
    330	if (!etnaviv_obj->vaddr)
    331		etnaviv_obj->vaddr = etnaviv_obj->ops->vmap(etnaviv_obj);
    332	mutex_unlock(&etnaviv_obj->lock);
    333
    334	return etnaviv_obj->vaddr;
    335}
    336
    337static void *etnaviv_gem_vmap_impl(struct etnaviv_gem_object *obj)
    338{
    339	struct page **pages;
    340
    341	lockdep_assert_held(&obj->lock);
    342
    343	pages = etnaviv_gem_get_pages(obj);
    344	if (IS_ERR(pages))
    345		return NULL;
    346
    347	return vmap(pages, obj->base.size >> PAGE_SHIFT,
    348			VM_MAP, pgprot_writecombine(PAGE_KERNEL));
    349}
    350
    351static inline enum dma_data_direction etnaviv_op_to_dma_dir(u32 op)
    352{
    353	if (op & ETNA_PREP_READ)
    354		return DMA_FROM_DEVICE;
    355	else if (op & ETNA_PREP_WRITE)
    356		return DMA_TO_DEVICE;
    357	else
    358		return DMA_BIDIRECTIONAL;
    359}
    360
    361int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op,
    362		struct drm_etnaviv_timespec *timeout)
    363{
    364	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
    365	struct drm_device *dev = obj->dev;
    366	bool write = !!(op & ETNA_PREP_WRITE);
    367	int ret;
    368
    369	if (!etnaviv_obj->sgt) {
    370		void *ret;
    371
    372		mutex_lock(&etnaviv_obj->lock);
    373		ret = etnaviv_gem_get_pages(etnaviv_obj);
    374		mutex_unlock(&etnaviv_obj->lock);
    375		if (IS_ERR(ret))
    376			return PTR_ERR(ret);
    377	}
    378
    379	if (op & ETNA_PREP_NOSYNC) {
    380		if (!dma_resv_test_signaled(obj->resv,
    381					    dma_resv_usage_rw(write)))
    382			return -EBUSY;
    383	} else {
    384		unsigned long remain = etnaviv_timeout_to_jiffies(timeout);
    385
    386		ret = dma_resv_wait_timeout(obj->resv, dma_resv_usage_rw(write),
    387					    true, remain);
    388		if (ret <= 0)
    389			return ret == 0 ? -ETIMEDOUT : ret;
    390	}
    391
    392	if (etnaviv_obj->flags & ETNA_BO_CACHED) {
    393		dma_sync_sgtable_for_cpu(dev->dev, etnaviv_obj->sgt,
    394					 etnaviv_op_to_dma_dir(op));
    395		etnaviv_obj->last_cpu_prep_op = op;
    396	}
    397
    398	return 0;
    399}
    400
    401int etnaviv_gem_cpu_fini(struct drm_gem_object *obj)
    402{
    403	struct drm_device *dev = obj->dev;
    404	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
    405
    406	if (etnaviv_obj->flags & ETNA_BO_CACHED) {
    407		/* fini without a prep is almost certainly a userspace error */
    408		WARN_ON(etnaviv_obj->last_cpu_prep_op == 0);
    409		dma_sync_sgtable_for_device(dev->dev, etnaviv_obj->sgt,
    410			etnaviv_op_to_dma_dir(etnaviv_obj->last_cpu_prep_op));
    411		etnaviv_obj->last_cpu_prep_op = 0;
    412	}
    413
    414	return 0;
    415}
    416
    417int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
    418	struct drm_etnaviv_timespec *timeout)
    419{
    420	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
    421
    422	return etnaviv_gpu_wait_obj_inactive(gpu, etnaviv_obj, timeout);
    423}
    424
    425#ifdef CONFIG_DEBUG_FS
    426static void etnaviv_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
    427{
    428	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
    429	struct dma_resv *robj = obj->resv;
    430	unsigned long off = drm_vma_node_start(&obj->vma_node);
    431	int r;
    432
    433	seq_printf(m, "%08x: %c %2d (%2d) %08lx %p %zd\n",
    434			etnaviv_obj->flags, is_active(etnaviv_obj) ? 'A' : 'I',
    435			obj->name, kref_read(&obj->refcount),
    436			off, etnaviv_obj->vaddr, obj->size);
    437
    438	r = dma_resv_lock(robj, NULL);
    439	if (r)
    440		return;
    441
    442	dma_resv_describe(robj, m);
    443	dma_resv_unlock(robj);
    444}
    445
    446void etnaviv_gem_describe_objects(struct etnaviv_drm_private *priv,
    447	struct seq_file *m)
    448{
    449	struct etnaviv_gem_object *etnaviv_obj;
    450	int count = 0;
    451	size_t size = 0;
    452
    453	mutex_lock(&priv->gem_lock);
    454	list_for_each_entry(etnaviv_obj, &priv->gem_list, gem_node) {
    455		struct drm_gem_object *obj = &etnaviv_obj->base;
    456
    457		seq_puts(m, "   ");
    458		etnaviv_gem_describe(obj, m);
    459		count++;
    460		size += obj->size;
    461	}
    462	mutex_unlock(&priv->gem_lock);
    463
    464	seq_printf(m, "Total %d objects, %zu bytes\n", count, size);
    465}
    466#endif
    467
    468static void etnaviv_gem_shmem_release(struct etnaviv_gem_object *etnaviv_obj)
    469{
    470	vunmap(etnaviv_obj->vaddr);
    471	put_pages(etnaviv_obj);
    472}
    473
    474static const struct etnaviv_gem_ops etnaviv_gem_shmem_ops = {
    475	.get_pages = etnaviv_gem_shmem_get_pages,
    476	.release = etnaviv_gem_shmem_release,
    477	.vmap = etnaviv_gem_vmap_impl,
    478	.mmap = etnaviv_gem_mmap_obj,
    479};
    480
    481void etnaviv_gem_free_object(struct drm_gem_object *obj)
    482{
    483	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
    484	struct etnaviv_drm_private *priv = obj->dev->dev_private;
    485	struct etnaviv_vram_mapping *mapping, *tmp;
    486
    487	/* object should not be active */
    488	WARN_ON(is_active(etnaviv_obj));
    489
    490	mutex_lock(&priv->gem_lock);
    491	list_del(&etnaviv_obj->gem_node);
    492	mutex_unlock(&priv->gem_lock);
    493
    494	list_for_each_entry_safe(mapping, tmp, &etnaviv_obj->vram_list,
    495				 obj_node) {
    496		struct etnaviv_iommu_context *context = mapping->context;
    497
    498		WARN_ON(mapping->use);
    499
    500		if (context)
    501			etnaviv_iommu_unmap_gem(context, mapping);
    502
    503		list_del(&mapping->obj_node);
    504		kfree(mapping);
    505	}
    506
    507	drm_gem_free_mmap_offset(obj);
    508	etnaviv_obj->ops->release(etnaviv_obj);
    509	drm_gem_object_release(obj);
    510
    511	kfree(etnaviv_obj);
    512}
    513
    514void etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj)
    515{
    516	struct etnaviv_drm_private *priv = dev->dev_private;
    517	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
    518
    519	mutex_lock(&priv->gem_lock);
    520	list_add_tail(&etnaviv_obj->gem_node, &priv->gem_list);
    521	mutex_unlock(&priv->gem_lock);
    522}
    523
    524static const struct vm_operations_struct vm_ops = {
    525	.fault = etnaviv_gem_fault,
    526	.open = drm_gem_vm_open,
    527	.close = drm_gem_vm_close,
    528};
    529
    530static const struct drm_gem_object_funcs etnaviv_gem_object_funcs = {
    531	.free = etnaviv_gem_free_object,
    532	.pin = etnaviv_gem_prime_pin,
    533	.unpin = etnaviv_gem_prime_unpin,
    534	.get_sg_table = etnaviv_gem_prime_get_sg_table,
    535	.vmap = etnaviv_gem_prime_vmap,
    536	.mmap = etnaviv_gem_mmap,
    537	.vm_ops = &vm_ops,
    538};
    539
    540static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
    541	const struct etnaviv_gem_ops *ops, struct drm_gem_object **obj)
    542{
    543	struct etnaviv_gem_object *etnaviv_obj;
    544	unsigned sz = sizeof(*etnaviv_obj);
    545	bool valid = true;
    546
    547	/* validate flags */
    548	switch (flags & ETNA_BO_CACHE_MASK) {
    549	case ETNA_BO_UNCACHED:
    550	case ETNA_BO_CACHED:
    551	case ETNA_BO_WC:
    552		break;
    553	default:
    554		valid = false;
    555	}
    556
    557	if (!valid) {
    558		dev_err(dev->dev, "invalid cache flag: %x\n",
    559			(flags & ETNA_BO_CACHE_MASK));
    560		return -EINVAL;
    561	}
    562
    563	etnaviv_obj = kzalloc(sz, GFP_KERNEL);
    564	if (!etnaviv_obj)
    565		return -ENOMEM;
    566
    567	etnaviv_obj->flags = flags;
    568	etnaviv_obj->ops = ops;
    569
    570	mutex_init(&etnaviv_obj->lock);
    571	INIT_LIST_HEAD(&etnaviv_obj->vram_list);
    572
    573	*obj = &etnaviv_obj->base;
    574	(*obj)->funcs = &etnaviv_gem_object_funcs;
    575
    576	return 0;
    577}
    578
    579/* convenience method to construct a GEM buffer object, and userspace handle */
    580int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
    581	u32 size, u32 flags, u32 *handle)
    582{
    583	struct etnaviv_drm_private *priv = dev->dev_private;
    584	struct drm_gem_object *obj = NULL;
    585	int ret;
    586
    587	size = PAGE_ALIGN(size);
    588
    589	ret = etnaviv_gem_new_impl(dev, size, flags,
    590				   &etnaviv_gem_shmem_ops, &obj);
    591	if (ret)
    592		goto fail;
    593
    594	lockdep_set_class(&to_etnaviv_bo(obj)->lock, &etnaviv_shm_lock_class);
    595
    596	ret = drm_gem_object_init(dev, obj, size);
    597	if (ret)
    598		goto fail;
    599
    600	/*
    601	 * Our buffers are kept pinned, so allocating them from the MOVABLE
    602	 * zone is a really bad idea, and conflicts with CMA. See comments
    603	 * above new_inode() why this is required _and_ expected if you're
    604	 * going to pin these pages.
    605	 */
    606	mapping_set_gfp_mask(obj->filp->f_mapping, priv->shm_gfp_mask);
    607
    608	etnaviv_gem_obj_add(dev, obj);
    609
    610	ret = drm_gem_handle_create(file, obj, handle);
    611
    612	/* drop reference from allocate - handle holds it now */
    613fail:
    614	drm_gem_object_put(obj);
    615
    616	return ret;
    617}
    618
    619int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,
    620	const struct etnaviv_gem_ops *ops, struct etnaviv_gem_object **res)
    621{
    622	struct drm_gem_object *obj;
    623	int ret;
    624
    625	ret = etnaviv_gem_new_impl(dev, size, flags, ops, &obj);
    626	if (ret)
    627		return ret;
    628
    629	drm_gem_private_object_init(dev, obj, size);
    630
    631	*res = to_etnaviv_bo(obj);
    632
    633	return 0;
    634}
    635
    636static int etnaviv_gem_userptr_get_pages(struct etnaviv_gem_object *etnaviv_obj)
    637{
    638	struct page **pvec = NULL;
    639	struct etnaviv_gem_userptr *userptr = &etnaviv_obj->userptr;
    640	int ret, pinned = 0, npages = etnaviv_obj->base.size >> PAGE_SHIFT;
    641
    642	might_lock_read(&current->mm->mmap_lock);
    643
    644	if (userptr->mm != current->mm)
    645		return -EPERM;
    646
    647	pvec = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
    648	if (!pvec)
    649		return -ENOMEM;
    650
    651	do {
    652		unsigned num_pages = npages - pinned;
    653		uint64_t ptr = userptr->ptr + pinned * PAGE_SIZE;
    654		struct page **pages = pvec + pinned;
    655
    656		ret = pin_user_pages_fast(ptr, num_pages,
    657					  FOLL_WRITE | FOLL_FORCE | FOLL_LONGTERM,
    658					  pages);
    659		if (ret < 0) {
    660			unpin_user_pages(pvec, pinned);
    661			kvfree(pvec);
    662			return ret;
    663		}
    664
    665		pinned += ret;
    666
    667	} while (pinned < npages);
    668
    669	etnaviv_obj->pages = pvec;
    670
    671	return 0;
    672}
    673
    674static void etnaviv_gem_userptr_release(struct etnaviv_gem_object *etnaviv_obj)
    675{
    676	if (etnaviv_obj->sgt) {
    677		etnaviv_gem_scatterlist_unmap(etnaviv_obj);
    678		sg_free_table(etnaviv_obj->sgt);
    679		kfree(etnaviv_obj->sgt);
    680	}
    681	if (etnaviv_obj->pages) {
    682		int npages = etnaviv_obj->base.size >> PAGE_SHIFT;
    683
    684		unpin_user_pages(etnaviv_obj->pages, npages);
    685		kvfree(etnaviv_obj->pages);
    686	}
    687}
    688
    689static int etnaviv_gem_userptr_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
    690		struct vm_area_struct *vma)
    691{
    692	return -EINVAL;
    693}
    694
    695static const struct etnaviv_gem_ops etnaviv_gem_userptr_ops = {
    696	.get_pages = etnaviv_gem_userptr_get_pages,
    697	.release = etnaviv_gem_userptr_release,
    698	.vmap = etnaviv_gem_vmap_impl,
    699	.mmap = etnaviv_gem_userptr_mmap_obj,
    700};
    701
    702int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
    703	uintptr_t ptr, u32 size, u32 flags, u32 *handle)
    704{
    705	struct etnaviv_gem_object *etnaviv_obj;
    706	int ret;
    707
    708	ret = etnaviv_gem_new_private(dev, size, ETNA_BO_CACHED,
    709				      &etnaviv_gem_userptr_ops, &etnaviv_obj);
    710	if (ret)
    711		return ret;
    712
    713	lockdep_set_class(&etnaviv_obj->lock, &etnaviv_userptr_lock_class);
    714
    715	etnaviv_obj->userptr.ptr = ptr;
    716	etnaviv_obj->userptr.mm = current->mm;
    717	etnaviv_obj->userptr.ro = !(flags & ETNA_USERPTR_WRITE);
    718
    719	etnaviv_gem_obj_add(dev, &etnaviv_obj->base);
    720
    721	ret = drm_gem_handle_create(file, &etnaviv_obj->base, handle);
    722
    723	/* drop reference from allocate - handle holds it now */
    724	drm_gem_object_put(&etnaviv_obj->base);
    725	return ret;
    726}