diff --git a/MAINTAINERS b/MAINTAINERS
index 77b1e11..ede00c5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -357,6 +357,11 @@ 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/*
+
 TOOLSTACK
 M:	Ian Jackson <ian.jackson@eu.citrix.com>
 M:	Wei Liu <wei.liu2@citrix.com>
diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index d46b98c..e1f112a 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -50,6 +50,14 @@ config HAS_ITS
         prompt "GICv3 ITS MSI controller support" if EXPERT = "y"
         depends on HAS_GICV3
 
+config ARM_TEE
+	bool "Enable TEE mediators support"
+	default n
+	depends on ARM
+	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"
@@ -167,3 +175,5 @@ endmenu
 source "common/Kconfig"
 
 source "drivers/Kconfig"
+
+source "arch/arm/tee/Kconfig"
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index ede21fd..2710e0e 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_ARM_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 784ae39..3290d39 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -31,6 +31,7 @@
 #include <asm/platform.h>
 #include <asm/procinfo.h>
 #include <asm/regs.h>
+#include <asm/tee.h>
 #include <asm/vfp.h>
 #include <asm/vgic.h>
 #include <asm/vtimer.h>
@@ -673,6 +674,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
     if ( is_hardware_domain(d) && (rc = domain_vuart_init(d)) )
         goto fail;
 
+    /* Notify TEE that new domain was created */
+    tee_domain_create(d);
+
     return 0;
 
 fail:
@@ -684,6 +688,9 @@ fail:
 
 void arch_domain_destroy(struct domain *d)
 {
+    /* Notify TEE that domain is being destroyed */
+    tee_domain_destroy(d);
+
     /* IOMMU page table is shared with P2M, always call
      * iommu_domain_destroy() before p2m_teardown().
      */
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 92f173b..8a4fcd8 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.h>
 #include <xsm/xsm.h>
 #include <asm/acpi.h>
 
@@ -846,6 +847,9 @@ void __init start_xen(unsigned long boot_phys_offset,
      */
     apply_alternatives_all();
 
+    /* Initialize TEE mediator */
+    tee_init();
+
     /* Create initial domain 0. */
     /* The vGIC for DOM0 is exactly emulating the hardware GIC */
     config.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
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..7f7a846
--- /dev/null
+++ b/xen/arch/arm/tee/tee.c
@@ -0,0 +1,134 @@
+/*
+ * xen/arch/arm/tee/tee.c
+ *
+ * Generic part of TEE mediator subsystem
+ *
+ * Volodymyr Babchuk <volodymyr_babchuk@epam.com>
+ * Copyright (c) 2017 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/types.h>
+#include <asm/smccc.h>
+#include <asm/tee.h>
+
+/*
+ * According to ARM SMCCC (ARM DEN 0028B, page 17), service owner
+ * for generic TEE queries is 63.
+ */
+#define TRUSTED_OS_GENERIC_API_OWNER 63
+
+#define ARM_SMCCC_FUNC_GET_TEE_UID                                      \
+        ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,                         \
+                           ARM_SMCCC_CONV_32,                           \
+                           TRUSTED_OS_GENERIC_API_OWNER,                \
+                           ARM_SMCCC_FUNC_CALL_UID)
+
+extern const struct tee_mediator_desc _steemediator[], _eteemediator[];
+static const struct tee_mediator_ops *mediator_ops;
+
+/* Helper function to read UID returned by SMC */
+static void parse_uid(const register_t regs[4], xen_uuid_t *uid)
+{
+    uint8_t *bytes = uid->a;
+    int n;
+
+    /*
+     * UID is returned in registers r0..r3, four bytes per register,
+     * first byte is stored in low-order bits of a register.
+     * (ARM DEN 0028B page 14)
+     */
+    for (n = 0; n < 16; n++)
+        bytes[n] = (uint8_t)(regs[n/4] >> ((n & 3) * 8));
+
+}
+
+void tee_init(void)
+{
+    const struct tee_mediator_desc *desc;
+    register_t resp[4];
+    xen_uuid_t tee_uid;
+    int ret;
+
+    /* Read UUID to determine which TEE is running */
+    call_smccc_smc(ARM_SMCCC_FUNC_GET_TEE_UID, 0, 0, 0, 0, 0, 0, 0, resp);
+    if ( resp[0] == 0xFFFFFFFF ) {
+        printk("No TEE found\n");
+        return;
+    }
+
+    parse_uid(resp, &tee_uid);
+
+    printk("TEE UID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
+           tee_uid.a[0 ], tee_uid.a[1 ], tee_uid.a[2 ], tee_uid.a[3 ],
+           tee_uid.a[4 ], tee_uid.a[5 ], tee_uid.a[6 ], tee_uid.a[7 ],
+           tee_uid.a[8 ], tee_uid.a[9 ], tee_uid.a[10], tee_uid.a[11],
+           tee_uid.a[12], tee_uid.a[13], tee_uid.a[14], tee_uid.a[15]);
+
+    for ( desc = _steemediator; desc != _eteemediator; desc++ )
+        if ( memcmp(&desc->uid, &tee_uid, sizeof(xen_uuid_t)) == 0 )
+        {
+            printk("Using TEE mediator for %sp\n", desc->name);
+            mediator_ops = desc->ops;
+            break;
+        }
+
+    if ( !mediator_ops )
+        return;
+
+    ret = mediator_ops->init();
+    if ( ret )
+    {
+        printk("TEE mediator failed to initialize :%d\n", ret);
+        mediator_ops = NULL;
+    }
+}
+
+bool tee_handle_smc(struct cpu_user_regs *regs)
+{
+    if ( !mediator_ops )
+        return false;
+
+    return mediator_ops->handle_smc(regs);
+}
+
+void tee_domain_create(struct domain *d)
+{
+    if ( !mediator_ops )
+        return;
+
+    return mediator_ops->domain_create(d);
+}
+
+void tee_domain_destroy(struct domain *d)
+{
+    if ( !mediator_ops )
+        return;
+
+    return mediator_ops->domain_destroy(d);
+}
+
+void tee_remove(void)
+{
+    if ( !mediator_ops )
+        return;
+
+    return mediator_ops->remove();
+}
+
+/*
+ * 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 7bd6008..186e34b 100644
--- a/xen/arch/arm/vsmc.c
+++ b/xen/arch/arm/vsmc.c
@@ -22,6 +22,7 @@
 #include <asm/psci.h>
 #include <asm/regs.h>
 #include <asm/smccc.h>
+#include <asm/tee.h>
 #include <asm/traps.h>
 
 /* Number of functions currently supported by Hypervisor Service. */
@@ -288,6 +289,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_smc(regs);
+            break;
         }
     }
 
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index c9b9546..b78b7f1 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -126,6 +126,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.h b/xen/include/asm-arm/tee.h
new file mode 100644
index 0000000..7f500ac
--- /dev/null
+++ b/xen/include/asm-arm/tee.h
@@ -0,0 +1,79 @@
+/*
+ * xen/include/asm-arm/tee.h
+ *
+ * Generic part of TEE mediator subsystem
+ *
+ * Volodymyr Babchuk <volodymyr_babchuk@epam.com>
+ * Copyright (c) 2017 EPAM Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#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_ARM_TEE
+
+struct tee_mediator_ops {
+    int (*init)(void);
+    void (*domain_create)(struct domain *d);
+    void (*domain_destroy)(struct domain *d);
+    bool (*handle_smc)(struct cpu_user_regs *regs);
+    void (*remove)(void);
+};
+
+struct tee_mediator_desc {
+    const char *name;
+    const xen_uuid_t uid;
+    const struct tee_mediator_ops *ops;
+};
+
+void tee_init(void);
+bool tee_handle_smc(struct cpu_user_regs *regs);
+void tee_domain_create(struct domain *d);
+void tee_domain_destroy(struct domain *d);
+void tee_remove(void);
+
+#define REGISTER_TEE_MEDIATOR(_name, _namestr, _uid, _ops)          \
+static const struct tee_mediator_desc __tee_desc_##_name __used     \
+__section(".teemediator.info") = {                                  \
+    .name = _namestr,                                               \
+    .uid = _uid,                                                    \
+    .ops = _ops                                                     \
+}
+
+#else
+
+static inline void tee_init(void) {}
+static inline bool tee_handle_smc(struct cpu_user_regs *regs)
+{
+    return false;
+}
+static inline void tee_domain_create(struct domain *d) {}
+static inline tee_domain_destroy(struct domain *d) {}
+static inline tee_remove(void) {}
+
+#endif  /* CONFIG_ARM_TEE */
+
+#endif /* __ARCH_ARM_TEE_TEE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
