summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk@arm.linux.org.uk>2014-08-26 15:49:06 +0100
committerRussell King <rmk@arm.linux.org.uk>2014-08-26 19:09:11 +0100
commitb93820a7a76e8e2f37335cdb4e3f9074ced6415a (patch)
tree36d5d24f8c934591f3c5924206c75714de1ac3a1
parentb7cbb7aaf15b2c905003c8b1d8f7ddbd75eb4ea8 (diff)
Add support to permit mapping memory with protection infoHEADmaster
The standard galcore user memory mapping function fails when asked to map read-only memory, such as X shmem buffers. The reason these fail is because get_user_pages() is always attempted with "write" mode enabled, which is not permissible with read-only mappings. To allow this to work (so that Xv can be implemented efficiently) we must be able to map read-only buffers. This adds an extension to etnaviv, found in my Dove galcore driver and Jon Nettleton's iMX6 kernels which permit this without changing the existing galcore APIs. Signed-off-by: Russell King <rmk@arm.linux.org.uk>
-rw-r--r--src/etnaviv/etna_bo.c18
-rw-r--r--src/etnaviv/etna_bo.h3
-rw-r--r--src/etnaviv/viv.c29
-rw-r--r--src/etnaviv/viv.h5
4 files changed, 55 insertions, 0 deletions
diff --git a/src/etnaviv/etna_bo.c b/src/etnaviv/etna_bo.c
index ea5248b..010b62a 100644
--- a/src/etnaviv/etna_bo.c
+++ b/src/etnaviv/etna_bo.c
@@ -232,6 +232,24 @@ struct etna_bo* etna_bo_new(struct viv_conn *conn, size_t bytes, uint32_t flags)
return mem;
}
+struct etna_bo *etna_bo_from_usermem_prot(struct viv_conn *conn, void *memory, size_t size, int prot)
+{
+ struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
+ if(mem == NULL) return NULL;
+
+ mem->bo_type = ETNA_BO_TYPE_USERMEM;
+ mem->logical = memory;
+ mem->size = size;
+
+ if(viv_map_user_memory_prot(conn, memory, size, prot, &mem->usermem_info, &mem->address)!=0)
+ {
+ ETNA_FREE(mem);
+ return NULL;
+ }
+
+ return mem;
+}
+
struct etna_bo *etna_bo_from_usermem(struct viv_conn *conn, void *memory, size_t size)
{
struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
diff --git a/src/etnaviv/etna_bo.h b/src/etnaviv/etna_bo.h
index a4f1024..ad5bffb 100644
--- a/src/etnaviv/etna_bo.h
+++ b/src/etnaviv/etna_bo.h
@@ -62,6 +62,9 @@ struct etna_bo;
/* Allocate linear block of video memory */
struct etna_bo *etna_bo_new(struct viv_conn *conn, size_t bytes, uint32_t flags);
+/* Map user memory (which may be write protected) into GPU memory space */
+struct etna_bo *etna_bo_from_usermem_prot(struct viv_conn *conn, void *memory, size_t size, int prot);
+
/* Map user memory into GPU memory space */
struct etna_bo *etna_bo_from_usermem(struct viv_conn *conn, void *memory, size_t size);
diff --git a/src/etnaviv/viv.c b/src/etnaviv/viv.c
index b3f6225..f476a47 100644
--- a/src/etnaviv/viv.c
+++ b/src/etnaviv/viv.c
@@ -70,6 +70,17 @@ struct viv_dmabuf_map {
};
#define IOC_GDMABUF_MAP _IOWR('_', 0, struct viv_dmabuf_map)
+/* rmk's extension for mapping read-only memory (X shmem buffers) */
+struct viv_membuf_map {
+ union rmk_gcabi_header hdr;
+ uint64_t info;
+ uint64_t address;
+ uint64_t virt;
+ uint32_t size;
+ uint32_t prot;
+};
+#define IOC_GMEMBUF_MAP _IOWR('_', 1, struct viv_membuf_map)
+
const char *galcore_device[] = {"/dev/gal3d", "/dev/galcore", "/dev/graphics/galcore", NULL};
#define INTERFACE_SIZE (sizeof(gcsHAL_INTERFACE))
@@ -616,6 +627,24 @@ int viv_map_dmabuf(struct viv_conn *conn, int fd, viv_usermem_t *info, viv_addr_
return VIV_STATUS_OK;
}
+int viv_map_user_memory_prot(struct viv_conn *conn, void *memory, size_t size, int prot, viv_usermem_t *info, viv_addr_t *address)
+{
+ struct viv_membuf_map map = {
+#ifdef GCABI_HAS_HARDWARE_TYPE
+ .hdr.v4.hwtype = (gceHARDWARE_TYPE)conn->hw_type,
+#endif
+ .virt = (uintptr_t)memory,
+ .size = size,
+ .prot = prot,
+ };
+ int ret = viv_ioctl(conn, IOC_GMEMBUF_MAP, &map, sizeof(map));
+ if(ret < 0 || map.hdr.v4.status)
+ return -1;
+ *info = VIV_TO_HANDLE(map.info);
+ *address = map.address;
+ return VIV_STATUS_OK;
+}
+
int viv_map_user_memory(struct viv_conn *conn, void *memory, size_t size, viv_usermem_t *info, viv_addr_t *address)
{
gcsHAL_INTERFACE id = {
diff --git a/src/etnaviv/viv.h b/src/etnaviv/viv.h
index ec044f5..4496840 100644
--- a/src/etnaviv/viv.h
+++ b/src/etnaviv/viv.h
@@ -268,6 +268,11 @@ int viv_free_contiguous(struct viv_conn *conn, size_t bytes, viv_addr_t physical
*/
int viv_map_dmabuf(struct viv_conn *conn, int fd, viv_usermem_t *info, viv_addr_t *address, int prot);
+/** Map user memory to GPU memory, allowing for read/write protections.
+ * Note: GPU is not protected against reads/writes.
+ */
+int viv_map_user_memory_prot(struct viv_conn *conn, void *memory, size_t size, int prot, viv_usermem_t *info, viv_addr_t *address);
+
/** Map user memory to GPU memory.
*/
int viv_map_user_memory(struct viv_conn *conn, void *memory, size_t size, viv_usermem_t *info, viv_addr_t *address);