Xen-Devel Archive on lore.kernel.org
 help / color / Atom feed
From: Volodymyr Babchuk <Volodymyr_Babchuk@epam.com>
To: "xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>
Cc: "tee-dev@lists.linaro.org" <tee-dev@lists.linaro.org>,
	Julien Grall <julien.grall@arm.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Volodymyr Babchuk <Volodymyr_Babchuk@epam.com>
Subject: [Xen-devel] [PATCH v6 07/10] xen/arm: optee: add support for arbitrary shared memory
Date: Tue, 11 Jun 2019 18:46:39 +0000
Message-ID: <20190611184541.7281-8-volodymyr_babchuk@epam.com> (raw)
In-Reply-To: <20190611184541.7281-1-volodymyr_babchuk@epam.com>

Shared memory is widely used by NW (Normal World) to communicate with
TAs (Trusted Applications) in OP-TEE. NW can share part of own memory
with TA or with OP-TEE core, by registering it in OP-TEE, or by
providing a temporal reference. Anyways, information about such memory
buffers are sent to OP-TEE as a list of pages. This mechanism is
described in optee_msg.h.

Mediator should step in when NW tries to share memory with
OP-TEE for two reasons:

1. Do address translation from IPA to PA.
2. Pin domain pages while they are mapped into OP-TEE or TA
   address space, so domain can't transfer this pages to
   other domain or balloon out them.

Address translation is done by translate_noncontig(...) function.
It allocates new buffer from domheap and then walks on guest
provided list of pages, translates addresses and stores PAs into
newly allocated buffer. This buffer will be provided to OP-TEE
instead of original buffer from the guest. This buffer will
be freed at the end of standard call.

In the same time this function pins pages and stores them in
struct optee_shm_buf object. This object will live all the time,
when given SHM buffer is known to OP-TEE. It will be freed
after guest unregisters shared buffer. At this time pages
will be unpinned.

Guest can share buffer with OP-TEE for duration for one call,
or permanently, using OPTEE_MSG_CMD_REGISTER_SHM call. We need
to handle both options.

Also we want to limit total size of shared buffers. As it is not
possible to get limit from OP-TEE, we need to choose some arbitrary
value. Currently limit is 16384 of 4K pages.

Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@epam.com>
Acked-by: Julien Grall <julien.grall@arm.com>

---
 All the patches to optee.c should be merged together. They were
 split to ease up review. But they depend heavily on each other.

 Changes from v5:
 - Added BUILD_BUG_ON(PAGE_SIZE != 4096)
 - Updated "TODO" comment about 16384 calls to
   lookup_and_pin_guest_ram_addr()

 Changes from v3:
 - Reworked pagelists storage - there is no more static storage for
   5 buffers, instead structure with all data is allocated dynamically
 - Now this code uses domheap instead of xenheap
 - Various style fixes
 - gdprintk() fixes

 Changes from v2:
 - Made sure that guest does not tries to register shared buffer with
   the same cookie twice
 - Fixed coding style
 - Use access_guest_memory_by_ipa() instead of direct memory mapping
---
 xen/arch/arm/tee/optee.c | 416 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 416 insertions(+)

diff --git a/xen/arch/arm/tee/optee.c b/xen/arch/arm/tee/optee.c
index 175789fb00..d4888acd8d 100644
--- a/xen/arch/arm/tee/optee.c
+++ b/xen/arch/arm/tee/optee.c
@@ -53,9 +53,21 @@
  */
 #define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006
 
+/* "System ran out of resources" as in GP TEE Client API Specification */
+#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
+
 /* Client ID 0 is reserved for the hypervisor itself */
 #define OPTEE_CLIENT_ID(domain) ((domain)->domain_id + 1)
 
+/*
+ * Maximum total number of pages that guest can share with
+ * OP-TEE. Currently value is selected arbitrary. Actual number of
+ * pages depends on free heap in OP-TEE. As we can't do any
+ * assumptions about OP-TEE heap usage, we limit number of pages
+ * arbitrary.
+ */
+#define MAX_TOTAL_SMH_BUF_PG    16384
+
 #define OPTEE_KNOWN_NSEC_CAPS OPTEE_SMC_NSEC_CAP_UNIPROCESSOR
 #define OPTEE_KNOWN_SEC_CAPS (OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM | \
                               OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM | \
