diff mbox series

[v6,03/10] xen/arm: optee: add OP-TEE mediator skeleton

Message ID 20190611184541.7281-4-volodymyr_babchuk@epam.com (mailing list archive)
State Superseded
Headers show
Series TEE mediator (and OP-TEE) support in XEN | expand

Commit Message

Volodymyr Babchuk June 11, 2019, 6:46 p.m. UTC
Add very basic OP-TEE mediator. It can probe for OP-TEE presence,
tell it about domain creation/destruction and then return an error
to all calls to the guest.

This code issues two non-preemptible calls to OP-TEE: to create and
to destroy client context. They can't block in OP-TEE, as they are
considered "fast calls" in terms of ARM SMCCC.

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 v4:
  - Removed OPTEE_ENABLED macro. Empty (for now) struct optee_domain
    is used instead.
  - Removed forward_call() function, mediator now will return
    OPTEE_SMC_RETURN_ENOTAVAIL for all unimplemented calls
  - Fixed mistake when OPTEE_SMC_FUNCID_GET_OS_REVISION instead of
    OPTEE_SMC_CALL_GET_OS_REVISION was used
  - OP-TEE is informed about domain destruction in
    optee_relinquish_resources()
  - removed optee_domain_destroy() function because all job is done
    in the optee_relinquish_resources() function

Changes from v3:
  - Introduced optee_relinquish_resources() function to free
    mediator resources in a more controllable way

Changes from v2:
  - Fixed coding style
  - Introduced tee/Kconfig
  - Fixed error messages
---
 xen/arch/arm/Kconfig          |   2 +
 xen/arch/arm/domain.c         |   3 +-
 xen/arch/arm/tee/Kconfig      |   4 +
 xen/arch/arm/tee/Makefile     |   1 +
 xen/arch/arm/tee/optee.c      | 166 ++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/domain.h  |   3 +
 xen/include/public/arch-arm.h |   1 +
 7 files changed, 179 insertions(+), 1 deletion(-)
 create mode 100644 xen/arch/arm/tee/Kconfig
 create mode 100644 xen/arch/arm/tee/optee.c

Comments

Julien Grall June 19, 2019, 11:01 a.m. UTC | #1
Hi Volodymyr,

On 11/06/2019 19:46, Volodymyr Babchuk wrote:
> diff --git a/xen/arch/arm/tee/Kconfig b/xen/arch/arm/tee/Kconfig
> new file mode 100644
> index 0000000000..5b829db2e9
> --- /dev/null
> +++ b/xen/arch/arm/tee/Kconfig
> @@ -0,0 +1,4 @@
> +config OPTEE
> +	bool "Enable OP-TEE mediator"
> +	default n
> +	depends on TEE

I have played a bit with the menuconfig that "Enable OP-TEE mediator" will 
appear at the top-level while "Enable TEE mediators support" is under 
"Architecture features".

Arguably, both should be under "Device Drivers". Can you send a follow-up patch 
to fix that up?

While you are doing that, can you add a description in "Enable OP-TEE mediator" 
explaining this require a virtualization-aware OP-TEE in order to work.

Cheers,
Julien Grall June 19, 2019, 11:03 a.m. UTC | #2
On 19/06/2019 12:01, Julien Grall wrote:
> Hi Volodymyr,
> 
> On 11/06/2019 19:46, Volodymyr Babchuk wrote:
>> diff --git a/xen/arch/arm/tee/Kconfig b/xen/arch/arm/tee/Kconfig
>> new file mode 100644
>> index 0000000000..5b829db2e9
>> --- /dev/null
>> +++ b/xen/arch/arm/tee/Kconfig
>> @@ -0,0 +1,4 @@
>> +config OPTEE
>> +    bool "Enable OP-TEE mediator"
>> +    default n
>> +    depends on TEE
> 
> I have played a bit with the menuconfig that "Enable OP-TEE mediator" will 
> appear at the top-level while "Enable TEE mediators support" is under 
> "Architecture features".
> 
> Arguably, both should be under "Device Drivers". Can you send a follow-up patch 
> to fix that up?

Another alternative is moving the two in "Architecture features" with "Enable 
OP-TEE mediator" under "Enable TEE mediator supports".

> 
> While you are doing that, can you add a description in "Enable OP-TEE mediator" 
> explaining this require a virtualization-aware OP-TEE in order to work.
> 
> Cheers,
>
Volodymyr Babchuk June 19, 2019, 3:44 p.m. UTC | #3
Hi Julien,

Julien Grall writes:

