]> xenbits.xensource.com Git - people/dariof/xen.git/commitdiff
xen/arm: add generic TEE mediator framework
authorVolodymyr Babchuk <Volodymyr_Babchuk@epam.com>
Tue, 11 Jun 2019 18:46:17 +0000 (18:46 +0000)
committerJulien Grall <julien.grall@arm.com>
Wed, 19 Jun 2019 10:53:18 +0000 (11:53 +0100)
This patch adds basic framework for TEE mediators. Guests can't talk
to TEE directly, we need some entity that will intercept request
and decide what to do with them. "TEE mediator" is a such entity.

This is how it works: user can build XEN with multiple TEE mediators
(see the next patches, where OP-TEE mediator is introduced).
TEE mediator register self with REGISTER_TEE_MEDIATOR() macro in the
same way, as device drivers use DT_DEVICE_START()/DT_DEVICE_END()
macros.

At run-time, during initialization, framework calls probe() function
for each available mediator driver to find which TEE is installed
on the platform. Then generic vSMC handler will call selected mediator
when it intercept SMC/HVC that belongs to TEE OS or TEE application.

Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@epam.com>
Reviewed-by: Julien Grall <julien.grall@arm.com>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
12 files changed:
MAINTAINERS
xen/arch/arm/Kconfig
xen/arch/arm/Makefile
xen/arch/arm/domain.c
xen/arch/arm/setup.c
xen/arch/arm/tee/Makefile [new file with mode: 0644]
xen/arch/arm/tee/tee.c [new file with mode: 0644]
xen/arch/arm/vsmc.c
xen/arch/arm/xen.lds.S
xen/include/asm-arm/domain.h
xen/include/asm-arm/tee/tee.h [new file with mode: 0644]
xen/include/public/arch-arm.h

index 6fbdc2bdcbb1cddc479b4a7bd37bf1e31731e141..ab32e7f409c6247f0198b53a8932dfb8bee72ffd 100644 (file)
@@ -381,6 +381,12 @@ F: config/Stubdom.mk.in
 F:     m4/stubdom.m4
 F:     stubdom/
 
+TEE MEDIATORS
+M:     Volodymyr Babchuk <volodymyr_babchuk@epam.com>
+S:     Supported
+F:     xen/arch/arm/tee/
+F:     xen/include/asm-arm/tee
+
 TOOLSTACK
 M:     Ian Jackson <ian.jackson@eu.citrix.com>
 M:     Wei Liu <wl@xen.org>
index 585b57f023865c46f3376b5c54b42dde9e5e996c..caaf377a33c2a86a7270af30fdeae8078cc61c80 100644 (file)
@@ -106,6 +106,13 @@ config HARDEN_BRANCH_PREDICTOR
 
          If unsure, say Y.
 
+config TEE
+       bool "Enable TEE mediators support" if EXPERT = "y"
+       default n
+       help
+         This option enables generic TEE mediators support. It allows guests
+         to access real TEE via one of TEE mediators implemented in XEN.
+
 endmenu
 
 menu "ARM errata workaround via the alternative framework"
index 872a155b60767773fe73cf76e23b94ca7c4439b9..70f532e42a06326618f0efc7d75de5c970cb1c4c 100644 (file)
@@ -5,6 +5,7 @@ subdir-$(CONFIG_ACPI) += acpi
 ifneq ($(CONFIG_NO_PLAT),y)
 subdir-y += platforms
 endif
+subdir-$(CONFIG_TEE) += tee
 
 obj-$(CONFIG_HAS_ALTERNATIVE) += alternative.o
 obj-y += bootfdt.init.o
index ef0c656b6fa2a3fec027a1af0947d8445a247cad..f84a8ae90e1648fa3f5690655a6df04c7834a5b3 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/platform.h>
 #include <asm/procinfo.h>
 #include <asm/regs.h>
+#include <asm/tee/tee.h>
 #include <asm/vfp.h>
 #include <asm/vgic.h>
 #include <asm/vtimer.h>
@@ -648,6 +649,12 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
         return -EINVAL;
     }
 
+    if ( config->arch.tee_type != XEN_DOMCTL_CONFIG_TEE_NONE )
+    {
+        dprintk(XENLOG_INFO, "Unsupported TEE type\n");
+        return -EINVAL;
+    }
+
     return 0;
 }
 