@@ -88,11 +100,31 @@ struct shm_rpc {
     uint64_t cookie;
 };
 
+/* Shared memory buffer for arbitrary data */
+struct optee_shm_buf {
+    struct list_head list;
+    uint64_t cookie;
+    unsigned int page_cnt;
+    /*
+     * Shadowed container for list of pages that guest tries to share
+     * with OP-TEE. This is not the list of pages that guest shared
+     * with OP-TEE, but container for list of those pages. Check
+     * OPTEE_MSG_ATTR_NONCONTIG definition in optee_msg.h for more
+     * information.
+     */
+    struct page_info *pg_list;
+    unsigned int pg_list_order;
+    /* Pinned guest pages that are shared with OP-TEE */
+    struct page_info *pages[];
+};
+
 /* Domain context */
 struct optee_domain {
     struct list_head call_list;
     struct list_head shm_rpc_list;
+    struct list_head optee_shm_buf_list;
     atomic_t call_count;
+    atomic_t optee_shm_buf_pages;
     spinlock_t lock;
 };
 
@@ -167,7 +199,9 @@ static int optee_domain_init(struct domain *d)
 
     INIT_LIST_HEAD(&ctx->call_list);
     INIT_LIST_HEAD(&ctx->shm_rpc_list);
+    INIT_LIST_HEAD(&ctx->optee_shm_buf_list);
     atomic_set(&ctx->call_count, 0);
+    atomic_set(&ctx->optee_shm_buf_pages, 0);
     spin_lock_init(&ctx->lock);
 
     d->arch.tee = ctx;
@@ -376,11 +410,142 @@ static void free_shm_rpc(struct optee_domain *ctx, uint64_t cookie)
     xfree(shm_rpc);
 }
 