> On 19/06/2019 12:01, Julien Grall wrote:
>> Hi Volodymyr,
>>
>> On 11/06/2019 19:46, Volodymyr Babchuk wrote:
>>> diff --git a/xen/arch/arm/tee/Kconfig b/xen/arch/arm/tee/Kconfig
>>> new file mode 100644
>>> index 0000000000..5b829db2e9
>>> --- /dev/null
>>> +++ b/xen/arch/arm/tee/Kconfig
>>> @@ -0,0 +1,4 @@
>>> +config OPTEE
>>> + bool "Enable OP-TEE mediator"
>>> + default n
>>> + depends on TEE
>>
>> I have played a bit with the menuconfig that "Enable OP-TEE
>> mediator" will appear at the top-level while "Enable TEE mediators
>> support" is under "Architecture features".
>>
>> Arguably, both should be under "Device Drivers". Can you send a
>> follow-up patch to fix that up?
>
> Another alternative is moving the two in "Architecture features" with
> "Enable OP-TEE mediator" under "Enable TEE mediator supports".
>
I'll do in this way, if there is no objections. As TEE is not a device,
strictly speaking, I don't think that "Device Drivers" is a good place
for it.
diff mbox series

Patch

diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index caaf377a33..04d399ffbf 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -238,3 +238,5 @@  source "arch/arm/platforms/Kconfig"
 source "common/Kconfig"
 
 source "drivers/Kconfig"
+
+source "arch/arm/tee/Kconfig"
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index d27a137f7a..e8657447d7 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -648,7 +648,8 @@  int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
         return -EINVAL;
     }
 