@@ -705,6 +712,9 @@ int arch_domain_create(struct domain *d,
     if ( (rc = domain_vtimer_init(d, &config->arch)) != 0 )
         goto fail;
 
+    if ( (rc = tee_domain_init(d, config->arch.tee_type)) != 0 )
+        goto fail;
+
     update_domain_wallclock_time(d);
 
     /*
@@ -949,6 +959,14 @@ int domain_relinquish_resources(struct domain *d)
          */
         domain_vpl011_deinit(d);
 
+        d->arch.relmem = RELMEM_tee;
+        /* Fallthrough */
+
+    case RELMEM_tee:
+        ret = tee_relinquish_resources(d);
+        if (ret )
+            return ret;
+
         d->arch.relmem = RELMEM_xen;
         /* Fallthrough */
 
index 21127155794ef8c8c990487a9db2334f93b8ed51..4156c0ebb330627c19f7ce653c512562c5f760dd 100644 (file)
@@ -50,6 +50,7 @@
 #include <asm/platform.h>
 #include <asm/procinfo.h>
 #include <asm/setup.h>
+#include <asm/tee/tee.h>
 #include <xsm/xsm.h>
 #include <asm/acpi.h>
 
@@ -903,6 +904,7 @@ void __init start_xen(unsigned long boot_phys_offset,
     dom0_cfg.arch.nr_spis = min(gic_number_lines(), (unsigned int) 992) - 32;
     if ( gic_number_lines() > 992 )
         printk(XENLOG_WARNING "Maximum number of vGIC IRQs exceeded.\n");
+    dom0_cfg.arch.tee_type = tee_get_type();
     dom0_cfg.max_vcpus = dom0_max_vcpus();
 
     dom0 = domain_create(0, &dom0_cfg, true);
diff --git a/xen/arch/arm/tee/Makefile b/xen/arch/arm/tee/Makefile
new file mode 100644 (file)
index 0000000..c54d479
--- /dev/null
@@ -0,0 +1 @@
+obj-y += tee.o
diff --git a/xen/arch/arm/tee/tee.c b/xen/arch/arm/tee/tee.c
new file mode 100644 (file)
index 0000000..3964a8a
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * xen/arch/arm/tee/tee.c
+ *
+ * Generic part of TEE mediator subsystem
+ *
+ * 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/errno.h>
+#include <xen/init.h>
+#include <xen/types.h>
+
+#include <asm/tee/tee.h>
+
+extern const struct tee_mediator_desc _steemediator[], _eteemediator[];
+static const struct tee_mediator_desc __read_mostly *cur_mediator;
+
+/*
+ * TODO: Add function to alter Dom0 DTB, so we can properly describe
+ * present TEE.
+ */
+
+bool tee_handle_call(struct cpu_user_regs *regs)
+{
+    if ( unlikely(!cur_mediator) )
+        return false;
+
+    return cur_mediator->ops->handle_call(regs);
+}
+
+int tee_domain_init(struct domain *d, uint16_t tee_type)
+{
+    if ( tee_type == XEN_DOMCTL_CONFIG_TEE_NONE )
+        return 0;
+
+    if ( !cur_mediator )
+        return -ENODEV;
+
+    if ( cur_mediator->tee_type != tee_type )
+        return -EINVAL;
+
+    return cur_mediator->ops->domain_init(d);
+}
+
+int tee_relinquish_resources(struct domain *d)
+{
+    if ( !cur_mediator )
+        return 0;
+
+    return cur_mediator->ops->relinquish_resources(d);
+}
+
+uint16_t tee_get_type(void)
+{
+    if ( !cur_mediator )
+        return XEN_DOMCTL_CONFIG_TEE_NONE;
+
+    return cur_mediator->tee_type;
+}
+
+
+static int __init tee_init(void)
+{
+    const struct tee_mediator_desc *desc;
+
+    for ( desc = _steemediator; desc != _eteemediator; desc++ )
+    {
+        if ( desc->ops->probe() )
+        {
+            printk(XENLOG_INFO "Using TEE mediator for %s\n", desc->name);
+            cur_mediator = desc;
+            return 0;
+        }
+    }
+
+    return 0;
+}
+
+__initcall(tee_init);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index c72b9a04ff767972b26868afec5103b5cb5f7422..f8e350311ddbfa2c982d98d7087c5ddc24f7b6d6 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/monitor.h>
 #include <asm/regs.h>
 #include <asm/smccc.h>
+#include <asm/tee/tee.h>
 #include <asm/traps.h>
 #include <asm/vpsci.h>
 #include <asm/platform.h>
@@ -276,6 +277,10 @@ static bool vsmccc_handle_call(struct cpu_user_regs *regs)
         case ARM_SMCCC_OWNER_SIP:
             handled = platform_smc(regs);
             break;
+        case ARM_SMCCC_OWNER_TRUSTED_APP ... ARM_SMCCC_OWNER_TRUSTED_APP_END:
+        case ARM_SMCCC_OWNER_TRUSTED_OS ... ARM_SMCCC_OWNER_TRUSTED_OS_END:
+            handled = tee_handle_call(regs);
+            break;
         }
     }
 