+static struct optee_shm_buf *allocate_optee_shm_buf(struct optee_domain *ctx,
+                                                    uint64_t cookie,
+                                                    unsigned int pages_cnt,
+                                                    struct page_info *pg_list,
+                                                    unsigned int pg_list_order)
+{
+    struct optee_shm_buf *optee_shm_buf, *optee_shm_buf_tmp;
+    int old, new;
+    int err_code;
+
+    do
+    {
+        old = atomic_read(&ctx->optee_shm_buf_pages);
+        new = old + pages_cnt;
+        if ( new >= MAX_TOTAL_SMH_BUF_PG )
+            return ERR_PTR(-ENOMEM);
+    }
+    while ( unlikely(old != atomic_cmpxchg(&ctx->optee_shm_buf_pages,
+                                           old, new)) );
+
+    /*
+     * TODO: Guest can try to register many small buffers, thus, forcing
+     * XEN to allocate context for every buffer. Probably we need to
+     * limit not only total number of pages pinned but also number
+     * of buffer objects.
+     */
+    optee_shm_buf = xzalloc_bytes(sizeof(struct optee_shm_buf) +
+                                  pages_cnt * sizeof(struct page *));
+    if ( !optee_shm_buf )
+    {
+        err_code = -ENOMEM;
+        goto err;
+    }
+
+    optee_shm_buf->cookie = cookie;
+    optee_shm_buf->pg_list = pg_list;
+    optee_shm_buf->pg_list_order = pg_list_order;
+
+    spin_lock(&ctx->lock);
+    /* Check if there is already SHM with the same cookie */
+    list_for_each_entry( optee_shm_buf_tmp, &ctx->optee_shm_buf_list, list )
+    {
+        if ( optee_shm_buf_tmp->cookie == cookie )
+        {
+            spin_unlock(&ctx->lock);
+            gdprintk(XENLOG_WARNING, "Guest tries to use the same SHM buffer cookie %lx\n",
+                     cookie);
+            err_code = -EINVAL;
+            goto err;
+        }
+    }
+
+    list_add_tail(&optee_shm_buf->list, &ctx->optee_shm_buf_list);
+    spin_unlock(&ctx->lock);
+
+    return optee_shm_buf;
+
+err:
+    xfree(optee_shm_buf);
+    atomic_sub(pages_cnt, &ctx->optee_shm_buf_pages);
+
+    return ERR_PTR(err_code);
+}
+
+static void free_pg_list(struct optee_shm_buf *optee_shm_buf)
+{
+    if ( optee_shm_buf->pg_list )
+    {
+        free_domheap_pages(optee_shm_buf->pg_list,
+                           optee_shm_buf->pg_list_order);
+        optee_shm_buf->pg_list = NULL;
+    }
+}
+
+static void free_optee_shm_buf(struct optee_domain *ctx, uint64_t cookie)
+{
+    struct optee_shm_buf *optee_shm_buf;
+    unsigned int i;
+    bool found = false;
+
+    spin_lock(&ctx->lock);
+    list_for_each_entry( optee_shm_buf, &ctx->optee_shm_buf_list, list )
+    {
+        if ( optee_shm_buf->cookie == cookie )
+        {
+            found = true;
+            list_del(&optee_shm_buf->list);
+            break;
+        }
+    }
+    spin_unlock(&ctx->lock);
+
+    if ( !found )
+        return;
+
+    for ( i = 0; i < optee_shm_buf->page_cnt; i++ )
+        if ( optee_shm_buf->pages[i] )
+            put_page(optee_shm_buf->pages[i]);
+
+    free_pg_list(optee_shm_buf);
+
+    atomic_sub(optee_shm_buf->page_cnt, &ctx->optee_shm_buf_pages);
+
+    xfree(optee_shm_buf);
+}
+
+static void free_optee_shm_buf_pg_list(struct optee_domain *ctx,
+                                       uint64_t cookie)
+{
+    struct optee_shm_buf *optee_shm_buf;
+    bool found = false;
+
+    spin_lock(&ctx->lock);
+    list_for_each_entry( optee_shm_buf, &ctx->optee_shm_buf_list, list )
+    {
+        if ( optee_shm_buf->cookie == cookie )
+        {
+            found = true;
+            break;
+        }
+    }
+    spin_unlock(&ctx->lock);
+
+    if ( found )
+        free_pg_list(optee_shm_buf);
+    else
+        gdprintk(XENLOG_ERR, "Can't find pagelist for SHM buffer with cookie %lx to free it\n",
+                 cookie);
+}
+
 static int optee_relinquish_resources(struct domain *d)
 {
     struct arm_smccc_res resp;
     struct optee_std_call *call, *call_tmp;
     struct shm_rpc *shm_rpc, *shm_rpc_tmp;
+    struct optee_shm_buf *optee_shm_buf, *optee_shm_buf_tmp;
     struct optee_domain *ctx = d->arch.tee;
 
     if ( !ctx )
@@ -407,6 +572,17 @@ static int optee_relinquish_resources(struct domain *d)
     if ( hypercall_preempt_check() )
         return -ERESTART;
 
+    /*
+     * TODO: Guest can pin up to MAX_TOTAL_SMH_BUF_PG pages and all of
+     * them will be put in this loop. It is worth considering to
+     * check for preemption inside the loop.
+     */
+    list_for_each_entry_safe( optee_shm_buf, optee_shm_buf_tmp,
+                              &ctx->optee_shm_buf_list, list )
+        free_optee_shm_buf(ctx, optee_shm_buf->cookie);
+
+    if ( hypercall_preempt_check() )
+        return -ERESTART;
     /*
      * Inform OP-TEE that domain is shutting down. This is
      * also a fast SMC call, like OPTEE_SMC_VM_CREATED, so
@@ -421,6 +597,7 @@ static int optee_relinquish_resources(struct domain *d)
 
     ASSERT(!spin_is_locked(&ctx->lock));
     ASSERT(!atomic_read(&ctx->call_count));
+    ASSERT(!atomic_read(&ctx->optee_shm_buf_pages));
     ASSERT(list_empty(&ctx->shm_rpc_list));
 
     XFREE(d->arch.tee);
@@ -428,6 +605,189 @@ static int optee_relinquish_resources(struct domain *d)
     return 0;
 }
 
+#define PAGELIST_ENTRIES_PER_PAGE                       \
+    ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(u64)) - 1)
+
+static size_t get_pages_list_size(size_t num_entries)
+{
+    int pages = DIV_ROUND_UP(num_entries, PAGELIST_ENTRIES_PER_PAGE);
+
+    return pages * OPTEE_MSG_NONCONTIG_PAGE_SIZE;
+}
+
+static int translate_noncontig(struct optee_domain *ctx,
+                               struct optee_std_call *call,
+                               struct optee_msg_param *param)
+{
+    uint64_t size;
+    unsigned int offset;
+    unsigned int pg_count;
+    unsigned int order;
+    unsigned int idx = 0;
+    gfn_t gfn;
+    struct page_info *guest_pg, *xen_pgs;
+    struct optee_shm_buf *optee_shm_buf;
+    /*
+     * This is memory layout for page list. Basically list consists of 4k pages,
+     * every page store 511 page addresses of user buffer and page address of
+     * the next page of list.
+     *
+     * Refer to OPTEE_MSG_ATTR_NONCONTIG description in optee_msg.h for details.
+     */
+    struct {
+        uint64_t pages_list[PAGELIST_ENTRIES_PER_PAGE];
+        uint64_t next_page_data;
+    } *guest_data, *xen_data;
+
+    /* Offset of user buffer withing OPTEE_MSG_NONCONTIG_PAGE_SIZE-sized page */
+    offset = param->u.tmem.buf_ptr & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1);
+
+    /* Size of the user buffer in bytes */
+    size = ROUNDUP(param->u.tmem.size + offset, OPTEE_MSG_NONCONTIG_PAGE_SIZE);
+
+    pg_count = DIV_ROUND_UP(size, OPTEE_MSG_NONCONTIG_PAGE_SIZE);
+    order = get_order_from_bytes(get_pages_list_size(pg_count));
+
+    /*
+     * In the worst case we will want to allocate 33 pages, which is
+     * MAX_TOTAL_SMH_BUF_PG/511 rounded up. This gives order 6 or at
+     * most 64 pages allocated. This buffer will be freed right after
+     * the end of the call and there can be no more than
+     * max_optee_threads calls simultaneously. So in the worst case
+     * guest can trick us to allocate 64 * max_optee_threads pages in
+     * total.
+     */
+    xen_pgs = alloc_domheap_pages(current->domain, order, 0);
+    if ( !xen_pgs )
+        return -ENOMEM;
+
+    optee_shm_buf = allocate_optee_shm_buf(ctx, param->u.tmem.shm_ref,
+                                           pg_count, xen_pgs, order);
+    if ( IS_ERR(optee_shm_buf) )
+        return PTR_ERR(optee_shm_buf);
+
+    gfn = gaddr_to_gfn(param->u.tmem.buf_ptr &
+                       ~(OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
+
+    while ( pg_count )
+    {
+        struct page_info *page;
+
+        if ( idx == 0 )
+        {
+            guest_pg = get_domain_ram_page(gfn);
+            if ( !guest_pg )
+                return -EINVAL;
+
+            guest_data = __map_domain_page(guest_pg);
+            xen_data = __map_domain_page(xen_pgs);
+        }
+
+        /*
+         * TODO: That function can pin up to 64MB of guest memory by
+         * calling lookup_and_pin_guest_ram_addr() 16384 times
+         * (assuming that PAGE_SIZE equals to 4096).
+         * This should be addressed before declaring OP-TEE security
+         * supported.
+         */
+        BUILD_BUG_ON(PAGE_SIZE != 4096);
+        page = get_domain_ram_page(gaddr_to_gfn(guest_data->pages_list[idx]));
+        if ( !page )
+            goto err_unmap;
+
+        optee_shm_buf->pages[optee_shm_buf->page_cnt++] = page;
+        xen_data->pages_list[idx] = page_to_maddr(page);
+        idx++;
+
+        if ( idx == PAGELIST_ENTRIES_PER_PAGE )
+        {
+            /* Roll over to the next page */
+            xen_data->next_page_data = page_to_maddr(xen_pgs + 1);
+            xen_pgs++;
+
+            gfn = gaddr_to_gfn(guest_data->next_page_data);
+
+            unmap_domain_page(xen_data);
+            unmap_domain_page(guest_data);
+            put_page(guest_pg);
+
+            idx = 0;
+        }
+        pg_count--;
+    }
+
+    if ( idx )
+    {
+        unmap_domain_page(guest_data);
+        unmap_domain_page(xen_data);
+        put_page(guest_pg);
+    }
+    param->u.tmem.buf_ptr = page_to_maddr(optee_shm_buf->pg_list) | offset;
+
+    return 0;
+
+err_unmap:
+    unmap_domain_page(guest_data);
+    unmap_domain_page(xen_data);
+    put_page(guest_pg);
+    free_optee_shm_buf(ctx, optee_shm_buf->cookie);
+
+    return -EINVAL;
+}
+
+static int translate_params(struct optee_domain *ctx,
+                            struct optee_std_call *call)
+{
+    unsigned int i;
+    uint32_t attr;
+    int ret = 0;
+
+    for ( i = 0; i < call->xen_arg->num_params; i++ )
+    {
+        attr = call->xen_arg->params[i].attr;
+
+        switch ( attr & OPTEE_MSG_ATTR_TYPE_MASK )
+        {
+        case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
+        case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
+        case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
+            if ( attr & OPTEE_MSG_ATTR_NONCONTIG )
+            {
+                ret = translate_noncontig(ctx, call, call->xen_arg->params + i);
+                if ( ret )
+                    goto out;
+            }
+            else
+            {
+                gdprintk(XENLOG_WARNING, "Guest tries to use old tmem arg\n");
+                ret = -EINVAL;
+                goto out;
+            }
+            break;
+        case OPTEE_MSG_ATTR_TYPE_NONE:
+        case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
+        case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
+        case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
+        case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
+        case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
+        case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
+            continue;
+        }
+    }
+
+out:
+    if ( ret )
+    {
+        call->xen_arg->ret_origin = TEEC_ORIGIN_COMMS;
+        if ( ret == -ENOMEM )
+            call->xen_arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
+        else
+            call->xen_arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+    }
+
+    return ret;
+}
+
 /*
  * Copy command buffer into domheap memory to:
  * 1) Hide translated addresses from guest
@@ -549,6 +909,27 @@ static void copy_std_request_back(struct optee_domain *ctx,
     put_page(page);
 }
 
+
+static void free_shm_buffers(struct optee_domain *ctx,
+                             struct optee_msg_arg *arg)
+{
+    unsigned int i;
+
+    for ( i = 0; i < arg->num_params; i ++ )
+    {
+        switch ( arg->params[i].attr & OPTEE_MSG_ATTR_TYPE_MASK )
+        {
+        case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
+        case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
+        case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
+            free_optee_shm_buf(ctx, arg->params[i].u.tmem.shm_ref);
+            break;
+        default:
+            break;
+        }
+    }
+}
+
 /* Handle RPC return from OP-TEE */
 static void handle_rpc_return(struct arm_smccc_res *res,
                               struct cpu_user_regs *regs,
@@ -574,6 +955,8 @@ static void handle_rpc_return(struct arm_smccc_res *res,
  * If this is RPC - we need to store call context and return back to guest.
  * If call is complete - we need to return results with copy_std_request_back()
  * and then we will destroy the call context as it is not needed anymore.
+ *
+ * Shared buffers should be handled in a special way.
  */
 static void do_call_with_arg(struct optee_domain *ctx,
                              struct optee_std_call *call,
@@ -597,6 +980,27 @@ static void do_call_with_arg(struct optee_domain *ctx,
     copy_std_request_back(ctx, regs, call);
     set_user_reg(regs, 0, res.a0);
 
+    switch ( call->xen_arg->cmd )
+    {
+    case OPTEE_MSG_CMD_REGISTER_SHM:
+        if ( call->xen_arg->ret == 0 )
+            /* OP-TEE registered buffer, we don't need pg_list anymore */
+            free_optee_shm_buf_pg_list(ctx,
+                                       call->xen_arg->params[0].u.tmem.shm_ref);
+        else
+            /* OP-TEE failed to register buffer, we need to unpin guest pages */
+            free_optee_shm_buf(ctx, call->xen_arg->params[0].u.tmem.shm_ref);
+        break;
+    case OPTEE_MSG_CMD_UNREGISTER_SHM:
+        if ( call->xen_arg->ret == 0 )
+            /* Now we can unpin guest pages */
+            free_optee_shm_buf(ctx, call->xen_arg->params[0].u.rmem.shm_ref);
+        break;
+    default:
+        /* Free any temporary shared buffers */
+        free_shm_buffers(ctx, call->xen_arg);
+    }
+
     put_std_call(ctx, call);
     free_std_call(ctx, call);
 }
@@ -658,6 +1062,18 @@ static void handle_std_call(struct optee_domain *ctx,
     case OPTEE_MSG_CMD_CANCEL:
     case OPTEE_MSG_CMD_REGISTER_SHM:
     case OPTEE_MSG_CMD_UNREGISTER_SHM:
+        if( translate_params(ctx, call) )
+        {
+            /*
+             * translate_params() sets xen_arg->ret value to non-zero.
+             * So, technically, SMC was successful, but there was an error
+             * during handling standard call encapsulated into this SMC.
+             */
+            copy_std_request_back(ctx, regs, call);
+            set_user_reg(regs, 0, OPTEE_SMC_RETURN_OK);
+            goto err;
+        }
+
         xen_addr = page_to_maddr(call->xen_arg_pg);
         uint64_to_regpair(&a1, &a2, xen_addr);
 
-- 
2.21.0

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply index

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-11 18:46 [Xen-devel] [PATCH v6 00/10] TEE mediator (and OP-TEE) support in XEN Volodymyr Babchuk
2019-06-11 18:46 ` [Xen-devel] [PATCH v6 01/10] xen/arm: add generic TEE mediator framework Volodymyr Babchuk
2019-06-17 16:11   ` Stefano Stabellini
2019-06-11 18:46 ` [Xen-devel] [PATCH v6 02/10] xen/arm: optee: add OP-TEE header files Volodymyr Babchuk
2019-06-15 18:39   ` Julien Grall
2019-06-17 15:24     ` Julien Grall
2019-06-17 16:28       ` Stefano Stabellini
2019-06-17 16:34         ` Julien Grall
2019-06-17 17:28           ` Stefano Stabellini
2019-06-19  8:20             ` Lars Kurth
2019-06-19 10:26               ` Julien Grall
2019-06-11 18:46 ` [Xen-devel] [PATCH v6 03/10] xen/arm: optee: add OP-TEE mediator skeleton Volodymyr Babchuk
2019-06-19 11:01   ` Julien Grall
2019-06-19 11:03     ` Julien Grall
2019-06-19 15:44       ` Volodymyr Babchuk
2019-06-11 18:46 ` [Xen-devel] [PATCH v6 04/10] xen/arm: optee: add fast calls handling Volodymyr Babchuk
2019-06-11 18:46 ` [Xen-devel] [PATCH v6 05/10] xen/arm: optee: add std call handling Volodymyr Babchuk
2019-06-11 18:46 ` [Xen-devel] [PATCH v6 06/10] xen/arm: optee: add support for RPC SHM buffers Volodymyr Babchuk
2019-06-11 18:46 ` Volodymyr Babchuk [this message]
2019-06-11 18:46 ` [Xen-devel] [PATCH v6 08/10] xen/arm: optee: add support for RPC commands Volodymyr Babchuk
2019-06-11 18:46 ` [Xen-devel] [PATCH v6 09/10] tools/arm: tee: add "tee" option for xl.cfg Volodymyr Babchuk
2019-06-15 19:10   ` Julien Grall
2019-06-18 11:19     ` Volodymyr Babchuk
2019-06-18 12:49       ` Julien Grall
2019-06-18 14:30         ` Volodymyr Babchuk
2019-06-18 15:19           ` Julien Grall
2019-06-18 15:23             ` Volodymyr Babchuk
2019-06-19 10:30               ` Julien Grall
2019-06-11 18:46 ` [Xen-devel] [PATCH v6 10/10] tools/arm: optee: create optee firmware node in DT if tee=optee Volodymyr Babchuk
2019-06-19 11:08 ` [Xen-devel] [PATCH v6 00/10] TEE mediator (and OP-TEE) support in XEN Julien Grall

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190611184541.7281-8-volodymyr_babchuk@epam.com \
    --to=volodymyr_babchuk@epam.com \
    --cc=julien.grall@arm.com \
    --cc=sstabellini@kernel.org \
    --cc=tee-dev@lists.linaro.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Xen-Devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/xen-devel/0 xen-devel/git/0.git
	git clone --mirror https://lore.kernel.org/xen-devel/1 xen-devel/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 xen-devel xen-devel/ https://lore.kernel.org/xen-devel \
		xen-devel@lists.xenproject.org xen-devel@lists.xen.org xen-devel@archiver.kernel.org
	public-inbox-index xen-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.xenproject.lists.xen-devel


AGPL code for this site: git clone https://public-inbox.org/ public-inbox