Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx>
---
  Changes from v1:
   - Removed tee_remove() function
   - CONFIG_TEE depends on EXPERT
   - tee_domain_created() converted to tee_enable()
   - tee_init() is called using initcall() mechanism
   - tee_handle_smc() renamed to tee_handle_call()
  Changes from "RFC" version:
   - renamed CONFIG_ARM_TEE to CONFIG_TEE
   - changed discovery mechanism: instead of UUID mathing, TEE-specific
      probing is used
  MAINTAINERS                   |  6 +++
  xen/arch/arm/Kconfig          |  9 +++++
  xen/arch/arm/Makefile         |  1 +
  xen/arch/arm/domain.c         |  4 ++
  xen/arch/arm/domain_build.c   |  4 ++
  xen/arch/arm/setup.c          |  1 +
  xen/arch/arm/shutdown.c       |  1 +
  xen/arch/arm/tee/Kconfig      |  0
  xen/arch/arm/tee/Makefile     |  1 +
  xen/arch/arm/tee/tee.c        | 69 ++++++++++++++++++++++++++++++++
  xen/arch/arm/vsmc.c           |  5 +++
  xen/arch/arm/xen.lds.S        |  7 ++++
  xen/include/asm-arm/tee/tee.h | 91 +++++++++++++++++++++++++++++++++++++++++++
  13 files changed, 199 insertions(+)
  create mode 100644 xen/arch/arm/tee/Kconfig
  create mode 100644 xen/arch/arm/tee/Makefile
  create mode 100644 xen/arch/arm/tee/tee.c
  create mode 100644 xen/include/asm-arm/tee/tee.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 1970100..605e6bd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -376,6 +376,12 @@ F: config/Stubdom.mk.in
  F:    m4/stubdom.m4
  F:    stubdom/
  
+TEE MEDIATORS
+M:     Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx>
+S:     Supported
+F:     xen/arch/arm/tee/
+F:     xen/include/asm-arm/tee
+
  TOOLSTACK
  M:    Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
  M:    Wei Liu <wei.liu2@xxxxxxxxxx>
diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 586bc62..0968378 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -102,6 +102,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"
@@ -227,3 +234,5 @@ source "arch/arm/platforms/Kconfig"
  source "common/Kconfig"
  
  source "drivers/Kconfig"
+
+source "arch/arm/tee/Kconfig"
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 37fa826..630d816 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -3,6 +3,7 @@ subdir-$(CONFIG_ARM_64) += arm64
  subdir-y += platforms
  subdir-$(CONFIG_ARM_64) += efi
  subdir-$(CONFIG_ACPI) += acpi
+subdir-$(CONFIG_TEE) += tee
  
  obj-$(CONFIG_HAS_ALTERNATIVE) += alternative.o
  obj-y += bootfdt.init.o
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 4baecc2..db5f5ef 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -32,6 +32,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>
@@ -902,6 +903,9 @@ int domain_relinquish_resources(struct domain *d)
           */
          domain_vpl011_deinit(d);
  
+        /* Free TEE mediator resources */
+        tee_domain_destroy(d);
+
          d->arch.relmem = RELMEM_xen;
          /* Fallthrough */
  
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index e1c79b2..d208ec7 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -20,6 +20,7 @@
  #include <asm/psci.h>
  #include <asm/setup.h>
  #include <asm/cpufeature.h>
+#include <asm/tee/tee.h>
  
  #include <xen/irq.h>
  #include <xen/grant_table.h>
@@ -2193,6 +2194,9 @@ int __init construct_dom0(struct domain *d)
      set_current(saved_current);
      p2m_restore_state(saved_current);
  
+    /* Enable TEE */
+    tee_enable(d);
+
      discard_initial_modules();
  
      memset(regs, 0, sizeof(*regs));
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 45f3841..680356f 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -47,6 +47,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>
  
diff --git a/xen/arch/arm/shutdown.c b/xen/arch/arm/shutdown.c
index b32f07e..30c6950 100644
--- a/xen/arch/arm/shutdown.c
+++ b/xen/arch/arm/shutdown.c
@@ -5,6 +5,7 @@
  #include <xen/smp.h>
  #include <asm/platform.h>
  #include <asm/psci.h>