index 1e72906477c823bb8e8fa0502d6a90831e7e8b01..e664c4441a516bda16b4e7c29723fd449365f631 100644 (file)
@@ -137,6 +137,13 @@ SECTIONS
       _aedevice = .;
   } :text
 
+  . = ALIGN(8);
+  .teemediator.info : {
+      _steemediator = .;
+      *(.teemediator.info)
+      _eteemediator = .;
+  } :text
+
   . = ALIGN(PAGE_SIZE);             /* Init code and data */
   __init_begin = .;
   .init.text : {
index 312fec89328187f7614b96d49ac828bbfa75aeb5..0f15372098ad6aa9b2c759062612565dd5689114 100644 (file)
@@ -58,6 +58,7 @@ struct arch_domain
     /* Continuable domain_relinquish_resources(). */
     enum {
         RELMEM_not_started,
+        RELMEM_tee,
         RELMEM_xen,
         RELMEM_page,
         RELMEM_mapping,
diff --git a/xen/include/asm-arm/tee/tee.h b/xen/include/asm-arm/tee/tee.h
new file mode 100644 (file)
index 0000000..f483986
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * xen/include/asm-arm/tee/tee.h
+ *
+ * Generic part of TEE mediator subsystem
+ *
+ * Volodymyr Babchuk <volodymyr_babchuk@epam.com>
+ * Copyright (c) 2018 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.
+ */
+
+#ifndef __ARCH_ARM_TEE_TEE_H__
+#define __ARCH_ARM_TEE_TEE_H__
+
+#include <xen/lib.h>
+#include <xen/types.h>
+
+#include <asm/regs.h>
+
+#ifdef CONFIG_TEE
+
+struct tee_mediator_ops {
+    /*
+     * Probe for TEE. Should return true if TEE found and
+     * mediator is initialized.
+     */
+    bool (*probe)(void);
+
+    /*
+     * Called during domain construction if toolstack requests to enable
+     * TEE support so mediator can inform TEE about new
+     * guest and create own structures for the new domain.
+     */
+    int (*domain_init)(struct domain *d);
+
+    /*
+     * Called during domain destruction to relinquish resources used
+     * by mediator itself. This function can return -ERESTART to indicate
+     * that it does not finished work and should be called again.
+     */
+    int (*relinquish_resources)(struct domain *d);
+
+    /* Handle SMCCC call for current domain. */
+    bool (*handle_call)(struct cpu_user_regs *regs);
+};
+
+struct tee_mediator_desc {
+    /* Printable name of the TEE. */
+    const char *name;
+
+    /* Mediator callbacks as described above. */
+    const struct tee_mediator_ops *ops;
+
+    /*
+     * ID of TEE. Corresponds to xen_arch_domainconfig.tee_type.
+     * Should be one of XEN_DOMCTL_CONFIG_TEE_xxx
+     */
+    uint16_t tee_type;
+};
+
+bool tee_handle_call(struct cpu_user_regs *regs);
+int tee_domain_init(struct domain *d, uint16_t tee_type);
+int tee_relinquish_resources(struct domain *d);
+uint16_t tee_get_type(void);
+
+#define REGISTER_TEE_MEDIATOR(_name, _namestr, _type, _ops)         \
+static const struct tee_mediator_desc __tee_desc_##_name __used     \
+__section(".teemediator.info") = {                                  \
+    .name = _namestr,                                               \
+    .ops = _ops,                                                    \
+    .tee_type = _type                                               \
+}
+
+#else
+
+static inline bool tee_handle_call(struct cpu_user_regs *regs)
+{
+    return false;
+}
+
+static inline int tee_domain_init(struct domain *d, uint16_t tee_type)
+{
+    if ( likely(tee_type == XEN_DOMCTL_CONFIG_TEE_NONE) )
+        return 0;
+
+    return -ENODEV;
+}
+
+static inline int tee_relinquish_resources(struct domain *d)
+{
+    return 0;
+}
+
+static inline uint16_t tee_get_type(void)
+{
+    return XEN_DOMCTL_CONFIG_TEE_NONE;
+}
+
+#endif  /* CONFIG_TEE */
+
+#endif /* __ARCH_ARM_TEE_TEE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index eb424e8286d02abe36a2adaf7c7547db05882103..bb69c380eca287047bee8818231ffc3d3db29527 100644 (file)
@@ -304,10 +304,15 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
 #define XEN_DOMCTL_CONFIG_GIC_NATIVE    0
 #define XEN_DOMCTL_CONFIG_GIC_V2        1
 #define XEN_DOMCTL_CONFIG_GIC_V3        2
+
+#define XEN_DOMCTL_CONFIG_TEE_NONE      0
+
 struct xen_arch_domainconfig {
     /* IN/OUT */
     uint8_t gic_version;
     /* IN */
+    uint16_t tee_type;
+    /* IN */
     uint32_t nr_spis;
     /*
      * OUT