-    if ( config->arch.tee_type != XEN_DOMCTL_CONFIG_TEE_NONE )
+    if ( config->arch.tee_type != XEN_DOMCTL_CONFIG_TEE_NONE &&
+         config->arch.tee_type != tee_get_type() )
     {
         dprintk(XENLOG_INFO, "Unsupported TEE type\n");
         return -EINVAL;
diff --git a/xen/arch/arm/tee/Kconfig b/xen/arch/arm/tee/Kconfig
new file mode 100644
index 0000000000..5b829db2e9
--- /dev/null
+++ b/xen/arch/arm/tee/Kconfig
@@ -0,0 +1,4 @@ 
+config OPTEE
+	bool "Enable OP-TEE mediator"
+	default n
+	depends on TEE
diff --git a/xen/arch/arm/tee/Makefile b/xen/arch/arm/tee/Makefile
index c54d4796ff..982c879684 100644
--- a/xen/arch/arm/tee/Makefile
+++ b/xen/arch/arm/tee/Makefile
@@ -1 +1,2 @@ 
 obj-y += tee.o
+obj-$(CONFIG_OPTEE) += optee.o
diff --git a/xen/arch/arm/tee/optee.c b/xen/arch/arm/tee/optee.c
new file mode 100644
index 0000000000..e9b69bd2d2
--- /dev/null
+++ b/xen/arch/arm/tee/optee.c
@@ -0,0 +1,166 @@ 
+/*
+ * xen/arch/arm/tee/optee.c
+ *
+ * OP-TEE mediator. It sits in between OP-TEE and guests and performs
+ * actual calls to OP-TEE when some guest tries to interact with
+ * OP-TEE. As OP-TEE does not know about second stage MMU translation,
+ * mediator does this translation and performs other housekeeping tasks.
+ *
+ * OP-TEE ABI/protocol is described in two header files:
+ *  - optee_smc.h provides information about SMCs: all possible calls,
+ *    register allocation and return codes.
+ *  - optee_msg.h provides format for messages that are passed with
+ *    standard call OPTEE_SMC_CALL_WITH_ARG.
+ *
+ * Volodymyr Babchuk <volodymyr_babchuk@epam.com>
+ * Copyright (c) 2018-2019 EPAM Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/device_tree.h>
+#include <xen/sched.h>
+
+#include <asm/smccc.h>
+#include <asm/tee/tee.h>
+#include <asm/tee/optee_msg.h>
+#include <asm/tee/optee_smc.h>
+
+/* Client ID 0 is reserved for the hypervisor itself */
+#define OPTEE_CLIENT_ID(domain) ((domain)->domain_id + 1)
+
+/* Domain context */
+struct optee_domain {
+};
+
+static bool optee_probe(void)
+{
+    struct dt_device_node *node;
+    struct arm_smccc_res resp;
+
+    /* Check for entry in dtb */
+    node = dt_find_compatible_node(NULL, NULL, "linaro,optee-tz");
+    if ( !node )
+        return false;
+
+    /* Check UID */
+    arm_smccc_smc(ARM_SMCCC_CALL_UID_FID(TRUSTED_OS_END), &resp);
+
+    if ( (uint32_t)resp.a0 != OPTEE_MSG_UID_0 ||
+         (uint32_t)resp.a1 != OPTEE_MSG_UID_1 ||
+         (uint32_t)resp.a2 != OPTEE_MSG_UID_2 ||
+         (uint32_t)resp.a3 != OPTEE_MSG_UID_3 )
+        return false;
+
+    return true;
+}
+
+static int optee_domain_init(struct domain *d)
+{
+    struct arm_smccc_res resp;
+    struct optee_domain *ctx;
+
+    ctx = xzalloc(struct optee_domain);
+    if ( !ctx )
+        return -ENOMEM;
+
+    /*
+     * Inform OP-TEE about a new guest.  This is a "Fast" call in
+     * terms of OP-TEE. This basically means that it can't be
+     * preempted, because there is no thread allocated for it in
+     * OP-TEE. No blocking calls can be issued and interrupts are
+     * disabled.
+     *
+     * a7 should be 0, so we can't skip last 6 parameters of arm_smccc_smc()
+     */
+    arm_smccc_smc(OPTEE_SMC_VM_CREATED, OPTEE_CLIENT_ID(d), 0, 0, 0, 0, 0, 0,
+                  &resp);
+    if ( resp.a0 != OPTEE_SMC_RETURN_OK )
+    {
+        printk(XENLOG_WARNING "%pd: Unable to create OPTEE client: rc = 0x%X\n",
+               d, (uint32_t)resp.a0);
+
+        xfree(ctx);
+
+        return -ENODEV;
+    }
+
+    d->arch.tee = ctx;
+
+    return 0;
+}
+
+static int optee_relinquish_resources(struct domain *d)
+{
+    struct arm_smccc_res resp;
+
+    if ( !d->arch.tee )
+        return 0;
+
+    /*
+     * Inform OP-TEE that domain is shutting down. This is
+     * also a fast SMC call, like OPTEE_SMC_VM_CREATED, so
+     * it is also non-preemptible.
+     * At this time all domain VCPUs should be stopped. OP-TEE
+     * relies on this.
+     *
+     * a7 should be 0, so we can't skip last 6 parameters of arm_smccc_smc()
+     */
+    arm_smccc_smc(OPTEE_SMC_VM_DESTROYED, OPTEE_CLIENT_ID(d), 0, 0, 0, 0, 0, 0,
+                  &resp);
+
+    XFREE(d->arch.tee);
+
+    return 0;
+}
+
+static bool optee_handle_call(struct cpu_user_regs *regs)
+{
+    if ( !current->domain->arch.tee )
+        return false;
+
+    switch ( get_user_reg(regs, 0) )
+    {
+    case OPTEE_SMC_CALLS_COUNT:
+    case OPTEE_SMC_CALLS_UID:
+    case OPTEE_SMC_CALLS_REVISION:
+    case OPTEE_SMC_CALL_GET_OS_UUID:
+    case OPTEE_SMC_CALL_GET_OS_REVISION:
+    case OPTEE_SMC_ENABLE_SHM_CACHE:
+    case OPTEE_SMC_DISABLE_SHM_CACHE:
+    case OPTEE_SMC_GET_SHM_CONFIG:
+    case OPTEE_SMC_EXCHANGE_CAPABILITIES:
+    case OPTEE_SMC_CALL_WITH_ARG:
+    case OPTEE_SMC_CALL_RETURN_FROM_RPC:
+        set_user_reg(regs, 0, OPTEE_SMC_RETURN_ENOTAVAIL);
+        return true;
+
+    default:
+        return false;
+    }
+}
+
+static const struct tee_mediator_ops optee_ops =
+{
+    .probe = optee_probe,
+    .domain_init = optee_domain_init,
+    .relinquish_resources = optee_relinquish_resources,
+    .handle_call = optee_handle_call,
+};
+
+REGISTER_TEE_MEDIATOR(optee, "OP-TEE", XEN_DOMCTL_CONFIG_TEE_OPTEE, &optee_ops);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 0f15372098..2960a53e69 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -98,6 +98,9 @@  struct arch_domain
     struct vpl011 vpl011;
 #endif
 
+#ifdef CONFIG_TEE
+    void *tee;
+#endif
 }  __cacheline_aligned;
 
 struct arch_vcpu
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index bb69c380ec..3e8cdc151d 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -306,6 +306,7 @@  DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
 #define XEN_DOMCTL_CONFIG_GIC_V3        2
 
 #define XEN_DOMCTL_CONFIG_TEE_NONE      0
+#define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
 
 struct xen_arch_domainconfig {
     /* IN/OUT */