+#include <asm/tee/tee.h>
  
  static void noreturn halt_this_cpu(void *arg)
  {
diff --git a/xen/arch/arm/tee/Kconfig b/xen/arch/arm/tee/Kconfig
new file mode 100644
index 0000000..e69de29
diff --git a/xen/arch/arm/tee/Makefile b/xen/arch/arm/tee/Makefile
new file mode 100644
index 0000000..c54d479
--- /dev/null
+++ b/xen/arch/arm/tee/Makefile
@@ -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
index 0000000..7fd0148
--- /dev/null
+++ b/xen/arch/arm/tee/tee.c
@@ -0,0 +1,69 @@
+/*
+ * xen/arch/arm/tee/tee.c
+ *
+ * Generic part of TEE mediator subsystem
+ *
+ * Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx>
+ * 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.
+ */
+
+#include <xen/init.h>
+#include <xen/errno.h>
+#include <xen/types.h>
+#include <asm/tee/tee.h>
+
+extern const struct tee_mediator_desc _steemediator[], _eteemediator[];
+static const struct tee_mediator_ops *mediator_ops;
+
+bool tee_handle_call(struct cpu_user_regs *regs)
+{
+    if ( !mediator_ops )
+        return false;
+
+    return mediator_ops->handle_call(regs);
+}
+
+int tee_enable(struct domain *d)
+{
+    if ( !mediator_ops )
+        return -ENODEV;
+
+    return mediator_ops->enable(d);
+}
+
+void tee_domain_destroy(struct domain *d)
+{
+    if ( !mediator_ops )
+        return;
+
+    return mediator_ops->domain_destroy(d);
+}
+
+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);
+            mediator_ops = desc->ops;
+            return 0;
+        }
+    return 0;
+}
+
+__initcall(tee_init);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/vsmc.c b/xen/arch/arm/vsmc.c
index c4ccae6..d0199c7 100644
--- a/xen/arch/arm/vsmc.c
+++ b/xen/arch/arm/vsmc.c
@@ -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>
  
@@ -272,6 +273,10 @@ static bool vsmccc_handle_call(struct cpu_user_regs *regs)
          case ARM_SMCCC_OWNER_STANDARD:
              handled = handle_sssc(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;
          }
      }
  
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index 245a0e0..e4a2d6e 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -133,6 +133,13 @@ SECTIONS
        _aedevice = .;
    } :text
  
+  . = ALIGN(8);
+  .teemediator.info : {
+      _steemediator = .;
+      *(.teemediator.info)
+      _eteemediator = .;
+  } :text
+
    . = ALIGN(PAGE_SIZE);             /* Init code and data */
    __init_begin = .;
    .init.text : {
diff --git a/xen/include/asm-arm/tee/tee.h b/xen/include/asm-arm/tee/tee.h
new file mode 100644
index 0000000..0e8b576
--- /dev/null
+++ b/xen/include/asm-arm/tee/tee.h
@@ -0,0 +1,91 @@
+/*
+ * xen/include/asm-arm/tee/tee.h
+ *
+ * Generic part of TEE mediator subsystem
+ *
+ * Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx>
+ * 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 (*enable)(struct domain *d);
+
+    /*
+     * Called during domain destruction to inform TEE that guest is now dead
+     * and to destroy all resources allocated for the domain being destroyed.
+     */
+    void (*domain_destroy)(struct domain *d);
+
+    /* Handle SMCCC call for current domain. */
+    bool (*handle_call)(struct cpu_user_regs *regs);
+};
+
+struct tee_mediator_desc {
+    /* Name of the TEE. Just for debugging purposes. */
+    const char *name;
+
+    /* Mediator callbacks as described above. */
+    const struct tee_mediator_ops *ops;
+};
+
+bool tee_handle_call(struct cpu_user_regs *regs);
+int tee_enable(struct domain *d);
+void tee_domain_destroy(struct domain *d);
+
+#define REGISTER_TEE_MEDIATOR(_name, _namestr, _ops)          \
+static const struct tee_mediator_desc __tee_desc_##_name __used     \
+__section(".teemediator.info") = {                                  \
+    .name = _namestr,                                               \
+    .ops = _ops                                                     \
+}
+
+#else
+
+static inline bool tee_handle_call(struct cpu_user_regs *regs)
+{
+    return false;
+}
+
+static inline int tee_enable(struct domain *d)
+{
+    return -ENODEV;
+}
+
+static inline void tee_domain_destroy(struct domain *d) {}
+
+#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:
+ */