With softpin we allow the userspace to take control over the GPU virtual
address space. The new capability is relected by a bump of the minor DRM
version. There are a few restrictions for userspace to take into
account:
1. The kernel reserves a bit of the address space to implement zero page
faulting and mapping of the kernel internal ring buffer. Userspace can
query the kernel for the first usable GPU VM address via
ETNAVIV_PARAM_SOFTPIN_START_ADDR.
2. We only allow softpin on GPUs, which implement proper process
separation via PPAS. If softpin is not available the softpin start
address will be set to ~0.
3. Softpin is all or nothing. A submit using softpin must not use any
address fixups via relocs.
Signed-off-by: Lucas Stach
---
drivers/gpu/drm/etnaviv/etnaviv_drv.c| 2 +-
drivers/gpu/drm/etnaviv/etnaviv_drv.h| 2 ++
drivers/gpu/drm/etnaviv/etnaviv_gem.c| 4 ++--
drivers/gpu/drm/etnaviv/etnaviv_gem.h| 1 +
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 25 +++-
drivers/gpu/drm/etnaviv/etnaviv_gpu.c| 9 +++
include/uapi/drm/etnaviv_drm.h | 5 +++-
7 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 8bcbd3fb02c6..e2e60cdf8741 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -529,7 +529,7 @@ static struct drm_driver etnaviv_drm_driver = {
.desc = "etnaviv DRM",
.date = "20151214",
.major = 1,
- .minor = 2,
+ .minor = 3,
};
/*
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h
b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
index a488cfdb6bbf..32cfa5a48d42 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
@@ -24,6 +24,8 @@ struct etnaviv_gem_object;
struct etnaviv_gem_submit;
struct etnaviv_iommu_global;
+#define ETNAVIV_SOFTPIN_START_ADDRESS SZ_4M /* must be >= SUBALLOC_SIZE */
+
struct etnaviv_file_private {
struct etnaviv_iommu_context*mmu;
struct drm_sched_entity sched_entity[ETNA_MAX_PIPES];
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index 5dde3e4c3949..dd863bd858f8 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -248,7 +248,7 @@ void etnaviv_gem_mapping_unreference(struct
etnaviv_vram_mapping *mapping)
}
struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(
- struct drm_gem_object *obj, struct etnaviv_iommu_context *mmu)
+ struct drm_gem_object *obj, struct etnaviv_iommu_context *mmu, u64 va)
{
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
struct etnaviv_vram_mapping *mapping;
@@ -308,7 +308,7 @@ struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(
mapping->use = 1;
ret = etnaviv_iommu_map_gem(mmu, etnaviv_obj, mmu->global->memory_base,
- mapping, 0);
+ mapping, va);
if (ret < 0)
kfree(mapping);
else
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h
b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
index 92f3090b8348..c64e93a6293b 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
@@ -77,6 +77,7 @@ static inline bool is_active(struct etnaviv_gem_object
*etnaviv_obj)
struct etnaviv_gem_submit_bo {
u32 flags;
+ u64 va;
struct etnaviv_gem_object *obj;
struct etnaviv_vram_mapping *mapping;
struct dma_fence *excl;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
index 627c80ed63d8..09e38f78753c 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -72,6 +72,14 @@ static int submit_lookup_objects(struct etnaviv_gem_submit
*submit,
}
submit->bos[i].flags = bo->flags;
+ if (submit->flags & ETNA_SUBMIT_SOFTPIN) {
+ if (bo->presumed < ETNAVIV_SOFTPIN_START_ADDRESS) {
+ DRM_ERROR("invalid softpin address\n");
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+ submit->bos[i].va = bo->presumed;
+ }
/* normally use drm_gem_object_lookup(), but for bulk lookup
* all under single table_lock just hit object_idr directly:
@@ -224,11 +232,16 @@ static int submit_pin_objects(struct etnaviv_gem_submit
*submit)
struct etnaviv_vram_mapping *mapping;
mapping = etnaviv_gem_mapping_get(_obj->base,
- submit->mmu);
+