[FOSS_TLK]Revert "security: tlk_driver: delete te_pin_user_pages() and its usage"
Sharif Inamdar [Tue, 3 Jun 2014 04:48:11 +0000 (09:48 +0530)]
We are reverting this as we want to add support of
te_pin_user_pages(). TA can have dynamic mappings
created as part of an OpenSession or LaunchOperation
command.

If either of these specify a buffer as an argument
(with virt addr and length as params), the TLK kernel
will create a mapping to it. This happens for things
that go between TAs (no pin issue there) and between
the NS and S worlds.

In the case of NS buffers being passed in, we need
phys memory to stay where it is, because the secure
world has a mapping to it that Linux is unaware of,
which is why we pin it.

This reverts commit f4a063081552617e72cbdda5596ae7bd537696f7.

Change-Id: I7676f7786cef469f6cbb39a76a05541b417dc5f7
Signed-off-by: Sharif Inamdar <isharif@nvidia.com>
Reviewed-on: http://git-master/r/754994
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Varun Wadekar <vwadekar@nvidia.com>
Tested-by: Varun Wadekar <vwadekar@nvidia.com>

security/tlk_driver/ote_comms.c
security/tlk_driver/ote_protocol.h

index 11d43b5..8560de1 100644 (file)
@@ -35,7 +35,35 @@ core_param(verbose_smc, verbose_smc, bool, 0644);
 
 #define SET_RESULT(req, r, ro) { req->result = r; req->result_origin = ro; }
 
+static int te_pin_user_pages(void *buffer, size_t size,
+               unsigned long *pages_ptr)
+{
+       int ret = 0;
+       unsigned int nr_pages;
+       struct page **pages = NULL;
+
+       nr_pages = (((unsigned int)buffer & (PAGE_SIZE - 1)) +
+                       (size + PAGE_SIZE - 1)) >> PAGE_SHIFT;
+
+       pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+       if (!pages)
+               return -ENOMEM;
+
+       down_read(&current->mm->mmap_sem);
+       ret = get_user_pages(current, current->mm, (unsigned long)buffer,
+                               nr_pages, WRITE, 0, pages, NULL);
+       if (ret < 0)
+               ret = get_user_pages(current, current->mm, (unsigned long)buffer,
+                               nr_pages, WRITE, 1/*force*/, pages, NULL);
+       up_read(&current->mm->mmap_sem);
+
+       *pages_ptr = (unsigned long) pages;
+
+       return ret;
+}
+
 static struct te_shmem_desc *te_add_shmem_desc(void *buffer, size_t size,
+               unsigned int nr_pages, struct page **pages,
                struct tlk_context *context)
 {
        struct te_shmem_desc *shmem_desc = NULL;
@@ -44,6 +72,8 @@ static struct te_shmem_desc *te_add_shmem_desc(void *buffer, size_t size,
                INIT_LIST_HEAD(&(shmem_desc->list));
                shmem_desc->buffer = buffer;
                shmem_desc->size = size;
+               shmem_desc->nr_pages = nr_pages;
+               shmem_desc->pages = pages;
                list_add_tail(&shmem_desc->list, &(context->shmem_alloc_list));
        }
 
@@ -56,7 +86,16 @@ static int te_pin_mem_buffers(void *buffer, size_t size,
        struct te_shmem_desc *shmem_desc = NULL;
        int ret = 0;
 
-       shmem_desc = te_add_shmem_desc(buffer, size, context);
+       nr_pages = te_pin_user_pages(buffer, size, &pages);
+       if (nr_pages <= 0) {
+               pr_err("%s: te_pin_user_pages Failed (%d)\n", __func__,
+                       nr_pages);
+               ret = OTE_ERROR_OUT_OF_MEMORY;
+               goto error;
+       }
+
+       shmem_desc = te_add_shmem_desc(buffer, size,
+                               nr_pages, (struct page **)pages, context);
        if (!shmem_desc) {
                pr_err("%s: te_add_shmem_desc Failed\n", __func__);
                ret = OTE_ERROR_OUT_OF_MEMORY;
@@ -147,6 +186,9 @@ static void te_del_shmem_desc(void *buffer, struct tlk_context *context)
                &(context->shmem_alloc_list), list) {
                if (shmem_desc->buffer == buffer) {
                        list_del(&shmem_desc->list);
+                       for (i = 0; i < shmem_desc->nr_pages; i++)
+                               page_cache_release(shmem_desc->pages[i]);
+                       kfree(shmem_desc->pages);
                        kfree(shmem_desc);
                }
        }
index 608ee89..550876e 100644 (file)
@@ -109,6 +109,8 @@ struct te_shmem_desc {
        void *buffer;
        size_t size;
        unsigned int mem_type;
+       struct page **pages;
+       unsigned int nr_pages;
 };
 
 struct tlk_context {